@astralyn/pi 0.82.6 → 0.83.0

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 (263) hide show
  1. package/CHANGELOG.md +61 -5099
  2. package/README.md +12 -111
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +9 -2
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/cli/credential-print.d.ts +23 -0
  7. package/dist/cli/credential-print.d.ts.map +1 -0
  8. package/dist/cli/credential-print.js +116 -0
  9. package/dist/cli/credential-print.js.map +1 -0
  10. package/dist/cli/session-picker.d.ts.map +1 -1
  11. package/dist/cli/session-picker.js +11 -13
  12. package/dist/cli/session-picker.js.map +1 -1
  13. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  14. package/dist/core/agent-session-runtime.js +3 -0
  15. package/dist/core/agent-session-runtime.js.map +1 -1
  16. package/dist/core/agent-session.d.ts +1 -1
  17. package/dist/core/agent-session.d.ts.map +1 -1
  18. package/dist/core/agent-session.js +13 -6
  19. package/dist/core/agent-session.js.map +1 -1
  20. package/dist/core/extensions/runner.d.ts +1 -0
  21. package/dist/core/extensions/runner.d.ts.map +1 -1
  22. package/dist/core/extensions/runner.js +7 -0
  23. package/dist/core/extensions/runner.js.map +1 -1
  24. package/dist/core/extensions/types.d.ts +11 -0
  25. package/dist/core/extensions/types.d.ts.map +1 -1
  26. package/dist/core/extensions/types.js.map +1 -1
  27. package/dist/core/footer-data-provider.d.ts +10 -0
  28. package/dist/core/footer-data-provider.d.ts.map +1 -1
  29. package/dist/core/footer-data-provider.js +1 -1
  30. package/dist/core/footer-data-provider.js.map +1 -1
  31. package/dist/core/model-runtime.d.ts +2 -0
  32. package/dist/core/model-runtime.d.ts.map +1 -1
  33. package/dist/core/model-runtime.js.map +1 -1
  34. package/dist/core/package-manager.d.ts.map +1 -1
  35. package/dist/core/package-manager.js +13 -6
  36. package/dist/core/package-manager.js.map +1 -1
  37. package/dist/core/resource-loader.d.ts +15 -0
  38. package/dist/core/resource-loader.d.ts.map +1 -1
  39. package/dist/core/resource-loader.js +70 -9
  40. package/dist/core/resource-loader.js.map +1 -1
  41. package/dist/core/session-manager.d.ts.map +1 -1
  42. package/dist/core/session-manager.js +2 -2
  43. package/dist/core/session-manager.js.map +1 -1
  44. package/dist/core/tools/bash.d.ts +1 -5
  45. package/dist/core/tools/bash.d.ts.map +1 -1
  46. package/dist/core/tools/bash.js +16 -41
  47. package/dist/core/tools/bash.js.map +1 -1
  48. package/dist/core/tools/edit.d.ts.map +1 -1
  49. package/dist/core/tools/edit.js +42 -11
  50. package/dist/core/tools/edit.js.map +1 -1
  51. package/dist/core/tools/find.d.ts.map +1 -1
  52. package/dist/core/tools/find.js +40 -11
  53. package/dist/core/tools/find.js.map +1 -1
  54. package/dist/core/tools/grep.d.ts.map +1 -1
  55. package/dist/core/tools/grep.js +17 -8
  56. package/dist/core/tools/grep.js.map +1 -1
  57. package/dist/core/tools/ls.d.ts.map +1 -1
  58. package/dist/core/tools/ls.js +3 -3
  59. package/dist/core/tools/ls.js.map +1 -1
  60. package/dist/core/tools/read.d.ts.map +1 -1
  61. package/dist/core/tools/read.js +4 -4
  62. package/dist/core/tools/read.js.map +1 -1
  63. package/dist/core/tools/render-utils.d.ts +7 -0
  64. package/dist/core/tools/render-utils.d.ts.map +1 -1
  65. package/dist/core/tools/render-utils.js +11 -0
  66. package/dist/core/tools/render-utils.js.map +1 -1
  67. package/dist/core/tools/write.d.ts.map +1 -1
  68. package/dist/core/tools/write.js +2 -3
  69. package/dist/core/tools/write.js.map +1 -1
  70. package/dist/core/trust-manager.d.ts.map +1 -1
  71. package/dist/core/trust-manager.js +48 -9
  72. package/dist/core/trust-manager.js.map +1 -1
  73. package/dist/extensions/deepwiki/render.d.ts.map +1 -1
  74. package/dist/extensions/deepwiki/render.js +34 -22
  75. package/dist/extensions/deepwiki/render.js.map +1 -1
  76. package/dist/extensions/index.d.ts.map +1 -1
  77. package/dist/extensions/index.js +0 -2
  78. package/dist/extensions/index.js.map +1 -1
  79. package/dist/extensions/llama/provider.d.ts.map +1 -1
  80. package/dist/extensions/llama/provider.js +1 -1
  81. package/dist/extensions/llama/provider.js.map +1 -1
  82. package/dist/extensions/question/dialog.d.ts.map +1 -1
  83. package/dist/extensions/question/dialog.js +29 -10
  84. package/dist/extensions/question/dialog.js.map +1 -1
  85. package/dist/extensions/question/index.d.ts.map +1 -1
  86. package/dist/extensions/question/index.js +7 -2
  87. package/dist/extensions/question/index.js.map +1 -1
  88. package/dist/extensions/question/render.d.ts +4 -8
  89. package/dist/extensions/question/render.d.ts.map +1 -1
  90. package/dist/extensions/question/render.js +202 -29
  91. package/dist/extensions/question/render.js.map +1 -1
  92. package/dist/extensions/question/results.d.ts.map +1 -1
  93. package/dist/extensions/question/results.js +1 -0
  94. package/dist/extensions/question/results.js.map +1 -1
  95. package/dist/extensions/question/schema.d.ts.map +1 -1
  96. package/dist/extensions/question/schema.js +2 -2
  97. package/dist/extensions/question/schema.js.map +1 -1
  98. package/dist/extensions/question/types.d.ts +1 -0
  99. package/dist/extensions/question/types.d.ts.map +1 -1
  100. package/dist/extensions/question/types.js +1 -1
  101. package/dist/extensions/question/types.js.map +1 -1
  102. package/dist/extensions/router/stream.d.ts +1 -0
  103. package/dist/extensions/router/stream.d.ts.map +1 -1
  104. package/dist/extensions/router/stream.js +44 -13
  105. package/dist/extensions/router/stream.js.map +1 -1
  106. package/dist/extensions/subagent/constants.d.ts +1 -0
  107. package/dist/extensions/subagent/constants.d.ts.map +1 -1
  108. package/dist/extensions/subagent/constants.js +1 -0
  109. package/dist/extensions/subagent/constants.js.map +1 -1
  110. package/dist/extensions/subagent/index.d.ts.map +1 -1
  111. package/dist/extensions/subagent/index.js +2 -0
  112. package/dist/extensions/subagent/index.js.map +1 -1
  113. package/dist/extensions/subagent/render.d.ts.map +1 -1
  114. package/dist/extensions/subagent/render.js +121 -48
  115. package/dist/extensions/subagent/render.js.map +1 -1
  116. package/dist/extensions/subagent/retry.d.ts +17 -0
  117. package/dist/extensions/subagent/retry.d.ts.map +1 -0
  118. package/dist/extensions/subagent/retry.js +41 -0
  119. package/dist/extensions/subagent/retry.js.map +1 -0
  120. package/dist/extensions/subagent/runner.d.ts.map +1 -1
  121. package/dist/extensions/subagent/runner.js +33 -5
  122. package/dist/extensions/subagent/runner.js.map +1 -1
  123. package/dist/extensions/subagent/sdk-runner.d.ts +6 -0
  124. package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
  125. package/dist/extensions/subagent/sdk-runner.js +46 -24
  126. package/dist/extensions/subagent/sdk-runner.js.map +1 -1
  127. package/dist/extensions/subagent/types.d.ts +7 -0
  128. package/dist/extensions/subagent/types.d.ts.map +1 -1
  129. package/dist/extensions/subagent/types.js.map +1 -1
  130. package/dist/extensions/todo/index.d.ts.map +1 -1
  131. package/dist/extensions/todo/index.js +1 -1
  132. package/dist/extensions/todo/index.js.map +1 -1
  133. package/dist/extensions/todo/state.d.ts.map +1 -1
  134. package/dist/extensions/todo/state.js +10 -2
  135. package/dist/extensions/todo/state.js.map +1 -1
  136. package/dist/extensions/todo/view.d.ts +1 -1
  137. package/dist/extensions/todo/view.d.ts.map +1 -1
  138. package/dist/extensions/todo/view.js +179 -34
  139. package/dist/extensions/todo/view.js.map +1 -1
  140. package/dist/main.d.ts.map +1 -1
  141. package/dist/main.js +43 -0
  142. package/dist/main.js.map +1 -1
  143. package/dist/migrations.d.ts.map +1 -1
  144. package/dist/migrations.js +2 -1
  145. package/dist/migrations.js.map +1 -1
  146. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  147. package/dist/modes/interactive/components/armin.js +5 -0
  148. package/dist/modes/interactive/components/armin.js.map +1 -1
  149. package/dist/modes/interactive/components/bash-execution.d.ts +1 -0
  150. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  151. package/dist/modes/interactive/components/bash-execution.js +4 -2
  152. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  153. package/dist/modes/interactive/components/countdown-timer.d.ts +13 -6
  154. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  155. package/dist/modes/interactive/components/countdown-timer.js +54 -17
  156. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  157. package/dist/modes/interactive/components/extension-selector.d.ts +1 -1
  158. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  159. package/dist/modes/interactive/components/extension-selector.js +10 -6
  160. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  161. package/dist/modes/interactive/components/keybinding-hints.d.ts +11 -1
  162. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  163. package/dist/modes/interactive/components/keybinding-hints.js +56 -0
  164. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  165. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  166. package/dist/modes/interactive/components/model-selector.js +4 -1
  167. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  168. package/dist/modes/interactive/components/session-selector.d.ts +3 -0
  169. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  170. package/dist/modes/interactive/components/session-selector.js +52 -2
  171. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  172. package/dist/modes/interactive/components/tool-execution.d.ts +10 -0
  173. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  174. package/dist/modes/interactive/components/tool-execution.js +133 -18
  175. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  176. package/dist/modes/interactive/components/tool-group.d.ts +1 -0
  177. package/dist/modes/interactive/components/tool-group.d.ts.map +1 -1
  178. package/dist/modes/interactive/components/tool-group.js +5 -0
  179. package/dist/modes/interactive/components/tool-group.js.map +1 -1
  180. package/dist/modes/interactive/components/tree-selector.d.ts +10 -1
  181. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  182. package/dist/modes/interactive/components/tree-selector.js +55 -2
  183. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  184. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  185. package/dist/modes/interactive/external-editor.js +40 -3
  186. package/dist/modes/interactive/external-editor.js.map +1 -1
  187. package/dist/modes/interactive/interactive-mode.d.ts +5 -0
  188. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  189. package/dist/modes/interactive/interactive-mode.js +92 -24
  190. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  191. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  192. package/dist/modes/interactive/theme/theme.js +3 -2
  193. package/dist/modes/interactive/theme/theme.js.map +1 -1
  194. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  195. package/dist/modes/rpc/rpc-mode.js +13 -0
  196. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  197. package/dist/utils/paths.d.ts +5 -0
  198. package/dist/utils/paths.d.ts.map +1 -1
  199. package/dist/utils/paths.js +7 -0
  200. package/dist/utils/paths.js.map +1 -1
  201. package/docs/bundled/README.md +13 -15
  202. package/docs/bundled/extensions/deepwiki.md +1 -1
  203. package/docs/bundled/extensions/question.md +7 -5
  204. package/docs/bundled/extensions/router.md +3 -4
  205. package/docs/bundled/extensions/statusline.md +0 -1
  206. package/docs/bundled/extensions/subagent.md +4 -3
  207. package/docs/bundled/extensions/todo.md +1 -1
  208. package/docs/bundled/themes.md +1 -1
  209. package/docs/bundled/tool-presentation.md +17 -16
  210. package/docs/compaction.md +25 -30
  211. package/docs/custom-provider.md +298 -583
  212. package/docs/docs.json +0 -8
  213. package/docs/extensions.md +132 -121
  214. package/docs/index.md +18 -74
  215. package/docs/json.md +20 -14
  216. package/docs/models.md +193 -151
  217. package/docs/providers.md +2 -1
  218. package/docs/quickstart.md +3 -3
  219. package/docs/rpc.md +166 -124
  220. package/docs/sdk.md +119 -178
  221. package/docs/security.md +1 -1
  222. package/docs/session-format.md +139 -119
  223. package/docs/skills.md +0 -1
  224. package/docs/themes.md +2 -2
  225. package/docs/tui.md +411 -549
  226. package/docs/usage.md +3 -11
  227. package/examples/README.md +6 -1
  228. package/examples/extensions/README.md +13 -33
  229. package/examples/extensions/custom-provider-anthropic/index.ts +9 -3
  230. package/examples/extensions/dynamic-resources/dynamic.json +1 -1
  231. package/examples/extensions/truncated-tool.ts +2 -2
  232. package/examples/sdk/12-full-control.ts +2 -0
  233. package/npm-shrinkwrap.json +25 -25
  234. package/package.json +5 -5
  235. package/dist/extensions/plan/constants.d.ts +0 -40
  236. package/dist/extensions/plan/constants.d.ts.map +0 -1
  237. package/dist/extensions/plan/constants.js +0 -69
  238. package/dist/extensions/plan/constants.js.map +0 -1
  239. package/dist/extensions/plan/index.d.ts +0 -3
  240. package/dist/extensions/plan/index.d.ts.map +0 -1
  241. package/dist/extensions/plan/index.js +0 -323
  242. package/dist/extensions/plan/index.js.map +0 -1
  243. package/dist/extensions/plan/schema.d.ts +0 -15
  244. package/dist/extensions/plan/schema.d.ts.map +0 -1
  245. package/dist/extensions/plan/schema.js +0 -13
  246. package/dist/extensions/plan/schema.js.map +0 -1
  247. package/dist/extensions/plan/state.d.ts +0 -29
  248. package/dist/extensions/plan/state.d.ts.map +0 -1
  249. package/dist/extensions/plan/state.js +0 -74
  250. package/dist/extensions/plan/state.js.map +0 -1
  251. package/dist/extensions/plan/storage.d.ts +0 -18
  252. package/dist/extensions/plan/storage.d.ts.map +0 -1
  253. package/dist/extensions/plan/storage.js +0 -58
  254. package/dist/extensions/plan/storage.js.map +0 -1
  255. package/dist/extensions/plan/view.d.ts +0 -36
  256. package/dist/extensions/plan/view.d.ts.map +0 -1
  257. package/dist/extensions/plan/view.js +0 -74
  258. package/dist/extensions/plan/view.js.map +0 -1
  259. package/docs/bundled/extensions/README.md +0 -19
  260. package/docs/bundled/extensions/plan.md +0 -33
  261. package/examples/extensions/plan-mode/README.md +0 -66
  262. package/examples/extensions/plan-mode/index.ts +0 -390
  263. package/examples/extensions/plan-mode/utils.ts +0 -168
package/docs/rpc.md CHANGED
@@ -59,7 +59,7 @@ With images:
59
59
  {"type": "prompt", "message": "New instruction", "streamingBehavior": "steer"}
60
60
  ```
61
61
 
62
- - `"steer"`: Queue the message while the agent is running. It is delivered after the current assistant turn finishes executing its tool calls, before the next LLM call.
62
+ - `"steer"`: Queue the message during execution; see the [steer command](#steer).
63
63
  - `"followUp"`: Wait until the agent finishes. Message is delivered only when agent stops.
64
64
 
65
65
  If the agent is streaming and no `streamingBehavior` is specified, the command returns an error.
@@ -190,7 +190,7 @@ Response:
190
190
  }
191
191
  ```
192
192
 
193
- The `model` field is a full [Model](#model) object or `null`. The `sessionName` field is the display name set via `set_session_name`, or omitted if not set.
193
+ The `model` field is a full [Model](#model) object when one is selected, otherwise it is omitted. The `sessionFile` and `sessionName` fields are also omitted when unavailable; `sessionName` is the display name set via `set_session_name`.
194
194
 
195
195
  #### get_messages
196
196
 
@@ -210,7 +210,7 @@ Response:
210
210
  }
211
211
  ```
212
212
 
213
- Messages are `AgentMessage` objects (see [Message Types](#message-types)).
213
+ Messages are `AgentMessage` objects (see [Types](#types)).
214
214
 
215
215
  ### Model
216
216
 
@@ -288,6 +288,8 @@ Set the reasoning/thinking level for models that support it.
288
288
 
289
289
  Levels: `"off"`, `"minimal"`, `"low"`, `"medium"`, `"high"`, `"xhigh"`, `"max"`
290
290
 
291
+ The requested level is clamped to one supported by the selected model. Use `get_available_thinking_levels`, `get_state`, or the `thinking_level_changed` event to observe the effective level.
292
+
291
293
  `"xhigh"` and `"max"` are exposed only when supported by the selected model. Some models, including GPT-5.6, expose both.
292
294
 
293
295
  Response:
@@ -408,7 +410,7 @@ Response:
408
410
  }
409
411
  ```
410
412
 
411
- `estimatedTokensAfter` is a heuristic estimate over the rebuilt message context immediately after compaction, not a provider-exact token count. `usage` reports the LLM call or calls that generated the summary and may be omitted by custom compaction handlers.
413
+ `estimatedTokensAfter`, `usage`, and `details` are optional. When present, `estimatedTokensAfter` is a heuristic estimate over the rebuilt message context immediately after compaction, not a provider-exact token count. `usage` reports the LLM call or calls that generated the summary.
412
414
 
413
415
  #### set_auto_compaction
414
416
 
@@ -455,13 +457,17 @@ Response:
455
457
 
456
458
  #### bash
457
459
 
458
- Execute a shell command and add output to conversation context. Output streams as `bash_execution_update` events while the command runs; the response contains the final result.
460
+ Execute a shell command and record its output in the session. By default the output is added to LLM context on the next prompt; `excludeFromContext` opts out. Output streams as `bash_execution_update` events while the command runs; the response contains the final result.
459
461
 
460
462
  ```json
461
463
  {"id": "req-1", "type": "bash", "command": "ls -la"}
462
464
  ```
463
465
 
464
- Include an `id` to associate streamed `bash_execution_update` events with this command.
466
+ Include an `id` to associate streamed `bash_execution_update` events with this command. Set `excludeFromContext: true` to record and return the result without including it in the LLM context:
467
+
468
+ ```json
469
+ {"type": "bash", "command": "git status --short", "excludeFromContext": true}
470
+ ```
465
471
 
466
472
  Response:
467
473
  ```json
@@ -479,7 +485,7 @@ Response:
479
485
  }
480
486
  ```
481
487
 
482
- If output was truncated, includes `fullOutputPath`:
488
+ If output was truncated, `fullOutputPath` is present with the temporary file path. `exitCode` is omitted when the command was cancelled:
483
489
  ```json
484
490
  {
485
491
  "type": "response",
@@ -497,9 +503,9 @@ If output was truncated, includes `fullOutputPath`:
497
503
 
498
504
  **How bash results reach the LLM:**
499
505
 
500
- The `bash` command executes immediately and returns a `BashResult`. Internally, a `BashExecutionMessage` is created and stored in the agent's message state.
506
+ The `bash` command executes immediately and returns a `BashResult`. Internally, Pi creates and stores a `BashExecutionMessage`.
501
507
 
502
- When the next `prompt` command is sent, all messages (including `BashExecutionMessage`) are transformed before being sent to the LLM. The `BashExecutionMessage` is converted to a `UserMessage` with this format:
508
+ Unless `excludeFromContext` is `true`, the next `prompt` converts that message to a `UserMessage` for the LLM in this format:
503
509
 
504
510
  ````
505
511
  Ran `ls -la`
@@ -510,8 +516,9 @@ drwxr-xr-x ...
510
516
  ````
511
517
 
512
518
  This means:
513
- 1. Bash output is included in the LLM context on the **next prompt**, not immediately
514
- 2. Multiple bash commands can be executed before a prompt; all outputs will be included
519
+ 1. Unless `excludeFromContext` is `true`, bash output is included in the LLM context on the **next prompt**, not immediately.
520
+ 2. Multiple bash commands can be executed before a prompt; all non-excluded outputs are included.
521
+ 3. `excludeFromContext` affects only LLM context. The command still returns its result, streams `bash_execution_update`, and is visible through `get_messages`.
515
522
 
516
523
  #### abort_bash
517
524
 
@@ -567,7 +574,7 @@ Response:
567
574
  }
568
575
  ```
569
576
 
570
- `tokens` and `cost` include assistant messages, usage reported by tools, and compaction/branch-summary generation across the full session. `contextUsage` contains the actual current context-window estimate used for compaction and footer display.
577
+ `tokens` and `cost` include assistant messages, usage reported by tools, and compaction/branch-summary generation across the full session. `sessionFile` is omitted when session persistence is disabled. `contextUsage` contains the actual current context-window estimate used for compaction and footer display.
571
578
 
572
579
  `contextUsage` is omitted when no model or context window is available. `contextUsage.tokens` and `contextUsage.percent` are `null` immediately after compaction until a fresh post-compaction assistant response provides valid usage data.
573
580
 
@@ -806,9 +813,39 @@ Response:
806
813
  "success": true,
807
814
  "data": {
808
815
  "commands": [
809
- {"name": "session-name", "description": "Set or clear session name", "source": "extension", "path": "/home/user/.pi/agent/extensions/session.ts"},
810
- {"name": "fix-tests", "description": "Fix failing tests", "source": "prompt", "location": "project", "path": "/home/user/myproject/.pi/agent/prompts/fix-tests.md"},
811
- {"name": "skill:brave-search", "description": "Web search via Brave API", "source": "skill", "location": "user", "path": "/home/user/.pi/agent/skills/brave-search/SKILL.md"}
816
+ {
817
+ "name": "session-name",
818
+ "description": "Set session name",
819
+ "source": "extension",
820
+ "sourceInfo": {
821
+ "path": "/home/user/.pi/agent/extensions/session.ts",
822
+ "source": "auto",
823
+ "scope": "user",
824
+ "origin": "top-level"
825
+ }
826
+ },
827
+ {
828
+ "name": "fix-tests",
829
+ "description": "Fix failing tests",
830
+ "source": "prompt",
831
+ "sourceInfo": {
832
+ "path": "/home/user/myproject/.pi/prompts/fix-tests.md",
833
+ "source": "auto",
834
+ "scope": "project",
835
+ "origin": "top-level"
836
+ }
837
+ },
838
+ {
839
+ "name": "skill:brave-search",
840
+ "description": "Web search via Brave API",
841
+ "source": "skill",
842
+ "sourceInfo": {
843
+ "path": "/home/user/.pi/agent/skills/brave-search/SKILL.md",
844
+ "source": "auto",
845
+ "scope": "user",
846
+ "origin": "top-level"
847
+ }
848
+ }
812
849
  ]
813
850
  }
814
851
  }
@@ -817,15 +854,10 @@ Response:
817
854
  Each command has:
818
855
  - `name`: Command name (invoke with `/name`)
819
856
  - `description`: Human-readable description (optional for extension commands)
820
- - `source`: What kind of command:
821
- - `"extension"`: Registered via `pi.registerCommand()` in an extension
822
- - `"prompt"`: Loaded from a prompt template `.md` file
823
- - `"skill"`: Loaded from a skill directory (name is prefixed with `skill:`)
824
- - `location`: Where it was loaded from (optional, not present for extensions):
825
- - `"user"`: User-level (`~/.pi/agent/`)
826
- - `"project"`: Project-level (`./.pi/agent/`)
827
- - `"path"`: Explicit path via CLI or settings
828
- - `path`: Absolute file path to the command source (optional)
857
+ - `source`: What kind of command: `"extension"`, `"prompt"`, or `"skill"`
858
+ - `sourceInfo`: Required [SourceInfo](#sourceinfo) provenance metadata for the resource; it replaces the former flat `location` and `path` fields.
859
+
860
+ Project-local resources use `.pi/extensions/`, `.pi/prompts/`, and `.pi/skills/`; they do not live under `.pi/agent/`.
829
861
 
830
862
  **Note**: Built-in TUI commands (`/settings`, `/hotkeys`, etc.) are not included. They are handled only in interactive mode and would not execute if sent via `prompt`.
831
863
 
@@ -850,6 +882,9 @@ Events are streamed to stdout as JSON lines during agent operation. Events do no
850
882
  | `tool_execution_update` | Tool execution progress (streaming output) |
851
883
  | `tool_execution_end` | Tool completes |
852
884
  | `queue_update` | Pending steering/follow-up queue changed |
885
+ | `entry_appended` | An extension appended a custom session entry |
886
+ | `session_info_changed` | Session display name changed |
887
+ | `thinking_level_changed` | Effective thinking level changed |
853
888
  | `compaction_start` | Compaction begins |
854
889
  | `compaction_end` | Compaction completes |
855
890
  | `auto_retry_start` | Auto-retry begins (after transient error) |
@@ -981,7 +1016,7 @@ Emitted when a tool begins, streams progress, and completes execution.
981
1016
  }
982
1017
  ```
983
1018
 
984
- During execution, `tool_execution_update` events stream partial results (e.g., bash output as it arrives):
1019
+ During execution, `tool_execution_update` events carry a tool-defined partial result. For the built-in `bash` tool, each nonempty update is an accumulated output snapshot rather than only the newest delta:
985
1020
 
986
1021
  ```json
987
1022
  {
@@ -991,7 +1026,7 @@ During execution, `tool_execution_update` events stream partial results (e.g., b
991
1026
  "args": {"command": "ls -la"},
992
1027
  "partialResult": {
993
1028
  "content": [{"type": "text", "text": "partial output so far..."}],
994
- "details": {"truncation": null, "fullOutputPath": null}
1029
+ "details": {}
995
1030
  }
996
1031
  }
997
1032
  ```
@@ -1011,7 +1046,7 @@ When complete:
1011
1046
  }
1012
1047
  ```
1013
1048
 
1014
- Use `toolCallId` to correlate events. The `partialResult` in `tool_execution_update` contains the accumulated output so far (not just the delta), allowing clients to simply replace their display on each update.
1049
+ Use `toolCallId` to correlate events. The `partialResult` shape is tool-defined; built-in bash snapshots can be rendered by replacement, while other tools may use a different shape.
1015
1050
 
1016
1051
  ### queue_update
1017
1052
 
@@ -1025,6 +1060,28 @@ Emitted whenever the pending steering or follow-up queue changes.
1025
1060
  }
1026
1061
  ```
1027
1062
 
1063
+ ### entry_appended / session_info_changed / thinking_level_changed
1064
+
1065
+ These session-state events are also part of `AgentSessionEvent` (see [JSON mode](json.md#event-types)).
1066
+
1067
+ `entry_appended` is emitted when an extension appends a custom session entry:
1068
+
1069
+ ```json
1070
+ {"type": "entry_appended", "entry": {"type": "custom", "id": "abc123", "parentId": "def456", "timestamp": "...", "customType": "my-extension", "data": {}}}
1071
+ ```
1072
+
1073
+ `session_info_changed` carries the current display name; `name` is omitted when it is undefined:
1074
+
1075
+ ```json
1076
+ {"type": "session_info_changed", "name": "my-feature-work"}
1077
+ ```
1078
+
1079
+ `thinking_level_changed` carries the effective level after a change or model switch:
1080
+
1081
+ ```json
1082
+ {"type": "thinking_level_changed", "level": "high"}
1083
+ ```
1084
+
1028
1085
  ### compaction_start / compaction_end
1029
1086
 
1030
1087
  Emitted when compaction runs, whether manual or automatic.
@@ -1061,9 +1118,9 @@ The `reason` field is `"manual"`, `"threshold"`, or `"overflow"`.
1061
1118
 
1062
1119
  If `reason` was `"overflow"` and compaction succeeds, `willRetry` is `true` and the agent will automatically retry the prompt.
1063
1120
 
1064
- If compaction was aborted, `result` is `null` and `aborted` is `true`.
1121
+ If compaction was aborted, `result` is omitted and `aborted` is `true`.
1065
1122
 
1066
- If compaction failed (e.g., API quota exceeded), `result` is `null`, `aborted` is `false`, and `errorMessage` contains the error description.
1123
+ If compaction failed (e.g., API quota exceeded), `result` is omitted, `aborted` is `false`, and `errorMessage` contains the error description. `errorMessage` can also accompany a successful result when the retained context remains above the compaction threshold.
1067
1124
 
1068
1125
  ### auto_retry_start / auto_retry_end
1069
1126
 
@@ -1152,15 +1209,17 @@ There are two categories of extension UI methods:
1152
1209
  If a dialog method includes a `timeout` field, the agent-side will auto-resolve with a default value when the timeout expires. The client does not need to track timeouts.
1153
1210
 
1154
1211
  Some `ExtensionUIContext` methods are not supported or degraded in RPC mode because they require direct TUI access:
1155
- - `custom()` returns `undefined`
1156
- - `setWorkingMessage()`, `setWorkingIndicator()`, `setFooter()`, `setHeader()`, `setEditorComponent()`, `setToolsExpanded()` are no-ops
1212
+ - `custom()` and `getEditorComponent()` return `undefined`
1213
+ - `onTerminalInput()` returns a no-op unsubscribe function
1214
+ - `addAutocompleteProvider()`, `setWorkingMessage()`, `setWorkingVisible()`, `setWorkingIndicator()`, `setHiddenThinkingLabel()`, `setFooter()`, `setHeader()`, `setEditorComponent()`, and `setToolsExpanded()` are no-ops
1157
1215
  - `getEditorText()` returns `""`
1158
1216
  - `getToolsExpanded()` returns `false`
1159
1217
  - `pasteToEditor()` delegates to `setEditorText()` (no paste/collapse handling)
1160
- - `getAllThemes()` returns `[]`
1161
- - `getTheme()` returns `undefined`
1218
+ - `getAllThemes()` returns `[]`; `getTheme()` returns `undefined`
1162
1219
  - `setTheme()` returns `{ success: false, error: "..." }`
1163
1220
 
1221
+ `select()` sends only string labels on the wire. Descriptions supplied through the richer Extension API option objects are not included.
1222
+
1164
1223
  Note: `ctx.mode` is `"rpc"` and `ctx.hasUI` is `true` in RPC mode because the dialog and fire-and-forget methods are functional via the extension UI sub-protocol. Use `ctx.mode === "tui"` to guard TUI-specific features like `custom()` that require a real terminal.
1165
1224
 
1166
1225
  ### Extension UI Requests (stdout)
@@ -1182,7 +1241,7 @@ Prompt the user to choose from a list. Dialog methods with a `timeout` field inc
1182
1241
  }
1183
1242
  ```
1184
1243
 
1185
- Expected response: `extension_ui_response` with `value` (the selected option string) or `cancelled: true`.
1244
+ The `options` array contains string labels. If an extension registered richer select options, their descriptions are not sent over RPC. Expected response: `extension_ui_response` with `value` (the selected option string) or `cancelled: true`.
1186
1245
 
1187
1246
  #### confirm
1188
1247
 
@@ -1263,7 +1322,7 @@ Set or clear a status entry in the footer/status bar. Fire-and-forget.
1263
1322
  }
1264
1323
  ```
1265
1324
 
1266
- Send `statusText: undefined` (or omit it) to clear the status entry for that key.
1325
+ Omit `statusText` to clear the status entry for that key. JSON has no `undefined` value.
1267
1326
 
1268
1327
  #### setWidget
1269
1328
 
@@ -1280,7 +1339,7 @@ Set or clear a widget (block of text lines) displayed above or below the editor.
1280
1339
  }
1281
1340
  ```
1282
1341
 
1283
- Send `widgetLines: undefined` (or omit it) to clear the widget. The `widgetPlacement` field is `"aboveEditor"` (default) or `"belowEditor"`. Only string arrays are supported in RPC mode; component factories are ignored.
1342
+ Omit `widgetLines` to clear the widget. The `widgetPlacement` field is `"aboveEditor"` (default) or `"belowEditor"`. Only string arrays are supported in RPC mode; component factories are ignored.
1284
1343
 
1285
1344
  #### setTitle
1286
1345
 
@@ -1358,9 +1417,48 @@ Parse errors:
1358
1417
 
1359
1418
  ## Types
1360
1419
 
1361
- RPC messages use the public SDK and protocol types documented by this package. The model and agent message shapes are summarized below; applications embedding Pi should import the public API from `@astralyn/pi` rather than relying on package source files.
1420
+ For Node.js and TypeScript clients, the public type exports are the authority rather than copied protocol declarations:
1362
1421
 
1363
- ### Model
1422
+ ```typescript
1423
+ import type {
1424
+ AgentSessionEvent,
1425
+ CompactionResult,
1426
+ RpcCommand,
1427
+ RpcExtensionUIRequest,
1428
+ RpcExtensionUIResponse,
1429
+ RpcResponse,
1430
+ RpcSessionState,
1431
+ SessionEntry,
1432
+ SessionTreeNode,
1433
+ SourceInfo,
1434
+ } from "@astralyn/pi";
1435
+ import type { AgentMessage, ThinkingLevel } from "@earendil-works/pi-agent-core";
1436
+ import type { AssistantMessageEvent, ImageContent, Model } from "@earendil-works/pi-ai";
1437
+ ```
1438
+
1439
+ `RpcCommand` and `RpcResponse` are discriminated unions for the commands and responses above. `AgentSessionEvent` is the event union also documented in [JSON mode](json.md#event-types). Raw RPC stdout additionally carries `extension_ui_request` and `extension_error` objects; extension UI requests use `RpcExtensionUIRequest`.
1440
+
1441
+ Optional TypeScript properties are omitted in JSON; JSON never represents an omitted property as `undefined`.
1442
+
1443
+ ### SourceInfo
1444
+
1445
+ `get_commands` returns `sourceInfo` with this shape:
1446
+
1447
+ ```json
1448
+ {
1449
+ "path": "/home/user/myproject/.pi/prompts/fix-tests.md",
1450
+ "source": "auto",
1451
+ "scope": "project",
1452
+ "origin": "top-level",
1453
+ "baseDir": "/home/user/myproject/.pi"
1454
+ }
1455
+ ```
1456
+
1457
+ `path`, `source`, `scope`, and `origin` are required. `scope` is `"user"`, `"project"`, or `"temporary"`; `origin` is `"top-level"` or `"package"`; `baseDir` is optional. `source` is a source identifier, not the command kind—use the containing command's `source` field for `"extension"`, `"prompt"`, or `"skill"`.
1458
+
1459
+ ### Model and messages
1460
+
1461
+ A `Model` response is a full model object. This example shows its required common fields; optional provider-specific fields, such as `thinkingLevelMap`, `headers`, and `compat`, may also be present:
1364
1462
 
1365
1463
  ```json
1366
1464
  {
@@ -1382,72 +1480,17 @@ RPC messages use the public SDK and protocol types documented by this package. T
1382
1480
  }
1383
1481
  ```
1384
1482
 
1385
- ### UserMessage
1483
+ `AgentMessage` is the standard `UserMessage`, `AssistantMessage`, or `ToolResultMessage` union, plus Pi's session roles. A user message has no `attachments` field: images are `ImageContent` blocks in `content`.
1386
1484
 
1387
1485
  ```json
1388
- {
1389
- "role": "user",
1390
- "content": "Hello!",
1391
- "timestamp": 1733234567890,
1392
- "attachments": []
1393
- }
1486
+ {"role":"user","content":[{"type":"text","text":"Hello!"},{"type":"image","data":"base64-encoded-data","mimeType":"image/png"}],"timestamp":1733234567890}
1487
+ {"role":"assistant","content":[{"type":"text","text":"Hello!"},{"type":"toolCall","id":"call_123","name":"bash","arguments":{"command":"ls"}}],"api":"anthropic-messages","provider":"anthropic","model":"claude-sonnet-4-20250514","usage":{"input":100,"output":50,"cacheRead":0,"cacheWrite":0,"totalTokens":150,"cost":{"input":0.0003,"output":0.00075,"cacheRead":0,"cacheWrite":0,"total":0.00105}},"stopReason":"stop","timestamp":1733234567890}
1488
+ {"role":"toolResult","toolCallId":"call_123","toolName":"bash","content":[{"type":"text","text":"total 48\ndrwxr-xr-x ..."}],"isError":false,"timestamp":1733234567890}
1394
1489
  ```
1395
1490
 
1396
- The `content` field can be a string or an array of `TextContent`/`ImageContent` blocks.
1491
+ Assistant stop reasons are `"stop"`, `"length"`, `"toolUse"`, `"error"`, and `"aborted"`. Tool results can additionally carry `details`, `usage`, and `addedToolNames`; when present, `usage` reports nested LLM work and contributes to session totals.
1397
1492
 
1398
- ### AssistantMessage
1399
-
1400
- ```json
1401
- {
1402
- "role": "assistant",
1403
- "content": [
1404
- {"type": "text", "text": "Hello! How can I help?"},
1405
- {"type": "thinking", "thinking": "User is greeting me..."},
1406
- {"type": "toolCall", "id": "call_123", "name": "bash", "arguments": {"command": "ls"}}
1407
- ],
1408
- "api": "anthropic-messages",
1409
- "provider": "anthropic",
1410
- "model": "claude-sonnet-4-20250514",
1411
- "usage": {
1412
- "input": 100,
1413
- "output": 50,
1414
- "cacheRead": 0,
1415
- "cacheWrite": 0,
1416
- "cost": {"input": 0.0003, "output": 0.00075, "cacheRead": 0, "cacheWrite": 0, "total": 0.00105}
1417
- },
1418
- "stopReason": "stop",
1419
- "timestamp": 1733234567890
1420
- }
1421
- ```
1422
-
1423
- Stop reasons: `"stop"`, `"length"`, `"toolUse"`, `"error"`, `"aborted"`
1424
-
1425
- ### ToolResultMessage
1426
-
1427
- ```json
1428
- {
1429
- "role": "toolResult",
1430
- "toolCallId": "call_123",
1431
- "toolName": "bash",
1432
- "content": [{"type": "text", "text": "total 48\ndrwxr-xr-x ..."}],
1433
- "usage": {
1434
- "input": 100,
1435
- "output": 50,
1436
- "cacheRead": 0,
1437
- "cacheWrite": 0,
1438
- "totalTokens": 150,
1439
- "cost": {"input": 0.0003, "output": 0.00075, "cacheRead": 0, "cacheWrite": 0, "total": 0.00105}
1440
- },
1441
- "isError": false,
1442
- "timestamp": 1733234567890
1443
- }
1444
- ```
1445
-
1446
- `usage` is optional and reports nested LLM work performed by the tool. When present, it contributes to session token and cost totals.
1447
-
1448
- ### BashExecutionMessage
1449
-
1450
- Created by the `bash` RPC command (not by LLM tool calls):
1493
+ The Pi-specific roles are `bashExecution`, `custom`, `branchSummary`, and `compactionSummary`. For example, `bash` creates this message (not an LLM tool result):
1451
1494
 
1452
1495
  ```json
1453
1496
  {
@@ -1457,46 +1500,45 @@ Created by the `bash` RPC command (not by LLM tool calls):
1457
1500
  "exitCode": 0,
1458
1501
  "cancelled": false,
1459
1502
  "truncated": false,
1460
- "fullOutputPath": null,
1461
- "timestamp": 1733234567890
1503
+ "timestamp": 1733234567890,
1504
+ "excludeFromContext": true
1462
1505
  }
1463
1506
  ```
1464
1507
 
1465
- ### Attachment
1466
-
1467
- ```json
1468
- {
1469
- "id": "img1",
1470
- "type": "image",
1471
- "fileName": "photo.jpg",
1472
- "mimeType": "image/jpeg",
1473
- "size": 102400,
1474
- "content": "base64-encoded-data...",
1475
- "extractedText": null,
1476
- "preview": null
1477
- }
1478
- ```
1508
+ `fullOutputPath` is an optional string on `BashExecutionMessage` and `BashResult`, and `exitCode` is omitted when cancellation leaves it undefined. See [Session Format](session-format.md) for the other Pi-specific message and `SessionEntry` shapes.
1479
1509
 
1480
1510
  ## Example: Basic Client (Python)
1481
1511
 
1482
1512
  ```python
1483
- import subprocess
1484
1513
  import json
1514
+ import os
1515
+ import subprocess
1485
1516
 
1486
1517
  proc = subprocess.Popen(
1487
1518
  ["pi", "--mode", "rpc", "--no-session"],
1488
1519
  stdin=subprocess.PIPE,
1489
1520
  stdout=subprocess.PIPE,
1490
- text=True
1491
1521
  )
1492
1522
 
1493
- def send(cmd):
1494
- proc.stdin.write(json.dumps(cmd) + "\n")
1523
+ def send(command):
1524
+ proc.stdin.write((json.dumps(command) + "\n").encode("utf-8"))
1495
1525
  proc.stdin.flush()
1496
1526
 
1527
+ def decode_record(record):
1528
+ if record.endswith(b"\r"):
1529
+ record = record[:-1]
1530
+ return json.loads(record.decode("utf-8"))
1531
+
1497
1532
  def read_events():
1498
- for line in proc.stdout:
1499
- yield json.loads(line)
1533
+ buffer = b""
1534
+ while chunk := os.read(proc.stdout.fileno(), 4096):
1535
+ buffer += chunk
1536
+ while (newline := buffer.find(b"\n")) != -1:
1537
+ record, buffer = buffer[:newline], buffer[newline + 1:]
1538
+ if record:
1539
+ yield decode_record(record)
1540
+ if buffer:
1541
+ yield decode_record(buffer)
1500
1542
 
1501
1543
  # Send prompt
1502
1544
  send({"type": "prompt", "message": "Hello!"})
@@ -1507,15 +1549,15 @@ for event in read_events():
1507
1549
  delta = event.get("assistantMessageEvent", {})
1508
1550
  if delta.get("type") == "text_delta":
1509
1551
  print(delta["delta"], end="", flush=True)
1510
-
1511
- if event.get("type") == "agent_end":
1552
+
1553
+ if event.get("type") == "agent_settled":
1512
1554
  print()
1513
1555
  break
1514
1556
  ```
1515
1557
 
1516
1558
  ## Example: Interactive Client (Node.js)
1517
1559
 
1518
- For a complete interactive example, see the published [RPC extension UI example](../examples/rpc-extension-ui.ts), which pairs with the published [RPC demo extension](../examples/extensions/rpc-demo.ts). For embedded Node.js or TypeScript clients, use the [public SDK API](sdk.md).
1560
+ For a TUI demonstration of handling extension UI requests, see the published [RPC extension UI example](../examples/rpc-extension-ui.ts), which pairs with the published [RPC demo extension](../examples/extensions/rpc-demo.ts). Use strict JSONL framing such as the reader below in protocol clients. For embedded Node.js or TypeScript clients, use the [public SDK API](sdk.md).
1519
1561
 
1520
1562
  ```javascript
1521
1563
  const { spawn } = require("child_process");