@zihanw/pi-forge 0.5.3 → 0.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/README.md +67 -103
  3. package/README.zh-CN.md +67 -95
  4. package/assets/pi-forge-header-concept-1.png +0 -0
  5. package/assets/readme/PROVENANCE.md +95 -0
  6. package/assets/readme/en/capability-tools.gif +0 -0
  7. package/assets/readme/en/context-composition.gif +0 -0
  8. package/assets/readme/en/context-toggle.gif +0 -0
  9. package/assets/readme/en/draft-diff.png +0 -0
  10. package/assets/readme/en/edit-draft-diff.gif +0 -0
  11. package/assets/readme/en/editor-overview-v3.png +0 -0
  12. package/assets/readme/en/editor-overview.png +0 -0
  13. package/assets/readme/en/mode-tools.gif +0 -0
  14. package/assets/readme/en/regex-transforms.gif +0 -0
  15. package/assets/readme/en/tool-selection.gif +0 -0
  16. package/assets/readme/tui-quickstart.gif +0 -0
  17. package/assets/readme/zh-CN/capability-tools.gif +0 -0
  18. package/assets/readme/zh-CN/context-composition.gif +0 -0
  19. package/assets/readme/zh-CN/context-toggle.gif +0 -0
  20. package/assets/readme/zh-CN/draft-diff.png +0 -0
  21. package/assets/readme/zh-CN/edit-draft-diff.gif +0 -0
  22. package/assets/readme/zh-CN/editor-overview-v3.png +0 -0
  23. package/assets/readme/zh-CN/editor-overview.png +0 -0
  24. package/assets/readme/zh-CN/mode-tools.gif +0 -0
  25. package/assets/readme/zh-CN/regex-transforms.gif +0 -0
  26. package/assets/readme/zh-CN/tool-selection.gif +0 -0
  27. package/dist/active-state.d.ts +148 -0
  28. package/dist/active-state.d.ts.map +1 -0
  29. package/dist/active-state.js +374 -0
  30. package/dist/active-state.js.map +1 -0
  31. package/dist/agent-profile.d.ts.map +1 -1
  32. package/dist/agent-profile.js +11 -0
  33. package/dist/agent-profile.js.map +1 -1
  34. package/dist/capabilities.d.ts +39 -0
  35. package/dist/capabilities.d.ts.map +1 -0
  36. package/dist/capabilities.js +160 -0
  37. package/dist/capabilities.js.map +1 -0
  38. package/dist/capability-anchors.d.ts +45 -0
  39. package/dist/capability-anchors.d.ts.map +1 -0
  40. package/dist/capability-anchors.js +263 -0
  41. package/dist/capability-anchors.js.map +1 -0
  42. package/dist/capability-command.d.ts +4 -0
  43. package/dist/capability-command.d.ts.map +1 -0
  44. package/dist/capability-command.js +164 -0
  45. package/dist/capability-command.js.map +1 -0
  46. package/dist/capability-events.d.ts +79 -0
  47. package/dist/capability-events.d.ts.map +1 -0
  48. package/dist/capability-events.js +478 -0
  49. package/dist/capability-events.js.map +1 -0
  50. package/dist/capability-projection.d.ts +22 -0
  51. package/dist/capability-projection.d.ts.map +1 -0
  52. package/dist/capability-projection.js +273 -0
  53. package/dist/capability-projection.js.map +1 -0
  54. package/dist/capability-protocol.d.ts +21 -0
  55. package/dist/capability-protocol.d.ts.map +1 -0
  56. package/dist/capability-protocol.js +15 -0
  57. package/dist/capability-protocol.js.map +1 -0
  58. package/dist/capability-state.d.ts +74 -0
  59. package/dist/capability-state.d.ts.map +1 -0
  60. package/dist/capability-state.js +43 -0
  61. package/dist/capability-state.js.map +1 -0
  62. package/dist/capability-tool.d.ts +11 -0
  63. package/dist/capability-tool.d.ts.map +1 -0
  64. package/dist/capability-tool.js +25 -0
  65. package/dist/capability-tool.js.map +1 -0
  66. package/dist/capability-web-host.d.ts +11 -0
  67. package/dist/capability-web-host.d.ts.map +1 -0
  68. package/dist/capability-web-host.js +105 -0
  69. package/dist/capability-web-host.js.map +1 -0
  70. package/dist/codecs/capability.d.ts +71 -0
  71. package/dist/codecs/capability.d.ts.map +1 -0
  72. package/dist/codecs/capability.js +363 -0
  73. package/dist/codecs/capability.js.map +1 -0
  74. package/dist/codecs/prompt-stack.d.ts +1 -1
  75. package/dist/codecs/prompt-stack.d.ts.map +1 -1
  76. package/dist/codecs/prompt-stack.js +140 -13
  77. package/dist/codecs/prompt-stack.js.map +1 -1
  78. package/dist/command-contribution/index.d.ts +21 -0
  79. package/dist/command-contribution/index.d.ts.map +1 -0
  80. package/dist/command-contribution/index.js +14 -0
  81. package/dist/command-contribution/index.js.map +1 -0
  82. package/dist/compile-cycle.d.ts +7 -1
  83. package/dist/compile-cycle.d.ts.map +1 -1
  84. package/dist/compile-cycle.js +2 -0
  85. package/dist/compile-cycle.js.map +1 -1
  86. package/dist/compiler.d.ts +7 -1
  87. package/dist/compiler.d.ts.map +1 -1
  88. package/dist/compiler.js +140 -19
  89. package/dist/compiler.js.map +1 -1
  90. package/dist/context-diff-history.d.ts +2 -0
  91. package/dist/context-diff-history.d.ts.map +1 -1
  92. package/dist/context-diff-history.js +9 -0
  93. package/dist/context-diff-history.js.map +1 -1
  94. package/dist/forge-command.d.ts +10 -0
  95. package/dist/forge-command.d.ts.map +1 -0
  96. package/dist/forge-command.js +106 -0
  97. package/dist/forge-command.js.map +1 -0
  98. package/dist/index.d.ts +2 -2
  99. package/dist/index.d.ts.map +1 -1
  100. package/dist/index.js +58 -7
  101. package/dist/index.js.map +1 -1
  102. package/dist/json-fingerprint.d.ts +11 -0
  103. package/dist/json-fingerprint.d.ts.map +1 -0
  104. package/dist/json-fingerprint.js +66 -0
  105. package/dist/json-fingerprint.js.map +1 -0
  106. package/dist/lifecycle.d.ts +14 -0
  107. package/dist/lifecycle.d.ts.map +1 -1
  108. package/dist/lifecycle.js +175 -66
  109. package/dist/lifecycle.js.map +1 -1
  110. package/dist/payload-command.d.ts +2 -2
  111. package/dist/payload-command.d.ts.map +1 -1
  112. package/dist/payload-command.js +80 -26
  113. package/dist/payload-command.js.map +1 -1
  114. package/dist/payload-state.d.ts +1 -0
  115. package/dist/payload-state.d.ts.map +1 -1
  116. package/dist/payload-state.js +1 -0
  117. package/dist/payload-state.js.map +1 -1
  118. package/dist/policy.d.ts +2 -1
  119. package/dist/policy.d.ts.map +1 -1
  120. package/dist/policy.js +3 -0
  121. package/dist/policy.js.map +1 -1
  122. package/dist/preset-command.d.ts +2 -0
  123. package/dist/preset-command.d.ts.map +1 -1
  124. package/dist/preset-command.js +101 -36
  125. package/dist/preset-command.js.map +1 -1
  126. package/dist/preview-text.d.ts +5 -0
  127. package/dist/preview-text.d.ts.map +1 -0
  128. package/dist/preview-text.js +27 -0
  129. package/dist/preview-text.js.map +1 -0
  130. package/dist/preview.d.ts +18 -1
  131. package/dist/preview.d.ts.map +1 -1
  132. package/dist/preview.js +134 -99
  133. package/dist/preview.js.map +1 -1
  134. package/dist/profile-command.d.ts +4 -1
  135. package/dist/profile-command.d.ts.map +1 -1
  136. package/dist/profile-command.js +77 -14
  137. package/dist/profile-command.js.map +1 -1
  138. package/dist/prompt-cache-warning.d.ts +23 -0
  139. package/dist/prompt-cache-warning.d.ts.map +1 -0
  140. package/dist/prompt-cache-warning.js +74 -0
  141. package/dist/prompt-cache-warning.js.map +1 -0
  142. package/dist/regex.d.ts.map +1 -1
  143. package/dist/regex.js +5 -0
  144. package/dist/regex.js.map +1 -1
  145. package/dist/render-helpers.d.ts.map +1 -1
  146. package/dist/render-helpers.js +2 -0
  147. package/dist/render-helpers.js.map +1 -1
  148. package/dist/repositories/capability.d.ts +53 -0
  149. package/dist/repositories/capability.d.ts.map +1 -0
  150. package/dist/repositories/capability.js +294 -0
  151. package/dist/repositories/capability.js.map +1 -0
  152. package/dist/runtime/capability-runtime.d.ts +91 -0
  153. package/dist/runtime/capability-runtime.d.ts.map +1 -0
  154. package/dist/runtime/capability-runtime.js +967 -0
  155. package/dist/runtime/capability-runtime.js.map +1 -0
  156. package/dist/runtime/tool-policy-runtime.d.ts +8 -0
  157. package/dist/runtime/tool-policy-runtime.d.ts.map +1 -1
  158. package/dist/runtime/tool-policy-runtime.js +171 -30
  159. package/dist/runtime/tool-policy-runtime.js.map +1 -1
  160. package/dist/session-adapter.d.ts +13 -0
  161. package/dist/session-adapter.d.ts.map +1 -1
  162. package/dist/session-adapter.js +110 -0
  163. package/dist/session-adapter.js.map +1 -1
  164. package/dist/session-usage.d.ts +65 -0
  165. package/dist/session-usage.d.ts.map +1 -0
  166. package/dist/session-usage.js +134 -0
  167. package/dist/session-usage.js.map +1 -0
  168. package/dist/subagent/fingerprints.d.ts +3 -15
  169. package/dist/subagent/fingerprints.d.ts.map +1 -1
  170. package/dist/subagent/fingerprints.js +5 -69
  171. package/dist/subagent/fingerprints.js.map +1 -1
  172. package/dist/subagent/index.d.ts +2 -0
  173. package/dist/subagent/index.d.ts.map +1 -1
  174. package/dist/subagent/index.js +2 -0
  175. package/dist/subagent/index.js.map +1 -1
  176. package/dist/subagent-host.d.ts +2 -2
  177. package/dist/subagent-host.d.ts.map +1 -1
  178. package/dist/subagent-host.js +13 -1
  179. package/dist/subagent-host.js.map +1 -1
  180. package/dist/types.d.ts +6 -1
  181. package/dist/types.d.ts.map +1 -1
  182. package/dist/types.js.map +1 -1
  183. package/dist/web-editor/client-script.generated.d.ts.map +1 -1
  184. package/dist/web-editor/client-script.generated.js +1 -1
  185. package/dist/web-editor/client-script.generated.js.map +1 -1
  186. package/dist/web-editor/client-styles.generated.d.ts.map +1 -1
  187. package/dist/web-editor/client-styles.generated.js +1 -1
  188. package/dist/web-editor/client-styles.generated.js.map +1 -1
  189. package/dist/web-editor/server.d.ts.map +1 -1
  190. package/dist/web-editor/server.js +152 -4
  191. package/dist/web-editor/server.js.map +1 -1
  192. package/dist/web-editor/styles.d.ts.map +1 -1
  193. package/dist/web-editor/styles.js +521 -116
  194. package/dist/web-editor/styles.js.map +1 -1
  195. package/dist/web-editor/types.d.ts +81 -1
  196. package/dist/web-editor/types.d.ts.map +1 -1
  197. package/dist/web-host.d.ts +7 -0
  198. package/dist/web-host.d.ts.map +1 -1
  199. package/dist/web-host.js +168 -5
  200. package/dist/web-host.js.map +1 -1
  201. package/dist/workspace.d.ts +11 -0
  202. package/dist/workspace.d.ts.map +1 -1
  203. package/dist/workspace.js +63 -5
  204. package/dist/workspace.js.map +1 -1
  205. package/docs/README.md +4 -0
  206. package/docs/design/README.md +3 -1
  207. package/docs/design/architecture-0.5.md +22 -0
  208. package/docs/design/archive/2026-09-12-system-update-design.md +229 -0
  209. package/docs/design/pi-forge-system-update-design-notes.md +157 -0
  210. package/docs/development/release.md +20 -20
  211. package/docs/development/roadmap.md +17 -2
  212. package/docs/development/scoped-global-profiles-stacks.md +1 -1
  213. package/docs/development/setup.md +1 -1
  214. package/docs/getting-started.md +1 -1
  215. package/docs/guides/delegation.md +22 -20
  216. package/docs/guides/migrating-to-0.5.md +29 -0
  217. package/docs/guides/use-cases.md +6 -2
  218. package/docs/guides/web-editor.md +73 -5
  219. package/docs/reference/active-state.md +77 -0
  220. package/docs/reference/capabilities.md +259 -0
  221. package/docs/reference/commands.md +52 -24
  222. package/docs/reference/configuration.md +4 -2
  223. package/docs/reference/features.md +70 -4
  224. package/docs/reference/provider-support.md +67 -0
  225. package/docs/reference/public-api.md +49 -3
  226. package/docs/reference/session-cache.md +112 -0
  227. package/docs/reference/stack-schema.md +18 -4
  228. package/docs/reference/subagent-host-port.md +8 -0
  229. package/docs/zh-CN/README.md +3 -0
  230. package/docs/zh-CN/getting-started.md +1 -1
  231. package/docs/zh-CN/guides/delegation.md +22 -10
  232. package/docs/zh-CN/guides/migrating-to-0.5.md +29 -0
  233. package/docs/zh-CN/guides/web-editor.md +74 -7
  234. package/docs/zh-CN/reference/capabilities.md +259 -0
  235. package/docs/zh-CN/reference/commands.md +61 -33
  236. package/docs/zh-CN/reference/provider-support.md +67 -0
  237. package/docs/zh-CN/reference/session-cache.md +112 -0
  238. package/examples/capabilities/review.json +12 -0
  239. package/examples/capabilities/write-tools.json +15 -0
  240. package/examples/read-first-worker-prompt-stack.json +49 -0
  241. package/package.json +16 -9
@@ -10,7 +10,7 @@
10
10
 
11
11
  `/preset ui restart` 会替换 server,`/preset ui stop` 会关闭它。
12
12
 
13
- 编辑器绑定在带 session token 的可用 `127.0.0.1` 端口;多个项目可以同时运行。读取、预览和 payload 检查在合适范围内可用;写入要求 Pi 信任项目,并且文件被限制在 Pi Forge 的预设/Profile 存储内。可以在 `.pi/forge/config.json` 中设置偏好端口:
13
+ 编辑器绑定在带 session token 的可用 `127.0.0.1` 端口;多个项目可以同时运行。读取、预览和 payload 检查在合适范围内可用;写入要求 Pi 信任项目,内置 Web 写入被限制在 Pi Forge 的预设/Profile、Capability 和可信 Forge 配置存储内。可以在 `.pi/forge/config.json` 中设置偏好端口:
14
14
 
15
15
  ```json
16
16
  {
@@ -28,22 +28,89 @@
28
28
 
29
29
  支持:
30
30
 
31
- - 从默认 Pi mirror 新建预设;
32
- - 在 **堆栈** tab 中编排有序的 Block/Slot;
33
- - 结构化和原始 JSON 编辑;
31
+ - 从模板新建预设(默认 Pi 提示词镜像、空白预设、极简工作者);
32
+ - 在 **堆栈**(Stack)tab 中编排有序的 Block/Slot;
33
+ - 在 **策略**(Policy)tab 中配置工具与技能的 allow/deny 资源策略及自定义默认工具(`tools.initial`);
34
+ - 在独立的同级 **能力绑定**(Capability bindings)tab 中关联能力(Preset 元数据面板不再包含绑定);
35
+ - 结构化元数据、参数、上下文以及 **Regex** 规则编辑;
34
36
  - 拖拽排序、启用/禁用、校验和完整编译预览;
35
37
  - 工具/skill 搜索、精确名称 chips 和通配符策略;
36
- - variables、context 和 regex 规则;
37
38
  - 原生 pi-forge JSON 导入;
38
39
  - 导出、fork、删除和 payload 捕获。
39
40
 
40
- 已有 ID 在编辑时不可修改;需要新 ID 时使用 **Fork**,避免破坏 Profile 引用和当前选择。工具栏的 scope 下拉(默认 `project`)决定新建、导入和 fork 的写入位置:选择 `global` 写入用户全局 `~/.pi/forge/prompt-stacks`,选择 `project` 写入项目 `.pi/forge/prompt-stacks`;这些目录名在 0.5.3 中为兼容性暂时保留。列表会为全局预设显示 `global` badge;保存和删除通过 `global:<id>` 路由精确作用于全局文件。保存、导入、fork 和删除后会重新加载当前 Pi session。
41
+ ### 编辑与检查
42
+
43
+ 资源标题区区分“正在编辑哪份预设”与“它是否已在会话中启用”。切换页面时,全局会话指令摘要仍然可见。打开预设属性、条目属性、规则卡片或绑定详情,不会修改草稿。**预设属性**从资源标题区打开,不再推挤正文;字段修改仍归同一份预设草稿,须显式保存。全局会话指令保留紧凑摘要,操作区进入独立、非模态的**当前会话**工作区,不与编辑中的资源混淆。生效工具、指令摘要、活动能力与启用操作优先;完整指令正文、会话身份和传输详情按需展开;信任/过期/错误和 pending/prepared 警告仍直接可见。预设状态反馈放在页脚;其中的停用仍针对当前生效预设,不是选中的草稿。
44
+
45
+ - **堆栈:** 列表显示名称/开关与一行摘要,如 `user · report` 或 `slot · chat-history`。完整身份保留在提示与**属性**内,可复制 ID;Role、插槽选择与属性同排,正文紧接其后。支持 Enter/空格选择及拖拽;标题旁保留低强调的直接删除按钮与确认。插槽参数按内容高度排列,不再把几行选项纵向撑满。
46
+ - **正则:** 先浏览规则名称、启用状态、阶段/效果与表达式摘要,再展开编辑。表达式与替换正文直接可见,频率、目标、角色和范围限制在高级区。列表末尾的虚线入口添加并聚焦新规则;规则/绑定移除需确认,仍是草稿改动,通过预设的**保存**按钮写入。
47
+ - **策略:** 许可上限与默认工具分成两张卡;字面量/通配符输入收在高级区,技能列表可见性另列,不能当作执行沙箱。
48
+ - **预览/草稿差异/运行差异:** 预览是独立工作区开关,开关或切换编辑页签都保留当前编辑页。边界尖角把侧栏加宽;加宽时分别提供“收窄”和“专注”两个按钮,退出专注恢复之前的非专注布局并保留检查页签,不替换草稿。专注时点击其他编辑页签会露出编辑区并保留预览。面板首次默认侧栏。切换预览、草稿差异或运行差异时只切换内容,保留当前宽度和专注状态;专注阅读需手动进入。窄窗口改为上下布局,避免硬挤四列;专注阅读时暂时隐藏编辑区,返回或选择编辑页签后恢复。草稿差异比较草稿编译结果与已保存定义;运行差异比较捕获的提供商轮次快照。查看本身不请求模型,也不证明缓存命中。
49
+
50
+ Profile 编辑按 Provider/Model、Thinking/Preset 分组,不可变身份在标题处显示;Profile 与 Capability 创建时仍明确选择 ID 与作用域。预设高级页把可编辑参数放在折叠的扩展参考目录之前。预览工具详情按需展开,段落统计可在标题提示中查看。
51
+
52
+ 插件贡献的**设置**页自动保存,并反馈待保存/保存中/已保存/失败;保存失败的编辑会留在表单。预设、能力与 Profile 仍使用显式保存。
53
+
54
+ ### 检查能力对上下文的影响
55
+
56
+ **当前会话**工作区左侧是能力与工具控制,右侧是会话投影,窄屏上下排列。当前生效工具和活动指令摘要直接可见。在本页面成功启用、停用或重置后,还显示操作前后实际观测到的工具增减;这不是持久历史。能力**配置的工具调整**另行标注:多个能力重叠作用时,实际工具可能完全不变。
57
+
58
+ 点击**在上下文中定位**,控制区保持可见,右侧高亮关联更新并滚到最近匹配;普通更新不抢阅读位置。这里检查的是**已启用的已保存预设+当前会话能力**,不是编辑器选中的任意预设。原预设编辑页仍能一边编辑,一边查看**预览/草稿差异/运行差异**;跨工作区保留草稿、选择、检查页签及宽度/专注状态。
59
+
60
+ 后台状态检查静默进行,不再每轮读取能力目录或让可用控件闪成禁用态。目录在进入工作区、主动刷新及相关操作后读取;返回时废弃上一轮迟到读取,但不丢弃正在进行的写操作回执。投影由状态的实际变化驱动,不另开轮询;同分支刷新暂保留并明确标注上次投影,过期/不可信或会话/分支切换时使旧结果失效。
61
+
62
+ 块序号只对该次预览有效。原生 System 分段与归属明确的 user fallback 保留实际角色;停用不会抹去此前的更新。没有可靠匹配时会明确提示,不猜测位置。第一版要求可信会话与已启用预设,尚不提供完整的启停事件历史浏览。
63
+
64
+ 检查只是本地读取,不准备/投递请求,不改变工具或会话历史。它不是已捕获的提供商 payload,也不能证明缓存复用;实际请求差异与 usage 请分别看 Run diff/Payload 和提供商返回的数据。
65
+
66
+ ### 工具选择与默认工具编辑器
67
+
68
+ **策略**(Policy)tab 提供可选的自定义默认工具编辑器(`tools.initial?: string[]`):
69
+
70
+ - **默认工具选择器:** 提供基于 SDK `sourceInfo`(Pi 内置工具、扩展包工具及顶层入口点)的可折叠、可搜索分组选择器。分组复选框批量选择/取消当前筛选结果;**手动输入工具名**保留字面量/离线名称入口,能力编辑器也使用同一入口。
71
+ - **确切工具名称:** 选择器保存具体的工具名称;不持久化包引用,不自动安装依赖包,扩展包后续新增的工具也不会被自动加入。未激活但已注册的工具在选择器中可见;未加载的工具在当前会话不可用,但手动保存的引用不会被丢弃。
72
+ - **缺省与零默认工具:** 缺省不配置 `tools.initial` 时保持传统行为(选择性 allow 匹配已注册目录;不限/deny 保留或过滤会话基线,不会全选目录);显式配置为空列表 `[]` 时,默认激活零个工具。
73
+ - **权威上限:** 保留高级字面量与通配符 allow/deny 策略作为权威上限;被 allow/deny 拦截的工具无法作为默认工具生效。
74
+ - **运行时生命周期:** 配置的默认工具在预设处于激活状态期间作为常态基准(并非每轮一次性重置)。停用能力后按默认工具与剩余能力重新计算;停用预设恢复经外部变更协调的会话基线,切换预设则按新预设与保留的非绑定能力计算。
75
+
76
+ ### 能力绑定 tab
77
+
78
+ 能力绑定在独立的同级 **能力绑定**(Capability bindings)tab 中管理:
79
+
80
+ - 每张绑定卡片只显示一次带作用域的能力引用,以及“允许模型启用”授权开关;绑定 ID 收入详情,不再常驻卡头。
81
+ - **高级选项**(Advanced)展开绑定 ID 与覆盖项(正文替换/追加、工具增加/移除);源定义/生效值实时对比有独立展开入口。
82
+ - 工具覆盖选择**继承**或**自定义覆盖**,配备与策略页面一致的分组选择器。自定义允许空列表:`[]` 将原能力对应的添加/移除列表覆盖为空;继承则不写覆盖字段。这不是清空所有会话工具,也不绕过其他权限限制。
83
+ - 绑定排列只决定目录顺序,不是执行优先级,因此编辑器不再提供上下按钮。直接移除仍需确认,并随外层预设保存;删除其他绑定不会让当前展开的详情跑到别的条目。
84
+
85
+ ### 保存行为与执行影响
86
+
87
+ **激活**使用已保存的预设;草稿有未保存修改时暂不可用,须先显式保存。保存与激活不是一个合并事务。
88
+
89
+ - **能力界面:** 保存能力仅更新能力库文件定义,绝不会在当前会话中自动启用该能力。
90
+ - **预设编辑:** 保存**未激活**的 Preset 仅更新其磁盘文件,不会选中或激活它;**关键**:保存**当前已激活**的 Preset 会立即刷新其实时工具策略与能力授权,但不会替换已冻结的活动能力快照。
91
+
92
+ 已有 ID 在编辑时不可修改;需要新 ID 时使用 **Fork**,避免破坏 Profile 引用和当前选择。新建、导入和 fork 的小表单在写入前一起确认名称、ID 与目标 scope(默认 `project`):选择 `global` 写入用户全局 `~/.pi/forge/prompt-stacks`, 选择 `project` 写入项目 `.pi/forge/prompt-stacks`;这些目录名在 0.5.3 中为兼容性暂时保留。
93
+
94
+ **新建预设**对话框提供三种起始模板:
95
+ - **默认 Pi 提示词:** 完整镜像所有默认块与插槽,保留可移动的工具、规范、文档、项目上下文、技能与聊天历史;
96
+ - **空白预设:** 条目为空(`items: []`),不设置工具或技能策略;此时 Pi 会自动保留其基础系统提示词与历史记录(并非零上下文或无工具);
97
+ - **极简工作者:** 匹配 `examples/minimal-prompt-stack.json` 的极简结构:包含单行系统提示词(“You are a helpful software engineer assistant.”)、关闭摘要的聊天历史,并仅限使用 `bash` 与 `edit` 工具。
98
+
99
+ 选择模板会自动同步更新建议名称(只要用户未手动修改过名称)。导入与 Fork 对话框不显示模板选择器,继续使用导入内容或当前载入的源预设,不套用新建模板。
100
+
101
+ 预设列表下方放置虚线新建入口,条目列表下方通过“添加内容/插槽”选择 Block 或 Slot。列表会为全局预设显示 `global` badge;保存和删除通过 `global:<id>` 路由精确作用于全局文件。保存、导入、fork 和删除后会刷新当前 Pi 会话中的 Forge 资源,不重启 Pi 进程。
102
+
103
+ ### 兼容性说明
104
+
105
+ 使用 `tools.initial` 的预设需要新版 Forge 支持。旧版 Forge 可能忽略 `tools.initial` 并恢复旧选择逻辑(选择性 allow 匹配目录,不限/deny 保留或过滤会话基线)(不支持向下降级兼容)。这些变化需要 Forge 0.5.5;宿主要求保持 Pi `>=0.87.0 <0.88.0` 不变。
41
106
 
42
107
  ## Agent profile 工作区
43
108
 
44
109
  列表显示 Profile ID、名称、模型、思考等级、预设、校验状态、auto-activation 和 last-applied provenance。每个 Profile 都带 `project` / `global` scope badge;同 ID 的 shadow 对会显示 `shadows global:<id>` 或 `shadowed by project:<id>`。
45
110
 
46
- 可信项目通过 **New profile** 旁的 scope 下拉(默认 `project`)选择目标 scope:选择 `global` 写入用户全局 `~/.pi/forge/agent-profiles`,选择 `project` 写入项目 `.pi/forge/agent-profiles`。全局 Profile 可通过显式 `global:<id>` 路由编辑、校验、保存、一次性应用和删除;未限定路由始终只作用于项目资源。编辑全局 Profile 时,预设下拉只显示全局预设。Model 选项来自 Pi registry,thinking 选项反映模型支持,预设选项来自同一个 repository。编辑器会拒绝同 scope 内第二个 auto-activation Profile。
111
+ Profile/Capability 库把虚线新建入口放在资源列表下方;创建编辑器名称优先,作用域只在表单内选择一次,保留必要的模型/正文编辑,不为列表占位提前写入不完整资源。
112
+
113
+ 可信项目通过创建表单内的 scope 字段(默认 `project`)选择目标 scope:选择 `global` 写入用户全局 `~/.pi/forge/agent-profiles`,选择 `project` 写入项目 `.pi/forge/agent-profiles`。全局 Profile 可通过显式 `global:<id>` 路由编辑、校验、保存、一次性应用和删除;未限定路由始终只作用于项目资源。编辑全局 Profile 时,预设下拉只显示全局预设。Model 选项来自 Pi registry,thinking 选项反映模型支持,预设选项来自同一个 repository。编辑器会拒绝同 scope 内第二个 auto-activation Profile。
47
114
 
48
115
  ## Delegation
49
116
 
@@ -0,0 +1,259 @@
1
+ # 能力(`/capability`)
2
+
3
+ [中文文档](../README.md) · [English](../../reference/capabilities.md)
4
+
5
+ Pi-forge 引入了能力(Capabilities):会话级动态提示词指令与动态工具门控。`/capability` 是 CLI 命令名。本文档涵盖能力配置、所有权作用域、CLI 操作、Web 资源编辑、Preset 授权与 Agent 控制、投递模型、状态恢复边界与兼容性限制。
6
+
7
+ ## 环境要求与安装
8
+
9
+ - **宿主版本:** Pi `>=0.87.0 <0.88.0`(仓库开发 SDK 固定为 `0.87.0`,peer 范围为 `>=0.87.0 <0.88.0`;最低 SDK 0.87 保持不变;不声称对 0.86 的双重运行时支持)。能力功能需要 Forge 0.5.5。
10
+ - **项目信任:** 激活能力、预设绑定或添加手动指令需要项目处于受信任状态(`isProjectTrusted()`)。
11
+ - **兼容性限制:** 包含 `tools.initial` 的配置需要新版 Forge 支持;旧版 Forge 会忽略 `initial`,因而配置不具备向下降级兼容性。
12
+
13
+ 能力为 JSON 文件,存放在以下目录之一:
14
+
15
+ - **项目目录:** `.pi/forge/capabilities/<id>.json`
16
+ - **全局目录:** `~/.pi/forge/capabilities/<id>.json`
17
+
18
+ ```json
19
+ {
20
+ "schemaVersion": 1,
21
+ "type": "pi-forge.capability",
22
+ "id": "review",
23
+ "name": "Review",
24
+ "description": "Report findings and evidence before editing.",
25
+ "content": "List findings, evidence, and risks. Do not directly edit files.",
26
+ "tools": {
27
+ "add": [],
28
+ "remove": ["bash", "powershell", "write", "edit"]
29
+ }
30
+ }
31
+ ```
32
+
33
+ ### 资源规则
34
+
35
+ - **纯字面内容:** `content` 严格按字面文本处理(上限 100,000 字符),非文件路径、脚本或宏,不会展开模板变量。
36
+ - **工具名称:** `add` 与 `remove` 数组中的工具名必须为确切标识符(上限 128 字符,无空白符、控制符或 `*`/`?` 通配符,每个数组限 256 个工具)。
37
+ - **工具补丁约束:** 能力仅支持 `add` 与 `remove`;候选的 `only` 或能力级 allowlist 未实现。
38
+ - **解析与遮蔽:** 裸 ID 采用“项目优先于全局”的查找逻辑。若项目存在损坏或非法的 JSON,解析直接在本地报错(fail-closed),绝不静默回退到全局同名定义。可通过 `project:<id>` 或 `global:<id>` 指定明确 scope。
39
+
40
+ ## 所有权作用域与生命周期
41
+
42
+ - **所有权划分:** 能力定义(capabilities)为可复用资源,归属于项目或全局库;绑定与授权归属于预设(Preset JSON 顶层的 `capabilities` 数组);活跃状态与激活项严格归属于会话(Session)。
43
+ - **直接启用 vs 绑定启用:**
44
+ - 通过 CLI 直接激活(`/capability enable <[scope:]id>`)或 Web 能力库直接启用,创建的是会话中的**未绑定**活动项。
45
+ - 通过 CLI 绑定激活(`/capability enable-bound <id>`)或 Web 预设绑定启用,创建的是与当前 Preset 关联的**绑定**活动项。
46
+ - **不可变快照语义:** 激活时捕获不可变快照(包括内容、工具策略、内容指纹)。修改或删除磁盘上的 JSON 文件不会引发活跃会话漂移。
47
+ - **同 Preset 重载 vs 切换 Preset:** 重新加载同一 Preset 保持既有的冻结活动快照;切换 Preset 会自动停用(lifecycle 停用)旧 Preset 关联的绑定项,同时保留手动输入与未绑定的用户规则。
48
+ - **授权撤销行为:** 在 Preset 中撤销授权(将 `modelCallable` 设为 `false`)或删除绑定项,不会追溯抹除已激活的快照;用户通过 CLI(`/capability disable` 或 `/capability reset`)或 Web 面板停用是标准恢复路径。
49
+ - **用户与 Agent 所有权及去重:** 激活项记录归属主体(`user` 或 `agent`)。重复 `enable` 已激活的能力具备幂等性,绝不自动在用户与 Agent 之间转移所有权(takeover)。接管必须通过显式关闭后再重新启用。
50
+
51
+ ## Preset 授权的 Agent 控制
52
+
53
+ Preset 的 `capabilities` 绑定支持智能体自主选择与启用能力:
54
+
55
+ - **模型工具注册:** `forge_capability` 以固定 schema 注册一次,可见性遵循普通可执行工具选择;注册本身不授予能力权限。调用要求存在活跃 Preset,enable/disable 还会重查具体绑定的当前授权。
56
+ - **显式授权机制:** 仅当活跃 Preset 中的绑定显式声明 `modelCallable: true` 时,Agent 才能调用;缺省默认为 `false`。
57
+ - **固定参数契约:** 仅接受 `{ action: "list" | "status" | "enable" | "disable", id?: string }`(ID 上限 128 字符)。
58
+ - `list`:列出当前活跃 Preset 中具备调用资格的绑定能力;活动快照由 `status` 查看。
59
+ - `status`:返回当前会话的激活数量、呈现形式、投递状态及生效工具列表。
60
+ - `enable`:需要提供绑定的 `id`;仅可激活已授权且 `modelCallable: true` 的预设绑定能力。
61
+ - `disable`:需要提供 `id`(绑定 ID 或激活 UUID);仅可关闭归属于 `agent` 的激活项。
62
+ - **安全与权限边界:**
63
+ - 每次调用均重新校验项目信任、活跃 Preset 状态、绑定标识、`modelCallable: true` 以及当前工具策略。
64
+ - Agent 无法关闭用户启用的指令或手动指令。
65
+ - Agent 无法执行 `reset` 操作,也无法添加任意提示词文本。
66
+ - Agent 无法激活会移除 `forge_capability` 工具自身的能力。
67
+ - 在运行时已注销、正在恢复或会话上下文不一致时,调用直接 fail-closed 报错。
68
+
69
+ Agent 的 list/status 回复不复制完整规则正文:list 提供作者填写的描述与效果,status 提供活动元数据,避免把仅请求内投影的规则再次塞进普通工具历史和后续摘要。人类 CLI/Web 仍可查看完整冻结正文;真实对话及作者填写的描述不会被过滤。
70
+
71
+ ### Read-first Worker
72
+
73
+ 一个最小主包示例:[预设](../../../examples/read-first-worker-prompt-stack.json)+[Write tools 能力](../../../examples/capabilities/write-tools.json)。使用 Forge 0.5.5;旧发布版可能忽略 `tools.initial`。可选 subagent 执行仍是独立且尚未完成的 release。
74
+
75
+ 1. 在可信的临时项目中,将预设复制为 `.pi/forge/prompt-stacks/read-first-worker.json`,能力复制为 `.pi/forge/capabilities/write-tools.json`。先检查是否已有同名文件,不覆盖自己的资源。仅导入预设不会顺带安装引用的能力。
76
+ 2. 用已加载 Forge 的全新 Pi 会话,执行 `/preset reload`,再执行 `/preset use project:read-first-worker`。示例 `autoActivate: false`,绑定明确指向**项目作用域**;放到全局时,能力也须放全局并修改 `ref`。
77
+ 3. 没有其他活动能力时,默认工具只有 `read`、`ls` 与 `forge_capability`;后者是能力管理工具,不是文件写入工具。模型可用 `{ "action": "list" }` 列出授权绑定,以 `{ "action": "enable", "id": "write-tools" }` 启用命令/编辑能力,再以 `{ "action": "disable", "id": "write-tools" }` 停用自己的激活项。
78
+ 4. 在**当前会话**或 `/capability status` 观察:`read, ls, forge_capability` → 增加 `bash, edit` → 回到默认集。其他活动能力仍参与计算。若由人类启用,模型不能关闭该人类拥有的激活项,应从界面或 `/capability disable <activation-id>` 停用。
79
+
80
+ `allow` 是许可上限,`initial` 是默认集,`modelCallable: true` 明确允许模型选择该绑定,**不是每次启用都弹出人类审批**。若希望仅人类启用,将它改为 `false`。示例提示词要求任务结束后关闭,但这不是自动生命周期保证;Off 不撤销文件修改,也不终止运行中的工具。**Read-first 不是只读沙箱:** `bash` 能执行任意命令,而不只是写文件;这些配置不提供文件系统/进程隔离。为保持最小风格,替换提示词省略了 Pi 默认的项目上下文、技能和工具指导插槽;需要这些内容时请从默认 Pi mirror 改起。
81
+
82
+ ## 命令行操作
83
+
84
+ 通过 `/capability` 管理会话指令:
85
+
86
+ | 命令 | 行为 |
87
+ |---|---|
88
+ | `/capability list` | 显式重新发现能力库,并列出项目与全局能力及校验状态。 |
89
+ | `/capability bindings` | 列出当前活跃 Preset 的能力绑定,包括人类专用绑定。 |
90
+ | `/capability enable <[scope:]id>` | 激活指定的未绑定能力(裸 ID 或限定作用域)。直接 enable 保持未绑定。 |
91
+ | `/capability enable-bound <id>` | 按绑定 ID 激活当前 Preset 中已绑定的能力。 |
92
+ | `/capability status` | 显示激活能力数量、投递表现形式、投递状态以及当前选中的工具。 |
93
+ | `/capability disable <activation-or-capability-id>` | 通过激活 UUID 或能力 ID 关闭激活的能力。 |
94
+ | `/capability reset` | 关闭当前会话所有激活的能力与手动指令(仅限用户)。 |
95
+ | `/capability add <text>` | 向当前会话追加一条手动字面指令(无工具变更)。 |
96
+ | `/capability help` | 显示命令用法与兼容性说明。 |
97
+
98
+ 补全使用当前 session 与最近发布的 workspace snapshot,不会在每次按键时扫描资源。需要显式刷新发现时使用 `/capability list`。`/capability enable` 补全在唯一时提供裸 ID,在同名冲突或键入 `:` 作用域前缀时提供限定作用域的选择器(标签始终保留来源与名称限定)。`bindings` 仍显示人类专用绑定;`modelCallable: false` 只禁止 Agent 控制,不会把绑定从人类检查或启用列表中过滤掉。
99
+
100
+ **零推理成本:** 所有 `/capability` 斜杠命令与 Web 活动面板操作均在本地执行,仅更新内部会话状态并同步工具策略,操作本身不调用模型推理,不消耗付费 token。活动指令的规则正文仅在随后的真实模型请求中占用输入 token。
101
+
102
+ ## Web 资源编辑
103
+
104
+ ### 能力管理界面(Capabilities CRUD)
105
+
106
+ 顶部导航栏的**能力**(Capabilities)页面提供项目与全局能力的完整生命周期管理。能力库 API 为 `GET /api/capabilities`,选择器与 effective 变体为 `/api/capabilities/<selector>` 和 `/api/capabilities/effective`:
107
+
108
+ - **浏览与审查:** 查看能力 ID、显示名称、描述、指令正文及工具变更(`+add`、`-remove`),并显示校验诊断。
109
+ - **新建:** 在明确的项目作用域(`.pi/forge/capabilities/`)或全局作用域(`~/.pi/forge/capabilities/`)下创建新能力。
110
+ - **编辑与保存:** 编辑显示名称、描述、指令正文与工具增删项。能力 ID 在保存时不可修改。
111
+ - **分组工具选择器:** 能力工具选择(`+add` / `-remove`)提供基于 SDK `sourceInfo`(Pi 内置工具、扩展包工具及顶层入口点)的分组选择器。选择器保存具体确切的工具名称(EXACT concrete tool names):不持久化包引用,不自动安装依赖包,外部包新增的工具也不会自动加入。未激活但已注册的工具在选择器中可见;未加载的工具在当前会话不可用,但手动保存的引用不会被丢弃。
112
+ - **删除:** 支持在二次确认后删除磁盘上的能力 JSON 文件。
113
+ - **版本防脏写(`sourceRevision`):** 保存与删除操作强制校验界面加载时的源文件哈希版本(`sourceRevision`)。并发修改导致版本过期时返回 `409 Conflict` 并完整保留本地编辑草稿。
114
+ - **资源安全与保存执行影响:** 保存能力仅更新能力库定义,绝不自动将其激活到活跃会话中。非法 JSON fail-closed 本地报错;符号链接目录与目标不可写入。
115
+
116
+ ### Preset 能力绑定 tab
117
+
118
+ 在 Preset 编辑器中,能力绑定现已独立为同级的“**能力绑定**”(`bindings`)tab;Preset 元数据面板不再包含绑定:
119
+
120
+ - **限定引用:** 必须使用限定作用域引用(`project:<id>` 或 `global:<id>`)。
121
+ - **绑定 ID 与元数据:** 在 Preset 内唯一定义的绑定标识符(上限 128 字符)。
122
+ - **Agent 授权:** 勾选 `modelCallable` 开关(默认关闭),允许智能体通过 `forge_capability` 自主调用。
123
+ - **折叠的高级选项:** 覆盖项与源定义/有效值对比预览默认折叠在高级选项(Advanced)中,保持主列表清爽。
124
+ - **有限覆盖(Finite Overrides):**
125
+ - **正文覆盖:** 可选*无(沿用源内容)*、*替换*(`content`)或*追加*(`appendContent`,以双换行追加)。
126
+ - **工具覆盖:** `tools.add` 与 `tools.remove` 分别选择*继承*(省略字段)或*自定义覆盖*(字面工具列表,允许显式 `[]` 清空源定义该项),并使用集成分组工具选择器。
127
+ - 不支持注入任意自定义字段、脚本或继承链。
128
+ - **源定义与有效值对比预览:** 左右对比分栏实时展示源定义的正文/工具与覆盖生效后的有效正文/工具,复用服务端与运行时完全一致的解析器(`resolveCapabilityBindings`)。
129
+ - **防脏写保护:** 当 Preset 包含或修改绑定时,保存请求强制校验磁盘源版本(`sourceRevision`),防止覆盖外部并发编辑或新增的绑定(409 Conflict)。
130
+ - **Preset 保存执行影响:** 保存未激活的 Preset 仅更新其定义,绝不会选中或激活它;**关键**:保存当前已激活的 Preset 会立即重载并同步其实时工具策略与能力授权,但不会替换已冻结的活动能力快照。
131
+
132
+ ## Web 会话能力面板
133
+
134
+ Web 编辑器保留全局**会话能力**(Session capabilities)摘要,入口进入非模态的**当前会话**工作区:左侧能力/工具控制,右侧当前会话投影。预设编辑页仍保留独立的 Preview/Draft diff/Run diff;跨工作区保留未保存编辑和检查布局。
135
+
136
+ ### 面板功能与状态展示
137
+
138
+ - **活动能力列表:** 展示当前会话处于活动状态的所有能力与手动指令。每个卡片呈现:
139
+ - **标识与来源:** 激活 ID、显示名称以及解析来源(如 `project:review`、`global:review` 或 `manual`)。
140
+ - **开启者:** 标明由用户(`user`)还是智能体(`agent`)启用。
141
+ - **冻结正文快照:** 默认显示摘要,可展开查看激活时捕获的完整规则字面内容(frozen snapshot)。
142
+ - **工具调整与生效工具:** 卡片明确区分配置的工具补丁与当前生效工具;本页面最近一次成功操作显示实际净增减,多个能力重叠时生效集可能不变。
143
+ - **投递与呈现状态:**
144
+ - **投递状态:** 显示 `none`(无变更记录)、`pending`(等待下次请求生效)或 `prepared`(上下文已为本轮就绪)。面板特别注明:`prepared` 仅表示提示词上下文准备完毕,不代表模型实际遵从或确认送达。
145
+ - **文本呈现:** 显示当前模型使用 `native` 原生系统消息分段还是 `user` 带标记的时间线更新。
146
+ - **会话操作:**
147
+ - **单项停用:** 点击**停用**按钮,按 `activationId` 关闭指定项。
148
+ - **确认重置:** 点击**重置全部**后提供二次确认按钮(**确认重置** / **取消**),防止误操作清空会话指令。
149
+ - **提示词缓存用量:** 当当前分支存在提示词缓存数据时,面板展示本轮及整场会话的提示词缓存命中率与请求次数,并在界面上严格区分主会话请求与嵌套工具调用。详见[会话缓存用量](session-cache.md)。
150
+
151
+ ### 人类启用选择器(带守卫的预览与启用)
152
+
153
+ 面板内置了人类专用的能力启用选择器:
154
+
155
+ - **会话投影(`GET /api/capability-state/preview`):** 只读检查已启用的已保存预设及当前能力快照,编译前后核对 session/leaf/revision 及活动预设指纹。Preview 旁路元数据将真实投影更新块关联到 activation ID,不修改提示词消息。要求可信会话与已启用预设;缺失或过期明确报错,不准备请求、同步工具或证明提供商送达/缓存复用。
156
+ - **资源发现(`GET /api/capability-state/available`):** 纯本地只读接口,返回当前会话状态及可用能力选项,清晰分为*能力库项(未绑定)*与*当前预设(已绑定)*。读取操作绝不修改工具策略或产生会话事件。
157
+ - **即时预选预览:** 在下拉框中选择能力后,立即展开预选卡片呈现:
158
+ - 标签名称、ID、类别徽标(`能力库` 或 `预设绑定`)及正文指纹摘要(`#<hash>`)。
159
+ - 工具差异预览(`+add`、`-remove` 或 `无工具变更`)。
160
+ - 若该能力无法通过工具策略校验,显示异常警示条(Problem banner)。
161
+ - 完整的字面规则内容预览。
162
+ - **Bodyguard 安全启用(`POST /api/capability-state/enable`):**
163
+ - 提交载荷包含 `{ guard: { sessionId, leafId, revision }, kind, id, fingerprint }`。
164
+ - 服务端在执行前严格比对会话 Guard 与磁盘定义的最新内容指纹。
165
+ - 若会话、分支、版本或源文件发生变更,服务端返回 `409 Conflict` 拒绝操作。
166
+ - 绝不自动猜测或盲目重试。
167
+ - 启用操作需要项目已受信任(`isProjectTrusted() === true`),未信任会话返回 `403 Forbidden`。
168
+
169
+ ### 轮询策略、并发保护与安全机制
170
+
171
+ - **页面可见轮询与零推理开销:** 页面可见时每3秒静默读取 `GET /api/capability-state`,窗口获焦或主动刷新也会同步。能力目录只在进入工作区、主动刷新或相关操作后读取,不随每次轮询重载;无变化的后台检查不闪 loading 或禁用控件。会话投影由实际状态变化驱动,离开后忽略迟到回包。所有查询均为本地读取,不产生模型推理与 API token 开销。
172
+ - **错误与冲突时不盲目重试:** 遇到请求失败或 409 冲突时标记为 stale,需人工复核,不自动重试写操作。
173
+ - **项目信任要求:** 在 Web 端修改会话能力严格要求项目已受信任(`isProjectTrusted() === true`)。未受信任返回 `403 Forbidden`,命令行恢复通道保留。
174
+ - **Guard 防旧页与服务生命周期保护:** 每次修改均携带会话 Guard(`sessionId`、`leafId`、`revision`)。服务注销或不可用时返回 `503 Service Unavailable`。
175
+
176
+ ### 本地测试与宿主热加载
177
+
178
+ 在本地开发测试场(已有本地 build 接线)中调试时注意:
179
+ - 宿主热加载需要用户在 Pi 宿主控制台中手动执行 `/reload`。
180
+ - 若在 reload 之前已有 Web 服务器在运行,还需在宿主中执行 `/preset ui restart`,并使用新生成的带 token URL 打开。老 Web 服务器的闭包绑定在旧宿主生命周期上,不会随宿主刷新自动新增路由。切勿假定全局 host 已自动切换。
181
+
182
+ ## 生命周期与工具同步
183
+
184
+ - **统一的 `context_with_system` 流水线:** 在 Pi 0.87 中,标准 `context` 生命周期 hook 默认排除 System 消息。Forge 将完整编译器、基础提示词替换与能力投影流水线全部移至 `context_with_system`,无需内部两阶段拆分。
185
+ - **使用 `buildSessionProjection` 规范投影:** 运行时、预览与锚点定位基于 Pi 0.87 的规范 `buildSessionProjection`(支持 `context_edit` 的 omission、replacement 与 `sourceEntry`),确保瞬态请求拼装准确反映轮次上下文编辑,同时保持磁盘上的原始会话历史完全不变。
186
+ - **保持 Leading System 在首位:** SDK 传入的 leading System 始终保持在首位,Forge 自身的前缀纯元数据锚点紧跟其后插入。
187
+ - **续跑与结算生命周期:** `agent_end` 仍是安全的落锚提交时机,但编译周期与 busy fence 仅在 `agent_settled` 时重置。这确保了由 `agent_before_settle` 发起的继续执行(continuation)不会丢失已编译的 Preset 状态。
188
+ - **立即工具同步 vs. 下次请求提示词生效:**
189
+ - 可执行工具策略在能力激活时**立即同步**(`pi.setActiveTools()`),被策略禁用的工具在执行期立即被拦截。
190
+ - 提示词文本与原生 System 分段或 fallback 用户更新在**下一次模型请求边界**生效。
191
+ - 正在执行中的工具调用批次绝不会被中途终止。
192
+ - **顶层预设策略优先:** 能力不能越权启用已被当前预设 deny 策略禁用的工具。多个能力并存时,工具移除(remove)在当前会话的活动能力之间全局优先。
193
+ - **工具基线恢复:** 关闭能力后按预设默认工具与剩余能力重新计算;预设工具选择与能力叠加均不再生效时,恢复经过外部变更协调的会话基线。对缺乏记录的旧会话,Forge 采取保守策略恢复,而非盲目授予所有已注册工具。
194
+ - **Parent 生命周期与重入围栏:** 严格维护 `disposed` 标志、`lifecycleRevision` 计数器与 `sameContext` 会话校验,杜绝跨会话串号与注销后的非法重入。
195
+
196
+ ## 检查规则更新的预览
197
+
198
+ 现有 **Preview/预览** 按“选中的 Preset 草稿+当前会话能力快照”试算:
199
+
200
+ - 复用正常请求的纯预设/能力投影:显示原生 System 分段或带归属的 user 更新,包括停用通知和压缩检查点。
201
+ - 投递标记为纯元数据锚点,不作为对话消息展示。
202
+ - System 正文、原生命名分段与历史工具声明分开展示。代码区和分段复制只含正文/分段值,不把检查器生成的 `Added tool` 等提示混入原生文本。
203
+ - 历史工具声明折叠显示,并明确标注不是当前选择。
204
+ - 预览工具选择采用草稿策略+当前能力计算出的工具。
205
+ - 文本估算不含工具 schema 和检查器标签;投影后真正空掉的 System 卡片隐藏。
206
+ - 历史只按连续段分组:中途插入的能力更新保持在前后消息之间,不移到全部历史末尾。
207
+ - 纯只读检查:读取或复制预览内容不会发起推理、不会改变工具状态,也不会将 pending 标记为 prepared。全文不受原先消息布局 8,000 字符限制。
208
+
209
+ ## 投递模型:Native 与 Fallback
210
+
211
+ Forge 在每次发起模型请求时通过两阶段拼装动态投影能力增量:
212
+
213
+ 1. **编译前物化(Materialize):** 扫描通过 `buildSessionProjection` 规范投影后的会话条目中的纯 `custom` 元数据锚点(`pi-forge-capability-delivery`)。在请求上下文边界(`prepareCapabilityMessages`)校验元数据,并严格按其在投影转录中的序数位置物化为内存中的瞬态标记,绝不在磁盘转录中伪造对话消息或修改原始历史。
214
+ 2. **规则投影(Project):** 由 `projectCapabilityMessages` 将物化后的增量转化为适配当前模型的呈现形式:
215
+ - **Native 投递:** 当模型服务商声明支持会话中系统消息(`compat.supportsMidConvoSystemMessages === true`)时,增量以 `SystemMessage.sections`(以 `forge-capability-<id>` 为 key)注入,关闭时发送 null patch。Native 投递完全依赖服务商 capability 标记,并非所有提供商都支持。
216
+ - **Fallback 投递:** 对不支持原生系统更新的模型,增量以带来源标记的时间线用户消息(`[pi-forge capability update]`)投递。Forge 绝不折叠或篡改首条 leading system prompt,不把用户/工具对话提升为系统权限。
217
+ - **纯工具能力:** 正文为空或只有空白的能力在两条路径下都不发文字更新:启用时不发分段,停用时不发移除通知,compaction checkpoint 里也不包含它。只有工具变化进入请求,**当前会话**中也不提供“在上下文中定位”按钮。
218
+ - **如何判断走哪条路径:** 每次请求都按 Pi 模型目录中当前模型的 `compat` 条目决定;该目录由 Pi 拉取并缓存在本地,可能随更新变化。服务商名称、认证方式或认证扩展都不决定这一点,同一服务商的不同型号也可能不同。例如 2026-09-26 在 Pi 0.87.1 下观察到的目录中,`anthropic/claude-opus-4-8`、`claude-opus-5`、`claude-opus-5-5` 带有该标记,`anthropic/claude-sonnet-5` 没有。用 `/model` 切换后,之后的请求随之改变投递方式。`/capability status` 和 Agent 的 `status` 动作会显示 `native system sections` 或 `attributed user updates`;测试原生更新或缓存行为前请先确认。各 API 的行为和 Pi 0.87.1 时带标记的模型见[服务商支持情况](provider-support.md)。
219
+ - **Fallback 的附带影响:** 对未标记的模型,Pi 还会把它自己的工具变更声明折回首条 system 消息和顶层工具列表,因此工具变化会改写下一次请求的开头,这部分缓存前缀无法复用。部分模型可能把带标记的用户更新当作不可信文本,先质疑再使用新工具。
220
+
221
+ ## 状态恢复与验证边界
222
+
223
+ 能力状态由追加式会话事件与投递游标(`throughEventId`)推导恢复:
224
+
225
+ - **纯元数据投递锚点:** 投递标记以同名类型(`pi-forge-capability-delivery`)的纯 `custom` 会话条目持久化,仅包含 `{ schemaVersion: 1, throughEventId }` 游标元数据,不写入 `custom_message`,不使用 `sendMessage`。空闲变更立即落锚;运行中变更在工具批次完成后安全落锚;`agent_end` 在没有 Forge 上下文处理失败且批次完整时补齐未提交游标。UI 状态通知独立解耦,不向模型排入额外轮次。
226
+ - **SDK 离线验证:** 会话恢复、手动 compaction checkpoint 及分支切换(`session.navigateTree`)均已通过 SDK 本地测试套件离线验证。这验证了提示词拼装与工具门控逻辑,但不构成对远程模型实际遵从或服从程度的保证。
227
+ - **Compaction 与缓存:** 压缩断点(compaction checkpoint)位置保持不变(位于引导系统提示词之后、压缩摘要之前;上游 Pi 的元数据切分 bug 独立存在,当前尚未修复)。真实 SDK 压缩请求输入表征测试表明:新的控制元数据和仅请求内投影的规则**不会自动进入摘要输入**;选中摘要窗口内的真实用户、助手与 peer 对话不因这次修复被过滤,其中真实引用的规则文字仍保留。测试套件采用模拟假响应,仅用于验证请求组装与管线形状,不能等同于远程 LLM 实际语义压缩与遵从验收。
228
+ - **预发布破坏性边界:** 本次重命名不提供旧别名或旧读取器。使用旧指令模式键、Schema、目录或工具名的开发配置必须转换为新的能力名称;包含旧能力状态的会话不支持继续恢复该状态。Forge 不会改写旧 JSONL 或历史摘要;完成转换后请开启新会话,不要依赖部分恢复。
229
+ - **会话写盘时机:** 在仅输入斜杠命令的新会话中,在首个 assistant 回复产生前,Pi 可能尚未向磁盘写出 JSONL 会话条目。
230
+
231
+ ## 兼容性与安全边界
232
+
233
+ - **要求上游 Pi 0.87:** 必须使用上游 Pi `>=0.87.0 <0.88.0`。不提供对 0.86 的双重运行时支持。之前在 `context` hook 中操作或读取完整 System 消息的第三方扩展必须迁移到 `context_with_system` 完整 hook。
234
+ - **`before_agent_start` 注入时机:** `before_agent_start` 阶段强制注入的 System 提示词在 Pi 执行流中仍然晚于 `context_with_system` 生效。
235
+ - **前置扩展上下文改写:** Pi 允许 hook 改写消息。当可见元数据锚点或未锚定事件需要定位时,Forge 要求输入与规范会话投影有唯一的有序对应,否则中止而非猜测(fail-closed)。Pi 可能先保存排队的 custom 消息、但暂不放入工具续跑上下文:Forge 仅容许位置能唯一确定的 custom 消息缺省,忽略其重新生成的外层时间戳;保留传入对象,不擅自把缺省对话补回请求。前置改写因而可能与该定位方式冲突;简单后移不保证组合安全。通用插件、warming、自动 overflow 兼容性仍未全面验收。
236
+ - **上游缺陷与协议限制:** 上游 Pi 元数据分块及语义截断缺陷(semantic-cut defect)未被修复,压缩检查点位置保持不变。旧会话和旧投递载体保持原样,不支持继续恢复能力状态;Forge 不会迁移旧 JSONL 或改写历史摘要。不支持也不承诺 OMP(Oh My Pi)。
237
+ - **系统提示词 Getter:** `ctx.getSystemPrompt()` 和 SDK 接口返回 Pi 的原始基础提示词,而非 Forge 编译后的完整请求。请使用 `/forge payload`(裸 `/payload` 仍兼容)或 Run context diff 查看实际编译结果。Forge 不声称已同步 SDK getter。在生命周期 hook 中强行返回完整 `systemPrompt` 的第三方扩展会引发投影冲突,不被支持。
238
+ - **Provider 托管与缓存保守预警:** 工具传输序列化与提示词前缀缓存命中由下游提供商完全托管。工具策略变更、提示词前缀波动及会话压缩均会破坏缓存边界。支持追加的 Codex 传输在保留历史没有移除/重复声明时可追加全新工具以保留请求前缀,但不保证命中;移除或同名再声明会回退到当前全量工具表;Anthropic 原生工具变化等各 API 行为见[服务商支持情况](provider-support.md);pi-forge 提供保守的 Provider 托管与缓存预警,不提供权限绕过或缓存保障(不保证零 KV 缓存失效)。
239
+ - **沙盒免责:** 能力不提供操作系统级沙盒或权限隔离。示例 `review.json` 移除了 `bash`、`powershell`、`write` 和 `edit`,但未封禁外部 MCP 工具或 subagent,不能视为真正沙盒。请根据具体运行环境配置相应的执行工具移除列表。
240
+
241
+ ## 交付状态(0.5.5)
242
+
243
+ 0.5.5 核心功能源码已在所有规划的开发通道中全量交付:
244
+
245
+ - 能力基础编解码器、多范围解析、会话事件与不可变快照 Reducer。
246
+ - 人工 CLI 操作集(`/capability` add、list、bindings、enable、enable-bound、disable、status、reset)。
247
+ - 纯元数据锚点投影机制与编译前序数物化。
248
+ - Web 会话能力活动面板与带守卫的人类启用选择器(`GET /api/capability-state/available`, `POST /api/capability-state/enable`)。
249
+ - Live Preset 绑定在独立的同级“能力绑定”tab 中支持(`capabilities`),具备有限覆盖、折叠的高级面板及 `modelCallable: true` 显式授权。
250
+ - 限制级智能体控制工具 `forge_capability`(list、status、enable、disable,ID ≤ 128 字符)。
251
+ - Web 能力管理界面(Capabilities CRUD)支持 SDK 分组工具选择器与 `sourceRevision` 防脏写。
252
+ - Preset 策略新增自定义默认工具编辑器(`tools.initial?: string[]`),支持具体工具名、零默认工具(`[]`)以及缺省回退到传统逻辑。
253
+ - Parent 核心防护:源版本一致性保障、外部新增绑定防脏写检测、生命周期与重入安全围栏。
254
+ - 工具补丁仅支持 `add` 与 `remove`;候选的 `only`/allowlist 未实现。
255
+ - 提供保守的 Provider 托管与缓存预警;兼容的 Codex 传输在保留历史没有移除/重复声明时可追加全新工具以保留前缀(不保证缓存命中);移除/同名重加回退全量当前工具表;不进行自动旧数据迁移,不重写历史摘要;无 Pi split patch;不声称 forceprompt、warming、autooverflow 或远程模型验收保证。
256
+ - 2026-09-24 UI 收口时(提交 `89c6ba2`)本地构建、完整 Node/浏览器/打包验证已通过;这是有日期的本地结果,不是当前 CI 证据、远端提供商验收或 npm 已发布的证明。宿主仍要求 Pi `>=0.87.0 <0.88.0`;可选 runtime/subagent 集成及其生成者接入工作独立测试和发布。
257
+
258
+
259
+ 文件路径校验会拒绝检查时已存在的符号链接,但不能隔离另一个本地进程并发替换目录的攻击;源版本比较也不是跨进程锁。不要把资源编辑用于不可信进程可竞争修改的共享目录。
@@ -2,60 +2,88 @@
2
2
 
3
3
  [中文文档](../README.md) · [English](../../reference/commands.md)
4
4
 
5
- 方括号参数可选。写项目文件的命令要求项目已被信任。未限定的 `<id>` 使用项目优先的有效查找;需要精确选择时使用 `project:<id>` 或 `global:<id>`。
5
+ 方括号参数可选。主 pi-forge 命令会严格检查参数:未知 flag 和多余参数都会被拒绝。写入项目文件的命令要求项目已受信任。未限定的 `<id>` 使用项目优先查找;需要精确选择时使用 `project:<id>` 或 `global:<id>`。
6
6
 
7
- ## Prompt stack
7
+ ## Forge 命令
8
+
9
+ `/forge` 是推荐的根命令。不带参数时显示 Forge 帮助;`/forge help` 也一样。
10
+
11
+ | 命令 | 行为 |
12
+ |---|---|
13
+ | `/forge ui [stop\|restart]` | 打开、停止或明确重启本地 Web 编辑器。 |
14
+ | `/forge payload next [save=<path> [--overwrite]]` | 捕获下一个 provider hook payload,显示并可选保存。路径含空格时要加引号,例如 `save="path with spaces.json"`。 |
15
+ | `/forge payload status` | 显示是否有待处理捕获,以及是否已有最近捕获。 |
16
+ | `/forge payload cancel` | 只取消待处理的下一次捕获;不会删除或重置已保留的捕获或 context-diff 历史。 |
17
+ | `/forge payload help` | 显示 payload 语法和捕获边界。 |
18
+ | `/forge subagent ...` | 由匹配的 `@zihanw/pi-forge-subagents` 可选包提供的子命令。重复贡献者会 fail closed。 |
19
+
20
+ `/forge payload` 和裸 `/payload` 都会布置下一次捕获。`/intercept` 仍是同一“捕获但不保存”行为的兼容快捷方式。只有在 `save=<path>` 中显式提供 `--overwrite` 才会覆盖已有文件;布置捕获本身不会调用模型。捕获发生在 `before_provider_request`,所以后续插件改写可能使最终 wire body 不同。即使脱敏了类似 credential 的字段,保存内容仍可能包含 prompt 和对话文本。
21
+
22
+ 旧的 `/subagent` 命令是独立的底层 smoke helper,不是 `/forge subagent` 的执行计划命令。
23
+
24
+ ## Prompt preset
8
25
 
9
26
  | 命令 | 行为 |
10
27
  |---|---|
11
- | `/preset list` | 列出 stack 和状态 |
12
- | `/preset status` | 显示当前 stack 和诊断摘要 |
13
- | `/preset use <id>` | 校验并选择 stack |
14
- | `/preset use none` | 在当前 session branch 禁用 stack |
15
- | `/preset preview [id]` | 编译但不发送 provider 请求 |
16
- | `/preset validate [id]` | 校验一个或全部 stack |
17
- | `/preset diagnostics` | 显示 loader、runtime、policy、regex 和 extension 诊断 |
18
- | `/preset reload` | 重新加载 stack 和可信 macro/slot registration |
19
- | `/preset ui [stop\|restart]` | 打开或管理 Web 编辑器 |
20
-
21
- ## 迁移与导入
28
+ | `/preset list` | 列出 preset 以及启用/校验状态。 |
29
+ | `/preset status` | 显示选中的 preset 和诊断摘要。 |
30
+ | `/preset use <id>` | 校验并选择 preset。 |
31
+ | `/preset use none` | 在当前 session branch 禁用 preset;也接受 `disable`。 |
32
+ | `/preset preview [id]` | 编译并显示 preset,不发送 provider 请求;省略时使用选中的 preset。 |
33
+ | `/preset validate [id]` | 省略参数时校验当前选中的 preset;指定参数时只校验该 preset,默认不会校验全部 preset。 |
34
+ | `/preset diagnostics` | 显示 loader、runtime、policy、regex 和可信 extension 诊断。 |
35
+ | `/preset reload` | 重新加载 preset 及可信 macro/slot registration。 |
36
+ | `/preset ui [stop\|restart]` | 本地 Web 编辑器的兼容入口;推荐使用 `/forge ui`。 |
37
+ | `/preset help` | 显示 preset 命令帮助。 |
38
+
39
+ ## 存储迁移
22
40
 
23
41
  | 命令 | 行为 |
24
42
  |---|---|
25
- | `/preset migrate-stacks [--dry-run] [--overwrite] [--delete-legacy]` | 把旧 stack 复制到 `.pi/forge/prompt-stacks` |
43
+ | `/preset migrate-stacks [--dry-run] [--overwrite] [--delete-legacy]` | 将旧 `.pi/prompt-stacks` 文件复制到 `.pi/forge/prompt-stacks`。 |
26
44
 
27
- 覆盖或删除之前请先使用 `--dry-run`。
45
+ 覆盖或删除前请先使用 `--dry-run`。
28
46
 
29
47
  ## Agent profile
30
48
 
31
49
  | 命令 | 行为 |
32
50
  |---|---|
33
- | `/profile list` | 列出 profile 和解析诊断 |
34
- | `/profile use <id>` | preflight 并一次性应用 |
35
- | `/profile save <id\|global:id> [--overwrite]` | 捕获当前模型、thinking 和 stack;`global:<id>` 写入用户全局目录 |
36
- | `/profile status` | 比较当前 runtime 和 last-applied provenance |
37
- | `/profile preview <id>` | 不应用地解析模型/auth/thinking/stack/tools |
38
- | `/profile validate [id]` | 校验一个或全部 profile |
39
- | `/profile reload` | 重新加载定义,但不应用 |
40
- | `/profile forget` | 删除 provenance,不改变 runtime |
51
+ | `/profile list` | 列出 project profile 和解析诊断。 |
52
+ | `/profile use <id>` | preflight 并一次性应用 profile。 |
53
+ | `/profile save <id\|global:id> [--overwrite]` | 捕获当前模型、thinking 和 preset。 |
54
+ | `/profile status` | 比较当前 runtime 与 last-applied provenance。 |
55
+ | `/profile preview <id>` | 不应用地解析 model/auth/thinking/preset/tools。 |
56
+ | `/profile validate [id]` | 省略参数时校验全部已加载 profile;指定参数时只校验该 profile。 |
57
+ | `/profile reload` | 重新加载定义但不应用。 |
58
+ | `/profile forget` | 删除 last-applied provenance,不改变 runtime。 |
59
+ | `/profile help` | 显示 profile 命令帮助。 |
41
60
 
42
- ## 实验性 delegation
61
+ ## 能力
43
62
 
44
- 以下命令由可选包 `@zihanw/pi-forge-subagents` 提供。
63
+ `/capability` 用于管理会话能力。
45
64
 
46
65
  | 命令 | 行为 |
47
66
  |---|---|
48
- | `/forge-agent backends` | 列出 backend、capabilities 和默认值 |
49
- | `/forge-agent plan <profile> [--backend <id>] <task>` | 准备、显示并丢弃计划,不联系 provider |
50
- | `/forge-agent run <profile> [--backend <id>] <task>` | 审批并执行前台只读任务 |
67
+ | `/capability add <text>` | 添加字面手动指令。 |
68
+ | `/capability list` | 显式重新发现并列出能力库。 |
69
+ | `/capability bindings` | 列出当前 preset 的绑定,包括人类专用绑定(`modelCallable: false`)。 |
70
+ | `/capability enable <[scope:]id>` | 启用未绑定的能力库项。 |
71
+ | `/capability enable-bound <id>` | 启用当前 preset 的一个绑定。 |
72
+ | `/capability disable <activation-id>` | 停用一个活动能力。 |
73
+ | `/capability status` | 显示活动能力和生效工具。 |
74
+ | `/capability reset` | 停用全部活动能力和手动指令。 |
75
+ | `/capability help` | 显示用法和兼容性说明。 |
76
+
77
+ 补全使用当前 session 与最近发布的 workspace snapshot,不会在每次按键时扫描资源。需要显式刷新发现时使用 `/capability list`。`bindings` 仍显示人类专用绑定;`modelCallable: false` 只禁止 Agent 控制,不会把它从人类列表中过滤掉。
51
78
 
52
- 只接受明确 scope 的授权:请在 `subagents.json` 中使用 `project:<id>` 或 `global:<id>` key。裸授权 key 始终表示 `project:<id>`,即使它位于全局配置中;`.pi/forge/config.json.subagents` 仅作为只读兼容来源。模型工具为 `forge_subagent_profiles` 和 `forge_subagent`。见[安全说明](../guides/delegation.md)。
79
+ ## 可选前台委派
53
80
 
54
- ## Payload
81
+ 以下命令由匹配的可选包 `@zihanw/pi-forge-subagents` 提供,不属于主 pi-forge:
55
82
 
56
83
  | 命令 | 行为 |
57
84
  |---|---|
58
- | `/intercept` | 显示下一个脱敏 provider payload |
59
- | `/payload next [save=<path>]` | 显示并可选保存 payload,同时提供给 Web 编辑器 |
85
+ | `/forge-agent backends` | 列出已注册 backend、能力和有效默认值。 |
86
+ | `/forge-agent plan <profile> [--backend <id>] <task>` | 准备、显示并丢弃精确计划,不发送 provider 请求。 |
87
+ | `/forge-agent run <profile> [--backend <id>] <task>` | 准备前台运行,始终请求人类审批,然后通过所选 backend 执行。backend 可能写文件;它并非天然只读。 |
60
88
 
61
- 即使 credentials 字段被脱敏,保存的 payload 仍可能包含 prompt 和对话内容,请按敏感数据处理。
89
+ 可选包只接受明确 scope 的 profile:在其 `subagents.json` 中使用 `project:<id>` 或 `global:<id>` key。模型工具对应为 `forge_subagent_profiles`(本地发现)和 `forge_subagent`(执行)。模型可调用的 `forge_subagent` 工具是另一条路径。它是否可无人值守由可信项目中的显式授权控制;不能用来绕过 `/forge-agent run` 必须审批的要求。见[委派安全说明](../guides/delegation.md)。
@@ -0,0 +1,67 @@
1
+ # 各服务商对会话中更新的支持情况(Pi 0.87.1 快照)
2
+
3
+ [中文文档](../README.md) · [English](../../reference/provider-support.md)
4
+
5
+ 本页记录 Pi 0.87.1 在各 API 下如何发送会话中的 system 更新和工具变化,以及 Pi 模型目录中哪些模型带有相应标记。它解释了为什么同一个[能力](capabilities.md#投递模型native-与-fallback)在一个模型上以原生 system 更新送达,换到另一个模型却变成带标记的用户消息。
6
+
7
+ > **快照状态:** Pi 0.87.1(`@earendil-works/pi-ai` 0.87.1),本地模型目录最近检查于 2026-09-21 至 2026-09-25,记录于 2026-09-26。模型目录由 Pi 远程拉取并缓存在 `~/.pi/agent/models-store.json`,标记可能在不升级 Pi 的情况下变化。依赖下表之前,请先用 `/capability status` 确认当前模型走哪条路径。
8
+
9
+ ## 如何决定
10
+
11
+ Pi 和 Forge 在每次请求时都读取当前模型的 `compat` 标记:
12
+
13
+ | 标记 | 为 `true` 时 | 缺失或为 `false` 时 |
14
+ |---|---|---|
15
+ | `supportsMidConvoSystemMessages` | 后续 system 消息保留在对话中的原位置;Forge 以原生 system 分段发送指令正文。 | Pi 把所有 system 消息折回首条 system 提示词,并在请求级别发送当前工具列表;Forge 以带标记的 `[pi-forge capability update]` 用户消息发送指令正文。 |
16
+ | `supportsMidConvoToolChanges`(Anthropic Messages) | 工具增删以 `tool_addition` / `tool_removal` 块放在 system 更新中发送。 | 在请求级别发送完整的当前工具列表。 |
17
+ | `supportsAdditionalTools` / `supportsToolSearch`(OpenAI Responses、Codex、Azure) | 新工具在原位置加载(`additional_tools`,或客户端 tool search 的调用与结果)。 | 在请求级别发送完整的当前工具列表。 |
18
+ | `supportsMidConvoToolAdditions`(OpenAI Completions) | 新工具由一条带 `tools` 的 system 消息在原位置加载。 | 在请求级别发送完整的当前工具列表。 |
19
+
20
+ 工具相关标记只有在 `supportsMidConvoSystemMessages` 也启用时才生效。服务商名称、认证方式和认证扩展都不决定走哪条路径;同一个模型挂在不同服务商下,标记也可能不同。
21
+
22
+ ## 各 API 的行为
23
+
24
+ | API | 指令正文 | 工具变化 |
25
+ |---|---|---|
26
+ | `anthropic-messages` | 有标记时为 `role: "system"` 消息。Pi 会把它留到下一条 assistant 消息之前再发,因此不会插在 `tool_use` 和对应的 `tool_result` 之间;记录在用户消息之前的更新,实际会发在该用户消息之后。 | 有 `supportsMidConvoToolChanges`、至少一个初始工具且没有同名重定义时:初始工具保持在最前,之后的工具带 `defer_loading` 追加,变化以 `tool_addition` / `tool_removal` 块表示,请求级工具列表只增不减。否则在请求级别发送当前列表。 |
27
+ | `openai-responses`、`openai-codex-responses`、`azure-openai-responses` | 有标记时,在原位置发送 `developer` 消息(支持 developer 角色的推理模型)或 `system` 消息。 | 保留的历史中只有新增时,新工具在原位置加载;历史中任何位置出现过移除或同名重声明,这次请求就改为在请求级别发送完整的当前列表。 |
28
+ | `openai-completions` | 有标记时,在原位置发送 `developer` 或 `system` 消息。 | 有 `supportsMidConvoToolAdditions` 时新增在原位置加载;移除和重声明改为发送完整的当前列表。 |
29
+ | `mistral-conversations` | 有标记时,在原位置发送 `system` 消息。 | 始终在请求级别发送完整的当前列表。 |
30
+ | Google Generative AI / Vertex | 始终折入 `systemInstruction`,没有会话中路径。 | 完整的当前列表。 |
31
+ | Bedrock Converse | 始终折入请求级 system 提示词。 | 完整的当前工具配置。 |
32
+ | `pi-messages` | 原样把上下文交给后端,行为取决于该后端。 | 由后端决定。 |
33
+
34
+ 更新正文渲染为 `Updated system prompt section "<name>": ...` 或 `Removed system prompt section "<name>".`。[纯工具能力](capabilities.md#投递模型native-与-fallback)不发送文字更新。
35
+
36
+ ## 2026-09 目录中带标记的模型
37
+
38
+ 只列出 `supportsMidConvoSystemMessages: true` 的模型。
39
+
40
+ | 服务商 | 模型 | 工具变化 |
41
+ |---|---|---|
42
+ | `anthropic` | `claude-fable-5`、`claude-fable-5-1`、`claude-opus-4-8`、`claude-opus-5`、`claude-opus-5-5` | 原生增删 |
43
+ | `openai-codex` | `gpt-5.6-luna`、`gpt-5.6-sol`、`gpt-5.6-terra`、`gpt-6-astra`、`gpt-6-luna`、`gpt-6-sol` | 新增在原位置加载(`additional_tools`) |
44
+ | `openai-codex` | `gpt-5.5` | 新增通过 tool search 在原位置加载 |
45
+ | `opencode` | `gpt-5.4`、`gpt-5.4-mini`、`gpt-5.4-pro`、`gpt-5.5`、`gpt-5.6-luna`、`gpt-5.6-sol`、`gpt-5.6-terra`、`gpt-6-astra` | 新增在原位置加载(`additional_tools`) |
46
+ | `opencode` | `claude-fable-5`、`claude-fable-5-1`、`claude-opus-4-8`、`claude-opus-5` | 仅正文;任何工具变化都发送完整列表 |
47
+ | `opencode`、`opencode-go` | `kimi-k3` | 新增在原位置加载 |
48
+ | `opencode-go` | `gpt-5.6-luna` | 新增在原位置加载(`additional_tools`) |
49
+ | `deepseek` | `deepseek-v4-pro` | 仅正文;任何工具变化都发送完整列表 |
50
+
51
+ 同一目录中没有标记的模型包括:`anthropic/claude-sonnet-5`、`claude-sonnet-4-5`、`claude-sonnet-4-6`、`claude-opus-4-5` 至 `claude-opus-4-7`、`claude-haiku-4-5`;`openai-codex/gpt-5.3-codex-spark`;`deepseek/deepseek-flash`;以及所有 `google` 和 `kimi-coding` 模型。
52
+
53
+ ## 实测缓存表现
54
+
55
+ 以下是单个会话中的观察,不构成保证。缓存是否复用由服务商决定。
56
+
57
+ - **`anthropic/claude-opus-5-5`,原生路径(通过认证扩展使用 OAuth):** 新增、移除、重新添加工具,包括模型自己启用的能力,18 次续轮请求全部完整复用了已缓存的前缀。命中率偏低的请求是在写入新内容,例如新的工具定义或大文件读取结果,并没有丢失之前的缓存。
58
+ - **`anthropic/claude-sonnet-5`,fallback 路径:** 工具变化后的那次请求没有读到任何缓存,因为 Pi 改写了首条 system 提示词和工具列表。模型还对带标记的用户更新产生了怀疑,确认后才使用新工具。
59
+ - **OpenAI Responses / Codex:** 之前的测试中,一次移除就改为发送完整工具列表,缓存读取降为 0;只有新增的请求保住了前缀。
60
+
61
+ 想让缓存稳定,优先选用带原生工具变化标记的模型;在 Responses 系列模型上,如果在意缓存复用,尽量不要在同一会话中移除工具。
62
+
63
+ ## 检查自己的环境
64
+
65
+ 1. 运行 `/capability status`,它会显示当前模型使用 `native system sections` 还是 `attributed user updates`。
66
+ 2. 如需直接查看标记,在 `~/.pi/agent/models-store.json` 中找到对应服务商下的模型,读取其 `compat` 对象。
67
+ 3. 如需确认实际发送格式,用 `/forge payload next` 捕获下一次真实请求。