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.
- package/README.md +2 -4
- package/bin/cli.js +164 -145
- package/config/constitution.yaml +3 -0
- package/dashboard/dist/assets/{index-DNOHYBhy.css → index-BaGY7kJI.css} +1 -1
- package/dashboard/dist/assets/{index-6itPuGFl.js → index-DfHY_3ln.js} +25 -25
- package/dashboard/dist/index.html +2 -2
- package/lib/cli/CliLogger.js +78 -0
- package/lib/cli/SetupService.js +9 -719
- package/lib/cli/UpgradeService.js +23 -398
- package/lib/cli/deploy/FileDeployer.js +562 -0
- package/lib/cli/deploy/FileManifest.js +272 -0
- package/lib/external/mcp/McpServer.js +22 -26
- package/lib/external/mcp/autoApproveInjector.js +1 -0
- package/lib/external/mcp/handlers/bootstrap/BootstrapSession.js +5 -5
- package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +25 -3
- package/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +6 -6
- package/lib/external/mcp/handlers/bootstrap/pipeline/ToolResultCache.js +4 -0
- package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-configs.js +5 -5
- package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +89 -44
- package/lib/external/mcp/handlers/consolidated.js +8 -9
- package/lib/external/mcp/handlers/dimension-complete-external.js +4 -4
- package/lib/external/mcp/handlers/guard.js +283 -5
- package/lib/external/mcp/handlers/task.js +183 -9
- package/lib/external/mcp/tools.js +32 -81
- package/lib/http/routes/task.js +55 -0
- package/lib/service/chat/AnalystAgent.js +12 -12
- package/lib/service/chat/ChatAgent.js +227 -545
- package/lib/service/chat/ChatAgentPrompts.js +9 -11
- package/lib/service/chat/ContextWindow.js +2 -296
- package/lib/service/chat/EpisodicConsolidator.js +15 -15
- package/lib/service/chat/ExplorationTracker.js +1262 -0
- package/lib/service/chat/HandoffProtocol.js +8 -9
- package/lib/service/chat/Memory.js +4 -0
- package/lib/service/chat/ProducerAgent.js +9 -6
- package/lib/service/chat/ProjectSemanticMemory.js +4 -0
- package/lib/service/chat/ReasoningTrace.js +182 -0
- package/lib/service/chat/WorkingMemory.js +4 -0
- package/lib/service/chat/memory/ActiveContext.js +910 -0
- package/lib/service/chat/memory/MemoryCoordinator.js +662 -0
- package/lib/service/chat/memory/PersistentMemory.js +450 -0
- package/lib/service/chat/memory/SessionStore.js +896 -0
- package/lib/service/chat/memory/index.js +13 -0
- package/lib/service/chat/tools/ast-graph.js +17 -16
- package/lib/service/cursor/AgentInstructionsGenerator.js +75 -40
- package/lib/service/cursor/FileProtection.js +4 -1
- package/lib/service/guard/GuardCheckEngine.js +10 -3
- package/lib/service/task/TaskGraphService.js +3 -3
- package/lib/shared/LanguageService.js +2 -1
- package/package.json +1 -1
- package/skills/autosnippet-intent/SKILL.md +1 -3
- package/skills/autosnippet-recipes/SKILL.md +1 -3
- package/templates/claude-code/commands/prime.md +19 -0
- package/templates/claude-code/hooks/autosnippet-session.sh +63 -0
- package/templates/claude-code/settings.json +21 -0
- package/templates/copilot-instructions.md +66 -177
- package/templates/cursor-hooks/commands/prime.md +12 -0
- package/templates/cursor-hooks/hooks/session-start.sh +10 -0
- package/templates/cursor-hooks/hooks.json +11 -0
- package/templates/cursor-rules/autosnippet-conventions.mdc +52 -3
- package/templates/cursor-rules/autosnippet-workflow.mdc +51 -27
- package/lib/external/mcp/handlers/decide.js +0 -109
- package/lib/external/mcp/handlers/ready.js +0 -42
- package/lib/service/chat/ReasoningLayer.js +0 -888
- 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: 来自
|
|
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} [
|
|
222
|
+
* @param {object} [activeContext] — ActiveContext 实例 (提供 distill 结果)
|
|
223
223
|
* @returns {AnalysisArtifact}
|
|
224
224
|
*/
|
|
225
|
-
export function buildAnalysisArtifact(analystResult, dimensionId, projectGraph = 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: 从
|
|
239
|
-
const distilled =
|
|
238
|
+
// §3: 从 ActiveContext 获取结构化发现 (保持与 distill() 一致的规范形状)
|
|
239
|
+
const distilled = activeContext?.distill() || { keyFindings: [], toolCallSummary: [] };
|
|
240
240
|
const findings = distilled.keyFindings.map((f) => ({
|
|
241
|
-
|
|
242
|
-
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)
|
|
@@ -143,15 +143,15 @@ function buildProducerPromptV2(artifact, dimConfig, projectInfo) {
|
|
|
143
143
|
// §2 分析内容
|
|
144
144
|
parts.push(`---\n${artifact.analysisText}\n---`);
|
|
145
145
|
|
|
146
|
-
// §3 结构化发现 (
|
|
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.
|
|
153
|
-
if (f.evidence
|
|
154
|
-
findingLines.push(` 证据: ${f.evidence
|
|
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
|
-
|
|
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
|
-
|
|
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
|
* 策略:
|