@mariozechner/pi-coding-agent 0.23.3 → 0.23.5
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 +61 -0
- package/README.md +20 -13
- package/dist/core/custom-tools/loader.d.ts.map +1 -1
- package/dist/core/custom-tools/loader.js +56 -4
- package/dist/core/custom-tools/loader.js.map +1 -1
- package/dist/core/custom-tools/types.d.ts +9 -1
- package/dist/core/custom-tools/types.d.ts.map +1 -1
- package/dist/core/custom-tools/types.js.map +1 -1
- package/dist/core/hooks/index.d.ts +2 -1
- package/dist/core/hooks/index.d.ts.map +1 -1
- package/dist/core/hooks/index.js +1 -0
- package/dist/core/hooks/index.js.map +1 -1
- package/dist/core/hooks/loader.d.ts.map +1 -1
- package/dist/core/hooks/loader.js +4 -2
- package/dist/core/hooks/loader.js.map +1 -1
- package/dist/core/hooks/runner.d.ts.map +1 -1
- package/dist/core/hooks/runner.js +44 -4
- package/dist/core/hooks/runner.js.map +1 -1
- package/dist/core/hooks/tool-wrapper.d.ts.map +1 -1
- package/dist/core/hooks/tool-wrapper.js +5 -9
- package/dist/core/hooks/tool-wrapper.js.map +1 -1
- package/dist/core/hooks/types.d.ts +73 -11
- package/dist/core/hooks/types.d.ts.map +1 -1
- package/dist/core/hooks/types.js +22 -1
- package/dist/core/hooks/types.js.map +1 -1
- package/dist/core/skills.d.ts +18 -5
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +183 -72
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +2 -2
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +2 -2
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +5 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/find.d.ts +5 -0
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts +6 -0
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts +6 -5
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/ls.d.ts +5 -0
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/read.d.ts +4 -0
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +4 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +1 -0
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +16 -7
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/diff.d.ts +12 -0
- package/dist/modes/interactive/components/diff.d.ts.map +1 -0
- package/dist/modes/interactive/components/diff.js +133 -0
- package/dist/modes/interactive/components/diff.js.map +1 -0
- package/dist/modes/interactive/components/hook-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/hook-input.js +2 -2
- package/dist/modes/interactive/components/hook-input.js.map +1 -1
- package/dist/modes/interactive/components/hook-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/hook-selector.js +2 -2
- package/dist/modes/interactive/components/hook-selector.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +2 -2
- 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 +2 -2
- 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 +3 -3
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +26 -20
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.js +3 -3
- package/dist/modes/interactive/components/user-message-selector.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 +63 -1
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/dark.json +9 -9
- package/dist/modes/interactive/theme/light.json +9 -9
- package/dist/modes/interactive/theme/theme.d.ts +10 -0
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +131 -3
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +10 -0
- package/dist/modes/print-mode.js.map +1 -1
- package/docs/custom-tools.md +43 -4
- package/docs/hooks.md +104 -5
- package/docs/skills.md +65 -24
- package/examples/custom-tools/README.md +18 -7
- package/examples/custom-tools/subagent/README.md +172 -0
- package/examples/custom-tools/subagent/agents/planner.md +37 -0
- package/examples/custom-tools/subagent/agents/reviewer.md +35 -0
- package/examples/custom-tools/subagent/agents/scout.md +50 -0
- package/examples/custom-tools/subagent/agents/worker.md +24 -0
- package/examples/custom-tools/subagent/agents.ts +157 -0
- package/examples/custom-tools/subagent/commands/implement-and-review.md +10 -0
- package/examples/custom-tools/subagent/commands/implement.md +10 -0
- package/examples/custom-tools/subagent/commands/scout-and-plan.md +9 -0
- package/examples/custom-tools/subagent/index.ts +772 -0
- package/package.json +6 -6
- /package/examples/custom-tools/{hello.ts → hello/index.ts} +0 -0
- /package/examples/custom-tools/{question.ts → question/index.ts} +0 -0
- /package/examples/custom-tools/{todo.ts → todo/index.ts} +0 -0
package/dist/modes/print-mode.js
CHANGED
|
@@ -90,5 +90,15 @@ export async function runPrintMode(session, mode, messages, initialMessage, init
|
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
|
+
// Ensure stdout is fully flushed before returning
|
|
94
|
+
// This prevents race conditions where the process exits before all output is written
|
|
95
|
+
await new Promise((resolve, reject) => {
|
|
96
|
+
process.stdout.write("", (err) => {
|
|
97
|
+
if (err)
|
|
98
|
+
reject(err);
|
|
99
|
+
else
|
|
100
|
+
resolve();
|
|
101
|
+
});
|
|
102
|
+
});
|
|
93
103
|
}
|
|
94
104
|
//# sourceMappingURL=print-mode.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"print-mode.js","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"print-mode.js","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Print mode (single-shot): Send prompts, output result, exit.\n *\n * Used for:\n * - `pi -p \"prompt\"` - text output\n * - `pi --mode json \"prompt\"` - JSON event stream\n */\n\nimport type { Attachment } from \"@mariozechner/pi-agent-core\";\nimport type { AssistantMessage } from \"@mariozechner/pi-ai\";\nimport type { AgentSession } from \"../core/agent-session.js\";\n\n/**\n * Run in print (single-shot) mode.\n * Sends prompts to the agent and outputs the result.\n *\n * @param session The agent session\n * @param mode Output mode: \"text\" for final response only, \"json\" for all events\n * @param messages Array of prompts to send\n * @param initialMessage Optional first message (may contain @file content)\n * @param initialAttachments Optional attachments for the initial message\n */\nexport async function runPrintMode(\n\tsession: AgentSession,\n\tmode: \"text\" | \"json\",\n\tmessages: string[],\n\tinitialMessage?: string,\n\tinitialAttachments?: Attachment[],\n): Promise<void> {\n\t// Load entries once for session start events\n\tconst entries = session.sessionManager.loadEntries();\n\n\t// Hook runner already has no-op UI context by default (set in main.ts)\n\t// Set up hooks for print mode (no UI)\n\tconst hookRunner = session.hookRunner;\n\tif (hookRunner) {\n\t\t// Use actual session file if configured (via --session), otherwise null\n\t\thookRunner.setSessionFile(session.sessionFile);\n\t\thookRunner.onError((err) => {\n\t\t\tconsole.error(`Hook error (${err.hookPath}): ${err.error}`);\n\t\t});\n\t\t// No-op send handler for print mode (single-shot, no async messages)\n\t\thookRunner.setSendHandler(() => {\n\t\t\tconsole.error(\"Warning: pi.send() is not supported in print mode\");\n\t\t});\n\t\t// Emit session event\n\t\tawait hookRunner.emit({\n\t\t\ttype: \"session\",\n\t\t\tentries,\n\t\t\tsessionFile: session.sessionFile,\n\t\t\tpreviousSessionFile: null,\n\t\t\treason: \"start\",\n\t\t});\n\t}\n\n\t// Emit session start event to custom tools (no UI in print mode)\n\tfor (const { tool } of session.customTools) {\n\t\tif (tool.onSession) {\n\t\t\ttry {\n\t\t\t\tawait tool.onSession({\n\t\t\t\t\tentries,\n\t\t\t\t\tsessionFile: session.sessionFile,\n\t\t\t\t\tpreviousSessionFile: null,\n\t\t\t\t\treason: \"start\",\n\t\t\t\t});\n\t\t\t} catch (_err) {\n\t\t\t\t// Silently ignore tool errors\n\t\t\t}\n\t\t}\n\t}\n\n\t// Always subscribe to enable session persistence via _handleAgentEvent\n\tsession.subscribe((event) => {\n\t\t// In JSON mode, output all events\n\t\tif (mode === \"json\") {\n\t\t\tconsole.log(JSON.stringify(event));\n\t\t}\n\t});\n\n\t// Send initial message with attachments\n\tif (initialMessage) {\n\t\tawait session.prompt(initialMessage, { attachments: initialAttachments });\n\t}\n\n\t// Send remaining messages\n\tfor (const message of messages) {\n\t\tawait session.prompt(message);\n\t}\n\n\t// In text mode, output final response\n\tif (mode === \"text\") {\n\t\tconst state = session.state;\n\t\tconst lastMessage = state.messages[state.messages.length - 1];\n\n\t\tif (lastMessage?.role === \"assistant\") {\n\t\t\tconst assistantMsg = lastMessage as AssistantMessage;\n\n\t\t\t// Check for error/aborted\n\t\t\tif (assistantMsg.stopReason === \"error\" || assistantMsg.stopReason === \"aborted\") {\n\t\t\t\tconsole.error(assistantMsg.errorMessage || `Request ${assistantMsg.stopReason}`);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\t// Output text content\n\t\t\tfor (const content of assistantMsg.content) {\n\t\t\t\tif (content.type === \"text\") {\n\t\t\t\t\tconsole.log(content.text);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Ensure stdout is fully flushed before returning\n\t// This prevents race conditions where the process exits before all output is written\n\tawait new Promise<void>((resolve, reject) => {\n\t\tprocess.stdout.write(\"\", (err) => {\n\t\t\tif (err) reject(err);\n\t\t\telse resolve();\n\t\t});\n\t});\n}\n"]}
|
package/docs/custom-tools.md
CHANGED
|
@@ -22,7 +22,7 @@ See [examples/custom-tools/](../examples/custom-tools/) for working examples.
|
|
|
22
22
|
|
|
23
23
|
## Quick Start
|
|
24
24
|
|
|
25
|
-
Create a file `~/.pi/agent/tools/hello.ts`:
|
|
25
|
+
Create a file `~/.pi/agent/tools/hello/index.ts`:
|
|
26
26
|
|
|
27
27
|
```typescript
|
|
28
28
|
import { Type } from "@sinclair/typebox";
|
|
@@ -51,13 +51,26 @@ The tool is automatically discovered and available in your next pi session.
|
|
|
51
51
|
|
|
52
52
|
## Tool Locations
|
|
53
53
|
|
|
54
|
+
Tools must be in a subdirectory with an `index.ts` entry point:
|
|
55
|
+
|
|
54
56
|
| Location | Scope | Auto-discovered |
|
|
55
57
|
|----------|-------|-----------------|
|
|
56
|
-
| `~/.pi/agent/tools
|
|
57
|
-
| `.pi/tools
|
|
58
|
+
| `~/.pi/agent/tools/*/index.ts` | Global (all projects) | Yes |
|
|
59
|
+
| `.pi/tools/*/index.ts` | Project-local | Yes |
|
|
58
60
|
| `settings.json` `customTools` array | Configured paths | Yes |
|
|
59
61
|
| `--tool <path>` CLI flag | One-off/debugging | No |
|
|
60
62
|
|
|
63
|
+
**Example structure:**
|
|
64
|
+
```
|
|
65
|
+
~/.pi/agent/tools/
|
|
66
|
+
├── hello/
|
|
67
|
+
│ └── index.ts # Entry point (auto-discovered)
|
|
68
|
+
└── complex-tool/
|
|
69
|
+
├── index.ts # Entry point (auto-discovered)
|
|
70
|
+
├── helpers.ts # Helper module (not loaded directly)
|
|
71
|
+
└── types.ts # Type definitions (not loaded directly)
|
|
72
|
+
```
|
|
73
|
+
|
|
61
74
|
**Priority:** Later sources win on name conflicts. CLI `--tool` takes highest priority.
|
|
62
75
|
|
|
63
76
|
**Reserved names:** Custom tools cannot use built-in tool names (`read`, `write`, `edit`, `bash`, `grep`, `find`, `ls`).
|
|
@@ -125,7 +138,7 @@ The factory receives a `ToolAPI` object (named `pi` by convention):
|
|
|
125
138
|
```typescript
|
|
126
139
|
interface ToolAPI {
|
|
127
140
|
cwd: string; // Current working directory
|
|
128
|
-
exec(command: string, args: string[]): Promise<ExecResult>;
|
|
141
|
+
exec(command: string, args: string[], options?: ExecOptions): Promise<ExecResult>;
|
|
129
142
|
ui: {
|
|
130
143
|
select(title: string, options: string[]): Promise<string | null>;
|
|
131
144
|
confirm(title: string, message: string): Promise<boolean>;
|
|
@@ -134,10 +147,36 @@ interface ToolAPI {
|
|
|
134
147
|
};
|
|
135
148
|
hasUI: boolean; // false in --print or --mode rpc
|
|
136
149
|
}
|
|
150
|
+
|
|
151
|
+
interface ExecOptions {
|
|
152
|
+
signal?: AbortSignal; // Cancel the process
|
|
153
|
+
timeout?: number; // Timeout in milliseconds
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
interface ExecResult {
|
|
157
|
+
stdout: string;
|
|
158
|
+
stderr: string;
|
|
159
|
+
code: number;
|
|
160
|
+
killed?: boolean; // True if process was killed by signal/timeout
|
|
161
|
+
}
|
|
137
162
|
```
|
|
138
163
|
|
|
139
164
|
Always check `pi.hasUI` before using UI methods.
|
|
140
165
|
|
|
166
|
+
### Cancellation Example
|
|
167
|
+
|
|
168
|
+
Pass the `signal` from `execute` to `pi.exec` to support cancellation:
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
async execute(toolCallId, params, signal) {
|
|
172
|
+
const result = await pi.exec("long-running-command", ["arg"], { signal });
|
|
173
|
+
if (result.killed) {
|
|
174
|
+
return { content: [{ type: "text", text: "Cancelled" }] };
|
|
175
|
+
}
|
|
176
|
+
return { content: [{ type: "text", text: result.stdout }] };
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
141
180
|
## Session Lifecycle
|
|
142
181
|
|
|
143
182
|
Tools can implement `onSession` to react to session changes:
|
package/docs/hooks.md
CHANGED
|
@@ -222,13 +222,104 @@ Fired after tool executes. **Can modify result.**
|
|
|
222
222
|
|
|
223
223
|
```typescript
|
|
224
224
|
pi.on("tool_result", async (event, ctx) => {
|
|
225
|
-
// event.toolName
|
|
226
|
-
// event.
|
|
225
|
+
// event.toolName: string
|
|
226
|
+
// event.toolCallId: string
|
|
227
|
+
// event.input: Record<string, unknown>
|
|
228
|
+
// event.content: (TextContent | ImageContent)[]
|
|
229
|
+
// event.details: tool-specific (see below)
|
|
227
230
|
// event.isError: boolean
|
|
228
|
-
|
|
231
|
+
|
|
232
|
+
// Return modified content/details, or undefined to keep original
|
|
233
|
+
return { content: [...], details: {...} };
|
|
229
234
|
});
|
|
230
235
|
```
|
|
231
236
|
|
|
237
|
+
The event type is a discriminated union based on `toolName`. Use the provided type guards to narrow `details` to the correct type:
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
import { isBashToolResult, type HookAPI } from "@mariozechner/pi-coding-agent/hooks";
|
|
241
|
+
|
|
242
|
+
export default function (pi: HookAPI) {
|
|
243
|
+
pi.on("tool_result", async (event, ctx) => {
|
|
244
|
+
if (isBashToolResult(event)) {
|
|
245
|
+
// event.details is BashToolDetails | undefined
|
|
246
|
+
if (event.details?.truncation?.truncated) {
|
|
247
|
+
// Access full output from temp file
|
|
248
|
+
const fullPath = event.details.fullOutputPath;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Available type guards: `isBashToolResult`, `isReadToolResult`, `isEditToolResult`, `isWriteToolResult`, `isGrepToolResult`, `isFindToolResult`, `isLsToolResult`.
|
|
256
|
+
|
|
257
|
+
#### Tool Details Types
|
|
258
|
+
|
|
259
|
+
Each built-in tool has a typed `details` field. Types are exported from `@mariozechner/pi-coding-agent`:
|
|
260
|
+
|
|
261
|
+
| Tool | Details Type | Source |
|
|
262
|
+
|------|-------------|--------|
|
|
263
|
+
| `bash` | `BashToolDetails` | `src/core/tools/bash.ts` |
|
|
264
|
+
| `read` | `ReadToolDetails` | `src/core/tools/read.ts` |
|
|
265
|
+
| `edit` | `undefined` | - |
|
|
266
|
+
| `write` | `undefined` | - |
|
|
267
|
+
| `grep` | `GrepToolDetails` | `src/core/tools/grep.ts` |
|
|
268
|
+
| `find` | `FindToolDetails` | `src/core/tools/find.ts` |
|
|
269
|
+
| `ls` | `LsToolDetails` | `src/core/tools/ls.ts` |
|
|
270
|
+
|
|
271
|
+
Common fields in details:
|
|
272
|
+
- `truncation?: TruncationResult` - present when output was truncated
|
|
273
|
+
- `fullOutputPath?: string` - path to temp file with full output (bash only)
|
|
274
|
+
|
|
275
|
+
`TruncationResult` contains:
|
|
276
|
+
- `truncated: boolean` - whether truncation occurred
|
|
277
|
+
- `truncatedBy: "lines" | "bytes" | null` - which limit was hit
|
|
278
|
+
- `totalLines`, `totalBytes` - original size
|
|
279
|
+
- `outputLines`, `outputBytes` - truncated size
|
|
280
|
+
|
|
281
|
+
Custom tools use `CustomToolResultEvent` with `details: unknown`. Create your own type guard to get full type safety:
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
import {
|
|
285
|
+
isBashToolResult,
|
|
286
|
+
type CustomToolResultEvent,
|
|
287
|
+
type HookAPI,
|
|
288
|
+
type ToolResultEvent,
|
|
289
|
+
} from "@mariozechner/pi-coding-agent/hooks";
|
|
290
|
+
|
|
291
|
+
interface MyCustomToolDetails {
|
|
292
|
+
someField: string;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Type guard that narrows both toolName and details
|
|
296
|
+
function isMyCustomToolResult(e: ToolResultEvent): e is CustomToolResultEvent & {
|
|
297
|
+
toolName: "my-custom-tool";
|
|
298
|
+
details: MyCustomToolDetails;
|
|
299
|
+
} {
|
|
300
|
+
return e.toolName === "my-custom-tool";
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export default function (pi: HookAPI) {
|
|
304
|
+
pi.on("tool_result", async (event, ctx) => {
|
|
305
|
+
// Built-in tool: use provided type guard
|
|
306
|
+
if (isBashToolResult(event)) {
|
|
307
|
+
if (event.details?.fullOutputPath) {
|
|
308
|
+
console.log(`Full output at: ${event.details.fullOutputPath}`);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Custom tool: use your own type guard
|
|
313
|
+
if (isMyCustomToolResult(event)) {
|
|
314
|
+
// event.details is now MyCustomToolDetails
|
|
315
|
+
console.log(event.details.someField);
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
**Note:** If you modify `content`, you should also update `details` accordingly. The TUI uses `details` (e.g., truncation info) for rendering, so inconsistent values will cause display issues.
|
|
322
|
+
|
|
232
323
|
## Context API
|
|
233
324
|
|
|
234
325
|
Every event handler receives a context object with these methods:
|
|
@@ -272,15 +363,23 @@ ctx.ui.notify("Operation complete", "info");
|
|
|
272
363
|
ctx.ui.notify("Something went wrong", "error");
|
|
273
364
|
```
|
|
274
365
|
|
|
275
|
-
### ctx.exec(command, args)
|
|
366
|
+
### ctx.exec(command, args, options?)
|
|
276
367
|
|
|
277
|
-
Execute a command and get the result.
|
|
368
|
+
Execute a command and get the result. Supports cancellation via `AbortSignal` and timeout.
|
|
278
369
|
|
|
279
370
|
```typescript
|
|
280
371
|
const result = await ctx.exec("git", ["status"]);
|
|
281
372
|
// result.stdout: string
|
|
282
373
|
// result.stderr: string
|
|
283
374
|
// result.code: number
|
|
375
|
+
// result.killed?: boolean // True if killed by signal/timeout
|
|
376
|
+
|
|
377
|
+
// With timeout (5 seconds)
|
|
378
|
+
const result = await ctx.exec("slow-command", [], { timeout: 5000 });
|
|
379
|
+
|
|
380
|
+
// With abort signal
|
|
381
|
+
const controller = new AbortController();
|
|
382
|
+
const result = await ctx.exec("long-command", [], { signal: controller.signal });
|
|
284
383
|
```
|
|
285
384
|
|
|
286
385
|
### ctx.cwd
|
package/docs/skills.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
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.
|
|
4
4
|
|
|
5
|
+
Pi implements the [Agent Skills standard](https://agentskills.io/specification).
|
|
6
|
+
|
|
5
7
|
**Example use cases:**
|
|
6
8
|
- Web search and content extraction (Brave Search API)
|
|
7
9
|
- Browser automation via Chrome DevTools Protocol
|
|
@@ -65,14 +67,13 @@ description: What this skill does and when to use it. Be specific.
|
|
|
65
67
|
|
|
66
68
|
Run once before first use:
|
|
67
69
|
\`\`\`bash
|
|
68
|
-
cd
|
|
69
|
-
npm install
|
|
70
|
+
cd /path/to/skill && npm install
|
|
70
71
|
\`\`\`
|
|
71
72
|
|
|
72
73
|
## Usage
|
|
73
74
|
|
|
74
75
|
\`\`\`bash
|
|
75
|
-
|
|
76
|
+
./scripts/process.sh <input>
|
|
76
77
|
\`\`\`
|
|
77
78
|
|
|
78
79
|
## Workflow
|
|
@@ -84,20 +85,54 @@ npm install
|
|
|
84
85
|
|
|
85
86
|
### Frontmatter Fields
|
|
86
87
|
|
|
87
|
-
|
|
88
|
+
Per the [Agent Skills specification](https://agentskills.io/specification#frontmatter-required):
|
|
89
|
+
|
|
90
|
+
| Field | Required | Constraints |
|
|
88
91
|
|-------|----------|-------------|
|
|
89
|
-
| `
|
|
90
|
-
| `
|
|
92
|
+
| `name` | Yes | Max 64 chars. Lowercase a-z, 0-9, hyphens only. Must match parent directory name. |
|
|
93
|
+
| `description` | Yes | Max 1024 chars. What the skill does and when to use it. |
|
|
94
|
+
| `license` | No | License name or reference to bundled license file. |
|
|
95
|
+
| `compatibility` | No | Max 500 chars. Environment requirements (system packages, network access, etc.). |
|
|
96
|
+
| `metadata` | No | Arbitrary key-value mapping for additional metadata. |
|
|
97
|
+
| `allowed-tools` | No | Space-delimited list of pre-approved tools (experimental). |
|
|
98
|
+
|
|
99
|
+
#### Name Validation
|
|
100
|
+
|
|
101
|
+
The `name` field must:
|
|
102
|
+
- Be 1-64 characters
|
|
103
|
+
- Contain only lowercase letters (a-z), numbers (0-9), and hyphens
|
|
104
|
+
- Not start or end with a hyphen
|
|
105
|
+
- Not contain consecutive hyphens (--)
|
|
106
|
+
- Match the parent directory name exactly
|
|
107
|
+
|
|
108
|
+
Valid: `pdf-processing`, `data-analysis`, `code-review`
|
|
109
|
+
Invalid: `PDF-Processing`, `-pdf`, `pdf--processing`
|
|
91
110
|
|
|
92
|
-
|
|
111
|
+
#### Description Best Practices
|
|
112
|
+
|
|
113
|
+
The `description` is critical. It determines when the agent loads the skill. Be specific about both what it does and when to use it.
|
|
114
|
+
|
|
115
|
+
Good:
|
|
116
|
+
```yaml
|
|
117
|
+
description: Extracts text and tables from PDF files, fills PDF forms, and merges multiple PDFs. Use when working with PDF documents or when the user mentions PDFs, forms, or document extraction.
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Poor:
|
|
121
|
+
```yaml
|
|
122
|
+
description: Helps with PDFs.
|
|
123
|
+
```
|
|
93
124
|
|
|
94
|
-
###
|
|
125
|
+
### File References
|
|
95
126
|
|
|
96
|
-
Use
|
|
127
|
+
Use relative paths from the skill directory:
|
|
97
128
|
|
|
98
129
|
```markdown
|
|
99
|
-
|
|
100
|
-
|
|
130
|
+
See [the reference guide](references/REFERENCE.md) for details.
|
|
131
|
+
|
|
132
|
+
Run the extraction script:
|
|
133
|
+
\`\`\`bash
|
|
134
|
+
./scripts/extract.py input.pdf
|
|
135
|
+
\`\`\`
|
|
101
136
|
```
|
|
102
137
|
|
|
103
138
|
## Skill Locations
|
|
@@ -110,21 +145,28 @@ Skills are discovered from these locations (later wins on name collision):
|
|
|
110
145
|
4. `~/.pi/agent/skills/**/SKILL.md` (Pi user, recursive)
|
|
111
146
|
5. `<cwd>/.pi/skills/**/SKILL.md` (Pi project, recursive)
|
|
112
147
|
|
|
113
|
-
### Subdirectory Naming
|
|
114
|
-
|
|
115
|
-
Pi skills in subdirectories use colon-separated names:
|
|
116
|
-
- `~/.pi/agent/skills/db/migrate/SKILL.md` → `db:migrate`
|
|
117
|
-
- `<cwd>/.pi/skills/aws/s3/upload/SKILL.md` → `aws:s3:upload`
|
|
118
|
-
|
|
119
148
|
## How Skills Work
|
|
120
149
|
|
|
121
150
|
1. At startup, pi scans skill locations and extracts names + descriptions
|
|
122
|
-
2. The system prompt includes
|
|
151
|
+
2. The system prompt includes available skills in XML format
|
|
123
152
|
3. When a task matches, the agent uses `read` to load the full SKILL.md
|
|
124
|
-
4. The agent follows the instructions, using
|
|
153
|
+
4. The agent follows the instructions, using relative paths to reference scripts/assets
|
|
125
154
|
|
|
126
155
|
This is progressive disclosure: only descriptions are always in context, full instructions load on-demand.
|
|
127
156
|
|
|
157
|
+
## Validation Warnings
|
|
158
|
+
|
|
159
|
+
Pi validates skills against the Agent Skills standard and warns (but still loads) non-compliant skills:
|
|
160
|
+
|
|
161
|
+
- Name doesn't match parent directory
|
|
162
|
+
- Name exceeds 64 characters
|
|
163
|
+
- Name contains invalid characters
|
|
164
|
+
- Name starts/ends with hyphen or has consecutive hyphens
|
|
165
|
+
- Description missing or exceeds 1024 characters
|
|
166
|
+
- Unknown frontmatter fields
|
|
167
|
+
|
|
168
|
+
Name collisions (same name from different locations) warn and keep the first skill found.
|
|
169
|
+
|
|
128
170
|
## Example: Web Search Skill
|
|
129
171
|
|
|
130
172
|
```
|
|
@@ -146,21 +188,20 @@ description: Web search and content extraction via Brave Search API. Use for sea
|
|
|
146
188
|
## Setup
|
|
147
189
|
|
|
148
190
|
\`\`\`bash
|
|
149
|
-
cd
|
|
150
|
-
npm install
|
|
191
|
+
cd /path/to/brave-search && npm install
|
|
151
192
|
\`\`\`
|
|
152
193
|
|
|
153
194
|
## Search
|
|
154
195
|
|
|
155
196
|
\`\`\`bash
|
|
156
|
-
|
|
157
|
-
|
|
197
|
+
./search.js "query" # Basic search
|
|
198
|
+
./search.js "query" --content # Include page content
|
|
158
199
|
\`\`\`
|
|
159
200
|
|
|
160
201
|
## Extract Page Content
|
|
161
202
|
|
|
162
203
|
\`\`\`bash
|
|
163
|
-
|
|
204
|
+
./content.js https://example.com
|
|
164
205
|
\`\`\`
|
|
165
206
|
```
|
|
166
207
|
|
|
@@ -4,27 +4,38 @@ Example custom tools for pi-coding-agent.
|
|
|
4
4
|
|
|
5
5
|
## Examples
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Each example uses the `subdirectory/index.ts` structure required for tool discovery.
|
|
8
|
+
|
|
9
|
+
### hello/
|
|
8
10
|
Minimal example showing the basic structure of a custom tool.
|
|
9
11
|
|
|
10
|
-
### question
|
|
12
|
+
### question/
|
|
11
13
|
Demonstrates `pi.ui.select()` for asking the user questions with options.
|
|
12
14
|
|
|
13
|
-
### todo
|
|
15
|
+
### todo/
|
|
14
16
|
Full-featured example demonstrating:
|
|
15
17
|
- `onSession` for state reconstruction from session history
|
|
16
18
|
- Custom `renderCall` and `renderResult`
|
|
17
19
|
- Proper branching support via details storage
|
|
18
20
|
- State management without external files
|
|
19
21
|
|
|
22
|
+
### subagent/
|
|
23
|
+
Delegate tasks to specialized subagents with isolated context windows. Includes:
|
|
24
|
+
- `index.ts` - The custom tool (single, parallel, and chain modes)
|
|
25
|
+
- `agents.ts` - Agent discovery helper
|
|
26
|
+
- `agents/` - Sample agent definitions (scout, planner, reviewer, worker)
|
|
27
|
+
- `commands/` - Workflow presets (/implement, /scout-and-plan, /implement-and-review)
|
|
28
|
+
|
|
29
|
+
See [subagent/README.md](subagent/README.md) for full documentation.
|
|
30
|
+
|
|
20
31
|
## Usage
|
|
21
32
|
|
|
22
33
|
```bash
|
|
23
|
-
# Test directly
|
|
24
|
-
pi --tool examples/custom-tools/todo.ts
|
|
34
|
+
# Test directly (can point to any .ts file)
|
|
35
|
+
pi --tool examples/custom-tools/todo/index.ts
|
|
25
36
|
|
|
26
|
-
# Or copy to tools directory for persistent use
|
|
27
|
-
cp todo
|
|
37
|
+
# Or copy entire folder to tools directory for persistent use
|
|
38
|
+
cp -r todo ~/.pi/agent/tools/
|
|
28
39
|
```
|
|
29
40
|
|
|
30
41
|
Then in pi:
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Subagent Example
|
|
2
|
+
|
|
3
|
+
Delegate tasks to specialized subagents with isolated context windows.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Isolated context**: Each subagent runs in a separate `pi` process
|
|
8
|
+
- **Streaming output**: See tool calls and progress as they happen
|
|
9
|
+
- **Parallel streaming**: All parallel tasks stream updates simultaneously
|
|
10
|
+
- **Markdown rendering**: Final output rendered with proper formatting (expanded view)
|
|
11
|
+
- **Usage tracking**: Shows turns, tokens, cost, and context usage per agent
|
|
12
|
+
- **Abort support**: Ctrl+C propagates to kill subagent processes
|
|
13
|
+
|
|
14
|
+
## Structure
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
subagent/
|
|
18
|
+
├── README.md # This file
|
|
19
|
+
├── subagent.ts # The custom tool (entry point)
|
|
20
|
+
├── agents.ts # Agent discovery logic
|
|
21
|
+
├── agents/ # Sample agent definitions
|
|
22
|
+
│ ├── scout.md # Fast recon, returns compressed context
|
|
23
|
+
│ ├── planner.md # Creates implementation plans
|
|
24
|
+
│ ├── reviewer.md # Code review
|
|
25
|
+
│ └── worker.md # General-purpose (full capabilities)
|
|
26
|
+
└── commands/ # Workflow presets
|
|
27
|
+
├── implement.md # scout -> planner -> worker
|
|
28
|
+
├── scout-and-plan.md # scout -> planner (no implementation)
|
|
29
|
+
└── implement-and-review.md # worker -> reviewer -> worker
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Installation
|
|
33
|
+
|
|
34
|
+
From the repository root, symlink the files:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Symlink the tool (must be in a subdirectory with index.ts)
|
|
38
|
+
mkdir -p ~/.pi/agent/tools/subagent
|
|
39
|
+
ln -sf "$(pwd)/packages/coding-agent/examples/custom-tools/subagent/subagent.ts" ~/.pi/agent/tools/subagent/index.ts
|
|
40
|
+
ln -sf "$(pwd)/packages/coding-agent/examples/custom-tools/subagent/agents.ts" ~/.pi/agent/tools/subagent/agents.ts
|
|
41
|
+
|
|
42
|
+
# Symlink agents
|
|
43
|
+
mkdir -p ~/.pi/agent/agents
|
|
44
|
+
for f in packages/coding-agent/examples/custom-tools/subagent/agents/*.md; do
|
|
45
|
+
ln -sf "$(pwd)/$f" ~/.pi/agent/agents/$(basename "$f")
|
|
46
|
+
done
|
|
47
|
+
|
|
48
|
+
# Symlink workflow commands
|
|
49
|
+
mkdir -p ~/.pi/agent/commands
|
|
50
|
+
for f in packages/coding-agent/examples/custom-tools/subagent/commands/*.md; do
|
|
51
|
+
ln -sf "$(pwd)/$f" ~/.pi/agent/commands/$(basename "$f")
|
|
52
|
+
done
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Security Model
|
|
56
|
+
|
|
57
|
+
This tool executes a separate `pi` subprocess with a delegated system prompt and tool/model configuration.
|
|
58
|
+
|
|
59
|
+
**Project-local agents** (`.pi/agents/*.md`) are repo-controlled prompts that can instruct the model to read files, run bash commands, etc.
|
|
60
|
+
|
|
61
|
+
**Default behavior:** Only loads **user-level agents** from `~/.pi/agent/agents`.
|
|
62
|
+
|
|
63
|
+
To enable project-local agents, pass `agentScope: "both"` (or `"project"`). Only do this for repositories you trust.
|
|
64
|
+
|
|
65
|
+
When running interactively, the tool prompts for confirmation before running project-local agents. Set `confirmProjectAgents: false` to disable.
|
|
66
|
+
|
|
67
|
+
## Usage
|
|
68
|
+
|
|
69
|
+
### Single agent
|
|
70
|
+
```
|
|
71
|
+
Use scout to find all authentication code
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Parallel execution
|
|
75
|
+
```
|
|
76
|
+
Run 2 scouts in parallel: one to find models, one to find providers
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Chained workflow
|
|
80
|
+
```
|
|
81
|
+
Use a chain: first have scout find the read tool, then have planner suggest improvements
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Workflow commands
|
|
85
|
+
```
|
|
86
|
+
/implement add Redis caching to the session store
|
|
87
|
+
/scout-and-plan refactor auth to support OAuth
|
|
88
|
+
/implement-and-review add input validation to API endpoints
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Tool Modes
|
|
92
|
+
|
|
93
|
+
| Mode | Parameter | Description |
|
|
94
|
+
|------|-----------|-------------|
|
|
95
|
+
| Single | `{ agent, task }` | One agent, one task |
|
|
96
|
+
| Parallel | `{ tasks: [...] }` | Multiple agents run concurrently (max 8, 4 concurrent) |
|
|
97
|
+
| Chain | `{ chain: [...] }` | Sequential with `{previous}` placeholder |
|
|
98
|
+
|
|
99
|
+
## Output Display
|
|
100
|
+
|
|
101
|
+
**Collapsed view** (default):
|
|
102
|
+
- Status icon (✓/✗/⏳) and agent name
|
|
103
|
+
- Last 5-10 items (tool calls and text)
|
|
104
|
+
- Usage stats: `3 turns ↑input ↓output RcacheRead WcacheWrite $cost ctx:contextTokens model`
|
|
105
|
+
|
|
106
|
+
**Expanded view** (Ctrl+O):
|
|
107
|
+
- Full task text
|
|
108
|
+
- All tool calls with formatted arguments
|
|
109
|
+
- Final output rendered as Markdown
|
|
110
|
+
- Per-task usage (for chain/parallel)
|
|
111
|
+
|
|
112
|
+
**Parallel mode streaming**:
|
|
113
|
+
- Shows all tasks with live status (⏳ running, ✓ done, ✗ failed)
|
|
114
|
+
- Updates as each task makes progress
|
|
115
|
+
- Shows "2/3 done, 1 running" status
|
|
116
|
+
|
|
117
|
+
**Tool call formatting** (mimics built-in tools):
|
|
118
|
+
- `$ command` for bash
|
|
119
|
+
- `read ~/path:1-10` for read
|
|
120
|
+
- `grep /pattern/ in ~/path` for grep
|
|
121
|
+
- etc.
|
|
122
|
+
|
|
123
|
+
## Agent Definitions
|
|
124
|
+
|
|
125
|
+
Agents are markdown files with YAML frontmatter:
|
|
126
|
+
|
|
127
|
+
```markdown
|
|
128
|
+
---
|
|
129
|
+
name: my-agent
|
|
130
|
+
description: What this agent does
|
|
131
|
+
tools: read, grep, find, ls
|
|
132
|
+
model: claude-haiku-4-5
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
System prompt for the agent goes here.
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Locations:**
|
|
139
|
+
- `~/.pi/agent/agents/*.md` - User-level (always loaded)
|
|
140
|
+
- `.pi/agents/*.md` - Project-level (only with `agentScope: "project"` or `"both"`)
|
|
141
|
+
|
|
142
|
+
Project agents override user agents with the same name when `agentScope: "both"`.
|
|
143
|
+
|
|
144
|
+
## Sample Agents
|
|
145
|
+
|
|
146
|
+
| Agent | Purpose | Model | Tools |
|
|
147
|
+
|-------|---------|-------|-------|
|
|
148
|
+
| `scout` | Fast codebase recon | Haiku | read, grep, find, ls, bash |
|
|
149
|
+
| `planner` | Implementation plans | Sonnet | read, grep, find, ls |
|
|
150
|
+
| `reviewer` | Code review | Sonnet | read, grep, find, ls, bash |
|
|
151
|
+
| `worker` | General-purpose | Sonnet | (all default) |
|
|
152
|
+
|
|
153
|
+
## Workflow Commands
|
|
154
|
+
|
|
155
|
+
| Command | Flow |
|
|
156
|
+
|---------|------|
|
|
157
|
+
| `/implement <query>` | scout → planner → worker |
|
|
158
|
+
| `/scout-and-plan <query>` | scout → planner |
|
|
159
|
+
| `/implement-and-review <query>` | worker → reviewer → worker |
|
|
160
|
+
|
|
161
|
+
## Error Handling
|
|
162
|
+
|
|
163
|
+
- **Exit code != 0**: Tool returns error with stderr/output
|
|
164
|
+
- **stopReason "error"**: LLM error propagated with error message
|
|
165
|
+
- **stopReason "aborted"**: User abort (Ctrl+C) kills subprocess, throws error
|
|
166
|
+
- **Chain mode**: Stops at first failing step, reports which step failed
|
|
167
|
+
|
|
168
|
+
## Limitations
|
|
169
|
+
|
|
170
|
+
- Output truncated to last 10 items in collapsed view (expand to see all)
|
|
171
|
+
- Agents discovered fresh on each invocation (allows editing mid-session)
|
|
172
|
+
- Parallel mode limited to 8 tasks, 4 concurrent
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: planner
|
|
3
|
+
description: Creates implementation plans from context and requirements
|
|
4
|
+
tools: read, grep, find, ls
|
|
5
|
+
model: claude-sonnet-4-5
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are a planning specialist. You receive context (from a scout) and requirements, then produce a clear implementation plan.
|
|
9
|
+
|
|
10
|
+
You must NOT make any changes. Only read, analyze, and plan.
|
|
11
|
+
|
|
12
|
+
Input format you'll receive:
|
|
13
|
+
- Context/findings from a scout agent
|
|
14
|
+
- Original query or requirements
|
|
15
|
+
|
|
16
|
+
Output format:
|
|
17
|
+
|
|
18
|
+
## Goal
|
|
19
|
+
One sentence summary of what needs to be done.
|
|
20
|
+
|
|
21
|
+
## Plan
|
|
22
|
+
Numbered steps, each small and actionable:
|
|
23
|
+
1. Step one - specific file/function to modify
|
|
24
|
+
2. Step two - what to add/change
|
|
25
|
+
3. ...
|
|
26
|
+
|
|
27
|
+
## Files to Modify
|
|
28
|
+
- `path/to/file.ts` - what changes
|
|
29
|
+
- `path/to/other.ts` - what changes
|
|
30
|
+
|
|
31
|
+
## New Files (if any)
|
|
32
|
+
- `path/to/new.ts` - purpose
|
|
33
|
+
|
|
34
|
+
## Risks
|
|
35
|
+
Anything to watch out for.
|
|
36
|
+
|
|
37
|
+
Keep the plan concrete. The worker agent will execute it verbatim.
|