@codex-infinity/pi-infinity 0.52.2 → 0.60.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +386 -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 +28 -6
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +289 -69
- 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/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 +126 -43
- 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 +1 -1
- 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 +75 -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 +4 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +160 -66
- 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/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.d.ts.map +1 -1
- package/dist/utils/clipboard.js +16 -15
- 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/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
|
|
package/docs/terminal-setup.md
CHANGED
|
@@ -8,13 +8,30 @@ Work out of the box.
|
|
|
8
8
|
|
|
9
9
|
## Ghostty
|
|
10
10
|
|
|
11
|
-
Add to your Ghostty config (`~/.config/ghostty/config`):
|
|
11
|
+
Add to your Ghostty config (`~/Library/Application Support/com.mitchellh.ghostty/config` on macOS, `~/.config/ghostty/config` on Linux):
|
|
12
12
|
|
|
13
13
|
```
|
|
14
14
|
keybind = alt+backspace=text:\x1b\x7f
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Older Claude Code versions may have added this Ghostty mapping:
|
|
18
|
+
|
|
19
|
+
```
|
|
15
20
|
keybind = shift+enter=text:\n
|
|
16
21
|
```
|
|
17
22
|
|
|
23
|
+
That mapping sends a raw linefeed byte. Inside pi, that is indistinguishable from `Ctrl+J`, so tmux and pi no longer see a real `shift+enter` key event.
|
|
24
|
+
|
|
25
|
+
If Claude Code 2.x or newer is the only reason you added that mapping, you can remove it, unless you want to use Claude Code in tmux, where it still requires that Ghostty mapping.
|
|
26
|
+
|
|
27
|
+
If you want `Shift+Enter` to keep working in tmux via that remap, add `ctrl+j` to your pi `newLine` keybinding in `~/.pi/agent/keybindings.json`:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"newLine": ["shift+enter", "ctrl+j"]
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
18
35
|
## WezTerm
|
|
19
36
|
|
|
20
37
|
Create `~/.wezterm.lua`:
|
|
@@ -46,7 +63,7 @@ Add to `keybindings.json` to enable `Shift+Enter` for multi-line input:
|
|
|
46
63
|
|
|
47
64
|
## Windows Terminal
|
|
48
65
|
|
|
49
|
-
Add to `settings.json` (Ctrl+Shift+, or Settings → Open JSON file):
|
|
66
|
+
Add to `settings.json` (Ctrl+Shift+, or Settings → Open JSON file) to forward the modified Enter keys pi uses:
|
|
50
67
|
|
|
51
68
|
```json
|
|
52
69
|
{
|
|
@@ -54,12 +71,31 @@ Add to `settings.json` (Ctrl+Shift+, or Settings → Open JSON file):
|
|
|
54
71
|
{
|
|
55
72
|
"command": { "action": "sendInput", "input": "\u001b[13;2u" },
|
|
56
73
|
"keys": "shift+enter"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"command": { "action": "sendInput", "input": "\u001b[13;3u" },
|
|
77
|
+
"keys": "alt+enter"
|
|
57
78
|
}
|
|
58
79
|
]
|
|
59
80
|
}
|
|
60
81
|
```
|
|
61
82
|
|
|
62
|
-
|
|
83
|
+
- `Shift+Enter` inserts a new line.
|
|
84
|
+
- Windows Terminal binds `Alt+Enter` to fullscreen by default. That prevents pi from receiving `Alt+Enter` for follow-up queueing.
|
|
85
|
+
- Remapping `Alt+Enter` to `sendInput` forwards the real key chord to pi instead.
|
|
86
|
+
|
|
87
|
+
If you already have an `actions` array, add the objects to it. If the old fullscreen behavior persists, fully close and reopen Windows Terminal.
|
|
88
|
+
|
|
89
|
+
## xfce4-terminal, terminator
|
|
90
|
+
|
|
91
|
+
These terminals have limited escape sequence support. Modified Enter keys like `Ctrl+Enter` and `Shift+Enter` cannot be distinguished from plain `Enter`, preventing custom keybindings such as `submit: ["ctrl+enter"]` from working.
|
|
92
|
+
|
|
93
|
+
For the best experience, use a terminal that supports the Kitty keyboard protocol:
|
|
94
|
+
- [Kitty](https://sw.kovidgoyal.net/kitty/)
|
|
95
|
+
- [Ghostty](https://ghostty.org/)
|
|
96
|
+
- [WezTerm](https://wezfurlong.org/wezterm/)
|
|
97
|
+
- [iTerm2](https://iterm2.com/)
|
|
98
|
+
- [Alacritty](https://github.com/alacritty/alacritty) (requires compilation with Kitty protocol support)
|
|
63
99
|
|
|
64
100
|
## IntelliJ IDEA (Integrated Terminal)
|
|
65
101
|
|
package/docs/tmux.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# tmux Setup
|
|
2
|
+
|
|
3
|
+
Pi works inside tmux, but tmux strips modifier information from certain keys by default. Without configuration, `Shift+Enter` and `Ctrl+Enter` are usually indistinguishable from plain `Enter`.
|
|
4
|
+
|
|
5
|
+
## Recommended Configuration
|
|
6
|
+
|
|
7
|
+
Add to `~/.tmux.conf`:
|
|
8
|
+
|
|
9
|
+
```tmux
|
|
10
|
+
set -g extended-keys on
|
|
11
|
+
set -g extended-keys-format csi-u
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Then restart tmux fully:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
tmux kill-server
|
|
18
|
+
tmux
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Pi requests extended key reporting automatically when Kitty keyboard protocol is not available. With `extended-keys-format csi-u`, tmux forwards modified keys in CSI-u format, which is the most reliable configuration.
|
|
22
|
+
|
|
23
|
+
## Why `csi-u` Is Recommended
|
|
24
|
+
|
|
25
|
+
With only:
|
|
26
|
+
|
|
27
|
+
```tmux
|
|
28
|
+
set -g extended-keys on
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
tmux defaults to `extended-keys-format xterm`. When an application requests extended key reporting, modified keys are forwarded in xterm `modifyOtherKeys` format such as:
|
|
32
|
+
|
|
33
|
+
- `Ctrl+C` → `\x1b[27;5;99~`
|
|
34
|
+
- `Ctrl+D` → `\x1b[27;5;100~`
|
|
35
|
+
- `Ctrl+Enter` → `\x1b[27;5;13~`
|
|
36
|
+
|
|
37
|
+
With `extended-keys-format csi-u`, the same keys are forwarded as:
|
|
38
|
+
|
|
39
|
+
- `Ctrl+C` → `\x1b[99;5u`
|
|
40
|
+
- `Ctrl+D` → `\x1b[100;5u`
|
|
41
|
+
- `Ctrl+Enter` → `\x1b[13;5u`
|
|
42
|
+
|
|
43
|
+
Pi supports both formats, but `csi-u` is the recommended tmux setup.
|
|
44
|
+
|
|
45
|
+
## What This Fixes
|
|
46
|
+
|
|
47
|
+
Without tmux extended keys, modified Enter keys collapse to legacy sequences:
|
|
48
|
+
|
|
49
|
+
| Key | Without extkeys | With `csi-u` |
|
|
50
|
+
|-----|-----------------|--------------|
|
|
51
|
+
| Enter | `\r` | `\r` |
|
|
52
|
+
| Shift+Enter | `\r` | `\x1b[13;2u` |
|
|
53
|
+
| Ctrl+Enter | `\r` | `\x1b[13;5u` |
|
|
54
|
+
| Alt/Option+Enter | `\x1b\r` | `\x1b[13;3u` |
|
|
55
|
+
|
|
56
|
+
This affects the default keybindings (`Enter` to submit, `Shift+Enter` for newline) and any custom keybindings using modified Enter.
|
|
57
|
+
|
|
58
|
+
## Requirements
|
|
59
|
+
|
|
60
|
+
- tmux 3.2 or later (run `tmux -V` to check)
|
|
61
|
+
- A terminal emulator that supports extended keys (Ghostty, Kitty, iTerm2, WezTerm, Windows Terminal)
|
package/docs/tree.md
CHANGED
|
@@ -33,16 +33,25 @@ Sessions are stored as trees where each entry has an `id` and `parentId`. The "l
|
|
|
33
33
|
| Key | Action |
|
|
34
34
|
|-----|--------|
|
|
35
35
|
| ↑/↓ | Navigate (depth-first order) |
|
|
36
|
+
| ←/→ | Page up/down |
|
|
37
|
+
| Ctrl+←/Ctrl+→ or Alt+←/Alt+→ | Fold/unfold and jump between branch segments |
|
|
36
38
|
| Enter | Select node |
|
|
37
39
|
| Escape/Ctrl+C | Cancel |
|
|
38
40
|
| Ctrl+U | Toggle: user messages only |
|
|
39
41
|
| Ctrl+O | Toggle: show all (including custom/label entries) |
|
|
40
42
|
|
|
43
|
+
`Ctrl+←` or `Alt+←` folds the current node if it is foldable. Foldable nodes are roots and branch segment starts that have visible children. If the current node is not foldable, or is already folded, the selection jumps up to the previous visible branch segment start.
|
|
44
|
+
|
|
45
|
+
`Ctrl+→` or `Alt+→` unfolds the current node if it is folded. Otherwise, the selection jumps down to the next visible branch segment start, or to the branch end when there is no further branch point.
|
|
46
|
+
|
|
41
47
|
### Display
|
|
42
48
|
|
|
43
49
|
- Height: half terminal height
|
|
44
50
|
- Current leaf marked with `← active`
|
|
45
51
|
- Labels shown inline: `[label-name]`
|
|
52
|
+
- Foldable branch starts show `⊟` in the connector. Folded branches show `⊞`
|
|
53
|
+
- Active path marker `•` appears after the fold indicator when applicable
|
|
54
|
+
- Search and filter changes reset all folds
|
|
46
55
|
- Default filter hides `label` and `custom` entries (shown in Ctrl+O mode)
|
|
47
56
|
- Children sorted by timestamp (oldest first)
|
|
48
57
|
|
|
@@ -33,6 +33,8 @@ cp permission-gate.ts ~/.pi/agent/extensions/
|
|
|
33
33
|
| `question.ts` | Demonstrates `ctx.ui.select()` for asking the user questions with custom UI |
|
|
34
34
|
| `questionnaire.ts` | Multi-question input with tab bar navigation between questions |
|
|
35
35
|
| `tool-override.ts` | Override built-in tools (e.g., add logging/access control to `read`) |
|
|
36
|
+
| `dynamic-tools.ts` | Register tools after startup (`session_start`) and at runtime via command, with prompt snippets and tool-specific prompt guidelines |
|
|
37
|
+
| `built-in-tool-renderer.ts` | Custom compact rendering for built-in tools (read, bash, edit, write) while keeping original behavior |
|
|
36
38
|
| `minimal-mode.ts` | Override built-in tool rendering for minimal display (only tool calls, no output in collapsed mode) |
|
|
37
39
|
| `truncated-tool.ts` | Wraps ripgrep with proper output truncation (50KB/2000 lines) |
|
|
38
40
|
| `antigravity-image-gen.ts` | Generate images via Google Antigravity with optional save-to-disk modes |
|
|
@@ -28,10 +28,9 @@
|
|
|
28
28
|
import { randomUUID } from "node:crypto";
|
|
29
29
|
import { existsSync, readFileSync } from "node:fs";
|
|
30
30
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
31
|
-
import { homedir } from "node:os";
|
|
32
31
|
import { join } from "node:path";
|
|
33
32
|
import { StringEnum } from "@mariozechner/pi-ai";
|
|
34
|
-
import type
|
|
33
|
+
import { type ExtensionAPI, getAgentDir } from "@mariozechner/pi-coding-agent";
|
|
35
34
|
import { type Static, Type } from "@sinclair/typebox";
|
|
36
35
|
|
|
37
36
|
const PROVIDER = "google-antigravity";
|
|
@@ -49,8 +48,10 @@ type SaveMode = (typeof SAVE_MODES)[number];
|
|
|
49
48
|
|
|
50
49
|
const ANTIGRAVITY_ENDPOINT = "https://daily-cloudcode-pa.sandbox.googleapis.com";
|
|
51
50
|
|
|
51
|
+
const DEFAULT_ANTIGRAVITY_VERSION = "1.18.3";
|
|
52
|
+
|
|
52
53
|
const ANTIGRAVITY_HEADERS = {
|
|
53
|
-
"User-Agent":
|
|
54
|
+
"User-Agent": `antigravity/${process.env.PI_AI_ANTIGRAVITY_VERSION || DEFAULT_ANTIGRAVITY_VERSION} darwin/arm64`,
|
|
54
55
|
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
|
|
55
56
|
"Client-Metadata": JSON.stringify({
|
|
56
57
|
ideType: "IDE_UNSPECIFIED",
|
|
@@ -182,7 +183,8 @@ function readConfigFile(path: string): ExtensionConfig {
|
|
|
182
183
|
}
|
|
183
184
|
|
|
184
185
|
function loadConfig(cwd: string): ExtensionConfig {
|
|
185
|
-
const
|
|
186
|
+
const globalPath = join(getAgentDir(), "extensions", "antigravity-image-gen.json");
|
|
187
|
+
const globalConfig = readConfigFile(globalPath);
|
|
186
188
|
const projectConfig = readConfigFile(join(cwd, ".pi", "extensions", "antigravity-image-gen.json"));
|
|
187
189
|
return { ...globalConfig, ...projectConfig };
|
|
188
190
|
}
|
|
@@ -202,7 +204,8 @@ function resolveSaveConfig(params: ToolParams, cwd: string): SaveConfig {
|
|
|
202
204
|
}
|
|
203
205
|
|
|
204
206
|
if (mode === "global") {
|
|
205
|
-
|
|
207
|
+
const outputDir = join(getAgentDir(), "generated-images");
|
|
208
|
+
return { mode, outputDir };
|
|
206
209
|
}
|
|
207
210
|
|
|
208
211
|
if (mode === "custom") {
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in Tool Renderer Example - Custom rendering for built-in tools
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates how to override the rendering of built-in tools (read, bash,
|
|
5
|
+
* edit, write) without changing their behavior. Each tool is re-registered
|
|
6
|
+
* with the same name, delegating execution to the original implementation
|
|
7
|
+
* while providing compact custom renderCall/renderResult functions.
|
|
8
|
+
*
|
|
9
|
+
* This is useful for users who prefer more concise tool output, or who want
|
|
10
|
+
* to highlight specific information (e.g., showing only the diff stats for
|
|
11
|
+
* edit, or just the exit code for bash).
|
|
12
|
+
*
|
|
13
|
+
* How it works:
|
|
14
|
+
* - registerTool() with the same name as a built-in replaces it entirely
|
|
15
|
+
* - We create instances of the original tools via createReadTool(), etc.
|
|
16
|
+
* and delegate execute() to them
|
|
17
|
+
* - renderCall() controls what's shown when the tool is invoked
|
|
18
|
+
* - renderResult() controls what's shown after execution completes
|
|
19
|
+
* - The `expanded` flag in renderResult indicates whether the user has
|
|
20
|
+
* toggled the tool output open (via ctrl+e or clicking)
|
|
21
|
+
*
|
|
22
|
+
* Usage:
|
|
23
|
+
* pi -e ./built-in-tool-renderer.ts
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import type { BashToolDetails, EditToolDetails, ExtensionAPI, ReadToolDetails } from "@mariozechner/pi-coding-agent";
|
|
27
|
+
import { createBashTool, createEditTool, createReadTool, createWriteTool } from "@mariozechner/pi-coding-agent";
|
|
28
|
+
import { Text } from "@mariozechner/pi-tui";
|
|
29
|
+
|
|
30
|
+
export default function (pi: ExtensionAPI) {
|
|
31
|
+
const cwd = process.cwd();
|
|
32
|
+
|
|
33
|
+
// --- Read tool: show path and line count ---
|
|
34
|
+
const originalRead = createReadTool(cwd);
|
|
35
|
+
pi.registerTool({
|
|
36
|
+
name: "read",
|
|
37
|
+
label: "read",
|
|
38
|
+
description: originalRead.description,
|
|
39
|
+
parameters: originalRead.parameters,
|
|
40
|
+
|
|
41
|
+
async execute(toolCallId, params, signal, onUpdate) {
|
|
42
|
+
return originalRead.execute(toolCallId, params, signal, onUpdate);
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
renderCall(args, theme) {
|
|
46
|
+
let text = theme.fg("toolTitle", theme.bold("read "));
|
|
47
|
+
text += theme.fg("accent", args.path);
|
|
48
|
+
if (args.offset || args.limit) {
|
|
49
|
+
const parts: string[] = [];
|
|
50
|
+
if (args.offset) parts.push(`offset=${args.offset}`);
|
|
51
|
+
if (args.limit) parts.push(`limit=${args.limit}`);
|
|
52
|
+
text += theme.fg("dim", ` (${parts.join(", ")})`);
|
|
53
|
+
}
|
|
54
|
+
return new Text(text, 0, 0);
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
renderResult(result, { expanded, isPartial }, theme) {
|
|
58
|
+
if (isPartial) return new Text(theme.fg("warning", "Reading..."), 0, 0);
|
|
59
|
+
|
|
60
|
+
const details = result.details as ReadToolDetails | undefined;
|
|
61
|
+
const content = result.content[0];
|
|
62
|
+
|
|
63
|
+
if (content?.type === "image") {
|
|
64
|
+
return new Text(theme.fg("success", "Image loaded"), 0, 0);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (content?.type !== "text") {
|
|
68
|
+
return new Text(theme.fg("error", "No content"), 0, 0);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const lineCount = content.text.split("\n").length;
|
|
72
|
+
let text = theme.fg("success", `${lineCount} lines`);
|
|
73
|
+
|
|
74
|
+
if (details?.truncation?.truncated) {
|
|
75
|
+
text += theme.fg("warning", ` (truncated from ${details.truncation.totalLines})`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (expanded) {
|
|
79
|
+
const lines = content.text.split("\n").slice(0, 15);
|
|
80
|
+
for (const line of lines) {
|
|
81
|
+
text += `\n${theme.fg("dim", line)}`;
|
|
82
|
+
}
|
|
83
|
+
if (lineCount > 15) {
|
|
84
|
+
text += `\n${theme.fg("muted", `... ${lineCount - 15} more lines`)}`;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return new Text(text, 0, 0);
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// --- Bash tool: show command and exit code ---
|
|
93
|
+
const originalBash = createBashTool(cwd);
|
|
94
|
+
pi.registerTool({
|
|
95
|
+
name: "bash",
|
|
96
|
+
label: "bash",
|
|
97
|
+
description: originalBash.description,
|
|
98
|
+
parameters: originalBash.parameters,
|
|
99
|
+
|
|
100
|
+
async execute(toolCallId, params, signal, onUpdate) {
|
|
101
|
+
return originalBash.execute(toolCallId, params, signal, onUpdate);
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
renderCall(args, theme) {
|
|
105
|
+
let text = theme.fg("toolTitle", theme.bold("$ "));
|
|
106
|
+
const cmd = args.command.length > 80 ? `${args.command.slice(0, 77)}...` : args.command;
|
|
107
|
+
text += theme.fg("accent", cmd);
|
|
108
|
+
if (args.timeout) {
|
|
109
|
+
text += theme.fg("dim", ` (timeout: ${args.timeout}s)`);
|
|
110
|
+
}
|
|
111
|
+
return new Text(text, 0, 0);
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
renderResult(result, { expanded, isPartial }, theme) {
|
|
115
|
+
if (isPartial) return new Text(theme.fg("warning", "Running..."), 0, 0);
|
|
116
|
+
|
|
117
|
+
const details = result.details as BashToolDetails | undefined;
|
|
118
|
+
const content = result.content[0];
|
|
119
|
+
const output = content?.type === "text" ? content.text : "";
|
|
120
|
+
|
|
121
|
+
const exitMatch = output.match(/exit code: (\d+)/);
|
|
122
|
+
const exitCode = exitMatch ? parseInt(exitMatch[1], 10) : null;
|
|
123
|
+
const lineCount = output.split("\n").filter((l) => l.trim()).length;
|
|
124
|
+
|
|
125
|
+
let text = "";
|
|
126
|
+
if (exitCode === 0 || exitCode === null) {
|
|
127
|
+
text += theme.fg("success", "done");
|
|
128
|
+
} else {
|
|
129
|
+
text += theme.fg("error", `exit ${exitCode}`);
|
|
130
|
+
}
|
|
131
|
+
text += theme.fg("dim", ` (${lineCount} lines)`);
|
|
132
|
+
|
|
133
|
+
if (details?.truncation?.truncated) {
|
|
134
|
+
text += theme.fg("warning", " [truncated]");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (expanded) {
|
|
138
|
+
const lines = output.split("\n").slice(0, 20);
|
|
139
|
+
for (const line of lines) {
|
|
140
|
+
text += `\n${theme.fg("dim", line)}`;
|
|
141
|
+
}
|
|
142
|
+
if (output.split("\n").length > 20) {
|
|
143
|
+
text += `\n${theme.fg("muted", "... more output")}`;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return new Text(text, 0, 0);
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// --- Edit tool: show path and diff stats ---
|
|
152
|
+
const originalEdit = createEditTool(cwd);
|
|
153
|
+
pi.registerTool({
|
|
154
|
+
name: "edit",
|
|
155
|
+
label: "edit",
|
|
156
|
+
description: originalEdit.description,
|
|
157
|
+
parameters: originalEdit.parameters,
|
|
158
|
+
|
|
159
|
+
async execute(toolCallId, params, signal, onUpdate) {
|
|
160
|
+
return originalEdit.execute(toolCallId, params, signal, onUpdate);
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
renderCall(args, theme) {
|
|
164
|
+
let text = theme.fg("toolTitle", theme.bold("edit "));
|
|
165
|
+
text += theme.fg("accent", args.path);
|
|
166
|
+
return new Text(text, 0, 0);
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
renderResult(result, { expanded, isPartial }, theme) {
|
|
170
|
+
if (isPartial) return new Text(theme.fg("warning", "Editing..."), 0, 0);
|
|
171
|
+
|
|
172
|
+
const details = result.details as EditToolDetails | undefined;
|
|
173
|
+
const content = result.content[0];
|
|
174
|
+
|
|
175
|
+
if (content?.type === "text" && content.text.startsWith("Error")) {
|
|
176
|
+
return new Text(theme.fg("error", content.text.split("\n")[0]), 0, 0);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (!details?.diff) {
|
|
180
|
+
return new Text(theme.fg("success", "Applied"), 0, 0);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Count additions and removals from the diff
|
|
184
|
+
const diffLines = details.diff.split("\n");
|
|
185
|
+
let additions = 0;
|
|
186
|
+
let removals = 0;
|
|
187
|
+
for (const line of diffLines) {
|
|
188
|
+
if (line.startsWith("+") && !line.startsWith("+++")) additions++;
|
|
189
|
+
if (line.startsWith("-") && !line.startsWith("---")) removals++;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
let text = theme.fg("success", `+${additions}`);
|
|
193
|
+
text += theme.fg("dim", " / ");
|
|
194
|
+
text += theme.fg("error", `-${removals}`);
|
|
195
|
+
|
|
196
|
+
if (expanded) {
|
|
197
|
+
for (const line of diffLines.slice(0, 30)) {
|
|
198
|
+
if (line.startsWith("+") && !line.startsWith("+++")) {
|
|
199
|
+
text += `\n${theme.fg("success", line)}`;
|
|
200
|
+
} else if (line.startsWith("-") && !line.startsWith("---")) {
|
|
201
|
+
text += `\n${theme.fg("error", line)}`;
|
|
202
|
+
} else {
|
|
203
|
+
text += `\n${theme.fg("dim", line)}`;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (diffLines.length > 30) {
|
|
207
|
+
text += `\n${theme.fg("muted", `... ${diffLines.length - 30} more diff lines`)}`;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return new Text(text, 0, 0);
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// --- Write tool: show path and size ---
|
|
216
|
+
const originalWrite = createWriteTool(cwd);
|
|
217
|
+
pi.registerTool({
|
|
218
|
+
name: "write",
|
|
219
|
+
label: "write",
|
|
220
|
+
description: originalWrite.description,
|
|
221
|
+
parameters: originalWrite.parameters,
|
|
222
|
+
|
|
223
|
+
async execute(toolCallId, params, signal, onUpdate) {
|
|
224
|
+
return originalWrite.execute(toolCallId, params, signal, onUpdate);
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
renderCall(args, theme) {
|
|
228
|
+
let text = theme.fg("toolTitle", theme.bold("write "));
|
|
229
|
+
text += theme.fg("accent", args.path);
|
|
230
|
+
const lineCount = args.content.split("\n").length;
|
|
231
|
+
text += theme.fg("dim", ` (${lineCount} lines)`);
|
|
232
|
+
return new Text(text, 0, 0);
|
|
233
|
+
},
|
|
234
|
+
|
|
235
|
+
renderResult(result, { isPartial }, theme) {
|
|
236
|
+
if (isPartial) return new Text(theme.fg("warning", "Writing..."), 0, 0);
|
|
237
|
+
|
|
238
|
+
const content = result.content[0];
|
|
239
|
+
if (content?.type === "text" && content.text.startsWith("Error")) {
|
|
240
|
+
return new Text(theme.fg("error", content.text.split("\n")[0]), 0, 0);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return new Text(theme.fg("success", "Written"), 0, 0);
|
|
244
|
+
},
|
|
245
|
+
});
|
|
246
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extension-custom-provider",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-extension-custom-provider",
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.11.1",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sdk": "^0.52.0"
|
|
12
12
|
}
|