mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-10-26 10:45:22 +00:00
真实会话里模型仍习惯性先调 bash grep,被拒后才改用 grep 工具;系统提示词里已有 4 处 提醒,但模型下调用决定时看的是工具 schema 描述,而 Pi 内置 bash 描述对此只字未提。 - 新增 extensions/bash-override.ts:用 Pi 的 createBashToolDefinition 重新注册 bash, 执行、输出结构与 codemode 说明完全沿用上游;shellPath/commandPrefix 按 ctx.cwd 经 SettingsManager 惰性解析,与内置一致 - tools.jsonc 新增 descriptionAppend 字段,由 prompt-guard 注册时拼接到上游描述后 - bash 增加命令→工具对照规则(grep -n / grep -rl / find -name),并提示 文件清单用 $(git ls-files) 传参、不要接 xargs(会触发权限审核) Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
12 KiB
12 KiB
my-pi 维护约定(extensions/)
本目录是组合包的薄 wrapper 与纯 helper 层:第三方扩展一律经这里的包装文件(多数再套 prompt-guard.ts 代理)加载,自维护实现位于各自顶层目录。
系统提示词单一所有权
extensions/system-prompt.ts是组合包唯一的系统提示词出口,必须排在pi.extensions最后,也是唯一允许在before_agent_start返回systemPrompt的扩展。提示词内容统一由config/prompt/管理:preamble.md(开场白)、tools.jsonc(每个工具的简介、规则及第三方工具说明覆盖)、routing.jsonc(跨工具工作流规则,渲染为<tool_routing>)、sections.jsonc(分区顺序)。- 其他组合包扩展不得返回
systemPrompt,也不得在context钩子中注入提示性消息;需要动态提示时只能写入event.systemPromptOptions.sections.<name>并在sections.jsonc登记顺序,静态规则写入promptGuidelines或该工具在tools.jsonc中的条目。 - 第三方扩展必须经
extensions/下的组合包包装文件加载,由extensions/prompt-guard.ts的代理 API 拦截其对系统提示词的直接改写,并在注册工具时应用tools.jsonc的description覆盖;上游硬编码且无配置开关的注入只能在对应包装文件内处理,并以测试锁定所依赖的上游原文(依赖保持精确版本)。 - 新增工具必须在
tools.jsonc登记(覆盖说明,或以"inherit": true表示已按本组合包审阅上游原文),否则tests/system-prompt.test.ts失败;config/prompt/中的文字不得引用被策略禁止或被替换的用法。运行时若检测到其他扩展已定死提示词或存在未登记工具,system-prompt.ts会各提示一次。
system-prompt.ts 开发约定
- 扩展入口是
extensions/system-prompt.ts,必须排在pi.extensions最后;纯 helper(JSONC 加载与校验、applyToolCatalog/renderRouting/orderSections/spliceCover/readPreamble等)位于extensions/system-prompt-config.ts以便node --test单测;组合包权威源是config/prompt/(preamble.md/tools.jsonc/routing.jsonc/sections.jsonc),扩展运行时直接读取已安装组合包内文件,不经任何脚本部署。 - 现代 Pi 下必须通过修改规范化
systemPromptOptions(toolSnippets/toolGuidelines/sections)保留分区结构,再读取重渲染的event.systemPrompt拼入封面并返回systemPrompt;宿主不提供结构化 options 或 options 不参与重渲染时自动降级为文本拼接。不得改用customPrompt选项——它会抑制tools/rules/docs分区。 - 宿主传入
customPrompt(pi-subagents 子 Agent prompt、SYSTEM.md)时,该开场白自含身份标记(如<active_agent/>),不得用preamble.md覆盖;其余分区处理(tool catalog、<tool_routing>、分区排序、降级追加)照常。子会话判定只用systemPromptOptions.customPrompt上的<active_agent name="..."/>契约(isSubagentCustomPrompt),绝不检测渲染后提示词——主会话的项目文档也可能含该字面量。 - 子 Agent 提示词画像在
config/prompt/subagent/(preamble.md+agents/*.md):由extensions/subagents.ts注入 pi-subagents 的basePrompt/bundledAgentsDir选项,替代上游的父提示词嵌入与内置默认 Agent;子会话经excludedExtensionPaths排除pi-ask-user(子会话无人可问)。 routing.jsonc规则可选"scope": "main" | "subagent"(缺省两者皆适用,其他值校验失败),renderRouting按 audience 过滤;sections.jsonc可选"subagentExclude"分区名列表,子会话在排序前删除这些分区(当前排除memory_policy与chrome_profile_bridge)。- 封面拼接边界必须是独占一行的裸标签,不能匹配带属性的标签:
<project_instructions path="...">嵌套在<project_context>内,只有裸标签才是分区边界。 preamble.md缺失、不可读或空白时保持 Pi 默认封面,不得写入空 preamble;config/prompt/解析或校验失败时before_agent_start警告一次并整体 no-op,绝不抛出。- 检测到其他扩展已设置
forceSystemPrompt、或激活工具未在tools.jsonc登记时各提示一次(warning);本扩展返回的systemPrompt把提示词冻结为最终文本是刻意设计——这也是它必须最后加载的原因。 config/prompt/随组合包发布,pi install/pi update后即就位,无需任何部署 helper;对已安装副本的临时修改由pi update覆盖。路由规则本体见config/prompt/routing.jsonc与 README,system-prompt.ts只负责渲染,不得替换 Pi 默认系统提示词。- 修改 loader、
spliceCover语义、注册顺序或config/prompt/路径后,必须运行node --test tests/system-prompt.test.ts、node --test tests/bundle-config.test.ts、node --test tests/extension-load.test.ts,并确认npm pack --dry-run包含config/prompt/。
各 wrapper 约定
fff-override.ts:强制 FFF 官方override模式,统一接管find、grep和@补全;multi_grep按上游保持关闭(加载前删除PI_FFF_MULTIGREP环境变量)。FFF 独占本地字面搜索,远端服务器搜索由ssh_find/ssh_grep负责,RTK 不得接管搜索工具(见pi-rtk-optimizer/AGENTS.md)。显式 CLI flag 仍遵循 FFF 官方优先级。bash-override.ts:用createBashToolDefinition重新注册内置bash,目的只是让tools.jsonc的descriptionAppend落到模型可见描述里(prompt-guard 在注册时拼接)。ExtensionContext 不暴露 session settings,因此shellPath/commandPrefix在首次 execute 时按ctx.cwd经SettingsManager.create(ctx.cwd, getAgentDir())惰性解析并按 cwd 缓存,metadata 来自process.cwd()的定义;执行、输出结构与 codemode 说明完全委托上游定义,不得改动上游执行逻辑,也不得用 prepareLoadout 或 provider-payload 改写实现同样效果。codegraph.ts+codegraph-client.ts:注册原生codegraph_explore工具,按索引根惰性常驻codegraph serve --mcp -p <root>子进程,经组合包自有 stdio 逐行 JSON-RPC 客户端直连(不经 shell、不带 pi-mcp-adapter 或 MCP SDK);serve 进程内置文件监听自动同步索引,无结果缓存。子进程 10 分钟无调用自动关闭、会话结束统一关闭;调用中死亡换新客户端透明重试一次;其启动的上游 daemon(.codegraph/daemon.sock)退出后可多驻留 ≤5 分钟,属上游行为,组合包不管理。- CodeGraph 是机器级依赖,
install.sh/update.sh经官方安装器管理codegraphCLI,组合包不内置其运行时。安装、升级和普通启动流程不得执行codegraph init;只有codegraph_explore在未初始化项目上被调用、且用户在ctx.ui.confirm中明确确认后才可codegraph init当前目录,拒绝记入会话级 declined 不再重复询问;init 失败必须如实报告并让模型回退内置工具;不得改动 CodeGraph 更新或遥测设置。CLI 缺失、init 被拒或服务调用失败都不得抛出,必须以文本结果打回并引导模型改用find/grep/read/LSP。已移除的plugin-init.ts(原/plugin_init)职责已并入本文件的惰性确认,不得恢复。 hashline.ts+hashline-config.ts:部署组合包权威config/pi-hashline-edit.json后加载pi-hashline-edit;默认以 2 字符行哈希覆盖内置read/edit,grep与replaceText均关闭。它保证锚定编辑而不负责压缩,大文件上下文节省必须来自先定位/隔离分析、再做最小范围offset/limit读取。permission-system.ts:直接加载仓库内pi-permission-system/src/index.ts,自身不部署、不播种、不迁移任何配置;运行时直接读取已安装组合包内config/pi-permission-policy.jsonc/config/pi-permission-hard-guards.jsonc;日志保留在<agentDir>/my-pi/permission-system/logs/。旧extensions/pi-permission-system/位置的残留文件被忽略,不迁移也不清理;项目级 policy 不读取。lsp.ts+lsp-config.ts:TypeScript/JavaScript 后端由根包固定依赖提供,用当前 Node 可执行文件直接启动包内typescript-language-serverCLI,不得依赖或调用 VS Code GUI;Kotlin/JDT LS 使用组合包部署的kotlin-lsp --stdio与jdtls配置,根包不安装这两个系统可执行文件。subagents.ts:pi-subagents 的组合包 wrapper,注入权威permission-system.ts的 canonical absolute path 为子会话 mandatory extension,并提供config/prompt/subagent/提示词画像(basePrompt+bundledAgentsDir)与excludedExtensionPaths(排除pi-ask-user);完整规则见pi-subagents/AGENTS.md。context-view.ts:只读的本地 effective-context observer(/context),只读取pi-compaction/src/service.ts发布的 projection metrics,不注册生产contextwriter;pi-minimal-footer优先显示同一 effective usage。.pi-debug/是/dump-system-prompt生成的本地诊断目录,不提交到仓库,也不作为组合包运行时配置源。
根目录 TypeScript 与 LSP 验证约定
- 根目录当前有意不安装 Pi runtime,也没有根级
tsconfig.json、devDependencies或@types/node;@earendil-works/pi-*只作为 optional host peer dependencies。TypeScript LSP 因而会把根目录.ts文件放入 inferred project,不能把宿主 Pi 的运行时解析能力等同于仓库内静态类型环境。 - 每个任务首次对相关根目录 TypeScript 文件调用
lsp_diagnostics时先建立并记录基线;后续只关注相对基线新增、消失或位置变化的诊断。文件和类型环境都未变化时不得重复调用 LSP 并重复报告同一组结果。 - 当前可预期的基线包括:宿主 peer 缺失导致的
TS2307(例如找不到@earendil-works/pi-coding-agent),Node 类型缺失导致的node:*/node:test/node:assertTS2591,以及由这些上游类型缺失级联产生的TS7006、TS18048、TS2722等。遇到级联错误时先确认其是否随缺失类型而产生,不要把它们直接归因于本次实现。 - 已知基线不等于忽略所有诊断:凡是无法由上述缺失依赖解释的新语法错误、结构类型错误、错误属性访问或本次修改所在代码的新诊断,必须修复并重新验证。交付时应把“已知类型环境基线”和“本次新增诊断”分开说明。
- 不得为了消除 LSP 基线而在根包安装第二套 Pi runtime、加入机器相关的宿主绝对路径或提交只在单机有效的
paths映射。若确需新增根级tsconfig.json、@types/node或其他开发类型环境,必须作为明确的仓库设计变更评估,并同步更新依赖、锁文件和本文档。 - 不要从泛型或重载的
ExtensionAPI方法直接用Parameters<...>猜取具体工具定义;解析失败时它可能退化为unknown。包装第三方工具时优先使用上游导出的具体类型;没有稳定导出时定义覆盖实际访问字段的最小结构类型,并用运行时集成测试验证。 node --test可直接测试仓库内的纯 TypeScript helper,但测试入口不得静态导入node_modules中的.ts;Node 原生 type stripping 会对这种路径报ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING。第三方 TypeScript 扩展 wrapper 应拆出本地纯 helper 做单元测试,并通过隔离的临时 Pi agent/jiti 加载验证真实扩展入口。- 对根目录扩展的最终验证优先组合使用:纯 helper 的
node --test、git diff --check、所需 npm 锁文件检查,以及隔离 Pi 环境的扩展加载。LSP 启动成功、单元测试通过和真实 Pi 加载通过是不同证据,不得互相替代或把类型环境基线误报为 LSP 后端启动失败。