autosnippet 3.2.8 → 3.2.10

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 (114) hide show
  1. package/bin/cli.js +6 -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 +23 -26
  6. package/lib/cli/SetupService.js +1 -1
  7. package/lib/cli/deploy/FileManifest.js +1 -1
  8. package/lib/core/AstAnalyzer.js +1 -1
  9. package/lib/core/discovery/index.js +2 -2
  10. package/lib/external/ai/AiProvider.js +66 -172
  11. package/lib/external/ai/providers/GoogleGeminiProvider.js +29 -5
  12. package/lib/external/mcp/handlers/bootstrap/BootstrapSession.js +1 -1
  13. package/lib/external/mcp/handlers/bootstrap/ExternalSubmissionTracker.js +3 -3
  14. package/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.js +1 -1
  15. package/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +1 -1
  16. package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-context.js +8 -8
  17. package/lib/external/mcp/handlers/bootstrap/pipeline/noAiFallback.js +1 -1
  18. package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +291 -204
  19. package/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +7 -6
  20. package/lib/external/mcp/handlers/bootstrap/shared/dimension-sop.js +1 -1
  21. package/lib/external/mcp/handlers/bootstrap-internal.js +2 -2
  22. package/lib/external/mcp/handlers/dimension-complete-external.js +6 -6
  23. package/lib/http/HttpServer.js +1 -1
  24. package/lib/http/middleware/requestLogger.js +1 -0
  25. package/lib/http/routes/ai.js +240 -35
  26. package/lib/http/routes/candidates.js +2 -3
  27. package/lib/http/routes/extract.js +13 -11
  28. package/lib/http/routes/modules.js +2 -2
  29. package/lib/http/routes/recipes.js +5 -5
  30. package/lib/http/routes/remote.js +134 -255
  31. package/lib/http/routes/violations.js +0 -54
  32. package/lib/http/utils/sse-sessions.js +1 -1
  33. package/lib/infrastructure/logging/Logger.js +5 -4
  34. package/lib/infrastructure/monitoring/PerformanceMonitor.js +3 -2
  35. package/lib/injection/ServiceContainer.js +64 -17
  36. package/lib/platform/ScreenCaptureService.js +177 -0
  37. package/lib/platform/ios/routes/spm.js +2 -2
  38. package/lib/service/agent/AgentEventBus.js +207 -0
  39. package/lib/service/agent/AgentFactory.js +535 -0
  40. package/lib/service/agent/AgentMessage.js +240 -0
  41. package/lib/service/agent/AgentRouter.js +228 -0
  42. package/lib/service/agent/AgentRuntime.js +1056 -0
  43. package/lib/service/agent/AgentState.js +217 -0
  44. package/lib/service/agent/IntentClassifier.js +331 -0
  45. package/lib/service/agent/LarkTransport.js +389 -0
  46. package/lib/service/agent/capabilities.js +409 -0
  47. package/lib/service/{chat → agent/context}/ContextWindow.js +37 -12
  48. package/lib/service/{chat → agent/context}/ExplorationTracker.js +112 -33
  49. package/lib/service/{chat → agent/core}/ChatAgentPrompts.js +5 -3
  50. package/lib/service/agent/core/LoopContext.js +170 -0
  51. package/lib/service/agent/core/MessageAdapter.js +223 -0
  52. package/lib/service/agent/core/ToolExecutionPipeline.js +376 -0
  53. package/lib/service/{chat → agent/domain}/ChatAgentTasks.js +15 -98
  54. package/lib/service/{chat → agent/domain}/EpisodicConsolidator.js +7 -7
  55. package/lib/service/{chat → agent/domain}/EvidenceCollector.js +4 -2
  56. package/lib/service/{chat/AnalystAgent.js → agent/domain/insight-analyst.js} +37 -172
  57. package/lib/service/{chat/HandoffProtocol.js → agent/domain/insight-gate.js} +85 -135
  58. package/lib/service/agent/domain/insight-producer.js +270 -0
  59. package/lib/service/agent/domain/scan-prompts.js +444 -0
  60. package/lib/service/agent/forced-summary.js +266 -0
  61. package/lib/service/agent/index.js +91 -0
  62. package/lib/service/{chat → agent}/memory/ActiveContext.js +29 -1
  63. package/lib/service/{chat → agent}/memory/MemoryCoordinator.js +7 -7
  64. package/lib/service/{chat/ProjectSemanticMemory.js → agent/memory/PersistentMemory.js} +359 -89
  65. package/lib/service/{chat → agent}/memory/SessionStore.js +1 -1
  66. package/lib/service/{chat → agent}/memory/index.js +1 -1
  67. package/lib/service/agent/policies.js +442 -0
  68. package/lib/service/agent/presets.js +305 -0
  69. package/lib/service/agent/strategies.js +756 -0
  70. package/lib/service/{chat → agent/tools}/ToolRegistry.js +3 -3
  71. package/lib/service/agent/tools/ai-analysis.js +75 -0
  72. package/lib/service/{chat → agent}/tools/composite.js +2 -1
  73. package/lib/service/{chat → agent}/tools/guard.js +1 -121
  74. package/lib/service/{chat → agent}/tools/index.js +27 -21
  75. package/lib/service/{chat → agent}/tools/infrastructure.js +1 -1
  76. package/lib/service/agent/tools/knowledge-graph.js +112 -0
  77. package/lib/service/agent/tools/scan-recipe.js +189 -0
  78. package/lib/service/agent/tools/system-interaction.js +476 -0
  79. package/lib/service/automation/DirectiveDetector.js +0 -1
  80. package/lib/service/automation/FileWatcher.js +0 -8
  81. package/lib/service/automation/handlers/CreateHandler.js +7 -3
  82. package/lib/service/automation/handlers/DraftHandler.js +7 -6
  83. package/lib/service/module/ModuleService.js +40 -73
  84. package/lib/service/skills/SignalCollector.js +26 -19
  85. package/lib/service/snippet/codecs/VSCodeCodec.js +1 -1
  86. package/lib/shared/FieldSpec.js +1 -1
  87. package/lib/shared/StyleGuide.js +1 -1
  88. package/package.json +4 -1
  89. package/resources/native-ui/screenshot.swift +228 -0
  90. package/dashboard/dist/assets/index-D5jiDBQG.css +0 -1
  91. package/dashboard/dist/assets/index-e5OKj-Ni.js +0 -128
  92. package/lib/core/discovery/SpmDiscoverer.js +0 -5
  93. package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +0 -750
  94. package/lib/external/mcp/handlers/bootstrap/pipeline/ToolResultCache.js +0 -277
  95. package/lib/http/routes/spm.js +0 -5
  96. package/lib/infrastructure/external/XcodeAutomation.js +0 -15
  97. package/lib/service/chat/ChatAgent.js +0 -1602
  98. package/lib/service/chat/Memory.js +0 -161
  99. package/lib/service/chat/ProducerAgent.js +0 -431
  100. package/lib/service/chat/ReasoningTrace.js +0 -523
  101. package/lib/service/chat/TaskPipeline.js +0 -357
  102. package/lib/service/chat/WorkingMemory.js +0 -359
  103. package/lib/service/chat/memory/PersistentMemory.js +0 -450
  104. package/lib/service/chat/tools/ai-analysis.js +0 -267
  105. package/lib/service/chat/tools/knowledge-graph.js +0 -234
  106. package/lib/service/chat/tools.js +0 -18
  107. package/lib/service/snippet/PlaceholderConverter.js +0 -5
  108. package/lib/service/snippet/codecs/XcodeCodec.js +0 -5
  109. /package/lib/service/{chat → agent}/ConversationStore.js +0 -0
  110. /package/lib/service/{chat → agent}/tools/_shared.js +0 -0
  111. /package/lib/service/{chat → agent}/tools/ast-graph.js +0 -0
  112. /package/lib/service/{chat → agent}/tools/lifecycle.js +0 -0
  113. /package/lib/service/{chat → agent}/tools/project-access.js +0 -0
  114. /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,19 @@ ${highSim.map((s) => `- ${s.title} (相似度: ${s.similarity})`).join('\n')}
61
61
 
62
62
  /**
63
63
  * 任务: 批量发现 Recipe 间的知识图谱关系
64
- * 遍历所有 Recipe,两两分析可能的关系
64
+ * 委托给 AgentFactory.discoverRelations (独立 Explore → Synthesize 管线)
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.discoverRelations({ batchSize });
153
70
  }
154
71
 
155
72
  /**
156
73
  * 任务: 批量 AI 补全候选语义字段
157
74
  */
158
75
  export async function taskFullEnrich(context, { status = 'pending', maxCount = 50 } = {}) {
159
- const { executeTool, container } = context;
76
+ const { invokeAgent, container } = context;
160
77
 
161
78
  const knowledgeService = container.get('knowledgeService');
162
79
 
@@ -179,7 +96,7 @@ export async function taskFullEnrich(context, { status = 'pending', maxCount = 5
179
96
  return { enriched: 0, message: 'All candidates already enriched' };
180
97
  }
181
98
 
182
- const result = await executeTool('enrich_candidate', {
99
+ const result = await invokeAgent('enrich_candidate', {
183
100
  candidateIds: needEnrich.map((c) => c.id).slice(0, 20),
184
101
  });
185
102
 
@@ -191,7 +108,7 @@ export async function taskFullEnrich(context, { status = 'pending', maxCount = 5
191
108
  * 对活跃 Recipe 逐个评分,返回低于阈值的列表
192
109
  */
193
110
  export async function taskQualityAudit(context, { threshold = 0.6, maxCount = 100 } = {}) {
194
- const { executeTool, container } = context;
111
+ const { invokeAgent, container } = context;
195
112
 
196
113
  const knowledgeService = container.get('knowledgeService');
197
114
 
@@ -208,7 +125,7 @@ export async function taskQualityAudit(context, { threshold = 0.6, maxCount = 10
208
125
  const gradeDistribution = { A: 0, B: 0, C: 0, D: 0, F: 0 };
209
126
 
210
127
  for (const recipe of recipes) {
211
- const scoreResult = await executeTool('quality_score', { recipe });
128
+ const scoreResult = await invokeAgent('quality_score', { recipe });
212
129
  if (scoreResult.grade) {
213
130
  gradeDistribution[scoreResult.grade] = (gradeDistribution[scoreResult.grade] || 0) + 1;
214
131
  }
@@ -239,14 +156,14 @@ export async function taskQualityAudit(context, { threshold = 0.6, maxCount = 10
239
156
  * 对代码运行全部 Guard 规则 + 生成修复建议
240
157
  */
241
158
  export async function taskGuardFullScan(context, { code, language, filePath } = {}) {
242
- const { executeTool, aiProvider } = context;
159
+ const { invokeAgent, aiProvider } = context;
243
160
 
244
161
  if (!code) {
245
162
  return { error: 'code is required' };
246
163
  }
247
164
 
248
165
  // Step 1: 静态检查
249
- const checkResult = await executeTool('guard_check_code', {
166
+ const checkResult = await invokeAgent('guard_check_code', {
250
167
  code,
251
168
  language: language || 'unknown',
252
169
  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;