@earendil-works/pi-coding-agent 0.74.0 → 0.74.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 +48 -0
- package/README.md +8 -6
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +1 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +10 -2
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +23 -20
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +2 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +1 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +2 -2
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +1 -0
- 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 -0
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/package-manager.d.ts +1 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +45 -7
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +6 -4
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/provider-display-names.d.ts.map +1 -1
- package/dist/core/provider-display-names.js +1 -0
- package/dist/core/provider-display-names.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 +1 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +39 -9
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +2 -5
- package/dist/core/skills.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +2 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js +1 -1
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +0 -10
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +1 -1
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +23 -1
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts +2 -0
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +6 -1
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts +5 -0
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js +19 -5
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +3 -1
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +2 -1
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +12 -4
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +74 -30
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/dark.json +1 -1
- package/dist/modes/interactive/theme/light.json +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +3 -1
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +6 -1
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/utils/ansi.d.ts +2 -0
- package/dist/utils/ansi.d.ts.map +1 -0
- package/dist/utils/ansi.js +52 -0
- package/dist/utils/ansi.js.map +1 -0
- package/dist/utils/html.d.ts +7 -0
- package/dist/utils/html.d.ts.map +1 -0
- package/dist/utils/html.js +40 -0
- package/dist/utils/html.js.map +1 -0
- package/dist/utils/mime.d.ts +1 -0
- package/dist/utils/mime.d.ts.map +1 -1
- package/dist/utils/mime.js +59 -16
- package/dist/utils/mime.js.map +1 -1
- package/dist/utils/paths.d.ts +2 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +16 -0
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/syntax-highlight.d.ts +12 -0
- package/dist/utils/syntax-highlight.d.ts.map +1 -0
- package/dist/utils/syntax-highlight.js +118 -0
- package/dist/utils/syntax-highlight.js.map +1 -0
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +80 -8
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/version-check.d.ts +4 -0
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +14 -0
- package/dist/utils/version-check.js.map +1 -1
- package/docs/custom-provider.md +58 -3
- package/docs/extensions.md +1 -1
- package/docs/index.md +7 -1
- package/docs/models.md +2 -2
- package/docs/providers.md +2 -0
- package/docs/sdk.md +24 -44
- package/docs/skills.md +3 -4
- package/docs/termux.md +3 -3
- package/docs/themes.md +2 -2
- 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/dynamic-resources/dynamic.json +1 -1
- 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/examples/sdk/01-minimal.ts +14 -10
- package/examples/sdk/02-custom-model.ts +12 -8
- package/examples/sdk/03-custom-prompt.ts +24 -16
- package/examples/sdk/04-skills.ts +2 -2
- package/examples/sdk/05-tools.ts +8 -4
- package/examples/sdk/06-extensions.ts +11 -7
- package/examples/sdk/07-context-files.ts +2 -2
- package/examples/sdk/08-prompt-templates.ts +2 -2
- package/examples/sdk/09-api-keys-and-oauth.ts +8 -4
- package/examples/sdk/10-settings.ts +4 -4
- package/examples/sdk/11-sessions.ts +4 -0
- package/examples/sdk/12-full-control.ts +11 -7
- package/examples/sdk/README.md +5 -8
- package/package.json +6 -11
package/docs/custom-provider.md
CHANGED
|
@@ -23,6 +23,7 @@ See these complete provider examples:
|
|
|
23
23
|
- [Unregister Provider](#unregister-provider)
|
|
24
24
|
- [OAuth Support](#oauth-support)
|
|
25
25
|
- [Custom Streaming API](#custom-streaming-api)
|
|
26
|
+
- [Context Overflow Errors](#context-overflow-errors)
|
|
26
27
|
- [Testing Your Implementation](#testing-your-implementation)
|
|
27
28
|
- [Config Reference](#config-reference)
|
|
28
29
|
- [Model Definition Reference](#model-definition-reference)
|
|
@@ -226,7 +227,7 @@ models: [{
|
|
|
226
227
|
}]
|
|
227
228
|
```
|
|
228
229
|
|
|
229
|
-
Use `qwen-chat-template` instead for local Qwen-compatible servers that read `chat_template_kwargs.enable_thinking`.
|
|
230
|
+
Use `openrouter` for OpenRouter-style `reasoning: { effort }` controls. Use `together` for Together-style `reasoning: { enabled }` controls; with `supportsReasoningEffort`, it also sends `reasoning_effort`. Use `qwen-chat-template` instead for local Qwen-compatible servers that read `chat_template_kwargs.enable_thinking`.
|
|
230
231
|
Use `cacheControlFormat: "anthropic"` for OpenAI-compatible providers that expose Anthropic-style prompt caching via `cache_control` on the system prompt, last tool definition, and last user/assistant text content.
|
|
231
232
|
|
|
232
233
|
> Migration note: Mistral moved from `openai-completions` to `mistral-conversations`.
|
|
@@ -506,6 +507,60 @@ output.usage.totalTokens = output.usage.input + output.usage.output +
|
|
|
506
507
|
calculateCost(model, output.usage);
|
|
507
508
|
```
|
|
508
509
|
|
|
510
|
+
### Context Overflow Errors
|
|
511
|
+
|
|
512
|
+
When a request exceeds the model's context window, pi can recover automatically by compacting the conversation and retrying. This recovery only kicks in if pi recognizes the failure as an overflow.
|
|
513
|
+
|
|
514
|
+
Detection runs on the finalized assistant message:
|
|
515
|
+
|
|
516
|
+
- `stopReason === "error"`
|
|
517
|
+
- `errorMessage` matches one of pi's known overflow patterns (see [`packages/ai/src/utils/overflow.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/ai/src/utils/overflow.ts))
|
|
518
|
+
|
|
519
|
+
If your provider returns overflow errors with a message pi does not recognize, normalize the error from the same extension that registers the provider. Use a `message_end` handler to rewrite the assistant message so its `errorMessage` starts with a phrase pi recognizes. The generic fallback `context_length_exceeded` is the safest choice.
|
|
520
|
+
|
|
521
|
+
```typescript
|
|
522
|
+
const MY_PROVIDER_OVERFLOW_PATTERN = /your provider's overflow phrase/i;
|
|
523
|
+
|
|
524
|
+
export default function (pi: ExtensionAPI) {
|
|
525
|
+
pi.registerProvider("my-provider", { /* ... */ });
|
|
526
|
+
|
|
527
|
+
pi.on("message_end", (event, ctx) => {
|
|
528
|
+
const message = event.message;
|
|
529
|
+
if (message.role !== "assistant") return;
|
|
530
|
+
if (message.stopReason !== "error") return;
|
|
531
|
+
if (
|
|
532
|
+
message.provider !== "my-provider" &&
|
|
533
|
+
ctx.model?.provider !== "my-provider"
|
|
534
|
+
)
|
|
535
|
+
return;
|
|
536
|
+
|
|
537
|
+
const errorMessage = message.errorMessage ?? "";
|
|
538
|
+
if (errorMessage.includes("context_length_exceeded")) return;
|
|
539
|
+
if (!MY_PROVIDER_OVERFLOW_PATTERN.test(errorMessage)) return;
|
|
540
|
+
|
|
541
|
+
return {
|
|
542
|
+
message: {
|
|
543
|
+
...message,
|
|
544
|
+
errorMessage: `context_length_exceeded: ${errorMessage}`,
|
|
545
|
+
},
|
|
546
|
+
};
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
`message_end` runs before pi tracks the assistant message for auto-compaction, so the rewritten `errorMessage` is what pi checks. With this in place, pi will:
|
|
552
|
+
|
|
553
|
+
1. Detect the overflow from `errorMessage`.
|
|
554
|
+
2. Drop the failed assistant message from live context.
|
|
555
|
+
3. Run compaction.
|
|
556
|
+
4. Retry the request once.
|
|
557
|
+
|
|
558
|
+
Guard the rewrite carefully:
|
|
559
|
+
|
|
560
|
+
- Scope it to your provider (`message.provider` and `ctx.model?.provider`) so unrelated errors from other providers are untouched.
|
|
561
|
+
- Match a provider-specific pattern, not pi's generic overflow patterns. Rewriting rate-limit or throttling errors (`rate limit`, `too many requests`) would falsely trigger compaction instead of pi's normal retry-with-backoff path.
|
|
562
|
+
- Skip when `errorMessage` already includes `context_length_exceeded` so the handler is idempotent.
|
|
563
|
+
|
|
509
564
|
### Registration
|
|
510
565
|
|
|
511
566
|
Register your stream function:
|
|
@@ -636,11 +691,11 @@ interface ProviderModelConfig {
|
|
|
636
691
|
requiresAssistantAfterToolResult?: boolean;
|
|
637
692
|
requiresThinkingAsText?: boolean;
|
|
638
693
|
requiresReasoningContentOnAssistantMessages?: boolean;
|
|
639
|
-
thinkingFormat?: "openai" | "deepseek" | "zai" | "qwen" | "qwen-chat-template";
|
|
694
|
+
thinkingFormat?: "openai" | "openrouter" | "deepseek" | "together" | "zai" | "qwen" | "qwen-chat-template";
|
|
640
695
|
cacheControlFormat?: "anthropic";
|
|
641
696
|
};
|
|
642
697
|
}
|
|
643
698
|
```
|
|
644
699
|
|
|
645
|
-
`deepseek` sends `thinking: { type: "enabled" | "disabled" }` and `reasoning_effort` when enabled. `qwen` is for DashScope-style top-level `enable_thinking`. Use `qwen-chat-template` for local Qwen-compatible servers that read `chat_template_kwargs.enable_thinking`.
|
|
700
|
+
`openrouter` sends `reasoning: { effort }`. `deepseek` sends `thinking: { type: "enabled" | "disabled" }` and `reasoning_effort` when enabled. `together` sends `reasoning: { enabled }` and also `reasoning_effort` when `supportsReasoningEffort` is enabled. `qwen` is for DashScope-style top-level `enable_thinking`. Use `qwen-chat-template` for local Qwen-compatible servers that read `chat_template_kwargs.enable_thinking`.
|
|
646
701
|
`cacheControlFormat: "anthropic"` applies Anthropic-style `cache_control` markers to the system prompt, last tool definition, and last user/assistant text content.
|
package/docs/extensions.md
CHANGED
|
@@ -162,7 +162,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
162
162
|
pi.on("event_name", async (event, ctx) => {
|
|
163
163
|
// ctx.ui for user interaction
|
|
164
164
|
const ok = await ctx.ui.confirm("Title", "Are you sure?");
|
|
165
|
-
ctx.ui.notify("Done!", "
|
|
165
|
+
ctx.ui.notify("Done!", "info");
|
|
166
166
|
ctx.ui.setStatus("my-ext", "Processing..."); // Footer status
|
|
167
167
|
ctx.ui.setWidget("my-ext", ["Line 1", "Line 2"]); // Widget above editor (default)
|
|
168
168
|
});
|
package/docs/index.md
CHANGED
|
@@ -4,7 +4,13 @@ Pi is a minimal terminal coding harness. It is designed to stay small at the cor
|
|
|
4
4
|
|
|
5
5
|
## Quick start
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
On linux or mac you can install Pi with curl:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
curl -fsSL https://pi.dev/install.sh | sh
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or alternatively with npm:
|
|
8
14
|
|
|
9
15
|
```bash
|
|
10
16
|
npm install -g @earendil-works/pi-coding-agent
|
package/docs/models.md
CHANGED
|
@@ -381,14 +381,14 @@ For providers with partial OpenAI compatibility, use the `compat` field.
|
|
|
381
381
|
| `requiresAssistantAfterToolResult` | Insert an assistant message before a user message after tool results |
|
|
382
382
|
| `requiresThinkingAsText` | Convert thinking blocks to plain text |
|
|
383
383
|
| `requiresReasoningContentOnAssistantMessages` | Include empty `reasoning_content` on all replayed assistant messages when reasoning is enabled |
|
|
384
|
-
| `thinkingFormat` | Use `reasoning_effort`, `deepseek`, `zai`, `qwen`, or `qwen-chat-template` thinking parameters |
|
|
384
|
+
| `thinkingFormat` | Use `reasoning_effort`, `openrouter`, `deepseek`, `together`, `zai`, `qwen`, or `qwen-chat-template` thinking parameters |
|
|
385
385
|
| `cacheControlFormat` | Use Anthropic-style `cache_control` markers on the system prompt, last tool definition, and last user/assistant text content. Currently only `anthropic` is supported. |
|
|
386
386
|
| `supportsStrictMode` | Include the `strict` field in tool definitions |
|
|
387
387
|
| `supportsLongCacheRetention` | Whether the provider accepts long cache retention when cache retention is `long`: `prompt_cache_retention: "24h"` for OpenAI prompt caching, or `cache_control.ttl: "1h"` when `cacheControlFormat` is `anthropic`. Default: `true`. |
|
|
388
388
|
| `openRouterRouting` | OpenRouter provider routing preferences. This object is sent as-is in the `provider` field of the [OpenRouter API request](https://openrouter.ai/docs/guides/routing/provider-selection). |
|
|
389
389
|
| `vercelGatewayRouting` | Vercel AI Gateway routing config for provider selection (`only`, `order`) |
|
|
390
390
|
|
|
391
|
-
`qwen` uses top-level `enable_thinking`. Use `qwen-chat-template` for local Qwen-compatible servers that require `chat_template_kwargs.enable_thinking`.
|
|
391
|
+
`openrouter` uses `reasoning: { effort }`. `together` uses `reasoning: { enabled }` and also `reasoning_effort` when `supportsReasoningEffort` is enabled. `qwen` uses top-level `enable_thinking`. Use `qwen-chat-template` for local Qwen-compatible servers that require `chat_template_kwargs.enable_thinking`.
|
|
392
392
|
|
|
393
393
|
`cacheControlFormat: "anthropic"` is for OpenAI-compatible providers that expose Anthropic-style prompt caching through `cache_control` markers on text content and tool definitions.
|
|
394
394
|
|
package/docs/providers.md
CHANGED
|
@@ -66,6 +66,7 @@ pi
|
|
|
66
66
|
| OpenCode Go | `OPENCODE_API_KEY` | `opencode-go` |
|
|
67
67
|
| Hugging Face | `HF_TOKEN` | `huggingface` |
|
|
68
68
|
| Fireworks | `FIREWORKS_API_KEY` | `fireworks` |
|
|
69
|
+
| Together AI | `TOGETHER_API_KEY` | `together` |
|
|
69
70
|
| Kimi For Coding | `KIMI_API_KEY` | `kimi-coding` |
|
|
70
71
|
| MiniMax | `MINIMAX_API_KEY` | `minimax` |
|
|
71
72
|
| MiniMax (China) | `MINIMAX_CN_API_KEY` | `minimax-cn` |
|
|
@@ -88,6 +89,7 @@ Store credentials in `~/.pi/agent/auth.json`:
|
|
|
88
89
|
"google": { "type": "api_key", "key": "..." },
|
|
89
90
|
"opencode": { "type": "api_key", "key": "..." },
|
|
90
91
|
"opencode-go": { "type": "api_key", "key": "..." },
|
|
92
|
+
"together": { "type": "api_key", "key": "..." },
|
|
91
93
|
"xiaomi": { "type": "api_key", "key": "..." },
|
|
92
94
|
"xiaomi-token-plan-cn": { "type": "api_key", "key": "..." },
|
|
93
95
|
"xiaomi-token-plan-ams": { "type": "api_key", "key": "..." },
|
package/docs/sdk.md
CHANGED
|
@@ -54,7 +54,7 @@ The main factory function for a single `AgentSession`.
|
|
|
54
54
|
`createAgentSession()` uses a `ResourceLoader` to supply extensions, skills, prompt templates, themes, and context files. If you do not provide one, it uses `DefaultResourceLoader` with standard discovery.
|
|
55
55
|
|
|
56
56
|
```typescript
|
|
57
|
-
import { createAgentSession } from "@earendil-works/pi-coding-agent";
|
|
57
|
+
import { createAgentSession, SessionManager } from "@earendil-works/pi-coding-agent";
|
|
58
58
|
|
|
59
59
|
// Minimal: defaults with DefaultResourceLoader
|
|
60
60
|
const { session } = await createAgentSession();
|
|
@@ -62,7 +62,7 @@ const { session } = await createAgentSession();
|
|
|
62
62
|
// Custom: override specific options
|
|
63
63
|
const { session } = await createAgentSession({
|
|
64
64
|
model: myModel,
|
|
65
|
-
tools: [
|
|
65
|
+
tools: ["read", "bash"],
|
|
66
66
|
sessionManager: SessionManager.inMemory(),
|
|
67
67
|
});
|
|
68
68
|
```
|
|
@@ -466,64 +466,50 @@ const { session } = await createAgentSession({ resourceLoader: loader });
|
|
|
466
466
|
|
|
467
467
|
### Tools
|
|
468
468
|
|
|
469
|
+
Specify which built-in tools to enable:
|
|
470
|
+
|
|
471
|
+
- Built-in tool names: `read`, `bash`, `edit`, `write`, `grep`, `find`, `ls`
|
|
472
|
+
- Default built-ins: `read`, `bash`, `edit`, `write`
|
|
473
|
+
- `noTools: "all"` disables all tools
|
|
474
|
+
- `noTools: "builtin"` disables default built-ins while keeping extension and custom tools enabled
|
|
475
|
+
|
|
469
476
|
```typescript
|
|
470
|
-
import {
|
|
471
|
-
codingTools, // read, bash, edit, write (default)
|
|
472
|
-
readOnlyTools, // read, grep, find, ls
|
|
473
|
-
readTool, bashTool, editTool, writeTool,
|
|
474
|
-
grepTool, findTool, lsTool,
|
|
475
|
-
} from "@earendil-works/pi-coding-agent";
|
|
477
|
+
import { createAgentSession } from "@earendil-works/pi-coding-agent";
|
|
476
478
|
|
|
477
|
-
//
|
|
479
|
+
// Read-only mode
|
|
478
480
|
const { session } = await createAgentSession({
|
|
479
|
-
tools:
|
|
481
|
+
tools: ["read", "grep", "find", "ls"],
|
|
480
482
|
});
|
|
481
483
|
|
|
482
484
|
// Pick specific tools
|
|
483
485
|
const { session } = await createAgentSession({
|
|
484
|
-
tools: [
|
|
486
|
+
tools: ["read", "bash", "grep"],
|
|
485
487
|
});
|
|
486
488
|
```
|
|
487
489
|
|
|
488
490
|
#### Tools with Custom cwd
|
|
489
491
|
|
|
490
|
-
|
|
492
|
+
When you pass a custom `cwd`, `createAgentSession()` builds selected built-in tools for that cwd.
|
|
491
493
|
|
|
492
494
|
```typescript
|
|
493
|
-
import {
|
|
494
|
-
createCodingTools, // Creates [read, bash, edit, write] for specific cwd
|
|
495
|
-
createReadOnlyTools, // Creates [read, grep, find, ls] for specific cwd
|
|
496
|
-
createReadTool,
|
|
497
|
-
createBashTool,
|
|
498
|
-
createEditTool,
|
|
499
|
-
createWriteTool,
|
|
500
|
-
createGrepTool,
|
|
501
|
-
createFindTool,
|
|
502
|
-
createLsTool,
|
|
503
|
-
} from "@earendil-works/pi-coding-agent";
|
|
495
|
+
import { createAgentSession, SessionManager } from "@earendil-works/pi-coding-agent";
|
|
504
496
|
|
|
505
497
|
const cwd = "/path/to/project";
|
|
506
498
|
|
|
507
|
-
// Use
|
|
499
|
+
// Use default tools for custom cwd
|
|
508
500
|
const { session } = await createAgentSession({
|
|
509
501
|
cwd,
|
|
510
|
-
|
|
502
|
+
sessionManager: SessionManager.inMemory(cwd),
|
|
511
503
|
});
|
|
512
504
|
|
|
513
|
-
// Or pick specific tools
|
|
505
|
+
// Or pick specific tools for custom cwd
|
|
514
506
|
const { session } = await createAgentSession({
|
|
515
507
|
cwd,
|
|
516
|
-
tools: [
|
|
508
|
+
tools: ["read", "bash", "grep"],
|
|
509
|
+
sessionManager: SessionManager.inMemory(cwd),
|
|
517
510
|
});
|
|
518
511
|
```
|
|
519
512
|
|
|
520
|
-
**When you don't need factories:**
|
|
521
|
-
- If you omit `tools`, pi automatically creates them with the correct `cwd`
|
|
522
|
-
- If you use `process.cwd()` as your `cwd`, the pre-built instances work fine
|
|
523
|
-
|
|
524
|
-
**When you must use factories:**
|
|
525
|
-
- When you specify both `cwd` (different from `process.cwd()`) AND `tools`
|
|
526
|
-
|
|
527
513
|
> See [examples/sdk/05-tools.ts](../examples/sdk/05-tools.ts)
|
|
528
514
|
|
|
529
515
|
### Custom Tools
|
|
@@ -556,6 +542,8 @@ Use `defineTool()` for standalone definitions and arrays like `customTools: [myT
|
|
|
556
542
|
|
|
557
543
|
Custom tools passed via `customTools` are combined with extension-registered tools. Extensions loaded by the ResourceLoader can also register tools via `pi.registerTool()`.
|
|
558
544
|
|
|
545
|
+
If you pass `tools`, include each custom or extension tool name you want enabled, for example `tools: ["read", "bash", "my_tool"]`.
|
|
546
|
+
|
|
559
547
|
> See [examples/sdk/05-tools.ts](../examples/sdk/05-tools.ts)
|
|
560
548
|
|
|
561
549
|
### Extensions
|
|
@@ -885,12 +873,10 @@ import { getModel } from "@earendil-works/pi-ai";
|
|
|
885
873
|
import { Type } from "typebox";
|
|
886
874
|
import {
|
|
887
875
|
AuthStorage,
|
|
888
|
-
bashTool,
|
|
889
876
|
createAgentSession,
|
|
890
877
|
DefaultResourceLoader,
|
|
891
878
|
defineTool,
|
|
892
879
|
ModelRegistry,
|
|
893
|
-
readTool,
|
|
894
880
|
SessionManager,
|
|
895
881
|
SettingsManager,
|
|
896
882
|
} from "@earendil-works/pi-coding-agent";
|
|
@@ -944,7 +930,7 @@ const { session } = await createAgentSession({
|
|
|
944
930
|
authStorage,
|
|
945
931
|
modelRegistry,
|
|
946
932
|
|
|
947
|
-
tools: [
|
|
933
|
+
tools: ["read", "bash", "status"],
|
|
948
934
|
customTools: [statusTool],
|
|
949
935
|
resourceLoader: loader,
|
|
950
936
|
|
|
@@ -1123,13 +1109,7 @@ defineTool
|
|
|
1123
1109
|
SessionManager
|
|
1124
1110
|
SettingsManager
|
|
1125
1111
|
|
|
1126
|
-
//
|
|
1127
|
-
codingTools
|
|
1128
|
-
readOnlyTools
|
|
1129
|
-
readTool, bashTool, editTool, writeTool
|
|
1130
|
-
grepTool, findTool, lsTool
|
|
1131
|
-
|
|
1132
|
-
// Tool factories (for custom cwd)
|
|
1112
|
+
// Tool factories
|
|
1133
1113
|
createCodingTools
|
|
1134
1114
|
createReadOnlyTools
|
|
1135
1115
|
createReadTool, createBashTool, createEditTool, createWriteTool
|
package/docs/skills.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
Skills are self-contained capability packages that the agent loads on-demand. A skill provides specialized workflows, setup instructions, helper scripts, and reference documentation for specific tasks.
|
|
6
6
|
|
|
7
|
-
Pi implements the [Agent Skills standard](https://agentskills.io/specification), warning about violations but remaining lenient.
|
|
7
|
+
Pi implements the [Agent Skills standard](https://agentskills.io/specification), warning about most violations but remaining lenient. Pi allows skill names to differ from their parent directory even though the standard disallows it; that rule is suboptimal for shared skill directories used across multiple agent harnesses.
|
|
8
8
|
|
|
9
9
|
## Table of Contents
|
|
10
10
|
|
|
@@ -140,7 +140,7 @@ Per the [Agent Skills specification](https://agentskills.io/specification#frontm
|
|
|
140
140
|
|
|
141
141
|
| Field | Required | Description |
|
|
142
142
|
|-------|----------|-------------|
|
|
143
|
-
| `name` | Yes | Max 64 chars. Lowercase a-z, 0-9, hyphens.
|
|
143
|
+
| `name` | Yes | Max 64 chars. Lowercase a-z, 0-9, hyphens. Unlike the standard, Pi does not require this to match the parent directory because that standard requirement is suboptimal for shared skill directories. |
|
|
144
144
|
| `description` | Yes | Max 1024 chars. What the skill does and when to use it. |
|
|
145
145
|
| `license` | No | License name or reference to bundled file. |
|
|
146
146
|
| `compatibility` | No | Max 500 chars. Environment requirements. |
|
|
@@ -154,7 +154,7 @@ Per the [Agent Skills specification](https://agentskills.io/specification#frontm
|
|
|
154
154
|
- Lowercase letters, numbers, hyphens only
|
|
155
155
|
- No leading/trailing hyphens
|
|
156
156
|
- No consecutive hyphens
|
|
157
|
-
|
|
157
|
+
Pi does not require the name to match the parent directory. The Agent Skills standard does, but that requirement is suboptimal for shared skill directories used by multiple tools.
|
|
158
158
|
|
|
159
159
|
Valid: `pdf-processing`, `data-analysis`, `code-review`
|
|
160
160
|
Invalid: `PDF-Processing`, `-pdf`, `pdf--processing`
|
|
@@ -177,7 +177,6 @@ description: Helps with PDFs.
|
|
|
177
177
|
|
|
178
178
|
Pi validates skills against the Agent Skills standard. Most issues produce warnings but still load the skill:
|
|
179
179
|
|
|
180
|
-
- Name doesn't match parent directory
|
|
181
180
|
- Name exceeds 64 characters or contains invalid characters
|
|
182
181
|
- Name starts/ends with hyphen or has consecutive hyphens
|
|
183
182
|
- Description exceeds 1024 characters
|
package/docs/termux.md
CHANGED
|
@@ -36,7 +36,7 @@ Image clipboard is not supported on Termux (the `ctrl+v` image paste feature wil
|
|
|
36
36
|
|
|
37
37
|
Create `~/.pi/agent/AGENTS.md` to help the agent understand the Termux environment:
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
````markdown
|
|
40
40
|
# Agent Environment: Termux on Android
|
|
41
41
|
|
|
42
42
|
## Location
|
|
@@ -53,7 +53,7 @@ termux-open-url "https://example.com"
|
|
|
53
53
|
## Opening Files
|
|
54
54
|
```bash
|
|
55
55
|
termux-open file.pdf # Opens with default app
|
|
56
|
-
termux-open
|
|
56
|
+
termux-open --chooser image.jpg # Choose app
|
|
57
57
|
```
|
|
58
58
|
|
|
59
59
|
## Clipboard
|
|
@@ -91,7 +91,7 @@ termux-camera-photo out.jpg # Take photo
|
|
|
91
91
|
- Termux:API app must be installed for `termux-*` commands
|
|
92
92
|
- Use `pkg install termux-api` for the command-line tools
|
|
93
93
|
- Storage permission needed for `/storage/emulated/0` access
|
|
94
|
-
|
|
94
|
+
````
|
|
95
95
|
|
|
96
96
|
## Limitations
|
|
97
97
|
|
package/docs/themes.md
CHANGED
|
@@ -52,7 +52,7 @@ vim ~/.pi/agent/themes/my-theme.json
|
|
|
52
52
|
|
|
53
53
|
```json
|
|
54
54
|
{
|
|
55
|
-
"$schema": "https://raw.githubusercontent.com/earendil-works/pi
|
|
55
|
+
"$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
|
56
56
|
"name": "my-theme",
|
|
57
57
|
"vars": {
|
|
58
58
|
"primary": "#00aaff",
|
|
@@ -122,7 +122,7 @@ vim ~/.pi/agent/themes/my-theme.json
|
|
|
122
122
|
|
|
123
123
|
```json
|
|
124
124
|
{
|
|
125
|
-
"$schema": "https://raw.githubusercontent.com/earendil-works/pi
|
|
125
|
+
"$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
|
126
126
|
"name": "my-theme",
|
|
127
127
|
"vars": {
|
|
128
128
|
"blue": "#0066cc",
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extension-custom-provider",
|
|
3
|
-
"version": "0.74.
|
|
3
|
+
"version": "0.74.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-extension-custom-provider",
|
|
9
|
-
"version": "0.74.
|
|
9
|
+
"version": "0.74.1",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sdk": "^0.52.0"
|
|
12
12
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "https://raw.githubusercontent.com/earendil-works/pi
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
|
3
3
|
"name": "dynamic-resources",
|
|
4
4
|
"vars": {
|
|
5
5
|
"cyan": "#00d7ff",
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extension-sandbox",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-extension-sandbox",
|
|
9
|
-
"version": "1.4.
|
|
9
|
+
"version": "1.4.1",
|
|
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.74.
|
|
3
|
+
"version": "0.74.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-extension-with-deps",
|
|
9
|
-
"version": "0.74.
|
|
9
|
+
"version": "0.74.1",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"ms": "^2.1.3"
|
|
12
12
|
},
|
|
@@ -9,14 +9,18 @@ import { createAgentSession } from "@earendil-works/pi-coding-agent";
|
|
|
9
9
|
|
|
10
10
|
const { session } = await createAgentSession();
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
12
|
+
try {
|
|
13
|
+
session.subscribe((event) => {
|
|
14
|
+
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
|
15
|
+
process.stdout.write(event.assistantMessageEvent.delta);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
17
18
|
|
|
18
|
-
await session.prompt("What files are in the current directory?");
|
|
19
|
-
session.state.messages.forEach((msg) => {
|
|
20
|
-
|
|
21
|
-
});
|
|
22
|
-
console.log();
|
|
19
|
+
await session.prompt("What files are in the current directory?");
|
|
20
|
+
session.state.messages.forEach((msg) => {
|
|
21
|
+
console.log(msg);
|
|
22
|
+
});
|
|
23
|
+
console.log();
|
|
24
|
+
} finally {
|
|
25
|
+
session.dispose();
|
|
26
|
+
}
|
|
@@ -38,12 +38,16 @@ if (available.length > 0) {
|
|
|
38
38
|
modelRegistry,
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
41
|
+
try {
|
|
42
|
+
session.subscribe((event) => {
|
|
43
|
+
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
|
44
|
+
process.stdout.write(event.assistantMessageEvent.delta);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
await session.prompt("Say hello in one sentence.");
|
|
49
|
+
console.log();
|
|
50
|
+
} finally {
|
|
51
|
+
session.dispose();
|
|
52
|
+
}
|
|
49
53
|
}
|
|
@@ -30,15 +30,19 @@ const { session: session1 } = await createAgentSession({
|
|
|
30
30
|
sessionManager: SessionManager.inMemory(),
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
33
|
+
try {
|
|
34
|
+
session1.subscribe((event) => {
|
|
35
|
+
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
|
36
|
+
process.stdout.write(event.assistantMessageEvent.delta);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
38
39
|
|
|
39
|
-
console.log("=== Replace prompt ===");
|
|
40
|
-
await session1.prompt("What is 2 + 2?");
|
|
41
|
-
console.log("\n");
|
|
40
|
+
console.log("=== Replace prompt ===");
|
|
41
|
+
await session1.prompt("What is 2 + 2?");
|
|
42
|
+
console.log("\n");
|
|
43
|
+
} finally {
|
|
44
|
+
session1.dispose();
|
|
45
|
+
}
|
|
42
46
|
|
|
43
47
|
// Option 2: Append instructions to the default prompt
|
|
44
48
|
const loader2 = new DefaultResourceLoader({
|
|
@@ -56,12 +60,16 @@ const { session: session2 } = await createAgentSession({
|
|
|
56
60
|
sessionManager: SessionManager.inMemory(),
|
|
57
61
|
});
|
|
58
62
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
63
|
+
try {
|
|
64
|
+
session2.subscribe((event) => {
|
|
65
|
+
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
|
66
|
+
process.stdout.write(event.assistantMessageEvent.delta);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
64
69
|
|
|
65
|
-
console.log("=== Modify prompt ===");
|
|
66
|
-
await session2.prompt("List 3 benefits of TypeScript.");
|
|
67
|
-
console.log();
|
|
70
|
+
console.log("=== Modify prompt ===");
|
|
71
|
+
await session2.prompt("List 3 benefits of TypeScript.");
|
|
72
|
+
console.log();
|
|
73
|
+
} finally {
|
|
74
|
+
session2.dispose();
|
|
75
|
+
}
|
|
@@ -47,9 +47,9 @@ if (diagnostics.length > 0) {
|
|
|
47
47
|
console.log("Warnings:", diagnostics);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
await createAgentSession({
|
|
50
|
+
const { session } = await createAgentSession({
|
|
51
51
|
resourceLoader: loader,
|
|
52
52
|
sessionManager: SessionManager.inMemory(),
|
|
53
53
|
});
|
|
54
|
-
|
|
55
54
|
console.log("Session created with filtered skills");
|
|
55
|
+
session.dispose();
|
package/examples/sdk/05-tools.ts
CHANGED
|
@@ -13,32 +13,36 @@
|
|
|
13
13
|
import { createAgentSession, SessionManager } from "@earendil-works/pi-coding-agent";
|
|
14
14
|
|
|
15
15
|
// Read-only mode (no edit/write)
|
|
16
|
-
await createAgentSession({
|
|
16
|
+
const { session: readOnlySession } = await createAgentSession({
|
|
17
17
|
tools: ["read", "grep", "find", "ls"],
|
|
18
18
|
sessionManager: SessionManager.inMemory(),
|
|
19
19
|
});
|
|
20
20
|
console.log("Read-only session created");
|
|
21
|
+
readOnlySession.dispose();
|
|
21
22
|
|
|
22
23
|
// Custom tool selection
|
|
23
|
-
await createAgentSession({
|
|
24
|
+
const { session: customToolsSession } = await createAgentSession({
|
|
24
25
|
tools: ["read", "bash", "grep"],
|
|
25
26
|
sessionManager: SessionManager.inMemory(),
|
|
26
27
|
});
|
|
27
28
|
console.log("Custom tools session created");
|
|
29
|
+
customToolsSession.dispose();
|
|
28
30
|
|
|
29
31
|
// With custom cwd
|
|
30
32
|
const customCwd = "/path/to/project";
|
|
31
|
-
await createAgentSession({
|
|
33
|
+
const { session: customCwdSession } = await createAgentSession({
|
|
32
34
|
cwd: customCwd,
|
|
33
35
|
tools: ["read", "bash", "edit", "write"],
|
|
34
36
|
sessionManager: SessionManager.inMemory(customCwd),
|
|
35
37
|
});
|
|
36
38
|
console.log("Custom cwd session created");
|
|
39
|
+
customCwdSession.dispose();
|
|
37
40
|
|
|
38
41
|
// Or pick specific tools for custom cwd
|
|
39
|
-
await createAgentSession({
|
|
42
|
+
const { session: specificToolsSession } = await createAgentSession({
|
|
40
43
|
cwd: customCwd,
|
|
41
44
|
tools: ["read", "bash", "grep"],
|
|
42
45
|
sessionManager: SessionManager.inMemory(customCwd),
|
|
43
46
|
});
|
|
44
47
|
console.log("Specific tools with custom cwd session created");
|
|
48
|
+
specificToolsSession.dispose();
|