UNPKG

autosnippet

Version:

Extract code patterns into a knowledge base for AI coding assistants

797 lines (796 loc) 41.3 kB
/** * ast-graph.js — AST 结构化分析 + Agent Memory 工具 (11) * * 44. get_project_overview 项目 AST 概览 * 45. get_class_hierarchy 类继承层级 * 46. get_class_info 类/结构体详细信息 (跨语言) * 47. get_protocol_info 协议/接口/trait 详细信息 (跨语言) * 48. get_method_overrides 方法覆写查询 * 49. get_category_map Category/Extension 扩展映射 * 50. get_previous_analysis 前序维度分析结果 * 51. note_finding 记录关键发现 * 52. get_previous_evidence 检索前序维度证据 * 53. query_code_graph 查询代码实体图谱 * 54. query_call_graph 查询方法调用链 (Phase 5) */ /** 辅助: 安全获取 ProjectGraph 实例 */ function _getProjectGraph(ctx) { try { return ctx.container?.get('projectGraph') || null; } catch { return null; } } // ──────────────────────────────────────────────────────────── // 44. get_project_overview — 项目 AST 概览 // ──────────────────────────────────────────────────────────── export const getProjectOverview = { name: 'get_project_overview', description: '获取项目的整体结构概览:文件统计、语言分布、模块列表、入口点、类/协议/Category 数量。' + '支持所有语言 (Swift/ObjC/Java/Kotlin/Python/TS/JS/Dart/Rust/Go 等)。' + '适用场景:了解项目规模和架构布局,规划探索路径。', parameters: { type: 'object', properties: {}, }, handler: async (_params, ctx) => { const graph = _getProjectGraph(ctx); if (!graph) { return 'AST 分析不可用 — ProjectGraph 未构建。请检查 tree-sitter 是否已安装。'; } const o = await graph.getOverview(); // §P2: 从文件扩展名统计语言分布 const langStats = {}; for (const filePath of graph.getAllFilePaths?.() || []) { const ext = filePath.split('.').pop(); if (ext) { langStats[ext] = (langStats[ext] || 0) + 1; } } const lines = [ `📊 项目 AST 概览 (构建耗时 ${o.buildTimeMs}ms)`, ``, `文件: ${o.totalFiles} | 类: ${o.totalClasses} | 协议/接口: ${o.totalProtocols} | Category/Extension: ${o.totalCategories} | 方法: ${o.totalMethods}`, ]; // 语言分布 const langEntries = Object.entries(langStats).sort((a, b) => b[1] - a[1]); if (langEntries.length > 0) { lines.push(``, `── 语言分布 ──`); for (const [ext, count] of langEntries) { lines.push(` .${ext}: ${count} 个文件`); } } lines.push(``, `── 模块 ──`); for (const mod of o.topLevelModules) { const count = o.classesPerModule[mod] || 0; lines.push(` ${mod}/ — ${count} 个类`); } if (o.entryPoints.length > 0) { lines.push(``, `── 入口点 ──`); for (const ep of o.entryPoints) { lines.push(` ${ep}`); } } return lines.join('\n'); }, }; // ──────────────────────────────────────────────────────────── // 45. get_class_hierarchy — 类继承层级 // ──────────────────────────────────────────────────────────── export const getClassHierarchy = { name: 'get_class_hierarchy', description: '查看指定类/结构体的继承链(向上到根类)和直接子类列表。' + '支持所有语言的类继承体系 (Swift class/struct, Java/Kotlin class, Python class, TS class, Dart class, Rust struct, Go struct 等)。' + '传入 className 查看指定类,不传则返回项目中所有根类及其子树。', parameters: { type: 'object', properties: { className: { type: 'string', description: '类名 (可选, 不填则返回完整层级)' }, }, }, handler: async (params, ctx) => { const graph = _getProjectGraph(ctx); if (!graph) { return 'AST 分析不可用 — ProjectGraph 未构建。'; } const className = params.className || params.class_name; if (className) { const chain = graph.getInheritanceChain(className); const subs = graph.getSubclasses(className); if (chain.length === 0) { return `未找到类 ${className}`; } const lines = [`🔗 ${className} 继承链:`, ` ${chain.join(' → ')}`]; if (subs.length > 0) { lines.push(``, `直接子类 (${subs.length}):`); for (const s of subs) { lines.push(` ├── ${s}`); } } return lines.join('\n'); } // 全量: 找出所有根类 (没有父类或父类不在项目中的类) const allClasses = graph.getAllClassNames(); const roots = allClasses.filter((c) => { const chain = graph.getInheritanceChain(c); return chain.length <= 1 || !allClasses.includes(chain[1]); }); const lines = [`🌳 项目类层级 (${allClasses.length} 个类, ${roots.length} 棵树)`]; for (const root of roots.slice(0, 30)) { const descendants = graph.getAllDescendants(root); lines.push(` ${root} (${descendants.length} 个后代)`); for (const d of descendants.slice(0, 5)) { lines.push(` └── ${d}`); } if (descendants.length > 5) { lines.push(` ... 还有 ${descendants.length - 5} 个`); } } if (roots.length > 30) { lines.push(`... 还有 ${roots.length - 30} 棵树`); } return lines.join('\n'); }, }; // ──────────────────────────────────────────────────────────── // 46. get_class_info — 类详细信息 // ──────────────────────────────────────────────────────────── export const getClassInfo = { name: 'get_class_info', description: '获取指定类/结构体的详细信息: 属性、方法签名、导入、继承关系、扩展。' + '跨语言通用:ObjC @interface, Swift class/struct, Java/Kotlin class, Python class, TS/JS class, Dart class, Rust struct impl, Go struct 等。', parameters: { type: 'object', properties: { className: { type: 'string', description: '类名 (必填)' }, }, required: ['className'], }, handler: async (params, ctx) => { const graph = _getProjectGraph(ctx); if (!graph) { return 'AST 分析不可用 — ProjectGraph 未构建。'; } const className = params.className || params.class_name; const info = graph.getClassInfo(className); if (!info) { return `未找到类 "${className}"。可以使用 get_project_overview 查看项目中的所有类。`; } const chain = graph.getInheritanceChain(className); const cats = graph.getCategoryExtensions(className); const subs = graph.getSubclasses(className); const lines = [ `📦 ${info.name}`, `文件: ${info.filePath}:${info.line}`, `继承: ${chain.join(' → ')}`, ]; if (info.protocols.length > 0) { lines.push(`实现: ${info.protocols.join(', ')}`); } if (info.properties.length > 0) { lines.push(``, `── 属性 (${info.properties.length}) ──`); for (const p of info.properties) { const attrs = p.attributes.length > 0 ? ` (${p.attributes.join(', ')})` : ''; lines.push(` ${p.name}: ${p.type}${attrs}`); } } if (info.methods.length > 0) { lines.push(``, `── 方法 (${info.methods.length}) ──`); const classMethods = info.methods.filter((m) => m.isClassMethod); const instanceMethods = info.methods.filter((m) => !m.isClassMethod); for (const m of classMethods) { const cx = m.complexity > 3 ? ` [复杂度:${m.complexity}]` : ''; lines.push(` + ${m.selector}${m.returnType}${cx}`); } for (const m of instanceMethods) { const cx = m.complexity > 3 ? ` [复杂度:${m.complexity}]` : ''; lines.push(` - ${m.selector}${m.returnType}${cx}`); } } if (cats.length > 0) { lines.push(``, `── 扩展 (${cats.length}) ──`); for (const cat of cats) { const methodNames = cat.methods.map((m) => m.selector).join(', '); lines.push(` ${info.name}(${cat.categoryName}) — ${cat.filePath} — [${methodNames}]`); } } if (subs.length > 0) { lines.push(``, `── 直接子类 (${subs.length}) ──`); for (const s of subs) { lines.push(` ${s}`); } } return lines.join('\n'); }, }; // ──────────────────────────────────────────────────────────── // 47. get_protocol_info — 协议详细信息 // ──────────────────────────────────────────────────────────── export const getProtocolInfo = { name: 'get_protocol_info', description: '获取指定协议/接口/trait 的定义(必选/可选方法)及所有实现者列表。' + '跨语言通用:ObjC @protocol, Swift protocol, Java/Kotlin interface, Python ABC, TS interface, Dart abstract class, Rust trait, Go interface 等。', parameters: { type: 'object', properties: { protocolName: { type: 'string', description: '协议名 (必填)' }, }, required: ['protocolName'], }, handler: async (params, ctx) => { const graph = _getProjectGraph(ctx); if (!graph) { return 'AST 分析不可用 — ProjectGraph 未构建。'; } const protocolName = params.protocolName || params.protocol_name; const info = graph.getProtocolInfo(protocolName); if (!info) { return `未找到协议/接口 "${protocolName}"。可以使用 get_project_overview 查看项目中的所有协议/接口。`; } const lines = [`📋 ${info.name}`, `文件: ${info.filePath}:${info.line}`]; if (info.inherits.length > 0) { lines.push(`继承: ${info.inherits.join(', ')}`); } if (info.requiredMethods.length > 0) { lines.push(``, `── 必须实现 (${info.requiredMethods.length}) ──`); for (const m of info.requiredMethods) { lines.push(` ${m.isClassMethod ? '+' : '-'} ${m.selector}${m.returnType}`); } } if (info.optionalMethods.length > 0) { lines.push(``, `── 可选实现 (${info.optionalMethods.length}) ──`); for (const m of info.optionalMethods) { lines.push(` ${m.isClassMethod ? '+' : '-'} ${m.selector}${m.returnType}`); } } if (info.conformers.length > 0) { lines.push(``, `── 实现者 (${info.conformers.length}) ──`); for (const c of info.conformers) { lines.push(` ${c}`); } } else { lines.push(``, `⚠️ 暂未发现实现此协议/接口的类`); } return lines.join('\n'); }, }; // ──────────────────────────────────────────────────────────── // 48. get_method_overrides — 方法覆写查询 // ──────────────────────────────────────────────────────────── export const getMethodOverrides = { name: 'get_method_overrides', description: '查找覆写了指定方法的所有子类。适用于理解方法在继承树中的多态行为。' + '跨语言通用:支持 ObjC/Swift/Java/Kotlin/Python/TS/Dart 等语言的方法覆写。', parameters: { type: 'object', properties: { className: { type: 'string', description: '定义该方法的基类名 (必填)' }, methodName: { type: 'string', description: '方法名或 selector (必填)' }, }, required: ['className', 'methodName'], }, handler: async (params, ctx) => { const graph = _getProjectGraph(ctx); if (!graph) { return 'AST 分析不可用 — ProjectGraph 未构建。'; } const className = params.className || params.class_name; const methodName = params.methodName || params.method_name; const overrides = graph.getMethodOverrides(className, methodName); if (overrides.length === 0) { return `"${className}.${methodName}" 没有在任何子类中被覆写。`; } const lines = [`🔀 ${className}.${methodName} 的覆写 (${overrides.length} 处):`]; for (const o of overrides) { const cx = o.method.complexity > 3 ? ` [复杂度:${o.method.complexity}]` : ''; lines.push(` ${o.className}${o.filePath}:${o.method.line}${cx}`); } return lines.join('\n'); }, }; // ──────────────────────────────────────────────────────────── // 49. get_category_map — Category 扩展映射 // ──────────────────────────────────────────────────────────── export const getCategoryMap = { name: 'get_category_map', description: '获取指定类的 Category/Extension 扩展映射。' + 'ObjC Category、Swift Extension 等语言的类扩展机制。了解它有助于发现功能划分。' + '不传 className 则返回整个项目中有扩展的类列表。', parameters: { type: 'object', properties: { className: { type: 'string', description: '类名 — 可选, 不填则返回整个项目中有 Category 的类列表', }, }, }, handler: async (params, ctx) => { const graph = _getProjectGraph(ctx); if (!graph) { return 'AST 分析不可用 — ProjectGraph 未构建。'; } const className = params.className || params.class_name; if (className) { const cats = graph.getCategoryExtensions(className); if (cats.length === 0) { return `"${className}" 没有 Category 扩展。`; } const lines = [`📂 ${className} 的 Category 扩展 (${cats.length}):`]; for (const cat of cats) { lines.push(` ${className}(${cat.categoryName}) — ${cat.filePath}:${cat.line}`); for (const m of cat.methods) { lines.push(` ${m.isClassMethod ? '+' : '-'} ${m.selector}`); } if (cat.protocols.length > 0) { lines.push(` 遵循: <${cat.protocols.join(', ')}>`); } } return lines.join('\n'); } // 全量概览 const allClasses = graph.getAllClassNames(); const withCats = allClasses .map((c) => ({ name: c, cats: graph.getCategoryExtensions(c) })) .filter((x) => x.cats.length > 0) .sort((a, b) => b.cats.length - a.cats.length); if (withCats.length === 0) { return '项目中没有发现 Category 扩展。'; } const lines = [`📂 项目 Category 概览 (${withCats.length} 个类有 Category):`]; for (const { name, cats } of withCats.slice(0, 30)) { const catNames = cats.map((c) => c.categoryName).join(', '); lines.push(` ${name}${cats.length} 个: (${catNames})`); } if (withCats.length > 30) { lines.push(`... 还有 ${withCats.length - 30} 个类`); } return lines.join('\n'); }, }; // ──────────────────────────────────────────────────────────── // 50. get_previous_analysis — 前序维度分析结果 (可选) // ──────────────────────────────────────────────────────────── export const getPreviousAnalysis = { name: 'get_previous_analysis', description: '获取前序维度的分析摘要。在 bootstrap 中,每个维度可能有前面维度的分析结果可用。' + '调用此工具可以获取之前维度产出的候选标题、设计决策等上下文,避免重复分析。' + '注意: 只有在你认为前序上下文对当前任务有帮助时才调用。', parameters: { type: 'object', properties: {}, }, handler: async (_params, ctx) => { // 从 ctx._dimensionMeta 读取前序分析 const meta = ctx._dimensionMeta; if (!meta || !meta.previousAnalysis) { return '没有前序维度的分析结果可用。'; } const prev = meta.previousAnalysis; if (typeof prev === 'string') { return prev; } // 格式化前序分析 const lines = ['📋 前序维度分析摘要:']; if (Array.isArray(prev)) { for (const item of prev) { if (typeof item === 'string') { lines.push(` ${item}`); } else if (item.dimension && item.summary) { lines.push(``, `── ${item.dimension} ──`); lines.push(` ${item.summary}`); if ((item.candidateTitles?.length ?? 0) > 0) { lines.push(` 已提交候选: ${item.candidateTitles.join(', ')}`); } } } } else if (typeof prev === 'object') { for (const [key, value] of Object.entries(prev)) { lines.push(` ${key}: ${typeof value === 'string' ? value : JSON.stringify(value)}`); } } return lines.join('\n'); }, }; // ──────────────────────────────────────────────────────────── // 51. note_finding — 记录关键发现到工作记忆 (Scratchpad) // ──────────────────────────────────────────────────────────── export const noteFinding = { name: 'note_finding', description: '记录一个关键发现到工作记忆的 Scratchpad。在分析过程中发现重要模式、设计决策或事实时调用。' + '这些发现会在上下文窗口压缩后依然保留,确保分析后期不会遗忘早期重要发现。' + '建议在发现关键架构模式、核心类职责、重要设计约束时调用。', parameters: { type: 'object', properties: { finding: { type: 'string', description: '关键发现描述 (≤150 字)。应是具体、可验证的陈述,例如 "BDNetworkManager 使用单例模式,所有请求通过其发起"', }, evidence: { type: 'string', description: '支持证据 (文件路径:行号),例如 "BDNetworkManager.m:45"', }, importance: { type: 'number', description: '重要性评分 1-10。8+ = 影响全局架构,5-7 = 常见模式,1-4 = 细节备注', }, }, required: ['finding'], }, handler: async (params, ctx) => { // v5.0: 通过 MemoryCoordinator const coordinator = ctx._memoryCoordinator; if (coordinator) { const finding = params.finding || ''; // P0 Fix: AI 可能传入 array/object,强制转为 string const rawEvidence = params.evidence; const evidence = typeof rawEvidence === 'string' ? rawEvidence : Array.isArray(rawEvidence) ? rawEvidence.join(', ') : rawEvidence ? String(rawEvidence) : ''; const importance = params.importance || 5; const round = ctx._currentRound || 0; const scopeId = ctx._dimensionScopeId || undefined; return coordinator.noteFinding(finding, evidence, importance, round, scopeId); } return '⚠ 工作记忆未初始化 (仅在 bootstrap 分析期间可用)'; }, }; // ──────────────────────────────────────────────────────────── // 52. get_previous_evidence — 检索前序维度的代码证据 // ──────────────────────────────────────────────────────────── export const getPreviousEvidence = { name: 'get_previous_evidence', description: '获取前序维度对特定文件/类/模式的分析证据。避免重复搜索和读取已经被其他维度分析过的内容。' + '当你要搜索某个类名或文件时,先调用此工具看前序维度是否已有发现。', parameters: { type: 'object', properties: { query: { type: 'string', description: '搜索查询 (文件名、类名、模式名、关键词)', }, dimId: { type: 'string', description: '指定维度 ID (可选,默认搜索所有前序维度)', }, }, required: ['query'], }, handler: async (params, ctx) => { // v5.0: 通过 MemoryCoordinator 获取 SessionStore const coordinator = ctx._memoryCoordinator; const sessionStore = coordinator?.getSessionStore(); if (!sessionStore) { return '没有前序维度的证据可用。'; } const results = sessionStore.searchEvidence(params.query, params.dimId || undefined); if (results.length === 0) { return `没有找到与 "${params.query}" 相关的前序证据。建议自行搜索。`; } const lines = [`📋 前序维度证据 (匹配 "${params.query}", ${results.length} 条):`]; for (const r of results.slice(0, 8)) { lines.push(` 📄 ${r.filePath}`); lines.push(` [${r.evidence.dimId}] [${r.evidence.importance || 5}/10] ${r.evidence.finding}`); } if (results.length > 8) { lines.push(` …还有 ${results.length - 8} 条证据`); } return lines.join('\n'); }, }; // ──────────────────────────────────────────────────────────── // 53. query_code_graph — 查询代码实体图谱 // ──────────────────────────────────────────────────────────── export const queryCodeGraph = { name: 'query_code_graph', description: '查询代码实体图谱 (Code Entity Graph)。可查询类继承链、协议遵循者、实体搜索、影响分析等。' + '图谱包含从 AST 提取的类、协议、Category、模块、设计模式及其关系。', parameters: { type: 'object', properties: { action: { type: 'string', enum: [ 'search', 'inheritance_chain', 'descendants', 'conformances', 'impact', 'topology', 'entity_edges', ], description: '查询动作: search=搜索实体, inheritance_chain=继承链, descendants=子类/遵循者, conformances=协议遵循, impact=影响分析, topology=拓扑概览, entity_edges=实体的所有边', }, entity_id: { type: 'string', description: '实体 ID (类名/协议名)。search 时为搜索关键词。', }, entity_type: { type: 'string', enum: ['class', 'protocol', 'category', 'module', 'pattern', 'method'], description: '实体类型过滤 (可选,含 Phase 5 method 类型)', }, max_depth: { type: 'number', description: '遍历深度 (默认 3)', }, }, required: ['action', 'entity_id'], }, handler: async (params, ctx) => { try { // 优先从 container 获取单例 CEG,避免每次创建新实例 let ceg = ctx?.container?.get?.('codeEntityGraph'); if (!ceg) { const { CodeEntityGraph } = await import('#service/knowledge/CodeEntityGraph.js'); const entityRepo = ctx?.container?.get?.('codeEntityRepository'); const edgeRepo = ctx?.container?.get?.('knowledgeEdgeRepository'); if (!entityRepo || !edgeRepo) { return '代码实体图谱不可用: 数据库未初始化'; } const projectRoot = ctx?.projectRoot || process.env.ASD_PROJECT_DIR || ''; ceg = new CodeEntityGraph(entityRepo, edgeRepo, { projectRoot }); } const maxDepth = params.max_depth || 3; switch (params.action) { case 'search': { const results = await ceg.searchEntities(params.entity_id, { type: params.entity_type, limit: 15, }); if (results.length === 0) { return `未找到匹配 "${params.entity_id}" 的代码实体。`; } const lines = [`🔍 代码实体搜索 "${params.entity_id}" (${results.length} 条):`]; for (const e of results) { lines.push(` • ${e.entityType}: \`${e.name}\`${e.filePath ? ` (${e.filePath}:${e.line || '?'})` : ''}${e.superclass ? ` → ${e.superclass}` : ''}`); } return lines.join('\n'); } case 'inheritance_chain': { const chain = await ceg.getInheritanceChain(params.entity_id, maxDepth); if (chain.length <= 1) { return `\`${params.entity_id}\` 没有已知的继承关系。`; } return `📐 继承链: \`${chain.join(' → ')}\``; } case 'descendants': { const type = params.entity_type || 'class'; const desc = await ceg.getDescendants(params.entity_id, type, maxDepth); if (desc.length === 0) { return `\`${params.entity_id}\` 没有已知的子类/遵循者。`; } const lines = [`📊 ${params.entity_id} 的后代 (${desc.length}):`]; for (const d of desc.slice(0, 20)) { lines.push(` ${' '.repeat(d.depth - 1)}└─ \`${d.id}\` (${d.type}, ${d.relation})`); } return lines.join('\n'); } case 'conformances': { const protos = await ceg.getConformances(params.entity_id); if (protos.length === 0) { return `\`${params.entity_id}\` 没有已知的协议遵循。`; } return `📋 \`${params.entity_id}\` 遵循: ${protos.map((p) => `\`${p}\``).join(', ')}`; } case 'impact': { const type = params.entity_type || 'class'; const impact = await ceg.getImpactRadius(params.entity_id, type, maxDepth); if (impact.length === 0) { return `修改 \`${params.entity_id}\` 没有检测到直接影响。`; } const lines = [`⚡ 修改 \`${params.entity_id}\` 的影响范围 (${impact.length}):`]; for (const i of impact.slice(0, 20)) { lines.push(` ${' '.repeat(i.depth - 1)}⬆ \`${i.id}\` (${i.type}, via ${i.relation})`); } return lines.join('\n'); } case 'topology': { const topo = await ceg.getTopology(); if (topo.totalEntities === 0) { return '代码实体图谱为空。需先执行 Bootstrap。'; } const lines = ['📈 代码实体图谱概览:']; lines.push(' 实体:'); for (const [type, count] of Object.entries(topo.entities)) { lines.push(` • ${type}: ${count}`); } lines.push(` 总边数: ${topo.totalEdges}`); if (topo.hotNodes.length > 0) { lines.push(' 核心实体 (入度最高):'); for (const n of topo.hotNodes.slice(0, 8)) { lines.push(` • \`${n.id}\` (${n.type}, 入度=${n.inDegree})`); } } return lines.join('\n'); } case 'entity_edges': { const type = params.entity_type || 'class'; const edges = await ceg.getEntityEdges(params.entity_id, type); const total = edges.outgoing.length + edges.incoming.length; if (total === 0) { return `\`${params.entity_id}\` 没有已知的图谱边。`; } const lines = [`🔗 \`${params.entity_id}\` 的关系 (${total} 条):`]; if (edges.outgoing.length > 0) { lines.push(' 出边:'); for (const e of edges.outgoing.slice(0, 10)) { lines.push(` → \`${e.toId}\` (${e.toType}, ${e.relation})`); } } if (edges.incoming.length > 0) { lines.push(' 入边:'); for (const e of edges.incoming.slice(0, 10)) { lines.push(` ← \`${e.fromId}\` (${e.fromType}, ${e.relation})`); } } return lines.join('\n'); } default: return `未知动作: ${params.action}`; } } catch (err) { return `代码实体图谱查询失败: ${err.message}`; } }, }; // ──────────────────────────────────────────────────────────── // 54. query_call_graph — 查询方法调用链 (Phase 5) // ──────────────────────────────────────────────────────────── export const queryCallGraph = { name: 'query_call_graph', description: '查询方法的调用链上下文 (Call Graph)。支持 10+ 种编程语言 (Swift/ObjC/Java/Kotlin/Python/TS/JS/Dart/Rust/Go)。\n' + '• callers: 谁调用了这个方法?(向上追踪调用者链)\n' + '• callees: 这个方法调用了谁?(向下追踪依赖链)\n' + '• both: 同时获取调用者和被调用者\n' + '• impact: 修改此方法的影响半径分析 (受影响文件数)\n' + '• search: 按名称搜索方法实体\n' + '⚠️ 需要先完成 bootstrap 才有数据。方法名格式: "ClassName.methodName" 或简写 "methodName"。', parameters: { type: 'object', properties: { methodName: { type: 'string', description: '方法名 (e.g. "UserService.getUser", "viewDidLoad", "handleClick")。' + 'search 模式下为搜索关键词。', }, direction: { type: 'string', enum: ['callers', 'callees', 'both', 'impact', 'search'], description: 'callers=调用者 | callees=被调用者 | both=双向 | impact=影响分析 | search=搜索方法实体', }, maxDepth: { type: 'number', description: '最大遍历深度 (1-5, 默认 2)', }, }, required: ['methodName'], }, handler: async (params, ctx) => { try { // 前置: 必填参数校验 (fail-fast) const methodName = params.methodName || params.method_name; if (!methodName) { return '请提供 methodName 参数。'; } // 优先从 container 获取单例 CEG,避免每次创建新实例 let ceg = ctx?.container?.get?.('codeEntityGraph'); if (!ceg) { // fallback: 手动构建 const { CodeEntityGraph } = await import('#service/knowledge/CodeEntityGraph.js'); const entityRepo = ctx?.container?.get?.('codeEntityRepository'); const edgeRepo = ctx?.container?.get?.('knowledgeEdgeRepository'); if (!entityRepo || !edgeRepo) { return '调用图查询不可用: 数据库未初始化。'; } const projectRoot = ctx?.projectRoot || process.env.ASD_PROJECT_DIR || ''; ceg = new CodeEntityGraph(entityRepo, edgeRepo, { projectRoot }); } const direction = params.direction || 'both'; const maxDepth = Math.min(Math.max(Number(params.maxDepth || params.max_depth) || 2, 1), 5); // search 模式: 按名称搜索方法实体 if (direction === 'search') { const results = await ceg.searchEntities(methodName, { type: 'method', limit: 15 }); if (results.length === 0) { // 降级: 不限类型搜索 const allResults = await ceg.searchEntities(methodName, { limit: 15 }); if (allResults.length === 0) { return `未找到匹配 "${methodName}" 的实体。请确认 bootstrap 已完成。`; } const lines = [`🔍 搜索 "${methodName}" (${allResults.length} 条, 无 method 类型匹配):`]; for (const e of allResults) { lines.push(` • [${e.entityType}] ${e.name}${e.filePath ? ` (${e.filePath})` : ''}`); } lines.push(``, `💡 提示: 调用图查询需使用 method 实体的 entityId。`); return lines.join('\n'); } const lines = [`🔍 方法搜索 "${methodName}" (${results.length} 条):`]; for (const e of results) { lines.push(` • ${e.name}${e.filePath ? ` (${e.filePath})` : ''}`); } lines.push(``, `💡 复制上面的完整方法名,用 callers/callees/both/impact 查询其调用链。`); return lines.join('\n'); } // impact 模式 if (direction === 'impact') { const impact = await ceg.getCallImpactRadius(methodName); const lines = [ `⚡ 修改 "${methodName}" 的影响半径:`, ` 直接调用者: ${impact.directCallers}`, ` 传递性调用者 (depth≤3): ${impact.transitiveCallers}`, ]; if (impact.affectedFiles.length > 0) { lines.push(` 受影响文件 (${impact.affectedFiles.length}):`); for (const f of impact.affectedFiles.slice(0, 15)) { lines.push(` 📄 ${f}`); } if (impact.affectedFiles.length > 15) { lines.push(` ... 还有 ${impact.affectedFiles.length - 15} 个文件`); } } else { lines.push(` 未发现受影响文件 (可能是叶子方法或 bootstrap 无调用图数据)。`); } return lines.join('\n'); } // callers / callees / both 模式 const result = {}; if (direction === 'callers' || direction === 'both') { result.callers = await ceg.getCallers(methodName, maxDepth); } if (direction === 'callees' || direction === 'both') { result.callees = await ceg.getCallees(methodName, maxDepth); } const totalCallers = result.callers?.length || 0; const totalCallees = result.callees?.length || 0; if (totalCallers === 0 && totalCallees === 0) { return (`"${methodName}" 在调用图中没有找到调用关系。\n\n` + `可能原因:\n` + ` 1. 方法名拼写不匹配 — 尝试 search 模式: query_call_graph({methodName:"关键词", direction:"search"})\n` + ` 2. 该方法是入口点/叶子节点,无上下游\n` + ` 3. bootstrap 尚未执行或不包含此文件`); } const lines = [`📞 "${methodName}" 的调用链 (depth≤${maxDepth}):`]; if ((result.callers?.length ?? 0) > 0) { lines.push(``, `── 调用者 (谁调用了它, ${result.callers.length} 条) ──`); for (const c of result.callers.slice(0, 20)) { const indent = ' '.repeat(c.depth); const typeTag = c.callType !== 'unknown' ? ` [${c.callType}]` : ''; lines.push(`${indent}${c.caller}${typeTag}`); } if (result.callers.length > 20) { lines.push(` ... 还有 ${result.callers.length - 20} 个调用者`); } } if ((result.callees?.length ?? 0) > 0) { lines.push(``, `── 被调用者 (它调用了谁, ${result.callees.length} 条) ──`); for (const c of result.callees.slice(0, 20)) { const indent = ' '.repeat(c.depth); const typeTag = c.callType !== 'unknown' ? ` [${c.callType}]` : ''; lines.push(`${indent}${c.callee}${typeTag}`); } if (result.callees.length > 20) { lines.push(` ... 还有 ${result.callees.length - 20} 个被调用者`); } } return lines.join('\n'); } catch (err) { // 表不存在 → 未 bootstrap if (err.message?.includes('no such table')) { return '调用图数据不可用 — knowledge_edges 表不存在,请先运行 bootstrap。'; } return `调用图查询失败: ${err.message}`; } }, };