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
@@ -0,0 +1,270 @@
1
+ /**
2
+ * insight-producer.js — Insight Producer 领域函数
3
+ *
4
+ * 从旧 ProducerAgent.js 提取的纯领域逻辑:
5
+ * - Producer System Prompt
6
+ * - 工具白名单
7
+ * - 预算常量
8
+ * - Prompt 构建器 (v1 + v2)
9
+ * - 代码上下文注入 (evidenceMap → prompt section)
10
+ * - 拒绝率门控 (producerRejectionGateEvaluator)
11
+ *
12
+ * 被 PipelineStrategy 的 bootstrap preset 直接引用。
13
+ * 不再包含任何 Agent 类 — Agent 由 AgentRuntime + PipelineStrategy 驱动。
14
+ *
15
+ * @module insight-producer
16
+ */
17
+
18
+ import { buildProducerStyleGuide, SUBMIT_REQUIREMENTS } from '../../../shared/StyleGuide.js';
19
+
20
+ // ──────────────────────────────────────────────────────────────────
21
+ // System Prompt — Producer 专用 (~150 tokens)
22
+ // ──────────────────────────────────────────────────────────────────
23
+
24
+ export const PRODUCER_SYSTEM_PROMPT = `你是知识管理专家。你会收到一段代码分析文本,需要将其中的知识点转化为结构化的知识候选。
25
+
26
+ 核心原则: 分析文本已经包含了所有发现,你的唯一工作是将它们格式化为 submit_knowledge 调用。
27
+
28
+ 每个候选必须:
29
+ 1. 有清晰的标题 (描述知识点的核心,使用项目真实类名)
30
+ 2. 有项目特写风格的正文 (content.markdown 字段,结合代码展示)
31
+ 3. 标注相关文件路径
32
+ 4. 选择正确的 kind (rule/pattern/fact)
33
+ 5. 提供完整的 Cursor 交付字段 (trigger, doClause, whenClause 等)
34
+
35
+ 工作流程:
36
+ 1. 阅读分析文本,识别每个独立的知识点/发现
37
+ 2. 用 read_project_file 批量获取关键代码片段:
38
+ read_project_file({ filePaths: ["FileA.m", "FileB.m"], maxLines: 80 })
39
+ 3. 立刻调用 submit_knowledge 提交
40
+ 4. 重复直到分析中的所有知识点都已提交
41
+
42
+ 关键规则:
43
+ - 分析中的每个要点/段落都应转化为至少一个候选
44
+ - read_project_file 支持 filePaths 数组批量读取多个文件,一次调用完成
45
+ - read_project_file 时读取足够多的行数(startLine + maxLines 至少 30 行)
46
+ - reasoning.sources 必须是非空数组,填写相关文件路径如 ["FileName.m"]
47
+ - 如果分析提到了 3 个模式,就应该提交 3 个候选,不要合并
48
+ - 禁止: 不要搜索新文件、不要做额外分析,专注于格式化和提交
49
+
50
+ 容错规则:
51
+ - 如果 read_project_file 返回"文件不存在"或错误,不要重试同一文件的其他路径变体
52
+ - 文件读取失败时,直接使用分析文本中已有的代码和描述来提交候选
53
+ - 永远不要因为文件读取失败而跳过知识点 — 分析文本已经包含足够信息
54
+ - 先提交候选,再考虑是否需要读取更多代码(提交优先于验证)`;
55
+
56
+ // ──────────────────────────────────────────────────────────────────
57
+ // Producer 可用工具白名单 — 只做格式化和提交
58
+ // ──────────────────────────────────────────────────────────────────
59
+
60
+ export const PRODUCER_TOOLS = ['submit_knowledge', 'submit_with_check', 'read_project_file'];
61
+
62
+ // ──────────────────────────────────────────────────────────────────
63
+ // Producer 预算
64
+ // ──────────────────────────────────────────────────────────────────
65
+
66
+ export const PRODUCER_BUDGET = {
67
+ maxIterations: 24,
68
+ searchBudget: 4,
69
+ searchBudgetGrace: 3,
70
+ maxSubmits: 10,
71
+ softSubmitLimit: 10,
72
+ idleRoundsToExit: 3,
73
+ };
74
+
75
+ // ──────────────────────────────────────────────────────────────────
76
+ // 项目特写风格指南 (从共享 StyleGuide.js 获取)
77
+ // ──────────────────────────────────────────────────────────────────
78
+
79
+ const STYLE_GUIDE = buildProducerStyleGuide();
80
+
81
+ // ──────────────────────────────────────────────────────────────────
82
+ // Prompt 构建
83
+ // ──────────────────────────────────────────────────────────────────
84
+
85
+ /**
86
+ * 构建 Producer Prompt (v1 — 用于 AnalysisReport)
87
+ *
88
+ * @param {import('./bootstrap-gate.js').AnalysisReport} analysisReport
89
+ * @param {object} dimConfig — { id, label, allowedKnowledgeTypes, outputType }
90
+ * @param {object} projectInfo — { name }
91
+ * @returns {string}
92
+ */
93
+ export function buildProducerPrompt(analysisReport, dimConfig, projectInfo) {
94
+ const parts = [];
95
+
96
+ parts.push(`将以下对 ${projectInfo.name} 项目 "${dimConfig.label}" 维度的分析,转化为知识候选:`);
97
+ parts.push(`---\n${analysisReport.analysisText}\n---`);
98
+
99
+ if (analysisReport.referencedFiles.length > 0) {
100
+ parts.push(`分析中引用的关键文件: ${analysisReport.referencedFiles.join(', ')}`);
101
+ }
102
+
103
+ parts.push(`维度约束:
104
+ - dimensionId: ${dimConfig.id}
105
+ - 允许的 knowledgeType: ${(dimConfig.allowedKnowledgeTypes || []).join(', ') || '(all)'}
106
+ - category: ${dimConfig.id}`);
107
+
108
+ parts.push(STYLE_GUIDE);
109
+ parts.push(SUBMIT_REQUIREMENTS);
110
+
111
+ return parts.join('\n\n');
112
+ }
113
+
114
+ /**
115
+ * 构建 Producer Prompt v2 — 用于 AnalysisArtifact
116
+ *
117
+ * 相比 v1 增加:
118
+ * - §3 结构化发现 (findings)
119
+ * - §4 代码证据 (evidenceMap → code context)
120
+ * - §5 负空间信号
121
+ *
122
+ * @param {import('./bootstrap-gate.js').AnalysisArtifact} artifact
123
+ * @param {object} dimConfig
124
+ * @param {object} projectInfo
125
+ * @returns {string}
126
+ */
127
+ export function buildProducerPromptV2(artifact, dimConfig, projectInfo) {
128
+ const parts = [];
129
+
130
+ parts.push(`将以下对 ${projectInfo.name} 项目 "${dimConfig.label}" 维度的分析,转化为知识候选:`);
131
+ parts.push(`---\n${artifact.analysisText}\n---`);
132
+
133
+ // §3 结构化发现
134
+ if (artifact.findings?.length > 0) {
135
+ const findingLines = ['## 关键发现 (Analyst 已确认)'];
136
+ const sorted = [...artifact.findings].sort((a, b) => b.importance - a.importance);
137
+ for (const f of sorted) {
138
+ const badge = f.importance >= 8 ? '⚠️' : '📋';
139
+ findingLines.push(`${badge} **[${f.importance}/10]** ${f.finding}`);
140
+ if (f.evidence) {
141
+ findingLines.push(` 证据: ${f.evidence}`);
142
+ }
143
+ }
144
+ findingLines.push('');
145
+ findingLines.push('☝️ 上述每个发现都应至少转化为一个候选。');
146
+ parts.push(findingLines.join('\n'));
147
+ }
148
+
149
+ // §4 代码证据
150
+ const codeContext = buildCodeContextSection(artifact.evidenceMap);
151
+ if (codeContext) {
152
+ parts.push(codeContext);
153
+ }
154
+
155
+ // §5 负空间信号
156
+ if (artifact.negativeSignals?.length > 0) {
157
+ const nsLines = ['## ⛔ 不存在的模式 (不要猜测)'];
158
+ for (const ns of artifact.negativeSignals.slice(0, 5)) {
159
+ nsLines.push(`- "${ns.searchPattern}" — ${ns.implication}`);
160
+ }
161
+ parts.push(nsLines.join('\n'));
162
+ }
163
+
164
+ // §6 引用文件
165
+ if (artifact.referencedFiles.length > 0) {
166
+ parts.push(`分析中引用的关键文件: ${artifact.referencedFiles.slice(0, 15).join(', ')}`);
167
+ }
168
+
169
+ // §7 维度约束
170
+ parts.push(`维度约束:
171
+ - dimensionId: ${dimConfig.id}
172
+ - 允许的 knowledgeType: ${(dimConfig.allowedKnowledgeTypes || []).join(', ') || '(all)'}
173
+ - category: ${dimConfig.id}`);
174
+
175
+ // §8 写作指南 + 提交要求
176
+ parts.push(STYLE_GUIDE);
177
+ parts.push(SUBMIT_REQUIREMENTS);
178
+
179
+ return parts.join('\n\n');
180
+ }
181
+
182
+ // ──────────────────────────────────────────────────────────────────
183
+ // 代码上下文注入 (Producer v2 辅助)
184
+ // ──────────────────────────────────────────────────────────────────
185
+
186
+ /**
187
+ * 从 evidenceMap 构建代码上下文段
188
+ *
189
+ * 策略: 按代码片段数量排序
190
+ * 预算: ≤ 4000 chars (~1000 tokens)
191
+ *
192
+ * @param {Map<string, import('./EvidenceCollector.js').EvidenceEntry>} evidenceMap
193
+ * @returns {string|null}
194
+ */
195
+ export function buildCodeContextSection(evidenceMap) {
196
+ if (!evidenceMap || evidenceMap.size === 0) return null;
197
+
198
+ const parts = ['## 📄 Analyst 已读取的代码 (直接引用, 无需 read_file)'];
199
+ let totalChars = 0;
200
+ const BUDGET = 4000;
201
+
202
+ const sortedEntries = [...evidenceMap.values()]
203
+ .filter((e) => e.codeSnippets.length > 0)
204
+ .sort((a, b) => b.codeSnippets.length - a.codeSnippets.length);
205
+
206
+ for (const entry of sortedEntries) {
207
+ if (totalChars >= BUDGET) break;
208
+
209
+ const header = `### ${entry.filePath}${entry.role ? ` (${entry.role})` : ''}`;
210
+ parts.push(header);
211
+ totalChars += header.length;
212
+
213
+ if (entry.summary) {
214
+ parts.push(entry.summary);
215
+ totalChars += entry.summary.length;
216
+ }
217
+
218
+ for (const snippet of entry.codeSnippets.slice(0, 2)) {
219
+ if (totalChars >= BUDGET) break;
220
+ const codeBlock = `\`\`\`\n// L${snippet.startLine}-${snippet.endLine}\n${snippet.content}\n\`\`\``;
221
+ if (snippet.analystNote) {
222
+ parts.push(`> ${snippet.analystNote}`);
223
+ totalChars += snippet.analystNote.length + 4;
224
+ }
225
+ parts.push(codeBlock);
226
+ totalChars += codeBlock.length;
227
+ }
228
+ }
229
+
230
+ return parts.length > 1 ? parts.join('\n') : null;
231
+ }
232
+
233
+ // ──────────────────────────────────────────────────────────────────
234
+ // PipelineStrategy gate.evaluator — 拒绝率门控
235
+ // ──────────────────────────────────────────────────────────────────
236
+
237
+ /**
238
+ * Producer 拒绝率门控 — 面向 PipelineStrategy gate.evaluator
239
+ *
240
+ * 当 produce 阶段的提交拒绝率过高时触发 retry。
241
+ *
242
+ * @param {object} source — produce 阶段的 reactLoop 返回值
243
+ * @param {object} _phaseResults
244
+ * @param {object} _strategyContext
245
+ * @returns {{ action: 'pass'|'retry', reason: string }}
246
+ */
247
+ export function producerRejectionGateEvaluator(source, _phaseResults, _strategyContext = {}) {
248
+ if (!source?.toolCalls) {
249
+ return { action: 'pass', reason: '' };
250
+ }
251
+
252
+ // 可配置的提交工具名 — bootstrap 用 submit_knowledge/submit_with_check,scan 用 collect_scan_recipe
253
+ const submitToolNames = _strategyContext.submitToolNames
254
+ || ['submit_knowledge', 'submit_with_check'];
255
+ const submitCalls = (source.toolCalls || []).filter(tc =>
256
+ submitToolNames.includes(tc.tool || tc.name),
257
+ );
258
+ const rejected = submitCalls.filter(tc => {
259
+ const res = tc.result;
260
+ if (!res) return false;
261
+ if (typeof res === 'string') return res.includes('rejected') || res.includes('error');
262
+ return res.status === 'rejected' || res.status === 'error' || res.reason === 'validation_failed';
263
+ }).length;
264
+ const success = submitCalls.length - rejected;
265
+
266
+ if (rejected > success && rejected >= 2) {
267
+ return { action: 'retry', reason: `${rejected} rejections vs ${success} successes` };
268
+ }
269
+ return { action: 'pass', reason: '' };
270
+ }