oh-my-pi 提交智能体逐文件分析提示词全解:analyze-file.md 的模板设计、并行调度与结构化输出
【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi
导读
本文聚焦 oh-my-pi 代码库中 agentic(智能体驱动)提交工作流的核心提示词模板 analyze-file.md。当一次改动涉及的 diff 过大或语义不清晰时,提交智能体会以该模板为任务书,为每个文件并行派发独立的 sonic 子代理,返回结构化的 JSON 分析(summary / highlights / risks),为最终生成符合 Conventional Commits 规范的提交信息提供证据。读完本文,你将掌握该模板的占位符渲染机制、JSON 输出契约、相关文件上下文的拼接策略,以及它如何与git_overview、git_file_diff、propose_commit等工具共同构成一条完整的提交生成流水线。
一、模板全貌:一份 22 行的“文件分析任务书”
完整内容见 analyze-file.md,其原始文本如下({{...}}为 Handlebars 风格占位符):
Analyze {{file}}. Goal: {{#if goal}} {{goal}} {{else}} Summarize purpose and commit-relevant changes. {{/if}} Return concise JSON object: - summary: 1-sentence file-role description - highlights: 2-5 bullets, notable behaviors or changes - risks: edge cases or risks worth noting; [] if none {{#if related_files}} ## Other Files in This Change {{related_files}} Relate file changes to these files. {{/if}} Call yield tool with JSON payload.这份模板的职责非常单一:告诉子代理分析哪个文件、以什么目标分析、以什么结构返回结果。它不涉及任何 git 操作细节,也没有模型专属指令,是一份高度可复用的任务提示词。
二、模板变量与渲染机制
模板通过@oh-my-pi/pi-utils的prompt.render函数渲染,调用点在 analyze-file.ts:
const assignment = prompt.render(analyzeFilePrompt, { file, goal: params.goal, related_files: relatedFiles, });三个变量语义如下:
| 变量 | 来源 | 说明 |
|---|---|---|
file | 工具参数files数组中的单个路径 | 必填,每个文件对应一次独立的子代理任务 |
goal | 工具参数goal? | 可选。传入时覆盖默认目标 “Summarize purpose and commit-relevant changes.”,用于聚焦分析方向 |
related_files | formatRelatedFiles()动态拼接 | 可选。列出同一次改动中的其他文件及行数/类型,帮助子代理建立“变更全景” |
其中related_files通过 formatRelatedFiles 生成,输出形如:
OTHER FILES IN THIS CHANGE: - src/lib.rs (120 lines): implementation - tests/foo_test.rs (45 lines): test file每行由文件路径、numstat统计出的改动行数(additions + deletions)以及inferFileType推断出的文件角色组成。若当前文件是本次改动中唯一的文件,related_files为undefined,模板中的{{#if related_files}}分支自动省略,避免输出空噪音。
三、文件类型推断:优先级驱动的角色标注
inferFileType的判定逻辑(analyze-file.ts)依赖getFilePriority(git-file-diff.ts)的优先级数值:
| 优先级 | 匹配规则 | 推断角色 |
|---|---|---|
| -100 | 二进制扩展名(.png/.jpg/.pdf/.zip/.so 等) | binary file |
| 10 | 路径含/test/、/tests/、.test.、.spec.等模式 | test file |
| 20 | 低优先扩展名(.md/.txt/.json/.yaml/.toml 等,且非清单文件) | documentation或configuration |
| 70 | 依赖清单(Cargo.toml、package.json、go.mod、pyproject.toml 等) | dependency manifest |
| 80 | 脚本类(.sh/.bash/.zsh/.sql) | script |
| 100 | 核心语言扩展名(.rs/.go/.py/.ts/.tsx/.java/.c/.cpp 等) | implementation |
| 50 | 其他 | source file |
可以看到,同一套优先级函数同时服务于 diff 排序与文件角色标注:processDiffs按优先级降序排列文件、优先展示实现代码,而analyze_files用它给相关文件打标签。这正是“一源多用”的工程设计——两个工具共享同一份“什么文件更重要”的领域知识。
四、JSON 输出契约:summary / highlights / risks
模板要求子代理返回 “concise JSON object”,三个字段在 analyzeFileOutputSchema 中被声明为结构化输出约束:
const analyzeFileOutputSchema = { properties: { summary: { type: "string" }, highlights: { elements: { type: "string" } }, risks: { elements: { type: "string" } }, }, };- summary:一句话描述文件在代码库中的角色(file-role description)。注意它描述的是“角色”而非“改动摘要”,子代理需结合文件在项目中的定位作答。
- highlights:2~5 条要点,聚焦 notable behaviors or changes,即值得写进提交信息的显著行为或变更。
- risks:值得注意的边界情况或风险;没有则为
[]。这一字段为后续的提交提案提供了“预警通道”,例如破坏性变更、遗留 TODO、异常分支等。
“Call yield tool with JSON payload” 对应底层TaskTool的 yield 机制。从 agent.ts 中关于 task tool 的注释可以确认:task 工具不再接收单次调用的 schema,而是由继承的会话 schema(即这里的analyzeFileOutputSchema)驱动每次派生子代理的结构化输出。
五、并行派发:Promise.all + 会话信号量限流
createAnalyzeFileTool 注册的自定义工具名为analyze_files,其入参 schema:
const analyzeFileSchema = type({ files: type("string").describe("file path").array().atLeastLength(1), "goal?": type("string").describe("analysis focus"), });执行逻辑的核心是按文件并行派发子代理:
const analyses = await Promise.all( params.files.map((file, index) => { const relatedFiles = formatRelatedFiles(params.files, file, numstat); const assignment = prompt.render(analyzeFilePrompt, { file, goal: params.goal, related_files: relatedFiles }); const taskParams: TaskParams = { name: `AnalyzeFile${index + 1}`, agent: "sonic", task: assignment, }; return taskTool.execute(`${toolCallId}-${index + 1}`, taskParams, signal); }), );几个值得注意的实现细节:
- 每个文件一个子代理:任务名依次为
AnalyzeFile1、AnalyzeFile2…,彼此独立,互不依赖。 - sonic 子代理:任务指定
agent: "sonic",即复用 oh-my-pi 的通用 agent 运行能力。 - 信号量限流:构建的
ToolSession携带会话信号量,taskTool.execute()的并行扇出受其约束(见 buildToolSession 的注释),避免一次性爆发过多并发请求。 - 内联结果收集:该会话没有
asyncJobManager,每次 execute 走 task 工具的同步回退路径,子代理结果就地返回,正适合“结果直接喂给提交智能体作为证据”这一场景。 - 聚合返回:所有子代理的文本结果以
\n\n连接合并,details.results收集结构化结果,totalDurationMs汇总各子代理耗时。
六、在 agentic 提交工作流中的定位:何时使用 analyze_files
提交智能体的系统提示词 system.md 定义了完整的工具工作流规则:
- 总是先调用
git_overview; - 控制工具调用量:关键文件优先用 1~2 次
git_file_diff(硬性上限 2 次); - 大 diff 用
git_hunk按 hunk 精读; - 需要风格上下文才用
recent_commits; analyze_files仅当 diff 过大或语义不清时使用;- 不使用 read 工具。
也就是说,analyze_files是提交智能体的“深度侦查”手段,是前四步常规侦查(overview → file_diff → hunk → recent_commits)之后的兜底方案。当 diff 体量超出上下文预算、或改动意图难以从 diff 本身判断时,主智能体把分析任务“外包”给多个并行子代理,每个子代理只专注一个文件,把结论压缩回三字段 JSON,既省 token 又提升分析质量。
工具注册在 tools/index.ts,受enableAnalyzeFiles开关控制(默认开启);agent.ts 中显式传入enableAnalyzeFiles: true,确认该功能在提交会话中默认启用。
七、证据闭环:从文件分析到提交提案验证
analyze_files的分析结果最终服务于propose_commit/split_commit。提交提案的验证逻辑在 validation.ts 中给出了硬性约束,这些约束与模板要求相呼应:
- summary 首词必须是过去式动词,长度 ≤ 72 字符(SUMMARY_MAX_CHARS);
- 规避填充词(comprehensive、various、several、improved、enhanced、better)与元描述短语(this commit、this change、updated code、modified files);
- detail 最多 6 条(MAX_DETAIL_ITEMS),超限时按关键词打分保留高价值条目(security/breaking/perf/bug/api 等关键词有更高分值);
validateTypeConsistency还会校验 commit type 与改动文件类型的一致性(如docs提交必须含文档改动、test提交必须含测试改动、perf提交应有 benchmark 或性能关键词)。
而propose_commit工具(propose-commit.ts)在收到提案后立即执行这三层校验,返回valid / errors / warnings,并把通过校验的提案写入state.proposal(state.ts 中的CommitAgentState),最终由runCommitAgentSession的完成检查(isProposalComplete)判定会话结束或触发最多 3 次重试提醒。
因此整条链路是:overview 摸清改动清单 → diff/hunk 精读关键文件 → analyze_files 并行深挖大而杂的改动 → propose_commit 汇总成受验证约束的 Conventional Commits 提案。analyze-file.md正是这条链路中“并行深挖”环节的任务定义,其 JSON 契约确保了子代理产出可以稳定地被聚合、引用和回填进最终提案。
八、实战要点与扩展思考
- 自定义 goal 的威力:默认目标是“总结用途与提交相关变更”,但当提交智能体已有明确怀疑点(如“确认是否引入破坏性变更”“定位性能退化位置”)时,可通过
goal参数注入聚焦指令,子代理的分析会据此收敛,输出质量显著提升。 - 相关文件上下文的取舍:
formatRelatedFiles使用numstat(来自git_overview的快照,见 git-overview.ts)计算行数,同一优先级函数驱动的类型标签让子代理一眼识别“这是个测试文件还是核心实现”,避免它把重心放在文档或清单文件上。 - 成本意识设计:模板反复强调 “concise”、“1-sentence”、“2-5 bullets”、“[] if none”,配合结构化输出 schema,等于强制每个子代理把高信息密度压缩进固定骨架,这正是大型 diff 场景下控制上下文占用的关键。
如果你希望在自己的提交工作流中复用该模式,可以直接把 analyze-file.md 作为子代理任务提示词模板,配套实现“每文件并行派发 + 三字段 JSON 输出 + 相关文件上下文注入”三件套,即可获得与 oh-my-pi agentic commit 相同的逐文件侦查能力。
【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考