autosnippet
Version:
Extract code patterns into a knowledge base for AI coding assistants
231 lines (219 loc) • 12.6 kB
JavaScript
/**
* insight-evolver.ts — Evolution Agent 领域函数
*
* Evolution Agent 是管线中的专职进化角色:
* - 接收当前维度的**全部**现有 Recipe(不仅是衰退的)
* - 使用工具读取真实代码,验证每个 Recipe 的真实性
* - 通过**附加提案**(Proposal)驱动状态变更,不创建新 Recipe
* - 三种决策: propose_evolution / confirm_deprecation / skip_evolution
*
* 被 PipelineStrategy 的 evolution preset 引用。
* 按维度隔离:每个维度的 Evolve Stage 只处理属于该维度的 Recipe。
*
* @module insight-evolver
*/
// ──────────────────────────────────────────────────────────────────
// System Prompt
// ──────────────────────────────────────────────────────────────────
export const EVOLVER_SYSTEM_PROMPT = `你是 AutoSnippet 的 **Evolution Agent**,专职验证项目中现有知识条目(Recipe)的真实性与时效性。
## 核心职责
你通过阅读项目真实代码来验证每条 Recipe 是否仍然反映当前项目实践。
你的工作结果以**提案(Proposal)**方式附加到现有 Recipe 上,推动知识库的渐进式演化。
你**不创建新 Recipe**——那是后续 Produce 阶段的职责。
## 验证流程
对每个 Recipe 按以下步骤验证:
1. 阅读 Recipe 的核心代码片段和源文件引用,理解其描述的模式
2. 使用 \`read_project_file\` 读取源文件,验证代码是否存在且与 Recipe 描述匹配
3. 如果源文件不存在或代码不匹配,使用 \`search_project_code\` 搜索该模式是否已迁移到其他位置
4. 基于真实代码的验证结果做出决策
## 决策规则
按以下决策树判断(优先级从上到下):
| 验证结果 | 决策 | 工具 |
|---------|------|------|
| 源文件存在 + 代码匹配 Recipe 描述 | **跳过**: 仍然有效 | \`skip_evolution\` |
| 源文件存在 + 代码已变化(接口改变/重构) | **进化提案**: 附加变更证据 | \`propose_evolution\` |
| 源文件不存在 + 模式已迁移到新位置 | **进化提案**: 附加迁移证据 | \`propose_evolution\` |
| 源文件不存在 + 完全无替代 | **确认废弃**: 知识已失效 | \`confirm_deprecation\` |
| 信息不足以做出判断 | **跳过**: 交给时限机制 | \`skip_evolution\` |
## 工具说明
- \`propose_evolution\` — 为 Recipe 附加进化提案,包含代码验证证据和建议变更。提案进入观察窗口(enhance: 48h, correction: 24h),不直接修改 Recipe
- \`confirm_deprecation\` — 确认 Recipe 已过时,立即标记为 deprecated(跳过观察窗口)
- \`skip_evolution\` — 显式跳过,reason 中说明是"验证有效"还是"信息不足"
## 重要约束
- 每个 Recipe 必须有一个明确决策,不要遗漏任何一个
- \`propose_evolution\` 的 evidence 字段必须包含你读到的真实代码,不要编造
- \`propose_evolution\` 的 type 区分: enhance(模式迁移/功能扩展)vs correction(描述错误/接口变更)
- 部分 Recipe 附带系统预检提示(auditHint),仅供参考——你必须以实际读到的代码为准
- 即使预检提示说"healthy",你读代码后发现不匹配也要提交提案`;
// ──────────────────────────────────────────────────────────────────
// 工具白名单
// ──────────────────────────────────────────────────────────────────
export const EVOLVER_TOOLS = [
'read_project_file',
'search_project_code',
'propose_evolution',
'confirm_deprecation',
'skip_evolution',
];
// ──────────────────────────────────────────────────────────────────
// 预算
// ──────────────────────────────────────────────────────────────────
export const EVOLVER_BUDGET = {
maxIterations: 20,
searchBudget: 10,
searchBudgetGrace: 4,
maxSubmits: 8,
softSubmitLimit: 8,
idleRoundsToExit: 2,
};
// ──────────────────────────────────────────────────────────────────
// Prompt 构建
// ──────────────────────────────────────────────────────────────────
/**
* 构建 Evolution Agent 的用户 Prompt
*
* 按维度打包全部现有 Recipe 清单 + 可选 audit hint + 项目概览,
* 让 Agent 通过提案机制对每个 Recipe 做出进化/废弃/跳过决策。
*/
export function buildEvolverPrompt(_phaseInput, _phaseResults, strategyContext) {
const { existingRecipes, dimensionId, dimensionLabel, projectOverview } = strategyContext;
const parts = [];
// §1 任务概述
parts.push(`# 验证任务: ${dimensionLabel} [${dimensionId}]`);
parts.push(`你需要验证 **${existingRecipes.length}** 个现有 Recipe 的真实性。`);
parts.push(`项目概况: ${projectOverview.primaryLang} 语言,${projectOverview.fileCount} 个文件。`);
if (projectOverview.modules.length > 0) {
parts.push(`主要模块: ${projectOverview.modules.slice(0, 10).join(', ')}`);
}
// §2 现有 Recipe 清单
parts.push('# 现有 Recipe 清单');
parts.push('以下是需要你验证的全部 Recipe。对每一个,你需要读取源文件、验证代码、然后做出决策。');
for (let i = 0; i < existingRecipes.length; i++) {
const recipe = existingRecipes[i];
const lines = [];
lines.push(`## [${i + 1}/${existingRecipes.length}] ${recipe.title}`);
lines.push(`- **ID**: \`${recipe.id}\``);
lines.push(`- **Trigger**: \`${recipe.trigger}\``);
// 源文件引用 — 验证的起点
if (recipe.sourceRefs && recipe.sourceRefs.length > 0) {
lines.push(`- **源文件引用** (请用 \`read_project_file\` 读取验证):`);
for (const ref of recipe.sourceRefs.slice(0, 5)) {
lines.push(` - \`${ref}\``);
}
if (recipe.sourceRefs.length > 5) {
lines.push(` - ... 及其他 ${recipe.sourceRefs.length - 5} 个文件`);
}
}
else {
lines.push('- **源文件引用**: 无(需要用 `search_project_code` 搜索相关代码)');
}
// Recipe 声称的核心代码(缩略)
if (recipe.content?.coreCode) {
const truncated = recipe.content.coreCode.length > 400
? `${recipe.content.coreCode.slice(0, 400)}...`
: recipe.content.coreCode;
lines.push(`- **Recipe 声称的核心代码** (需验证是否与实际一致):`);
lines.push(`\`\`\`\n${truncated}\n\`\`\``);
}
// Recipe 的设计原理
if (recipe.content?.rationale) {
const rationale = recipe.content.rationale.length > 200
? `${recipe.content.rationale.slice(0, 200)}...`
: recipe.content.rationale;
lines.push(`- **设计原理**: ${rationale}`);
}
// 静态审计 hint(可选)
if (recipe.auditHint) {
lines.push('- **系统预检提示** ⚠️ 仅供参考,以你读到的代码为准:');
lines.push(` - 评分: ${recipe.auditHint.relevanceScore}/100 → ${recipe.auditHint.verdict}`);
const ev = recipe.auditHint.evidence;
const checks = [
`Trigger: ${ev.triggerStillMatches ? '✅' : '❌'}`,
`符号: ${(ev.symbolsAlive * 100).toFixed(0)}%`,
`依赖: ${ev.depsIntact ? '✅' : '❌'}`,
`代码文件: ${(ev.codeFilesExist * 100).toFixed(0)}%`,
];
lines.push(` - ${checks.join(' | ')}`);
if (recipe.auditHint.decayReasons.length > 0) {
lines.push(` - 预检原因: ${recipe.auditHint.decayReasons.join('; ')}`);
}
}
parts.push(lines.join('\n'));
}
// §3 验证工作流
parts.push('# 验证工作流');
parts.push('对每个 Recipe 按以下步骤执行:');
parts.push('');
parts.push('**步骤 1 — 读取源文件**');
parts.push('- 使用 `read_project_file` 读取 sourceRefs 中列出的文件');
parts.push('- 如果没有 sourceRefs,跳到步骤 2');
parts.push('');
parts.push('**步骤 2 — 搜索验证**(仅在源文件缺失或代码不匹配时)');
parts.push('- 使用 `search_project_code` 搜索 Recipe 中的类名、函数名、关键模式');
parts.push('- 确认该模式是否迁移到了新位置或已被完全移除');
parts.push('');
parts.push('**步骤 3 — 做出决策**');
parts.push('- 基于步骤 1-2 的验证结果,调用对应的决策工具');
// §4 决策指令
parts.push('# 决策指令');
parts.push('对上述每个 Recipe 做出以下三种决策之一:');
parts.push('');
parts.push('### 1. 🔄 附加进化提案 — 代码已变但知识仍有价值');
parts.push('调用 `propose_evolution`:');
parts.push('```json');
parts.push('{');
parts.push(' "recipeId": "recipe-xxx",');
parts.push(' "type": "enhance", // enhance=模式迁移/功能扩展, correction=描述错误/接口变更');
parts.push(' "description": "说明发生了什么变化",');
parts.push(' "evidence": {');
parts.push(' "sourceStatus": "modified", // exists|moved|modified|deleted');
parts.push(' "currentCode": "你读到的实际代码片段",');
parts.push(' "newLocation": "新路径(仅 moved 时)",');
parts.push(' "suggestedChanges": "{结构化 JSON — 见下方格式}"');
parts.push(' },');
parts.push(' "confidence": 0.85');
parts.push('}');
parts.push('```');
parts.push('');
parts.push('#### suggestedChanges 格式(重要!)');
parts.push('suggestedChanges 必须是一个 JSON 字符串,格式如下:');
parts.push('```json');
parts.push('{');
parts.push(' "patchVersion": 1,');
parts.push(' "changes": [');
parts.push(' {');
parts.push(' "field": "coreCode",');
parts.push(' "action": "replace",');
parts.push(' "newValue": "更新后的代码片段"');
parts.push(' },');
parts.push(' {');
parts.push(' "field": "content.markdown",');
parts.push(' "action": "replace-section",');
parts.push(' "section": "### 使用指南",');
parts.push(' "newContent": "### 使用指南\\n更新后的内容"');
parts.push(' }');
parts.push(' ],');
parts.push(' "reasoning": "源代码变更原因说明"');
parts.push('}');
parts.push('```');
parts.push('');
parts.push('可修改的字段: `coreCode`, `doClause`, `dontClause`, `whenClause`, `content.markdown`, `content.rationale`, `sourceRefs`, `headers`');
parts.push('操作类型: `replace`=全量替换, `replace-section`=替换 Markdown section, `append`=追加');
parts.push('');
parts.push('### 2. ⛔ 确认废弃 — 知识确实过时,无法挽救');
parts.push('调用 `confirm_deprecation`:');
parts.push('```json');
parts.push('{ "recipeId": "recipe-xxx", "reason": "具体废弃原因" }');
parts.push('```');
parts.push('');
parts.push('### 3. ⏭️ 跳过 — 仍然有效 或 信息不足');
parts.push('调用 `skip_evolution`:');
parts.push('```json');
parts.push('{ "recipeId": "recipe-xxx", "reason": "验证有效: 代码与描述完全匹配" }');
parts.push('```');
parts.push('或:');
parts.push('```json');
parts.push('{ "recipeId": "recipe-xxx", "reason": "信息不足: 无法确认源文件位置" }');
parts.push('```');
return parts.join('\n\n');
}