@caupulican/pi-adaptative 0.76.1 → 0.77.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +55 -0
- package/README.md +9 -0
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +23 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +1 -0
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +1 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +4 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +25 -4
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bash-executor.d.ts +2 -0
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +26 -0
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +1 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +8 -2
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +7 -5
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +65 -13
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +1 -1
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts +9 -1
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +134 -11
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/sdk.d.ts +2 -0
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +4 -5
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +3 -5
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +42 -17
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +0 -3
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +175 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +4 -0
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/file-encoding-policy.d.ts +19 -0
- package/dist/core/tools/file-encoding-policy.d.ts.map +1 -0
- package/dist/core/tools/file-encoding-policy.js +54 -0
- package/dist/core/tools/file-encoding-policy.js.map +1 -0
- package/dist/core/tools/find.d.ts +1 -0
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +77 -60
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/git-filter.d.ts +41 -0
- package/dist/core/tools/git-filter.d.ts.map +1 -0
- package/dist/core/tools/git-filter.js +660 -0
- package/dist/core/tools/git-filter.js.map +1 -0
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +28 -3
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/ls.d.ts +7 -5
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +39 -5
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/read.d.ts +3 -0
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +98 -13
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/write.d.ts +2 -0
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +23 -3
- package/dist/core/tools/write.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +15 -2
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +118 -1
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts +1 -3
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +2 -4
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +2 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +51 -6
- 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 +10 -0
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/utils/deprecation.d.ts +4 -0
- package/dist/utils/deprecation.d.ts.map +1 -0
- package/dist/utils/deprecation.js +13 -0
- package/dist/utils/deprecation.js.map +1 -0
- package/dist/utils/json.d.ts +3 -0
- package/dist/utils/json.d.ts.map +1 -0
- package/dist/utils/json.js +7 -0
- package/dist/utils/json.js.map +1 -0
- package/docs/custom-provider.md +13 -10
- package/docs/extensions.md +12 -6
- package/docs/models.md +25 -12
- package/docs/providers.md +13 -5
- package/docs/quickstart.md +1 -0
- package/docs/rpc.md +2 -1
- package/docs/sdk.md +6 -0
- package/docs/session-format.md +1 -1
- package/docs/sessions.md +8 -0
- package/docs/usage.md +9 -0
- package/examples/extensions/README.md +1 -0
- package/examples/extensions/custom-provider-anthropic/index.ts +1 -1
- 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/index.ts +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/git-merge-and-resolve.ts +115 -0
- package/examples/extensions/input-transform-streaming.ts +39 -0
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +56 -56
- package/package.json +5 -5
package/docs/models.md
CHANGED
|
@@ -101,7 +101,7 @@ Use `google-generative-ai` with a `baseUrl` to add models from Google AI Studio,
|
|
|
101
101
|
"my-google": {
|
|
102
102
|
"baseUrl": "https://generativelanguage.googleapis.com/v1beta",
|
|
103
103
|
"api": "google-generative-ai",
|
|
104
|
-
"apiKey": "GEMINI_API_KEY",
|
|
104
|
+
"apiKey": "$GEMINI_API_KEY",
|
|
105
105
|
"models": [
|
|
106
106
|
{
|
|
107
107
|
"id": "gemma-4-31b-it",
|
|
@@ -143,22 +143,31 @@ Set `api` at provider level (default for all models) or model level (override pe
|
|
|
143
143
|
|
|
144
144
|
### Value Resolution
|
|
145
145
|
|
|
146
|
-
The `apiKey` and `headers` fields support
|
|
146
|
+
The `apiKey` and `headers` fields support command execution, environment interpolation, and literals:
|
|
147
147
|
|
|
148
|
-
- **Shell command:** `"!command"` executes and uses stdout
|
|
148
|
+
- **Shell command:** `"!command"` at the start executes the whole value as a command and uses stdout
|
|
149
149
|
```json
|
|
150
150
|
"apiKey": "!security find-generic-password -ws 'anthropic'"
|
|
151
151
|
"apiKey": "!op read 'op://vault/item/credential'"
|
|
152
152
|
```
|
|
153
|
-
- **Environment
|
|
153
|
+
- **Environment interpolation:** `"$ENV_VAR"` or `"${ENV_VAR}"` uses the value of the named variable. Interpolation works inside larger literals.
|
|
154
154
|
```json
|
|
155
|
-
"apiKey": "MY_API_KEY"
|
|
155
|
+
"apiKey": "$MY_API_KEY"
|
|
156
|
+
"apiKey": "${KEY_PREFIX}_${KEY_SUFFIX}"
|
|
157
|
+
```
|
|
158
|
+
`$FOO_BAR` is the variable `FOO_BAR`; use `${FOO}_BAR` when `BAR` is literal text. Missing environment variables make the value unresolved.
|
|
159
|
+
- **Escapes:** `"$$"` emits a literal `"$"`; `"$!"` emits a literal `"!"` without triggering command execution.
|
|
160
|
+
```json
|
|
161
|
+
"apiKey": "$$literal-dollar-prefix"
|
|
162
|
+
"apiKey": "$!literal-bang-prefix"
|
|
156
163
|
```
|
|
157
164
|
- **Literal value:** Used directly
|
|
158
165
|
```json
|
|
159
166
|
"apiKey": "sk-..."
|
|
160
167
|
```
|
|
161
168
|
|
|
169
|
+
Legacy uppercase env-var-like values such as `MY_API_KEY` are migrated to `$MY_API_KEY` on startup.
|
|
170
|
+
|
|
162
171
|
For `models.json`, shell commands are resolved at request time. pi intentionally does not apply built-in TTL, stale reuse, or recovery logic for arbitrary commands. Different commands need different caching and failure strategies, and pi cannot infer the right one.
|
|
163
172
|
|
|
164
173
|
If your command is slow, expensive, rate-limited, or should keep using a previous value on transient failures, wrap it in your own script or command that implements the caching or TTL behavior you want.
|
|
@@ -172,10 +181,10 @@ If your command is slow, expensive, rate-limited, or should keep using a previou
|
|
|
172
181
|
"providers": {
|
|
173
182
|
"custom-proxy": {
|
|
174
183
|
"baseUrl": "https://proxy.example.com/v1",
|
|
175
|
-
"apiKey": "MY_API_KEY",
|
|
184
|
+
"apiKey": "$MY_API_KEY",
|
|
176
185
|
"api": "anthropic-messages",
|
|
177
186
|
"headers": {
|
|
178
|
-
"x-portkey-api-key": "PORTKEY_API_KEY",
|
|
187
|
+
"x-portkey-api-key": "$PORTKEY_API_KEY",
|
|
179
188
|
"x-secret": "!op read 'op://vault/item/secret'"
|
|
180
189
|
},
|
|
181
190
|
"models": [...]
|
|
@@ -268,7 +277,7 @@ To merge custom models into a built-in provider, include the `models` array:
|
|
|
268
277
|
"providers": {
|
|
269
278
|
"anthropic": {
|
|
270
279
|
"baseUrl": "https://my-proxy.example.com/v1",
|
|
271
|
-
"apiKey": "ANTHROPIC_API_KEY",
|
|
280
|
+
"apiKey": "$ANTHROPIC_API_KEY",
|
|
272
281
|
"api": "anthropic-messages",
|
|
273
282
|
"models": [...]
|
|
274
283
|
}
|
|
@@ -321,17 +330,20 @@ By default pi sends per-tool `eager_input_streaming: true`. If a proxy or Anthro
|
|
|
321
330
|
|
|
322
331
|
Some Anthropic models require adaptive thinking (`thinking.type: "adaptive"` plus `output_config.effort`) instead of the legacy budget-based thinking payload. Built-in models set this automatically. For custom providers or aliases that route to those models, set `forceAdaptiveThinking` to `true`.
|
|
323
332
|
|
|
333
|
+
Some Anthropic-compatible providers emit thinking blocks with empty signatures and still expect them on replay. Set `allowEmptySignature` to `true` only for those providers; real Anthropic rejects empty thinking signatures.
|
|
334
|
+
|
|
324
335
|
```json
|
|
325
336
|
{
|
|
326
337
|
"providers": {
|
|
327
338
|
"anthropic-proxy": {
|
|
328
339
|
"baseUrl": "https://proxy.example.com",
|
|
329
340
|
"api": "anthropic-messages",
|
|
330
|
-
"apiKey": "ANTHROPIC_PROXY_KEY",
|
|
341
|
+
"apiKey": "$ANTHROPIC_PROXY_KEY",
|
|
331
342
|
"compat": {
|
|
332
343
|
"supportsEagerToolInputStreaming": false,
|
|
333
344
|
"supportsLongCacheRetention": true,
|
|
334
|
-
"forceAdaptiveThinking": true
|
|
345
|
+
"forceAdaptiveThinking": true,
|
|
346
|
+
"allowEmptySignature": true
|
|
335
347
|
},
|
|
336
348
|
"models": [
|
|
337
349
|
{
|
|
@@ -352,6 +364,7 @@ Some Anthropic models require adaptive thinking (`thinking.type: "adaptive"` plu
|
|
|
352
364
|
| `sendSessionAffinityHeaders` | Whether to send `x-session-affinity` from the session id when caching is enabled. Default: auto-detected for known providers. |
|
|
353
365
|
| `supportsCacheControlOnTools` | Whether the provider accepts Anthropic-style `cache_control` markers on tool definitions. Default: `true`. |
|
|
354
366
|
| `forceAdaptiveThinking` | Whether to send adaptive thinking (`thinking.type: "adaptive"` plus `output_config.effort`) for this model. Built-in adaptive models set this automatically. Default: `false`. |
|
|
367
|
+
| `allowEmptySignature` | Whether to replay empty thinking signatures as `signature: ""` instead of converting thinking to text. Default: `false`. |
|
|
355
368
|
|
|
356
369
|
## OpenAI Compatibility
|
|
357
370
|
|
|
@@ -405,7 +418,7 @@ Example:
|
|
|
405
418
|
"providers": {
|
|
406
419
|
"openrouter": {
|
|
407
420
|
"baseUrl": "https://openrouter.ai/api/v1",
|
|
408
|
-
"apiKey": "OPENROUTER_API_KEY",
|
|
421
|
+
"apiKey": "$OPENROUTER_API_KEY",
|
|
409
422
|
"api": "openai-completions",
|
|
410
423
|
"models": [
|
|
411
424
|
{
|
|
@@ -455,7 +468,7 @@ Vercel AI Gateway example:
|
|
|
455
468
|
"providers": {
|
|
456
469
|
"vercel-ai-gateway": {
|
|
457
470
|
"baseUrl": "https://ai-gateway.vercel.sh/v1",
|
|
458
|
-
"apiKey": "AI_GATEWAY_API_KEY",
|
|
471
|
+
"apiKey": "$AI_GATEWAY_API_KEY",
|
|
459
472
|
"api": "openai-completions",
|
|
460
473
|
"models": [
|
|
461
474
|
{
|
package/docs/providers.md
CHANGED
|
@@ -101,23 +101,31 @@ The file is created with `0600` permissions (user read/write only). Auth file cr
|
|
|
101
101
|
|
|
102
102
|
### Key Resolution
|
|
103
103
|
|
|
104
|
-
The `key` field supports
|
|
104
|
+
The `key` field supports command execution, environment interpolation, and literals:
|
|
105
105
|
|
|
106
|
-
- **Shell command:** `"!command"` executes and uses stdout (cached for process lifetime)
|
|
106
|
+
- **Shell command:** `"!command"` at the start executes the whole value as a command and uses stdout (cached for process lifetime)
|
|
107
107
|
```json
|
|
108
108
|
{ "type": "api_key", "key": "!security find-generic-password -ws 'anthropic'" }
|
|
109
109
|
{ "type": "api_key", "key": "!op read 'op://vault/item/credential'" }
|
|
110
110
|
```
|
|
111
|
-
- **Environment
|
|
111
|
+
- **Environment interpolation:** `"$ENV_VAR"` or `"${ENV_VAR}"` uses the value of the named variable. Interpolation works inside larger literals.
|
|
112
112
|
```json
|
|
113
|
-
{ "type": "api_key", "key": "MY_ANTHROPIC_KEY" }
|
|
113
|
+
{ "type": "api_key", "key": "$MY_ANTHROPIC_KEY" }
|
|
114
|
+
{ "type": "api_key", "key": "${KEY_PREFIX}_${KEY_SUFFIX}" }
|
|
115
|
+
```
|
|
116
|
+
`$FOO_BAR` is the variable `FOO_BAR`; use `${FOO}_BAR` when `BAR` is literal text. Missing environment variables make the value unresolved.
|
|
117
|
+
- **Escapes:** `"$$"` emits a literal `"$"`; `"$!"` emits a literal `"!"` without triggering command execution.
|
|
118
|
+
```json
|
|
119
|
+
{ "type": "api_key", "key": "$$literal-dollar-prefix" }
|
|
120
|
+
{ "type": "api_key", "key": "$!literal-bang-prefix" }
|
|
114
121
|
```
|
|
115
122
|
- **Literal value:** Used directly
|
|
116
123
|
```json
|
|
117
124
|
{ "type": "api_key", "key": "sk-ant-..." }
|
|
125
|
+
{ "type": "api_key", "key": "public" }
|
|
118
126
|
```
|
|
119
127
|
|
|
120
|
-
OAuth credentials are also stored here after `/login` and managed automatically.
|
|
128
|
+
Legacy uppercase env-var-like values such as `MY_API_KEY` are migrated to `$MY_API_KEY` on startup. OAuth credentials are also stored here after `/login` and managed automatically.
|
|
121
129
|
|
|
122
130
|
## Cloud Providers
|
|
123
131
|
|
package/docs/quickstart.md
CHANGED
package/docs/rpc.md
CHANGED
|
@@ -13,6 +13,7 @@ pi --mode rpc [options]
|
|
|
13
13
|
Common options:
|
|
14
14
|
- `--provider <name>`: Set the LLM provider (anthropic, openai, google, etc.)
|
|
15
15
|
- `--model <pattern>`: Model pattern or ID (supports `provider/id` and optional `:<thinking>`)
|
|
16
|
+
- `--name <name>` / `-n <name>`: Set the session display name at startup
|
|
16
17
|
- `--no-session`: Disable session persistence
|
|
17
18
|
- `--session-dir <path>`: Custom session storage directory
|
|
18
19
|
|
|
@@ -694,7 +695,7 @@ Response:
|
|
|
694
695
|
}
|
|
695
696
|
```
|
|
696
697
|
|
|
697
|
-
The current session name is available via `get_state` in the `sessionName` field.
|
|
698
|
+
The current session name is available via `get_state` in the `sessionName` field. To set the initial name when starting RPC mode, pass `--name <name>` or `-n <name>` to the `pi --mode rpc` process.
|
|
698
699
|
|
|
699
700
|
### Commands
|
|
700
701
|
|
package/docs/sdk.md
CHANGED
|
@@ -472,6 +472,7 @@ Specify which built-in tools to enable:
|
|
|
472
472
|
- Default built-ins: `read`, `bash`, `edit`, `write`
|
|
473
473
|
- `noTools: "all"` disables all tools
|
|
474
474
|
- `noTools: "builtin"` disables default built-ins while keeping extension and custom tools enabled
|
|
475
|
+
- `excludeTools` disables specific built-in, extension, or custom tool names after any `tools` allowlist is applied
|
|
475
476
|
|
|
476
477
|
The `edit` tool returns `details.diff` for Pi's TUI display and `details.patch` as a standard unified patch for SDK consumers.
|
|
477
478
|
|
|
@@ -487,6 +488,11 @@ const { session } = await createAgentSession({
|
|
|
487
488
|
const { session } = await createAgentSession({
|
|
488
489
|
tools: ["read", "bash", "grep"],
|
|
489
490
|
});
|
|
491
|
+
|
|
492
|
+
// Disable one tool while keeping the rest available
|
|
493
|
+
const { session } = await createAgentSession({
|
|
494
|
+
excludeTools: ["ask_question"],
|
|
495
|
+
});
|
|
490
496
|
```
|
|
491
497
|
|
|
492
498
|
#### Tools with Custom cwd
|
package/docs/session-format.md
CHANGED
|
@@ -282,7 +282,7 @@ Set `label` to `undefined` to clear a label.
|
|
|
282
282
|
|
|
283
283
|
### SessionInfoEntry
|
|
284
284
|
|
|
285
|
-
Session metadata (e.g., user-defined display name). Set via `/name`
|
|
285
|
+
Session metadata (e.g., user-defined display name). Set via `/name`, `--name` / `-n`, or `pi.setSessionName()` in extensions.
|
|
286
286
|
|
|
287
287
|
```json
|
|
288
288
|
{"type":"session_info","id":"k1l2m3n4","parentId":"j0k1l2m3","timestamp":"2024-12-03T14:35:00.000Z","name":"Refactor auth module"}
|
package/docs/sessions.md
CHANGED
|
@@ -10,6 +10,7 @@ Sessions auto-save to `~/.pi/agent/sessions/`, organized by working directory. E
|
|
|
10
10
|
pi -c # Continue most recent session
|
|
11
11
|
pi -r # Browse and select from past sessions
|
|
12
12
|
pi --no-session # Ephemeral mode; do not save
|
|
13
|
+
pi --name "my task" # Set session display name at startup
|
|
13
14
|
pi --session <path|id> # Use a specific session file or partial session ID
|
|
14
15
|
pi --fork <path|id> # Fork a session file or partial session ID into a new session
|
|
15
16
|
```
|
|
@@ -56,6 +57,13 @@ Use `/name <name>` to set a human-readable session name:
|
|
|
56
57
|
/name Refactor auth module
|
|
57
58
|
```
|
|
58
59
|
|
|
60
|
+
Set the name at startup with `--name` or `-n`:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pi --name "Refactor auth module"
|
|
64
|
+
pi --name "CI audit" -p "Review this build failure"
|
|
65
|
+
```
|
|
66
|
+
|
|
59
67
|
Named sessions are easier to find in `/resume` and `pi -r`.
|
|
60
68
|
|
|
61
69
|
## Branching with `/tree`
|
package/docs/usage.md
CHANGED
|
@@ -76,6 +76,7 @@ Sessions are saved automatically to `~/.pi/agent/sessions/`, organized by workin
|
|
|
76
76
|
pi -c # Continue most recent session
|
|
77
77
|
pi -r # Browse and select a session
|
|
78
78
|
pi --no-session # Ephemeral mode; do not save
|
|
79
|
+
pi --name "my task" # Set session display name at startup
|
|
79
80
|
pi --session <path|id> # Use a specific session file or session ID
|
|
80
81
|
pi --fork <path|id> # Fork a session into a new session file
|
|
81
82
|
```
|
|
@@ -178,12 +179,14 @@ cat README.md | pi -p "Summarize this text"
|
|
|
178
179
|
| `--fork <path\|id>` | Fork a session file or partial UUID into a new session |
|
|
179
180
|
| `--session-dir <dir>` | Custom session storage directory |
|
|
180
181
|
| `--no-session` | Ephemeral mode; do not save |
|
|
182
|
+
| `--name <name>`, `-n <name>` | Set session display name at startup |
|
|
181
183
|
|
|
182
184
|
### Tool Options
|
|
183
185
|
|
|
184
186
|
| Option | Description |
|
|
185
187
|
|--------|-------------|
|
|
186
188
|
| `--tools <list>`, `-t <list>` | Allowlist specific built-in, extension, and custom tools |
|
|
189
|
+
| `--exclude-tools <list>`, `-xt <list>` | Disable specific built-in, extension, and custom tools |
|
|
187
190
|
| `--no-builtin-tools`, `-nbt` | Disable built-in tools but keep extension/custom tools enabled |
|
|
188
191
|
| `--no-tools`, `-nt` | Disable all tools |
|
|
189
192
|
|
|
@@ -241,6 +244,9 @@ pi -p "Summarize this codebase"
|
|
|
241
244
|
# Non-interactive with piped stdin
|
|
242
245
|
cat README.md | pi -p "Summarize this text"
|
|
243
246
|
|
|
247
|
+
# Named one-shot session
|
|
248
|
+
pi --name "release audit" -p "Audit this repository"
|
|
249
|
+
|
|
244
250
|
# Different model
|
|
245
251
|
pi --provider openai --model gpt-4o "Help me refactor"
|
|
246
252
|
|
|
@@ -255,6 +261,9 @@ pi --models "claude-*,gpt-4o"
|
|
|
255
261
|
|
|
256
262
|
# Read-only mode
|
|
257
263
|
pi --tools read,grep,find,ls -p "Review the code"
|
|
264
|
+
|
|
265
|
+
# Disable one extension or built-in tool while keeping the rest available
|
|
266
|
+
pi --exclude-tools ask_question
|
|
258
267
|
```
|
|
259
268
|
|
|
260
269
|
### Environment Variables
|
|
@@ -75,6 +75,7 @@ cp permission-gate.ts ~/.pi/agent/extensions/
|
|
|
75
75
|
| `reload-runtime.ts` | Adds `/reload-runtime` and `reload_runtime` tool showing safe reload flow |
|
|
76
76
|
| `interactive-shell.ts` | Run interactive commands (vim, htop) with full terminal via `user_bash` hook |
|
|
77
77
|
| `inline-bash.ts` | Expands `!{command}` patterns in prompts via `input` event transformation |
|
|
78
|
+
| `input-transform-streaming.ts` | Skips expensive input preprocessing for mid-stream steering via `streamingBehavior` |
|
|
78
79
|
|
|
79
80
|
### Git Integration
|
|
80
81
|
|
|
@@ -568,7 +568,7 @@ function streamCustomAnthropic(
|
|
|
568
568
|
export default function (pi: ExtensionAPI) {
|
|
569
569
|
pi.registerProvider("custom-anthropic", {
|
|
570
570
|
baseUrl: "https://api.anthropic.com",
|
|
571
|
-
apiKey: "CUSTOM_ANTHROPIC_API_KEY",
|
|
571
|
+
apiKey: "$CUSTOM_ANTHROPIC_API_KEY",
|
|
572
572
|
api: "custom-anthropic-api",
|
|
573
573
|
|
|
574
574
|
models: [
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extension-custom-provider",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.77.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-extension-custom-provider",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.77.0",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sdk": "^0.52.0"
|
|
12
12
|
}
|
|
@@ -327,7 +327,7 @@ export function streamGitLabDuo(
|
|
|
327
327
|
export default function (pi: ExtensionAPI) {
|
|
328
328
|
pi.registerProvider("gitlab-duo", {
|
|
329
329
|
baseUrl: AI_GATEWAY_URL,
|
|
330
|
-
apiKey: "GITLAB_TOKEN",
|
|
330
|
+
apiKey: "$GITLAB_TOKEN",
|
|
331
331
|
api: "gitlab-duo-api",
|
|
332
332
|
models: MODELS.map(({ id, name, reasoning, input, cost, contextWindow, maxTokens }) => ({
|
|
333
333
|
id,
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge and Resolve
|
|
3
|
+
*
|
|
4
|
+
* Keeps the working branch up to date with its upstream tracking ref.
|
|
5
|
+
* After each agent turn, fetches and merges. Clean merges complete
|
|
6
|
+
* silently. When conflicts arise, the working tree is left dirty and
|
|
7
|
+
* the agent receives a follow-up message listing each conflict block
|
|
8
|
+
* with file, line range, and ours/theirs sections so it can resolve them.
|
|
9
|
+
* Also re-sends unresolved conflicts from a previous incomplete merge.
|
|
10
|
+
*
|
|
11
|
+
* Start pi with this extension:
|
|
12
|
+
* pi -e ./examples/extensions/git-merge-and-resolve.ts
|
|
13
|
+
*/
|
|
14
|
+
import { createReadStream } from "node:fs";
|
|
15
|
+
import { join } from "node:path";
|
|
16
|
+
import { createInterface } from "node:readline";
|
|
17
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
18
|
+
|
|
19
|
+
interface ConflictBlock {
|
|
20
|
+
file: string;
|
|
21
|
+
startLine: number;
|
|
22
|
+
separatorLine: number;
|
|
23
|
+
endLine: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Parse conflict markers from working tree files with unmerged paths. */
|
|
27
|
+
async function findConflicts(pi: ExtensionAPI, cwd: string): Promise<ConflictBlock[]> {
|
|
28
|
+
const { stdout, code } = await pi.exec("git", ["diff", "--name-only", "--diff-filter=U"]);
|
|
29
|
+
if (code !== 0 || !stdout.trim()) return [];
|
|
30
|
+
|
|
31
|
+
const blocks: ConflictBlock[] = [];
|
|
32
|
+
for (const file of stdout.trim().split("\n")) {
|
|
33
|
+
try {
|
|
34
|
+
const rl = createInterface({ input: createReadStream(join(cwd, file), "utf-8") });
|
|
35
|
+
let lineNo = 0;
|
|
36
|
+
let blockStart: number | undefined;
|
|
37
|
+
let separatorLine: number | undefined;
|
|
38
|
+
for await (const line of rl) {
|
|
39
|
+
lineNo++;
|
|
40
|
+
if (line.startsWith("<<<<<<<")) {
|
|
41
|
+
blockStart = lineNo;
|
|
42
|
+
separatorLine = undefined;
|
|
43
|
+
} else if (line.startsWith("=======") && blockStart !== undefined) {
|
|
44
|
+
separatorLine = lineNo;
|
|
45
|
+
} else if (line.startsWith(">>>>>>>") && blockStart !== undefined && separatorLine !== undefined) {
|
|
46
|
+
blocks.push({ file, startLine: blockStart, separatorLine, endLine: lineNo });
|
|
47
|
+
blockStart = undefined;
|
|
48
|
+
separatorLine = undefined;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
} catch {}
|
|
52
|
+
}
|
|
53
|
+
return blocks;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function formatRange(start: number, end: number): string {
|
|
57
|
+
if (start > end) return "empty";
|
|
58
|
+
if (start === end) return `${start}`;
|
|
59
|
+
return `${start}-${end}`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function formatConflicts(ref: string, blocks: ConflictBlock[]): string {
|
|
63
|
+
const lines = [`Merged ${ref} with conflicts:`, ""];
|
|
64
|
+
for (const b of blocks) {
|
|
65
|
+
const ours = formatRange(b.startLine + 1, b.separatorLine - 1);
|
|
66
|
+
const theirs = formatRange(b.separatorLine + 1, b.endLine - 1);
|
|
67
|
+
lines.push(` ${b.file}:${b.startLine}-${b.endLine} (ours ${ours}, theirs ${theirs})`);
|
|
68
|
+
}
|
|
69
|
+
lines.push("", "Resolve these conflicts.");
|
|
70
|
+
return lines.join("\n");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export default function (pi: ExtensionAPI) {
|
|
74
|
+
pi.on("agent_end", async (_event, ctx) => {
|
|
75
|
+
const { code: revParseCode } = await pi.exec("git", ["rev-parse", "--git-dir"]);
|
|
76
|
+
if (revParseCode !== 0) return;
|
|
77
|
+
|
|
78
|
+
let ref = "MERGE_HEAD";
|
|
79
|
+
|
|
80
|
+
// If not already in a merge, attempt one
|
|
81
|
+
const { code: mergeHeadCode } = await pi.exec("git", ["rev-parse", "MERGE_HEAD"]);
|
|
82
|
+
if (mergeHeadCode !== 0) {
|
|
83
|
+
// Only attempt a new merge if the working tree is clean
|
|
84
|
+
const { stdout: status } = await pi.exec("git", ["status", "--porcelain"]);
|
|
85
|
+
if (status.trim()) return;
|
|
86
|
+
|
|
87
|
+
const { stdout: upstream, code: upstreamCode } = await pi.exec("git", [
|
|
88
|
+
"rev-parse",
|
|
89
|
+
"--abbrev-ref",
|
|
90
|
+
"--symbolic-full-name",
|
|
91
|
+
"@{u}",
|
|
92
|
+
]);
|
|
93
|
+
if (upstreamCode !== 0) return;
|
|
94
|
+
|
|
95
|
+
ref = upstream.trim();
|
|
96
|
+
const remote = ref.split("/")[0];
|
|
97
|
+
ctx.ui.notify(`git-merge-and-resolve: fetching ${remote}, merging ${ref}`, "info");
|
|
98
|
+
|
|
99
|
+
const { code: fetchCode, stderr: fetchErr } = await pi.exec("git", ["fetch", remote]);
|
|
100
|
+
if (fetchCode !== 0) {
|
|
101
|
+
ctx.ui.notify(`git-merge-and-resolve: fetch failed: ${fetchErr.trim()}`, "warning");
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const { code: mergeCode } = await pi.exec("git", ["merge", "--no-ff", ref]);
|
|
106
|
+
if (mergeCode === 0) return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Either we just merged with conflicts, or we were already in an unfinished merge
|
|
110
|
+
const conflicts = await findConflicts(pi, ctx.cwd);
|
|
111
|
+
if (conflicts.length === 0) return;
|
|
112
|
+
|
|
113
|
+
pi.sendUserMessage(formatConflicts(ref, conflicts), { deliverAs: "followUp" });
|
|
114
|
+
});
|
|
115
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Streaming-Aware Input Gate
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates `event.streamingBehavior` to skip expensive pre-processing
|
|
5
|
+
* during mid-stream steering, where low latency matters.
|
|
6
|
+
*
|
|
7
|
+
* This extension prepends `git diff --stat` output when the user mentions
|
|
8
|
+
* file changes, giving the model immediate context. During steering the
|
|
9
|
+
* exec call is skipped so the correction reaches the model without delay.
|
|
10
|
+
*
|
|
11
|
+
* Start pi with this extension:
|
|
12
|
+
* pi -e ./examples/extensions/input-transform-streaming.ts
|
|
13
|
+
*/
|
|
14
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
15
|
+
|
|
16
|
+
const TRIGGER = /\b(changes?|diff|modified)\b/i;
|
|
17
|
+
|
|
18
|
+
export default function (pi: ExtensionAPI) {
|
|
19
|
+
pi.on("input", async (event) => {
|
|
20
|
+
// During steering, skip the exec call — corrections should be fast
|
|
21
|
+
if (event.streamingBehavior === "steer") {
|
|
22
|
+
return { action: "continue" };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!TRIGGER.test(event.text)) {
|
|
26
|
+
return { action: "continue" };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const { stdout, code } = await pi.exec("git", ["diff", "--stat"]);
|
|
30
|
+
if (code !== 0 || !stdout.trim()) {
|
|
31
|
+
return { action: "continue" };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
action: "transform",
|
|
36
|
+
text: `${event.text}\n\nCurrent uncommitted changes:\n\`\`\`\n${stdout.trim()}\n\`\`\``,
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extension-sandbox",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-extension-sandbox",
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.7.0",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sandbox-runtime": "^0.0.26"
|
|
12
12
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extension-with-deps",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.77.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-extension-with-deps",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.77.0",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"ms": "^2.1.3"
|
|
12
12
|
},
|