@zihanw/pi-forge 0.4.0-beta.1 → 0.4.1

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 (227) hide show
  1. package/CHANGELOG.md +45 -1
  2. package/PUBLIC_API.md +3 -26
  3. package/README.md +90 -601
  4. package/README.zh-CN.md +86 -585
  5. package/SUBAGENT_ADAPTER_CONTRACT.md +3 -197
  6. package/dist/agent-profile.d.ts +24 -1
  7. package/dist/agent-profile.d.ts.map +1 -1
  8. package/dist/agent-profile.js +146 -36
  9. package/dist/agent-profile.js.map +1 -1
  10. package/dist/catalog.d.ts +27 -0
  11. package/dist/catalog.d.ts.map +1 -0
  12. package/dist/catalog.js +59 -0
  13. package/dist/catalog.js.map +1 -0
  14. package/dist/forge-config.d.ts +106 -0
  15. package/dist/forge-config.d.ts.map +1 -1
  16. package/dist/forge-config.js +305 -18
  17. package/dist/forge-config.js.map +1 -1
  18. package/dist/index.d.ts +5 -5
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +55 -8
  21. package/dist/index.js.map +1 -1
  22. package/dist/lifecycle.d.ts +2 -1
  23. package/dist/lifecycle.d.ts.map +1 -1
  24. package/dist/lifecycle.js +7 -4
  25. package/dist/lifecycle.js.map +1 -1
  26. package/dist/loader.d.ts +17 -1
  27. package/dist/loader.d.ts.map +1 -1
  28. package/dist/loader.js +84 -25
  29. package/dist/loader.js.map +1 -1
  30. package/dist/preset-command.d.ts +1 -1
  31. package/dist/preset-command.d.ts.map +1 -1
  32. package/dist/preset-command.js +38 -10
  33. package/dist/preset-command.js.map +1 -1
  34. package/dist/profile-command.d.ts.map +1 -1
  35. package/dist/profile-command.js +46 -21
  36. package/dist/profile-command.js.map +1 -1
  37. package/dist/profile-service.d.ts +6 -3
  38. package/dist/profile-service.d.ts.map +1 -1
  39. package/dist/profile-service.js +55 -13
  40. package/dist/profile-service.js.map +1 -1
  41. package/dist/resource-identity.d.ts +33 -0
  42. package/dist/resource-identity.d.ts.map +1 -0
  43. package/dist/resource-identity.js +56 -0
  44. package/dist/resource-identity.js.map +1 -0
  45. package/dist/runtime/profile-runtime.d.ts.map +1 -1
  46. package/dist/runtime/profile-runtime.js +7 -2
  47. package/dist/runtime/profile-runtime.js.map +1 -1
  48. package/dist/runtime/prompt-stack-runtime.d.ts +1 -1
  49. package/dist/runtime/prompt-stack-runtime.d.ts.map +1 -1
  50. package/dist/runtime/prompt-stack-runtime.js +22 -12
  51. package/dist/runtime/prompt-stack-runtime.js.map +1 -1
  52. package/dist/runtime/subagent-runtime.d.ts +23 -8
  53. package/dist/runtime/subagent-runtime.d.ts.map +1 -1
  54. package/dist/runtime/subagent-runtime.js +296 -67
  55. package/dist/runtime/subagent-runtime.js.map +1 -1
  56. package/dist/storage.d.ts +11 -0
  57. package/dist/storage.d.ts.map +1 -1
  58. package/dist/storage.js +51 -2
  59. package/dist/storage.js.map +1 -1
  60. package/dist/subagent/canonical.d.ts +19 -7
  61. package/dist/subagent/canonical.d.ts.map +1 -1
  62. package/dist/subagent/canonical.js +19 -47
  63. package/dist/subagent/canonical.js.map +1 -1
  64. package/dist/subagent/contract.d.ts +1 -2
  65. package/dist/subagent/contract.d.ts.map +1 -1
  66. package/dist/subagent/contract.js +1 -2
  67. package/dist/subagent/contract.js.map +1 -1
  68. package/dist/subagent/index.d.ts +4 -3
  69. package/dist/subagent/index.d.ts.map +1 -1
  70. package/dist/subagent/index.js +4 -3
  71. package/dist/subagent/index.js.map +1 -1
  72. package/dist/subagent/plan.d.ts +5 -1
  73. package/dist/subagent/plan.d.ts.map +1 -1
  74. package/dist/subagent/plan.js +29 -32
  75. package/dist/subagent/plan.js.map +1 -1
  76. package/dist/subagent/request.d.ts.map +1 -1
  77. package/dist/subagent/request.js +36 -4
  78. package/dist/subagent/request.js.map +1 -1
  79. package/dist/subagent/types.d.ts +66 -178
  80. package/dist/subagent/types.d.ts.map +1 -1
  81. package/dist/subagent/types.js +1 -1
  82. package/dist/subagent/types.js.map +1 -1
  83. package/dist/subagent/validation.d.ts +14 -14
  84. package/dist/subagent/validation.d.ts.map +1 -1
  85. package/dist/subagent/validation.js +52 -238
  86. package/dist/subagent/validation.js.map +1 -1
  87. package/dist/subagent-command.d.ts +2 -1
  88. package/dist/subagent-command.d.ts.map +1 -1
  89. package/dist/subagent-command.js +115 -19
  90. package/dist/subagent-command.js.map +1 -1
  91. package/dist/subagent-host.d.ts.map +1 -1
  92. package/dist/subagent-host.js +43 -16
  93. package/dist/subagent-host.js.map +1 -1
  94. package/dist/subagent-profile-tool.d.ts +25 -2
  95. package/dist/subagent-profile-tool.d.ts.map +1 -1
  96. package/dist/subagent-profile-tool.js +41 -9
  97. package/dist/subagent-profile-tool.js.map +1 -1
  98. package/dist/subagent-tool.d.ts +31 -4
  99. package/dist/subagent-tool.d.ts.map +1 -1
  100. package/dist/subagent-tool.js +311 -137
  101. package/dist/subagent-tool.js.map +1 -1
  102. package/dist/types.d.ts +3 -0
  103. package/dist/types.d.ts.map +1 -1
  104. package/dist/types.js.map +1 -1
  105. package/dist/web-editor/client-script.generated.d.ts +1 -1
  106. package/dist/web-editor/client-script.generated.d.ts.map +1 -1
  107. package/dist/web-editor/client-script.generated.js +1 -1
  108. package/dist/web-editor/client-script.generated.js.map +1 -1
  109. package/dist/web-editor/client-styles.d.ts +2 -0
  110. package/dist/web-editor/client-styles.d.ts.map +1 -0
  111. package/dist/web-editor/client-styles.generated.d.ts +2 -0
  112. package/dist/web-editor/client-styles.generated.d.ts.map +1 -0
  113. package/dist/web-editor/client-styles.generated.js +3 -0
  114. package/dist/web-editor/client-styles.generated.js.map +1 -0
  115. package/dist/web-editor/client-styles.js +2 -0
  116. package/dist/web-editor/client-styles.js.map +1 -0
  117. package/dist/web-editor/page.d.ts +2 -0
  118. package/dist/web-editor/page.d.ts.map +1 -1
  119. package/dist/web-editor/page.js +11 -73
  120. package/dist/web-editor/page.js.map +1 -1
  121. package/dist/web-editor/server.d.ts.map +1 -1
  122. package/dist/web-editor/server.js +176 -1
  123. package/dist/web-editor/server.js.map +1 -1
  124. package/dist/web-editor/styles.d.ts.map +1 -1
  125. package/dist/web-editor/styles.js +60 -3
  126. package/dist/web-editor/styles.js.map +1 -1
  127. package/dist/web-editor/types.d.ts +87 -0
  128. package/dist/web-editor/types.d.ts.map +1 -1
  129. package/dist/web-host.d.ts +13 -2
  130. package/dist/web-host.d.ts.map +1 -1
  131. package/dist/web-host.js +371 -27
  132. package/dist/web-host.js.map +1 -1
  133. package/docs/README.md +41 -0
  134. package/docs/concepts/agent-profiles.md +60 -0
  135. package/docs/concepts/prompt-stacks.md +95 -0
  136. package/docs/design/README.md +17 -0
  137. package/docs/design/roadmap-0.4-archive.md +216 -0
  138. package/docs/design/subagents/design-review.md +220 -0
  139. package/docs/design/subagents/interface-design.md +274 -0
  140. package/docs/design/subagents/sdk-spike-findings.md +117 -0
  141. package/docs/development/complexity-review.md +86 -0
  142. package/docs/development/release.md +31 -0
  143. package/docs/development/roadmap.md +36 -0
  144. package/docs/development/scoped-global-profiles-stacks.md +325 -0
  145. package/docs/development/setup.md +75 -0
  146. package/docs/getting-started.md +95 -0
  147. package/docs/guides/custom-macros-and-slots.md +68 -0
  148. package/docs/guides/debugging.md +39 -0
  149. package/docs/guides/delegation.md +107 -0
  150. package/docs/guides/sillytavern-import.md +47 -0
  151. package/docs/guides/use-cases.md +65 -0
  152. package/docs/guides/web-editor.md +75 -0
  153. package/docs/reference/commands.md +60 -0
  154. package/docs/reference/configuration.md +66 -0
  155. package/docs/reference/features.md +280 -0
  156. package/docs/reference/macros-and-slots.md +82 -0
  157. package/docs/reference/public-api.md +28 -0
  158. package/docs/reference/stack-schema.md +167 -0
  159. package/docs/reference/subagent-adapter.md +204 -0
  160. package/docs/zh-CN/README.md +37 -0
  161. package/docs/zh-CN/concepts/agent-profiles.md +46 -0
  162. package/docs/zh-CN/concepts/prompt-stacks.md +42 -0
  163. package/docs/zh-CN/getting-started.md +81 -0
  164. package/docs/zh-CN/guides/delegation.md +66 -0
  165. package/docs/zh-CN/guides/web-editor.md +45 -0
  166. package/docs/zh-CN/reference/commands.md +60 -0
  167. package/package.json +29 -15
  168. package/dist/subagent/backend-registry.d.ts +0 -75
  169. package/dist/subagent/backend-registry.d.ts.map +0 -1
  170. package/dist/subagent/backend-registry.js +0 -463
  171. package/dist/subagent/backend-registry.js.map +0 -1
  172. package/dist/subagent/diagnostics.d.ts +0 -3
  173. package/dist/subagent/diagnostics.d.ts.map +0 -1
  174. package/dist/subagent/diagnostics.js +0 -5
  175. package/dist/subagent/diagnostics.js.map +0 -1
  176. package/dist/subagent/pi-model-runtime.d.ts +0 -8
  177. package/dist/subagent/pi-model-runtime.d.ts.map +0 -1
  178. package/dist/subagent/pi-model-runtime.js +0 -22
  179. package/dist/subagent/pi-model-runtime.js.map +0 -1
  180. package/dist/subagent/pi-sdk-backend.d.ts +0 -23
  181. package/dist/subagent/pi-sdk-backend.d.ts.map +0 -1
  182. package/dist/subagent/pi-sdk-backend.js +0 -383
  183. package/dist/subagent/pi-sdk-backend.js.map +0 -1
  184. package/dist/subagent/pi-subprocess-backend.d.ts +0 -72
  185. package/dist/subagent/pi-subprocess-backend.d.ts.map +0 -1
  186. package/dist/subagent/pi-subprocess-backend.js +0 -756
  187. package/dist/subagent/pi-subprocess-backend.js.map +0 -1
  188. package/dist/subagent/subprocess-bridge.d.ts +0 -21
  189. package/dist/subagent/subprocess-bridge.d.ts.map +0 -1
  190. package/dist/subagent/subprocess-bridge.js +0 -87
  191. package/dist/subagent/subprocess-bridge.js.map +0 -1
  192. package/dist/subagent/subprocess-report.d.ts +0 -4
  193. package/dist/subagent/subprocess-report.d.ts.map +0 -1
  194. package/dist/subagent/subprocess-report.js +0 -55
  195. package/dist/subagent/subprocess-report.js.map +0 -1
  196. package/dist/subagent-contract.d.ts +0 -8
  197. package/dist/subagent-contract.d.ts.map +0 -1
  198. package/dist/subagent-contract.js +0 -8
  199. package/dist/subagent-contract.js.map +0 -1
  200. package/dist/web-editor/client/api.d.ts +0 -9
  201. package/dist/web-editor/client/api.d.ts.map +0 -1
  202. package/dist/web-editor/client/api.js +0 -26
  203. package/dist/web-editor/client/api.js.map +0 -1
  204. package/dist/web-editor/client/dom.d.ts +0 -13
  205. package/dist/web-editor/client/dom.d.ts.map +0 -1
  206. package/dist/web-editor/client/dom.js +0 -30
  207. package/dist/web-editor/client/dom.js.map +0 -1
  208. package/dist/web-editor/client/inspector.d.ts +0 -22
  209. package/dist/web-editor/client/inspector.d.ts.map +0 -1
  210. package/dist/web-editor/client/inspector.js +0 -226
  211. package/dist/web-editor/client/inspector.js.map +0 -1
  212. package/dist/web-editor/client/main.d.ts +0 -2
  213. package/dist/web-editor/client/main.d.ts.map +0 -1
  214. package/dist/web-editor/client/main.js +0 -1468
  215. package/dist/web-editor/client/main.js.map +0 -1
  216. package/dist/web-editor/client/policy-editor.d.ts +0 -16
  217. package/dist/web-editor/client/policy-editor.d.ts.map +0 -1
  218. package/dist/web-editor/client/policy-editor.js +0 -330
  219. package/dist/web-editor/client/policy-editor.js.map +0 -1
  220. package/dist/web-editor/client/regex-editor.d.ts +0 -19
  221. package/dist/web-editor/client/regex-editor.d.ts.map +0 -1
  222. package/dist/web-editor/client/regex-editor.js +0 -281
  223. package/dist/web-editor/client/regex-editor.js.map +0 -1
  224. package/dist/web-editor/client/types.d.ts +0 -60
  225. package/dist/web-editor/client/types.d.ts.map +0 -1
  226. package/dist/web-editor/client/types.js +0 -2
  227. package/dist/web-editor/client/types.js.map +0 -1
package/README.zh-CN.md CHANGED
@@ -1,649 +1,150 @@
1
1
  # pi-forge
2
2
 
3
- [English](README.md) | [简体中文](README.zh-CN.md)
3
+ [English](README.md) | [简体中文](README.zh-CN.md) · [中文文档](docs/zh-CN/README.md)
4
4
 
5
5
  ![pi-forge header](https://raw.githubusercontent.com/MacroSony/pi-forge/main/assets/pi-forge-header-concept-1.png)
6
6
 
7
- **pi-forge** 让你自定义 Pi 的思考方式和行为。它提供用于 prompt/工具策略的 prompt stack(提示栈),也提供可一次性应用模型、思考等级和提示栈的 agent profile(agent 配置预设)。
7
+ **pi-forge** 让你自定义 [Pi](https://github.com/badlogic/pi-mono) 的思考方式和行为。Prompt stack(提示栈)负责 prompt 组合和工具策略;agent profile(agent 配置预设)可以一次性应用模型、思考等级和提示栈。
8
8
 
9
- 可以把它理解为 AI agent 的角色卡。
9
+ 可以把它理解为 AI agent 的角色卡和工作台。
10
10
 
11
- ## 能做什么
11
+ ## 主要能力
12
12
 
13
- - **赋予 Pi 个性** — 把它变成创意写手、角色扮演搭档、严格的代码审查员,或任何你想要的风格。
14
- - **一键切换模式** — 在"写代码"、"写小说"、"做翻译"之间用一条命令切换。
15
- - **保存完整 agent 预设** — 捕获当前模型、思考等级和提示栈,以后一条命令一起应用。
16
- - **控制 AI 看到什么** — 选择每个 prompt 中出现哪些工具、技能和项目上下文。
17
- - **按栈限制工具和技能** — 为专注模式启用工具策略,并过滤技能可见性。
18
- - **使用模板变量** — 定义 `{{char}}` / `{{user}}` 这样的静态值,并在 prompt 文本里使用 ST 风格的轮次/会话变量宏。
19
- - **转换发出和最终消息文本** — 对选中的历史、最终编译 prompt 或已结束的 assistant 消息执行确定性 regex 替换。
20
- - **导入 SillyTavern 预设** — 一条命令把 ST 角色预设迁移到 Pi。
21
- - **调试 prompt** — 拦截并查看实际发给模型的内容。
13
+ - 把 system prompt、聊天历史、工具、skills、项目上下文和运行时数据组合成可排序的 block 和 slot。
14
+ - 用一条命令切换编程、审查、写作、角色扮演和翻译模式。
15
+ - 保存并应用完整的模型/思考等级/提示栈预设。
16
+ - 按栈严格限制工具,并过滤模型可见的 skills。
17
+ - 使用静态、轮次和会话变量,以及支持嵌套的模板宏。
18
+ - 对发给模型的 prompt 或最终 assistant 消息执行确定性 regex 转换。
19
+ - 导入 SillyTavern 预设并检查迁移报告。
20
+ - 在本地 Web 编辑器中管理 stack/profile,并检查实际 provider payload。
21
+ - 用明确启用的 profile 运行实验性、需要审批的前台 subagent。
22
22
 
23
- ## 快速上手
23
+ ## 安装
24
24
 
25
- ### 安装
25
+ pi-forge 需要 Node.js 22.19 或更高版本。
26
26
 
27
27
  ```bash
28
- pi install npm:@zihanw/pi-forge@0.4.0-beta.1
28
+ pi install npm:@zihanw/pi-forge
29
29
  ```
30
30
 
31
- 此 beta 会发布到 npm 的 `next` channel,不会替换稳定版 `latest`。它要求 Node.js 22.19 或更高版本,并且必须使用 Pi 0.80.10 所采用的精确 `@earendil-works/pi-*` 0.80.10 package 版本。
31
+ 安装或更新后请重启 Pi。运行中的 Pi host 会向 extension 提供 SDK package;pi-forge 只在开发和测试中固定精确版本,以保证结果可复现,不会用 peer dependency 锁死 Pi 频繁发布的版本。兼容策略见[开发与兼容性](docs/development/setup.md#pi-compatibility)(英文)。
32
32
 
33
- > **Pi 版本兼容性:** Pi 在 0.80.x 系列内部修改了 session 认证/runtime 的接线方式。此 beta 只以 0.80.10 为目标;不声明兼容 0.80.6–0.80.9,也不声明兼容尚未验证的后续 0.80.x 版本。安装或重新 build pi-forge 后请重启 Pi,确保 extension 与 host SDK 使用同一套接口。如果主 agent 可以正常使用 provider,但 subagent preparation 报告 `No API key found`,请先检查是否仍在运行旧的 pi-forge build,不要直接执行 `/login`:使用 0.80.10 之前 session API 的 build 会在 preparation 时丢失主 session 的认证信息,重新登录无法修复这个版本不匹配。
33
+ ## 五分钟上手
34
34
 
35
- ### 第一个 prompt stack
35
+ ### 1. 创建 prompt stack
36
36
 
37
- 从 [examples/default-prompt-stack.json](examples/default-prompt-stack.json) 创建 `.pi/forge/prompt-stacks/default.json`。
38
-
39
- 默认示例参考了 `@earendil-works/pi-coding-agent/dist/core/system-prompt.js` 中 Pi 自己的 prompt builder,但把它拆成可移动的 pi-forge slot:角色、工具、guidelines、Pi 文档提示、append-system-prompt、项目上下文、技能、日期/cwd 和对话历史。
37
+ 从 [默认 Pi mirror](examples/default-prompt-stack.json) 创建 `.pi/forge/prompt-stacks/default.json`:
40
38
 
41
39
  ```bash
42
40
  mkdir -p .pi/forge/prompt-stacks
43
- $EDITOR .pi/forge/prompt-stacks/default.json
44
- ```
45
-
46
- 把示例 JSON 粘贴进去。如果你就在这个仓库里开发,也可以直接执行 `cp examples/default-prompt-stack.json .pi/forge/prompt-stacks/default.json`。
47
-
48
- 搞定。重启 Pi 或执行 `/preset reload`。如果当前没有选中其他栈,`default.json` 会自动启用;如果你之前执行过 `/preset use none` 或选择了别的栈,请执行 `/preset use default`。
49
-
50
- ### 可视化编辑器
51
-
52
- 不想手写 JSON?pi-forge 内置了 Web 编辑器:
53
-
54
- ```
55
- /preset ui
41
+ cp examples/default-prompt-stack.json .pi/forge/prompt-stacks/default.json
56
42
  ```
57
43
 
58
- 拖拽、新建、编辑、校验、查看完整预览和捕获的 payload、用 tabs 管理变量/context/regex 规则、切换深色模式、通过原始 stack JSON 修复高级字段、导入、导出、fork、删除栈 —— 全在浏览器里完成。新栈会从默认 Pi prompt mirror 布局开始。已有 stack ID 不可在保存时修改;需要新 ID 时请使用 Fork,避免破坏 profile 引用或当前选择。Stack metadata 可以折叠,方便把当前编辑区留在屏幕内。Policy tab 会显示已注册工具和已加载 skills,并提供已选 pattern chips 和过滤输入,方便用精确名称编写 allow/deny 规则,同时保留通配符写法。
44
+ 如果你通过 npm 安装而不是 clone 仓库,请直接打开 `/preset ui` 新建 stack;编辑器使用相同的 Pi mirror 布局。
59
45
 
60
- 导入支持原生 pi-forge stack JSON,也支持 SillyTavern 预设 JSON。SillyTavern 预设会自动转换成 prompt stack;如果一个预设里有多个 `character_id` 配置,编辑器会询问要使用哪一个。
61
-
62
- 编辑器默认运行在一个可用的 `127.0.0.1` 端口,并带有会话 token,所以多个 Pi 实例可以同时打开各自的编辑器。如果 Pi 在 session navigation 或新会话后重新初始化扩展,同一项目中的 `/preset ui` 会复用已有编辑器 URL,不会遗留旧 server 后再开一个新端口;resources 和 preview 在生命周期刷新后仍可使用。写入需要项目被信任,且只会写入 prompt-stack 存储目录。新建的栈会写入 `.pi/forge/prompt-stacks`;旧的 `.pi/prompt-stacks` 栈仍然可读取和编辑。保存、导入、fork、删除成功后会重新加载到当前 Pi 会话。需要时可以用 `/preset ui restart` 或 `/preset ui stop`。
63
-
64
- 要把旧栈复制到新位置,执行 `/preset migrate-stacks`。加 `--dry-run` 可先预览,加 `--overwrite` 可覆盖目标文件,加 `--delete-legacy` 会在复制成功后删除旧文件。
65
-
66
- 如果想优先使用某个端口,可以创建 `.pi/forge/config.json`。如果该端口被占用,pi-forge 会回退到其他可用端口,并显示实际 URL:
67
-
68
- ```json
69
- {
70
- "webEditor": {
71
- "port": 41738
72
- }
73
- }
74
- ```
75
-
76
- ### Agent profile
77
-
78
- Agent profile 是保存在 `.pi/forge/agent-profiles` 下的项目级 JSON 文件。先正常配置 Pi,然后捕获当前模型、思考等级和 prompt stack,就能快速创建:
46
+ 重启 Pi,或执行:
79
47
 
80
48
  ```text
81
- /profile save reviewer
82
- /profile use reviewer
49
+ /preset reload
50
+ /preset use default
83
51
  ```
84
52
 
85
- Profile 只应用一次,不会持续接管 Pi 的模型或思考等级;之后的手动修改会一直保留,直到再次执行 `/profile use reviewer`。被选中的 prompt stack 仍会在激活期间持续执行严格工具策略。
86
-
87
- 也可以直接编写 profile:
88
-
89
- ```json
90
- {
91
- "schemaVersion": 1,
92
- "type": "pi-forge.agent-profile",
93
- "id": "reviewer",
94
- "name": "Reviewer",
95
- "description": "只审查代码,不做修改。",
96
- "autoActivate": true,
97
- "model": {
98
- "provider": "provider-id",
99
- "id": "model-id"
100
- },
101
- "thinkingLevel": "high",
102
- "promptStack": "reviewer"
103
- }
104
- ```
105
-
106
- `autoActivate: true` 会在 Pi 启动全新 session 时一次性应用整个 profile。最多只能有一个 profile 请求自动应用。自动应用的 profile 优先于独立 prompt stack 的自动加载,即使它的 `promptStack` 为 `null` 也不会回退;如果没有 profile 请求自动应用,则继续使用现有的 `default.json`/`autoActivate` stack 规则。已恢复的 session branch 选择优先于这两种自动加载机制。
107
-
108
- `promptStack` 可以为 `null`。Profile v1 不保存工具名或 skill 列表;引用的 prompt stack 是工具策略和模型可见 skill 过滤的唯一来源。校验会拒绝不支持的字段,避免悄悄保留无效的生成参数或 runner 配置。
109
-
110
- `/profile preview <id>` 会解析模型、认证、思考等级支持、prompt stack 和最终工具集,但不会改变运行时。`/profile status` 显示上次应用的 profile 和当前 drift;profile provenance 会跟随 session branch 恢复用于状态显示,但 reload、resume、tree navigation 或 compaction 绝不会自动重新应用 profile。全新 session 的自动应用仍然是一次性的,因此之后的手动修改会被保留。
111
-
112
- ### 实验性前台 subagent
53
+ 没有其他 stack 或已恢复 session 选择优先时,`default.json` 会自动启用。
113
54
 
114
- 0.4 beta 可以把已有 profile 作为独立、干净、一次性的 Pi 子进程运行。无数据外发的 `forge_subagent_profiles` 工具让主 agent 查看当前已加载 profile 的 ID、名称、描述、声明的模型/思考等级/stack、当前解析状态和审批模式。用户没有指定 profile 时,主 agent 应先调用该工具,再调用 `forge_subagent`。限制严格的主 agent prompt stack 必须同时允许这两个工具名。用户也可以继续使用同一执行路径的命令:
55
+ ### 2. 打开可视化编辑器
115
56
 
116
57
  ```text
117
- /forge-agent backends
118
- /forge-agent plan reviewer 检查这个 API 设计是否正确。
119
- /forge-agent run reviewer 检查这个 API 设计是否正确。
120
- ```
121
-
122
- `plan` 会解析 profile 和 stack、编译实际将发送给 provider 的 prompt、校验不可变执行计划,然后丢弃它,不会联系 provider。`/forge-agent run` 和默认配置下的 `forge_subagent` 会先准备完全相同的精确计划,再显示审批界面。默认界面显示 agent 任务、profile/stack、provider、模型、思考等级、最终工具、工作目录、安全边界、payload 大小和执行 fingerprint。选择 **View full prompt** 可以在批准前查看完整 system prompt 和按顺序排列的 provider-bound messages;在查看器中的编辑不会生效。
123
-
124
- 如果要明确允许父 agent 无需逐次审批即可调用 `forge_subagent`,可以在受信任项目的 `.pi/forge/config.json` 中设置:
125
-
126
- ```json
127
- {
128
- "subagents": {
129
- "allowAgentInvocationWithoutApproval": true
130
- }
131
- }
132
- ```
133
-
134
- 此选项只影响模型可调用的 `forge_subagent` 工具;`/forge-agent run` 仍然需要交互审批。精确 preflight 和不可变计划校验仍会执行,tool result 也会记录 `trusted-project-config` 授权来源,但 provider transport 会在不向人类显示 prompt 的情况下开始。Profile discovery 会报告当前审批模式。未受信任项目会忽略该设置,格式错误的值会 fail closed。请把项目 config 当作授权文件:除非允许所有能调用 `forge_subagent` 的父 agent 无需再次询问就把编译后的 prompt 和可读文件内容发送给指定 provider,否则不要启用或提交此选项。
135
-
136
- 子 agent 从干净对话开始,不会自动继承主 agent 历史。它在前台运行,并使用 profile 指定的精确模型、思考等级和 prompt stack。候选工具只有 `read`、`grep`、`find` 和 `ls`,还会继续受到 stack 工具策略限制;不会加载 write/edit/shell 工具、skills、prompt templates、context files 或第三方 extensions。最终工具结果包含有界的模型可见报告和可展开的人类可见执行详情。保留的 transcript 会限制每个字符串的大小、删去类似 base64 的文本,并只保留 512 KiB 的滚动尾部,以便保留最终报告而不让 TUI 持有无界工具历史。内联图片数据会留在 child 内供所选视觉模型使用,但专用 report channel 会在任何内容进入主 session 前,把二进制 payload 替换成 MIME type 和编码体积元数据。
137
-
138
- 重要:首个 backend 是 **shared-user**,不是操作系统沙箱。只读是模型工具策略;子进程仍然拥有启动它的用户权限,因此可以读取该用户可读的绝对路径,把内容发送给所选 provider,并把文本保留在父级 tool-result details 中。Host timeout 和取消仅为 best effort。`/tree` 会从当前对话分支移除调用和结果,但被放弃的 entry 仍可能留在 Pi 的磁盘 session JSONL 中;要删除敏感的保留文本,需要删除相应 session 数据。`/tree` 也不能撤销 provider 请求、计费或外部副作用。默认工具集刻意不提供文件系统写入路径;bubblewrap 类沙箱和 staged write mode 留待后续实现。
139
-
140
- ## 使用场景
141
-
142
- ### 🎭 角色扮演 & 创意写作
143
-
144
- 让 Pi 扮演一个角色。在系统提示词中定义性格,用 user message 注入写作风格规则,用 `{{lastUserMessage}}` 在对话历史之后重新插入用户输入。
145
-
146
- 常用模式:
147
- - 把长期角色规则放在 `system` block。
148
- - 把 Pi 运行时上下文(工具、技能、项目)放在 `user` slot。
149
- - 把 `chat-history` slot 设为跳过最新用户消息。
150
- - 在最后加一个带 `{{lastUserMessage}}` 的 `user` block。
151
-
152
- 这样最新请求会更清晰,也不会重复出现。
153
-
154
- 如果想先从一个基线栈 fork 再改成角色,可以从 [examples/default-prompt-stack.json](examples/default-prompt-stack.json) 开始。
155
-
156
- ### 🧑‍💻 专注代码审查
157
-
158
- 创建一个 `reviewer.json` 栈,加入严格的审查规则,例如“优先检查正确性、回归风险、安全问题和缺失测试”。保留 `tools`、`project-context`、`variables` 和 `chat-history` slot,这样 Pi 仍然能检查仓库并看到你暴露的模板变量。
159
-
160
- 如果你想保留 Pi 原本的编程行为,只额外加上更严格的审查视角,可以使用 `mode: "append"`。
161
-
162
- ### 🌐 翻译模式
163
-
164
- 创建一个小型 `translator.json` 栈,用一个 system block 指定语气和目标语言,再保留 `chat-history` 和 `{{lastUserMessage}}` 的布局。这样可以在双语润色、直译、产品本地化审查之间快速切换,而不影响默认助手。
165
-
166
- ### 🔀 多模式切换
167
-
168
- 为不同任务创建独立的栈:
169
-
170
- ```
171
- .pi/forge/prompt-stacks/
172
- coder.json # 严格编程助手
173
- writer.json # 创意写作搭档
174
- translator.json # 双语翻译
175
- ```
176
-
177
- 用 `/preset use coder`、`/preset use writer` 等命令切换。
178
-
179
- ### 🧪 展示 pi-forge 特性的预设
180
-
181
- - **Pi mirror** — 从 [examples/default-prompt-stack.json](examples/default-prompt-stack.json) 开始。它保留 Pi 的默认行为,同时把每个运行时区块变成可移动、可检查的 slot。
182
- - **Focused reviewer** — 见 [examples/reviewer-prompt-stack.json](examples/reviewer-prompt-stack.json)。它禁用写文件工具,把旧聊天历史包裹成背景上下文,从 history 中移除最新用户消息,再用 `{{lastUserMessage}}` 作为明确的 review target 插入。
183
- - **SillyTavern DM writer** — 见 [examples/sillytavern-dm-writer-prompt-stack.json](examples/sillytavern-dm-writer-prompt-stack.json)。它用 `{{char}}` / `{{user}}` 定义 Dungeon Master 角色,包裹旧冒险历史,把 `{{lastUserMessage}}` 作为当前玩家行动重新插入,并用 regex 清理 OOC 注释、暗骰标记、骰子写法和 `Player:` 前缀。
184
-
185
- ### 🔧 模板变量
186
-
187
- 定义稳定的 prompt 常量:
188
-
189
- ```json
190
- "variables": {
191
- "char": "Konata",
192
- "user": "User"
193
- }
194
- ```
195
-
196
- 在 prompt 文本里用 ST 风格宏做局部变量读写:
197
-
198
- ```
199
- {{setvar::mood::focused}}
200
- {{getvar::mood}}
201
- {{setsessionvar::topic::compiler cleanup}}
202
- ```
203
-
204
- 需要长期保存的项目记忆请写入仓库文件,而不是 pi-forge prompt 变量。
205
-
206
- ### 📦 SillyTavern 迁移
207
-
208
- 把 ST 预设导入 Pi:
209
-
210
- ```
211
- /preset import-silly ~/SillyTavern/presets/my-preset.json
58
+ /preset ui
212
59
  ```
213
60
 
214
- pi-forge 会把预设转换为 prompt stack,并生成迁移报告,标明哪些已处理、哪些需要手动调整。
215
-
216
- 可安全表示的 SillyTavern `promptOnly` regex 脚本会作为 history 阶段规则转换成 pi-forge `regex.rules`,包括 full-match token 转换、trim strings、depth 字段和明确的 user/assistant placement。Display-only、prompt/display 混合、DOM/browser、CSS/HTML 美化、JavaScript、不支持的 placement 和无效 regex 脚本会保留为报告项,供手动检查。
217
-
218
- ### 🔍 Prompt 调试
219
-
220
- 查看实际发给模型的内容:
221
-
222
- ```
223
- /payload next save=.pi/forge/payloads/last.json
224
- ```
61
+ 本地编辑器可以新建、fork、校验、预览、导入、导出和删除 prompt stack,并可在新建/fork/导入时明确选择写入项目或用户全局存储。切换到 **Agent profiles** 可以浏览项目与全局 profile、编辑和删除全局 profile(通过显式 `global:<id>` 路由),并管理实验性 delegation 配置。写入操作要求项目已被信任。
225
62
 
226
- 或者打开 `/preset ui`,点击 **Arm payload**,发送下一条 Pi prompt,然后在浏览器里查看脱敏后的 provider payload。凭据形式的 token 字段仍会隐藏,而 `max_tokens`、`input_tokens`、`output_tokens` 等正常限制和计数字段会保留显示。
63
+ ### 3. 保存 profile
227
64
 
228
- 或者不发送只预览编译结果:
65
+ 先正常配置 Pi,然后捕获当前设置:
229
66
 
67
+ ```text
68
+ /profile save reviewer
69
+ /profile use reviewer
230
70
  ```
231
- /preset preview
232
- ```
233
-
234
- ## 工作原理
235
71
 
236
- 一个 prompt stack 是一个 JSON 文件,包含两种条目:
72
+ Profile 只应用一次。之后手动修改模型或思考等级会被保留,直到再次应用 profile;当前 prompt stack 的工具策略则会在启用期间持续执行。
237
73
 
238
- | 类型 | 作用 |
239
- |------|------|
240
- | **Block** | 在指定位置插入的静态文本(系统提示词、用户消息、助手消息) |
241
- | **Slot** | 来自 Pi 运行时的动态内容 —— 工具、技能、对话历史、日期、项目上下文等 |
74
+ ## 基本概念
242
75
 
243
- 条目按顺序排列。当栈激活时,pi-forge 会:
76
+ Prompt stack 是一个有序 JSON 文档,包含:
244
77
 
245
- 1. 用你的 `system` 角色 block 和 slot 生成系统提示词,然后按照栈的 `mode` 应用。
246
- 2. 在对话历史周围插入 `user`/`assistant` 角色的 block 和 slot。
247
- 3. 展开 `{{宏}}`,如 `{{lastUserMessage}}`、`{{date}}` 和自定义变量。
248
- 4. 将 stack 的工具策略应用到 Pi 当前 active tools,并过滤 pi-forge 渲染的 tool/skill slot。
249
- 5. 应用已启用的 `history` 和 `compiled` 阶段 outgoing regex 规则。
250
- 6. 可选地在 assistant 消息结束时应用破坏性的 `finalize` regex 规则。
78
+ | 类型 | 用途 |
79
+ |---|---|
80
+ | **Block** | 固定的 `system`、`user`、`assistant` 或隐藏 `custom` 文本 |
81
+ | **Slot** | 工具、skills、项目上下文、变量、日期/cwd、聊天历史等运行时内容 |
251
82
 
252
- ### Slot 一览
83
+ Stack 可以 `replace`、`append` 或 `prepend` Pi 的基础 system prompt。编译时,pi-forge 会展开宏、插入对话、执行工具策略、过滤自己渲染的 skill 列表,并应用已启用的 regex 规则。
253
84
 
254
- | Slot | 插入的内容 |
255
- |------|-----------|
256
- | `chat-history` | 当前对话 |
257
- | `tools` | 可用工具及其描述 |
258
- | `tool-guidelines` | 工具使用指导 |
259
- | `skills` | 已加载的 Pi 技能 |
260
- | `project-context` | 项目指令和上下文文件 |
261
- | `variables` | 静态/会话/轮次模板变量 |
262
- | `date` / `cwd` / `date-cwd` | 当前日期、可选当前时间和工作目录 |
263
- | `active-model` | 当前使用的模型 |
264
- | `append-system-prompt` | 用户追加的系统提示词 |
265
- | `pi-docs` | Pi 文档指导 |
85
+ Agent profile 是项目级或用户全局预设,引用精确 provider/model、思考等级和 prompt stack。它不会重复保存工具或 skill 策略;被引用的 stack 始终是唯一来源。项目 profile 和 stack 可以遮蔽同 ID 的全局资源;需要精确选择时使用 `project:<id>` 或 `global:<id>`。
266
86
 
267
- ### 模式
87
+ 推荐从这些示例开始:
268
88
 
269
- - **replace**(默认)— 你的栈完全替换 Pi 的系统提示词。
270
- - **append** — 你的栈追加在 Pi 默认系统提示词之后。
271
- - **prepend** — 你的栈插入在 Pi 默认系统提示词之前。
89
+ - [默认 Pi mirror](examples/default-prompt-stack.json):保留 Pi 默认行为,同时让所有区域都可移动。
90
+ - [专注代码审查](examples/reviewer-prompt-stack.json):只读工具策略、背景历史和明确的最新用户目标。
91
+ - [SillyTavern DM writer](examples/sillytavern-dm-writer-prompt-stack.json):角色、变量、历史布局和 regex 清理。
92
+ - [自定义 system-status extension](examples/custom-system-status-extension/README.md):注册可信 macro 和 slot。
272
93
 
273
94
  ## 常用命令
274
95
 
275
- ### 管理 prompt stack
276
-
277
- | 命令 | 作用 |
278
- |------|------|
279
- | `/preset list` | 显示所有可用栈 |
280
- | `/preset use <id>` | 激活一个栈 |
281
- | `/preset use none` | 在当前会话中禁用 prompt stack |
282
- | `/preset preview [id]` | 查看编译后的 prompt |
283
- | `/preset validate [id]` | 检查栈是否有问题 |
284
- | `/preset status` | 显示当前激活栈和诊断摘要 |
285
- | `/preset diagnostics` | 显示运行时诊断 |
286
- | `/preset reload` | 从磁盘重新加载栈 |
287
- | `/preset migrate-stacks [--dry-run] [--overwrite] [--delete-legacy]` | 将旧 `.pi/prompt-stacks` 文件复制到 `.pi/forge/prompt-stacks` |
288
- | `/preset ui [stop\|restart]` | 打开、停止或重启 Web 编辑器 |
289
-
290
- ### 管理 agent profile
291
-
292
- | 命令 | 作用 |
293
- |------|------|
294
- | `/profile list` | 显示项目 profile 和解析诊断 |
295
- | `/profile use <id>` | 预检并一次性应用 profile |
296
- | `/profile save <id> [--overwrite]` | 捕获当前模型、思考等级和 prompt stack |
297
- | `/profile status` | 显示当前运行时、上次应用来源和 drift |
298
- | `/profile preview <id>` | 不应用,只预览解析结果和最终工具 |
299
- | `/profile validate [id]` | 校验一个 profile;省略 id 时校验全部 |
300
- | `/profile reload` | 从磁盘重新加载 profile,但不应用 |
301
- | `/profile forget` | 忘记上次应用来源,不改变运行时 |
302
-
303
- ### 实验性前台 subagent
304
-
305
- | 命令 | 作用 |
306
- |------|------|
307
- | `/forge-agent backends` | 显示实验性 backend 及其能力 |
308
- | `/forge-agent plan <profile> <task>` | 不进行 provider transport,准备、校验、显示并丢弃精确执行计划 |
309
- | `/forge-agent run <profile> <task>` | 审查精确计划并在批准后运行一个前台只读文本任务 |
310
-
311
- 模型可调用的工具包括用于本地元数据发现的 `forge_subagent_profiles`,以及用于执行的 `forge_subagent`。发现工具不需要审批,也不会请求 provider 或准备 subagent prompt。当前主 agent 工具策略必须允许执行工具;之后还必须存在交互式审批 UI,或者启用上文明确说明的受信任项目免审批选项,subagent 才可运行。
312
-
313
- ### 导入 & 调试
314
-
315
- | 命令 | 作用 |
316
- |------|------|
317
- | `/preset import-silly <path>` | 导入 SillyTavern 预设 |
318
- | `/intercept` | 显示下一条 provider payload |
319
- | `/payload next [save=<path>]` | 显示并可保存下一条 payload |
320
-
321
- ## 常用宏
322
-
323
- 在 block 内容中使用这些宏来插入动态值:
324
-
325
- | 宏 | 展开为 |
326
- |----|--------|
327
- | `{{lastUserMessage}}` | 用户最新消息 |
328
- | `{{date}}` | 当前日期 (YYYY-MM-DD) |
329
- | `{{time}}` | 当前时间 (HH:MM:SS) |
330
- | `{{cwd}}` | 当前工作目录 |
331
- | `{{tools}}` | 逗号分隔的工具名 |
332
- | `{{selectedTools}}` | 所选工具名的别名 |
333
- | `{{activeModel}}` | 当前模型 (provider/id) |
334
- | `{{char}}` / `{{user}}` | 栈中定义的自定义变量 |
335
-
336
- ### 变量宏
337
-
338
- ```
339
- {{setvar::name::value}} 设置轮次变量(每条消息清空)
340
- {{setsessionvar::name::value}} 设置会话变量(持久化)
341
- {{setvar::session::name::value}} 也可设置会话变量
342
- {{getvar::name}} 读取变量(轮次 → 会话 → 静态)
343
- {{getturnvar::name}} 只读取轮次变量
344
- {{getsessionvar::name}} 只读取会话变量
345
- {{clearvar::name}} 清除变量
346
- {{clearturnvar::name}} 清除轮次变量
347
- {{clearsessionvar::name}} 清除会话变量
348
- ```
349
-
350
- ### 过滤和条件宏
351
-
352
- 宏支持嵌套,`::` 分隔符只会在当前宏深度拆分。
353
-
354
- | 宏 | 展开为 |
355
- |----|--------|
356
- | `{{trim::value}}` | 去掉首尾空白后的 `value` |
357
- | `{{upper::value}}` | 大写 `value` |
358
- | `{{lower::value}}` | 小写 `value` |
359
- | `{{json::value}}` | `value` 的 JSON 字符串字面量 |
360
- | `{{xml::value}}` | XML 转义后的 `value` |
361
- | `{{ifvar::name::then::else}}` | 变量存在时输出 `then`,否则输出 `else` |
362
- | `{{ifeq::name::expected::then::else}}` | 变量等于 `expected` 时输出 `then`,否则输出 `else` |
363
- | `{{iftools::tool::then::else}}` | 当前工具列表包含 `tool` 时输出 `then`,否则输出 `else` |
364
- | `{{ifslot::slot::then::else}}` | 启用的 stack 条目包含 `slot` 时输出 `then`,否则输出 `else` |
365
-
366
- 条件宏是 lazy 的:只有选中的分支会展开,所以被跳过的分支不会设置或清除变量。最后的 `else` 参数可省略,默认输出空文本。
367
-
368
- ### 可信自定义宏和 slot
369
-
370
- 自定义宏和 slot 由可信扩展代码注册,不把可执行代码写进 prompt-stack JSON。项目本地自定义代码放在 `.pi/forge/extensions/`。机器级个人自定义代码放在 `~/.pi/forge/extensions/`。pi-forge 会在项目受信任后、stack 校验前先加载全局模块,再加载项目本地模块;两个位置都会在 `/preset reload` 时重新加载。
371
-
372
- 这些模块会从 pi-forge 接收注册 API,所以不需要 import `@zihanw/pi-forge`,也不需要知道 pi-forge 安装在哪里。
373
-
374
- ```ts
375
- // .pi/forge/extensions/ticket-context.ts
376
- export default function register(api) {
377
- api.registerMacro({
378
- name: "ticketId",
379
- description: "从会话变量读取当前 ticket id。",
380
- render: (ctx) => ctx.variables.toMacroText(ctx.variables.get("ticket.id")),
381
- });
382
-
383
- api.registerSlot({
384
- name: "ticket-context",
385
- description: "渲染当前任务的 ticket 上下文。",
386
- options: {
387
- heading: { type: "string", default: "Ticket context" },
388
- },
389
- render: (ctx) => [
390
- String(ctx.options.heading ?? "Ticket context") + ":",
391
- "- Ticket: " + ctx.variables.toMacroText(ctx.variables.get("ticket.id")),
392
- "- Project: " + ctx.helpers.normalizePath(ctx.runtime.options.cwd),
393
- ].join("\n"),
394
- });
395
- }
396
- ```
397
-
398
- 支持 `.ts`、`.js`、`.mjs`、`.cjs` 文件,也支持子目录里的 `index.*`。TypeScript 模块应使用 Node 运行时可直接 strip 的语法;如果需要更复杂的构建,使用 `.js` / `.mjs`。模块可以导出 `default function register(api)`,也可以导出具名 `register(api)`。注册的宏和 slot 名称必须在内置项、全局扩展、项目扩展之间唯一;重复名称会显示为扩展加载 warning。
399
-
400
- API 包含 `cwd`、`forgeDir`、`extensionPath`、`helpers`、`registerMacro`、`registerSlot`、`getRegisteredMacros`、`getRegisteredSlots`。对全局模块来说,`forgeDir` 是 `~/.pi/forge`;对项目模块来说,它是 `<project>/.pi/forge`。
401
-
402
- 缺失的自定义 slot 会产生校验 warning,直到对应注册模块加载。内置宏和 slot 也使用同一个 registry,可用 `getRegisteredMacros()` 和 `getRegisteredSlots()` 作为实现参考。`/preset diagnostics` 会显示已加载的 pi-forge extension 文件和加载失败信息。
403
-
404
- 完整可复制的扩展和 stack 示例见 [examples/custom-system-status-extension](examples/custom-system-status-extension)。它通过 `.pi/forge/extensions/system-status.ts` 注册 `{{cpuLoad}}` 宏和 `machine-status` slot。
405
-
406
- 可复用的 Pi package 仍然可以从 `@zihanw/pi-forge` import `registerMacro` 和 `registerSlot`。`.pi/forge/extensions` 和 `~/.pi/forge/extensions` loader 主要用于不需要 package 样板的小型可信自定义逻辑。
407
-
408
- ## Stack 参考
409
-
410
- ### 完整条目类型
411
-
412
- **Block:**
413
-
414
- ```json
415
- {
416
- "kind": "block",
417
- "id": "unique-id",
418
- "name": "可读标签",
419
- "enabled": true,
420
- "role": "system",
421
- "content": "你的文本。用 {{宏}} 插入动态内容。"
422
- }
423
- ```
424
-
425
- 有效角色:`system`、`user`、`assistant`、`custom`。
426
-
427
- **Slot:**
428
-
429
- ```json
430
- {
431
- "kind": "slot",
432
- "id": "unique-id",
433
- "name": "对话历史",
434
- "enabled": true,
435
- "role": "user",
436
- "slot": "chat-history",
437
- "options": {
438
- "includeLastUserMessage": false
439
- }
440
- }
441
- ```
442
-
443
- ### Chat history 选项
444
-
445
- ```json
446
- "options": {
447
- "includeLastUserMessage": false,
448
- "stripAssistantThinking": true,
449
- "includeSummaries": true,
450
- "toolMode": "keep",
451
- "roles": ["user", "assistant"],
452
- "maxMessages": 40,
453
- "maxChars": 20000
454
- }
455
- ```
456
-
457
- 当你在 history 之后使用 `{{lastUserMessage}}` 时设为 `false`,避免用户消息出现两次。
458
-
459
- 把 `stripAssistantThinking` 设为 `true` 可以从插入的历史中移除之前 assistant 的 thinking block。可见 assistant 文本、tool call 和 tool result 消息会保留。它只影响这个 slot 插入到模型输入里的 history,不会修改当前 agent loop 或已存储 transcript。
460
-
461
- 使用 `includeSummaries: false` 可以排除 Pi 的 branch/compaction summary 消息;`roles` 可以只保留指定消息角色;`toolMode: "drop"` 可以移除之前的 tool call/tool result history;`maxMessages` / `maxChars` 可以只保留最近 history。当过滤或截断可能拆散 tool-call pair 时,pi-forge 会移除悬空的 tool call/result,避免发送不一致的 tool history。
462
-
463
- ### Date slot 选项
464
-
465
- 在 `date` 或 `date-cwd` slot 上设置 `"includeTime": true`,会在当前日期后加入 `HH:MM:SS` 格式的当前时间。
466
-
467
- ### 结构化 slot 格式选项
468
-
469
- 结构化运行时 slot 默认使用 XML 风格包装。给 `tools`、`tool-guidelines`、`skills`、`project-context` 或 `variables` slot 添加 `"format": "plain"`,可输出更紧凑的换行分隔文本。
470
-
471
- ```json
472
- {
473
- "kind": "slot",
474
- "id": "tools",
475
- "enabled": true,
476
- "role": "system",
477
- "slot": "tools",
478
- "options": {
479
- "format": "plain"
480
- }
481
- }
482
- ```
483
-
484
- 默认 Pi mirror 示例还会用到几个额外 slot 选项:
485
-
486
- ```json
487
- {
488
- "slot": "tools",
489
- "options": {
490
- "format": "plain",
491
- "onlyWithSnippets": true
492
- }
493
- }
494
- ```
495
-
496
- `tools.onlyWithSnippets` 会像 Pi 默认 prompt 一样,只显示带 prompt snippet 的工具。`tool-guidelines.heading`、`tool-guidelines.includePiDefaultGuidelines` 和 `tool-guidelines.piStyle` 用来匹配 Pi 默认的 guidelines 标题和条目。`skills.requireReadTool` 会在 read 工具未启用时隐藏 skills,和 Pi 默认行为一致。
497
-
498
- ### 工具和技能策略
499
-
500
- Prompt stack 可以用栈级 `allow` 或 `deny` 列表限制 active tools,并过滤模型可见的技能。模式默认精确匹配,也支持 `*` 通配符。
501
-
502
- ```json
503
- {
504
- "tools": {
505
- "allow": ["read", "bash"]
506
- },
507
- "skills": {
508
- "deny": ["browser-danger"]
509
- }
510
- }
511
- ```
512
-
513
- 对于工具,`allow` 只保留匹配的 active tools,`deny` 移除匹配的 active tools。对于技能,同样的 pattern 控制哪些技能保留在 pi-forge 渲染的 `skills` slot 中。同一个资源策略不能同时包含非空 `allow` 和 `deny` 列表;混用会产生 validation error。
514
-
515
- 工具策略会在栈激活期间通过 Pi 的 active tool list 强制执行。启动和 reload 时,pi-forge 会等其它扩展完成 `session_start` 工具配置,再记录 baseline 并应用 stack 策略;之后还会在用户输入和 turn 开始前重新应用策略。即使其它扩展稍后调用 `setActiveTools()`,tool-call guard 也会阻止模型执行策略之外的工具。外部扩展新增的工具会保留在可恢复 baseline 中,并在禁用 prompt stack 或切换到没有工具策略的 stack 时恢复。
516
-
517
- 技能策略会过滤 pi-forge `skills` slot 渲染出的技能。它不会禁用显式技能调用,也不是 capability 或安全边界。如果 stack 使用 `mode: "append"` 或 `"prepend"`,Pi base prompt 里可能已经包含未过滤的技能;需要控制模型可见的技能列表时请使用 `mode: "replace"`。
518
-
519
- ### Regex 转换
520
-
521
- Prompt stack 可以对发给模型的 prompt 文本执行确定性的 regex 替换,也可以选择清理已结束的 assistant 消息。Outgoing 规则支持 `history` 和 `compiled` 阶段。破坏性的最终消息清理使用 `stage: "compiled"`、`effect: "finalize"` 和 `messages` target。真正的 display-only streaming 转换和 provider-payload 重写还不会生效。
522
-
523
- ```json
524
- "regex": {
525
- "schemaVersion": 1,
526
- "rules": [
527
- {
528
- "id": "trim-ooc",
529
- "enabled": true,
530
- "stage": "history",
531
- "effect": "outgoing",
532
- "pattern": "\\(OOC:[^)]+\\)",
533
- "flags": "gi",
534
- "replace": "",
535
- "roles": ["assistant"],
536
- "maxMessages": 20
537
- }
538
- ]
539
- }
540
- ```
541
-
542
- 使用 `stage: "history"` 可以转换 `chat-history` slot 插入的消息。使用 `stage: "compiled"` 并可选配置 `targets: ["system"]`、`["messages"]` 或两者,可以转换最终编译后的 prompt。消息规则可以用 `roles`、`maxMessages`、`maxChars`、`minDepth` 和 `maxDepth` 限制范围,其中 depth `0` 是最新消息。Replacement 使用 JavaScript 语法(`$&` 表示完整匹配,`$1` 表示捕获组;`$0` 也作为完整匹配的别名,`$$` 转义字面 `$`)。`trimStrings` 会从展开后的 replacement match/capture 中移除字面量字符串,对应 SillyTavern 的 Trim Out 行为。支持的 regex flags 是 `g`、`i`、`m`、`s` 和 `u`。
543
-
544
- 要在 streaming 结束后清理一条 assistant 消息,使用 `effect: "finalize"`:
545
-
546
- ```json
547
- {
548
- "id": "finalize-ooc",
549
- "enabled": true,
550
- "stage": "compiled",
551
- "effect": "finalize",
552
- "targets": ["messages"],
553
- "roles": ["assistant"],
554
- "pattern": "\\s*\\(OOC:[^)]+\\)",
555
- "flags": "gi",
556
- "replace": ""
557
- }
558
- ```
96
+ | 命令 | 用途 |
97
+ |---|---|
98
+ | `/preset ui [stop\|restart]` | 打开或管理 Web 编辑器 |
99
+ | `/preset list` | 列出 prompt stack |
100
+ | `/preset use <id\|none>` | 选择或禁用 stack |
101
+ | `/preset preview [id]` | 编译 stack,但不发送请求 |
102
+ | `/preset validate [id]` | 校验一个或全部 stack |
103
+ | `/preset diagnostics` | 查看运行时和 extension 诊断 |
104
+ | `/profile list` | 列出并 preflight profile |
105
+ | `/profile save <id> [--overwrite]` | 把当前运行时保存为 profile |
106
+ | `/profile use <id>` | preflight 后一次性应用 profile |
107
+ | `/profile status` | 查看上次应用 provenance 和当前 drift |
108
+ | `/payload next [save=<path>]` | 检查下一个经过脱敏的 provider payload |
559
109
 
560
- 警告:`finalize` 在 `message_end` 运行,TUI 可能已经显示过原始 streaming 输出。它会把清理后的 replacement message 交回 Pi,因此 transcript 中不会保留模型原始输出。
110
+ 完整列表见[命令参考](docs/zh-CN/reference/commands.md)。
561
111
 
562
- `effect: "outgoing"` 改变发给模型的输入。`effect: "finalize"` 改变已结束的 assistant transcript 内容。`effect: "display"` 和 `"both"` 会通过校验并产生 warning,但在真正的 display transforms 实现前运行时会忽略。
112
+ ## 实验性前台 delegation
563
113
 
564
- SillyTavern 导入会把确定性的 prompt-only `{{match}}` / `$0` full-match replacement 转成 JavaScript `$&`(`$0` 和 `$&` 在 pi-forge 中都可以用),在 `source.sillytavern` 中保留原始 regex 元数据,并作为 history 阶段规则运行以保持 depth 相对 chat。display-only、browser、unsupported-placement 脚本保留为 report-only。Web 编辑器提供结构化 Regex 对话框来编辑这些规则字段,并会保留需要通过 raw JSON 编辑的高级未知字段。
114
+ pi-forge 可以把明确授权的 profile 作为干净、前台运行的 Pi 子进程。模型通过 `forge_subagent_profiles` 发现可用 profile,再用 `forge_subagent` 调用;用户可以使用 `/forge-agent plan` 和 `/forge-agent run`。
565
115
 
566
- ### Variables slot 选项
116
+ 此功能仍是**实验性功能**,profile 默认不能委派。请在可信项目的 `.pi/forge/config.json`(授权 `project:<id>`)或用户全局 `~/.pi/forge/config.json`(授权 `global:<id>`)中逐个启用,也可以使用 Web 编辑器 delegation 卡片。除非项目明确授权无人值守的模型调用,否则执行前会显示与不可变计划绑定的审批界面。
567
117
 
568
- ```json
569
- {
570
- "kind": "slot",
571
- "id": "variables",
572
- "enabled": true,
573
- "role": "user",
574
- "slot": "variables",
575
- "options": {
576
- "includeStatic": true,
577
- "includeSession": true,
578
- "includeTurn": false,
579
- "format": "xml"
580
- }
581
- }
582
- ```
118
+ > **安全边界:** 当前 backend 是 shared-user 进程,不是操作系统沙箱。“只读”只描述模型可见工具策略。Child 仍有启动用户的 OS 读取权限;可读内容可能发送给所选 provider,并保留在 Pi session 数据中。Timeout 和取消仅为 best effort,`/tree` 不能撤销 provider 请求、计费或外部影响。
583
119
 
584
- ## 开发环境搭建
120
+ 启用前必须阅读[前台 delegation 与安全模型](docs/zh-CN/guides/delegation.md)。
585
121
 
586
- ```bash
587
- git clone https://github.com/MacroSony/pi-forge.git
588
- cd pi-forge
589
- npm install
590
- npm run build
591
- # .pi/settings.json 会加载 package 构建后的 dist/index.js
592
- pi # 启动 Pi,信任项目,必要时 /reload
593
- ```
122
+ ## 文档导航
594
123
 
595
- npm package 会有意省略实际的 `src/` 文件,并在运行时加载编译后的 `dist/`。需要查看或修改 pi-forge 本身时,请 clone 或 fork 仓库,不要直接修改 `node_modules` 或生成的 `dist/`。仓库 clone 可以用 Git 保留改动,并包含开发依赖、测试以及 source-to-dist 一致性检查。
124
+ ### 学习
596
125
 
597
- 进行接近 release 的本地测试时,在 `.pi/settings.json` 中注册 clone 后的 package 目录;package manifest 会加载已跟踪的 `dist/index.js`:
126
+ - [快速上手](docs/zh-CN/getting-started.md)
127
+ - [Prompt stack 概念](docs/zh-CN/concepts/prompt-stacks.md)
128
+ - [Agent profile 概念](docs/zh-CN/concepts/agent-profiles.md)
129
+ - [Web 编辑器](docs/zh-CN/guides/web-editor.md)
130
+ - [前台 delegation](docs/zh-CN/guides/delegation.md)
598
131
 
599
- ```json
600
- {
601
- "packages": ["../pi-forge"]
602
- }
603
- ```
132
+ ### 参考
604
133
 
605
- 进行实时源码开发时,请移除上面的 pi-forge package entry,再通过 `.pi/settings.json` 直接加载 TypeScript extension:
134
+ - [命令](docs/zh-CN/reference/commands.md)
135
+ - [英文 stack schema](docs/reference/stack-schema.md)
136
+ - [英文 macros 与 slots](docs/reference/macros-and-slots.md)
137
+ - [英文配置参考](docs/reference/configuration.md)
606
138
 
607
- ```json
608
- {
609
- "extensions": ["../pi-forge/src/index.ts"]
610
- }
611
- ```
612
-
613
- 也可以用 `pi -e ../pi-forge/src/index.ts` 做一次性的源码级 smoke test。不要同时加载 package 和 source entry,否则 pi-forge 会初始化两次。修改 browser client 源码后还需要执行 `npm run build:client`,因为本地编辑器提供的是生成后的 browser bundle。
139
+ 完整英文文档从 [docs/README.md](docs/README.md) 开始。
614
140
 
615
- 运行测试:
616
-
617
- ```bash
618
- npm test
619
- ```
620
-
621
- 运行真实浏览器中的编辑器 smoke test(如果 Chrome 不在标准路径,请设置 `CHROME_PATH`):
622
-
623
- ```bash
624
- npm run test:browser
625
- ```
626
-
627
- 类型检查:
628
-
629
- ```bash
630
- npm run typecheck
631
- ```
632
-
633
- 构建 package 输出:
634
-
635
- ```bash
636
- npm run build
637
- ```
638
-
639
- 运行完整仓库验证,包括在临时目录中执行干净构建,并逐字节检查已跟踪的 `dist/` 是否与 `src/` 一致:
640
-
641
- ```bash
642
- npm run verify
643
- ```
141
+ ## 兼容性原则
644
142
 
645
- CI 会运行同一套验证。源代码变更影响生成输出时,请运行 `npm run build`,并将对应的 `dist/` 变更与源代码一起提交。
143
+ - npm 安装不会要求用户跟随某个精确 Pi patch 版本。
144
+ - Release 会分别记录实际测试过的 Pi 最低版本和当前版本。
145
+ - 如果实验性 subagent 依赖的 host capability 不存在,它应在 provider transport 前明确报错并 fail closed。
146
+ - 普通 prompt stack 和 profile 使用不应因为可选 delegation backend 不兼容而失效。
646
147
 
647
148
  ## License
648
149
 
649
- MIT
150
+ [MIT](LICENSE)