autosnippet 3.2.3 → 3.2.6

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 (64) hide show
  1. package/README.md +2 -4
  2. package/bin/cli.js +164 -145
  3. package/config/constitution.yaml +3 -0
  4. package/dashboard/dist/assets/{index-DNOHYBhy.css → index-BaGY7kJI.css} +1 -1
  5. package/dashboard/dist/assets/{index-6itPuGFl.js → index-DfHY_3ln.js} +25 -25
  6. package/dashboard/dist/index.html +2 -2
  7. package/lib/cli/CliLogger.js +78 -0
  8. package/lib/cli/SetupService.js +9 -719
  9. package/lib/cli/UpgradeService.js +23 -398
  10. package/lib/cli/deploy/FileDeployer.js +562 -0
  11. package/lib/cli/deploy/FileManifest.js +272 -0
  12. package/lib/external/mcp/McpServer.js +22 -26
  13. package/lib/external/mcp/autoApproveInjector.js +1 -0
  14. package/lib/external/mcp/handlers/bootstrap/BootstrapSession.js +5 -5
  15. package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +25 -3
  16. package/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +6 -6
  17. package/lib/external/mcp/handlers/bootstrap/pipeline/ToolResultCache.js +4 -0
  18. package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-configs.js +5 -5
  19. package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +89 -44
  20. package/lib/external/mcp/handlers/consolidated.js +8 -9
  21. package/lib/external/mcp/handlers/dimension-complete-external.js +4 -4
  22. package/lib/external/mcp/handlers/guard.js +283 -5
  23. package/lib/external/mcp/handlers/task.js +183 -9
  24. package/lib/external/mcp/tools.js +32 -81
  25. package/lib/http/routes/task.js +55 -0
  26. package/lib/service/chat/AnalystAgent.js +12 -12
  27. package/lib/service/chat/ChatAgent.js +227 -545
  28. package/lib/service/chat/ChatAgentPrompts.js +9 -11
  29. package/lib/service/chat/ContextWindow.js +2 -296
  30. package/lib/service/chat/EpisodicConsolidator.js +15 -15
  31. package/lib/service/chat/ExplorationTracker.js +1262 -0
  32. package/lib/service/chat/HandoffProtocol.js +8 -9
  33. package/lib/service/chat/Memory.js +4 -0
  34. package/lib/service/chat/ProducerAgent.js +9 -6
  35. package/lib/service/chat/ProjectSemanticMemory.js +4 -0
  36. package/lib/service/chat/ReasoningTrace.js +182 -0
  37. package/lib/service/chat/WorkingMemory.js +4 -0
  38. package/lib/service/chat/memory/ActiveContext.js +910 -0
  39. package/lib/service/chat/memory/MemoryCoordinator.js +662 -0
  40. package/lib/service/chat/memory/PersistentMemory.js +450 -0
  41. package/lib/service/chat/memory/SessionStore.js +896 -0
  42. package/lib/service/chat/memory/index.js +13 -0
  43. package/lib/service/chat/tools/ast-graph.js +17 -16
  44. package/lib/service/cursor/AgentInstructionsGenerator.js +75 -40
  45. package/lib/service/cursor/FileProtection.js +4 -1
  46. package/lib/service/guard/GuardCheckEngine.js +10 -3
  47. package/lib/service/task/TaskGraphService.js +3 -3
  48. package/lib/shared/LanguageService.js +2 -1
  49. package/package.json +1 -1
  50. package/skills/autosnippet-intent/SKILL.md +1 -3
  51. package/skills/autosnippet-recipes/SKILL.md +1 -3
  52. package/templates/claude-code/commands/prime.md +19 -0
  53. package/templates/claude-code/hooks/autosnippet-session.sh +63 -0
  54. package/templates/claude-code/settings.json +21 -0
  55. package/templates/copilot-instructions.md +66 -177
  56. package/templates/cursor-hooks/commands/prime.md +12 -0
  57. package/templates/cursor-hooks/hooks/session-start.sh +10 -0
  58. package/templates/cursor-hooks/hooks.json +11 -0
  59. package/templates/cursor-rules/autosnippet-conventions.mdc +52 -3
  60. package/templates/cursor-rules/autosnippet-workflow.mdc +51 -27
  61. package/lib/external/mcp/handlers/decide.js +0 -109
  62. package/lib/external/mcp/handlers/ready.js +0 -42
  63. package/lib/service/chat/ReasoningLayer.js +0 -888
  64. package/templates/claude-hooks.yaml +0 -19
@@ -211,7 +211,7 @@ export function buildAnalysisReport(analystResult, dimensionId, projectGraph = n
211
211
  * - evidenceMap: 文件 → 代码片段 + 摘要 (Producer 可直接引用)
212
212
  * - explorationLog: 工具调用意图 + 结果摘要序列
213
213
  * - negativeSignals: 搜索但未找到的模式 (告知 Producer 不要猜测)
214
- * - findings: 来自 WorkingMemory 的结构化发现
214
+ * - findings: 来自 ActiveContext 的结构化发现
215
215
  * - qualityReport: 多维度质量评分
216
216
  *
217
217
  * 向后兼容: 返回对象包含 v1 的所有字段 (analysisText, referencedFiles, searchQueries, classesExplored, metadata)
@@ -219,10 +219,10 @@ export function buildAnalysisReport(analystResult, dimensionId, projectGraph = n
219
219
  * @param {object} analystResult — ChatAgent.execute() 返回值
220
220
  * @param {string} dimensionId — 维度 ID
221
221
  * @param {object} [projectGraph] — ProjectGraph 实例
222
- * @param {object} [workingMemory] — WorkingMemory 实例 (提供 distill 结果)
222
+ * @param {object} [activeContext] — ActiveContext 实例 (提供 distill 结果)
223
223
  * @returns {AnalysisArtifact}
224
224
  */
225
- export function buildAnalysisArtifact(analystResult, dimensionId, projectGraph = null, workingMemory = null) {
225
+ export function buildAnalysisArtifact(analystResult, dimensionId, projectGraph = null, activeContext = null) {
226
226
  const toolCalls = analystResult.toolCalls || [];
227
227
 
228
228
  // §1: 构建 v1 报告 (复用已有逻辑获取 referencedFiles, searchQueries 等)
@@ -235,13 +235,12 @@ export function buildAnalysisArtifact(analystResult, dimensionId, projectGraph =
235
235
  }
236
236
  const evidence = collector.build();
237
237
 
238
- // §3: 从 WorkingMemory 获取结构化发现
239
- const distilled = workingMemory?.distill() || { keyFindings: [], toolCallSummary: [] };
238
+ // §3: 从 ActiveContext 获取结构化发现 (保持与 distill() 一致的规范形状)
239
+ const distilled = activeContext?.distill() || { keyFindings: [], toolCallSummary: [] };
240
240
  const findings = distilled.keyFindings.map((f) => ({
241
- claim: f.finding,
242
- evidence: f.evidence ? [f.evidence] : [],
241
+ finding: f.finding,
242
+ evidence: f.evidence || '',
243
243
  importance: f.importance,
244
- source: 'note_finding',
245
244
  }));
246
245
 
247
246
  // §4: 合并引用文件 (v1 提取 + evidenceMap 中的文件)
@@ -327,7 +326,7 @@ function buildQualityScores(analysisText, findings, evidence) {
327
326
 
328
327
  // §3: evidenceScore — 发现数量 + 有证据的发现比例
329
328
  const findingCount = findings?.length || 0;
330
- const evidencedFindings = (findings || []).filter((f) => f.evidence.length > 0).length;
329
+ const evidencedFindings = (findings || []).filter((f) => f.evidence && f.evidence.length > 0).length;
331
330
  scores.evidenceScore =
332
331
  findingCount > 0
333
332
  ? Math.min(100, (evidencedFindings / findingCount) * 60 + findingCount * 10)
@@ -1,4 +1,8 @@
1
1
  /**
2
+ * @deprecated Phase 5: 已由 PersistentMemory 取代。
3
+ * 数据可通过 `PersistentMemory.migrateFromLegacy(projectRoot)` 迁移到 SQLite。
4
+ * 新代码请使用 `import { PersistentMemory } from './memory/PersistentMemory.js'`
5
+ *
2
6
  * Memory — 跨对话轻量记忆(带 source 隔离 + 去重)
3
7
  *
4
8
  * 设计:
@@ -143,15 +143,15 @@ function buildProducerPromptV2(artifact, dimConfig, projectInfo) {
143
143
  // §2 分析内容
144
144
  parts.push(`---\n${artifact.analysisText}\n---`);
145
145
 
146
- // §3 结构化发现 (NEW — 来自 WorkingMemory note_finding)
146
+ // §3 结构化发现 (来自 ActiveContext note_finding)
147
147
  if (artifact.findings?.length > 0) {
148
148
  const findingLines = ['## 关键发现 (Analyst 已确认)'];
149
149
  const sorted = [...artifact.findings].sort((a, b) => b.importance - a.importance);
150
150
  for (const f of sorted) {
151
151
  const badge = f.importance >= 8 ? '⚠️' : '📋';
152
- findingLines.push(`${badge} **[${f.importance}/10]** ${f.claim}`);
153
- if (f.evidence.length > 0) {
154
- findingLines.push(` 证据: ${f.evidence.join(', ')}`);
152
+ findingLines.push(`${badge} **[${f.importance}/10]** ${f.finding}`);
153
+ if (f.evidence) {
154
+ findingLines.push(` 证据: ${f.evidence}`);
155
155
  }
156
156
  }
157
157
  findingLines.push('');
@@ -303,9 +303,11 @@ export class ProducerAgent {
303
303
  budget,
304
304
  systemPromptOverride: PRODUCER_SYSTEM_PROMPT,
305
305
  allowedTools: PRODUCER_TOOLS,
306
- disablePhaseRouter: true,
306
+ strategy: 'producer',
307
307
  temperature: 0.3,
308
308
  projectLanguage: projectInfo.lang,
309
+ // v5.0: 统一 MemoryCoordinator (修复 B2: Producer 获得 WM distilled context)
310
+ memoryCoordinator: options.memoryCoordinator || undefined,
309
311
  dimensionMeta: {
310
312
  id: dimId,
311
313
  outputType: dimConfig.outputType || 'candidate',
@@ -350,9 +352,10 @@ export class ProducerAgent {
350
352
  budget: { ...budget, maxIterations: 5, maxSubmits: rejectedCount },
351
353
  systemPromptOverride: PRODUCER_SYSTEM_PROMPT,
352
354
  allowedTools: PRODUCER_TOOLS,
353
- disablePhaseRouter: true,
355
+ strategy: 'producer',
354
356
  temperature: 0.3,
355
357
  projectLanguage: projectInfo.lang,
358
+ memoryCoordinator: options.memoryCoordinator || undefined,
356
359
  dimensionMeta: {
357
360
  id: dimId,
358
361
  outputType: dimConfig.outputType || 'candidate',
@@ -1,4 +1,8 @@
1
1
  /**
2
+ * @deprecated Phase 5: 已由 PersistentMemory 继承增强。
3
+ * 新代码请使用 `import { PersistentMemory } from './memory/PersistentMemory.js'`
4
+ * 本文件保留作为 PersistentMemory 的父类,暂不删除。
5
+ *
2
6
  * ProjectSemanticMemory — 项目级永久语义记忆 (Tier 3)
3
7
  *
4
8
  * 替代/增强 Memory.js 的 JSONL 存储,使用 SQLite 提供:
@@ -1,6 +1,10 @@
1
1
  /**
2
2
  * ReasoningTrace — 单次 execute() 的完整推理链记录
3
3
  *
4
+ * @deprecated Phase 3: 已合并入 ActiveContext (lib/service/chat/memory/ActiveContext.js)
5
+ * - rounds + plan + thoughts + extractAndSetPlan + buildObservationMeta 已迁入 ActiveContext
6
+ * - 本文件保留做向后兼容,新代码请使用 ActiveContext
7
+ *
4
8
  * 记录每轮 ReAct 循环的四要素:
5
9
  * Thought → AI 在执行工具前的推理文本
6
10
  * Action → 调用了什么工具、什么参数
@@ -315,6 +319,184 @@ export class ReasoningTrace {
315
319
  return [...new Set([...quoted, ...camelCase, ...acronyms])];
316
320
  }
317
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
+
318
500
  /**
319
501
  * 可序列化输出
320
502
  * @returns {object}
@@ -1,6 +1,10 @@
1
1
  /**
2
2
  * WorkingMemory — 会话级工作记忆 (Tier 1)
3
3
  *
4
+ * @deprecated Phase 3: 已合并入 ActiveContext (lib/service/chat/memory/ActiveContext.js)
5
+ * - Scratchpad + 工具压缩策略 + buildContext + distill 已迁入 ActiveContext
6
+ * - 本文件保留做向后兼容,新代码请使用 ActiveContext
7
+ *
4
8
  * 管理单次 ChatAgent.execute() 中的上下文压缩与关键发现暂存。
5
9
  *
6
10
  * 策略: