ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

oh-my-pi 结构化代码修复任务模板解析:用 Handlebar 模板生成精确的 bug 修复指令

oh-my-pi 结构化代码修复任务模板解析:用 Handlebar 模板生成精确的 bug 修复指令 oh-my-pi 结构化代码修复任务模板解析用 Handlebar 模板生成精确的 bug 修复指令【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi导读本文深入解析 oh-my-pi 项目中用于生成结构化代码修复任务的 Handlebar 模板 structural-task.md。该模板把 7 类常见代码缺陷fall-through 标签、重复块、错位块、冗余调试包装、块/语句顺序颠倒、if-else 分支互换的参数化描述与精确的代码片段 hunk 结合起来渲染出只改一处、其余不动的强约束修复指令。读完本文你将掌握该模板的分支逻辑、变量占位、hunk 渲染机制以及它背后的模板引擎实现与黄金测试验证方法可直接照此模式为 Agent 定制高质量的结构化任务提示词。一、模板的定位与整体结构structural-task.md位于 packages/utils/test/fixtures/template/ 目录下与file-operations.md、frontmatter.md、identifier-task.md、session-user.md并列是 oh-my-pi 为回归测试准备的真实模板黄金样本golden fixture。它是一个 Handlebar 语法模板输入一组结构化上下文文件路径、缺陷类型、hunk 列表等输出一段面向编码 Agent 的自然语言修复指令。模板整体由三部分组成标题区# Fix a bug in \{{filename}}用变量承载目标文件路径缺陷描述区一个{{#when kind ...}}多分支条件链根据kind字段输出对应缺陷类型的描述文案修复目标区遍历hunks数组用代码围栏逐段给出修复后必须精确呈现的代码片段并以一句强约束收尾。这种参数化描述 精确目标代码的结构保证了不同任务之间格式统一、机器可解析同时让 Agent 的修改范围被严格限定。二、缺陷类型分支when条件链模板核心是一个七分支条件结构全部通过{{#when kind xxx}}实现。每个分支描述一种典型的结构性 bugkind 取值缺陷描述期望修复动作case-labelswitch中{{label}}的值必须与紧随其后的 case 完全一致处理在{{before}}之前直接补一个 fall-through 的{{label}}标签duplicate-block以{{head}}起始的代码块连续出现两次第二次是复制粘贴事故删除第二个副本保留第一个move-block以{{head}}起始的代码块被移动到错误位置当前位于{{currentPrev}}之后移回使其直接位于{{destination}}之前wrap-if残留的调试包装是多余的删除第{{wrapperLine}}行的if (true) {及其右花括号并将被包裹的代码体整体减少一层缩进swap-blocks两个相邻代码块顺序颠倒交换两个代码块swap-lines两个相邻语句顺序颠倒交换两条语句swap-if-else{{condition}}的两个分支体互换交换 if 与 else 的分支体when并不是 Handlebar 内置块级助手而是 oh-my-pi 在 prompt.ts 中注册的自定义助手。它支持、、!、!、、、、八种比较运算符运算符不在支持集合内时回退到inverse分支handlebars.registerHelper( when, function (this: unknown, lhs: unknown, operator: string, rhs: unknown, options: Handlebars.HelperOptions): string { const ops: Recordstring, (a: unknown, b: unknown) boolean { : (a, b) a b, // ... : (a, b) (a as number) (b as number), // ... }; const fn ops[operator]; if (!fn) return options.inverse(this); return fn(lhs, rhs) ? options.fn(this) : options.inverse(this); }, );这段实现也解释了为什么模板中同时出现宽松写法与两者在实现上都映射到严格相等比较兼容不同风格的调用。三、hunk 渲染精确目标代码的注入机制描述完缺陷后模板通过{{#each hunks}}遍历所有需要修改的区域为每个 hunk 输出修复后必须读起来完全一致的代码After the fix, the affected {{#when hunkCount 1}}regions must{{else}}region must{{/when}} read exactly: {{#each hunks}} {{#if startLine}} Around line {{startLine}}: {{/if}} {{../fence}}{{../language}} {{newCode}} {{../fence}} {{/each}} Make exactly this change; do not modify anything else.这里有三个值得注意的机制单复数自适应{{#when hunkCount 1}}regions must{{else}}region must{{/when}}根据 hunk 数量输出regions must或region must保证语法的自然性../父级上下文引用hunk 处于{{#each hunks}}的循环作用域内而fence、language定义在顶层上下文因此模板使用{{../fence}}、{{../language}}向上回溯取值。这与 template.ts 中resolvePath对../前缀的处理一一对应——每消耗一个../就沿frame.parents向上跳一层可选行号锚点{{#if startLine}}为startLine 0的 hunk 输出Around line N:提示而startLine为 0 或缺失的 hunk例如删除型修改则直接输出代码块不附带行号。在黄金测试 template.test.ts 中swap-lines用例给出了真实的渲染输入输出输入上下文filename: src/a.ts、kind: swap-lines、secondHead: b();、firstHead: a();、hunkCount: 2、fence: 、language: ts以及两个 hunkstartLine: 4的a();\nb();与startLine: 0的c();渲染结果# Fix a bug in src/a.ts Two adjacent statements are in the wrong order: b(); belongs before a();. Swap the two statements. After the fix, the affected regions must read exactly: Around line 4: ts a(); b();c();Make exactly this change; do not modify anything else.可以看到hunkCount 1 触发了复数形式 regions must第二个 hunk 因 startLine 为 0 被 {{#if startLine}} 跳过直接输出代码块。整段输出不含任何多余修饰正是为了让 Agent 可以逐字符对照。 ## 四、渲染链路从模板到最终指令 模板不是直接拼接字符串而是经过一条完整的渲染流水线。核心入口是 [prompt.ts](https://link.gitcode.com/i/61c11be24eb29c090bb784319b82450c) 中的 render ts export function render(template: string, context: TemplateContext {}): string { const compiled compile(template); const rendered compiled(context ?? {}); return format(rendered, { renderPhase: post-render }); }链路分三步编译compile调用 template.ts 中基于parseTemplate实现的兼容 Handlebar 的编译器并带有基于原始模板字符串的编译结果缓存compiledTemplateCache重复渲染同一模板直接命中缓存跳过解析渲染用上下文执行编译产物过程中解析when、join、xml等自定义助手以及if、each、with等内置块级助手后处理format在post-render阶段统一清理输出——压缩 Markdown 表格间距、折叠多余空行、在{{/闭合标签行前清除尾随空行等保证最终指令干净、紧凑、适合直接进入上下文窗口。一个容易被忽略的细节是编译选项compile使用{ noEscape: true, strict: false }。也就是说模板中的{{newCode}}等内容不做 HTML 转义代码中的、等字符得以原样进入指令——这是代码片段类模板正确工作的前提。而 template.ts 中的escapeExpression仍保留着完整的转义实现与SafeString机制供需要转义的场景使用。五、与同系列模板的协同structural-task.md并非孤立存在它与同目录下的其他 fixture 共同覆盖了 Agent 指令生成的典型场景identifier-task.md标识符拼写错误修复使用{{#when count 1}}做单复数处理、{{join affectedLines , }}拼接受影响行号file-operations.md文件读写清单通过{{#xml files}}助手把文件列表包装成files.../files结构xml助手在 prompt.ts 中实现内容为空时整体不输出frontmatter.mdAgent 元信息name、model、thinking-level、blocking 等的 frontmatter 生成session-user.md会话上下文与 changelog 目标的注入。这些模板共享同一套渲染引擎与助手注册表。template.test.ts中还有一个全局保障测试遍历仓库内packages/*/src/**/*.md下所有含{{的模板文件逐一编译断言编译成功数量大于 100见 template.test.ts从侧面说明这套模板体系被广泛用于项目内的提示词生成。六、实战如何自定义一个新的结构化修复任务模板理解了模板机制后可以按同样的模式扩展新缺陷类型。一个最小化的新分支只需在条件链中追加{{#when kind your-new-kind}} The {{placeholder}} is misconfigured. Replace it with {{correctValue}}. {{/when}}并在 hunk 区提供修复后的目标代码。关键约束包括上下文契约模板引用的每个变量filename、kind、hunks、fence、language、hunkCount等都必须在渲染时由调用方提供缺失路径在非严格模式下渲染为空串不会报错但会产出残缺指令../回溯循环体内的 hunk 如需引用顶层变量必须使用{{../name}}形式精确性措辞收尾句Make exactly this change; do not modify anything else.与read exactly的强约束是结构化任务的精髓新模板不应削弱这类限定语黄金测试参照 template.test.ts 的GOLDENS数组为每个新分支固化输入上下文 → 期望输出的配对防止后续改动破坏渲染结果。七、总结structural-task.md是 oh-my-pi 提示词工程的一个缩影用一套行为兼容 Handlebar 的模板引擎template.ts、一组面向提示词定制的助手when、join、list、xml等见 prompt.ts和严格的后处理格式化把 7 类结构性代码缺陷的参数化描述渲染为精确、可执行的修复指令。它既是对 Agent 行为的强约束工具也是理解项目提示词生成管线的最佳入口——模板文件本身即是文档黄金测试即是规格。【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表