深入解析 oh-my-pi 的 project-prompt:编码 Agent 系统提示中的项目上下文注入机制
深入解析 oh-my-pi 的 project-prompt编码 Agent 系统提示中的项目上下文注入机制【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi导读在 oh-my-pi 这款把 IDE 接入 Agent的编码代理中系统提示system prompt并非一段写死的文本而是由多个模板区块按会话状态动态拼接而成。其中project-prompt.md承担着项目级上下文注入的职责它将工作站环境、仓库规则CLAUDE.md / AGENTS.md、工作区目录树、多根工作区以及强制行为准则一次性组装进模型上下文。本文以 project-prompt.md 为骨架结合 system-prompt.ts、workspace-tree.ts 与模板引擎源码逐区块拆解该模板的渲染逻辑、数据来源与工程化兜底帮助读者理解 Agent 系统提示的构建原理并掌握如何通过上下文文件、工作区树与自定义追加文本精准控制编码 Agent 的项目感知能力。一、模板在系统提示构建管线中的位置project-prompt.md位于packages/coding-agent/src/prompts/system/目录与system-prompt.md、custom-system-prompt.md、active-repo-context.md等同属系统提示模板族。在 system-prompt.ts 中它通过import projectPromptTemplate from ./prompts/system/project-prompt.md with { type: text }以纯文本形式被加载随后在buildSystemPrompt函数的收尾阶段被渲染并追加// packages/coding-agent/src/system-prompt.ts#L1040-L1045 const projectPrompt prompt .render(projectPromptTemplate, resolvedCustomPrompt ? { ...data, contextFiles: [], appendPrompt: } : data) .trim(); if (projectPrompt) { systemPrompt.push(projectPrompt); }从源码可见两个关键设计作为独立的尾部区块追加buildSystemPrompt返回systemPrompt: string[]L674-L677各区块保持独立便于 Provider 层按消息/块分发project-prompt.md的渲染结果追加在主模板之后、active-repo-context之前L1046-L1048。自定义提示下的降级渲染当调用方提供了customPrompt/resolvedCustomPrompt时渲染数据中的contextFiles被清空、appendPrompt置空L1041因为自定义模板已自行负责渲染上下文文件与追加文本项目脚注只保留环境、工作目录、工作区树与目录规则见 L1038-L1039 的注释说明。project-prompt.md本体是一份Handlebars 模板仓库在 prompt.ts 中通过Handlebars.create()创建独立实例并以noEscape: true编译以保证 XML/代码片段不被转义因此它的最终输出完全取决于运行时注入的数据——这正是下面逐区块分析的重点。二、workstation环境快照与模型标识模板开头是最简洁的环境信息块workstation {{#list environment prefix- join\n}}{{label}}: {{value}}{{/list}} {{#if model}}- Model: {{model}}{{/if}} /workstation{{#list ...}}是仓库自注册的 Handlebars 辅助函数prompt.ts#L331-L341支持prefix/suffix/join三个参数join\n会被自动反转义为真实换行当数组为空时整块不输出。environment数据由getEnvironmentInfo(cpuModel, gpu)生成system-prompt.ts#L987其中 CPU/GPU 探测通过独立的子进程完成并带有严格超时与空缓存兜底GPU_PROBE_TIMEOUT_MS SYSTEM_PROMPT_PREP_TIMEOUT_MS - 500见 L181-L185——即环境探测失败不会阻塞整个系统提示构建。model由构建选项model?: string传入L650-L653可通过includeModelInPrompt: false关闭显示默认开启。该区块为模型提供当前跑在哪台机器、用什么模型的最小事实集避免 Agent 凭猜测假设运行环境。三、repo-rules上下文文件的强制加载{{#if contextFiles.length}} repo-rules MUST follow these context files for all tasks: {{#each contextFiles}} file path{{path}} {{content}} /file {{/each}} /repo-rules {{/if}}这是模板中内容权重最高的区块一旦发现上下文文件就用大写的MUST follow要求模型在所有任务中遵循这些文件的内容并把每个文件的完整正文以file path...形式内联注入——模型无需额外调用read即可看到全部规则。数据从哪来contextFiles由 loadProjectContextFiles 负责加载通过能力系统loadCapability(contextFileCapability.id, ...)发现上下文文件。该能力在 capability/context-file.ts 中定义明确覆盖CLAUDE.md、AGENTS.md、GEMINI.md等持久化指令文件且支持 monorepo 层级结构中多级 AGENTS.md 并存。对每个文件执行expandAtImports(content, path)L466-L474展开其中的path/to/file引用展开基准是文件自身所在目录——与 Claude Code、Goose 等工具的相对导入约定一致。按depth降序排序离 cwd 越远越靠前最后经dedupeContainedContextFiles去重详见第五节。兜底与容错整个发现过程被withDeadline(loadProjectContextFiles, ...)包裹L882-L884buildSystemPrompt设有全局SYSTEM_PROMPT_PREP_TIMEOUT_MS 5000毫秒的构建预算L181任一准备步骤超时或失败都会回退到prepDefaults中的最小默认值同时在 stderr 打印警告L895-L913。超时的工作仍在后台继续完成以预热缓存供下一次会话使用L770-L780。四、dir-context目录级分层规则与禁止再 grep 规则文件声明{{#if agentsMdSearch.files.length}} dir-context Some directories may have rules; deeper rules override higher ones. Before changes in these directories, MUST read: {{#list agentsMdSearch.files join\n}}- {{this}}{{/list}} /dir-context {{/if}} {{#ifAny contextFiles.length agentsMdSearch.files.length}} Context files above auto-loaded. NEVER grep/glob for AGENTS.md, CLAUDE.md, .cursorrules, or similar agent/context files: relevant files already in context; others noise. {{/ifAny}}这两个区块联合实现了monorepo 分层规则的语义agentsMdSearch.files来自工作区树扫描附带收集的 AGENTS.md 清单。在 buildWorkspaceTree 中原生扫描器以collectAgentsMd: true一次性收集全部 AGENTS.md 路径L97系统提示构建器随后对其去重、排序并截断到硬上限AGENTS_MD_LIMIT 200workspace-tree.ts#L16、system-prompt.ts#L893。模板声明更深层的规则覆盖更高层并要求模型在修改这些目录之前必须阅读对应规则文件——注意这里与 repo-rules 的区别repo-rules 内联全文确定性指令dir-context 只列路径按需读取控制 token 开销。当两类文件任一存在时模板追加一条强约束绝不允许用grep/glob再去检索 AGENTS.md、CLAUDE.md、.cursorrules 之类的规则文件——相关文件已在上下文中其余的只是噪音。这既节省了工具的无效调用也防止模型被无关规则文件干扰。{{#ifAny}}同样来自模板引擎的注册辅助函数prompt.ts#L397-L400任一参数为真即输出块内容。五、workspace-tree按 mtime 排序的工作区布局{{#if includeWorkspaceTree}} {{#if workspaceTree.rendered}} workspace-tree Working-directory layout: newest mtime first; depth ≤ 3. {{workspaceTree.rendered}} {{#if workspaceTree.truncated}} {{#has tools glob}}{{#has tools read}}Some entries elided to shorten tree — use {{toolRefs.glob}}/{{toolRefs.read}} to drill in.{{/has}}{{/has}} {{/if}} /workspace-tree {{/if}} {{/if}}工作区树由includeWorkspaceTree选项控制默认falsesystem-prompt.ts#L656-L657。开启后渲染规则在模板中写得很明确目录布局按最新 mtime 在前排列深度不超过 3 层。其底层实现在 workspace-tree.ts几个值得注意的工程细节默认裁剪参数maxDepth: 3、perDirLimit: 12每目录子项上限、lineCap: 120渲染总行数硬上限L6-L10。超限时assembleTree会记录droppedCount并把超出的条目折叠为[recent…, oldest]布局同时置位truncated。一次原生扫描树与 AGENTS.md 清单由listWorkspace来自oh-my-pi/pi-natives的原生模块同一次扫描产出隐藏文件不显示、遵循.gitignore、并附加timeoutMs中止保护L92-L99系统提示构建器无需二次扫描。mtime 用绝对时间渲染注释明确指出该树嵌入在会被缓存的系统提示中若使用3 分钟前这类相对时间每次重建都会漂移、击穿提示缓存因此这里强制使用确定性的 UTC 绝对时间戳保证区块跨会话字节级一致L104-L108。截断提示只引用确实存在的工具{{#has tools glob}}/{{#has tools read}}会先检查工具清单只有对应工具存在时才建议模型用toolRefs.glob/toolRefs.read深入探查。toolRefs在 system-prompt.ts#L937 由工具名映射生成{{#has}}辅助函数支持数组 / Set / Map / 对象四种容器prompt.ts#L483-L500。六、workspace-roots多根工作区的上下文接管{{#if additionalWorkspaceRoots.length}} workspace-roots Additional workspace directories. This CURRENT workspace state supersedes workspace changes mentioned earlier in the conversation. ... Use absolute paths under these roots to read/grep/glob/edit. Manage with /add-dir and /remove-dir; /dirs lists them. {{#each additionalWorkspaceRoots}} - {{this}} {{/each}} /workspace-roots {{/if}}多根multi-root场景下模板向模型声明当前工作区状态优先于对话早期提到的工作区变更并要求模型对附加根使用绝对路径调用read/grep/glob/edit工具名同样是按需拼接——只有对应工具存在时才会出现在建议列表中system-prompt.ts#L44 的行内三元拼接。该区块的数据来源同样严谨附加根中与主 cwd 解析后相同的路径会被过滤掉system-prompt.ts#L803、L810、L1006。更重要的是每个附加根也会独立执行上下文文件发现与工作区树构建contextFilesPromise会对每个 root 调用loadProjectContextFiles并合并去重L798-L809workspaceTreePromise也会为每个 root 构建树并汇总 AGENTS.md 清单L811-L833。也就是说monorepo 拆分为多个工作区根时各根自己的AGENTS.md规则依然会被收集进 dir-context。七、critical会话级强制行为准则critical - Each response MUST advance the task; completion only stopping condition. - MUST default to informed action; do not ask for confirmation when tools or repo context can answer. - Before yielding, MUST verify significant behavioral changes: run the specific test, command, or scenario covering the change. /criticalcritical区块与前面的上下文注入不同它是无条件输出的行为契约三条规则分别约束推进目标每条响应都必须推进任务任务完成是唯一停止条件自主行动当工具或仓库上下文足以回答时不得停下来请求确认默认采取知情行动交付前验证在让出控制权之前必须对显著行为变更运行覆盖该变更的具体测试、命令或场景进行验证。这三条与仓库中eager-task、approval-mode等提示共同构成 oh-my-pi 编码 Agent 的少打扰、多动手、交付前自验基调。八、appendPrompt面向调用方的扩展点{{#if appendPrompt}} {{appendPrompt}} {{/if}}模板为外部调用方保留了appendPrompt追加位。该值来自BuildSystemPromptOptions.appendSystemPrompt经resolvePromptInput解析后注入数据system-prompt.ts#L698、L991。同时promptSources数组L979-L984将自定义提示、追加提示与全部上下文文件合并用于dedupeAlwaysApplyRules对 always-apply 规则做段落级包含去重L132-L141避免同一条规则在提示中重复出现。九、数据去重与 SYSTEM.md 协同模板本身只有 59 行但它的正确性依赖上游两道工序上下文文件去重dedupeContainedContextFilessystem-prompt.ts#L425-L444先将文件按 depth 降序排序离 cwd 越远越不权威、排前面再按规范化段落序列的连续包含规则剔除被更权威文件完全覆盖的文件仅改写或穿插的近似内容不会被误删注释明确包含是规范化后的精确匹配而非模糊匹配。SYSTEM.md 能力协同loadSystemPromptFilessystem-prompt.ts#L491-L505通过systemPromptCapability加载用户级 / 项目级SYSTEM.md项目级优先于用户级作为主模板区块渲染而project-prompt.md始终作为独立项目脚注存在。若调用方显式提供了customPrompt则主模板由自定义模板接管SYSTEM.md的走查被跳过见 L789-L797 注释这是为了避免 CLI 提供的提示被项目/用户 SYSTEM.md 静默增强。十、工程化要点小结维度实现要点源码位置模板引擎独立 Handlebars 实例noEscape编译自带list/ifAny/has/includes/when等辅助函数与编译缓存prompt.ts构建预算全量准备步骤共享 5000ms 超时超时/失败回退最小默认值后台继续预热缓存system-prompt.ts#L758-L787上下文发现capability 能力系统发现 CLAUDE.md/AGENTS.md/GEMINI.md支持import展开与段落级去重context-file.ts、system-prompt.ts#L451-L485工作区树原生单次扫描深度 ≤ 3、每目录 12 项、总行数 120 上限绝对 mtime 保证提示缓存稳定workspace-tree.tsAGENTS.md 上限清单硬上限 200 个超出的规则文件不再提示workspace-tree.ts#L16多根工作区附加根分别发现上下文与树并合并工具建议按需渲染system-prompt.ts#L798-L833结语project-prompt.md是 oh-my-pi 编码 Agent 系统提示的项目侧大脑它用最小的模板开销把环境快照、强制规则、分层目录规则、工作区布局与行为契约组装成一个结构清晰、缓存友好的尾注区块。理解它的渲染数据来源contextFiles、agentsMdSearch、workspaceTree、additionalWorkspaceRoots与上游的发现、去重、超时兜底机制等于掌握了如何让编码 Agent 精准感知你的仓库——无论是为 monorepo 各目录编写分层 AGENTS.md还是通过多根工作区与自定义追加提示定制 Agent 的项目视野都能在模板语义与源码实现之间找到精确的对应关系。【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考