@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.
- package/CHANGELOG.md +387 -0
- package/README.md +97 -66
- package/dist/bun/cli.d.ts +3 -0
- package/dist/bun/cli.d.ts.map +1 -0
- package/dist/bun/cli.js +6 -0
- package/dist/bun/cli.js.map +1 -0
- package/dist/bun/register-bedrock.d.ts +2 -0
- package/dist/bun/register-bedrock.d.ts.map +1 -0
- package/dist/bun/register-bedrock.js +4 -0
- package/dist/bun/register-bedrock.js.map +1 -0
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +17 -6
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/initial-message.d.ts +18 -0
- package/dist/cli/initial-message.d.ts.map +1 -0
- package/dist/cli/initial-message.js +22 -0
- package/dist/cli/initial-message.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/core/agent-session.d.ts +42 -6
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +346 -72
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +1 -0
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +27 -2
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bash-executor.d.ts +6 -7
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +8 -107
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +1 -0
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +6 -1
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/utils.d.ts +3 -0
- package/dist/core/compaction/utils.d.ts.map +1 -1
- package/dist/core/compaction/utils.js +16 -1
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/core/exec.d.ts.map +1 -1
- package/dist/core/exec.js +7 -3
- package/dist/core/exec.js.map +1 -1
- package/dist/core/export-html/index.d.ts +5 -2
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +4 -3
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/export-html/template.js +11 -14
- package/dist/core/export-html/tool-renderer.d.ts +5 -2
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js +17 -4
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/index.d.ts +2 -2
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +37 -11
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +8 -4
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +77 -8
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +56 -4
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/wrapper.d.ts +4 -11
- package/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/dist/core/extensions/wrapper.js +4 -78
- package/dist/core/extensions/wrapper.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +6 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +83 -37
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/keybindings.d.ts +3 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +22 -12
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-registry.d.ts +11 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +56 -16
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +6 -0
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +122 -39
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/package-manager.d.ts +19 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +290 -57
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +43 -8
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +4 -7
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +7 -0
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +1 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +21 -15
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +10 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +59 -5
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts +3 -2
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +29 -8
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +3 -2
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts +4 -0
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +43 -29
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +8 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +77 -69
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +1 -0
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +6 -3
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/index.d.ts +1 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +1 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +116 -36
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts +5 -2
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +9 -0
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +8 -23
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +1 -1
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +1 -1
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +1 -1
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +1 -1
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +15 -1
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.js +5 -1
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/theme-selector.js +5 -1
- package/dist/modes/interactive/components/theme-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +5 -1
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +7 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +158 -7
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts +21 -2
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +127 -10
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts +1 -0
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +12 -0
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +5 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +215 -71
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +5 -0
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/rpc/jsonl.d.ts +17 -0
- package/dist/modes/rpc/jsonl.d.ts.map +1 -0
- package/dist/modes/rpc/jsonl.js +49 -0
- package/dist/modes/rpc/jsonl.js.map +1 -0
- package/dist/modes/rpc/rpc-client.d.ts +1 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +7 -11
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +9 -11
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/utils/child-process.d.ts +11 -0
- package/dist/utils/child-process.d.ts.map +1 -0
- package/dist/utils/child-process.js +78 -0
- package/dist/utils/child-process.js.map +1 -0
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js +94 -11
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard-native.d.ts +1 -0
- package/dist/utils/clipboard-native.d.ts.map +1 -1
- package/dist/utils/clipboard-native.js.map +1 -1
- package/dist/utils/clipboard.d.ts +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +27 -16
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/exif-orientation.d.ts +5 -0
- package/dist/utils/exif-orientation.d.ts.map +1 -0
- package/dist/utils/exif-orientation.js +158 -0
- package/dist/utils/exif-orientation.js.map +1 -0
- package/dist/utils/image-convert.d.ts.map +1 -1
- package/dist/utils/image-convert.js +5 -1
- package/dist/utils/image-convert.js.map +1 -1
- package/dist/utils/image-resize.d.ts.map +1 -1
- package/dist/utils/image-resize.js +6 -1
- package/dist/utils/image-resize.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +66 -21
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/compaction.md +2 -0
- package/docs/custom-provider.md +57 -9
- package/docs/extensions.md +125 -12
- package/docs/keybindings.md +11 -1
- package/docs/models.md +44 -2
- package/docs/packages.md +9 -0
- package/docs/providers.md +10 -1
- package/docs/rpc.md +44 -7
- package/docs/sdk.md +2 -2
- package/docs/settings.md +11 -0
- package/docs/terminal-setup.md +39 -3
- package/docs/tmux.md +61 -0
- package/docs/tree.md +9 -0
- package/examples/extensions/README.md +2 -0
- package/examples/extensions/antigravity-image-gen.ts +8 -5
- package/examples/extensions/built-in-tool-renderer.ts +246 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +2 -2
- package/examples/extensions/custom-provider-qwen-cli/package.json +1 -1
- package/examples/extensions/dynamic-tools.ts +74 -0
- package/examples/extensions/overlay-qa-tests.ts +468 -1
- package/examples/extensions/preset.ts +2 -3
- package/examples/extensions/provider-payload.ts +14 -0
- package/examples/extensions/sandbox/index.ts +2 -3
- package/examples/extensions/subagent/agents.ts +2 -3
- package/examples/extensions/tool-override.ts +2 -3
- package/examples/extensions/with-deps/index.ts +1 -5
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +10 -7
package/docs/extensions.md
CHANGED
|
@@ -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
|
-
│ │ ├─►
|
|
252
|
-
│ │ └─►
|
|
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
|
|
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:
|
|
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
|
-
|
|
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) -
|
|
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"` -
|
|
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
|
|
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` |
|
package/docs/keybindings.md
CHANGED
|
@@ -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` |
|
|
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"`:
|
|
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
|
|
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
|
|
314
|
-
- `"one-at-a-time"`: Deliver one steering message per
|
|
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
|
|
1306
|
+
const { StringDecoder } = require("string_decoder");
|
|
1296
1307
|
|
|
1297
1308
|
const agent = spawn("pi", ["--mode", "rpc", "--no-session"]);
|
|
1298
1309
|
|
|
1299
|
-
|
|
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>; //
|
|
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
|
-
//
|
|
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
|
|