@codex-infinity/pi-infinity 0.52.4 → 0.60.2

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 (269) hide show
  1. package/CHANGELOG.md +387 -0
  2. package/README.md +97 -66
  3. package/dist/bun/cli.d.ts +3 -0
  4. package/dist/bun/cli.d.ts.map +1 -0
  5. package/dist/bun/cli.js +6 -0
  6. package/dist/bun/cli.js.map +1 -0
  7. package/dist/bun/register-bedrock.d.ts +2 -0
  8. package/dist/bun/register-bedrock.d.ts.map +1 -0
  9. package/dist/bun/register-bedrock.js +4 -0
  10. package/dist/bun/register-bedrock.js.map +1 -0
  11. package/dist/cli/args.d.ts +2 -0
  12. package/dist/cli/args.d.ts.map +1 -1
  13. package/dist/cli/args.js +17 -6
  14. package/dist/cli/args.js.map +1 -1
  15. package/dist/cli/initial-message.d.ts +18 -0
  16. package/dist/cli/initial-message.d.ts.map +1 -0
  17. package/dist/cli/initial-message.js +22 -0
  18. package/dist/cli/initial-message.js.map +1 -0
  19. package/dist/cli.d.ts.map +1 -1
  20. package/dist/cli.js +2 -0
  21. package/dist/cli.js.map +1 -1
  22. package/dist/core/agent-session.d.ts +42 -6
  23. package/dist/core/agent-session.d.ts.map +1 -1
  24. package/dist/core/agent-session.js +346 -72
  25. package/dist/core/agent-session.js.map +1 -1
  26. package/dist/core/auth-storage.d.ts +1 -0
  27. package/dist/core/auth-storage.d.ts.map +1 -1
  28. package/dist/core/auth-storage.js +27 -2
  29. package/dist/core/auth-storage.js.map +1 -1
  30. package/dist/core/bash-executor.d.ts +6 -7
  31. package/dist/core/bash-executor.d.ts.map +1 -1
  32. package/dist/core/bash-executor.js +8 -107
  33. package/dist/core/bash-executor.js.map +1 -1
  34. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  35. package/dist/core/compaction/branch-summarization.js +1 -0
  36. package/dist/core/compaction/branch-summarization.js.map +1 -1
  37. package/dist/core/compaction/compaction.d.ts.map +1 -1
  38. package/dist/core/compaction/compaction.js +6 -1
  39. package/dist/core/compaction/compaction.js.map +1 -1
  40. package/dist/core/compaction/utils.d.ts +3 -0
  41. package/dist/core/compaction/utils.d.ts.map +1 -1
  42. package/dist/core/compaction/utils.js +16 -1
  43. package/dist/core/compaction/utils.js.map +1 -1
  44. package/dist/core/exec.d.ts.map +1 -1
  45. package/dist/core/exec.js +7 -3
  46. package/dist/core/exec.js.map +1 -1
  47. package/dist/core/export-html/index.d.ts +5 -2
  48. package/dist/core/export-html/index.d.ts.map +1 -1
  49. package/dist/core/export-html/index.js +4 -3
  50. package/dist/core/export-html/index.js.map +1 -1
  51. package/dist/core/export-html/template.js +11 -14
  52. package/dist/core/export-html/tool-renderer.d.ts +5 -2
  53. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  54. package/dist/core/export-html/tool-renderer.js +17 -4
  55. package/dist/core/export-html/tool-renderer.js.map +1 -1
  56. package/dist/core/extensions/index.d.ts +2 -2
  57. package/dist/core/extensions/index.d.ts.map +1 -1
  58. package/dist/core/extensions/index.js +1 -1
  59. package/dist/core/extensions/index.js.map +1 -1
  60. package/dist/core/extensions/loader.d.ts.map +1 -1
  61. package/dist/core/extensions/loader.js +37 -11
  62. package/dist/core/extensions/loader.js.map +1 -1
  63. package/dist/core/extensions/runner.d.ts +8 -4
  64. package/dist/core/extensions/runner.d.ts.map +1 -1
  65. package/dist/core/extensions/runner.js +77 -8
  66. package/dist/core/extensions/runner.js.map +1 -1
  67. package/dist/core/extensions/types.d.ts +56 -4
  68. package/dist/core/extensions/types.d.ts.map +1 -1
  69. package/dist/core/extensions/types.js.map +1 -1
  70. package/dist/core/extensions/wrapper.d.ts +4 -11
  71. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  72. package/dist/core/extensions/wrapper.js +4 -78
  73. package/dist/core/extensions/wrapper.js.map +1 -1
  74. package/dist/core/footer-data-provider.d.ts +6 -1
  75. package/dist/core/footer-data-provider.d.ts.map +1 -1
  76. package/dist/core/footer-data-provider.js +83 -37
  77. package/dist/core/footer-data-provider.js.map +1 -1
  78. package/dist/core/index.d.ts +1 -1
  79. package/dist/core/index.d.ts.map +1 -1
  80. package/dist/core/index.js +1 -1
  81. package/dist/core/index.js.map +1 -1
  82. package/dist/core/keybindings.d.ts +3 -0
  83. package/dist/core/keybindings.d.ts.map +1 -1
  84. package/dist/core/keybindings.js +22 -12
  85. package/dist/core/keybindings.js.map +1 -1
  86. package/dist/core/model-registry.d.ts +11 -0
  87. package/dist/core/model-registry.d.ts.map +1 -1
  88. package/dist/core/model-registry.js +56 -16
  89. package/dist/core/model-registry.js.map +1 -1
  90. package/dist/core/model-resolver.d.ts +6 -0
  91. package/dist/core/model-resolver.d.ts.map +1 -1
  92. package/dist/core/model-resolver.js +122 -39
  93. package/dist/core/model-resolver.js.map +1 -1
  94. package/dist/core/package-manager.d.ts +19 -1
  95. package/dist/core/package-manager.d.ts.map +1 -1
  96. package/dist/core/package-manager.js +290 -57
  97. package/dist/core/package-manager.js.map +1 -1
  98. package/dist/core/resolve-config-value.d.ts.map +1 -1
  99. package/dist/core/resolve-config-value.js +43 -8
  100. package/dist/core/resolve-config-value.js.map +1 -1
  101. package/dist/core/resource-loader.d.ts.map +1 -1
  102. package/dist/core/resource-loader.js +4 -7
  103. package/dist/core/resource-loader.js.map +1 -1
  104. package/dist/core/sdk.d.ts +1 -1
  105. package/dist/core/sdk.d.ts.map +1 -1
  106. package/dist/core/sdk.js +7 -0
  107. package/dist/core/sdk.js.map +1 -1
  108. package/dist/core/session-manager.d.ts +1 -0
  109. package/dist/core/session-manager.d.ts.map +1 -1
  110. package/dist/core/session-manager.js +21 -15
  111. package/dist/core/session-manager.js.map +1 -1
  112. package/dist/core/settings-manager.d.ts +10 -0
  113. package/dist/core/settings-manager.d.ts.map +1 -1
  114. package/dist/core/settings-manager.js +59 -5
  115. package/dist/core/settings-manager.js.map +1 -1
  116. package/dist/core/skills.d.ts +3 -2
  117. package/dist/core/skills.d.ts.map +1 -1
  118. package/dist/core/skills.js +29 -8
  119. package/dist/core/skills.js.map +1 -1
  120. package/dist/core/slash-commands.d.ts.map +1 -1
  121. package/dist/core/slash-commands.js +3 -2
  122. package/dist/core/slash-commands.js.map +1 -1
  123. package/dist/core/system-prompt.d.ts +4 -0
  124. package/dist/core/system-prompt.d.ts.map +1 -1
  125. package/dist/core/system-prompt.js +43 -29
  126. package/dist/core/system-prompt.js.map +1 -1
  127. package/dist/core/tools/bash.d.ts +8 -0
  128. package/dist/core/tools/bash.d.ts.map +1 -1
  129. package/dist/core/tools/bash.js +77 -69
  130. package/dist/core/tools/bash.js.map +1 -1
  131. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  132. package/dist/core/tools/edit-diff.js +1 -0
  133. package/dist/core/tools/edit-diff.js.map +1 -1
  134. package/dist/core/tools/find.d.ts.map +1 -1
  135. package/dist/core/tools/find.js +6 -3
  136. package/dist/core/tools/find.js.map +1 -1
  137. package/dist/core/tools/index.d.ts +1 -1
  138. package/dist/core/tools/index.d.ts.map +1 -1
  139. package/dist/core/tools/index.js +1 -1
  140. package/dist/core/tools/index.js.map +1 -1
  141. package/dist/index.d.ts +3 -3
  142. package/dist/index.d.ts.map +1 -1
  143. package/dist/index.js +2 -2
  144. package/dist/index.js.map +1 -1
  145. package/dist/main.d.ts.map +1 -1
  146. package/dist/main.js +116 -36
  147. package/dist/main.js.map +1 -1
  148. package/dist/modes/interactive/components/extension-editor.d.ts +5 -2
  149. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  150. package/dist/modes/interactive/components/extension-editor.js +9 -0
  151. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  152. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  153. package/dist/modes/interactive/components/footer.js +8 -23
  154. package/dist/modes/interactive/components/footer.js.map +1 -1
  155. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  156. package/dist/modes/interactive/components/login-dialog.js +1 -1
  157. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  158. package/dist/modes/interactive/components/model-selector.d.ts +1 -1
  159. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  160. package/dist/modes/interactive/components/model-selector.js +1 -1
  161. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  162. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  163. package/dist/modes/interactive/components/oauth-selector.js +1 -1
  164. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  165. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  166. package/dist/modes/interactive/components/session-selector.js +1 -1
  167. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  168. package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  169. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  170. package/dist/modes/interactive/components/settings-selector.js +15 -1
  171. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  172. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  173. package/dist/modes/interactive/components/show-images-selector.js +5 -1
  174. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  175. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  176. package/dist/modes/interactive/components/theme-selector.js +5 -1
  177. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  178. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  179. package/dist/modes/interactive/components/thinking-selector.js +5 -1
  180. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  181. package/dist/modes/interactive/components/tool-execution.d.ts +7 -0
  182. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  183. package/dist/modes/interactive/components/tool-execution.js +158 -7
  184. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  185. package/dist/modes/interactive/components/tree-selector.d.ts +21 -2
  186. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  187. package/dist/modes/interactive/components/tree-selector.js +127 -10
  188. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  189. package/dist/modes/interactive/components/user-message.d.ts +1 -0
  190. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  191. package/dist/modes/interactive/components/user-message.js +12 -0
  192. package/dist/modes/interactive/components/user-message.js.map +1 -1
  193. package/dist/modes/interactive/interactive-mode.d.ts +5 -1
  194. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  195. package/dist/modes/interactive/interactive-mode.js +215 -71
  196. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  197. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  198. package/dist/modes/interactive/theme/theme.js +5 -0
  199. package/dist/modes/interactive/theme/theme.js.map +1 -1
  200. package/dist/modes/rpc/jsonl.d.ts +17 -0
  201. package/dist/modes/rpc/jsonl.d.ts.map +1 -0
  202. package/dist/modes/rpc/jsonl.js +49 -0
  203. package/dist/modes/rpc/jsonl.js.map +1 -0
  204. package/dist/modes/rpc/rpc-client.d.ts +1 -1
  205. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  206. package/dist/modes/rpc/rpc-client.js +7 -11
  207. package/dist/modes/rpc/rpc-client.js.map +1 -1
  208. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  209. package/dist/modes/rpc/rpc-mode.js +9 -11
  210. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  211. package/dist/utils/child-process.d.ts +11 -0
  212. package/dist/utils/child-process.d.ts.map +1 -0
  213. package/dist/utils/child-process.js +78 -0
  214. package/dist/utils/child-process.js.map +1 -0
  215. package/dist/utils/clipboard-image.d.ts.map +1 -1
  216. package/dist/utils/clipboard-image.js +94 -11
  217. package/dist/utils/clipboard-image.js.map +1 -1
  218. package/dist/utils/clipboard-native.d.ts +1 -0
  219. package/dist/utils/clipboard-native.d.ts.map +1 -1
  220. package/dist/utils/clipboard-native.js.map +1 -1
  221. package/dist/utils/clipboard.d.ts +1 -1
  222. package/dist/utils/clipboard.d.ts.map +1 -1
  223. package/dist/utils/clipboard.js +27 -16
  224. package/dist/utils/clipboard.js.map +1 -1
  225. package/dist/utils/exif-orientation.d.ts +5 -0
  226. package/dist/utils/exif-orientation.d.ts.map +1 -0
  227. package/dist/utils/exif-orientation.js +158 -0
  228. package/dist/utils/exif-orientation.js.map +1 -0
  229. package/dist/utils/image-convert.d.ts.map +1 -1
  230. package/dist/utils/image-convert.js +5 -1
  231. package/dist/utils/image-convert.js.map +1 -1
  232. package/dist/utils/image-resize.d.ts.map +1 -1
  233. package/dist/utils/image-resize.js +6 -1
  234. package/dist/utils/image-resize.js.map +1 -1
  235. package/dist/utils/tools-manager.d.ts.map +1 -1
  236. package/dist/utils/tools-manager.js +66 -21
  237. package/dist/utils/tools-manager.js.map +1 -1
  238. package/docs/compaction.md +2 -0
  239. package/docs/custom-provider.md +57 -9
  240. package/docs/extensions.md +125 -12
  241. package/docs/keybindings.md +11 -1
  242. package/docs/models.md +44 -2
  243. package/docs/packages.md +9 -0
  244. package/docs/providers.md +10 -1
  245. package/docs/rpc.md +44 -7
  246. package/docs/sdk.md +2 -2
  247. package/docs/settings.md +11 -0
  248. package/docs/terminal-setup.md +39 -3
  249. package/docs/tmux.md +61 -0
  250. package/docs/tree.md +9 -0
  251. package/examples/extensions/README.md +2 -0
  252. package/examples/extensions/antigravity-image-gen.ts +8 -5
  253. package/examples/extensions/built-in-tool-renderer.ts +246 -0
  254. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  255. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  256. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  257. package/examples/extensions/custom-provider-gitlab-duo/test.ts +2 -2
  258. package/examples/extensions/custom-provider-qwen-cli/package.json +1 -1
  259. package/examples/extensions/dynamic-tools.ts +74 -0
  260. package/examples/extensions/overlay-qa-tests.ts +468 -1
  261. package/examples/extensions/preset.ts +2 -3
  262. package/examples/extensions/provider-payload.ts +14 -0
  263. package/examples/extensions/sandbox/index.ts +2 -3
  264. package/examples/extensions/subagent/agents.ts +2 -3
  265. package/examples/extensions/tool-override.ts +2 -3
  266. package/examples/extensions/with-deps/index.ts +1 -5
  267. package/examples/extensions/with-deps/package-lock.json +2 -2
  268. package/examples/extensions/with-deps/package.json +1 -1
  269. package/package.json +10 -7
@@ -225,8 +225,9 @@ Run `npm install` in the extension directory, then imports from `node_modules/`
225
225
  ### Lifecycle Overview
226
226
 
227
227
  ```
228
- pi starts
228
+ pi starts (CLI only)
229
229
 
230
+ ├─► session_directory (CLI startup only, no ctx)
230
231
  └─► session_start
231
232
 
232
233
 
@@ -243,13 +244,14 @@ user sends prompt ────────────────────
243
244
  │ │ │ │
244
245
  │ ├─► turn_start │ │
245
246
  │ ├─► context (can modify messages) │ │
247
+ │ ├─► before_provider_request (can inspect or replace payload)
246
248
  │ │ │ │
247
249
  │ │ LLM responds, may call tools: │ │
248
- │ │ ├─► tool_call (can block) │ │
249
250
  │ │ ├─► tool_execution_start │ │
251
+ │ │ ├─► tool_call (can block) │ │
250
252
  │ │ ├─► tool_execution_update │ │
251
- │ │ ├─► tool_execution_end │ │
252
- │ │ └─► tool_result (can modify) │ │
253
+ │ │ ├─► tool_result (can modify) │ │
254
+ │ │ └─► tool_execution_end │ │
253
255
  │ │ │ │
254
256
  │ └─► turn_end │ │
255
257
  │ │
@@ -284,6 +286,26 @@ exit (Ctrl+C, Ctrl+D)
284
286
 
285
287
  See [session.md](session.md) for session storage internals and the SessionManager API.
286
288
 
289
+ #### session_directory
290
+
291
+ Fired by the `pi` CLI during startup session resolution, before the initial session manager is created.
292
+
293
+ This event is:
294
+ - CLI-only. It is not emitted in SDK mode.
295
+ - Startup-only. It is not emitted for later interactive `/new` or `/resume` actions.
296
+ - Bypassed when `--session-dir` is provided.
297
+ - Special-cased to receive no `ctx` argument.
298
+
299
+ If multiple extensions return `sessionDir`, the last one wins.
300
+
301
+ ```typescript
302
+ pi.on("session_directory", async (event) => {
303
+ return {
304
+ sessionDir: `/tmp/pi-sessions/${encodeURIComponent(event.cwd)}`,
305
+ };
306
+ });
307
+ ```
308
+
287
309
  #### session_start
288
310
 
289
311
  Fired on initial session load.
@@ -463,6 +485,11 @@ pi.on("message_end", async (event, ctx) => {
463
485
 
464
486
  Fired for tool execution lifecycle updates.
465
487
 
488
+ In parallel tool mode:
489
+ - `tool_execution_start` is emitted in assistant source order during the preflight phase
490
+ - `tool_execution_update` events may interleave across tools
491
+ - `tool_execution_end` is emitted in assistant source order, matching final tool result message order
492
+
466
493
  ```typescript
467
494
  pi.on("tool_execution_start", async (event, ctx) => {
468
495
  // event.toolCallId, event.toolName, event.args
@@ -489,6 +516,21 @@ pi.on("context", async (event, ctx) => {
489
516
  });
490
517
  ```
491
518
 
519
+ #### before_provider_request
520
+
521
+ Fired after the provider-specific payload is built, right before the request is sent. Handlers run in extension load order. Returning `undefined` keeps the payload unchanged. Returning any other value replaces the payload for later handlers and for the actual request.
522
+
523
+ ```typescript
524
+ pi.on("before_provider_request", (event, ctx) => {
525
+ console.log(JSON.stringify(event.payload, null, 2));
526
+
527
+ // Optional: replace payload
528
+ // return { ...event.payload, temperature: 0 };
529
+ });
530
+ ```
531
+
532
+ This is mainly useful for debugging provider serialization and cache behavior.
533
+
492
534
  ### Model Events
493
535
 
494
536
  #### model_select
@@ -516,7 +558,11 @@ Use this to update UI elements (status bars, footers) or perform model-specific
516
558
 
517
559
  #### tool_call
518
560
 
519
- Fired before tool executes. **Can block.** Use `isToolCallEventType` to narrow and get typed inputs.
561
+ Fired after `tool_execution_start`, before the tool executes. **Can block.** Use `isToolCallEventType` to narrow and get typed inputs.
562
+
563
+ Before `tool_call` runs, pi waits for previously emitted Agent events to finish draining through `AgentSession`. This means `ctx.sessionManager` is up to date through the current assistant tool-calling message.
564
+
565
+ In the default parallel tool execution mode, sibling tool calls from the same assistant message are preflighted sequentially, then executed concurrently. `tool_call` is not guaranteed to see sibling tool results from that same assistant message in `ctx.sessionManager`.
520
566
 
521
567
  ```typescript
522
568
  import { isToolCallEventType } from "@mariozechner/pi-coding-agent";
@@ -565,7 +611,7 @@ pi.on("tool_call", (event) => {
565
611
 
566
612
  #### tool_result
567
613
 
568
- Fired after tool executes. **Can modify result.**
614
+ Fired after tool execution finishes and before `tool_execution_end` plus the final tool result message events are emitted. **Can modify result.**
569
615
 
570
616
  `tool_result` handlers chain like middleware:
571
617
  - Handlers run in extension load order
@@ -595,6 +641,8 @@ pi.on("tool_result", async (event, ctx) => {
595
641
  Fired when user executes `!` or `!!` commands. **Can intercept.**
596
642
 
597
643
  ```typescript
644
+ import { createLocalBashOperations } from "@mariozechner/pi-coding-agent";
645
+
598
646
  pi.on("user_bash", (event, ctx) => {
599
647
  // event.command - the bash command
600
648
  // event.excludeFromContext - true if !! prefix
@@ -603,7 +651,17 @@ pi.on("user_bash", (event, ctx) => {
603
651
  // Option 1: Provide custom operations (e.g., SSH)
604
652
  return { operations: remoteBashOps };
605
653
 
606
- // Option 2: Full replacement - return result directly
654
+ // Option 2: Wrap pi's built-in local bash backend
655
+ const local = createLocalBashOperations();
656
+ return {
657
+ operations: {
658
+ exec(command, cwd, options) {
659
+ return local.exec(`source ~/.profile\n${command}`, cwd, options);
660
+ }
661
+ }
662
+ };
663
+
664
+ // Option 3: Full replacement - return result directly
607
665
  return { result: { output: "...", exitCode: 0, cancelled: false, truncated: false } };
608
666
  });
609
667
  ```
@@ -658,7 +716,9 @@ Transforms chain across handlers. See [input-transform.ts](../examples/extension
658
716
 
659
717
  ## ExtensionContext
660
718
 
661
- Every handler receives `ctx: ExtensionContext`:
719
+ All handlers except `session_directory` receive `ctx: ExtensionContext`.
720
+
721
+ `session_directory` is a CLI startup hook and receives only the event.
662
722
 
663
723
  ### ctx.ui
664
724
 
@@ -676,6 +736,8 @@ Current working directory.
676
736
 
677
737
  Read-only access to session state. See [session.md](session.md) for the full SessionManager API and entry types.
678
738
 
739
+ For `tool_call`, this state is synchronized through the current assistant message before handlers run. In parallel tool execution mode it is still not guaranteed to include sibling tool results from the same assistant message.
740
+
679
741
  ```typescript
680
742
  ctx.sessionManager.getEntries() // All entries
681
743
  ctx.sessionManager.getBranch() // Current branch
@@ -880,6 +942,14 @@ Subscribe to events. See [Events](#events) for event types and return values.
880
942
 
881
943
  Register a custom tool callable by the LLM. See [Custom Tools](#custom-tools) for full details.
882
944
 
945
+ `pi.registerTool()` works both during extension load and after startup. You can call it inside `session_start`, command handlers, or other event handlers. New tools are refreshed immediately in the same session, so they appear in `pi.getAllTools()` and are callable by the LLM without `/reload`.
946
+
947
+ Use `pi.setActiveTools()` to enable or disable tools (including dynamically added tools) at runtime.
948
+
949
+ Use `promptSnippet` to opt a custom tool into a one-line entry in `Available tools`, and `promptGuidelines` to append tool-specific bullets to the default `Guidelines` section when the tool is active.
950
+
951
+ See [dynamic-tools.ts](../examples/extensions/dynamic-tools.ts) for a full example.
952
+
883
953
  ```typescript
884
954
  import { Type } from "@sinclair/typebox";
885
955
  import { StringEnum } from "@mariozechner/pi-ai";
@@ -888,6 +958,8 @@ pi.registerTool({
888
958
  name: "my_tool",
889
959
  label: "My Tool",
890
960
  description: "What this tool does",
961
+ promptSnippet: "Summarize or transform text according to action",
962
+ promptGuidelines: ["Use this tool when the user asks to summarize previously generated text."],
891
963
  parameters: Type.Object({
892
964
  action: StringEnum(["list", "add"] as const),
893
965
  text: Type.Optional(Type.String()),
@@ -927,7 +999,7 @@ pi.sendMessage({
927
999
 
928
1000
  **Options:**
929
1001
  - `deliverAs` - Delivery mode:
930
- - `"steer"` (default) - Interrupts streaming. Delivered after current tool finishes, remaining tools skipped.
1002
+ - `"steer"` (default) - Queues the message while streaming. Delivered after the current assistant turn finishes executing its tool calls, before the next LLM call.
931
1003
  - `"followUp"` - Waits for agent to finish. Delivered only when agent has no more tool calls.
932
1004
  - `"nextTurn"` - Queued for next user prompt. Does not interrupt or trigger anything.
933
1005
  - `triggerTurn: true` - If agent is idle, trigger an LLM response immediately. Only applies to `"steer"` and `"followUp"` modes (ignored for `"nextTurn"`).
@@ -953,7 +1025,7 @@ pi.sendUserMessage("And then summarize", { deliverAs: "followUp" });
953
1025
 
954
1026
  **Options:**
955
1027
  - `deliverAs` - Required when agent is streaming:
956
- - `"steer"` - Interrupts after current tool, remaining tools skipped
1028
+ - `"steer"` - Queues the message for delivery after the current assistant turn finishes executing its tool calls
957
1029
  - `"followUp"` - Waits for agent to finish all tools
958
1030
 
959
1031
  When not streaming, the message is sent immediately and triggers a new turn. When streaming without `deliverAs`, throws an error.
@@ -1116,7 +1188,7 @@ const result = await pi.exec("git", ["status"], { signal, timeout: 5000 });
1116
1188
 
1117
1189
  ### pi.getActiveTools() / pi.getAllTools() / pi.setActiveTools(names)
1118
1190
 
1119
- Manage active tools.
1191
+ Manage active tools. This works for both built-in tools and dynamically registered tools.
1120
1192
 
1121
1193
  ```typescript
1122
1194
  const active = pi.getActiveTools(); // ["read", "bash", "edit", "write"]
@@ -1161,6 +1233,8 @@ pi.events.emit("my:event", { ... });
1161
1233
 
1162
1234
  Register or override a model provider dynamically. Useful for proxies, custom endpoints, or team-wide model configurations.
1163
1235
 
1236
+ Calls made during the extension factory function are queued and applied once the runner initialises. Calls made after that — for example from a command handler following a user setup flow — take effect immediately without requiring a `/reload`.
1237
+
1164
1238
  ```typescript
1165
1239
  // Register a new provider with custom models
1166
1240
  pi.registerProvider("my-proxy", {
@@ -1221,6 +1295,21 @@ pi.registerProvider("corporate-ai", {
1221
1295
 
1222
1296
  See [custom-provider.md](custom-provider.md) for advanced topics: custom streaming APIs, OAuth details, model definition reference.
1223
1297
 
1298
+ ### pi.unregisterProvider(name)
1299
+
1300
+ Remove a previously registered provider and its models. Built-in models that were overridden by the provider are restored. Has no effect if the provider was not registered.
1301
+
1302
+ Like `registerProvider`, this takes effect immediately when called after the initial load phase, so a `/reload` is not required.
1303
+
1304
+ ```typescript
1305
+ pi.registerCommand("my-setup-teardown", {
1306
+ description: "Remove the custom proxy provider",
1307
+ handler: async (_args, _ctx) => {
1308
+ pi.unregisterProvider("my-proxy");
1309
+ },
1310
+ });
1311
+ ```
1312
+
1224
1313
  ## State Management
1225
1314
 
1226
1315
  Extensions with state should store it in tool result `details` for proper branching support:
@@ -1259,6 +1348,10 @@ export default function (pi: ExtensionAPI) {
1259
1348
 
1260
1349
  Register tools the LLM can call via `pi.registerTool()`. Tools appear in the system prompt and can have custom rendering.
1261
1350
 
1351
+ Use `promptSnippet` for a short one-line entry in the `Available tools` section in the default system prompt. If omitted, custom tools are left out of that section.
1352
+
1353
+ Use `promptGuidelines` to add tool-specific bullets to the default system prompt `Guidelines` section. These bullets are included only while the tool is active (for example, after `pi.setActiveTools([...])`).
1354
+
1262
1355
  Note: Some models are idiots and include the @ prefix in tool path arguments. Built-in tools strip a leading @ before resolving paths. If your custom tool accepts a path, normalize a leading @ as well.
1263
1356
 
1264
1357
  ### Tool Definition
@@ -1272,6 +1365,10 @@ pi.registerTool({
1272
1365
  name: "my_tool",
1273
1366
  label: "My Tool",
1274
1367
  description: "What this tool does (shown to LLM)",
1368
+ promptSnippet: "List or add items in the project todo list",
1369
+ promptGuidelines: [
1370
+ "Use this tool for todo planning instead of direct file edits when the user asks for a task list."
1371
+ ],
1275
1372
  parameters: Type.Object({
1276
1373
  action: StringEnum(["list", "add"] as const), // Use StringEnum for Google compatibility
1277
1374
  text: Type.Optional(Type.String()),
@@ -1305,6 +1402,18 @@ pi.registerTool({
1305
1402
  });
1306
1403
  ```
1307
1404
 
1405
+ **Signaling errors:** To mark a tool execution as failed (sets `isError: true` on the result and reports it to the LLM), throw an error from `execute`. Returning a value never sets the error flag regardless of what properties you include in the return object.
1406
+
1407
+ ```typescript
1408
+ // Correct: throw to signal an error
1409
+ async execute(toolCallId, params) {
1410
+ if (!isValid(params.input)) {
1411
+ throw new Error(`Invalid input: ${params.input}`);
1412
+ }
1413
+ return { content: [{ type: "text", text: "OK" }], details: {} };
1414
+ }
1415
+ ```
1416
+
1308
1417
  **Important:** Use `StringEnum` from `@mariozechner/pi-ai` for string enums. `Type.Union`/`Type.Literal` doesn't work with Google's API.
1309
1418
 
1310
1419
  ### Overriding Built-in Tools
@@ -1368,6 +1477,8 @@ pi.registerTool({
1368
1477
 
1369
1478
  **Operations interfaces:** `ReadOperations`, `WriteOperations`, `EditOperations`, `BashOperations`, `LsOperations`, `GrepOperations`, `FindOperations`
1370
1479
 
1480
+ For `user_bash`, extensions can reuse pi's local shell backend via `createLocalBashOperations()` instead of reimplementing local process spawning, shell resolution, and process-tree termination.
1481
+
1371
1482
  The bash tool also supports a spawn hook to adjust the command, cwd, or env before execution:
1372
1483
 
1373
1484
  ```typescript
@@ -1845,7 +1956,7 @@ const highlighted = highlightCode(code, lang, theme);
1845
1956
 
1846
1957
  - Extension errors are logged, agent continues
1847
1958
  - `tool_call` errors block the tool (fail-safe)
1848
- - Tool `execute` errors are reported to the LLM with `isError: true`
1959
+ - Tool `execute` errors must be signaled by throwing; the thrown error is caught, reported to the LLM with `isError: true`, and execution continues
1849
1960
 
1850
1961
  ## Mode Behavior
1851
1962
 
@@ -1869,6 +1980,7 @@ All examples in [examples/extensions/](../examples/extensions/).
1869
1980
  | `question.ts` | Tool with user interaction | `registerTool`, `ui.select` |
1870
1981
  | `questionnaire.ts` | Multi-step wizard tool | `registerTool`, `ui.custom` |
1871
1982
  | `todo.ts` | Stateful tool with persistence | `registerTool`, `appendEntry`, `renderResult`, session events |
1983
+ | `dynamic-tools.ts` | Register tools after startup and during commands | `registerTool`, `session_start`, `registerCommand` |
1872
1984
  | `truncated-tool.ts` | Output truncation example | `registerTool`, `truncateHead` |
1873
1985
  | `tool-override.ts` | Override built-in read tool | `registerTool` (same name as built-in) |
1874
1986
  | **Commands** |||
@@ -1886,6 +1998,7 @@ All examples in [examples/extensions/](../examples/extensions/).
1886
1998
  | `dirty-repo-guard.ts` | Warn on dirty git repo | `on("session_before_*")`, `exec` |
1887
1999
  | `input-transform.ts` | Transform user input | `on("input")` |
1888
2000
  | `model-status.ts` | React to model changes | `on("model_select")`, `setStatus` |
2001
+ | `provider-payload.ts` | Inspect or patch provider payloads | `on("before_provider_request")` |
1889
2002
  | `system-prompt-header.ts` | Display system prompt info | `on("agent_start")`, `getSystemPrompt` |
1890
2003
  | `claude-rules.ts` | Load rules from files | `on("session_start")`, `on("before_agent_start")` |
1891
2004
  | `file-trigger.ts` | File watcher triggers messages | `sendMessage` |
@@ -2,16 +2,19 @@
2
2
 
3
3
  All keyboard shortcuts can be customized via `~/.pi/agent/keybindings.json`. Each action can be bound to one or more keys.
4
4
 
5
+ After editing `keybindings.json`, run `/reload` in pi to apply the changes without restarting the session.
6
+
5
7
  ## Key Format
6
8
 
7
9
  `modifier+key` where modifiers are `ctrl`, `shift`, `alt` (combinable) and keys are:
8
10
 
9
11
  - **Letters:** `a-z`
12
+ - **Digits:** `0-9`
10
13
  - **Special:** `escape`, `esc`, `enter`, `return`, `tab`, `space`, `backspace`, `delete`, `insert`, `clear`, `home`, `end`, `pageUp`, `pageDown`, `up`, `down`, `left`, `right`
11
14
  - **Function:** `f1`-`f12`
12
15
  - **Symbols:** `` ` ``, `-`, `=`, `[`, `]`, `\`, `;`, `'`, `,`, `.`, `/`, `!`, `@`, `#`, `$`, `%`, `^`, `&`, `*`, `(`, `)`, `_`, `+`, `|`, `~`, `{`, `}`, `:`, `<`, `>`, `?`
13
16
 
14
- Modifier combinations: `ctrl+shift+x`, `alt+ctrl+x`, `ctrl+shift+alt+x`, etc.
17
+ Modifier combinations: `ctrl+shift+x`, `alt+ctrl+x`, `ctrl+shift+alt+x`, `ctrl+1`, etc.
15
18
 
16
19
  ## All Actions
17
20
 
@@ -119,6 +122,13 @@ Modifier combinations: `ctrl+shift+x`, `alt+ctrl+x`, `ctrl+shift+alt+x`, etc.
119
122
  | `selectConfirm` | `enter` | Confirm selection |
120
123
  | `selectCancel` | `escape`, `ctrl+c` | Cancel selection |
121
124
 
125
+ ### Tree Navigation
126
+
127
+ | Action | Default | Description |
128
+ |--------|---------|-------------|
129
+ | `treeFoldOrUp` | `ctrl+left`, `alt+left` | Fold current branch segment, or jump to the previous segment start |
130
+ | `treeUnfoldOrDown` | `ctrl+right`, `alt+right` | Unfold current branch segment, or jump to the next segment start or branch end |
131
+
122
132
  ### Session Picker
123
133
 
124
134
  | Action | Default | Description |
package/docs/models.md CHANGED
@@ -35,6 +35,32 @@ For local models (Ollama, LM Studio, vLLM), only `id` is required per model:
35
35
 
36
36
  The `apiKey` is required but Ollama ignores it, so any value works.
37
37
 
38
+ Some OpenAI-compatible servers do not understand the `developer` role used for reasoning-capable models. For those providers, set `compat.supportsDeveloperRole` to `false` so pi sends the system prompt as a `system` message instead. If the server also does not support `reasoning_effort`, set `compat.supportsReasoningEffort` to `false` too.
39
+
40
+ You can set `compat` at the provider level to apply to all models, or at the model level to override a specific model. This commonly applies to Ollama, vLLM, SGLang, and similar OpenAI-compatible servers.
41
+
42
+ ```json
43
+ {
44
+ "providers": {
45
+ "ollama": {
46
+ "baseUrl": "http://localhost:11434/v1",
47
+ "api": "openai-completions",
48
+ "apiKey": "ollama",
49
+ "compat": {
50
+ "supportsDeveloperRole": false,
51
+ "supportsReasoningEffort": false
52
+ },
53
+ "models": [
54
+ {
55
+ "id": "gpt-oss:20b",
56
+ "reasoning": true
57
+ }
58
+ ]
59
+ }
60
+ }
61
+ }
62
+ ```
63
+
38
64
  ## Full Example
39
65
 
40
66
  Override defaults when you need specific values:
@@ -129,13 +155,18 @@ The `apiKey` and `headers` fields support three formats:
129
155
  | Field | Required | Default | Description |
130
156
  |-------|----------|---------|-------------|
131
157
  | `id` | Yes | — | Model identifier (passed to the API) |
132
- | `name` | No | `id` | Display name in model selector |
158
+ | `name` | No | `id` | Human-readable model label. Used for matching (`--model` patterns) and shown in model details/status text. |
133
159
  | `api` | No | provider's `api` | Override provider's API for this model |
134
160
  | `reasoning` | No | `false` | Supports extended thinking |
135
161
  | `input` | No | `["text"]` | Input types: `["text"]` or `["text", "image"]` |
136
162
  | `contextWindow` | No | `128000` | Context window size in tokens |
137
163
  | `maxTokens` | No | `16384` | Maximum output tokens |
138
164
  | `cost` | No | all zeros | `{"input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0}` (per million tokens) |
165
+ | `compat` | No | provider `compat` | OpenAI compatibility overrides. Merged with provider-level `compat` when both are set. |
166
+
167
+ Current behavior:
168
+ - `/model` and `--list-models` list entries by model `id`.
169
+ - The configured `name` is used for model matching and detail/status text.
139
170
 
140
171
  ## Overriding Built-in Providers
141
172
 
@@ -207,7 +238,10 @@ Behavior notes:
207
238
 
208
239
  ## OpenAI Compatibility
209
240
 
210
- For providers with partial OpenAI compatibility, use the `compat` field:
241
+ For providers with partial OpenAI compatibility, use the `compat` field.
242
+
243
+ - Provider-level `compat` applies defaults to all models under that provider.
244
+ - Model-level `compat` overrides provider-level values for that model.
211
245
 
212
246
  ```json
213
247
  {
@@ -230,11 +264,19 @@ For providers with partial OpenAI compatibility, use the `compat` field:
230
264
  | `supportsStore` | Provider supports `store` field |
231
265
  | `supportsDeveloperRole` | Use `developer` vs `system` role |
232
266
  | `supportsReasoningEffort` | Support for `reasoning_effort` parameter |
267
+ | `reasoningEffortMap` | Map pi thinking levels to provider-specific `reasoning_effort` values |
233
268
  | `supportsUsageInStreaming` | Supports `stream_options: { include_usage: true }` (default: `true`) |
234
269
  | `maxTokensField` | Use `max_completion_tokens` or `max_tokens` |
270
+ | `requiresToolResultName` | Include `name` on tool result messages |
271
+ | `requiresAssistantAfterToolResult` | Insert an assistant message before a user message after tool results |
272
+ | `requiresThinkingAsText` | Convert thinking blocks to plain text |
273
+ | `thinkingFormat` | Use `reasoning_effort`, `zai`, `qwen`, or `qwen-chat-template` thinking parameters |
274
+ | `supportsStrictMode` | Include the `strict` field in tool definitions |
235
275
  | `openRouterRouting` | OpenRouter routing config passed to OpenRouter for model/provider selection |
236
276
  | `vercelGatewayRouting` | Vercel AI Gateway routing config for provider selection (`only`, `order`) |
237
277
 
278
+ `qwen` uses top-level `enable_thinking`. Use `qwen-chat-template` for local Qwen-compatible servers that require `chat_template_kwargs.enable_thinking`.
279
+
238
280
  Example:
239
281
 
240
282
  ```json
package/docs/packages.md CHANGED
@@ -54,6 +54,15 @@ npm:pkg
54
54
  - Versioned specs are pinned and skipped by `pi update`.
55
55
  - Global installs use `npm install -g`.
56
56
  - Project installs go under `.pi/npm/`.
57
+ - Set `npmCommand` in `settings.json` to pin npm package lookup and install operations to a specific wrapper command such as `mise` or `asdf`.
58
+
59
+ Example:
60
+
61
+ ```json
62
+ {
63
+ "npmCommand": ["mise", "exec", "node@20", "--", "npm"]
64
+ }
65
+ ```
57
66
 
58
67
  ### git
59
68
 
package/docs/providers.md CHANGED
@@ -65,6 +65,7 @@ pi
65
65
  | Vercel AI Gateway | `AI_GATEWAY_API_KEY` | `vercel-ai-gateway` |
66
66
  | ZAI | `ZAI_API_KEY` | `zai` |
67
67
  | OpenCode Zen | `OPENCODE_API_KEY` | `opencode` |
68
+ | OpenCode Go | `OPENCODE_API_KEY` | `opencode-go` |
68
69
  | Hugging Face | `HF_TOKEN` | `huggingface` |
69
70
  | Kimi For Coding | `KIMI_API_KEY` | `kimi-coding` |
70
71
  | MiniMax | `MINIMAX_API_KEY` | `minimax` |
@@ -81,7 +82,8 @@ Store credentials in `~/.pi/agent/auth.json`:
81
82
  "anthropic": { "type": "api_key", "key": "sk-ant-..." },
82
83
  "openai": { "type": "api_key", "key": "sk-..." },
83
84
  "google": { "type": "api_key", "key": "..." },
84
- "opencode": { "type": "api_key", "key": "..." }
85
+ "opencode": { "type": "api_key", "key": "..." },
86
+ "opencode-go": { "type": "api_key", "key": "..." }
85
87
  }
86
88
  ```
87
89
 
@@ -145,6 +147,13 @@ Also supports ECS task roles (`AWS_CONTAINER_CREDENTIALS_*`) and IRSA (`AWS_WEB_
145
147
  pi --provider amazon-bedrock --model us.anthropic.claude-sonnet-4-20250514-v1:0
146
148
  ```
147
149
 
150
+ Prompt caching is enabled automatically for Claude models whose ID contains a recognizable model name (base models and system-defined inference profiles). For application inference profiles (whose ARNs don't contain the model name), set `AWS_BEDROCK_FORCE_CACHE=1` to enable cache points:
151
+
152
+ ```bash
153
+ export AWS_BEDROCK_FORCE_CACHE=1
154
+ pi --provider amazon-bedrock --model arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/abc123
155
+ ```
156
+
148
157
  If you are connecting to a Bedrock API proxy, the following environment variables can be used:
149
158
 
150
159
  ```bash
package/docs/rpc.md CHANGED
@@ -24,6 +24,17 @@ Common options:
24
24
 
25
25
  All commands support an optional `id` field for request/response correlation. If provided, the corresponding response will include the same `id`.
26
26
 
27
+ ### Framing
28
+
29
+ RPC mode uses strict JSONL semantics with LF (`\n`) as the only record delimiter.
30
+
31
+ This matters for clients:
32
+ - Split records on `\n` only
33
+ - Accept optional `\r\n` input by stripping a trailing `\r`
34
+ - Do not use generic line readers that treat Unicode separators as newlines
35
+
36
+ In particular, Node `readline` is not protocol-compliant for RPC mode because it also splits on `U+2028` and `U+2029`, which are valid inside JSON strings.
37
+
27
38
  ## Commands
28
39
 
29
40
  ### Prompting
@@ -47,7 +58,7 @@ With images:
47
58
  {"type": "prompt", "message": "New instruction", "streamingBehavior": "steer"}
48
59
  ```
49
60
 
50
- - `"steer"`: Interrupt the agent mid-run. Message is delivered after current tool execution, remaining tools are skipped.
61
+ - `"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.
51
62
  - `"followUp"`: Wait until the agent finishes. Message is delivered only when agent stops.
52
63
 
53
64
  If the agent is streaming and no `streamingBehavior` is specified, the command returns an error.
@@ -65,7 +76,7 @@ The `images` field is optional. Each image uses `ImageContent` format: `{"type":
65
76
 
66
77
  #### steer
67
78
 
68
- Queue a steering message to interrupt the agent mid-run. Delivered after current tool execution, remaining tools are skipped. Skill commands and prompt templates are expanded. Extension commands are not allowed (use `prompt` instead).
79
+ Queue a steering message while the agent is running. It is delivered after the current assistant turn finishes executing its tool calls, before the next LLM call. Skill commands and prompt templates are expanded. Extension commands are not allowed (use `prompt` instead).
69
80
 
70
81
  ```json
71
82
  {"type": "steer", "message": "Stop and do this instead"}
@@ -310,8 +321,8 @@ Control how steering messages (from `steer`) are delivered.
310
321
  ```
311
322
 
312
323
  Modes:
313
- - `"all"`: Deliver all steering messages at the next interruption point
314
- - `"one-at-a-time"`: Deliver one steering message per interruption (default)
324
+ - `"all"`: Deliver all steering messages after the current assistant turn finishes executing its tool calls
325
+ - `"one-at-a-time"`: Deliver one steering message per completed assistant turn (default)
315
326
 
316
327
  Response:
317
328
  ```json
@@ -1292,13 +1303,39 @@ For a complete example of handling the extension UI protocol, see [`examples/rpc
1292
1303
 
1293
1304
  ```javascript
1294
1305
  const { spawn } = require("child_process");
1295
- const readline = require("readline");
1306
+ const { StringDecoder } = require("string_decoder");
1296
1307
 
1297
1308
  const agent = spawn("pi", ["--mode", "rpc", "--no-session"]);
1298
1309
 
1299
- readline.createInterface({ input: agent.stdout }).on("line", (line) => {
1310
+ function attachJsonlReader(stream, onLine) {
1311
+ const decoder = new StringDecoder("utf8");
1312
+ let buffer = "";
1313
+
1314
+ stream.on("data", (chunk) => {
1315
+ buffer += typeof chunk === "string" ? chunk : decoder.write(chunk);
1316
+
1317
+ while (true) {
1318
+ const newlineIndex = buffer.indexOf("\n");
1319
+ if (newlineIndex === -1) break;
1320
+
1321
+ let line = buffer.slice(0, newlineIndex);
1322
+ buffer = buffer.slice(newlineIndex + 1);
1323
+ if (line.endsWith("\r")) line = line.slice(0, -1);
1324
+ onLine(line);
1325
+ }
1326
+ });
1327
+
1328
+ stream.on("end", () => {
1329
+ buffer += decoder.end();
1330
+ if (buffer.length > 0) {
1331
+ onLine(buffer.endsWith("\r") ? buffer.slice(0, -1) : buffer);
1332
+ }
1333
+ });
1334
+ }
1335
+
1336
+ attachJsonlReader(agent.stdout, (line) => {
1300
1337
  const event = JSON.parse(line);
1301
-
1338
+
1302
1339
  if (event.type === "message_update") {
1303
1340
  const { assistantMessageEvent } = event;
1304
1341
  if (assistantMessageEvent.type === "text_delta") {
package/docs/sdk.md CHANGED
@@ -78,7 +78,7 @@ interface AgentSession {
78
78
  prompt(text: string, options?: PromptOptions): Promise<void>;
79
79
 
80
80
  // Queue messages during streaming
81
- steer(text: string): Promise<void>; // Interrupt: delivered after current tool, skips remaining
81
+ steer(text: string): Promise<void>; // Queue for delivery after the current assistant turn finishes its tool calls
82
82
  followUp(text: string): Promise<void>; // Wait: delivered only when agent finishes
83
83
 
84
84
  // Subscribe to events (returns unsubscribe function)
@@ -150,7 +150,7 @@ await session.prompt("After you're done, also check X", { streamingBehavior: "fo
150
150
  For explicit queueing during streaming:
151
151
 
152
152
  ```typescript
153
- // Interrupt the agent (delivered after current tool, skips remaining tools)
153
+ // Queue a steering message for delivery after the current assistant turn finishes its tool calls
154
154
  await session.steer("New instruction");
155
155
 
156
156
  // Wait for agent to finish (delivered only when agent stops)
package/docs/settings.md CHANGED
@@ -42,6 +42,7 @@ Edit directly or use `/settings` for common options.
42
42
  | `quietStartup` | boolean | `false` | Hide startup header |
43
43
  | `collapseChangelog` | boolean | `false` | Show condensed changelog after updates |
44
44
  | `doubleEscapeAction` | string | `"tree"` | Action for double-escape: `"tree"`, `"fork"`, or `"none"` |
45
+ | `treeFilterMode` | string | `"default"` | Default filter for `/tree`: `"default"`, `"no-tools"`, `"user-only"`, `"labeled-only"`, `"all"` |
45
46
  | `editorPaddingX` | number | `0` | Horizontal padding for input editor (0-3) |
46
47
  | `autocompleteMaxVisible` | number | `5` | Max visible items in autocomplete dropdown (3-20) |
47
48
  | `showHardwareCursor` | boolean | `false` | Show terminal cursor |
@@ -69,6 +70,7 @@ Edit directly or use `/settings` for common options.
69
70
  | Setting | Type | Default | Description |
70
71
  |---------|------|---------|-------------|
71
72
  | `branchSummary.reserveTokens` | number | `16384` | Tokens reserved for branch summarization |
73
+ | `branchSummary.skipPrompt` | boolean | `false` | Skip "Summarize branch?" prompt on `/tree` navigation (defaults to no summary) |
72
74
 
73
75
  ### Retry
74
76
 
@@ -115,6 +117,15 @@ When a provider requests a retry delay longer than `maxDelayMs` (e.g., Google's
115
117
  |---------|------|---------|-------------|
116
118
  | `shellPath` | string | - | Custom shell path (e.g., for Cygwin on Windows) |
117
119
  | `shellCommandPrefix` | string | - | Prefix for every bash command (e.g., `"shopt -s expand_aliases"`) |
120
+ | `npmCommand` | string[] | - | Command argv used for npm package lookup/install operations (e.g., `["mise", "exec", "node@20", "--", "npm"]`) |
121
+
122
+ ```json
123
+ {
124
+ "npmCommand": ["mise", "exec", "node@20", "--", "npm"]
125
+ }
126
+ ```
127
+
128
+ `npmCommand` is used for all npm package-manager operations, including `npm root -g`, installs, uninstalls, and `npm install` inside git packages. Use argv-style entries exactly as the process should be launched.
118
129
 
119
130
  ### Model Cycling
120
131