@astralyn/pi 0.84.8 → 0.84.10

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 (270) hide show
  1. package/CHANGELOG.md +17 -2
  2. package/README.md +3 -2
  3. package/dist/cli/args.d.ts +1 -0
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +29 -9
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/file-processor.d.ts.map +1 -1
  8. package/dist/cli/file-processor.js +2 -1
  9. package/dist/cli/file-processor.js.map +1 -1
  10. package/dist/config.d.ts +4 -3
  11. package/dist/config.d.ts.map +1 -1
  12. package/dist/config.js +22 -14
  13. package/dist/config.js.map +1 -1
  14. package/dist/core/agent-session.d.ts +26 -7
  15. package/dist/core/agent-session.d.ts.map +1 -1
  16. package/dist/core/agent-session.js +83 -64
  17. package/dist/core/agent-session.js.map +1 -1
  18. package/dist/core/auth-storage.d.ts.map +1 -1
  19. package/dist/core/auth-storage.js +6 -7
  20. package/dist/core/auth-storage.js.map +1 -1
  21. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  22. package/dist/core/compaction/branch-summarization.js +3 -0
  23. package/dist/core/compaction/branch-summarization.js.map +1 -1
  24. package/dist/core/compaction/compaction.d.ts +4 -3
  25. package/dist/core/compaction/compaction.d.ts.map +1 -1
  26. package/dist/core/compaction/compaction.js +41 -32
  27. package/dist/core/compaction/compaction.js.map +1 -1
  28. package/dist/core/compaction-controller.d.ts +2 -1
  29. package/dist/core/compaction-controller.d.ts.map +1 -1
  30. package/dist/core/compaction-controller.js +64 -21
  31. package/dist/core/compaction-controller.js.map +1 -1
  32. package/dist/core/defaults.d.ts +1 -0
  33. package/dist/core/defaults.d.ts.map +1 -1
  34. package/dist/core/defaults.js +9 -0
  35. package/dist/core/defaults.js.map +1 -1
  36. package/dist/core/extensions/index.d.ts +2 -2
  37. package/dist/core/extensions/index.d.ts.map +1 -1
  38. package/dist/core/extensions/index.js +1 -1
  39. package/dist/core/extensions/index.js.map +1 -1
  40. package/dist/core/extensions/loader.d.ts.map +1 -1
  41. package/dist/core/extensions/loader.js +115 -48
  42. package/dist/core/extensions/loader.js.map +1 -1
  43. package/dist/core/extensions/types.d.ts +38 -9
  44. package/dist/core/extensions/types.d.ts.map +1 -1
  45. package/dist/core/extensions/types.js +3 -0
  46. package/dist/core/extensions/types.js.map +1 -1
  47. package/dist/core/footer-data-provider.d.ts +1 -1
  48. package/dist/core/footer-data-provider.js +1 -1
  49. package/dist/core/footer-data-provider.js.map +1 -1
  50. package/dist/core/keybindings.d.ts +20 -19
  51. package/dist/core/keybindings.d.ts.map +1 -1
  52. package/dist/core/keybindings.js +26 -5
  53. package/dist/core/keybindings.js.map +1 -1
  54. package/dist/core/model-config.d.ts +5 -0
  55. package/dist/core/model-config.d.ts.map +1 -1
  56. package/dist/core/model-config.js +3 -1
  57. package/dist/core/model-config.js.map +1 -1
  58. package/dist/core/model-resolver.d.ts +1 -0
  59. package/dist/core/model-resolver.d.ts.map +1 -1
  60. package/dist/core/model-resolver.js +14 -8
  61. package/dist/core/model-resolver.js.map +1 -1
  62. package/dist/core/models-store.d.ts.map +1 -1
  63. package/dist/core/models-store.js +2 -1
  64. package/dist/core/models-store.js.map +1 -1
  65. package/dist/core/package-manager.d.ts.map +1 -1
  66. package/dist/core/package-manager.js +22 -14
  67. package/dist/core/package-manager.js.map +1 -1
  68. package/dist/core/pi-manifest.d.ts.map +1 -1
  69. package/dist/core/pi-manifest.js +2 -1
  70. package/dist/core/pi-manifest.js.map +1 -1
  71. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  72. package/dist/core/remote-catalog-provider.js +2 -1
  73. package/dist/core/remote-catalog-provider.js.map +1 -1
  74. package/dist/core/resource-loader.d.ts.map +1 -1
  75. package/dist/core/resource-loader.js +3 -2
  76. package/dist/core/resource-loader.js.map +1 -1
  77. package/dist/core/sdk.d.ts +2 -2
  78. package/dist/core/sdk.d.ts.map +1 -1
  79. package/dist/core/sdk.js +10 -3
  80. package/dist/core/sdk.js.map +1 -1
  81. package/dist/core/session-export.d.ts +4 -0
  82. package/dist/core/session-export.d.ts.map +1 -0
  83. package/dist/core/session-export.js +32 -0
  84. package/dist/core/session-export.js.map +1 -0
  85. package/dist/core/session-manager.d.ts.map +1 -1
  86. package/dist/core/session-manager.js +4 -3
  87. package/dist/core/session-manager.js.map +1 -1
  88. package/dist/core/settings-diagnostics.d.ts +9 -0
  89. package/dist/core/settings-diagnostics.d.ts.map +1 -0
  90. package/dist/core/settings-diagnostics.js +21 -0
  91. package/dist/core/settings-diagnostics.js.map +1 -0
  92. package/dist/core/settings-manager.d.ts +9 -0
  93. package/dist/core/settings-manager.d.ts.map +1 -1
  94. package/dist/core/settings-manager.js +51 -10
  95. package/dist/core/settings-manager.js.map +1 -1
  96. package/dist/core/skills.d.ts.map +1 -1
  97. package/dist/core/skills.js +51 -33
  98. package/dist/core/skills.js.map +1 -1
  99. package/dist/core/slash-commands.d.ts.map +1 -1
  100. package/dist/core/slash-commands.js +2 -1
  101. package/dist/core/slash-commands.js.map +1 -1
  102. package/dist/core/system-prompt.d.ts.map +1 -1
  103. package/dist/core/system-prompt.js +11 -2
  104. package/dist/core/system-prompt.js.map +1 -1
  105. package/dist/core/tools/bash.d.ts +19 -1
  106. package/dist/core/tools/bash.d.ts.map +1 -1
  107. package/dist/core/tools/bash.js +59 -37
  108. package/dist/core/tools/bash.js.map +1 -1
  109. package/dist/core/tools/edit-diff.d.ts +0 -5
  110. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  111. package/dist/core/tools/edit-diff.js +2 -5
  112. package/dist/core/tools/edit-diff.js.map +1 -1
  113. package/dist/core/tools/edit.d.ts.map +1 -1
  114. package/dist/core/tools/edit.js +20 -4
  115. package/dist/core/tools/edit.js.map +1 -1
  116. package/dist/core/tools/index.d.ts +4 -1
  117. package/dist/core/tools/index.d.ts.map +1 -1
  118. package/dist/core/tools/index.js +18 -1
  119. package/dist/core/tools/index.js.map +1 -1
  120. package/dist/core/tools/powershell.d.ts +16 -0
  121. package/dist/core/tools/powershell.d.ts.map +1 -0
  122. package/dist/core/tools/powershell.js +39 -0
  123. package/dist/core/tools/powershell.js.map +1 -0
  124. package/dist/core/trust-manager.d.ts.map +1 -1
  125. package/dist/core/trust-manager.js +2 -1
  126. package/dist/core/trust-manager.js.map +1 -1
  127. package/dist/extensions/background/registry.d.ts +2 -3
  128. package/dist/extensions/background/registry.d.ts.map +1 -1
  129. package/dist/extensions/background/registry.js +2 -6
  130. package/dist/extensions/background/registry.js.map +1 -1
  131. package/dist/extensions/llama/index.d.ts.map +1 -1
  132. package/dist/extensions/llama/index.js +2 -0
  133. package/dist/extensions/llama/index.js.map +1 -1
  134. package/dist/extensions/llama/provider.d.ts.map +1 -1
  135. package/dist/extensions/llama/provider.js +6 -2
  136. package/dist/extensions/llama/provider.js.map +1 -1
  137. package/dist/extensions/question/types.d.ts +0 -1
  138. package/dist/extensions/question/types.d.ts.map +1 -1
  139. package/dist/extensions/question/types.js +1 -1
  140. package/dist/extensions/question/types.js.map +1 -1
  141. package/dist/extensions/router/register.d.ts +0 -1
  142. package/dist/extensions/router/register.d.ts.map +1 -1
  143. package/dist/extensions/router/register.js +0 -3
  144. package/dist/extensions/router/register.js.map +1 -1
  145. package/dist/extensions/router/stream.d.ts +0 -2
  146. package/dist/extensions/router/stream.d.ts.map +1 -1
  147. package/dist/extensions/router/stream.js +1 -12
  148. package/dist/extensions/router/stream.js.map +1 -1
  149. package/dist/extensions/subagent/index.js +2 -2
  150. package/dist/extensions/subagent/index.js.map +1 -1
  151. package/dist/extensions/subagent/render.d.ts +6 -2
  152. package/dist/extensions/subagent/render.d.ts.map +1 -1
  153. package/dist/extensions/subagent/render.js +143 -132
  154. package/dist/extensions/subagent/render.js.map +1 -1
  155. package/dist/extensions/subagent/text.d.ts +0 -1
  156. package/dist/extensions/subagent/text.d.ts.map +1 -1
  157. package/dist/extensions/subagent/text.js +1 -30
  158. package/dist/extensions/subagent/text.js.map +1 -1
  159. package/dist/extensions/subagent/ui/model-list.d.ts +0 -3
  160. package/dist/extensions/subagent/ui/model-list.d.ts.map +1 -1
  161. package/dist/extensions/subagent/ui/model-list.js +1 -10
  162. package/dist/extensions/subagent/ui/model-list.js.map +1 -1
  163. package/dist/index.d.ts +5 -5
  164. package/dist/index.d.ts.map +1 -1
  165. package/dist/index.js +4 -4
  166. package/dist/index.js.map +1 -1
  167. package/dist/main.d.ts +4 -0
  168. package/dist/main.d.ts.map +1 -1
  169. package/dist/main.js +18 -15
  170. package/dist/main.js.map +1 -1
  171. package/dist/migrations.js +5 -5
  172. package/dist/migrations.js.map +1 -1
  173. package/dist/modes/interactive/components/index.d.ts +0 -1
  174. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  175. package/dist/modes/interactive/components/index.js +0 -1
  176. package/dist/modes/interactive/components/index.js.map +1 -1
  177. package/dist/modes/interactive/components/model-selector.d.ts +9 -3
  178. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  179. package/dist/modes/interactive/components/model-selector.js +54 -11
  180. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  181. package/dist/modes/interactive/components/settings-selector.d.ts +7 -2
  182. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  183. package/dist/modes/interactive/components/settings-selector.js +118 -55
  184. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  185. package/dist/modes/interactive/components/settings-submenu.d.ts +72 -0
  186. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -0
  187. package/dist/modes/interactive/components/settings-submenu.js +151 -0
  188. package/dist/modes/interactive/components/settings-submenu.js.map +1 -0
  189. package/dist/modes/interactive/components/thinking-selector.d.ts +15 -3
  190. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  191. package/dist/modes/interactive/components/thinking-selector.js +68 -17
  192. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  193. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  194. package/dist/modes/interactive/external-editor.js +2 -1
  195. package/dist/modes/interactive/external-editor.js.map +1 -1
  196. package/dist/modes/interactive/interactive-mode.d.ts +11 -0
  197. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  198. package/dist/modes/interactive/interactive-mode.js +167 -105
  199. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  200. package/dist/modes/interactive/session-share.d.ts +16 -0
  201. package/dist/modes/interactive/session-share.d.ts.map +1 -0
  202. package/dist/modes/interactive/session-share.js +188 -0
  203. package/dist/modes/interactive/session-share.js.map +1 -0
  204. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  205. package/dist/modes/interactive/theme/theme.js +3 -2
  206. package/dist/modes/interactive/theme/theme.js.map +1 -1
  207. package/dist/modes/json-event.d.ts +16 -13
  208. package/dist/modes/json-event.d.ts.map +1 -1
  209. package/dist/modes/json-event.js +20 -6
  210. package/dist/modes/json-event.js.map +1 -1
  211. package/dist/package-manager-cli.d.ts +1 -0
  212. package/dist/package-manager-cli.d.ts.map +1 -1
  213. package/dist/package-manager-cli.js +186 -2
  214. package/dist/package-manager-cli.js.map +1 -1
  215. package/dist/utils/frontmatter.d.ts.map +1 -1
  216. package/dist/utils/frontmatter.js +2 -1
  217. package/dist/utils/frontmatter.js.map +1 -1
  218. package/dist/utils/management-http.d.ts +5 -3
  219. package/dist/utils/management-http.d.ts.map +1 -1
  220. package/dist/utils/management-http.js +14 -10
  221. package/dist/utils/management-http.js.map +1 -1
  222. package/dist/utils/paths.d.ts +0 -5
  223. package/dist/utils/paths.d.ts.map +1 -1
  224. package/dist/utils/paths.js +0 -7
  225. package/dist/utils/paths.js.map +1 -1
  226. package/dist/utils/shell.d.ts +3 -0
  227. package/dist/utils/shell.d.ts.map +1 -1
  228. package/dist/utils/shell.js +17 -5
  229. package/dist/utils/shell.js.map +1 -1
  230. package/dist/utils/text.d.ts +8 -0
  231. package/dist/utils/text.d.ts.map +1 -0
  232. package/dist/utils/text.js +9 -0
  233. package/dist/utils/text.js.map +1 -0
  234. package/docs/bundled/extensions/subagent.md +40 -23
  235. package/docs/compaction.md +19 -2
  236. package/docs/custom-provider.md +5 -2
  237. package/docs/environment-variables.md +8 -8
  238. package/docs/extensions.md +22 -10
  239. package/docs/json.md +7 -2
  240. package/docs/keybindings.md +10 -8
  241. package/docs/llama-cpp.md +6 -4
  242. package/docs/models.md +10 -3
  243. package/docs/packages.md +2 -1
  244. package/docs/rpc.md +9 -3
  245. package/docs/sdk.md +12 -2
  246. package/docs/settings.md +16 -5
  247. package/docs/skills.md +5 -4
  248. package/docs/terminal-setup.md +11 -9
  249. package/docs/usage.md +6 -2
  250. package/docs/windows.md +24 -2
  251. package/examples/extensions/border-status-editor.ts +1 -1
  252. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  253. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  254. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  255. package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
  256. package/examples/extensions/doom-overlay/doom/build.sh +0 -0
  257. package/examples/extensions/git-checkpoint.ts +2 -2
  258. package/examples/extensions/gondolin/package-lock.json +2 -2
  259. package/examples/extensions/gondolin/package.json +1 -1
  260. package/examples/extensions/notify.ts +3 -1
  261. package/examples/extensions/sandbox/package-lock.json +2 -2
  262. package/examples/extensions/sandbox/package.json +1 -1
  263. package/examples/extensions/titlebar-spinner.ts +1 -1
  264. package/examples/extensions/with-deps/package-lock.json +2 -2
  265. package/examples/extensions/with-deps/package.json +1 -1
  266. package/examples/rpc-extension-ui.ts +1 -1
  267. package/examples/sdk/06-extensions.ts +1 -1
  268. package/examples/sdk/README.md +1 -1
  269. package/npm-shrinkwrap.json +196 -257
  270. package/package.json +6 -8
@@ -332,7 +332,8 @@ user sends another prompt ◄─────────────────
332
332
 
333
333
  /compact or auto-compaction
334
334
  ├─► session_before_compact (can cancel or customize)
335
- └─► session_compact
335
+ ├─► session_compact (success)
336
+ └─► session_compact_failed (failure or abort)
336
337
 
337
338
  /tree navigation
338
339
  ├─► session_before_tree (can cancel or customize)
@@ -450,7 +451,7 @@ pi.on("session_before_fork", async (event, ctx) => {
450
451
  After a successful fork or clone, pi emits `session_shutdown` for the old extension instance, reloads and rebinds extensions for the new session, then emits `session_start` with `reason: "fork"` and `previousSessionFile`.
451
452
  Do cleanup work in `session_shutdown`, then reestablish any in-memory state in `session_start`.
452
453
 
453
- #### session_before_compact / session_compact
454
+ #### session_before_compact / session_compact / session_compact_failed
454
455
 
455
456
  Fired on compaction. See [compaction.md](compaction.md) for details.
456
457
 
@@ -483,6 +484,14 @@ pi.on("session_compact", async (event, ctx) => {
483
484
  // event.reason - "manual" (/compact), "threshold", or "overflow"
484
485
  // event.willRetry - whether overflow recovery will actually retry after retained-context verification
485
486
  });
487
+
488
+ pi.on("session_compact_failed", async (event, ctx) => {
489
+ // event.reason - "manual" (/compact), "threshold", or "overflow"
490
+ // event.errorMessage - present for non-abort failures
491
+ // event.aborted - true for cancelled/aborted compactions
492
+ // event.willRetry - whether the aborted turn would have retried after compaction
493
+ // event.fromExtension - whether extension-provided compaction content was being used
494
+ });
486
495
  ```
487
496
 
488
497
  #### session_before_tree / session_tree
@@ -842,7 +851,7 @@ In parallel tool mode, `tool_result` and `tool_execution_end` may interleave in
842
851
  Use `ctx.signal` for nested async work inside the handler. This lets Esc cancel model calls, `fetch()`, and other abort-aware operations started by the extension.
843
852
 
844
853
  ```typescript
845
- import { isBashToolResult } from "@astralyn/pi";
854
+ import { isBashToolResult, isPowerShellToolResult } from "@astralyn/pi";
846
855
 
847
856
  pi.on("tool_result", async (event, ctx) => {
848
857
  // event.toolName, event.toolCallId, event.input
@@ -851,6 +860,9 @@ pi.on("tool_result", async (event, ctx) => {
851
860
  if (isBashToolResult(event)) {
852
861
  // event.details is typed as BashToolDetails
853
862
  }
863
+ if (isPowerShellToolResult(event)) {
864
+ // event.details is typed as PowerShellToolDetails
865
+ }
854
866
 
855
867
  const response = await fetch("https://example.com/summarize", {
856
868
  method: "POST",
@@ -2110,7 +2122,7 @@ pi.registerTool({
2110
2122
 
2111
2123
  ### Overriding Built-in Tools
2112
2124
 
2113
- Extensions can override built-in tools (`read`, `bash`, `edit`, `write`, `grep`, `find`, `ls`) by registering a tool with the same name. Interactive mode displays a warning when this happens.
2125
+ Extensions can override built-in tools (`read`, `bash`, `powershell`, `edit`, `write`, `grep`, `find`, `ls`) by registering a tool with the same name. Interactive mode displays a warning when this happens.
2114
2126
 
2115
2127
  ```bash
2116
2128
  # Extension's read tool replaces built-in read
@@ -2129,7 +2141,7 @@ See [examples/extensions/tool-override.ts](../examples/extensions/tool-override.
2129
2141
 
2130
2142
  **Prompt metadata:** `promptSnippet` and `promptGuidelines` are not inherited from the built-in tool. If your override should keep those prompt instructions, define them on the override explicitly.
2131
2143
 
2132
- **Your implementation must match the exact result shape**, including the `details` type. The UI and session logic depend on these shapes for rendering and state tracking. The built-in detail types available from `@astralyn/pi` are `ReadToolDetails`, `BashToolDetails`, `EditToolDetails`, `GrepToolDetails`, `FindToolDetails`, and `LsToolDetails`.
2144
+ **Your implementation must match the exact result shape**, including the `details` type. The UI and session logic depend on these shapes for rendering and state tracking. The built-in detail types available from `@astralyn/pi` are `ReadToolDetails`, `BashToolDetails`, `PowerShellToolDetails`, `EditToolDetails`, `GrepToolDetails`, `FindToolDetails`, and `LsToolDetails`.
2133
2145
 
2134
2146
  ### Remote Execution
2135
2147
 
@@ -2160,11 +2172,11 @@ pi.registerTool({
2160
2172
  });
2161
2173
  ```
2162
2174
 
2163
- **Operations interfaces:** `ReadOperations`, `WriteOperations`, `EditOperations`, `BashOperations`, `LsOperations`, `GrepOperations`, `FindOperations`
2175
+ **Operations interfaces:** `ReadOperations`, `WriteOperations`, `EditOperations`, `BashOperations`, `PowerShellOperations`, `LsOperations`, `GrepOperations`, `FindOperations`
2164
2176
 
2165
- 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.
2177
+ 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. PowerShell-backed tools can use `createLocalPowerShellOperations()` with `PowerShellOperations`, `PowerShellSpawnContext`, and `PowerShellSpawnHook`.
2166
2178
 
2167
- The bash tool also supports a spawn hook to adjust the command, cwd, or env before execution:
2179
+ The `bash` and `powershell` tools also support a spawn hook to adjust the command, cwd, or env before execution:
2168
2180
 
2169
2181
  ```typescript
2170
2182
  import { createBashTool } from "@astralyn/pi";
@@ -2178,7 +2190,7 @@ const bashTool = createBashTool(cwd, {
2178
2190
  });
2179
2191
  ```
2180
2192
 
2181
- `createBashTool()` exposes the current session to commands through `PI_SESSION_ID`, `PI_SESSION_FILE`, `PI_PROVIDER`, `PI_MODEL`, and `PI_REASONING_LEVEL`. Injection happens before `spawnHook`, so hooks receive these values in `env` and preserve them when they spread the existing environment as above. Set `exposeSessionEnvironment: false` to disable them:
2193
+ `createBashTool()` and `createPowerShellTool()` expose the current session to commands through `PI_SESSION_ID`, `PI_SESSION_FILE`, `PI_PROVIDER`, `PI_MODEL`, and `PI_REASONING_LEVEL`. Injection happens before `spawnHook`, so hooks receive these values in `env` and preserve them when they spread the existing environment as above. Set `exposeSessionEnvironment: false` to disable them:
2182
2194
 
2183
2195
  ```typescript
2184
2196
  const bashTool = createBashTool(cwd, {
@@ -2186,7 +2198,7 @@ const bashTool = createBashTool(cwd, {
2186
2198
  });
2187
2199
  ```
2188
2200
 
2189
- See [Bash tool session environment](environment-variables.md#bash-tool-session-environment) for variable semantics. See [examples/extensions/ssh.ts](../examples/extensions/ssh.ts) for a complete SSH example with `--ssh` flag.
2201
+ See [Shell tool session environment](environment-variables.md#shell-tool-session-environment) for variable semantics. See [examples/extensions/ssh.ts](../examples/extensions/ssh.ts) for a complete SSH example with `--ssh` flag.
2190
2202
 
2191
2203
  ### Output Truncation
2192
2204
 
package/docs/json.md CHANGED
@@ -13,12 +13,16 @@ Wire events use `JsonAgentSessionEvent`, exported from [`@astralyn/pi`](https://
13
13
  ```typescript
14
14
  type WithoutPartial<T> = T extends { partial: unknown } ? Omit<T, "partial"> : T;
15
15
 
16
+ type JsonAssistantMessageEvent<T> = T extends { type: "toolcall_start"; partial: unknown }
17
+ ? WithoutPartial<T> & { id: string; toolName: string }
18
+ : WithoutPartial<T>;
19
+
16
20
  type JsonAgentSessionEvent =
17
21
  | Exclude<AgentSessionEvent, { type: "message_update" }>
18
22
  | {
19
23
  type: "message_update";
20
24
  usage: Usage;
21
- assistantMessageEvent: WithoutPartial<AssistantMessageEvent>;
25
+ assistantMessageEvent: JsonAssistantMessageEvent<AssistantMessageEvent>;
22
26
  };
23
27
  ```
24
28
 
@@ -104,7 +108,8 @@ Followed by events as they occur:
104
108
  `assistantMessageEvent.partial` to keep stream size linear. The top-level `usage` field contains
105
109
  the latest cumulative provider-reported usage and may remain zero when a provider only reports
106
110
  usage at completion. Use `contentIndex` and `delta` to assemble live text, thinking, or tool-call
107
- arguments if needed. `message_end` contains the final authoritative message.
111
+ arguments if needed. A `toolcall_start` event also includes the constant-sized `id` and `toolName`
112
+ fields. `message_end` contains the final authoritative message.
108
113
 
109
114
  ## Example
110
115
 
@@ -70,7 +70,7 @@ The dedicated history actions always change history entries, regardless of the c
70
70
  |--------|---------|-------------|
71
71
  | `tui.editor.yank` | `ctrl+y` | Paste most recently deleted text |
72
72
  | `tui.editor.yankPop` | `alt+y` | Cycle through deleted text after yank |
73
- | `tui.editor.undo` | `ctrl+-` | Undo last edit |
73
+ | `tui.editor.undo` | `ctrl+-` (`ctrl+z` on Windows; `alt+z` on WSL) | Undo last edit |
74
74
 
75
75
  ### TUI Clipboard and Selection
76
76
 
@@ -107,9 +107,9 @@ This routing remains configurable through the ordinary action bindings. For exam
107
107
  | `tui.altScreen.halfPageDown` | *(none)* | Scroll the transcript down by half a page |
108
108
  | `tui.altScreen.lineUp` | *(none)* | Scroll the transcript up by one line |
109
109
  | `tui.altScreen.lineDown` | *(none)* | Scroll the transcript down by one line |
110
- | `tui.altScreen.previousPrompt` | `ctrl+shift+up` | Jump to the previous marked message |
111
- | `tui.altScreen.nextPrompt` | `ctrl+shift+down` | Jump to the next marked message |
112
- | `tui.altScreen.search` | `ctrl+shift+f` | Search the rendered transcript |
110
+ | `tui.altScreen.previousPrompt` | `ctrl+shift+up`, `ctrl+up` (`ctrl+up` only on Windows and WSL) | Jump to the previous marked message |
111
+ | `tui.altScreen.nextPrompt` | `ctrl+shift+down`, `ctrl+down` (`ctrl+down` only on Windows and WSL) | Jump to the next marked message |
112
+ | `tui.altScreen.search` | `ctrl+shift+f` (`ctrl+f` on Windows and WSL) | Search the rendered transcript |
113
113
  | `tui.altScreen.searchNext` | `enter`, `ctrl+g` | Select the next search match while searching |
114
114
  | `tui.altScreen.searchPrevious` | `shift+enter`, `ctrl+shift+g` | Select the previous search match while searching |
115
115
  | `tui.altScreen.searchClose` | `escape` | Close transcript search |
@@ -125,7 +125,7 @@ This routing remains configurable through the ordinary action bindings. For exam
125
125
  | `app.exit` | `ctrl+d` | Exit (when editor empty) |
126
126
  | `app.suspend` | `ctrl+z` (none on Windows) | Suspend to background |
127
127
  | `app.editor.external` | `ctrl+g` | Open in external editor (`externalEditor`, `$VISUAL`, `$EDITOR`, Notepad on Windows, or `nano` elsewhere) |
128
- | `app.clipboard.pasteImage` | `ctrl+v` (`alt+v` on Windows) | Paste image or text from clipboard |
128
+ | `app.clipboard.pasteImage` | `ctrl+v` (`alt+v` on Windows and WSL) | Paste image or text from clipboard |
129
129
  | `app.backgroundTasks.kill` | `k` | Stop the selected task in the Background task menu |
130
130
 
131
131
  ### Sessions
@@ -149,18 +149,20 @@ This routing remains configurable through the ordinary action bindings. For exam
149
149
  |--------|---------|-------------|
150
150
  | `app.model.select` | `ctrl+l` | Open model selector |
151
151
  | `app.model.cycleForward` | `ctrl+p` | Cycle to next model |
152
- | `app.model.cycleBackward` | `shift+ctrl+p` | Cycle to previous model |
152
+ | `app.model.cycleBackward` | `shift+ctrl+p` (`alt+p` on Windows and WSL) | Cycle to previous model |
153
153
  | `app.thinking.cycle` | `shift+tab` | Cycle thinking level |
154
154
  | `app.thinking.toggle` | `ctrl+t` | Collapse or expand thinking blocks |
155
155
 
156
+ `/model` and `/thinking` open searchable selectors. Press Enter to change the current session without changing defaults. Press Ctrl+S in `/model` to select the highlighted model and save it as the global default; press Ctrl+S in `/thinking` to select the level and save it as the default for the current provider/model. Default entries are labeled and can be found by searching for `default`. Per-model thinking defaults can also be managed in `/settings`.
157
+
156
158
  ### Display and Message Queue
157
159
 
158
160
  | Keybinding id | Default | Description |
159
161
  |--------|---------|-------------|
160
162
  | `app.tools.expand` | `ctrl+o` | Collapse or expand tool output |
161
163
  | `app.message.copy` | `ctrl+x` | Copy the last assistant message, or the selected message in `/tree` |
162
- | `app.message.followUp` | `alt+enter` | Queue follow-up message |
163
- | `app.message.dequeue` | `alt+up` | Restore queued messages to editor |
164
+ | `app.message.followUp` | `alt+enter` (`ctrl+q` on Windows and WSL) | Queue follow-up message |
165
+ | `app.message.dequeue` | `alt+up` (`alt+q` on Windows and WSL) | Restore queued messages to editor |
164
166
 
165
167
  ### Tree Navigation
166
168
 
package/docs/llama-cpp.md CHANGED
@@ -53,6 +53,8 @@ Start Pi and configure the provider:
53
53
 
54
54
  Enter the router URL and optional API key. The default URL is `http://127.0.0.1:8080`.
55
55
 
56
+ If you start the router with `--no-models-autoload`, `/login llama.cpp` only stores the connection. Run `/llama` to load a model, then `/model` to select the loaded model for the current session.
57
+
56
58
  Environment variables can configure the same values without `/login`:
57
59
 
58
60
  ```bash
@@ -71,8 +73,8 @@ Run:
71
73
  /llama
72
74
  ```
73
75
 
74
- - Select an unloaded model to load it.
75
- - Select a loaded model to unload it.
76
+ - Select an unloaded model to load it. Pi shows router progress and waits for the model to reach the loaded state before refreshing the catalog.
77
+ - Select a loaded or idle-sleeping model to unload it.
76
78
  - Select **Download model…**, search Hugging Face, then choose a repository and quantization. Exact `owner/repository[:quant]` values also work.
77
79
  - Press Escape during a load or download to confirm cancellation.
78
80
 
@@ -80,7 +82,7 @@ Hugging Face search uses `HF_TOKEN` when set, then checks `$HF_TOKEN_PATH`, `$HF
80
82
 
81
83
  If other models are loaded, Pi asks whether to unload them first or keep them loaded. Pi does not silently unload models and never deletes model files. The router may be shared with other clients, so `/llama` always displays the router's current state.
82
84
 
83
- Only loaded models appear in `/model`. After loading a model, run `/model` to select it for the current Pi session.
85
+ Loaded models and models the router has put into its idle `sleeping` state appear in `/model`; selecting a sleeping model lets the router wake it for inference. Models that are unloaded or still loading do not appear. After loading a model, run `/model` to select it for the current Pi session.
84
86
 
85
87
  If the router disconnects, `/llama` shows **Retry** and **Close**. Retry reconnects and refreshes model state without replaying the interrupted operation.
86
88
 
@@ -94,6 +96,6 @@ curl http://127.0.0.1:8080/models
94
96
  ```
95
97
 
96
98
  - **No models in `/llama`:** Check `--models-dir`, the directory layout, and restart the router.
97
- - **Model missing from `/model`:** Load it with `/llama` first.
99
+ - **Model missing from `/model`:** Load it with `/llama` first and wait for loading to finish. Idle-sleeping models remain selectable.
98
100
  - **Load fails or uses too much memory:** Lower `-c` or unload another model.
99
101
  - **Server is not in router mode:** Start it without `--model`, `-m`, or `-hf`.
package/docs/models.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Use `~/.pi/agent/models.json` to add static providers and models, such as Ollama, vLLM, LM Studio, and compatible proxies. For a provider that needs OAuth, dynamic discovery, request rewriting, or a protocol Pi AI does not implement, use an [extension](custom-provider.md) instead.
4
4
 
5
- Pi reads this file at startup and on a model refresh, including when you open `/model`; restart is not required. It is a configuration overlay, not a discovered catalog stored in `models-store.json`.
5
+ Pi reads this file at startup and on a model refresh, including when you open `/model`; restart is not required. It accepts a leading UTF-8 byte-order mark (BOM). It is a configuration overlay, not a discovered catalog stored in `models-store.json`.
6
6
 
7
7
  ## Table of Contents
8
8
 
@@ -290,6 +290,9 @@ When `cost` is supplied on a `models` entry, it must contain all four base rates
290
290
  ```
291
291
 
292
292
  Only OpenAI-compatible APIs apply it (`openai-completions`, `openai-responses`, `azure-openai-responses`); other APIs ignore it. Keys override pi's named request fields (for example a `temperature` key here beats the request-level temperature), so prefer it as the single source of sampling truth for a model. In `modelOverrides`, `samplingParams` merges per key with the base model's value.
293
+
294
+ A constant thinking-token cap can go here too, but it will not follow `thinkingBudgets` or leave room for the answer. Prefer `compat.thinkingTokenBudgetField` (or the `supportsThinkingTokenBudget` alias) for that.
295
+
293
296
  ### Thinking Level Map
294
297
 
295
298
  `thinkingLevelMap` uses these Pi levels: `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`. It only affects a model with `reasoning: true`; a non-reasoning model exposes `off` only.
@@ -473,8 +476,10 @@ For `api: "openai-completions"`, Pi auto-detects many defaults from the provider
473
476
  | `requiresThinkingAsText` | Replays thinking blocks as text delimited by `<thinking>`. Default: URL-detected. |
474
477
  | `requiresReasoningContentOnAssistantMessages` | Includes empty `reasoning_content` on replayed assistant messages when reasoning is enabled. Default: URL-detected. |
475
478
  | `thinkingFormat` | One of `openai`, `openrouter`, `deepseek`, `together`, `zai`, `qwen`, `chat-template`, `qwen-chat-template`, `string-thinking`, or `ant-ling`. Default: `openai` unless URL detection selects a known provider format. |
476
- | `chatTemplateKwargs` | `chat_template_kwargs` for `thinkingFormat: "chat-template"`. Values may be strings, numbers, booleans, `null`, or `{ "$var": "thinking.enabled" | "thinking.effort", "omitWhenOff"?: true }`. |
477
- | `chatTemplateArgs` | `chat_template_args` for `thinkingFormat: "baseten"`. Values may be strings, numbers, booleans, `null`, or `{ "$var": "thinking.enabled" | "thinking.effort", "omitWhenOff"?: true }`. |
479
+ | `chatTemplateKwargs` | `chat_template_kwargs` for `thinkingFormat: "chat-template"`. Values may be strings, numbers, booleans, `null`, or `{ "$var": "thinking.enabled" | "thinking.effort" | "thinking.budget", "omitWhenOff"?: true }`. |
480
+ | `chatTemplateArgs` | `chat_template_args` for `thinkingFormat: "baseten"`. Values may be strings, numbers, booleans, `null`, or `{ "$var": "thinking.enabled" | "thinking.effort" | "thinking.budget", "omitWhenOff"?: true }`. |
481
+ | `thinkingTokenBudgetField` | Top-level request field used to cap reasoning tokens from `thinkingBudgets`, clamped so at least 1024 tokens remain for the answer. Use `thinking_token_budget` for vLLM, `thinking_budget` for Qwen/DashScope/SGLang, or `thinking_budget_tokens` for llama.cpp. Off by default. |
482
+ | `supportsThinkingTokenBudget` | Alias for `thinkingTokenBudgetField: "thinking_token_budget"` (vLLM). Prefer `thinkingTokenBudgetField`. Default: `false`. |
478
483
  | `zaiToolStream` | Sends top-level `tool_stream: true` when tools are present. Default: `false`; use only for Z.AI-compatible endpoints that require it. |
479
484
  | `cacheControlFormat` | `anthropic` applies Anthropic-style `cache_control` markers to the system prompt, last tool definition, and final text content when caching is enabled. |
480
485
  | `sendSessionAffinityHeaders` | Sends session-affinity headers from the session ID when caching is enabled. Default: `false`. |
@@ -488,6 +493,8 @@ For `api: "openai-completions"`, Pi auto-detects many defaults from the provider
488
493
 
489
494
  Thinking formats use these request shapes: `openai` sends `reasoning_effort`; `openrouter` sends `reasoning: { effort }`; `deepseek` sends `thinking: { type }` and, when enabled, `reasoning_effort`; `together` sends `reasoning: { enabled }` and optionally `reasoning_effort`; `zai` sends `thinking: { type }`; `qwen` sends `enable_thinking`; `qwen-chat-template` sends `chat_template_kwargs.enable_thinking` and `preserve_thinking`; `string-thinking` sends top-level `thinking` as a string; and `ant-ling` sends `reasoning: { effort }` only for a non-null mapped effort. `chat-template` sends the configured `chatTemplateKwargs`.
490
495
 
496
+ `thinkingTokenBudgetField` is independent of `thinkingFormat`. Do not enable it on the generated Qwen catalog: those models already send `reasoning_effort`, and DashScope rejects `thinking_budget` together with `reasoning_effort`.
497
+
491
498
  Use `qwen-chat-template` for local Qwen-compatible servers that need its fixed chat-template kwargs. Use `chat-template` for vLLM or Hugging Face templates that need custom kwargs, for example:
492
499
 
493
500
  ```json
package/docs/packages.md CHANGED
@@ -61,6 +61,7 @@ npm:pkg
61
61
  ```
62
62
 
63
63
  - Versioned specs are pinned and skipped by package updates (`pi update --extensions`, `pi update --all`).
64
+ - Update checks only offer a registry version newer than the installed version; Pi does not downgrade a package when the registry reports an older version.
64
65
  - User installs go under `~/.pi/agent/npm/`.
65
66
  - Project installs go under `.pi/npm/`.
66
67
  - Set `npmCommand` in `settings.json` to pin npm package lookup and install operations to a specific wrapper command such as `mise` or `asdf`.
@@ -130,7 +131,7 @@ Add a `pi` manifest to `package.json` or use conventional directories. Include t
130
131
  }
131
132
  ```
132
133
 
133
- Paths are relative to the package root. Arrays support glob patterns and `!exclusions`.
134
+ Paths are relative to the package root. Arrays support glob patterns and `!exclusions`. Positive manifest globs discover visible paths in lexical order. List dot-prefixed paths directly. If a glob would need to continue through a symlink, list the symlinked resource root directly.
134
135
 
135
136
  ### Gallery Metadata
136
137
 
package/docs/rpc.md CHANGED
@@ -980,7 +980,7 @@ The `assistantMessageEvent` field contains one of these delta types:
980
980
  | `thinking_start` | Thinking block started |
981
981
  | `thinking_delta` | Thinking content chunk |
982
982
  | `thinking_end` | Thinking block ended |
983
- | `toolcall_start` | Tool call started |
983
+ | `toolcall_start` | Tool call started (includes `id` and `toolName`) |
984
984
  | `toolcall_delta` | Tool call arguments chunk |
985
985
  | `toolcall_end` | Tool call ended (includes full `toolCall` object) |
986
986
 
@@ -995,11 +995,17 @@ Example streaming a text response:
995
995
  The top-level `usage` field contains the latest cumulative provider-reported usage. It may remain
996
996
  zero until completion when a provider does not report usage during streaming.
997
997
 
998
+ Example starting a tool call:
999
+ ```json
1000
+ {"type":"message_update","usage":{...},"assistantMessageEvent":{"type":"toolcall_start","contentIndex":1,"id":"call_abc123","toolName":"write"}}
1001
+ ```
1002
+
998
1003
  `message_update` intentionally omits the former cumulative `message` field and
999
1004
  `assistantMessageEvent.partial`. Clients that need a live partial message must assemble it
1000
1005
  from `message_start` and subsequent events using `contentIndex`. Treat `message_end.message`
1001
- as authoritative. For tool calls, buffer `toolcall_delta.delta`; `toolcall_end.toolCall`
1002
- contains the completed call.
1006
+ as authoritative. For tool calls, `toolcall_start` provides the call `id` and `toolName`;
1007
+ buffer `toolcall_delta.delta` for arguments. `toolcall_end.toolCall` contains the completed
1008
+ call.
1003
1009
 
1004
1010
  ### bash_execution_update
1005
1011
 
package/docs/sdk.md CHANGED
@@ -558,7 +558,7 @@ const { session } = await createAgentSession({ resourceLoader: loader });
558
558
 
559
559
  Specify which built-in tools to enable:
560
560
 
561
- - Built-in tool names: `read`, `bash`, `edit`, `write`, `grep`, `find`, `ls`
561
+ - Built-in tool names: `read`, `bash`, `powershell`, `edit`, `write`, `grep`, `find`, `ls`
562
562
  - Default built-ins: `read`, `bash`, `edit`, `write`
563
563
  - `noTools: "all"` disables all tools
564
564
  - `noTools: "builtin"` disables default built-ins while keeping extension and custom tools enabled
@@ -579,6 +579,11 @@ const { session: selectedToolsSession } = await createAgentSession({
579
579
  tools: ["read", "bash", "grep"],
580
580
  });
581
581
 
582
+ // Use PowerShell instead of Bash on Windows
583
+ const { session } = await createAgentSession({
584
+ tools: ["read", "powershell", "edit", "write"],
585
+ });
586
+
582
587
  // Disable one tool while keeping the rest available
583
588
  const { session: excludedToolsSession } = await createAgentSession({
584
589
  excludeTools: ["ask_question"],
@@ -1165,8 +1170,13 @@ SettingsManager
1165
1170
  // Tool factories
1166
1171
  createCodingTools
1167
1172
  createReadOnlyTools
1168
- createReadTool, createBashTool, createEditTool, createWriteTool
1173
+ createReadTool, createBashTool, createPowerShellTool, createEditTool, createWriteTool
1169
1174
  createGrepTool, createFindTool, createLsTool
1175
+ createPowerShellToolDefinition, createLocalPowerShellOperations, getPowerShellConfig
1176
+
1177
+ // PowerShell types
1178
+ PowerShellOperations, PowerShellSpawnContext, PowerShellSpawnHook
1179
+ PowerShellToolCallEvent, PowerShellToolDetails, PowerShellToolInput, PowerShellToolOptions
1170
1180
 
1171
1181
  // Types
1172
1182
  type CreateAgentSessionOptions
package/docs/settings.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Settings
2
2
 
3
- Pi uses JSON settings files with project settings overriding global settings.
3
+ Pi uses JSON settings files with project settings overriding global settings. JSON configuration files may begin with a UTF-8 byte-order mark (BOM); Pi strips it while reading and writes normalized BOM-free JSON after a setting changes.
4
4
 
5
5
  | Location | Scope |
6
6
  |----------|-------|
@@ -29,10 +29,13 @@ Use `/trust` in interactive mode to save a project trust decision for future ses
29
29
  |---------|------|---------|-------------|
30
30
  | `defaultProvider` | string | - | Default provider (e.g., `"anthropic"`, `"openai"`) |
31
31
  | `defaultModel` | string | - | Default model ID |
32
- | `defaultThinkingLevel` | string | - | `"off"`, `"minimal"`, `"low"`, `"medium"`, `"high"`, `"xhigh"`, `"max"` |
32
+ | `defaultThinkingLevel` | string | - | Global fallback: `"off"`, `"minimal"`, `"low"`, `"medium"`, `"high"`, `"xhigh"`, or `"max"` |
33
+ | `modelThinkingLevels` | object | - | Per-model default thinking levels keyed by `provider/modelId`; set through `/thinking` Ctrl+S or `/settings` |
33
34
  | `hideThinkingBlock` | boolean | `false` | Hide thinking blocks in output |
34
- | `showCacheMissNotices` | boolean | `false` | Show transcript notices for significant prompt-cache misses |
35
- | `thinkingBudgets` | object | - | Custom token budgets per thinking level |
35
+ | `showCacheMissNotices` | boolean | `false` | Show transcript notices for significant prompt-cache misses and compaction or branch-summary usage |
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
+
38
+ Selecting a model or thinking level with Enter changes only the current session. Ctrl+S in `/model` saves `defaultProvider` and `defaultModel`; Ctrl+S in `/thinking` saves the level under `modelThinkingLevels` for the active model. A per-model value takes precedence over `defaultThinkingLevel`.
36
39
 
37
40
  #### thinkingBudgets
38
41
 
@@ -220,7 +223,7 @@ Windows paths in JSON must use forward slashes or escaped backslashes:
220
223
  |---------|------|---------|-------------|
221
224
  | `defaultTools` | string[] | - | Built-in tools enabled initially. When omitted, Pi uses its standard defaults |
222
225
 
223
- `defaultTools` selects the built-in tools enabled at startup. Extension and SDK custom tools remain enabled:
226
+ `defaultTools` selects the built-in tools enabled at startup. Extension and SDK custom tools remain enabled. Available built-ins are `read`, `bash`, `powershell`, `edit`, `write`, `grep`, `find`, and `ls`:
224
227
 
225
228
  ```json
226
229
  {
@@ -228,6 +231,14 @@ Windows paths in JSON must use forward slashes or escaped backslashes:
228
231
  }
229
232
  ```
230
233
 
234
+ On Windows, select `powershell` instead of `bash`, or include both:
235
+
236
+ ```json
237
+ {
238
+ "defaultTools": ["read", "powershell", "edit", "write"]
239
+ }
240
+ ```
241
+
231
242
  An empty array starts with no built-in tools while preserving extension and SDK custom tools. `--tools` replaces this behavior with a strict allowlist for all tools, `--no-tools` disables all tools, and `--no-builtin-tools` disables the built-in defaults. `--exclude-tools` filters the resulting list. A project `defaultTools` array replaces the global array.
232
243
 
233
244
  ### Sessions
package/docs/skills.md CHANGED
@@ -34,9 +34,10 @@ Pi loads skills from:
34
34
  - CLI: `--skill <path>` (repeatable, additive even with `--no-skills`)
35
35
 
36
36
  Discovery rules:
37
- - In `~/.pi/agent/skills/` and `.pi/skills/`, direct root `.md` files are discovered as individual skills
37
+ - In `~/.pi/agent/skills/` and `.pi/skills/`, direct root `.md` files are discovered as individual skills when they have valid skill frontmatter with a non-empty `description`
38
38
  - In all skill locations, directories containing `SKILL.md` are discovered recursively
39
- - In `~/.agents/skills/` and project `.agents/skills/`, root `.md` files are ignored
39
+ - In `~/.agents/skills/` and project `.agents/skills/`, root `.md` files are ignored, but nested `.md` files in grouping folders are discovered when they declare skill frontmatter
40
+ - Root Markdown files other than `SKILL.md` that do not look like skills are ignored silently
40
41
 
41
42
  Disable discovery with `--no-skills` (explicit `--skill` paths still load).
42
43
 
@@ -180,9 +181,9 @@ Pi validates skills against the Agent Skills standard. Most issues produce warni
180
181
  - Name starts/ends with hyphen or has consecutive hyphens
181
182
  - Description exceeds 1024 characters
182
183
 
183
- Unknown frontmatter fields are ignored.
184
+ Unknown frontmatter fields are ignored. A leading UTF-8 byte-order mark (BOM) before the opening `---` is accepted.
184
185
 
185
- **Exception:** Skills with missing description are not loaded.
186
+ Declared skills with missing descriptions are not loaded. Malformed `SKILL.md` files and `SKILL.md` files without a description produce warnings and are not loaded. Other Markdown files without valid skill frontmatter are ignored.
186
187
 
187
188
  Name collisions (same name from different locations) warn and keep the first skill found.
188
189
 
@@ -120,7 +120,15 @@ Add to `keybindings.json`:
120
120
 
121
121
  ## Windows Terminal
122
122
 
123
- Add to `settings.json` (Ctrl+Shift+, or Settings → Open JSON file) to forward the modified Enter keys pi uses:
123
+ Pi uses Windows-style keybindings when running natively on Windows or in WSL:
124
+
125
+ - `Alt+V` pastes an image or clipboard text.
126
+ - `Ctrl+F` searches the transcript in fullscreen mode, and `Ctrl+Up`/`Ctrl+Down` jump between marked messages.
127
+ - `Alt+P` cycles to the previous model.
128
+ - `Ctrl+Z` undoes editing on native Windows; WSL uses `Alt+Z` so `Ctrl+Z` can suspend pi.
129
+ - `Ctrl+Q` queues a follow-up message and `Alt+Q` restores queued messages.
130
+
131
+ Add to `settings.json` (Ctrl+Shift+, or Settings → Open JSON file) to forward `Shift+Enter` for inserting a new line:
124
132
 
125
133
  ```json
126
134
  {
@@ -128,20 +136,14 @@ Add to `settings.json` (Ctrl+Shift+, or Settings → Open JSON file) to forward
128
136
  {
129
137
  "command": { "action": "sendInput", "input": "\u001b[13;2u" },
130
138
  "keys": "shift+enter"
131
- },
132
- {
133
- "command": { "action": "sendInput", "input": "\u001b[13;3u" },
134
- "keys": "alt+enter"
135
139
  }
136
140
  ]
137
141
  }
138
142
  ```
139
143
 
140
- - `Shift+Enter` inserts a new line.
141
- - Windows Terminal binds `Alt+Enter` to fullscreen by default. That prevents pi from receiving `Alt+Enter` for follow-up queueing.
142
- - Remapping `Alt+Enter` to `sendInput` forwards the real key chord to pi instead.
144
+ Windows Terminal binds `Alt+Enter` to fullscreen by default. To use it instead of pi's `Ctrl+Q` default for follow-up queueing, configure Windows Terminal to send the key and bind `app.message.followUp` to `alt+enter` in pi.
143
145
 
144
- If you already have an `actions` array, add the objects to it. If the old fullscreen behavior persists, fully close and reopen Windows Terminal.
146
+ If you already have an `actions` array, add the object to it. Fully close and reopen Windows Terminal after changing its settings.
145
147
 
146
148
  ## xfce4-terminal, terminator
147
149
 
package/docs/usage.md CHANGED
@@ -134,7 +134,7 @@ If you use pi for open source work and want to publish sessions for model, promp
134
134
  ## CLI Reference
135
135
 
136
136
  ```bash
137
- pi [options] [@files...] [messages...]
137
+ pi [options] [--] [@files...] [messages...]
138
138
  ```
139
139
 
140
140
  ### Package Commands
@@ -205,7 +205,7 @@ cat README.md | pi -p "Summarize this text"
205
205
  | `--no-builtin-tools`, `-nbt` | Disable built-in tools but keep extension/custom tools enabled |
206
206
  | `--no-tools`, `-nt` | Disable all tools |
207
207
 
208
- Built-in tools: `read`, `bash`, `edit`, `write`, `grep`, `find`, `ls`.
208
+ Built-in tools: `read`, `bash`, `powershell` (Windows), `edit`, `write`, `grep`, `find`, `ls`.
209
209
 
210
210
  ### Resource Options
211
211
 
@@ -238,6 +238,7 @@ pi --no-extensions -e ./my-extension.ts
238
238
  | `--verbose` | Force verbose startup |
239
239
  | `-a`, `--approve` | Trust project-local files for this run |
240
240
  | `-na`, `--no-approve` | Ignore project-local files for this run |
241
+ | `--` | Stop option parsing; remaining arguments are prompts or `@file` inputs |
241
242
  | `-h`, `--help` | Show help |
242
243
  | `-v`, `--version` | Show version |
243
244
 
@@ -264,6 +265,9 @@ pi "List all .ts files in src/"
264
265
  # Non-interactive
265
266
  pi -p "Summarize this codebase"
266
267
 
268
+ # Prompt beginning with a dash
269
+ pi -p -- "- Summarize these points"
270
+
267
271
  # Non-interactive with piped stdin
268
272
  cat README.md | pi -p "Summarize this text"
269
273
 
package/docs/windows.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Windows Setup
2
2
 
3
- Pi requires a bash shell on Windows. Checked locations (in order):
3
+ Pi uses Git Bash by default on Windows. Checked locations (in order):
4
4
 
5
5
  1. Custom path from `~/.pi/agent/settings.json`
6
6
  2. Git Bash (`C:\Program Files\Git\bin\bash.exe`)
@@ -8,7 +8,29 @@ Pi requires a bash shell on Windows. Checked locations (in order):
8
8
 
9
9
  For most users, [Git for Windows](https://git-scm.com/download/win) is sufficient.
10
10
 
11
- ## Custom Shell Path
11
+ ## PowerShell Tool
12
+
13
+ The optional `powershell` tool runs commands through `pwsh.exe` when available, otherwise Windows PowerShell. It starts PowerShell with `-NoProfile -NonInteractive -ExecutionPolicy Bypass`. Administrator-enforced execution policies can still take precedence.
14
+
15
+ Use `defaultTools` to replace the model-facing `bash` tool:
16
+
17
+ ```json
18
+ {
19
+ "defaultTools": ["read", "powershell", "edit", "write"]
20
+ }
21
+ ```
22
+
23
+ Or enable both while comparing behavior:
24
+
25
+ ```json
26
+ {
27
+ "defaultTools": ["read", "bash", "powershell", "edit", "write"]
28
+ }
29
+ ```
30
+
31
+ The `!` and `!!` editor commands still use Bash.
32
+
33
+ ## Custom Bash Path
12
34
 
13
35
  ```json
14
36
  {
@@ -87,7 +87,7 @@ export default function (pi: ExtensionAPI) {
87
87
  activeTui?.requestRender();
88
88
  });
89
89
 
90
- pi.on("agent_end", () => {
90
+ pi.on("agent_settled", () => {
91
91
  isWorking = false;
92
92
  stopSpinner();
93
93
  activeTui?.requestRender();
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider",
3
- "version": "0.84.2",
3
+ "version": "0.84.3",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-custom-provider",
9
- "version": "0.84.2",
9
+ "version": "0.84.3",
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.84.2",
4
+ "version": "0.84.3",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider-gitlab-duo",
3
3
  "private": true,
4
- "version": "0.84.2",
4
+ "version": "0.84.3",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
File without changes
@@ -46,8 +46,8 @@ export default function (pi: ExtensionAPI) {
46
46
  }
47
47
  });
48
48
 
49
- pi.on("agent_end", async () => {
50
- // Clear checkpoints after agent completes
49
+ pi.on("agent_settled", async () => {
50
+ // Clear checkpoints after the full agent run completes
51
51
  checkpoints.clear();
52
52
  });
53
53
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-gondolin",
3
- "version": "0.84.2",
3
+ "version": "0.84.3",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-gondolin",
9
- "version": "0.84.2",
9
+ "version": "0.84.3",
10
10
  "dependencies": {
11
11
  "@earendil-works/gondolin": "0.12.0"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-gondolin",
3
3
  "private": true,
4
- "version": "0.84.2",
4
+ "version": "0.84.3",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",