@oh-my-pi/pi-coding-agent 3.20.1 → 3.24.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 +107 -8
- package/docs/custom-tools.md +3 -3
- package/docs/extensions.md +226 -220
- package/docs/hooks.md +2 -2
- package/docs/sdk.md +50 -53
- package/examples/custom-tools/README.md +2 -17
- package/examples/extensions/README.md +76 -74
- package/examples/extensions/todo.ts +2 -5
- package/examples/hooks/custom-compaction.ts +2 -4
- package/examples/hooks/handoff.ts +1 -1
- package/examples/hooks/qna.ts +1 -1
- package/examples/sdk/02-custom-model.ts +1 -1
- package/examples/sdk/README.md +7 -11
- package/package.json +6 -6
- package/src/cli/args.ts +9 -6
- package/src/cli/file-processor.ts +1 -1
- package/src/cli/list-models.ts +1 -1
- package/src/core/agent-session.ts +16 -5
- package/src/core/auth-storage.ts +1 -1
- package/src/core/compaction/branch-summarization.ts +2 -2
- package/src/core/compaction/compaction.ts +2 -2
- package/src/core/compaction/utils.ts +1 -1
- package/src/core/custom-tools/types.ts +1 -1
- package/src/core/custom-tools/wrapper.ts +0 -1
- package/src/core/extensions/index.ts +1 -6
- package/src/core/extensions/runner.ts +1 -1
- package/src/core/extensions/types.ts +1 -1
- package/src/core/extensions/wrapper.ts +1 -8
- package/src/core/file-mentions.ts +5 -8
- package/src/core/hooks/runner.ts +2 -2
- package/src/core/hooks/types.ts +1 -1
- package/src/core/messages.ts +1 -1
- package/src/core/model-registry.ts +1 -1
- package/src/core/model-resolver.ts +1 -1
- package/src/core/sdk.ts +64 -105
- package/src/core/session-manager.ts +18 -22
- package/src/core/settings-manager.ts +66 -1
- package/src/core/slash-commands.ts +12 -5
- package/src/core/system-prompt.ts +49 -36
- package/src/core/title-generator.ts +2 -2
- package/src/core/tools/ask.ts +98 -4
- package/src/core/tools/bash-interceptor.ts +11 -4
- package/src/core/tools/bash.ts +121 -5
- package/src/core/tools/context.ts +7 -0
- package/src/core/tools/edit-diff.ts +73 -24
- package/src/core/tools/edit.ts +221 -34
- package/src/core/tools/exa/render.ts +4 -16
- package/src/core/tools/find.ts +149 -5
- package/src/core/tools/gemini-image.ts +279 -56
- package/src/core/tools/git.ts +17 -3
- package/src/core/tools/grep.ts +185 -5
- package/src/core/tools/index.test.ts +180 -0
- package/src/core/tools/index.ts +96 -242
- package/src/core/tools/ls.ts +133 -5
- package/src/core/tools/lsp/index.ts +32 -29
- package/src/core/tools/lsp/render.ts +21 -22
- package/src/core/tools/notebook.ts +112 -4
- package/src/core/tools/output.ts +175 -15
- package/src/core/tools/read.ts +127 -25
- package/src/core/tools/render-utils.ts +241 -0
- package/src/core/tools/renderers.ts +40 -828
- package/src/core/tools/review.ts +26 -25
- package/src/core/tools/rulebook.ts +11 -3
- package/src/core/tools/task/agents.ts +28 -7
- package/src/core/tools/task/discovery.ts +0 -6
- package/src/core/tools/task/executor.ts +264 -254
- package/src/core/tools/task/index.ts +48 -208
- package/src/core/tools/task/render.ts +26 -11
- package/src/core/tools/task/types.ts +7 -12
- package/src/core/tools/task/worker-protocol.ts +17 -0
- package/src/core/tools/task/worker.ts +238 -0
- package/src/core/tools/truncate.ts +27 -1
- package/src/core/tools/web-fetch.ts +25 -49
- package/src/core/tools/web-search/index.ts +132 -46
- package/src/core/tools/web-search/providers/anthropic.ts +7 -2
- package/src/core/tools/web-search/providers/exa.ts +2 -1
- package/src/core/tools/web-search/providers/perplexity.ts +6 -1
- package/src/core/tools/web-search/render.ts +6 -4
- package/src/core/tools/web-search/types.ts +13 -0
- package/src/core/tools/write.ts +96 -14
- package/src/core/voice.ts +1 -1
- package/src/discovery/helpers.test.ts +1 -1
- package/src/index.ts +5 -16
- package/src/main.ts +5 -5
- package/src/modes/interactive/components/assistant-message.ts +1 -1
- package/src/modes/interactive/components/custom-message.ts +1 -1
- package/src/modes/interactive/components/extensions/inspector-panel.ts +25 -22
- package/src/modes/interactive/components/extensions/state-manager.ts +12 -0
- package/src/modes/interactive/components/footer.ts +1 -1
- package/src/modes/interactive/components/hook-message.ts +1 -1
- package/src/modes/interactive/components/model-selector.ts +1 -1
- package/src/modes/interactive/components/oauth-selector.ts +1 -1
- package/src/modes/interactive/components/settings-defs.ts +49 -0
- package/src/modes/interactive/components/status-line.ts +1 -1
- package/src/modes/interactive/components/tool-execution.ts +93 -538
- package/src/modes/interactive/interactive-mode.ts +19 -7
- package/src/modes/interactive/theme/theme.ts +4 -4
- package/src/modes/print-mode.ts +1 -1
- package/src/modes/rpc/rpc-client.ts +1 -1
- package/src/modes/rpc/rpc-types.ts +1 -1
- package/src/prompts/system-prompt.md +4 -0
- package/src/prompts/task.md +0 -7
- package/src/prompts/tools/gemini-image.md +5 -1
- package/src/prompts/tools/output.md +6 -2
- package/src/prompts/tools/task.md +68 -0
- package/src/prompts/tools/web-fetch.md +1 -0
- package/src/prompts/tools/web-search.md +2 -0
- package/src/utils/image-convert.ts +8 -2
- package/src/utils/image-magick.ts +247 -0
- package/src/utils/image-resize.ts +53 -13
- package/examples/custom-tools/question/index.ts +0 -84
- package/examples/custom-tools/subagent/README.md +0 -172
- package/examples/custom-tools/subagent/agents/planner.md +0 -37
- package/examples/custom-tools/subagent/agents/scout.md +0 -50
- package/examples/custom-tools/subagent/agents/worker.md +0 -24
- package/examples/custom-tools/subagent/agents.ts +0 -156
- package/examples/custom-tools/subagent/commands/implement-and-review.md +0 -10
- package/examples/custom-tools/subagent/commands/implement.md +0 -10
- package/examples/custom-tools/subagent/commands/scout-and-plan.md +0 -9
- package/examples/custom-tools/subagent/index.ts +0 -1002
- package/examples/sdk/05-tools.ts +0 -94
- package/examples/sdk/12-full-control.ts +0 -95
- package/src/prompts/browser.md +0 -71
package/docs/hooks.md
CHANGED
|
@@ -72,7 +72,7 @@ Additional paths via `settings.json`:
|
|
|
72
72
|
| --------------------------------- | --------------------------------------------- |
|
|
73
73
|
| `@oh-my-pi/pi-coding-agent/hooks` | Hook types (`HookAPI`, `HookContext`, events) |
|
|
74
74
|
| `@oh-my-pi/pi-coding-agent` | Additional types if needed |
|
|
75
|
-
| `@
|
|
75
|
+
| `@mariozechner/pi-ai` | AI utilities |
|
|
76
76
|
| `@oh-my-pi/pi-tui` | TUI components |
|
|
77
77
|
|
|
78
78
|
Node.js built-ins (`node:fs`, `node:path`, etc.) are also available.
|
|
@@ -548,7 +548,7 @@ Current model, or `undefined` if none selected yet. Use for LLM calls in hooks:
|
|
|
548
548
|
```typescript
|
|
549
549
|
if (ctx.model) {
|
|
550
550
|
const apiKey = await ctx.modelRegistry.getApiKey(ctx.model);
|
|
551
|
-
// Use with @
|
|
551
|
+
// Use with @mariozechner/pi-ai complete()
|
|
552
552
|
}
|
|
553
553
|
```
|
|
554
554
|
|
package/docs/sdk.md
CHANGED
|
@@ -248,7 +248,7 @@ const { session } = await createAgentSession({
|
|
|
248
248
|
### Model
|
|
249
249
|
|
|
250
250
|
```typescript
|
|
251
|
-
import { getModel } from "@
|
|
251
|
+
import { getModel } from "@mariozechner/pi-ai";
|
|
252
252
|
import { discoverAuthStorage, discoverModels } from "@oh-my-pi/pi-coding-agent";
|
|
253
253
|
|
|
254
254
|
const authStorage = discoverAuthStorage();
|
|
@@ -347,60 +347,60 @@ const { session } = await createAgentSession({
|
|
|
347
347
|
|
|
348
348
|
### Tools
|
|
349
349
|
|
|
350
|
-
|
|
351
|
-
import {
|
|
352
|
-
codingTools, // read, bash, edit, write (default)
|
|
353
|
-
readOnlyTools, // read, grep, find, ls
|
|
354
|
-
readTool,
|
|
355
|
-
bashTool,
|
|
356
|
-
editTool,
|
|
357
|
-
writeTool,
|
|
358
|
-
grepTool,
|
|
359
|
-
findTool,
|
|
360
|
-
lsTool,
|
|
361
|
-
} from "@oh-my-pi/pi-coding-agent";
|
|
350
|
+
By default, `createAgentSession` creates all built-in tools automatically. You can filter which tools are available using `toolNames`:
|
|
362
351
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
});
|
|
352
|
+
```typescript
|
|
353
|
+
// Use all built-in tools (default)
|
|
354
|
+
const { session } = await createAgentSession();
|
|
367
355
|
|
|
368
|
-
//
|
|
356
|
+
// Filter to specific tools
|
|
369
357
|
const { session } = await createAgentSession({
|
|
370
|
-
|
|
358
|
+
toolNames: ["read", "grep", "find", "ls"], // Read-only tools
|
|
371
359
|
});
|
|
372
360
|
```
|
|
373
361
|
|
|
374
|
-
####
|
|
362
|
+
#### Available Built-in Tools
|
|
363
|
+
|
|
364
|
+
All tools are defined in `BUILTIN_TOOLS`:
|
|
375
365
|
|
|
376
|
-
|
|
366
|
+
- `ask` - Interactive user prompts (requires UI)
|
|
367
|
+
- `bash` - Shell command execution
|
|
368
|
+
- `edit` - Surgical file editing
|
|
369
|
+
- `find` - File search by glob patterns
|
|
370
|
+
- `git` - Git operations (can be disabled via settings)
|
|
371
|
+
- `grep` - Content search with regex
|
|
372
|
+
- `ls` - Directory listing
|
|
373
|
+
- `lsp` - Language server protocol integration
|
|
374
|
+
- `notebook` - Jupyter notebook editing
|
|
375
|
+
- `output` - Task output retrieval
|
|
376
|
+
- `read` - File reading (text and images)
|
|
377
|
+
- `rulebook` - Rule reference (requires rules)
|
|
378
|
+
- `task` - Subagent spawning
|
|
379
|
+
- `web_fetch` - Web page fetching
|
|
380
|
+
- `web_search` - Web search
|
|
381
|
+
- `write` - File writing
|
|
382
|
+
|
|
383
|
+
#### Creating Tools Manually
|
|
384
|
+
|
|
385
|
+
For advanced use cases, you can create tools directly using `createTools`:
|
|
377
386
|
|
|
378
387
|
```typescript
|
|
379
388
|
import {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
createBashTool,
|
|
384
|
-
createEditTool,
|
|
385
|
-
createWriteTool,
|
|
386
|
-
createGrepTool,
|
|
387
|
-
createFindTool,
|
|
388
|
-
createLsTool,
|
|
389
|
+
BUILTIN_TOOLS,
|
|
390
|
+
createTools,
|
|
391
|
+
type ToolSession,
|
|
389
392
|
} from "@oh-my-pi/pi-coding-agent";
|
|
390
393
|
|
|
391
|
-
const
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
394
|
+
const session: ToolSession = {
|
|
395
|
+
cwd: "/path/to/project",
|
|
396
|
+
hasUI: false,
|
|
397
|
+
rulebookRules: [],
|
|
398
|
+
getSessionFile: () => null,
|
|
399
|
+
getSessionSpawns: () => "*",
|
|
400
|
+
getAvailableTools: () => Object.keys(BUILTIN_TOOLS),
|
|
401
|
+
};
|
|
398
402
|
|
|
399
|
-
|
|
400
|
-
const { session } = await createAgentSession({
|
|
401
|
-
cwd,
|
|
402
|
-
tools: [createReadTool(cwd), createBashTool(cwd), createGrepTool(cwd)],
|
|
403
|
-
});
|
|
403
|
+
const tools = await createTools(session);
|
|
404
404
|
```
|
|
405
405
|
|
|
406
406
|
**When you don't need factories:**
|
|
@@ -733,7 +733,7 @@ Project overrides global. Nested objects merge keys. Setters only modify global
|
|
|
733
733
|
All discovery functions accept optional `cwd` and `agentDir` parameters.
|
|
734
734
|
|
|
735
735
|
```typescript
|
|
736
|
-
import { getModel } from "@
|
|
736
|
+
import { getModel } from "@mariozechner/pi-ai";
|
|
737
737
|
import {
|
|
738
738
|
AuthStorage,
|
|
739
739
|
ModelRegistry,
|
|
@@ -806,7 +806,7 @@ interface CreateAgentSessionResult {
|
|
|
806
806
|
## Complete Example
|
|
807
807
|
|
|
808
808
|
```typescript
|
|
809
|
-
import { getModel } from "@
|
|
809
|
+
import { getModel } from "@mariozechner/pi-ai";
|
|
810
810
|
import { Type } from "@sinclair/typebox";
|
|
811
811
|
import {
|
|
812
812
|
AuthStorage,
|
|
@@ -943,17 +943,14 @@ buildSystemPrompt
|
|
|
943
943
|
SessionManager
|
|
944
944
|
SettingsManager
|
|
945
945
|
|
|
946
|
-
//
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
grepTool, findTool, lsTool
|
|
946
|
+
// Tool registry and factory
|
|
947
|
+
BUILTIN_TOOLS // Map of tool name to factory
|
|
948
|
+
createTools // Create all tools from ToolSession
|
|
949
|
+
type ToolSession // Session context for tool creation
|
|
951
950
|
|
|
952
|
-
//
|
|
953
|
-
createCodingTools
|
|
954
|
-
createReadOnlyTools
|
|
951
|
+
// Individual tool factories
|
|
955
952
|
createReadTool, createBashTool, createEditTool, createWriteTool
|
|
956
|
-
createGrepTool, createFindTool, createLsTool
|
|
953
|
+
createGrepTool, createFindTool, createLsTool, createGitTool
|
|
957
954
|
|
|
958
955
|
// Types
|
|
959
956
|
type CreateAgentSessionOptions
|
|
@@ -10,10 +10,6 @@ Each example uses the `subdirectory/index.ts` structure required for tool discov
|
|
|
10
10
|
|
|
11
11
|
Minimal example showing the basic structure of a custom tool.
|
|
12
12
|
|
|
13
|
-
### question/
|
|
14
|
-
|
|
15
|
-
Demonstrates `pi.ui.select()` for asking the user questions with options.
|
|
16
|
-
|
|
17
13
|
### todo/
|
|
18
14
|
|
|
19
15
|
Full-featured example demonstrating:
|
|
@@ -23,17 +19,6 @@ Full-featured example demonstrating:
|
|
|
23
19
|
- Proper branching support via details storage
|
|
24
20
|
- State management without external files
|
|
25
21
|
|
|
26
|
-
### subagent/
|
|
27
|
-
|
|
28
|
-
Delegate tasks to specialized subagents with isolated context windows. Includes:
|
|
29
|
-
|
|
30
|
-
- `index.ts` - The custom tool (single, parallel, and chain modes)
|
|
31
|
-
- `agents.ts` - Agent discovery helper
|
|
32
|
-
- `agents/` - Sample agent definitions (scout, planner, reviewer, worker)
|
|
33
|
-
- `commands/` - Workflow presets (/implement, /scout-and-plan, /implement-and-review)
|
|
34
|
-
|
|
35
|
-
See [subagent/README.md](subagent/README.md) for full documentation.
|
|
36
|
-
|
|
37
22
|
## Usage
|
|
38
23
|
|
|
39
24
|
```bash
|
|
@@ -63,7 +48,7 @@ See [docs/custom-tools.md](../../docs/custom-tools.md) for full documentation.
|
|
|
63
48
|
|
|
64
49
|
```typescript
|
|
65
50
|
import { Type } from "@sinclair/typebox";
|
|
66
|
-
import { StringEnum } from "@
|
|
51
|
+
import { StringEnum } from "@mariozechner/pi-ai";
|
|
67
52
|
import { Text } from "@oh-my-pi/pi-tui";
|
|
68
53
|
import type { CustomToolFactory } from "@oh-my-pi/pi-coding-agent";
|
|
69
54
|
|
|
@@ -114,7 +99,7 @@ renderResult(result, { expanded, isPartial }, theme) {
|
|
|
114
99
|
**Use StringEnum for string parameters** (required for Google API compatibility):
|
|
115
100
|
|
|
116
101
|
```typescript
|
|
117
|
-
import { StringEnum } from "@
|
|
102
|
+
import { StringEnum } from "@mariozechner/pi-ai";
|
|
118
103
|
|
|
119
104
|
// Good
|
|
120
105
|
action: StringEnum(["list", "add"] as const);
|
|
@@ -16,54 +16,54 @@ cp permission-gate.ts ~/.omp/agent/extensions/
|
|
|
16
16
|
|
|
17
17
|
### Lifecycle & Safety
|
|
18
18
|
|
|
19
|
-
| Extension
|
|
20
|
-
|
|
21
|
-
| `permission-gate.ts`
|
|
22
|
-
| `protected-paths.ts`
|
|
23
|
-
| `confirm-destructive.ts` | Confirms before destructive session actions (clear, switch, branch)
|
|
24
|
-
| `dirty-repo-guard.ts`
|
|
19
|
+
| Extension | Description |
|
|
20
|
+
| ------------------------ | ---------------------------------------------------------------------------- |
|
|
21
|
+
| `permission-gate.ts` | Prompts for confirmation before dangerous bash commands (rm -rf, sudo, etc.) |
|
|
22
|
+
| `protected-paths.ts` | Blocks writes to protected paths (.env, .git/, node_modules/) |
|
|
23
|
+
| `confirm-destructive.ts` | Confirms before destructive session actions (clear, switch, branch) |
|
|
24
|
+
| `dirty-repo-guard.ts` | Prevents session changes with uncommitted git changes |
|
|
25
25
|
|
|
26
26
|
### Custom Tools
|
|
27
27
|
|
|
28
|
-
| Extension
|
|
29
|
-
|
|
30
|
-
| `todo.ts`
|
|
31
|
-
| `hello.ts`
|
|
32
|
-
| `question.ts` | Demonstrates `ctx.ui.select()` for asking the user questions
|
|
33
|
-
| `subagent/`
|
|
28
|
+
| Extension | Description |
|
|
29
|
+
| ------------- | ----------------------------------------------------------------------------- |
|
|
30
|
+
| `todo.ts` | Todo list tool + `/todos` command with custom rendering and state persistence |
|
|
31
|
+
| `hello.ts` | Minimal custom tool example |
|
|
32
|
+
| `question.ts` | Demonstrates `ctx.ui.select()` for asking the user questions |
|
|
33
|
+
| `subagent/` | Delegate tasks to specialized subagents with isolated context windows |
|
|
34
34
|
|
|
35
35
|
### Commands & UI
|
|
36
36
|
|
|
37
|
-
| Extension
|
|
38
|
-
|
|
39
|
-
| `plan-mode.ts`
|
|
40
|
-
| `tools.ts`
|
|
41
|
-
| `handoff.ts`
|
|
42
|
-
| `qna.ts`
|
|
43
|
-
| `status-line.ts` | Shows turn progress in footer via `ctx.ui.setStatus()` with themed colors
|
|
44
|
-
| `snake.ts`
|
|
37
|
+
| Extension | Description |
|
|
38
|
+
| ---------------- | ------------------------------------------------------------------------------ |
|
|
39
|
+
| `plan-mode.ts` | Claude Code-style plan mode for read-only exploration with `/plan` command |
|
|
40
|
+
| `tools.ts` | Interactive `/tools` command to enable/disable tools with session persistence |
|
|
41
|
+
| `handoff.ts` | Transfer context to a new focused session via `/handoff <goal>` |
|
|
42
|
+
| `qna.ts` | Extracts questions from last response into editor via `ctx.ui.setEditorText()` |
|
|
43
|
+
| `status-line.ts` | Shows turn progress in footer via `ctx.ui.setStatus()` with themed colors |
|
|
44
|
+
| `snake.ts` | Snake game with custom UI, keyboard handling, and session persistence |
|
|
45
45
|
|
|
46
46
|
### Git Integration
|
|
47
47
|
|
|
48
|
-
| Extension
|
|
49
|
-
|
|
50
|
-
| `git-checkpoint.ts`
|
|
51
|
-
| `auto-commit-on-exit.ts` | Auto-commits on exit using last assistant message for commit message
|
|
48
|
+
| Extension | Description |
|
|
49
|
+
| ------------------------ | ------------------------------------------------------------------------- |
|
|
50
|
+
| `git-checkpoint.ts` | Creates git stash checkpoints at each turn for code restoration on branch |
|
|
51
|
+
| `auto-commit-on-exit.ts` | Auto-commits on exit using last assistant message for commit message |
|
|
52
52
|
|
|
53
53
|
### System Prompt & Compaction
|
|
54
54
|
|
|
55
|
-
| Extension
|
|
56
|
-
|
|
57
|
-
| `pirate.ts`
|
|
58
|
-
| `custom-compaction.ts` | Custom compaction that summarizes entire conversation
|
|
55
|
+
| Extension | Description |
|
|
56
|
+
| ---------------------- | --------------------------------------------------------------------- |
|
|
57
|
+
| `pirate.ts` | Demonstrates `systemPromptAppend` to dynamically modify system prompt |
|
|
58
|
+
| `custom-compaction.ts` | Custom compaction that summarizes entire conversation |
|
|
59
59
|
|
|
60
60
|
### External Dependencies
|
|
61
61
|
|
|
62
|
-
| Extension
|
|
63
|
-
|
|
62
|
+
| Extension | Description |
|
|
63
|
+
| ----------------- | ------------------------------------------------------------------------- |
|
|
64
64
|
| `chalk-logger.ts` | Uses chalk from parent node_modules (demonstrates jiti module resolution) |
|
|
65
|
-
| `with-deps/`
|
|
66
|
-
| `file-trigger.ts` | Watches a trigger file and injects contents into conversation
|
|
65
|
+
| `with-deps/` | Extension with its own package.json and dependencies |
|
|
66
|
+
| `file-trigger.ts` | Watches a trigger file and injects contents into conversation |
|
|
67
67
|
|
|
68
68
|
## Writing Extensions
|
|
69
69
|
|
|
@@ -74,68 +74,70 @@ import type { ExtensionAPI } from "@oh-my-pi/pi-coding-agent";
|
|
|
74
74
|
import { Type } from "@sinclair/typebox";
|
|
75
75
|
|
|
76
76
|
export default function (pi: ExtensionAPI) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
77
|
+
// Subscribe to lifecycle events
|
|
78
|
+
pi.on("tool_call", async (event, ctx) => {
|
|
79
|
+
if (event.toolName === "bash" && event.input.command?.includes("rm -rf")) {
|
|
80
|
+
const ok = await ctx.ui.confirm("Dangerous!", "Allow rm -rf?");
|
|
81
|
+
if (!ok) return { block: true, reason: "Blocked by user" };
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Register custom tools
|
|
86
|
+
pi.registerTool({
|
|
87
|
+
name: "greet",
|
|
88
|
+
label: "Greeting",
|
|
89
|
+
description: "Generate a greeting",
|
|
90
|
+
parameters: Type.Object({
|
|
91
|
+
name: Type.String({ description: "Name to greet" }),
|
|
92
|
+
}),
|
|
93
|
+
async execute(toolCallId, params, onUpdate, ctx, signal) {
|
|
94
|
+
return {
|
|
95
|
+
content: [{ type: "text", text: `Hello, ${params.name}!` }],
|
|
96
|
+
details: {},
|
|
97
|
+
};
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Register commands
|
|
102
|
+
pi.registerCommand("hello", {
|
|
103
|
+
description: "Say hello",
|
|
104
|
+
handler: async (args, ctx) => {
|
|
105
|
+
ctx.ui.notify("Hello!", "info");
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
108
|
}
|
|
109
109
|
```
|
|
110
110
|
|
|
111
111
|
## Key Patterns
|
|
112
112
|
|
|
113
113
|
**Use StringEnum for string parameters** (required for Google API compatibility):
|
|
114
|
+
|
|
114
115
|
```typescript
|
|
115
|
-
import { StringEnum } from "@
|
|
116
|
+
import { StringEnum } from "@mariozechner/pi-ai";
|
|
116
117
|
|
|
117
118
|
// Good
|
|
118
|
-
action: StringEnum(["list", "add"] as const)
|
|
119
|
+
action: StringEnum(["list", "add"] as const);
|
|
119
120
|
|
|
120
121
|
// Bad - doesn't work with Google
|
|
121
|
-
action: Type.Union([Type.Literal("list"), Type.Literal("add")])
|
|
122
|
+
action: Type.Union([Type.Literal("list"), Type.Literal("add")]);
|
|
122
123
|
```
|
|
123
124
|
|
|
124
125
|
**State persistence via details:**
|
|
126
|
+
|
|
125
127
|
```typescript
|
|
126
128
|
// Store state in tool result details for proper branching support
|
|
127
129
|
return {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
+
content: [{ type: "text", text: "Done" }],
|
|
131
|
+
details: { todos: [...todos], nextId }, // Persisted in session
|
|
130
132
|
};
|
|
131
133
|
|
|
132
134
|
// Reconstruct on session events
|
|
133
135
|
pi.on("session_start", async (_event, ctx) => {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
136
|
+
for (const entry of ctx.sessionManager.getBranch()) {
|
|
137
|
+
if (entry.type === "message" && entry.message.toolName === "my_tool") {
|
|
138
|
+
const details = entry.message.details;
|
|
139
|
+
// Reconstruct state from details
|
|
140
|
+
}
|
|
141
|
+
}
|
|
140
142
|
});
|
|
141
143
|
```
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* correct for that point in history.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import { StringEnum } from "@
|
|
13
|
+
import { StringEnum } from "@mariozechner/pi-ai";
|
|
14
14
|
import type { ExtensionAPI, ExtensionContext, Theme } from "@oh-my-pi/pi-coding-agent";
|
|
15
15
|
import { matchesKey, Text, truncateToWidth } from "@oh-my-pi/pi-tui";
|
|
16
16
|
import { Type } from "@sinclair/typebox";
|
|
@@ -261,10 +261,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
261
261
|
case "add": {
|
|
262
262
|
const added = todoList[todoList.length - 1];
|
|
263
263
|
return new Text(
|
|
264
|
-
theme.fg("success", "✓ Added ") +
|
|
265
|
-
theme.fg("accent", `#${added.id}`) +
|
|
266
|
-
" " +
|
|
267
|
-
theme.fg("muted", added.text),
|
|
264
|
+
`${theme.fg("success", "✓ Added ") + theme.fg("accent", `#${added.id}`)} ${theme.fg("muted", added.text)}`,
|
|
268
265
|
0,
|
|
269
266
|
0,
|
|
270
267
|
);
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* omp --hook examples/hooks/custom-compaction.ts
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import { complete, getModel } from "@
|
|
16
|
+
import { complete, getModel } from "@mariozechner/pi-ai";
|
|
17
17
|
import type { HookAPI } from "@oh-my-pi/pi-coding-agent";
|
|
18
18
|
import { convertToLlm, serializeConversation } from "@oh-my-pi/pi-coding-agent";
|
|
19
19
|
|
|
@@ -42,9 +42,7 @@ export default function (pi: HookAPI) {
|
|
|
42
42
|
const allMessages = [...messagesToSummarize, ...turnPrefixMessages];
|
|
43
43
|
|
|
44
44
|
ctx.ui.notify(
|
|
45
|
-
`Custom compaction: summarizing ${allMessages.length} messages (${tokensBefore.toLocaleString()} tokens) with ${
|
|
46
|
-
model.id
|
|
47
|
-
}...`,
|
|
45
|
+
`Custom compaction: summarizing ${allMessages.length} messages (${tokensBefore.toLocaleString()} tokens) with ${model.id}...`,
|
|
48
46
|
"info",
|
|
49
47
|
);
|
|
50
48
|
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* The generated prompt appears as a draft in the editor for review/editing.
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import { complete, type Message } from "@
|
|
15
|
+
import { complete, type Message } from "@mariozechner/pi-ai";
|
|
16
16
|
import type { HookAPI, SessionEntry } from "@oh-my-pi/pi-coding-agent";
|
|
17
17
|
import { BorderedLoader, convertToLlm, serializeConversation } from "@oh-my-pi/pi-coding-agent";
|
|
18
18
|
|
package/examples/hooks/qna.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* 3. Loads the result into the editor for user to fill in answers
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { complete, type UserMessage } from "@
|
|
10
|
+
import { complete, type UserMessage } from "@mariozechner/pi-ai";
|
|
11
11
|
import type { HookAPI } from "@oh-my-pi/pi-coding-agent";
|
|
12
12
|
import { BorderedLoader } from "@oh-my-pi/pi-coding-agent";
|
|
13
13
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Shows how to select a specific model and thinking level.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { getModel } from "@
|
|
7
|
+
import { getModel } from "@mariozechner/pi-ai";
|
|
8
8
|
import { createAgentSession, discoverAuthStorage, discoverModels } from "@oh-my-pi/pi-coding-agent";
|
|
9
9
|
|
|
10
10
|
// Set up auth storage and model registry
|
package/examples/sdk/README.md
CHANGED
|
@@ -29,7 +29,7 @@ npx tsx examples/sdk/01-minimal.ts
|
|
|
29
29
|
## Quick Reference
|
|
30
30
|
|
|
31
31
|
```typescript
|
|
32
|
-
import { getModel } from "@
|
|
32
|
+
import { getModel } from "@mariozechner/pi-ai";
|
|
33
33
|
import {
|
|
34
34
|
AuthStorage,
|
|
35
35
|
createAgentSession,
|
|
@@ -44,12 +44,8 @@ import {
|
|
|
44
44
|
buildSystemPrompt,
|
|
45
45
|
ModelRegistry,
|
|
46
46
|
SessionManager,
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
readTool,
|
|
50
|
-
bashTool,
|
|
51
|
-
editTool,
|
|
52
|
-
writeTool,
|
|
47
|
+
BUILTIN_TOOLS,
|
|
48
|
+
createTools,
|
|
53
49
|
} from "@oh-my-pi/pi-coding-agent";
|
|
54
50
|
|
|
55
51
|
// Auth and models setup
|
|
@@ -70,8 +66,8 @@ const { session } = await createAgentSession({
|
|
|
70
66
|
modelRegistry,
|
|
71
67
|
});
|
|
72
68
|
|
|
73
|
-
// Read-only
|
|
74
|
-
const { session } = await createAgentSession({
|
|
69
|
+
// Read-only tools
|
|
70
|
+
const { session } = await createAgentSession({ toolNames: ["read", "grep", "find", "ls"], authStorage, modelRegistry });
|
|
75
71
|
|
|
76
72
|
// In-memory
|
|
77
73
|
const { session } = await createAgentSession({
|
|
@@ -90,7 +86,7 @@ const { session } = await createAgentSession({
|
|
|
90
86
|
authStorage: customAuth,
|
|
91
87
|
modelRegistry: customRegistry,
|
|
92
88
|
systemPrompt: "You are helpful.",
|
|
93
|
-
|
|
89
|
+
toolNames: ["read", "bash"],
|
|
94
90
|
customTools: [{ tool: myTool }],
|
|
95
91
|
hooks: [{ factory: myHook }],
|
|
96
92
|
skills: [],
|
|
@@ -119,7 +115,7 @@ await session.prompt("Hello");
|
|
|
119
115
|
| `model` | From settings/first available | Model to use |
|
|
120
116
|
| `thinkingLevel` | From settings/"off" | off, low, medium, high |
|
|
121
117
|
| `systemPrompt` | Discovered | String or `(default) => modified` |
|
|
122
|
-
| `
|
|
118
|
+
| `toolNames` | All built-in tools | Filter which tools to include |
|
|
123
119
|
| `customTools` | Discovered | Replaces discovery |
|
|
124
120
|
| `additionalCustomToolPaths` | `[]` | Merge with discovery |
|
|
125
121
|
| `hooks` | Discovered | Replaces discovery |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oh-my-pi/pi-coding-agent",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.24.0",
|
|
4
4
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"ompConfig": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"CHANGELOG.md"
|
|
30
30
|
],
|
|
31
31
|
"scripts": {
|
|
32
|
-
"check": "tsgo
|
|
32
|
+
"check": "tsgo -p tsconfig.check.json",
|
|
33
33
|
"clean": "rm -rf dist",
|
|
34
34
|
"build": "tsgo -p tsconfig.build.json && chmod +x dist/cli.js",
|
|
35
35
|
"build:binary": "bun build --compile ./src/cli.ts --outfile dist/omp",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"prepublishOnly": "bun run generate-template && bun run clean && bun run build"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@
|
|
43
|
-
"@oh-my-pi/pi-
|
|
44
|
-
"@oh-my-pi/pi-git-tool": "3.
|
|
45
|
-
"@oh-my-pi/pi-tui": "3.
|
|
42
|
+
"@mariozechner/pi-ai": "^0.37.4",
|
|
43
|
+
"@oh-my-pi/pi-agent-core": "3.24.0",
|
|
44
|
+
"@oh-my-pi/pi-git-tool": "3.24.0",
|
|
45
|
+
"@oh-my-pi/pi-tui": "3.24.0",
|
|
46
46
|
"@openai/agents": "^0.3.7",
|
|
47
47
|
"@sinclair/typebox": "^0.34.46",
|
|
48
48
|
"ajv": "^8.17.1",
|
package/src/cli/args.ts
CHANGED
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
6
6
|
import chalk from "chalk";
|
|
7
7
|
import { APP_NAME, CONFIG_DIR_NAME, ENV_AGENT_DIR } from "../config";
|
|
8
|
-
import {
|
|
8
|
+
import { BUILTIN_TOOLS } from "../core/tools/index";
|
|
9
9
|
|
|
10
10
|
export type Mode = "text" | "json" | "rpc";
|
|
11
11
|
|
|
12
12
|
export interface Args {
|
|
13
|
+
cwd?: string;
|
|
13
14
|
provider?: string;
|
|
14
15
|
model?: string;
|
|
15
16
|
smol?: string;
|
|
@@ -27,7 +28,7 @@ export interface Args {
|
|
|
27
28
|
session?: string;
|
|
28
29
|
sessionDir?: string;
|
|
29
30
|
models?: string[];
|
|
30
|
-
tools?:
|
|
31
|
+
tools?: string[];
|
|
31
32
|
hooks?: string[];
|
|
32
33
|
extensions?: string[];
|
|
33
34
|
print?: boolean;
|
|
@@ -94,13 +95,15 @@ export function parseArgs(args: string[], extensionFlags?: Map<string, { type: "
|
|
|
94
95
|
result.models = args[++i].split(",").map((s) => s.trim());
|
|
95
96
|
} else if (arg === "--tools" && i + 1 < args.length) {
|
|
96
97
|
const toolNames = args[++i].split(",").map((s) => s.trim());
|
|
97
|
-
const validTools:
|
|
98
|
+
const validTools: string[] = [];
|
|
98
99
|
for (const name of toolNames) {
|
|
99
|
-
if (name in
|
|
100
|
-
validTools.push(name
|
|
100
|
+
if (name in BUILTIN_TOOLS) {
|
|
101
|
+
validTools.push(name);
|
|
101
102
|
} else {
|
|
102
103
|
console.error(
|
|
103
|
-
chalk.yellow(
|
|
104
|
+
chalk.yellow(
|
|
105
|
+
`Warning: Unknown tool "${name}". Valid tools: ${Object.keys(BUILTIN_TOOLS).join(", ")}`,
|
|
106
|
+
),
|
|
104
107
|
);
|
|
105
108
|
}
|
|
106
109
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
6
6
|
import { resolve } from "node:path";
|
|
7
|
-
import type { ImageContent } from "@
|
|
7
|
+
import type { ImageContent } from "@mariozechner/pi-ai";
|
|
8
8
|
import chalk from "chalk";
|
|
9
9
|
import { resolveReadPath } from "../core/tools/path-utils";
|
|
10
10
|
import { formatDimensionNote, resizeImage } from "../utils/image-resize";
|
package/src/cli/list-models.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* List available models with optional fuzzy search
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type { Api, Model } from "@
|
|
5
|
+
import type { Api, Model } from "@mariozechner/pi-ai";
|
|
6
6
|
import type { ModelRegistry } from "../core/model-registry";
|
|
7
7
|
import { fuzzyFilter } from "../utils/fuzzy";
|
|
8
8
|
|