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,523 +0,0 @@
1
- /**
2
- * ReasoningTrace — 单次 execute() 的完整推理链记录
3
- *
4
- * @deprecated Phase 3: 已合并入 ActiveContext (lib/service/chat/memory/ActiveContext.js)
5
- * - rounds + plan + thoughts + extractAndSetPlan + buildObservationMeta 已迁入 ActiveContext
6
- * - 本文件保留做向后兼容,新代码请使用 ActiveContext
7
- *
8
- * 记录每轮 ReAct 循环的四要素:
9
- * Thought → AI 在执行工具前的推理文本
10
- * Action → 调用了什么工具、什么参数
11
- * Observation → 工具返回的结构化观察
12
- * Reflection → 周期性自我评估
13
- *
14
- * 设计原则:
15
- * - 纯数据收集,不影响主循环控制流
16
- * - 零 token 开销 — 不向 LLM 上下文注入额外内容
17
- * - 可序列化 — toJSON() 用于审计日志和 API 返回
18
- *
19
- * @module ReasoningTrace
20
- */
21
-
22
- /**
23
- * @typedef {Object} Round
24
- * @property {number} iteration — 轮次编号
25
- * @property {string|null} thought — AI 的推理文本
26
- * @property {Array<{tool: string, params: object}>} actions — 本轮工具调用
27
- * @property {Array<{tool: string, gotNewInfo: boolean, resultType: string, keyFacts: string[], resultSize: number}>} observations — 结构化观察
28
- * @property {string|null} reflection — 反思内容
29
- * @property {object|null} roundSummary — 轮次摘要
30
- * @property {number} startTime — 轮次开始时间
31
- * @property {number|null} endTime — 轮次结束时间
32
- */
33
-
34
- /**
35
- * @typedef {Object} PlanStep
36
- * @property {string} description — 步骤描述
37
- * @property {'pending'|'done'|'skipped'} status — 当前状态
38
- * @property {string[]} keywords — 从描述中提取的匹配关键词
39
- */
40
-
41
- /**
42
- * @typedef {Object} Plan
43
- * @property {string} text — 原始计划文本
44
- * @property {Array<PlanStep>} steps — 解析出的步骤列表
45
- * @property {number} createdAtIteration — 创建于第几轮
46
- * @property {number} lastUpdatedAtIteration — 最近更新于第几轮
47
- */
48
-
49
- export class ReasoningTrace {
50
- /** @type {Array<Round>} */
51
- #rounds = [];
52
- /** @type {Round|null} */
53
- #currentRound = null;
54
- /** @type {Plan|null} */
55
- #plan = null;
56
- /** @type {Array<Plan>} */
57
- #planHistory = [];
58
-
59
- /**
60
- * 开始新一轮推理
61
- * @param {number} iteration — 轮次编号
62
- */
63
- startRound(iteration) {
64
- if (this.#currentRound) {
65
- this.endRound(); // 安全关闭上一轮
66
- }
67
- this.#currentRound = {
68
- iteration,
69
- thought: null,
70
- actions: [],
71
- observations: [],
72
- reflection: null,
73
- roundSummary: null,
74
- startTime: Date.now(),
75
- endTime: null,
76
- };
77
- }
78
-
79
- /**
80
- * 记录 AI 的推理文本(从 aiResult.text 提取)
81
- * @param {string} text
82
- */
83
- setThought(text) {
84
- if (this.#currentRound && text) {
85
- this.#currentRound.thought = text;
86
- }
87
- }
88
-
89
- /**
90
- * 记录一次工具调用
91
- * @param {string} toolName
92
- * @param {object} params
93
- */
94
- addAction(toolName, params) {
95
- this.#currentRound?.actions.push({ tool: toolName, params });
96
- }
97
-
98
- /**
99
- * 记录一次工具结果的结构化观察
100
- * @param {string} toolName
101
- * @param {object} meta — { gotNewInfo, resultType, resultSize, keyFacts }
102
- */
103
- addObservation(toolName, meta) {
104
- this.#currentRound?.observations.push({ tool: toolName, ...meta });
105
- }
106
-
107
- /**
108
- * 记录反思内容
109
- * @param {string} text
110
- */
111
- setReflection(text) {
112
- if (this.#currentRound && text) {
113
- this.#currentRound.reflection = text;
114
- }
115
- }
116
-
117
- /**
118
- * 记录轮次摘要
119
- * @param {object} summary — { newInfoCount, totalCalls, submits, cumulativeFiles, cumulativePatterns }
120
- */
121
- setRoundSummary(summary) {
122
- if (this.#currentRound) {
123
- this.#currentRound.roundSummary = summary;
124
- }
125
- }
126
-
127
- /**
128
- * 结束当前轮次
129
- */
130
- endRound() {
131
- if (this.#currentRound) {
132
- this.#currentRound.endTime = Date.now();
133
- this.#rounds.push(this.#currentRound);
134
- this.#currentRound = null;
135
- }
136
- }
137
-
138
- // ─── 分析方法 ──────────────────────────────────────────
139
-
140
- /**
141
- * 获取所有有 Thought 的轮次
142
- * @returns {Array<{iteration: number, thought: string}>}
143
- */
144
- getThoughts() {
145
- return this.#rounds
146
- .filter((r) => r.thought)
147
- .map((r) => ({ iteration: r.iteration, thought: r.thought }));
148
- }
149
-
150
- /**
151
- * 获取最近 N 轮的紧凑摘要(用于 Reflection 注入)
152
- * @param {number} [n=3] — 回看轮数
153
- * @returns {object|null}
154
- */
155
- getRecentSummary(n = 3) {
156
- const recent = this.#rounds.slice(-n);
157
- if (recent.length === 0) {
158
- return null;
159
- }
160
-
161
- const thoughts = recent
162
- .filter((r) => r.thought)
163
- .map((r) => (r.thought.length > 100 ? `${r.thought.substring(0, 100)}…` : r.thought));
164
-
165
- const tools = recent.flatMap((r) => r.actions.map((a) => a.tool));
166
-
167
- const newInfoCount = recent.reduce(
168
- (c, r) => c + r.observations.filter((o) => o.gotNewInfo).length,
169
- 0
170
- );
171
- const totalObs = recent.reduce((c, r) => c + r.observations.length, 0);
172
-
173
- return {
174
- roundCount: recent.length,
175
- thoughts,
176
- toolCalls: tools,
177
- newInfoRatio: totalObs > 0 ? newInfoCount / totalObs : 0,
178
- lastIteration: recent[recent.length - 1].iteration,
179
- };
180
- }
181
-
182
- /**
183
- * 统计指标
184
- * @returns {object}
185
- */
186
- getStats() {
187
- return {
188
- totalRounds: this.#rounds.length,
189
- thoughtCount: this.#rounds.filter((r) => r.thought).length,
190
- totalActions: this.#rounds.reduce((c, r) => c + r.actions.length, 0),
191
- totalObservations: this.#rounds.reduce((c, r) => c + r.observations.length, 0),
192
- reflectionCount: this.#rounds.filter((r) => r.reflection).length,
193
- totalDurationMs: this.#rounds.reduce(
194
- (d, r) => d + ((r.endTime || Date.now()) - r.startTime),
195
- 0
196
- ),
197
- };
198
- }
199
-
200
- // ─── Planning 方法 ──────────────────────────────────────
201
-
202
- /**
203
- * 设置初始计划
204
- * @param {string} planText — AI 输出的计划文本
205
- * @param {number} iteration — 创建轮次
206
- */
207
- setPlan(planText, iteration) {
208
- this.#plan = {
209
- text: planText,
210
- steps: this.#parsePlanSteps(planText),
211
- createdAtIteration: iteration,
212
- lastUpdatedAtIteration: iteration,
213
- };
214
- }
215
-
216
- /**
217
- * 更新计划(replan 后调用)
218
- * @param {string} replanText — AI 输出的新计划文本
219
- * @param {number} iteration — 更新轮次
220
- */
221
- updatePlan(replanText, iteration) {
222
- if (!this.#plan) {
223
- this.setPlan(replanText, iteration);
224
- return;
225
- }
226
- this.#planHistory.push({ ...this.#plan, steps: this.#plan.steps.map((s) => ({ ...s })) });
227
- this.#plan.text = replanText;
228
- this.#plan.steps = this.#parsePlanSteps(replanText);
229
- this.#plan.lastUpdatedAtIteration = iteration;
230
- }
231
-
232
- /**
233
- * 获取当前计划(只读副本)
234
- * @returns {Plan|null}
235
- */
236
- getPlan() {
237
- if (!this.#plan) {
238
- return null;
239
- }
240
- return {
241
- ...this.#plan,
242
- steps: this.#plan.steps.map((s) => ({ ...s })),
243
- };
244
- }
245
-
246
- /**
247
- * 获取计划步骤的可变引用(内部用于匹配更新状态)
248
- * @returns {Array<PlanStep>}
249
- */
250
- getPlanStepsMutable() {
251
- return this.#plan?.steps || [];
252
- }
253
-
254
- /**
255
- * 获取计划历史
256
- * @returns {Array<Plan>}
257
- */
258
- getPlanHistory() {
259
- return this.#planHistory.map((p) => ({ ...p, steps: p.steps.map((s) => ({ ...s })) }));
260
- }
261
-
262
- /**
263
- * 获取当前轮次的 actions (供 Planning 匹配使用)
264
- * @returns {Array<{tool: string, params: object}>}
265
- */
266
- getCurrentRoundActions() {
267
- return this.#currentRound?.actions || [];
268
- }
269
-
270
- /**
271
- * 获取当前轮次的 iteration 编号
272
- * @returns {number|null}
273
- */
274
- getCurrentIteration() {
275
- return this.#currentRound?.iteration || null;
276
- }
277
-
278
- // ─── 私有: Plan 解析 ──────────────────────────────────
279
-
280
- /**
281
- * 从 AI 文本中解析计划步骤(编号列表提取)
282
- * @param {string} text
283
- * @returns {Array<PlanStep>}
284
- * @private
285
- */
286
- #parsePlanSteps(text) {
287
- if (!text) {
288
- return [];
289
- }
290
- const lines = text.split('\n');
291
- const steps = [];
292
- for (const line of lines) {
293
- // 匹配: 1. xxx / - xxx / * xxx / 1) xxx
294
- const m = line.match(/^\s*(?:\d+[.)]\s*|[-*]\s+)(.+)/);
295
- if (m && m[1].trim().length > 5) {
296
- steps.push({
297
- description: m[1].trim(),
298
- status: 'pending',
299
- keywords: this.#extractKeywords(m[1]),
300
- });
301
- }
302
- }
303
- return steps;
304
- }
305
-
306
- /**
307
- * 从步骤描述中提取关键词(用于模糊匹配工具调用)
308
- * @param {string} text
309
- * @returns {string[]}
310
- * @private
311
- */
312
- #extractKeywords(text) {
313
- // 提取反引号/引号内的标识符
314
- const quoted = [...text.matchAll(/[`"']([A-Za-z_]\w{2,})[`"']/g)].map((m) => m[1]);
315
- // 提取 CamelCase 词
316
- const camelCase = [...text.matchAll(/\b([A-Z][a-z]+(?:[A-Z][a-z]+)+)\b/g)].map((m) => m[0]);
317
- // 提取全大写缩写 (如 API, HTTP, URL)
318
- const acronyms = [...text.matchAll(/\b([A-Z]{2,}[a-z]\w+)\b/g)].map((m) => m[0]);
319
- return [...new Set([...quoted, ...camelCase, ...acronyms])];
320
- }
321
-
322
- // ─── 从 ReasoningLayer 迁入的方法 ─────────────────────
323
-
324
- /**
325
- * 从 AI 响应文本中提取计划,自动调用 setPlan/updatePlan
326
- * (合并了 ReasoningLayer.afterAICall 中 plan 提取逻辑)
327
- *
328
- * @param {string} text — AI 完整响应文本
329
- * @param {number} iteration — 当前轮次
330
- * @returns {boolean} — 是否成功提取到计划
331
- */
332
- extractAndSetPlan(text, iteration) {
333
- const planText = this.#extractPlanFromText(text);
334
- if (!planText) return false;
335
-
336
- if (this.#plan) {
337
- this.updatePlan(planText, iteration);
338
- } else {
339
- this.setPlan(planText, iteration);
340
- }
341
- return true;
342
- }
343
-
344
- /**
345
- * 从 AI 响应文本中提取"计划"部分(从 ReasoningLayer 迁入)
346
- *
347
- * 策略:
348
- * 1. 查找"计划/plan/步骤"标记后的编号列表
349
- * 2. 如果没有明确标记,提取文本前部分的编号列表
350
- *
351
- * @param {string} text — AI 完整响应文本
352
- * @returns {string|null}
353
- * @private
354
- */
355
- #extractPlanFromText(text) {
356
- if (!text || text.length < 30) return null;
357
-
358
- const searchArea = text.substring(0, 2000);
359
-
360
- // 策略 1: 查找"计划"标记
361
- const planMarkers = [
362
- /(?:探索|分析)?计划[::\s]/i,
363
- /(?:my\s+)?plan[::\s]/i,
364
- /步骤[::\s]/i,
365
- /以下是.*(?:计划|步骤)/i,
366
- ];
367
-
368
- let planStart = -1;
369
- for (const marker of planMarkers) {
370
- const match = searchArea.match(marker);
371
- if (match) {
372
- planStart = match.index + match[0].length;
373
- break;
374
- }
375
- }
376
-
377
- // 策略 2: 如果没有标记,查找第一个编号列表
378
- if (planStart === -1) {
379
- const listMatch = searchArea.match(/\n\s*1[.)]\s+/);
380
- if (listMatch) {
381
- planStart = listMatch.index;
382
- }
383
- }
384
-
385
- if (planStart === -1) return null;
386
-
387
- const remaining = searchArea.substring(planStart);
388
- const lines = remaining.split('\n');
389
- const planLines = [];
390
- let inList = false;
391
-
392
- for (const line of lines) {
393
- if (/^\s*(?:\d+[.)]\s+|[-*]\s+)/.test(line)) {
394
- inList = true;
395
- planLines.push(line);
396
- } else if (inList && line.trim() === '') {
397
- break;
398
- } else if (inList) {
399
- break;
400
- }
401
- }
402
-
403
- return planLines.length >= 2 ? planLines.join('\n').trim() : null;
404
- }
405
-
406
- /**
407
- * 从工具执行结果构建结构化观察元数据(从 ReasoningLayer 迁入)
408
- *
409
- * 不改变工具结果传给 AI 的内容,只影响 ReasoningTrace 记录
410
- *
411
- * @param {string} toolName
412
- * @param {object} args
413
- * @param {*} result
414
- * @param {boolean} isNew — 由 ExplorationTracker.recordToolCall 提供
415
- * @returns {{ gotNewInfo: boolean, resultType: string, keyFacts: string[], resultSize: number }}
416
- */
417
- static buildObservationMeta(toolName, args, result, isNew) {
418
- const meta = {
419
- gotNewInfo: isNew,
420
- resultType: 'unknown',
421
- keyFacts: [],
422
- resultSize: 0,
423
- };
424
-
425
- const resultStr = typeof result === 'string' ? result : JSON.stringify(result || '');
426
- meta.resultSize = resultStr.length;
427
-
428
- switch (toolName) {
429
- case 'search_project_code': {
430
- meta.resultType = 'search';
431
- const matches = result?.matches || [];
432
- const batchResults = result?.batchResults;
433
- const totalMatches = batchResults
434
- ? Object.values(batchResults).reduce((s, br) => s + (br.matches?.length || 0), 0)
435
- : matches.length;
436
- meta.keyFacts.push(`${totalMatches} matches found`);
437
- if (isNew) meta.keyFacts.push('new files discovered');
438
- break;
439
- }
440
-
441
- case 'read_project_file': {
442
- meta.resultType = 'file_content';
443
- const fp = args?.filePath || '';
444
- const fps = args?.filePaths || [];
445
- const allPaths = fp ? [fp, ...fps] : fps;
446
- meta.keyFacts.push(`read ${allPaths.length} file(s)`);
447
- break;
448
- }
449
-
450
- case 'submit_knowledge':
451
- case 'submit_with_check': {
452
- meta.resultType = 'submit';
453
- meta.gotNewInfo = true; // submit 本身就是进展
454
- const status = typeof result === 'object' ? result?.status || 'ok' : 'ok';
455
- const title = args?.title || '(untitled)';
456
- meta.keyFacts.push(`submit "${title}": ${status}`);
457
- break;
458
- }
459
-
460
- case 'list_project_structure': {
461
- meta.resultType = 'structure';
462
- meta.keyFacts.push(`list ${args?.directory || '/'}`);
463
- break;
464
- }
465
-
466
- case 'get_class_info':
467
- case 'get_class_hierarchy':
468
- case 'get_protocol_info':
469
- case 'get_method_overrides':
470
- case 'get_category_map': {
471
- meta.resultType = 'ast_query';
472
- const target = args?.className || args?.protocolName || args?.name || '';
473
- meta.keyFacts.push(`${toolName}(${target})`);
474
- break;
475
- }
476
-
477
- case 'get_project_overview': {
478
- meta.resultType = 'overview';
479
- meta.keyFacts.push('project overview');
480
- break;
481
- }
482
-
483
- case 'semantic_search_code':
484
- case 'get_file_summary':
485
- case 'get_previous_analysis': {
486
- meta.resultType = 'query';
487
- meta.keyFacts.push(toolName);
488
- break;
489
- }
490
-
491
- default: {
492
- meta.resultType = 'other';
493
- meta.keyFacts.push(toolName);
494
- }
495
- }
496
-
497
- return meta;
498
- }
499
-
500
- /**
501
- * 可序列化输出
502
- * @returns {object}
503
- */
504
- toJSON() {
505
- return {
506
- rounds: this.#rounds.map((r) => ({ ...r })),
507
- stats: this.getStats(),
508
- ...(this.#plan
509
- ? {
510
- plan: {
511
- text: this.#plan.text,
512
- steps: this.#plan.steps.map((s) => ({ ...s })),
513
- createdAtIteration: this.#plan.createdAtIteration,
514
- lastUpdatedAtIteration: this.#plan.lastUpdatedAtIteration,
515
- },
516
- planHistory: this.#planHistory.length,
517
- }
518
- : {}),
519
- };
520
- }
521
- }
522
-
523
- export default ReasoningTrace;