pi-namespace-patch 0.85.1 → 0.86.0-namespace.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 (317) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/README.md +26 -705
  3. package/dist/bundle/chunks/anthropic-messages-MYU5ZMRF.js +6 -0
  4. package/dist/bundle/chunks/azure-openai-responses-HUSQ3GP2.js +2 -0
  5. package/dist/bundle/chunks/bedrock-converse-stream.js +47 -38
  6. package/dist/bundle/chunks/chunk-A3JYRWB6.js +2 -0
  7. package/dist/bundle/chunks/chunk-DTD7JQ7Y.js +42 -0
  8. package/dist/bundle/chunks/chunk-FUXEF6JQ.js +44 -0
  9. package/dist/bundle/chunks/chunk-IS2VY2NY.js +1561 -0
  10. package/dist/bundle/chunks/{chunk-IDDQWTHI.js → chunk-RCZIEVGO.js} +10 -1
  11. package/dist/bundle/chunks/chunk-S7SZN6Z3.js +2 -0
  12. package/dist/bundle/chunks/chunk-SXW7XMQG.js +2 -0
  13. package/dist/bundle/chunks/chunk-WIUZI2CJ.js +11 -0
  14. package/dist/bundle/chunks/github-copilot.js +1 -1
  15. package/dist/bundle/chunks/google-generative-ai-IMS5EK2Y.js +2 -0
  16. package/dist/bundle/chunks/google-vertex-O4YJEQUW.js +2 -0
  17. package/dist/bundle/chunks/jiti-loader-C3NU2SDH.js +21 -0
  18. package/dist/bundle/chunks/jiti-static-loader-E6ANQD5T.js +2 -0
  19. package/dist/bundle/chunks/mistral-conversations-NOSQHBEY.js +5 -0
  20. package/dist/bundle/chunks/{node-KG362ECQ.js → node-O3RIBJRH.js} +1 -1
  21. package/dist/bundle/chunks/openai-codex-responses-QDSOTBBO.js +10 -0
  22. package/dist/bundle/chunks/openai-completions-KQPOPEVM.js +7 -0
  23. package/dist/bundle/chunks/openai-responses-HWEUZ6WZ.js +2 -0
  24. package/dist/bundle/chunks/{pi-messages-PML4SPVJ.js → pi-messages-GFKBWJHZ.js} +1 -1
  25. package/dist/bundle/chunks/virtual-modules-UQVS3IVK.js +2 -0
  26. package/dist/bundle/cli.js +1 -1
  27. package/dist/bundle/index.js +1 -1
  28. package/dist/bundle/rpc-entry.js +1 -1
  29. package/dist/cli/session-picker.d.ts +1 -1
  30. package/dist/cli/session-picker.d.ts.map +1 -1
  31. package/dist/cli/session-picker.js.map +1 -1
  32. package/dist/config.d.ts.map +1 -1
  33. package/dist/config.js +1 -1
  34. package/dist/config.js.map +1 -1
  35. package/dist/core/agent-session.d.ts +56 -6
  36. package/dist/core/agent-session.d.ts.map +1 -1
  37. package/dist/core/agent-session.js +294 -157
  38. package/dist/core/agent-session.js.map +1 -1
  39. package/dist/core/bug-report-upload.d.ts +12 -0
  40. package/dist/core/bug-report-upload.d.ts.map +1 -0
  41. package/dist/core/bug-report-upload.js +22 -0
  42. package/dist/core/bug-report-upload.js.map +1 -0
  43. package/dist/core/bug-report.d.ts +176 -0
  44. package/dist/core/bug-report.d.ts.map +1 -0
  45. package/dist/core/bug-report.js +292 -0
  46. package/dist/core/bug-report.js.map +1 -0
  47. package/dist/core/cache-stats.d.ts.map +1 -1
  48. package/dist/core/cache-stats.js +12 -1
  49. package/dist/core/cache-stats.js.map +1 -1
  50. package/dist/core/cache-warmer.d.ts +102 -0
  51. package/dist/core/cache-warmer.d.ts.map +1 -0
  52. package/dist/core/cache-warmer.js +342 -0
  53. package/dist/core/cache-warmer.js.map +1 -0
  54. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  55. package/dist/core/compaction/branch-summarization.js +2 -2
  56. package/dist/core/compaction/branch-summarization.js.map +1 -1
  57. package/dist/core/compaction/compaction.d.ts +2 -2
  58. package/dist/core/compaction/compaction.d.ts.map +1 -1
  59. package/dist/core/compaction/compaction.js +11 -12
  60. package/dist/core/compaction/compaction.js.map +1 -1
  61. package/dist/core/crash-log.d.ts +22 -0
  62. package/dist/core/crash-log.d.ts.map +1 -0
  63. package/dist/core/crash-log.js +71 -0
  64. package/dist/core/crash-log.js.map +1 -0
  65. package/dist/core/experimental.d.ts +0 -4
  66. package/dist/core/experimental.d.ts.map +1 -1
  67. package/dist/core/experimental.js +0 -4
  68. package/dist/core/experimental.js.map +1 -1
  69. package/dist/core/extensions/index.d.ts +1 -1
  70. package/dist/core/extensions/index.d.ts.map +1 -1
  71. package/dist/core/extensions/index.js.map +1 -1
  72. package/dist/core/extensions/jiti-loader.d.ts +2 -0
  73. package/dist/core/extensions/jiti-loader.d.ts.map +1 -0
  74. package/dist/core/extensions/jiti-loader.js +4 -0
  75. package/dist/core/extensions/jiti-loader.js.map +1 -0
  76. package/dist/core/extensions/jiti-static-loader.d.ts +2 -0
  77. package/dist/core/extensions/jiti-static-loader.d.ts.map +1 -0
  78. package/dist/core/extensions/jiti-static-loader.js +4 -0
  79. package/dist/core/extensions/jiti-static-loader.js.map +1 -0
  80. package/dist/core/extensions/loader.d.ts.map +1 -1
  81. package/dist/core/extensions/loader.js +38 -51
  82. package/dist/core/extensions/loader.js.map +1 -1
  83. package/dist/core/extensions/runner.d.ts +10 -7
  84. package/dist/core/extensions/runner.d.ts.map +1 -1
  85. package/dist/core/extensions/runner.js +85 -67
  86. package/dist/core/extensions/runner.js.map +1 -1
  87. package/dist/core/extensions/types.d.ts +60 -50
  88. package/dist/core/extensions/types.d.ts.map +1 -1
  89. package/dist/core/extensions/types.js.map +1 -1
  90. package/dist/core/extensions/virtual-modules.d.ts +3 -0
  91. package/dist/core/extensions/virtual-modules.d.ts.map +1 -0
  92. package/dist/core/extensions/virtual-modules.js +38 -0
  93. package/dist/core/extensions/virtual-modules.js.map +1 -0
  94. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  95. package/dist/core/extensions/wrapper.js +1 -20
  96. package/dist/core/extensions/wrapper.js.map +1 -1
  97. package/dist/core/index.d.ts +2 -1
  98. package/dist/core/index.d.ts.map +1 -1
  99. package/dist/core/index.js.map +1 -1
  100. package/dist/core/keybindings.d.ts +1 -1
  101. package/dist/core/keybindings.d.ts.map +1 -1
  102. package/dist/core/keybindings.js +1 -1
  103. package/dist/core/keybindings.js.map +1 -1
  104. package/dist/core/messages.d.ts.map +1 -1
  105. package/dist/core/messages.js +1 -0
  106. package/dist/core/messages.js.map +1 -1
  107. package/dist/core/model-config.d.ts +101 -20
  108. package/dist/core/model-config.d.ts.map +1 -1
  109. package/dist/core/model-config.js +25 -18
  110. package/dist/core/model-config.js.map +1 -1
  111. package/dist/core/model-registry.d.ts +5 -1
  112. package/dist/core/model-registry.d.ts.map +1 -1
  113. package/dist/core/model-registry.js +8 -0
  114. package/dist/core/model-registry.js.map +1 -1
  115. package/dist/core/model-resolver.d.ts.map +1 -1
  116. package/dist/core/model-resolver.js +1 -1
  117. package/dist/core/model-resolver.js.map +1 -1
  118. package/dist/core/model-runtime.d.ts.map +1 -1
  119. package/dist/core/model-runtime.js +5 -3
  120. package/dist/core/model-runtime.js.map +1 -1
  121. package/dist/core/provider-composer.d.ts +3 -2
  122. package/dist/core/provider-composer.d.ts.map +1 -1
  123. package/dist/core/provider-composer.js +2 -0
  124. package/dist/core/provider-composer.js.map +1 -1
  125. package/dist/core/radius.d.ts +3 -0
  126. package/dist/core/radius.d.ts.map +1 -1
  127. package/dist/core/radius.js +6 -0
  128. package/dist/core/radius.js.map +1 -1
  129. package/dist/core/sdk.d.ts.map +1 -1
  130. package/dist/core/sdk.js +60 -38
  131. package/dist/core/sdk.js.map +1 -1
  132. package/dist/core/session-export.d.ts +6 -2
  133. package/dist/core/session-export.d.ts.map +1 -1
  134. package/dist/core/session-export.js +14 -13
  135. package/dist/core/session-export.js.map +1 -1
  136. package/dist/core/session-manager.d.ts +29 -6
  137. package/dist/core/session-manager.d.ts.map +1 -1
  138. package/dist/core/session-manager.js +159 -96
  139. package/dist/core/session-manager.js.map +1 -1
  140. package/dist/core/settings-manager.d.ts +20 -4
  141. package/dist/core/settings-manager.d.ts.map +1 -1
  142. package/dist/core/settings-manager.js +43 -7
  143. package/dist/core/settings-manager.js.map +1 -1
  144. package/dist/core/slash-commands.d.ts.map +1 -1
  145. package/dist/core/slash-commands.js +1 -0
  146. package/dist/core/slash-commands.js.map +1 -1
  147. package/dist/core/system-prompt.d.ts +49 -6
  148. package/dist/core/system-prompt.d.ts.map +1 -1
  149. package/dist/core/system-prompt.js +121 -92
  150. package/dist/core/system-prompt.js.map +1 -1
  151. package/dist/core/tools/bash.d.ts +2 -1
  152. package/dist/core/tools/bash.d.ts.map +1 -1
  153. package/dist/core/tools/bash.js +10 -4
  154. package/dist/core/tools/bash.js.map +1 -1
  155. package/dist/core/tools/edit.d.ts.map +1 -1
  156. package/dist/core/tools/edit.js +1 -2
  157. package/dist/core/tools/edit.js.map +1 -1
  158. package/dist/core/tools/read.d.ts.map +1 -1
  159. package/dist/core/tools/read.js +1 -2
  160. package/dist/core/tools/read.js.map +1 -1
  161. package/dist/core/tools/renderers/bash.d.ts.map +1 -1
  162. package/dist/core/tools/renderers/bash.js +9 -1
  163. package/dist/core/tools/renderers/bash.js.map +1 -1
  164. package/dist/core/tools/write.d.ts.map +1 -1
  165. package/dist/core/tools/write.js +1 -2
  166. package/dist/core/tools/write.js.map +1 -1
  167. package/dist/core/usage-totals.d.ts +1 -1
  168. package/dist/core/usage-totals.d.ts.map +1 -1
  169. package/dist/core/usage-totals.js +5 -1
  170. package/dist/core/usage-totals.js.map +1 -1
  171. package/dist/extensions/llama/client.d.ts +2 -0
  172. package/dist/extensions/llama/client.d.ts.map +1 -1
  173. package/dist/extensions/llama/client.js +7 -3
  174. package/dist/extensions/llama/client.js.map +1 -1
  175. package/dist/extensions/llama/provider.d.ts.map +1 -1
  176. package/dist/extensions/llama/provider.js +20 -5
  177. package/dist/extensions/llama/provider.js.map +1 -1
  178. package/dist/index.d.ts +3 -2
  179. package/dist/index.d.ts.map +1 -1
  180. package/dist/index.js.map +1 -1
  181. package/dist/main.d.ts.map +1 -1
  182. package/dist/main.js +13 -9
  183. package/dist/main.js.map +1 -1
  184. package/dist/migrations.d.ts.map +1 -1
  185. package/dist/migrations.js +2 -2
  186. package/dist/migrations.js.map +1 -1
  187. package/dist/modes/interactive/bug-report.d.ts +14 -0
  188. package/dist/modes/interactive/bug-report.d.ts.map +1 -0
  189. package/dist/modes/interactive/bug-report.js +209 -0
  190. package/dist/modes/interactive/bug-report.js.map +1 -0
  191. package/dist/modes/interactive/chat-viewport.d.ts.map +1 -1
  192. package/dist/modes/interactive/chat-viewport.js +1 -1
  193. package/dist/modes/interactive/chat-viewport.js.map +1 -1
  194. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  195. package/dist/modes/interactive/components/branch-summary-message.js +12 -5
  196. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  197. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  198. package/dist/modes/interactive/components/compaction-summary-message.js +12 -5
  199. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  200. package/dist/modes/interactive/components/custom-editor.d.ts +3 -3
  201. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  202. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  203. package/dist/modes/interactive/components/extension-input.d.ts +2 -0
  204. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  205. package/dist/modes/interactive/components/extension-input.js +6 -0
  206. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  207. package/dist/modes/interactive/components/extension-selector.d.ts +1 -0
  208. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  209. package/dist/modes/interactive/components/extension-selector.js +4 -0
  210. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  211. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  212. package/dist/modes/interactive/components/footer.js +4 -1
  213. package/dist/modes/interactive/components/footer.js.map +1 -1
  214. package/dist/modes/interactive/components/session-selector.d.ts +5 -5
  215. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  216. package/dist/modes/interactive/components/session-selector.js +74 -48
  217. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  218. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  219. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  220. package/dist/modes/interactive/components/settings-selector.js +11 -0
  221. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  222. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  223. package/dist/modes/interactive/components/skill-invocation-message.js +11 -4
  224. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  225. package/dist/modes/interactive/components/status-indicator.d.ts +2 -2
  226. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
  227. package/dist/modes/interactive/components/status-indicator.js +7 -7
  228. package/dist/modes/interactive/components/status-indicator.js.map +1 -1
  229. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  230. package/dist/modes/interactive/components/tool-execution.js +18 -9
  231. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  232. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  233. package/dist/modes/interactive/components/tree-selector.js +2 -0
  234. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  235. package/dist/modes/interactive/interactive-mode.d.ts +13 -1
  236. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  237. package/dist/modes/interactive/interactive-mode.js +220 -84
  238. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  239. package/dist/modes/interactive/session-share.d.ts +2 -0
  240. package/dist/modes/interactive/session-share.d.ts.map +1 -1
  241. package/dist/modes/interactive/session-share.js +8 -4
  242. package/dist/modes/interactive/session-share.js.map +1 -1
  243. package/dist/modes/interactive/tui-renderer.d.ts.map +1 -1
  244. package/dist/modes/interactive/tui-renderer.js +2 -2
  245. package/dist/modes/interactive/tui-renderer.js.map +1 -1
  246. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  247. package/dist/modes/rpc/rpc-mode.js +2 -2
  248. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  249. package/dist/utils/clipboard-command.d.ts +7 -0
  250. package/dist/utils/clipboard-command.d.ts.map +1 -0
  251. package/dist/utils/clipboard-command.js +45 -0
  252. package/dist/utils/clipboard-command.js.map +1 -0
  253. package/dist/utils/clipboard-image.d.ts.map +1 -1
  254. package/dist/utils/clipboard-image.js +52 -69
  255. package/dist/utils/clipboard-image.js.map +1 -1
  256. package/dist/utils/clipboard.d.ts.map +1 -1
  257. package/dist/utils/clipboard.js +61 -125
  258. package/dist/utils/clipboard.js.map +1 -1
  259. package/dist/utils/version-check.d.ts.map +1 -1
  260. package/dist/utils/version-check.js +11 -4
  261. package/dist/utils/version-check.js.map +1 -1
  262. package/dist/utils/zip.d.ts +7 -0
  263. package/dist/utils/zip.d.ts.map +1 -0
  264. package/dist/utils/zip.js +60 -0
  265. package/dist/utils/zip.js.map +1 -0
  266. package/docs/compaction.md +39 -13
  267. package/docs/custom-provider.md +22 -13
  268. package/docs/development.md +4 -4
  269. package/docs/docs.json +4 -0
  270. package/docs/environment-variables.md +1 -0
  271. package/docs/extensions.md +57 -43
  272. package/docs/json.md +4 -4
  273. package/docs/models.md +33 -2
  274. package/docs/providers.md +2 -2
  275. package/docs/sdk.md +4 -2
  276. package/docs/security.md +1 -1
  277. package/docs/session-format.md +82 -40
  278. package/docs/sessions.md +27 -0
  279. package/docs/settings.md +60 -1
  280. package/docs/termux.md +0 -1
  281. package/docs/tui.md +2 -2
  282. package/docs/usage.md +1 -0
  283. package/examples/extensions/README.md +0 -1
  284. package/examples/extensions/custom-provider-anthropic/index.ts +18 -12
  285. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  286. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  287. package/examples/extensions/custom-provider-gitlab-duo/index.ts +2 -2
  288. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  289. package/examples/extensions/gondolin/package-lock.json +2 -2
  290. package/examples/extensions/gondolin/package.json +1 -1
  291. package/examples/extensions/prompt-customizer.ts +19 -67
  292. package/examples/extensions/sandbox/package-lock.json +2 -2
  293. package/examples/extensions/sandbox/package.json +1 -1
  294. package/examples/extensions/with-deps/package-lock.json +2 -2
  295. package/examples/extensions/with-deps/package.json +1 -1
  296. package/npm-shrinkwrap.json +435 -762
  297. package/package.json +17 -23
  298. package/dist/bundle/chunks/anthropic-messages-VWZZOSJQ.js +0 -6
  299. package/dist/bundle/chunks/azure-openai-responses-BJLAM6CD.js +0 -2
  300. package/dist/bundle/chunks/chunk-AXIIZGTV.js +0 -2
  301. package/dist/bundle/chunks/chunk-CLNPYIDP.js +0 -42
  302. package/dist/bundle/chunks/chunk-GMWCTUPB.js +0 -2
  303. package/dist/bundle/chunks/chunk-JJ2YFCJF.js +0 -1547
  304. package/dist/bundle/chunks/chunk-OUXLLA64.js +0 -11
  305. package/dist/bundle/chunks/chunk-U6ZMQKGD.js +0 -50
  306. package/dist/bundle/chunks/chunk-UAQELI3K.js +0 -2
  307. package/dist/bundle/chunks/google-generative-ai-Q2K7FBDI.js +0 -2
  308. package/dist/bundle/chunks/google-vertex-7UJBF4S7.js +0 -2
  309. package/dist/bundle/chunks/mistral-conversations-4M6BZBX6.js +0 -5
  310. package/dist/bundle/chunks/openai-codex-responses-R6VYZTVY.js +0 -10
  311. package/dist/bundle/chunks/openai-completions-EKZT2IH2.js +0 -7
  312. package/dist/bundle/chunks/openai-responses-TFDINO6W.js +0 -2
  313. package/dist/utils/clipboard-native.d.ts +0 -11
  314. package/dist/utils/clipboard-native.d.ts.map +0 -1
  315. package/dist/utils/clipboard-native.js +0 -20
  316. package/dist/utils/clipboard-native.js.map +0 -1
  317. package/examples/extensions/kimi-deferred-tools.ts +0 -61
@@ -5,10 +5,10 @@ Sessions are stored as JSONL (JSON Lines) files. Each line is a JSON object with
5
5
  ## File Location
6
6
 
7
7
  ```
8
- ~/.pi/agent/sessions/--<path>--/<timestamp>_<uuid>.jsonl
8
+ ~/.pi/agent/sessions/--<path>--/<timestamp>_<session-id>.jsonl
9
9
  ```
10
10
 
11
- Where `<path>` is the working directory with `/` replaced by `-`.
11
+ By default, `<session-id>` is a UUID. Callers can supply a custom ID through the SDK or `--session-id`. For `<path>`, Pi removes the leading path separator and replaces `/`, `\\`, and `:` with `-`.
12
12
 
13
13
  ## Deleting Sessions
14
14
 
@@ -28,11 +28,11 @@ Existing sessions are automatically migrated to the current version (v3) when lo
28
28
 
29
29
  ## Source Files
30
30
 
31
- Source on GitHub ([pi-mono](https://github.com/earendil-works/pi-mono)):
32
- - [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/session-manager.ts) - Session entry types and SessionManager
33
- - [`packages/coding-agent/src/core/messages.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/messages.ts) - Extended message types (BashExecutionMessage, CustomMessage, etc.)
34
- - [`packages/ai/src/types.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/ai/src/types.ts) - Base message types (UserMessage, AssistantMessage, ToolResultMessage)
35
- - [`packages/agent/src/types.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/agent/src/types.ts) - AgentMessage union type
31
+ Source on GitHub ([pi](https://github.com/earendil-works/pi)):
32
+ - [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/core/session-manager.ts) - Session entry types and SessionManager
33
+ - [`packages/coding-agent/src/core/messages.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/core/messages.ts) - Extended message types (BashExecutionMessage, CustomMessage, etc.)
34
+ - [`packages/ai/src/types.ts`](https://github.com/earendil-works/pi/blob/main/packages/ai/src/types.ts) - Base message types (UserMessage, AssistantMessage, ToolResultMessage)
35
+ - [`packages/agent/src/types.ts`](https://github.com/earendil-works/pi/blob/main/packages/agent/src/types.ts) - AgentMessage union type
36
36
 
37
37
  For TypeScript definitions in your project, inspect `node_modules/@earendil-works/pi-coding-agent/dist/` and `node_modules/@earendil-works/pi-ai/dist/`.
38
38
 
@@ -48,6 +48,7 @@ Messages contain arrays of typed content blocks:
48
48
  interface TextContent {
49
49
  type: "text";
50
50
  text: string;
51
+ textSignature?: string;
51
52
  }
52
53
 
53
54
  interface ImageContent {
@@ -59,6 +60,8 @@ interface ImageContent {
59
60
  interface ThinkingContent {
60
61
  type: "thinking";
61
62
  thinking: string;
63
+ thinkingSignature?: string;
64
+ redacted?: boolean;
62
65
  }
63
66
 
64
67
  interface ToolCall {
@@ -66,12 +69,22 @@ interface ToolCall {
66
69
  id: string;
67
70
  name: string;
68
71
  arguments: Record<string, any>;
72
+ thoughtSignature?: string;
73
+ namespace?: string;
69
74
  }
70
75
  ```
71
76
 
72
77
  ### Base Message Types (from pi-ai)
73
78
 
74
79
  ```typescript
80
+ interface SystemMessage {
81
+ role: "system";
82
+ content: string | TextContent[];
83
+ toolsAdded?: Tool[];
84
+ toolsRemoved?: Array<{ name: string }>;
85
+ timestamp: number; // Unix ms
86
+ }
87
+
75
88
  interface UserMessage {
76
89
  role: "user";
77
90
  content: string | (TextContent | ImageContent)[];
@@ -84,9 +97,16 @@ interface AssistantMessage {
84
97
  api: string;
85
98
  provider: string;
86
99
  model: string;
100
+ responseModel?: string;
101
+ responseId?: string;
102
+ providerThinkingLevel?: string;
103
+ diagnostics?: AssistantMessageDiagnostic[];
87
104
  usage: Usage;
88
- stopReason: "stop" | "length" | "toolUse" | "error" | "aborted";
105
+ stopReason: "pending" | "stop" | "length" | "toolUse" | "error" | "aborted" | "deferred";
106
+ deferred?: DeferredHandle;
89
107
  errorMessage?: string;
108
+ rawStopReason?: string;
109
+ endTurn?: boolean;
90
110
  timestamp: number;
91
111
  }
92
112
 
@@ -106,6 +126,8 @@ interface Usage {
106
126
  output: number;
107
127
  cacheRead: number;
108
128
  cacheWrite: number;
129
+ cacheWrite1h?: number;
130
+ reasoning?: number;
109
131
  totalTokens: number;
110
132
  cost: {
111
133
  input: number;
@@ -117,7 +139,7 @@ interface Usage {
117
139
  }
118
140
  ```
119
141
 
120
- The exported pi-ai `StopReason` type also includes `"pending"`, but that value is reserved for partial messages in streaming events. Terminal `done`/`error` messages replace it with a completion reason before pi persists the assistant message, so `"pending"` should never appear in session JSONL.
142
+ `"pending"` is reserved for partial messages in streaming events. Terminal events replace it with a completion reason before Pi persists the assistant message, so `"pending"` should never appear in session JSONL. `"deferred"` is a terminal reason for a provider response that will complete later; its `deferred` handle contains the provider data needed to retrieve that response.
121
143
 
122
144
  ### Extended Message Types (from pi-coding-agent)
123
145
 
@@ -146,7 +168,7 @@ interface CustomMessage {
146
168
  interface BranchSummaryMessage {
147
169
  role: "branchSummary";
148
170
  summary: string;
149
- fromId: string; // Entry we branched from
171
+ fromId: string | null; // Previous leaf whose abandoned path was summarized
150
172
  timestamp: number;
151
173
  }
152
174
 
@@ -162,6 +184,7 @@ interface CompactionSummaryMessage {
162
184
 
163
185
  ```typescript
164
186
  type AgentMessage =
187
+ | SystemMessage
165
188
  | UserMessage
166
189
  | AssistantMessage
167
190
  | ToolResultMessage
@@ -178,8 +201,8 @@ All entries (except `SessionHeader`) extend `SessionEntryBase`:
178
201
  ```typescript
179
202
  interface SessionEntryBase {
180
203
  type: string;
181
- id: string; // 8-char hex ID
182
- parentId: string | null; // Parent entry ID (null for first entry)
204
+ id: string; // Usually an 8-char hex ID; may fall back to a full UUID
205
+ parentId: string | null; // Parent entry ID (null for a root entry)
183
206
  timestamp: string; // ISO timestamp
184
207
  }
185
208
  ```
@@ -202,12 +225,19 @@ For sessions with a parent (created via `/fork`, `/clone`, or `newSession({ pare
202
225
 
203
226
  ### SessionMessageEntry
204
227
 
205
- A message in the conversation. The `message` field contains an `AgentMessage`.
228
+ A message in the conversation. The `message` field contains an `AgentMessage`. System messages carry the prompt and tool loadout: the first request of a session persists one with every prompt section and tool declaration, and later changes persist as system messages that patch `sections` by name (`null` removes one) and list `toolsAdded`/`toolsRemoved`. Replaying them in order yields the current prompt and tools; there is no separate prompt state entry.
229
+
230
+ ```json
231
+ {"type":"message","id":"a0b1c2d3","parentId":null,"timestamp":"2024-12-03T14:00:00.000Z","message":{"role":"system","content":"","sections":{"preamble":"You are an expert coding assistant...","tools":"<tools>\n- read: ...\n</tools>","cwd":"/project"},"toolsAdded":[{"name":"read","description":"...","parameters":{}}],"timestamp":1733234400000}}
232
+ {"type":"message","id":"d4e5f6g7","parentId":"c3d4e5f6","timestamp":"2024-12-03T14:04:00.000Z","message":{"role":"system","content":"","sections":{"skills":"<skills>...</skills>"},"toolsRemoved":[{"name":"write"}],"timestamp":1733234640000}}
233
+ ```
234
+
235
+ Sessions created before system messages existed have no leading system message; the first request declares the current prompt as a later system message, which replays the same way.
206
236
 
207
237
  ```json
208
- {"type":"message","id":"a1b2c3d4","parentId":"prev1234","timestamp":"2024-12-03T14:00:01.000Z","message":{"role":"user","content":"Hello"}}
209
- {"type":"message","id":"b2c3d4e5","parentId":"a1b2c3d4","timestamp":"2024-12-03T14:00:02.000Z","message":{"role":"assistant","content":[{"type":"text","text":"Hi!"}],"provider":"anthropic","model":"claude-sonnet-4-5","usage":{...},"stopReason":"stop"}}
210
- {"type":"message","id":"c3d4e5f6","parentId":"b2c3d4e5","timestamp":"2024-12-03T14:00:03.000Z","message":{"role":"toolResult","toolCallId":"call_123","toolName":"bash","content":[{"type":"text","text":"output"}],"isError":false}}
238
+ {"type":"message","id":"a1b2c3d4","parentId":"prev1234","timestamp":"2024-12-03T14:00:01.000Z","message":{"role":"user","content":"Hello","timestamp":1733234401000}}
239
+ {"type":"message","id":"b2c3d4e5","parentId":"a1b2c3d4","timestamp":"2024-12-03T14:00:02.000Z","message":{"role":"assistant","content":[{"type":"text","text":"Hi!"}],"api":"anthropic-messages","provider":"anthropic","model":"claude-sonnet-4-5","usage":{...},"stopReason":"stop","timestamp":1733234402000}}
240
+ {"type":"message","id":"c3d4e5f6","parentId":"b2c3d4e5","timestamp":"2024-12-03T14:00:03.000Z","message":{"role":"toolResult","toolCallId":"call_123","toolName":"bash","content":[{"type":"text","text":"output"}],"isError":false,"timestamp":1733234403000}}
211
241
  ```
212
242
 
213
243
  ### ModelChangeEntry
@@ -226,26 +256,31 @@ Emitted when the user changes the thinking/reasoning level.
226
256
  {"type":"thinking_level_change","id":"e5f6g7h8","parentId":"d4e5f6g7","timestamp":"2024-12-03T14:06:00.000Z","thinkingLevel":"high"}
227
257
  ```
228
258
 
229
- ### CompactionEntry
259
+ ### UsageEntry
230
260
 
231
- Created when context is compacted. Stores a summary of earlier messages.
261
+ Records model-attributed usage that is not an assistant message and does not participate in LLM context. `kind` is an arbitrary string identifying the operation; for example, cache warming uses `"cache_warm"`.
232
262
 
233
263
  ```json
234
- {"type":"compaction","id":"f6g7h8i9","parentId":"e5f6g7h8","timestamp":"2024-12-03T14:10:00.000Z","summary":"User discussed X, Y, Z...","firstKeptEntryId":"c3d4e5f6","tokensBefore":50000}
264
+ {"type":"usage","id":"f6g7h8i9","parentId":"e5f6g7h8","timestamp":"2024-12-03T14:08:00.000Z","kind":"cache_warm","provider":"anthropic","model":"claude-sonnet-4-5","usage":{"input":0,"output":0,"cacheRead":50000,"cacheWrite":0,"totalTokens":50000,"cost":{"input":0,"output":0,"cacheRead":0.015,"cacheWrite":0,"total":0.015}}}
235
265
  ```
236
266
 
237
- Newer harness-generated compactions embed the retained post-compaction context directly on the entry, instead of `firstKeptEntryId`:
267
+ Usage entries contribute to session token and cost totals. Pi hides them from the conversation tree. Consumers should treat unknown `kind` values as normal usage rather than rejecting them.
268
+
269
+ ### CompactionEntry
270
+
271
+ Created when context is compacted. Stores a summary of earlier messages and a complete system prompt/tool checkpoint.
238
272
 
239
273
  ```json
240
- {"type":"compaction","id":"f6g7h8i9","parentId":"e5f6g7h8","timestamp":"2024-12-03T14:10:00.000Z","summary":"User discussed X, Y, Z...","tokensBefore":50000,"retainedTail":[{"role":"user","content":"latest request"},{"role":"assistant","content":[{"type":"text","text":"latest reply"}],"provider":"anthropic","model":"claude-sonnet-4-5","usage":{...},"stopReason":"stop"}]}
274
+ {"type":"compaction","id":"f6g7h8i9","parentId":"e5f6g7h8","timestamp":"2024-12-03T14:10:00.000Z","summary":"User discussed X, Y, Z...","firstKeptEntryId":"c3d4e5f6","tokensBefore":50000,"systemMessage":{"role":"system","content":"You are a coding assistant.","toolsAdded":[],"timestamp":1733235000000}}
241
275
  ```
242
276
 
277
+ `firstKeptEntryId` is required. It identifies the first entry retained from before the compaction entry. When rebuilding context, Pi replaces older summarized entries with the compaction summary and keeps the range beginning at this entry.
278
+
243
279
  Optional fields:
280
+ - `systemMessage`: The replayed prompt sections and tool declarations at the compaction boundary; it becomes the leading system message of the compacted context, and system messages among the kept entries are dropped in its favor. It is absent on older session entries.
244
281
  - `usage`: LLM usage from generating the summary; included in session token and cost totals
245
- - `retainedTail`: Materialized `AgentMessage[]` kept after compaction. This is optional only for backward compatibility with older sessions. Newer harness-generated compactions include it so we can rebuild context from this checkpoint without walking older entries before the compaction entry.
246
282
  - `details`: Implementation-specific data (e.g., `{ readFiles: string[], modifiedFiles: string[] }` for default, or custom data for extensions)
247
283
  - `fromHook`: `true` if generated by an extension, `false`/`undefined` if pi-generated (legacy field name)
248
- - `firstKeptEntryId`: for compatibility with old entry format.
249
284
 
250
285
  ### BranchSummaryEntry
251
286
 
@@ -255,6 +290,8 @@ Created when switching branches via `/tree` with an LLM generated summary of the
255
290
  {"type":"branch_summary","id":"g7h8i9j0","parentId":"a1b2c3d4","timestamp":"2024-12-03T14:15:00.000Z","fromId":"f6g7h8i9","summary":"Branch explored approach A..."}
256
291
  ```
257
292
 
293
+ `parentId` is the entry from which the new branch continues. `fromId` is the previous leaf whose abandoned path was summarized.
294
+
258
295
  Optional fields:
259
296
  - `usage`: LLM usage from generating the summary; included in session token and cost totals
260
297
  - `details`: File tracking data (`{ readFiles: string[], modifiedFiles: string[] }`) for default, or custom data for extensions
@@ -305,11 +342,12 @@ The session name is displayed in the session selector (`/resume`) instead of the
305
342
 
306
343
  ## Tree Structure
307
344
 
308
- Entries form a tree:
309
- - First entry has `parentId: null`
310
- - Each subsequent entry points to its parent via `parentId`
345
+ Entries normally form one tree, but navigation APIs can create multiple roots:
346
+ - A root entry has `parentId: null`; the first entry is initially the root
347
+ - Each non-root entry points to its parent via `parentId`
311
348
  - Branching creates new children from an earlier entry
312
349
  - The "leaf" is the current position in the tree
350
+ - Calling `resetLeaf()` or `branchWithSummary(null, ...)` allows a later entry to become another root
313
351
 
314
352
  ```
315
353
  [user msg] ─── [assistant] ─── [user msg] ─── [assistant] ─┬─ [user msg] ← current leaf
@@ -322,11 +360,10 @@ Entries form a tree:
322
360
  `buildContextEntries()` walks from the current leaf to the root, producing the active entry list while honoring compaction:
323
361
 
324
362
  1. Collects all entries on the path
325
- 2. If a `CompactionEntry` is on the path:
363
+ 2. If one or more `CompactionEntry` values are on the path, uses the latest one:
326
364
  - Includes the compaction entry first
327
- - If `retainedTail` is present, it acts as a self-contained checkpoint and entries after the compaction are included
328
- - Otherwise entries from `firstKeptEntryId` to the compaction are included
329
- - Then entries after compaction are included
365
+ - Includes non-system entries from `firstKeptEntryId` up to, but not including, the compaction entry
366
+ - Includes entries after the compaction entry
330
367
  3. Preserves non-message entries in the selected range so interactive mode can render them
331
368
 
332
369
  `buildSessionContext()` builds on that entry list to produce the message list for the LLM:
@@ -334,12 +371,12 @@ Entries form a tree:
334
371
  1. Extracts current model and thinking level settings from the full path
335
372
  2. Converts selected entries to messages:
336
373
  - `message` -> stored `AgentMessage`
337
- - `compaction` -> `compactionSummary` plus `retainedTail` when present
374
+ - `compaction` -> complete system checkpoint followed by `compactionSummary`
338
375
  - `branch_summary` -> `branchSummary`
339
376
  - `custom_message` -> `CustomMessage`
340
- - `custom` -> no context message
377
+ - `usage` and `custom` -> no context message
341
378
 
342
- This makes newer compactions act like self-contained checkpoints. `retainedTail` is optional only so older sessions that only store `firstKeptEntryId` continue to load correctly.
379
+ The compaction summary replaces entries before `firstKeptEntryId`. Pre-compaction system messages are folded into the complete checkpoint rather than replayed from the retained range. Retained non-system entries and all entries after the compaction remain available to the LLM.
343
380
 
344
381
  ## Parsing Example
345
382
 
@@ -364,6 +401,9 @@ for (const line of lines) {
364
401
  case "branch_summary":
365
402
  console.log(`[${entry.id}] Branch from ${entry.fromId}`);
366
403
  break;
404
+ case "usage":
405
+ console.log(`[${entry.id}] Usage (${entry.kind}): ${entry.usage.totalTokens} tokens`);
406
+ break;
367
407
  case "custom":
368
408
  console.log(`[${entry.id}] Custom (${entry.customType}): ${JSON.stringify(entry.data)}`);
369
409
  break;
@@ -388,18 +428,19 @@ for (const line of lines) {
388
428
  Key methods for working with sessions programmatically.
389
429
 
390
430
  ### Static Creation Methods
391
- - `SessionManager.create(cwd, sessionDir?)` - New session
392
- - `SessionManager.open(path, sessionDir?)` - Open existing session file
431
+ - `SessionManager.create(cwd, sessionDir?, options?)` - New session; `options` can set `id` and `parentSession`
432
+ - `SessionManager.open(path, sessionDir?, cwdOverride?)` - Open existing session file
393
433
  - `SessionManager.continueRecent(cwd, sessionDir?)` - Continue most recent or create new
394
- - `SessionManager.inMemory(cwd?)` - No file persistence
395
- - `SessionManager.forkFrom(sourcePath, targetCwd, sessionDir?)` - Fork session from another project
434
+ - `SessionManager.inMemory(cwd?, options?, entries?)` - No file persistence, optionally initialized from entries
435
+ - `SessionManager.forkFrom(sourcePath, targetCwd, sessionDir?, options?)` - Fork session from another project
396
436
 
397
437
  ### Static Listing Methods
398
438
  - `SessionManager.list(cwd, sessionDir?, onProgress?)` - List sessions for a directory
399
439
  - `SessionManager.listAll(onProgress?)` - List all sessions across all projects
440
+ - `SessionManager.listAll(sessionDir?, onProgress?)` - List sessions from a custom session root
400
441
 
401
442
  ### Instance Methods - Session Management
402
- - `newSession(options?)` - Start a new session (options: `{ parentSession?: string }`)
443
+ - `newSession(options?)` - Start a new session (options: `{ id?: string, parentSession?: string }`)
403
444
  - `setSessionFile(path)` - Switch to a different session file
404
445
  - `createBranchedSession(leafId)` - Extract branch to new session file
405
446
 
@@ -407,7 +448,8 @@ Key methods for working with sessions programmatically.
407
448
  - `appendMessage(message)` - Add message
408
449
  - `appendThinkingLevelChange(level)` - Record thinking change
409
450
  - `appendModelChange(provider, modelId)` - Record model change
410
- - `appendCompaction(summary, firstKeptEntryId, tokensBefore, details?, fromHook?)` - Add compaction
451
+ - `appendUsage(kind, provider, model, usage)` - Record model-attributed usage outside the conversation
452
+ - `appendCompaction(summary, firstKeptEntryId, tokensBefore, details?, fromHook?, usage?)` - Add compaction
411
453
  - `appendCustomEntry(customType, data?)` - Extension state (not in context)
412
454
  - `appendSessionInfo(name)` - Set session display name
413
455
  - `appendCustomMessageEntry(customType, content, display, details?)` - Extension message (in context)
@@ -423,7 +465,7 @@ Key methods for working with sessions programmatically.
423
465
  - `getLabel(id)` - Get label for entry
424
466
  - `branch(entryId)` - Move leaf to earlier entry
425
467
  - `resetLeaf()` - Reset leaf to null (before any entries)
426
- - `branchWithSummary(entryId, summary, details?, fromHook?)` - Branch with context summary
468
+ - `branchWithSummary(entryId, summary, details?, fromHook?, usage?)` - Branch with context summary; `entryId` may be `null` to branch from the root
427
469
 
428
470
  ### Instance Methods - Context & Info
429
471
  - `buildContextEntries()` - Get active branch entries with compaction applied
package/docs/sessions.md CHANGED
@@ -33,6 +33,7 @@ For the JSONL file format and SessionManager API, see [Session Format](session-f
33
33
  | `/compact [prompt]` | Summarize older context; see [Compaction](compaction.md) |
34
34
  | `/export [file]` | Export session to HTML |
35
35
  | `/share` | Upload as private GitHub gist with shareable HTML link |
36
+ | `/bug [description]` | Report a bug to the Pi developers; see [Reporting Bugs](#reporting-bugs) |
36
37
 
37
38
  ## Resuming and Deleting Sessions
38
39
 
@@ -138,6 +139,32 @@ When prompted, choose one of:
138
139
 
139
140
  See [Compaction](compaction.md) for branch summarization internals and extension hooks.
140
141
 
142
+ ## Reporting Bugs
143
+
144
+ `/bug [description]` collects a bug report for the Pi developers. The report is not shared publicly. The dialog asks for an optional description and whether to include the session transcript. If you decline the transcript, pi offers to have the current model write a summary of what went wrong instead; the transcript is sent to your provider with your credentials, and only the summary is attached.
145
+
146
+ The last step chooses where the report goes:
147
+
148
+ - **Upload Report** sends it to the Pi developers through `radius.pi.dev`. No login is required; if you are logged into Radius, the report is attributed to your account so the developers can follow up. If the upload fails, pi offers to export the zip instead.
149
+ - **Export as Zip** writes a zip archive to the current directory. Attach it to an issue or send it to the developers yourself.
150
+
151
+ Both contain the same files:
152
+
153
+ | File | Content |
154
+ |------|---------|
155
+ | `report.json` | pi version, runtime, OS, terminal, current model and provider configuration, loaded extensions, and settings. API keys, header values, URL credentials, and the analytics tracking id are never included. |
156
+ | `diagnostics.json` | Provider and runtime error diagnostics attached to assistant messages across the whole session (failed or aborted turns, retries, error messages), plus any recorded crashes. Always included; message content is not. |
157
+ | `session.jsonl` | The current branch of the session, only when you chose to include it. It contains file contents and command output read during the session. |
158
+ | `summary.md` | The model-written summary, only when you chose to generate one. |
159
+
160
+ Each report has a UUID. pi shows it after upload or export and records it in the session as a `pi.bug-report` entry so you can refer to it later.
161
+
162
+ Set `PI_RADIUS_GATEWAY` to upload to a different Radius deployment.
163
+
164
+ ### Crashes
165
+
166
+ When pi exits because of an uncaught exception or a fatal runtime error, it stores the error message and stack trace in `~/.pi/agent/crashes.json` (the newest five). The next interactive start shows a warning once; running `/bug` attaches the stored crashes to `diagnostics.json` and removes the file after the report is uploaded or exported. Resume the crashed session with `pi -r` first if you want the transcript in the report.
167
+
141
168
  ## Session Format
142
169
 
143
170
  Session files are JSONL and contain message entries, model changes, thinking-level changes, labels, compactions, branch summaries, and extension entries.
package/docs/settings.md CHANGED
@@ -32,8 +32,31 @@ Use `/trust` in interactive mode to save a project trust decision for future ses
32
32
  | `defaultThinkingLevel` | string | - | Startup thinking level (saved with Ctrl+S in `/thinking`, or edited manually): `"off"`, `"minimal"`, `"low"`, `"medium"`, `"high"`, `"xhigh"`, `"max"` |
33
33
  | `modelThinkingLevels` | object | - | Per-model startup thinking levels keyed by `"provider/modelId"`; configure from `/settings` → Default thinking level per model or edit manually |
34
34
  | `hideThinkingBlock` | boolean | `false` | Hide thinking blocks in output |
35
- | `showCacheMissNotices` | boolean | `false` | Show transcript notices for significant prompt-cache misses, compaction or branch-summary usage, and provider recovery diagnostics such as dropped Anthropic thinking blocks |
35
+ | `showCacheMissNotices` | boolean | `false` | Show transcript notices for significant prompt-cache misses, successful cache-warming usage, compaction or branch-summary usage, and provider recovery diagnostics such as dropped Anthropic thinking blocks |
36
36
  | `thinkingBudgets` | object | - | Custom token budgets per thinking level. Anthropic, Google, and Bedrock use these natively. OpenAI-compatible models use them when `compat.thinkingTokenBudgetField` (or `supportsThinkingTokenBudget`) is set. |
37
+ | `cacheWarming` | string | `"streaming"` | Prompt cache-warming mode: `"off"`, `"streaming"`, or `"idle"`. Global setting only. |
38
+
39
+ #### Cache Warming
40
+
41
+ Providers drop a prompt cache entry after a period of inactivity, so the first request after a pause pays full input price again. Cache warming re-sends the last request with a one-token output budget shortly before expiry:
42
+
43
+ - `"off"` disables warming.
44
+ - `"streaming"` protects expensive prefixes during long tool executions and stops as soon as the agent settles.
45
+ - `"idle"` also considers refreshes while waiting for your next prompt, using a fixed 15% continuation probability measured from real usage.
46
+
47
+ ```json
48
+ {
49
+ "cacheWarming": "idle"
50
+ }
51
+ ```
52
+
53
+ A refresh is sent only when the expected avoided cache-miss cost, minus the cost of the refresh, leaves at least $0.05 of expected savings. Active agent runs use 100% continuation probability. `/session` shows the next decision, continuation probability, expected savings, threshold, and estimated costs. When cache miss notices are enabled, each successful refresh appears in the transcript with its cost; notices identify extension overrides.
54
+
55
+ Warming stops when the context changes (model switch, compaction, branch navigation). Idle warming stops no later than 30 minutes after the last real provider request; warming during an active agent run stops after 60 minutes. Extensions can override each decision through the [`cache_warming_decision`](extensions.md#cache_warming_decision) event.
56
+
57
+ Each refresh is billed as a cache read of the full context plus one output token. Usage and cost show up in session totals but never enter model context. Pi schedules candidates at 90% of the cache lifetime while leaving at least ten seconds before expiry.
58
+
59
+ Warming needs a known cache lifetime for the model and the retention tier the request used (`short`, or `long` with `PI_CACHE_RETENTION=long`). The built-in catalog carries lifetimes for direct Anthropic; custom models and other providers can declare theirs with `promptCache` in `models.json` (see [Prompt Cache Lifetimes](models.md#prompt-cache-lifetimes)). Claude models that use budget-based rather than adaptive thinking are skipped while thinking is on, because Anthropic derives the thinking budget from `max_tokens` and keys the message cache on it, so a one-token request cannot reproduce the entry.
37
60
 
38
61
  #### thinkingBudgets
39
62
 
@@ -118,6 +141,7 @@ Set `PI_SKIP_VERSION_CHECK=1` to disable the Pi version update check. Use `--off
118
141
  | `compaction.enabled` | boolean | `true` | Enable auto-compaction |
119
142
  | `compaction.reserveTokens` | number | `16384` | Tokens reserved for LLM response |
120
143
  | `compaction.keepRecentTokens` | number | `20000` | Recent tokens to keep (not summarized) |
144
+ | `compaction.modelOverrides` | object | - | Per-model `reserveTokens` and `keepRecentTokens` overrides keyed by exact `"provider/modelId"` |
121
145
 
122
146
  ```json
123
147
  {
@@ -129,6 +153,37 @@ Set `PI_SKIP_VERSION_CHECK=1` to disable the Pi version update check. Use `--off
129
153
  }
130
154
  ```
131
155
 
156
+ #### Per-model compaction overrides
157
+
158
+ ```json
159
+ {
160
+ "compaction": {
161
+ "enabled": true,
162
+ "reserveTokens": 16384,
163
+ "keepRecentTokens": 20000,
164
+ "modelOverrides": {
165
+ "some-provider/big-model": {
166
+ "reserveTokens": 400000
167
+ },
168
+ "local/small-model": {
169
+ "reserveTokens": 2048,
170
+ "keepRecentTokens": 4096
171
+ }
172
+ }
173
+ }
174
+ }
175
+ ```
176
+
177
+ Keys match exact, case-sensitive `provider/modelId` values, not names or glob patterns. Model IDs may contain slashes (for example, `openrouter/anthropic/claude-sonnet-4`).
178
+
179
+ Each token setting resolves independently: matching model override → ordinary `compaction` setting → built-in default. In the example, `some-provider/big-model` keeps the ordinary 20000 recent tokens. Token values must be non-negative safe integers. Invalid values in the matching model override produce an error when read; only omitted fields fall back to the ordinary setting. Model override entries must be objects. Invalid ordinary token settings produce an error when read, even if the active model has a valid override. Only omitted ordinary values use built-in defaults. Zero is accepted, but `reserveTokens: 0` leaves no response margin and also sets the summarization output budget to zero.
180
+
181
+ Global and project settings merge recursively **before** model lookup. A project can override one field for a model without replacing its other fields or other models. A global model-specific value takes precedence over a project-wide fallback; override the same model entry in the project to change it.
182
+
183
+ `enabled` is not model-specific. The active model's token settings apply to manual compaction, automatic threshold checks (including between assistant turns), and overflow recovery. Switching models takes effect on the next check or compaction. Configure overrides in JSON; `/settings` retains the ordinary auto-compaction toggle.
184
+
185
+ See [compaction.md](compaction.md) for trigger and summarization behavior.
186
+
132
187
  ### Branch Summary
133
188
 
134
189
  | Setting | Type | Default | Description |
@@ -143,10 +198,13 @@ Set `PI_SKIP_VERSION_CHECK=1` to disable the Pi version update check. Use `--off
143
198
  | `retry.enabled` | boolean | `true` | Enable automatic agent-level retry on transient errors |
144
199
  | `retry.maxRetries` | number | `3` | Maximum agent-level retry attempts |
145
200
  | `retry.baseDelayMs` | number | `2000` | Base delay for agent-level exponential backoff (2s, 4s, 8s) |
201
+ | `retry.maxAgentDelayMs` | number | `60000` | Max agent-level retry delay (60s) |
146
202
  | `retry.provider.timeoutMs` | number | SDK default | Provider/SDK request timeout in milliseconds |
147
203
  | `retry.provider.maxRetries` | number | `0` | Provider/SDK retry attempts |
148
204
  | `retry.provider.maxRetryDelayMs` | number | `60000` | Max server-requested delay before failing (60s) |
149
205
 
206
+ Agent-level retries use exponential backoff capped by `retry.maxAgentDelayMs`, so long retry runs stay responsive after prolonged outages.
207
+
150
208
  When a provider requests a retry delay longer than `retry.provider.maxRetryDelayMs`, the request fails immediately with an informative error instead of waiting silently. Set it to `0` to disable the limit.
151
209
 
152
210
  Keep `retry.provider.maxRetries` at `0` unless provider-level retries are explicitly needed. Setting it above `0` can make SDK/provider retries handle out-of-usage-limit errors before Pi sees them, which may block the agent until the provider quota resets in some circumstances.
@@ -157,6 +215,7 @@ Keep `retry.provider.maxRetries` at `0` unless provider-level retries are explic
157
215
  "enabled": true,
158
216
  "maxRetries": 3,
159
217
  "baseDelayMs": 2000,
218
+ "maxAgentDelayMs": 60000,
160
219
  "provider": {
161
220
  "timeoutMs": 3600000,
162
221
  "maxRetries": 0,
package/docs/termux.md CHANGED
@@ -96,7 +96,6 @@ termux-camera-photo out.jpg # Take photo
96
96
  ## Limitations
97
97
 
98
98
  - **No image clipboard**: Termux clipboard API only supports text
99
- - **No native binaries**: Some optional native dependencies (like the clipboard module) are unavailable on Android ARM64 and are skipped during installation
100
99
  - **Storage access**: To access files in `/storage/emulated/0` (Downloads, etc.), run `termux-setup-storage` once to grant permissions
101
100
 
102
101
  ## Troubleshooting
package/docs/tui.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  Extensions and custom tools can render custom TUI components for interactive user interfaces. This page covers the component system and available building blocks.
6
6
 
7
- **Source:** [`@earendil-works/pi-tui`](https://github.com/earendil-works/pi-mono/tree/main/packages/tui)
7
+ **Source:** [`@earendil-works/pi-tui`](https://github.com/earendil-works/pi/tree/main/packages/tui)
8
8
 
9
9
  ## Component Interface
10
10
 
@@ -930,7 +930,7 @@ export default function (pi: ExtensionAPI) {
930
930
 
931
931
  - **Extend `CustomEditor`** (not base `Editor`) to get app keybindings (escape to abort, ctrl+d to exit, model switching, etc.)
932
932
  - **Call `super.handleInput(data)`** for keys you don't handle
933
- - **Working status**: custom editors keep the standalone working row by default. Pass `{ embedWorkingStatus: true }` as the fourth `CustomEditor` constructor argument to use the built-in editor-border spinner instead.
933
+ - **Status spinners**: custom editors keep standalone status rows by default. Pass `{ embedWorkingStatus: true }` as the fourth `CustomEditor` constructor argument to embed working, compaction, branch summarization, and retry spinners in the editor border instead.
934
934
  - **Factory pattern**: `setEditorComponent` receives a factory function that gets `tui`, `theme`, and `keybindings`
935
935
  - **Pass `undefined`** to restore the default editor: `ctx.ui.setEditorComponent(undefined)`
936
936
 
package/docs/usage.md CHANGED
@@ -55,6 +55,7 @@ Type `/` in the editor to open command completion. Extensions can register custo
55
55
  | `/export [file]` | Export session to HTML or JSONL |
56
56
  | `/import <file>` | Import and resume a session from a JSONL file |
57
57
  | `/share` | Upload as private GitHub gist with shareable HTML link |
58
+ | `/bug [description]` | Report a bug to the Pi developers; see [Sessions](sessions.md#reporting-bugs) |
58
59
  | `/reload` | Reload keybindings, extensions, skills, prompts, themes, and context files |
59
60
  | `/hotkeys` | Show all keyboard shortcuts |
60
61
  | `/changelog` | Display version history |
@@ -36,7 +36,6 @@ cp permission-gate.ts ~/.pi/agent/extensions/
36
36
  | `questionnaire.ts` | Multi-question input with tab bar navigation between questions |
37
37
  | `tool-override.ts` | Override built-in tools (e.g., add logging/access control to `read`) |
38
38
  | `dynamic-tools.ts` | Register tools after startup (`session_start`) and at runtime via command, with prompt snippets and tool-specific prompt guidelines |
39
- | `kimi-deferred-tools.ts` | Search for and progressively activate tools for Kimi's deferred-tool loading protocol |
40
39
  | `structured-output.ts` | Final structured-output tool that returns `terminate: true` so the agent can end on the tool call |
41
40
  | `built-in-tool-renderer.ts` | Custom compact rendering for built-in tools (read, bash, edit, write) while keeping original behavior |
42
41
  | `minimal-mode.ts` | Override built-in tool rendering for minimal display (only tool calls, no output in collapsed mode) |
@@ -27,9 +27,11 @@ import {
27
27
  type Api,
28
28
  type AssistantMessage,
29
29
  type AssistantMessageEventStream,
30
- type Context,
31
30
  calculateCost,
31
+ collapseSystemMessages,
32
32
  createAssistantMessageEventStream,
33
+ getCurrentSystemPrompt,
34
+ getCurrentTools,
33
35
  type ImageContent,
34
36
  type Message,
35
37
  type Model,
@@ -42,6 +44,7 @@ import {
42
44
  type Tool,
43
45
  type ToolCall,
44
46
  type ToolResultMessage,
47
+ type TranscriptContext,
45
48
  } from "@earendil-works/pi-ai";
46
49
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
47
50
 
@@ -334,10 +337,15 @@ function mapStopReason(reason: string): StopReason {
334
337
 
335
338
  function streamCustomAnthropic(
336
339
  model: Model<Api>,
337
- context: Context,
340
+ context: TranscriptContext,
338
341
  options?: SimpleStreamOptions,
339
342
  ): AssistantMessageEventStream {
340
343
  const stream = createAssistantMessageEventStream();
344
+ // The transcript carries the prompt and tools in its system messages. This provider sends
345
+ // one top-level system prompt, so fold later system messages into the leading one first.
346
+ const transcript = collapseSystemMessages(context);
347
+ const systemPrompt = getCurrentSystemPrompt(transcript.messages);
348
+ const tools = getCurrentTools(transcript.messages);
341
349
 
342
350
  (async () => {
343
351
  const output: AssistantMessage = {
@@ -393,7 +401,7 @@ function streamCustomAnthropic(
393
401
  // Build request params
394
402
  const params: MessageCreateParamsStreaming = {
395
403
  model: model.id,
396
- messages: convertMessages(context.messages, isOAuth, context.tools),
404
+ messages: convertMessages(transcript.messages, isOAuth, tools),
397
405
  max_tokens: options?.maxTokens || Math.floor(model.maxTokens / 3),
398
406
  stream: true,
399
407
  };
@@ -407,25 +415,25 @@ function streamCustomAnthropic(
407
415
  cache_control: { type: "ephemeral" },
408
416
  },
409
417
  ];
410
- if (context.systemPrompt) {
418
+ if (systemPrompt) {
411
419
  params.system.push({
412
420
  type: "text",
413
- text: sanitizeSurrogates(context.systemPrompt),
421
+ text: sanitizeSurrogates(systemPrompt),
414
422
  cache_control: { type: "ephemeral" },
415
423
  });
416
424
  }
417
- } else if (context.systemPrompt) {
425
+ } else if (systemPrompt) {
418
426
  params.system = [
419
427
  {
420
428
  type: "text",
421
- text: sanitizeSurrogates(context.systemPrompt),
429
+ text: sanitizeSurrogates(systemPrompt),
422
430
  cache_control: { type: "ephemeral" },
423
431
  },
424
432
  ];
425
433
  }
426
434
 
427
- if (context.tools) {
428
- params.tools = convertTools(context.tools, isOAuth);
435
+ if (tools.length > 0) {
436
+ params.tools = convertTools(tools, isOAuth);
429
437
  }
430
438
 
431
439
  // Handle thinking/reasoning
@@ -474,9 +482,7 @@ function streamCustomAnthropic(
474
482
  output.content.push({
475
483
  type: "toolCall",
476
484
  id: event.content_block.id,
477
- name: isOAuth
478
- ? fromClaudeCodeName(event.content_block.name, context.tools)
479
- : event.content_block.name,
485
+ name: isOAuth ? fromClaudeCodeName(event.content_block.name, tools) : event.content_block.name,
480
486
  arguments: {},
481
487
  partialJson: "",
482
488
  index: event.index,
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider",
3
- "version": "0.85.1",
3
+ "version": "0.86.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-custom-provider",
9
- "version": "0.85.1",
9
+ "version": "0.86.0",
10
10
  "dependencies": {
11
11
  "@anthropic-ai/sdk": "^0.52.0"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider-anthropic",
3
3
  "private": true,
4
- "version": "0.85.1",
4
+ "version": "0.86.0",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -13,7 +13,6 @@ import {
13
13
  type Api,
14
14
  type AssistantMessageEventStream,
15
15
  anthropicMessagesApi,
16
- type Context,
17
16
  createAssistantMessageEventStream,
18
17
  type Model,
19
18
  type OAuthCredentials,
@@ -21,6 +20,7 @@ import {
21
20
  openAIResponsesApi,
22
21
  type SimpleStreamOptions,
23
22
  type ThinkingLevelMap,
23
+ type TranscriptContext,
24
24
  } from "@earendil-works/pi-ai/compat";
25
25
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
26
26
 
@@ -306,7 +306,7 @@ async function refreshGitLabToken(credentials: OAuthCredentials, signal: AbortSi
306
306
 
307
307
  export function streamGitLabDuo(
308
308
  model: Model<Api>,
309
- context: Context,
309
+ context: TranscriptContext,
310
310
  options?: SimpleStreamOptions,
311
311
  ): AssistantMessageEventStream {
312
312
  const stream = createAssistantMessageEventStream();