autosnippet 3.2.7 → 3.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/bin/cli.js +13 -5
  2. package/dashboard/dist/assets/index-BTAsOZv2.js +128 -0
  3. package/dashboard/dist/assets/index-C_72Ct98.css +1 -0
  4. package/dashboard/dist/index.html +2 -2
  5. package/lib/cli/AiScanService.js +26 -29
  6. package/lib/cli/SetupService.js +1 -1
  7. package/lib/core/AstAnalyzer.js +27 -5
  8. package/lib/core/analysis/CallEdgeResolver.js +402 -0
  9. package/lib/core/analysis/CallGraphAnalyzer.js +367 -0
  10. package/lib/core/analysis/CallSiteExtractor.js +629 -0
  11. package/lib/core/analysis/DataFlowInferrer.js +57 -0
  12. package/lib/core/analysis/ImportPathResolver.js +189 -0
  13. package/lib/core/analysis/ImportRecord.js +105 -0
  14. package/lib/core/analysis/SymbolTableBuilder.js +211 -0
  15. package/lib/core/ast/ProjectGraph.js +8 -0
  16. package/lib/core/ast/lang-dart.js +352 -5
  17. package/lib/core/ast/lang-go.js +212 -10
  18. package/lib/core/ast/lang-java.js +205 -1
  19. package/lib/core/ast/lang-kotlin.js +330 -1
  20. package/lib/core/ast/lang-python.js +31 -2
  21. package/lib/core/ast/lang-rust.js +284 -3
  22. package/lib/core/ast/lang-swift.js +180 -1
  23. package/lib/core/ast/lang-typescript.js +290 -1
  24. package/lib/core/discovery/index.js +2 -2
  25. package/lib/external/ai/AiProvider.js +66 -172
  26. package/lib/external/ai/providers/GoogleGeminiProvider.js +23 -1
  27. package/lib/external/mcp/McpServer.js +1 -0
  28. package/lib/external/mcp/handlers/bootstrap/BootstrapSession.js +1 -1
  29. package/lib/external/mcp/handlers/bootstrap/ExternalSubmissionTracker.js +3 -3
  30. package/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.js +22 -1
  31. package/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +1 -1
  32. package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-configs.js +2 -1
  33. package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-context.js +8 -8
  34. package/lib/external/mcp/handlers/bootstrap/pipeline/noAiFallback.js +1 -1
  35. package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +311 -162
  36. package/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +102 -7
  37. package/lib/external/mcp/handlers/bootstrap/shared/dimension-sop.js +1 -1
  38. package/lib/external/mcp/handlers/bootstrap-external.js +9 -2
  39. package/lib/external/mcp/handlers/bootstrap-internal.js +19 -8
  40. package/lib/external/mcp/handlers/consolidated.js +9 -0
  41. package/lib/external/mcp/handlers/dimension-complete-external.js +6 -6
  42. package/lib/external/mcp/handlers/guard.js +3 -3
  43. package/lib/external/mcp/handlers/structure.js +62 -0
  44. package/lib/external/mcp/handlers/wiki-external.js +66 -3
  45. package/lib/external/mcp/tools.js +36 -1
  46. package/lib/http/HttpServer.js +1 -1
  47. package/lib/http/middleware/requestLogger.js +1 -0
  48. package/lib/http/routes/ai.js +240 -35
  49. package/lib/http/routes/candidates.js +2 -3
  50. package/lib/http/routes/extract.js +13 -11
  51. package/lib/http/routes/modules.js +2 -2
  52. package/lib/http/routes/recipes.js +9 -5
  53. package/lib/http/routes/remote.js +149 -270
  54. package/lib/http/routes/violations.js +0 -54
  55. package/lib/http/utils/sse-sessions.js +1 -1
  56. package/lib/infrastructure/logging/Logger.js +5 -4
  57. package/lib/infrastructure/monitoring/PerformanceMonitor.js +3 -2
  58. package/lib/injection/ServiceContainer.js +70 -28
  59. package/lib/platform/ScreenCaptureService.js +177 -0
  60. package/lib/platform/ios/index.js +2 -2
  61. package/lib/platform/ios/routes/spm.js +2 -2
  62. package/lib/platform/ios/spm/PackageSwiftParser.js +14 -3
  63. package/lib/platform/ios/spm/SpmDiscoverer.js +123 -17
  64. package/lib/platform/ios/spm/{SpmService.js → SpmHelper.js} +43 -675
  65. package/lib/platform/ios/xcode/XcodeWriteUtils.js +1 -1
  66. package/lib/service/agent/AgentEventBus.js +207 -0
  67. package/lib/service/agent/AgentFactory.js +490 -0
  68. package/lib/service/agent/AgentMessage.js +240 -0
  69. package/lib/service/agent/AgentRouter.js +228 -0
  70. package/lib/service/agent/AgentRuntime.js +1016 -0
  71. package/lib/service/agent/AgentState.js +217 -0
  72. package/lib/service/agent/IntentClassifier.js +331 -0
  73. package/lib/service/agent/LarkTransport.js +389 -0
  74. package/lib/service/agent/capabilities.js +408 -0
  75. package/lib/service/{chat → agent/context}/ContextWindow.js +37 -12
  76. package/lib/service/{chat → agent/context}/ExplorationTracker.js +77 -22
  77. package/lib/service/{chat → agent/core}/ChatAgentPrompts.js +14 -2
  78. package/lib/service/agent/core/LoopContext.js +170 -0
  79. package/lib/service/agent/core/MessageAdapter.js +223 -0
  80. package/lib/service/agent/core/ToolExecutionPipeline.js +376 -0
  81. package/lib/service/{chat → agent/domain}/ChatAgentTasks.js +19 -98
  82. package/lib/service/{chat → agent/domain}/EpisodicConsolidator.js +7 -7
  83. package/lib/service/{chat → agent/domain}/EvidenceCollector.js +4 -2
  84. package/lib/service/{chat/AnalystAgent.js → agent/domain/insight-analyst.js} +37 -172
  85. package/lib/service/{chat/HandoffProtocol.js → agent/domain/insight-gate.js} +91 -123
  86. package/lib/service/agent/domain/insight-producer.js +267 -0
  87. package/lib/service/agent/domain/scan-prompts.js +105 -0
  88. package/lib/service/agent/forced-summary.js +266 -0
  89. package/lib/service/agent/index.js +91 -0
  90. package/lib/service/{chat → agent}/memory/ActiveContext.js +3 -1
  91. package/lib/service/{chat → agent}/memory/MemoryCoordinator.js +7 -7
  92. package/lib/service/{chat/ProjectSemanticMemory.js → agent/memory/PersistentMemory.js} +359 -89
  93. package/lib/service/{chat → agent}/memory/SessionStore.js +5 -4
  94. package/lib/service/{chat → agent}/memory/index.js +1 -1
  95. package/lib/service/agent/policies.js +442 -0
  96. package/lib/service/agent/presets.js +303 -0
  97. package/lib/service/agent/strategies.js +717 -0
  98. package/lib/service/{chat → agent/tools}/ToolRegistry.js +3 -3
  99. package/lib/service/agent/tools/ai-analysis.js +75 -0
  100. package/lib/service/{chat → agent}/tools/ast-graph.js +229 -32
  101. package/lib/service/{chat → agent}/tools/composite.js +2 -1
  102. package/lib/service/{chat → agent}/tools/guard.js +1 -121
  103. package/lib/service/{chat → agent}/tools/index.js +33 -22
  104. package/lib/service/{chat → agent}/tools/infrastructure.js +6 -1
  105. package/lib/service/agent/tools/knowledge-graph.js +112 -0
  106. package/lib/service/agent/tools/scan-recipe.js +189 -0
  107. package/lib/service/agent/tools/system-interaction.js +476 -0
  108. package/lib/service/automation/DirectiveDetector.js +0 -1
  109. package/lib/service/automation/FileWatcher.js +0 -8
  110. package/lib/service/automation/handlers/CreateHandler.js +7 -3
  111. package/lib/service/automation/handlers/DraftHandler.js +7 -6
  112. package/lib/service/cursor/CursorDeliveryPipeline.js +167 -1
  113. package/lib/service/knowledge/CodeEntityGraph.js +327 -2
  114. package/lib/service/knowledge/KnowledgeService.js +5 -1
  115. package/lib/service/module/ModuleService.js +49 -73
  116. package/lib/service/skills/SignalCollector.js +26 -19
  117. package/lib/service/snippet/codecs/VSCodeCodec.js +1 -1
  118. package/lib/service/wiki/WikiGenerator.js +1 -1
  119. package/lib/shared/FieldSpec.js +1 -1
  120. package/lib/shared/PathGuard.js +1 -1
  121. package/lib/shared/StyleGuide.js +1 -1
  122. package/package.json +4 -1
  123. package/resources/native-ui/screenshot.swift +228 -0
  124. package/dashboard/dist/assets/index-BaGY7kJI.css +0 -1
  125. package/dashboard/dist/assets/index-DfHY_3ln.js +0 -128
  126. package/lib/core/discovery/SpmDiscoverer.js +0 -5
  127. package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +0 -749
  128. package/lib/external/mcp/handlers/bootstrap/pipeline/ToolResultCache.js +0 -277
  129. package/lib/http/routes/spm.js +0 -5
  130. package/lib/infrastructure/external/XcodeAutomation.js +0 -15
  131. package/lib/service/chat/ChatAgent.js +0 -1602
  132. package/lib/service/chat/Memory.js +0 -161
  133. package/lib/service/chat/ProducerAgent.js +0 -431
  134. package/lib/service/chat/ReasoningTrace.js +0 -523
  135. package/lib/service/chat/TaskPipeline.js +0 -357
  136. package/lib/service/chat/WorkingMemory.js +0 -357
  137. package/lib/service/chat/memory/PersistentMemory.js +0 -450
  138. package/lib/service/chat/tools/ai-analysis.js +0 -267
  139. package/lib/service/chat/tools/knowledge-graph.js +0 -234
  140. package/lib/service/chat/tools.js +0 -18
  141. package/lib/service/snippet/PlaceholderConverter.js +0 -5
  142. package/lib/service/snippet/codecs/XcodeCodec.js +0 -5
  143. /package/lib/service/{chat → agent}/ConversationStore.js +0 -0
  144. /package/lib/service/{chat → agent}/tools/_shared.js +0 -0
  145. /package/lib/service/{chat → agent}/tools/lifecycle.js +0 -0
  146. /package/lib/service/{chat → agent}/tools/project-access.js +0 -0
  147. /package/lib/service/{chat → agent}/tools/query.js +0 -0
@@ -1,16 +1,16 @@
1
1
  /**
2
2
  * ToolRegistry — 统一工具注册表
3
3
  *
4
- * 管理 ChatAgent 可调用的所有工具定义。
4
+ * 管理 Agent 可调用的所有工具定义。
5
5
  * 每个工具包含: name, description, parameters(JSON Schema), handler
6
6
  *
7
7
  * 设计原则:
8
8
  * - 所有 AI 能力均封装为 Tool,不再散落在各处
9
9
  * - Tool handler 仅做参数整理 + 调用已有 Service,不含业务逻辑
10
- * - 支持 programmatic 直接调用 (executeTool) Agent ReAct 循环调用
10
+ * - 支持 Agent ReAct 循环调用(通过 LLM 推理决定工具调用)
11
11
  */
12
12
 
13
- import Logger from '../../infrastructure/logging/Logger.js';
13
+ import Logger from '../../../infrastructure/logging/Logger.js';
14
14
 
15
15
  /**
16
16
  * AI 模型常见的参数命名变体 → schema 标准名映射
@@ -0,0 +1,75 @@
1
+ /**
2
+ * ai-analysis.js — AI 分析类工具 (2)
3
+ *
4
+ * 9. enrich_candidate 结构补齐
5
+ * 9b. refine_bootstrap_candidates 内容润色
6
+ *
7
+ * 注意: summarize_code / extract_recipes 已删除。
8
+ * 代码摘要和 Recipe 提取由 Agent LLM 直接推理完成,不再需要专用工具。
9
+ */
10
+
11
+ // ────────────────────────────────────────────────────────────
12
+ // 9. enrich_candidate
13
+ // ────────────────────────────────────────────────────────────
14
+ export const enrichCandidate = {
15
+ name: 'enrich_candidate',
16
+ description:
17
+ '① 结构补齐 — 自动填充缺失的结构性语义字段(rationale/knowledgeType/complexity/scope/steps/constraints)。批量处理,只填空不覆盖。建议在 refine_bootstrap_candidates 之前执行。',
18
+ parameters: {
19
+ type: 'object',
20
+ properties: {
21
+ candidateIds: {
22
+ type: 'array',
23
+ items: { type: 'string' },
24
+ description: '候选 ID 列表 (最多 20 个)',
25
+ },
26
+ },
27
+ required: ['candidateIds'],
28
+ },
29
+ handler: async (params, ctx) => {
30
+ if (!ctx.aiProvider) {
31
+ return { error: 'AI provider not available' };
32
+ }
33
+ // V3: 使用 MCP handler enrichCandidates 的逻辑
34
+ const { enrichCandidates: enrichFn } = await import('../../../external/mcp/handlers/candidate.js');
35
+ const result = await enrichFn(ctx, { candidateIds: params.candidateIds });
36
+ return result?.data || result;
37
+ },
38
+ };
39
+
40
+ // ────────────────────────────────────────────────────────────
41
+ // 9b. refine_bootstrap_candidates (Phase 6)
42
+ // ────────────────────────────────────────────────────────────
43
+ export const refineBootstrapCandidates = {
44
+ name: 'refine_bootstrap_candidates',
45
+ description:
46
+ '② 内容润色 — 逐条精炼 Bootstrap 候选的内容质量:改善 summary、补充架构 insight、推断 relations 关联、调整 confidence、丰富 tags。建议在 enrich_candidate 之后执行。',
47
+ parameters: {
48
+ type: 'object',
49
+ properties: {
50
+ candidateIds: {
51
+ type: 'array',
52
+ items: { type: 'string' },
53
+ description: '指定候选 ID 列表(可选,默认全部 bootstrap 候选)',
54
+ },
55
+ userPrompt: {
56
+ type: 'string',
57
+ description: '用户自定义润色提示词,指导 AI 润色方向(如"侧重描述线程安全注意事项")',
58
+ },
59
+ dryRun: { type: 'boolean', description: '仅预览 AI 润色结果,不写入数据库' },
60
+ },
61
+ },
62
+ handler: async (params, ctx) => {
63
+ if (!ctx.aiProvider) {
64
+ return { error: 'AI provider not available' };
65
+ }
66
+ // V3: 委托给 bootstrap handler 的 refine 逻辑
67
+ const { bootstrapRefine } = await import('../../../external/mcp/handlers/bootstrap-internal.js');
68
+ const result = await bootstrapRefine(ctx, {
69
+ candidateIds: params.candidateIds,
70
+ userPrompt: params.userPrompt,
71
+ dryRun: params.dryRun,
72
+ });
73
+ return result?.data || result;
74
+ },
75
+ };
@@ -1,16 +1,17 @@
1
1
  /**
2
- * ast-graph.js — AST 结构化分析 + Agent Memory 工具 (10)
2
+ * ast-graph.js — AST 结构化分析 + Agent Memory 工具 (11)
3
3
  *
4
4
  * 44. get_project_overview 项目 AST 概览
5
5
  * 45. get_class_hierarchy 类继承层级
6
- * 46. get_class_info 类详细信息
7
- * 47. get_protocol_info 协议详细信息
6
+ * 46. get_class_info 类/结构体详细信息 (跨语言)
7
+ * 47. get_protocol_info 协议/接口/trait 详细信息 (跨语言)
8
8
  * 48. get_method_overrides 方法覆写查询
9
- * 49. get_category_map Category 扩展映射
9
+ * 49. get_category_map Category/Extension 扩展映射
10
10
  * 50. get_previous_analysis 前序维度分析结果
11
11
  * 51. note_finding 记录关键发现
12
12
  * 52. get_previous_evidence 检索前序维度证据
13
13
  * 53. query_code_graph 查询代码实体图谱
14
+ * 54. query_call_graph 查询方法调用链 (Phase 5)
14
15
  */
15
16
 
16
17
  // ════════════════════════════════════════════════════════════
@@ -36,7 +37,8 @@ function _getProjectGraph(ctx) {
36
37
  export const getProjectOverview = {
37
38
  name: 'get_project_overview',
38
39
  description:
39
- '获取项目的整体结构概览:文件统计、模块列表、入口点、类/协议/Category 数量。' +
40
+ '获取项目的整体结构概览:文件统计、语言分布、模块列表、入口点、类/协议/Category 数量。' +
41
+ '支持所有语言 (Swift/ObjC/Java/Kotlin/Python/TS/JS/Dart/Rust/Go 等)。' +
40
42
  '适用场景:了解项目规模和架构布局,规划探索路径。',
41
43
  parameters: {
42
44
  type: 'object',
@@ -49,13 +51,30 @@ export const getProjectOverview = {
49
51
  }
50
52
 
51
53
  const o = graph.getOverview();
54
+
55
+ // §P2: 从文件扩展名统计语言分布
56
+ const langStats = {};
57
+ for (const filePath of graph.getAllFilePaths?.() || []) {
58
+ const ext = filePath.split('.').pop();
59
+ if (ext) langStats[ext] = (langStats[ext] || 0) + 1;
60
+ }
61
+
52
62
  const lines = [
53
63
  `📊 项目 AST 概览 (构建耗时 ${o.buildTimeMs}ms)`,
54
64
  ``,
55
- `文件: ${o.totalFiles} | 类: ${o.totalClasses} | 协议: ${o.totalProtocols} | Category: ${o.totalCategories} | 方法: ${o.totalMethods}`,
56
- ``,
57
- `── 模块 ──`,
65
+ `文件: ${o.totalFiles} | 类: ${o.totalClasses} | 协议/接口: ${o.totalProtocols} | Category/Extension: ${o.totalCategories} | 方法: ${o.totalMethods}`,
58
66
  ];
67
+
68
+ // 语言分布
69
+ const langEntries = Object.entries(langStats).sort((a, b) => b[1] - a[1]);
70
+ if (langEntries.length > 0) {
71
+ lines.push(``, `── 语言分布 ──`);
72
+ for (const [ext, count] of langEntries) {
73
+ lines.push(` .${ext}: ${count} 个文件`);
74
+ }
75
+ }
76
+
77
+ lines.push(``, `── 模块 ──`);
59
78
  for (const mod of o.topLevelModules) {
60
79
  const count = o.classesPerModule[mod] || 0;
61
80
  lines.push(` ${mod}/ — ${count} 个类`);
@@ -76,7 +95,8 @@ export const getProjectOverview = {
76
95
  export const getClassHierarchy = {
77
96
  name: 'get_class_hierarchy',
78
97
  description:
79
- '查看指定类的继承链(向上到根类)和直接子类列表。' +
98
+ '查看指定类/结构体的继承链(向上到根类)和直接子类列表。' +
99
+ '支持所有语言的类继承体系 (Swift class/struct, Java/Kotlin class, Python class, TS class, Dart class, Rust struct, Go struct 等)。' +
80
100
  '传入 className 查看指定类,不传则返回项目中所有根类及其子树。',
81
101
  parameters: {
82
102
  type: 'object',
@@ -138,7 +158,9 @@ export const getClassHierarchy = {
138
158
  // ────────────────────────────────────────────────────────────
139
159
  export const getClassInfo = {
140
160
  name: 'get_class_info',
141
- description: '获取指定类的详细信息: 属性、方法签名、导入、继承关系、Category 扩展。',
161
+ description:
162
+ '获取指定类/结构体的详细信息: 属性、方法签名、导入、继承关系、扩展。' +
163
+ '跨语言通用:ObjC @interface, Swift class/struct, Java/Kotlin class, Python class, TS/JS class, Dart class, Rust struct impl, Go struct 等。',
142
164
  parameters: {
143
165
  type: 'object',
144
166
  properties: {
@@ -169,7 +191,7 @@ export const getClassInfo = {
169
191
  ];
170
192
 
171
193
  if (info.protocols.length > 0) {
172
- lines.push(`遵循: <${info.protocols.join(', ')}>`);
194
+ lines.push(`实现: ${info.protocols.join(', ')}`);
173
195
  }
174
196
 
175
197
  if (info.properties.length > 0) {
@@ -195,7 +217,7 @@ export const getClassInfo = {
195
217
  }
196
218
 
197
219
  if (cats.length > 0) {
198
- lines.push(``, `── Category 扩展 (${cats.length}) ──`);
220
+ lines.push(``, `── 扩展 (${cats.length}) ──`);
199
221
  for (const cat of cats) {
200
222
  const methodNames = cat.methods.map((m) => m.selector).join(', ');
201
223
  lines.push(` ${info.name}(${cat.categoryName}) — ${cat.filePath} — [${methodNames}]`);
@@ -218,7 +240,9 @@ export const getClassInfo = {
218
240
  // ────────────────────────────────────────────────────────────
219
241
  export const getProtocolInfo = {
220
242
  name: 'get_protocol_info',
221
- description: '获取指定协议的定义(必选/可选方法)及所有遵循该协议的类。',
243
+ description:
244
+ '获取指定协议/接口/trait 的定义(必选/可选方法)及所有实现者列表。' +
245
+ '跨语言通用:ObjC @protocol, Swift protocol, Java/Kotlin interface, Python ABC, TS interface, Dart abstract class, Rust trait, Go interface 等。',
222
246
  parameters: {
223
247
  type: 'object',
224
248
  properties: {
@@ -235,36 +259,36 @@ export const getProtocolInfo = {
235
259
  const protocolName = params.protocolName || params.protocol_name;
236
260
  const info = graph.getProtocolInfo(protocolName);
237
261
  if (!info) {
238
- return `未找到协议 "${protocolName}"。可以使用 get_project_overview 查看项目中的所有协议。`;
262
+ return `未找到协议/接口 "${protocolName}"。可以使用 get_project_overview 查看项目中的所有协议/接口。`;
239
263
  }
240
264
 
241
- const lines = [`📋 @protocol ${info.name}`, `文件: ${info.filePath}:${info.line}`];
265
+ const lines = [`📋 ${info.name}`, `文件: ${info.filePath}:${info.line}`];
242
266
 
243
267
  if (info.inherits.length > 0) {
244
- lines.push(`继承: <${info.inherits.join(', ')}>`);
268
+ lines.push(`继承: ${info.inherits.join(', ')}`);
245
269
  }
246
270
 
247
271
  if (info.requiredMethods.length > 0) {
248
- lines.push(``, `── @required (${info.requiredMethods.length}) ──`);
272
+ lines.push(``, `── 必须实现 (${info.requiredMethods.length}) ──`);
249
273
  for (const m of info.requiredMethods) {
250
274
  lines.push(` ${m.isClassMethod ? '+' : '-'} ${m.selector} → ${m.returnType}`);
251
275
  }
252
276
  }
253
277
 
254
278
  if (info.optionalMethods.length > 0) {
255
- lines.push(``, `── @optional (${info.optionalMethods.length}) ──`);
279
+ lines.push(``, `── 可选实现 (${info.optionalMethods.length}) ──`);
256
280
  for (const m of info.optionalMethods) {
257
281
  lines.push(` ${m.isClassMethod ? '+' : '-'} ${m.selector} → ${m.returnType}`);
258
282
  }
259
283
  }
260
284
 
261
285
  if (info.conformers.length > 0) {
262
- lines.push(``, `── 遵循者 (${info.conformers.length}) ──`);
286
+ lines.push(``, `── 实现者 (${info.conformers.length}) ──`);
263
287
  for (const c of info.conformers) {
264
288
  lines.push(` ${c}`);
265
289
  }
266
290
  } else {
267
- lines.push(``, `⚠️ 暂未发现遵循此协议的类`);
291
+ lines.push(``, `⚠️ 暂未发现实现此协议/接口的类`);
268
292
  }
269
293
 
270
294
  return lines.join('\n');
@@ -276,7 +300,9 @@ export const getProtocolInfo = {
276
300
  // ────────────────────────────────────────────────────────────
277
301
  export const getMethodOverrides = {
278
302
  name: 'get_method_overrides',
279
- description: '查找覆写了指定方法的所有子类。适用于理解方法在继承树中的多态行为。',
303
+ description:
304
+ '查找覆写了指定方法的所有子类。适用于理解方法在继承树中的多态行为。' +
305
+ '跨语言通用:支持 ObjC/Swift/Java/Kotlin/Python/TS/Dart 等语言的方法覆写。',
280
306
  parameters: {
281
307
  type: 'object',
282
308
  properties: {
@@ -314,7 +340,9 @@ export const getMethodOverrides = {
314
340
  export const getCategoryMap = {
315
341
  name: 'get_category_map',
316
342
  description:
317
- '获取指定类或整个项目的 ObjC Category 扩展映射。Category 是 ObjC 的核心模式,了解它有助于发现功能划分。',
343
+ '获取指定类的 Category/Extension 扩展映射。' +
344
+ 'ObjC Category、Swift Extension 等语言的类扩展机制。了解它有助于发现功能划分。' +
345
+ '不传 className 则返回整个项目中有扩展的类列表。',
318
346
  parameters: {
319
347
  type: 'object',
320
348
  properties: {
@@ -455,7 +483,9 @@ export const noteFinding = {
455
483
  const coordinator = ctx._memoryCoordinator;
456
484
  if (coordinator) {
457
485
  const finding = params.finding || '';
458
- const evidence = params.evidence || '';
486
+ // P0 Fix: AI 可能传入 array/object,强制转为 string
487
+ const rawEvidence = params.evidence;
488
+ const evidence = typeof rawEvidence === 'string' ? rawEvidence : Array.isArray(rawEvidence) ? rawEvidence.join(', ') : rawEvidence ? String(rawEvidence) : '';
459
489
  const importance = params.importance || 5;
460
490
  const round = ctx._currentRound || 0;
461
491
  const scopeId = ctx._dimensionScopeId || undefined;
@@ -547,8 +577,8 @@ export const queryCodeGraph = {
547
577
  },
548
578
  entity_type: {
549
579
  type: 'string',
550
- enum: ['class', 'protocol', 'category', 'module', 'pattern'],
551
- description: '实体类型过滤 (可选)',
580
+ enum: ['class', 'protocol', 'category', 'module', 'pattern', 'method'],
581
+ description: '实体类型过滤 (可选,含 Phase 5 method 类型)',
552
582
  },
553
583
  max_depth: {
554
584
  type: 'number',
@@ -559,14 +589,17 @@ export const queryCodeGraph = {
559
589
  },
560
590
  handler: async (params, ctx) => {
561
591
  try {
562
- const { CodeEntityGraph } = await import('../../knowledge/CodeEntityGraph.js');
563
- const db = ctx?.container?.get('database');
564
- if (!db) {
565
- return '代码实体图谱不可用: 数据库未初始化';
592
+ // 优先从 container 获取单例 CEG,避免每次创建新实例
593
+ let ceg = ctx?.container?.get?.('codeEntityGraph');
594
+ if (!ceg) {
595
+ const { CodeEntityGraph } = await import('../../knowledge/CodeEntityGraph.js');
596
+ const db = ctx?.container?.get?.('database');
597
+ if (!db) {
598
+ return '代码实体图谱不可用: 数据库未初始化';
599
+ }
600
+ const projectRoot = ctx?.projectRoot || process.env.ASD_PROJECT_DIR || '';
601
+ ceg = new CodeEntityGraph(db, { projectRoot });
566
602
  }
567
-
568
- const projectRoot = ctx?.projectRoot || process.env.ASD_PROJECT_DIR || '';
569
- const ceg = new CodeEntityGraph(db, { projectRoot });
570
603
  const maxDepth = params.max_depth || 3;
571
604
 
572
605
  switch (params.action) {
@@ -680,3 +713,167 @@ export const queryCodeGraph = {
680
713
  }
681
714
  },
682
715
  };
716
+
717
+ // ────────────────────────────────────────────────────────────
718
+ // 54. query_call_graph — 查询方法调用链 (Phase 5)
719
+ // ────────────────────────────────────────────────────────────
720
+ export const queryCallGraph = {
721
+ name: 'query_call_graph',
722
+ description:
723
+ '查询方法的调用链上下文 (Call Graph)。支持 10+ 种编程语言 (Swift/ObjC/Java/Kotlin/Python/TS/JS/Dart/Rust/Go)。\n' +
724
+ '• callers: 谁调用了这个方法?(向上追踪调用者链)\n' +
725
+ '• callees: 这个方法调用了谁?(向下追踪依赖链)\n' +
726
+ '• both: 同时获取调用者和被调用者\n' +
727
+ '• impact: 修改此方法的影响半径分析 (受影响文件数)\n' +
728
+ '• search: 按名称搜索方法实体\n' +
729
+ '⚠️ 需要先完成 bootstrap 才有数据。方法名格式: "ClassName.methodName" 或简写 "methodName"。',
730
+ parameters: {
731
+ type: 'object',
732
+ properties: {
733
+ methodName: {
734
+ type: 'string',
735
+ description:
736
+ '方法名 (e.g. "UserService.getUser", "viewDidLoad", "handleClick")。' +
737
+ 'search 模式下为搜索关键词。',
738
+ },
739
+ direction: {
740
+ type: 'string',
741
+ enum: ['callers', 'callees', 'both', 'impact', 'search'],
742
+ description:
743
+ 'callers=调用者 | callees=被调用者 | both=双向 | impact=影响分析 | search=搜索方法实体',
744
+ },
745
+ maxDepth: {
746
+ type: 'number',
747
+ description: '最大遍历深度 (1-5, 默认 2)',
748
+ },
749
+ },
750
+ required: ['methodName'],
751
+ },
752
+ handler: async (params, ctx) => {
753
+ try {
754
+ // 前置: 必填参数校验 (fail-fast)
755
+ const methodName = params.methodName || params.method_name;
756
+ if (!methodName) {
757
+ return '请提供 methodName 参数。';
758
+ }
759
+
760
+ // 优先从 container 获取单例 CEG,避免每次创建新实例
761
+ let ceg = ctx?.container?.get?.('codeEntityGraph');
762
+ if (!ceg) {
763
+ // fallback: 手动构建
764
+ const { CodeEntityGraph } = await import('../../knowledge/CodeEntityGraph.js');
765
+ const db = ctx?.container?.get?.('database');
766
+ if (!db) {
767
+ return '调用图查询不可用: 数据库未初始化。';
768
+ }
769
+ const projectRoot = ctx?.projectRoot || process.env.ASD_PROJECT_DIR || '';
770
+ ceg = new CodeEntityGraph(db, { projectRoot });
771
+ }
772
+
773
+ const direction = params.direction || 'both';
774
+ const maxDepth = Math.min(Math.max(Number(params.maxDepth || params.max_depth) || 2, 1), 5);
775
+
776
+ // search 模式: 按名称搜索方法实体
777
+ if (direction === 'search') {
778
+ const results = ceg.searchEntities(methodName, { type: 'method', limit: 15 });
779
+ if (results.length === 0) {
780
+ // 降级: 不限类型搜索
781
+ const allResults = ceg.searchEntities(methodName, { limit: 15 });
782
+ if (allResults.length === 0) {
783
+ return `未找到匹配 "${methodName}" 的实体。请确认 bootstrap 已完成。`;
784
+ }
785
+ const lines = [`🔍 搜索 "${methodName}" (${allResults.length} 条, 无 method 类型匹配):`];
786
+ for (const e of allResults) {
787
+ lines.push(` • [${e.entityType}] ${e.name}${e.filePath ? ` (${e.filePath})` : ''}`);
788
+ }
789
+ lines.push(``, `💡 提示: 调用图查询需使用 method 实体的 entityId。`);
790
+ return lines.join('\n');
791
+ }
792
+ const lines = [`🔍 方法搜索 "${methodName}" (${results.length} 条):`];
793
+ for (const e of results) {
794
+ lines.push(` • ${e.name}${e.filePath ? ` (${e.filePath})` : ''}`);
795
+ }
796
+ lines.push(``, `💡 复制上面的完整方法名,用 callers/callees/both/impact 查询其调用链。`);
797
+ return lines.join('\n');
798
+ }
799
+
800
+ // impact 模式
801
+ if (direction === 'impact') {
802
+ const impact = ceg.getCallImpactRadius(methodName);
803
+ const lines = [
804
+ `⚡ 修改 "${methodName}" 的影响半径:`,
805
+ ` 直接调用者: ${impact.directCallers}`,
806
+ ` 传递性调用者 (depth≤3): ${impact.transitiveCallers}`,
807
+ ];
808
+ if (impact.affectedFiles.length > 0) {
809
+ lines.push(` 受影响文件 (${impact.affectedFiles.length}):`);
810
+ for (const f of impact.affectedFiles.slice(0, 15)) {
811
+ lines.push(` 📄 ${f}`);
812
+ }
813
+ if (impact.affectedFiles.length > 15) {
814
+ lines.push(` ... 还有 ${impact.affectedFiles.length - 15} 个文件`);
815
+ }
816
+ } else {
817
+ lines.push(` 未发现受影响文件 (可能是叶子方法或 bootstrap 无调用图数据)。`);
818
+ }
819
+ return lines.join('\n');
820
+ }
821
+
822
+ // callers / callees / both 模式
823
+ const result = {};
824
+ if (direction === 'callers' || direction === 'both') {
825
+ result.callers = ceg.getCallers(methodName, maxDepth);
826
+ }
827
+ if (direction === 'callees' || direction === 'both') {
828
+ result.callees = ceg.getCallees(methodName, maxDepth);
829
+ }
830
+
831
+ const totalCallers = result.callers?.length || 0;
832
+ const totalCallees = result.callees?.length || 0;
833
+
834
+ if (totalCallers === 0 && totalCallees === 0) {
835
+ return (
836
+ `"${methodName}" 在调用图中没有找到调用关系。\n\n` +
837
+ `可能原因:\n` +
838
+ ` 1. 方法名拼写不匹配 — 尝试 search 模式: query_call_graph({methodName:"关键词", direction:"search"})\n` +
839
+ ` 2. 该方法是入口点/叶子节点,无上下游\n` +
840
+ ` 3. bootstrap 尚未执行或不包含此文件`
841
+ );
842
+ }
843
+
844
+ const lines = [`📞 "${methodName}" 的调用链 (depth≤${maxDepth}):`];
845
+
846
+ if (result.callers?.length > 0) {
847
+ lines.push(``, `── 调用者 (谁调用了它, ${result.callers.length} 条) ──`);
848
+ for (const c of result.callers.slice(0, 20)) {
849
+ const indent = ' '.repeat(c.depth);
850
+ const typeTag = c.callType !== 'unknown' ? ` [${c.callType}]` : '';
851
+ lines.push(`${indent}⬆ ${c.caller}${typeTag}`);
852
+ }
853
+ if (result.callers.length > 20) {
854
+ lines.push(` ... 还有 ${result.callers.length - 20} 个调用者`);
855
+ }
856
+ }
857
+
858
+ if (result.callees?.length > 0) {
859
+ lines.push(``, `── 被调用者 (它调用了谁, ${result.callees.length} 条) ──`);
860
+ for (const c of result.callees.slice(0, 20)) {
861
+ const indent = ' '.repeat(c.depth);
862
+ const typeTag = c.callType !== 'unknown' ? ` [${c.callType}]` : '';
863
+ lines.push(`${indent}⬇ ${c.callee}${typeTag}`);
864
+ }
865
+ if (result.callees.length > 20) {
866
+ lines.push(` ... 还有 ${result.callees.length - 20} 个被调用者`);
867
+ }
868
+ }
869
+
870
+ return lines.join('\n');
871
+ } catch (err) {
872
+ // 表不存在 → 未 bootstrap
873
+ if (err.message?.includes('no such table')) {
874
+ return '调用图数据不可用 — knowledge_edges 表不存在,请先运行 bootstrap。';
875
+ }
876
+ return `调用图查询失败: ${err.message}`;
877
+ }
878
+ },
879
+ };
@@ -160,7 +160,7 @@ export const submitWithCheck = {
160
160
  content: {
161
161
  type: 'object',
162
162
  description:
163
- '{ markdown: "项目特写 Markdown", pattern: "核心代码 3-8 行,必须语法完整(括号配对、不能以 } 开头或 { 结尾)" }',
163
+ '{ markdown: "项目特写 Markdown (≥200字符,含代码块)", rationale: "设计原理说明 (必填)", pattern: "核心代码 3-8 行,语法完整" }',
164
164
  },
165
165
  title: { type: 'string', description: '候选标题' },
166
166
  description: { type: 'string', description: '中文简述 ≤80 字' },
@@ -234,6 +234,7 @@ export const submitWithCheck = {
234
234
  ctx.logger?.info(`[submit_with_check] ✗ validator rejected: ${validResult.errors.join('; ')}`);
235
235
  return {
236
236
  submitted: false,
237
+ status: 'rejected',
237
238
  reason: 'validation_failed',
238
239
  errors: validResult.errors,
239
240
  warnings: validResult.warnings,
@@ -1,12 +1,10 @@
1
1
  /**
2
- * guard.js — Guard 安全类工具 (6)
2
+ * guard.js — Guard 安全类工具 (4)
3
3
  *
4
4
  * 7b. list_guard_rules 列出 Guard 规则
5
5
  * 8b. get_recommendations 获取推荐 Recipe
6
- * 12. ai_translate AI 翻译
7
6
  * 13. guard_check_code Guard 检查代码
8
7
  * 14. query_violations 查询违规历史
9
- * 15. generate_guard_rule AI 生成 Guard 规则
10
8
  */
11
9
 
12
10
  // ────────────────────────────────────────────────────────────
@@ -75,46 +73,6 @@ export const getRecommendations = {
75
73
  },
76
74
  };
77
75
 
78
- // ────────────────────────────────────────────────────────────
79
- // 12. ai_translate
80
- // ────────────────────────────────────────────────────────────
81
- export const aiTranslate = {
82
- name: 'ai_translate',
83
- description: 'AI 翻译 — 将中文 summary/usageGuide 翻译为英文。',
84
- parameters: {
85
- type: 'object',
86
- properties: {
87
- summary: { type: 'string', description: '中文摘要' },
88
- usageGuide: { type: 'string', description: '中文使用指南' },
89
- },
90
- },
91
- handler: async (params, ctx) => {
92
- if (!ctx.aiProvider) {
93
- return { error: 'AI provider not available' };
94
- }
95
- const { summary, usageGuide } = params;
96
- if (!summary && !usageGuide) {
97
- return { summaryEn: '', usageGuideEn: '' };
98
- }
99
-
100
- const systemPrompt =
101
- 'You are a technical translator. Translate from Chinese to English. Keep technical terms unchanged. Return ONLY valid JSON: { "summaryEn": "...", "usageGuideEn": "..." }.';
102
- const parts = [];
103
- if (summary) {
104
- parts.push(`summary: ${summary}`);
105
- }
106
- if (usageGuide) {
107
- parts.push(`usageGuide: ${usageGuide}`);
108
- }
109
-
110
- const parsed = await ctx.aiProvider.chatWithStructuredOutput(parts.join('\n'), {
111
- systemPrompt,
112
- temperature: 0.2,
113
- });
114
- return parsed || { summaryEn: summary || '', usageGuideEn: usageGuide || '' };
115
- },
116
- };
117
-
118
76
  // ────────────────────────────────────────────────────────────
119
77
  // 13. guard_check_code
120
78
  // ────────────────────────────────────────────────────────────
@@ -184,82 +142,4 @@ export const queryViolations = {
184
142
  },
185
143
  };
186
144
 
187
- // ────────────────────────────────────────────────────────────
188
- // 15. generate_guard_rule
189
- // ────────────────────────────────────────────────────────────
190
- export const generateGuardRule = {
191
- name: 'generate_guard_rule',
192
- description: 'AI 生成 Guard 规则 — 描述你想阻止的代码模式,AI 自动生成正则表达式和规则定义。',
193
- parameters: {
194
- type: 'object',
195
- properties: {
196
- description: {
197
- type: 'string',
198
- description: '规则描述(例如 "禁止在主线程使用同步网络请求")',
199
- },
200
- language: { type: 'string', description: '目标语言 (swift/objc 等)' },
201
- severity: { type: 'string', description: '严重程度 (error/warning/info),默认 warning' },
202
- autoCreate: { type: 'boolean', description: '是否自动创建到数据库,默认 false' },
203
- },
204
- required: ['description'],
205
- },
206
- handler: async (params, ctx) => {
207
- if (!ctx.aiProvider) {
208
- return { error: 'AI provider not available' };
209
- }
210
- const { description, language = 'swift', severity = 'warning', autoCreate = false } = params;
211
-
212
- const prompt = `Generate a Guard rule for this requirement:
213
- Description: ${description}
214
- Language: ${language}
215
- Severity: ${severity}
216
-
217
- Return ONLY valid JSON:
218
- {
219
- "name": "rule-name-kebab-case",
220
- "description": "One-line description in English",
221
- "description_cn": "一行中文描述",
222
- "pattern": "regex pattern for matching the problematic code",
223
- "languages": ["${language}"],
224
- "severity": "${severity}",
225
- "testCases": {
226
- "shouldMatch": ["code example that should trigger"],
227
- "shouldNotMatch": ["code example that should NOT trigger"]
228
- }
229
- }`;
230
-
231
- const rule = await ctx.aiProvider.chatWithStructuredOutput(prompt, { temperature: 0.2 });
232
- if (!rule) {
233
- return { error: 'Failed to parse AI response' };
234
- }
235
145
 
236
- // 验证正则表达式
237
- try {
238
- new RegExp(rule.pattern);
239
- } catch (e) {
240
- return { error: `Invalid regex pattern: ${e.message}`, rule };
241
- }
242
-
243
- // 自动创建
244
- if (autoCreate && rule.name && rule.pattern) {
245
- try {
246
- const guardService = ctx.container.get('guardService');
247
- const created = await guardService.createRule(
248
- {
249
- name: rule.name,
250
- description: rule.description || description,
251
- pattern: rule.pattern,
252
- languages: rule.languages || [language],
253
- severity: rule.severity || severity,
254
- },
255
- { userId: 'agent' }
256
- );
257
- return { rule, created: true, recipeId: created.id };
258
- } catch (err) {
259
- return { rule, created: false, error: err.message };
260
- }
261
- }
262
-
263
- return { rule, created: false };
264
- },
265
- };