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,8 +1,8 @@
1
1
  /**
2
- * ChatAgentTasks — ChatAgent 预定义任务方法(从 ChatAgent.js 提取)
2
+ * ChatAgentTasks — Agent 预定义任务方法
3
3
  *
4
- * 每个任务接收 context 对象: { executeTool, aiProvider, container, logger }
5
- * - executeTool(toolName, params) — 执行指定工具
4
+ * 每个任务接收 context 对象: { invokeAgent, aiProvider, container, logger }
5
+ * - invokeAgent(toolName, params) — 直接执行工具 handler(纯数据工具)
6
6
  * - aiProvider — AI Provider 实例
7
7
  * - container — ServiceContainer
8
8
  * - logger — Logger 实例
@@ -14,10 +14,10 @@
14
14
  * 2. 顺便返回质量评估建议
15
15
  */
16
16
  export async function taskCheckAndSubmit(context, { candidate, projectRoot }) {
17
- const { executeTool, aiProvider } = context;
17
+ const { invokeAgent, aiProvider } = context;
18
18
 
19
19
  // Step 1: 查重
20
- const duplicates = await executeTool('check_duplicate', {
20
+ const duplicates = await invokeAgent('check_duplicate', {
21
21
  candidate,
22
22
  projectRoot,
23
23
  threshold: 0.5,
@@ -61,102 +61,23 @@ ${highSim.map((s) => `- ${s.title} (相似度: ${s.similarity})`).join('\n')}
61
61
 
62
62
  /**
63
63
  * 任务: 批量发现 Recipe 间的知识图谱关系
64
- * 遍历所有 Recipe,两两分析可能的关系
64
+ * 委托给 AgentFactory.scanKnowledge (Agent 多轮推理)
65
65
  */
66
66
  export async function taskDiscoverAllRelations(context, { batchSize = 20 } = {}) {
67
- const { executeTool, aiProvider, container, logger } = context;
68
-
69
- const knowledgeService = container.get('knowledgeService');
70
- if (!knowledgeService) {
71
- throw new Error('KnowledgeService 不可用');
72
- }
73
-
74
- if (!aiProvider) {
75
- throw new Error('AI Provider 未配置,请先设置 API Key');
76
- }
77
-
78
- // 获取所有活跃知识条目
79
- const { items = [], data = [] } = await knowledgeService.list(
80
- { lifecycle: 'active' },
81
- { page: 1, pageSize: 500 }
82
- );
83
- const recipes = items.length > 0 ? items : data;
84
- if (recipes.length < 2) {
85
- return {
86
- discovered: 0,
87
- totalPairs: 0,
88
- message: `只有 ${recipes.length} 条 Recipe,至少需要 2 条`,
89
- };
90
- }
91
-
92
- // 按 batch 分组分析
93
- const pairs = [];
94
- for (let i = 0; i < recipes.length; i++) {
95
- for (let j = i + 1; j < recipes.length; j++) {
96
- pairs.push([recipes[i], recipes[j]]);
97
- }
98
- }
99
-
100
- let discovered = 0;
101
- const results = [];
102
- let batchErrors = 0;
103
-
104
- // 分批处理,单批失败不终止整体
105
- for (let b = 0; b < pairs.length; b += batchSize) {
106
- const batch = pairs.slice(b, b + batchSize);
107
- try {
108
- const result = await executeTool('discover_relations', {
109
- recipePairs: batch.map(([a, b]) => ({
110
- a: {
111
- id: a.id,
112
- title: a.title,
113
- category: a.category,
114
- language: a.language,
115
- code: String(a.content || a.code || '').substring(0, 500),
116
- },
117
- b: {
118
- id: b.id,
119
- title: b.title,
120
- category: b.category,
121
- language: b.language,
122
- code: String(b.content || b.code || '').substring(0, 500),
123
- },
124
- })),
125
- });
126
-
127
- if (result.error) {
128
- batchErrors++;
129
- logger.warn(
130
- `[DiscoverRelations] Batch ${Math.floor(b / batchSize) + 1} error: ${result.error}`
131
- );
132
- continue;
133
- }
134
- if (result.relations) {
135
- discovered += result.relations.length;
136
- results.push(...result.relations);
137
- }
138
- } catch (err) {
139
- batchErrors++;
140
- logger.warn(
141
- `[DiscoverRelations] Batch ${Math.floor(b / batchSize) + 1} threw: ${err.message}`
142
- );
143
- }
144
- }
145
-
146
- return {
147
- discovered,
148
- totalPairs: pairs.length,
149
- totalBatches: Math.ceil(pairs.length / batchSize),
150
- batchErrors,
151
- relations: results,
152
- };
67
+ const { container } = context;
68
+ const agentFactory = container.get('agentFactory');
69
+ return agentFactory.scanKnowledge({
70
+ label: 'knowledge-graph',
71
+ files: [],
72
+ task: 'relations',
73
+ });
153
74
  }
154
75
 
155
76
  /**
156
77
  * 任务: 批量 AI 补全候选语义字段
157
78
  */
158
79
  export async function taskFullEnrich(context, { status = 'pending', maxCount = 50 } = {}) {
159
- const { executeTool, container } = context;
80
+ const { invokeAgent, container } = context;
160
81
 
161
82
  const knowledgeService = container.get('knowledgeService');
162
83
 
@@ -179,7 +100,7 @@ export async function taskFullEnrich(context, { status = 'pending', maxCount = 5
179
100
  return { enriched: 0, message: 'All candidates already enriched' };
180
101
  }
181
102
 
182
- const result = await executeTool('enrich_candidate', {
103
+ const result = await invokeAgent('enrich_candidate', {
183
104
  candidateIds: needEnrich.map((c) => c.id).slice(0, 20),
184
105
  });
185
106
 
@@ -191,7 +112,7 @@ export async function taskFullEnrich(context, { status = 'pending', maxCount = 5
191
112
  * 对活跃 Recipe 逐个评分,返回低于阈值的列表
192
113
  */
193
114
  export async function taskQualityAudit(context, { threshold = 0.6, maxCount = 100 } = {}) {
194
- const { executeTool, container } = context;
115
+ const { invokeAgent, container } = context;
195
116
 
196
117
  const knowledgeService = container.get('knowledgeService');
197
118
 
@@ -208,7 +129,7 @@ export async function taskQualityAudit(context, { threshold = 0.6, maxCount = 10
208
129
  const gradeDistribution = { A: 0, B: 0, C: 0, D: 0, F: 0 };
209
130
 
210
131
  for (const recipe of recipes) {
211
- const scoreResult = await executeTool('quality_score', { recipe });
132
+ const scoreResult = await invokeAgent('quality_score', { recipe });
212
133
  if (scoreResult.grade) {
213
134
  gradeDistribution[scoreResult.grade] = (gradeDistribution[scoreResult.grade] || 0) + 1;
214
135
  }
@@ -239,14 +160,14 @@ export async function taskQualityAudit(context, { threshold = 0.6, maxCount = 10
239
160
  * 对代码运行全部 Guard 规则 + 生成修复建议
240
161
  */
241
162
  export async function taskGuardFullScan(context, { code, language, filePath } = {}) {
242
- const { executeTool, aiProvider } = context;
163
+ const { invokeAgent, aiProvider } = context;
243
164
 
244
165
  if (!code) {
245
166
  return { error: 'code is required' };
246
167
  }
247
168
 
248
169
  // Step 1: 静态检查
249
- const checkResult = await executeTool('guard_check_code', {
170
+ const checkResult = await invokeAgent('guard_check_code', {
250
171
  code,
251
172
  language: language || 'unknown',
252
173
  scope: 'project',
@@ -2,18 +2,18 @@
2
2
  * EpisodicConsolidator — Episodic → Semantic 固化引擎
3
3
  *
4
4
  * Bootstrap 完成后,将 SessionStore (Tier 2) 中的维度分析结果
5
- * 提炼为结构化记忆,固化到 ProjectSemanticMemory (Tier 3)。
5
+ * 提炼为结构化记忆,固化到 PersistentMemory (Tier 3)。
6
6
  *
7
7
  * 固化策略 (规则化,无需额外 AI 调用):
8
8
  * 1. 从每个维度的 findings 提取 fact 记忆
9
9
  * 2. 从 Tier Reflections 的 crossDimensionPatterns 提取 insight 记忆
10
10
  * 3. 从 analysisText 中提取项目级别事实 (正则匹配)
11
- * 4. 使用 ProjectSemanticMemory.consolidate() 进行去重和合并
11
+ * 4. 使用 PersistentMemory.consolidate() 进行去重和合并
12
12
  *
13
13
  * @module EpisodicConsolidator
14
14
  */
15
15
 
16
- import Logger from '../../infrastructure/logging/Logger.js';
16
+ import Logger from '../../../infrastructure/logging/Logger.js';
17
17
 
18
18
  // ──────────────────────────────────────────────────────────────
19
19
  // 正则: 从分析文本中提取陈述性知识
@@ -57,14 +57,14 @@ const INSIGHT_PATTERNS = [
57
57
  // ──────────────────────────────────────────────────────────────
58
58
 
59
59
  export class EpisodicConsolidator {
60
- /** @type {import('./ProjectSemanticMemory.js').ProjectSemanticMemory} */
60
+ /** @type {import('../memory/PersistentMemory.js').PersistentMemory} */
61
61
  #semanticMemory;
62
62
 
63
63
  /** @type {import('../../infrastructure/logging/Logger.js').default} */
64
64
  #logger;
65
65
 
66
66
  /**
67
- * @param {import('./ProjectSemanticMemory.js').ProjectSemanticMemory} semanticMemory
67
+ * @param {import('../memory/PersistentMemory.js').PersistentMemory} semanticMemory
68
68
  * @param {object} [opts]
69
69
  * @param {object} [opts.logger]
70
70
  */
@@ -74,9 +74,9 @@ export class EpisodicConsolidator {
74
74
  }
75
75
 
76
76
  /**
77
- * 执行固化: SessionStore → ProjectSemanticMemory
77
+ * 执行固化: SessionStore → PersistentMemory
78
78
  *
79
- * @param {import('./memory/SessionStore.js').SessionStore} sessionStore
79
+ * @param {import('../memory/SessionStore.js').SessionStore} sessionStore
80
80
  * @param {object} [opts]
81
81
  * @param {string} [opts.bootstrapSession] — Bootstrap session ID
82
82
  * @param {boolean} [opts.clearPrevious=false] — 是否先清除旧的 bootstrap 记忆
@@ -1,8 +1,10 @@
1
1
  /**
2
2
  * EvidenceCollector.js — 从 Analyst 工具调用中收集结构化证据
3
3
  *
4
- * HandoffProtocol v2 核心组件: 将 Analyst toolCall 序列转化为
5
- * 类型化的证据地图、探索日志和负空间信号,供 Producer 直接引用。
4
+ * Bootstrap 质量门控核心组件: 将 Analyst 阶段的 toolCall 序列转化为
5
+ * 类型化的证据地图、探索日志和负空间信号,供 Producer 阶段直接引用。
6
+ *
7
+ * 被 bootstrap-gate.js (buildAnalysisArtifact) 调用。
6
8
  *
7
9
  * 设计原则:
8
10
  * - 不保留原始工具返回值 (体积过大)
@@ -1,26 +1,25 @@
1
1
  /**
2
- * AnalystAgent.js — v3.0 分析者 Agent
2
+ * insight-analyst.js — Insight Analyst 领域函数
3
3
  *
4
- * 职责:
5
- * - 使用 AST 工具 + 文件搜索工具自由探索代码库
6
- * - 输出自然语言分析结果 (无格式约束)
7
- * - 不提交候选、不关心格式
4
+ * 从旧 AnalystAgent.js 提取的纯领域逻辑:
5
+ * - Analyst System Prompt
6
+ * - 工具白名单
7
+ * - 预算常量
8
+ * - 9 段式 Prompt 构建器
8
9
  *
9
- * 设计哲学:
10
- * "给 AI 一个任务描述和一套好工具,让它像资深工程师一样自由探索代码库。"
10
+ * 被 PipelineStrategy 的 bootstrap preset 直接引用。
11
+ * 不再包含任何 Agent 类 — Agent 由 AgentRuntime + PipelineStrategy 驱动。
11
12
  *
12
- * @module AnalystAgent
13
+ * @module insight-analyst
13
14
  */
14
15
 
15
- import Logger from '../../infrastructure/logging/Logger.js';
16
- import { analysisQualityGate, buildAnalysisReport, buildAnalysisArtifact, buildRetryPrompt } from './HandoffProtocol.js';
17
- import { getDimensionSOP } from '../../external/mcp/handlers/bootstrap/shared/dimension-sop.js';
16
+ import { getDimensionSOP } from '../../../external/mcp/handlers/bootstrap/shared/dimension-sop.js';
18
17
 
19
18
  // ──────────────────────────────────────────────────────────────────
20
19
  // System Prompt — Analyst 专用 (~100 tokens)
21
20
  // ──────────────────────────────────────────────────────────────────
22
21
 
23
- const ANALYST_SYSTEM_PROMPT = `你是一位高级软件架构师,正在深度分析一个真实项目的某个维度。
22
+ export const ANALYST_SYSTEM_PROMPT = `你是一位高级软件架构师,正在深度分析一个真实项目的某个维度。
24
23
 
25
24
  ## 执行计划
26
25
  你有 **N 轮**工具调用机会(系统会告知具体数字)。请严格按以下节奏分配:
@@ -50,7 +49,7 @@ const ANALYST_SYSTEM_PROMPT = `你是一位高级软件架构师,正在深度
50
49
  // Analyst 可用工具白名单 — 只做探索,不做提交
51
50
  // ──────────────────────────────────────────────────────────────────
52
51
 
53
- const ANALYST_TOOLS = [
52
+ export const ANALYST_TOOLS = [
54
53
  // AST 结构化分析
55
54
  'get_project_overview',
56
55
  'get_class_hierarchy',
@@ -77,30 +76,42 @@ const ANALYST_TOOLS = [
77
76
  // Analyst 预算 — 使用 analyst 策略(自由探索,无阶段约束)
78
77
  // ──────────────────────────────────────────────────────────────────
79
78
 
80
- const ANALYST_BUDGET = {
81
- maxIterations: 24, // was 18 — 大项目维度需要充足探索轮次
82
- searchBudget: 18, // was 14 — 匹配更大探索空间
83
- searchBudgetGrace: 10, // was 8
84
- maxSubmits: 0, // Analyst 不提交候选
79
+ export const ANALYST_BUDGET = {
80
+ maxIterations: 24,
81
+ searchBudget: 18,
82
+ searchBudgetGrace: 10,
83
+ maxSubmits: 0,
85
84
  softSubmitLimit: 0,
86
- idleRoundsToExit: 2, // 减少空转
85
+ idleRoundsToExit: 2,
87
86
  };
88
87
 
89
88
  // ──────────────────────────────────────────────────────────────────
90
- // 维度 Prompt 模板
89
+ // 维度 Prompt 模板 (9 段式)
91
90
  // ──────────────────────────────────────────────────────────────────
92
91
 
93
92
  /**
94
93
  * 构建 Analyst Prompt
95
- * @param {object} dimConfig — 维度配置 { id, label, guide, focusKeywords }
94
+ *
95
+ * 9 段结构:
96
+ * §1 任务描述
97
+ * §2 维度指引
98
+ * §3 SOP (分析步骤 + 常见错误)
99
+ * §4 输出要求
100
+ * §5 工具提示
101
+ * §6 前序维度上下文 (SessionStore / DimensionContext)
102
+ * §7 Tier Reflection 洞察
103
+ * §8 历史语义记忆 (Tier 3)
104
+ * §9 代码实体图谱 (Phase E)
105
+ *
106
+ * @param {object} dimConfig — 维度配置 { id, label, guide, focusKeywords, outputType }
96
107
  * @param {object} projectInfo — { name, lang, fileCount }
97
108
  * @param {object} [dimensionContext] — DimensionContext 实例 (跨维度上下文)
98
- * @param {object} [episodicMemory] — EpisodicMemory 实例 (v4.0 增强上下文)
99
- * @param {object} [semanticMemory] — ProjectSemanticMemory 实例 (v4.1 历史记忆)
109
+ * @param {object} [episodicMemory] — SessionStore 实例 (v4.0 增强上下文)
110
+ * @param {object} [semanticMemory] — PersistentMemory 实例 (v4.1 历史记忆)
100
111
  * @param {object} [codeEntityGraph] — CodeEntityGraph 实例 (Phase E 代码实体图谱)
101
112
  * @returns {string}
102
113
  */
103
- function buildAnalystPrompt(
114
+ export function buildAnalystPrompt(
104
115
  dimConfig,
105
116
  projectInfo,
106
117
  dimensionContext,
@@ -137,8 +148,6 @@ function buildAnalystPrompt(
137
148
  }
138
149
  }
139
150
  } else if (dimConfig.guide) {
140
- // 回退: 无 SOP 的维度使用 guide 作为关注要点
141
- // guide 格式如 "命名约定、注释风格、文件组织规范",按分隔符拆分为列表
142
151
  const items = dimConfig.guide.split(/[、,,/]/).map(s => s.trim()).filter(Boolean);
143
152
  if (items.length > 1) {
144
153
  parts.push(`重点关注:\n${items.map((f) => `- ${f}`).join('\n')}`);
@@ -170,8 +179,6 @@ ${depthHint}
170
179
  parts.push('使用 get_previous_evidence 工具查询前序维度对特定文件/类的分析证据,避免重复搜索。');
171
180
 
172
181
  // §6 前序维度分析摘要 (Tier 2+ 才有)
173
- // v4.0: 优先使用 EpisodicMemory (更丰富的发现 + 文件清单 + 交叉引用),
174
- // 回退到 DimensionContext (兼容)
175
182
  if (episodicMemory) {
176
183
  const emContext = episodicMemory.buildContextForDimension(
177
184
  dimConfig.id,
@@ -204,7 +211,7 @@ ${depthHint}
204
211
  }
205
212
  }
206
213
 
207
- // §8: 历史语义记忆 (Tier 3) — 上次 Bootstrap 遗留的项目级知识
214
+ // §8: 历史语义记忆 (Tier 3)
208
215
  if (semanticMemory) {
209
216
  try {
210
217
  const query = `${dimConfig.label} ${dimConfig.guide || ''} ${projectInfo.lang}`;
@@ -221,7 +228,7 @@ ${depthHint}
221
228
  }
222
229
  }
223
230
 
224
- // §9: 代码实体图谱 (Phase E) — 类/协议/Category 关系拓扑
231
+ // §9: 代码实体图谱 (Phase E)
225
232
  if (codeEntityGraph) {
226
233
  try {
227
234
  const graphCtx = codeEntityGraph.generateContextForAgent({ maxEntities: 20, maxEdges: 40 });
@@ -236,145 +243,3 @@ ${depthHint}
236
243
 
237
244
  return parts.join('\n\n');
238
245
  }
239
-
240
- // ──────────────────────────────────────────────────────────────────
241
- // AnalystAgent 类
242
- // ──────────────────────────────────────────────────────────────────
243
-
244
- export class AnalystAgent {
245
- /** @type {import('./ChatAgent.js').ChatAgent} */
246
- #chatAgent;
247
-
248
- /** @type {import('../../core/ast/ProjectGraph.js').default} */
249
- #projectGraph;
250
-
251
- /** @type {import('../../infrastructure/logging/Logger.js').default} */
252
- #logger;
253
-
254
- /** @type {number} Gate 最大重试次数 */
255
- #maxRetries;
256
-
257
- /**
258
- * @param {object} chatAgent — ChatAgent 实例
259
- * @param {object} [projectGraph] — ProjectGraph 实例
260
- * @param {object} [options]
261
- * @param {number} [options.maxRetries=1] — Gate 失败最大重试次数
262
- */
263
- constructor(chatAgent, projectGraph = null, options = {}) {
264
- this.#chatAgent = chatAgent;
265
- this.#projectGraph = projectGraph;
266
- this.#logger = Logger.getInstance();
267
- this.#maxRetries = options.maxRetries ?? 1;
268
- }
269
-
270
- /**
271
- * 分析指定维度
272
- *
273
- * @param {object} dimConfig — 维度配置 { id, label, guide, focusKeywords }
274
- * @param {object} projectInfo — { name, lang, fileCount }
275
- * @param {object} [options]
276
- * @param {string} [options.sessionId] — Bootstrap session ID
277
- * @param {object} [options.dimensionContext] — DimensionContext 实例
278
- * @returns {Promise<import('./HandoffProtocol.js').AnalysisReport>}
279
- */
280
- async analyze(dimConfig, projectInfo, options = {}) {
281
- const dimId = dimConfig.id;
282
- const prompt = buildAnalystPrompt(
283
- dimConfig,
284
- projectInfo,
285
- options.dimensionContext,
286
- options.memoryCoordinator?.getSessionStore(), // v5.0: SessionStore 提供跨维度上下文
287
- options.semanticMemory, // v4.1: ProjectSemanticMemory 历史记忆
288
- options.codeEntityGraph // Phase E: CodeEntityGraph 代码实体图谱
289
- );
290
-
291
- this.#logger.info(
292
- `[AnalystAgent] ▶ analyzing dimension "${dimId}" — prompt ${prompt.length} chars`
293
- );
294
-
295
- let retries = 0;
296
- let lastReport = null;
297
-
298
- while (retries <= this.#maxRetries) {
299
- const execPrompt =
300
- retries === 0
301
- ? prompt
302
- : `${prompt}\n\n${buildRetryPrompt(lastReport?._gateReason || 'Analysis too short')}`;
303
-
304
- try {
305
- const result = await this.#chatAgent.execute(execPrompt, {
306
- source: 'system',
307
- conversationId: options.sessionId ? `analyst-${options.sessionId}-${dimId}` : undefined,
308
- budget: ANALYST_BUDGET,
309
- systemPromptOverride: ANALYST_SYSTEM_PROMPT,
310
- allowedTools: ANALYST_TOOLS,
311
- strategy: 'analyst',
312
- temperature: 0.4,
313
- dimensionMeta: {
314
- id: dimId,
315
- outputType: 'analysis',
316
- allowedKnowledgeTypes: dimConfig.allowedKnowledgeTypes || [],
317
- },
318
- // v5.0: 统一 MemoryCoordinator
319
- memoryCoordinator: options.memoryCoordinator || undefined,
320
- });
321
-
322
- // v5.0: 当有 MemoryCoordinator 时使用 ActiveContext 的 distill 结果
323
- // 构建 AnalysisArtifact (包含 evidenceMap/findings/negativeSignals)
324
- // 使用显式 scopeId 确保并行执行安全
325
- const analystScopeId = `${dimId}:analyst`;
326
- const ac = options.memoryCoordinator?.getActiveContext(analystScopeId);
327
- const report = ac
328
- ? buildAnalysisArtifact(result, dimId, this.#projectGraph, ac)
329
- : buildAnalysisReport(result, dimId, this.#projectGraph);
330
-
331
- // 附加推理链数据(如果 ChatAgent 返回了 ReasoningTrace)
332
- if (result.reasoningTrace) {
333
- report.reasoningStats = result.reasoningTrace.getStats();
334
- report.thoughts = result.reasoningTrace.getThoughts();
335
- }
336
- if (result.reasoningQuality) {
337
- report.reasoningQuality = result.reasoningQuality;
338
- }
339
-
340
- // 质量门控 — 传入 outputType 以调整门槛
341
- const gate = analysisQualityGate(report, {
342
- outputType: dimConfig.outputType || 'analysis',
343
- });
344
- if (gate.pass) {
345
- this.#logger.info(
346
- `[AnalystAgent] ✅ dimension "${dimId}" — ${report.analysisText.length} chars, ${report.referencedFiles.length} files referenced, ${report.metadata.toolCallCount} tool calls`
347
- );
348
- return report;
349
- }
350
-
351
- this.#logger.warn(
352
- `[AnalystAgent] ⚠ Gate failed for "${dimId}": ${gate.reason} (action=${gate.action})`
353
- );
354
-
355
- if (gate.action === 'degrade') {
356
- // 直接降级 — 不重试
357
- report._gateResult = gate;
358
- return report;
359
- }
360
-
361
- // retry
362
- lastReport = report;
363
- lastReport._gateReason = gate.reason;
364
- retries++;
365
- } catch (err) {
366
- this.#logger.error(`[AnalystAgent] ❌ dimension "${dimId}" error: ${err.message}`);
367
- // 返回空 report
368
- return buildAnalysisReport({ reply: '', toolCalls: [] }, dimId, this.#projectGraph);
369
- }
370
- }
371
-
372
- // 重试耗尽 — 返回最后一次结果
373
- this.#logger.warn(`[AnalystAgent] Retries exhausted for "${dimId}" — returning last report`);
374
- return (
375
- lastReport || buildAnalysisReport({ reply: '', toolCalls: [] }, dimId, this.#projectGraph)
376
- );
377
- }
378
- }
379
-
380
- export default AnalystAgent;