@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.
Files changed (123) hide show
  1. package/CHANGELOG.md +107 -8
  2. package/docs/custom-tools.md +3 -3
  3. package/docs/extensions.md +226 -220
  4. package/docs/hooks.md +2 -2
  5. package/docs/sdk.md +50 -53
  6. package/examples/custom-tools/README.md +2 -17
  7. package/examples/extensions/README.md +76 -74
  8. package/examples/extensions/todo.ts +2 -5
  9. package/examples/hooks/custom-compaction.ts +2 -4
  10. package/examples/hooks/handoff.ts +1 -1
  11. package/examples/hooks/qna.ts +1 -1
  12. package/examples/sdk/02-custom-model.ts +1 -1
  13. package/examples/sdk/README.md +7 -11
  14. package/package.json +6 -6
  15. package/src/cli/args.ts +9 -6
  16. package/src/cli/file-processor.ts +1 -1
  17. package/src/cli/list-models.ts +1 -1
  18. package/src/core/agent-session.ts +16 -5
  19. package/src/core/auth-storage.ts +1 -1
  20. package/src/core/compaction/branch-summarization.ts +2 -2
  21. package/src/core/compaction/compaction.ts +2 -2
  22. package/src/core/compaction/utils.ts +1 -1
  23. package/src/core/custom-tools/types.ts +1 -1
  24. package/src/core/custom-tools/wrapper.ts +0 -1
  25. package/src/core/extensions/index.ts +1 -6
  26. package/src/core/extensions/runner.ts +1 -1
  27. package/src/core/extensions/types.ts +1 -1
  28. package/src/core/extensions/wrapper.ts +1 -8
  29. package/src/core/file-mentions.ts +5 -8
  30. package/src/core/hooks/runner.ts +2 -2
  31. package/src/core/hooks/types.ts +1 -1
  32. package/src/core/messages.ts +1 -1
  33. package/src/core/model-registry.ts +1 -1
  34. package/src/core/model-resolver.ts +1 -1
  35. package/src/core/sdk.ts +64 -105
  36. package/src/core/session-manager.ts +18 -22
  37. package/src/core/settings-manager.ts +66 -1
  38. package/src/core/slash-commands.ts +12 -5
  39. package/src/core/system-prompt.ts +49 -36
  40. package/src/core/title-generator.ts +2 -2
  41. package/src/core/tools/ask.ts +98 -4
  42. package/src/core/tools/bash-interceptor.ts +11 -4
  43. package/src/core/tools/bash.ts +121 -5
  44. package/src/core/tools/context.ts +7 -0
  45. package/src/core/tools/edit-diff.ts +73 -24
  46. package/src/core/tools/edit.ts +221 -34
  47. package/src/core/tools/exa/render.ts +4 -16
  48. package/src/core/tools/find.ts +149 -5
  49. package/src/core/tools/gemini-image.ts +279 -56
  50. package/src/core/tools/git.ts +17 -3
  51. package/src/core/tools/grep.ts +185 -5
  52. package/src/core/tools/index.test.ts +180 -0
  53. package/src/core/tools/index.ts +96 -242
  54. package/src/core/tools/ls.ts +133 -5
  55. package/src/core/tools/lsp/index.ts +32 -29
  56. package/src/core/tools/lsp/render.ts +21 -22
  57. package/src/core/tools/notebook.ts +112 -4
  58. package/src/core/tools/output.ts +175 -15
  59. package/src/core/tools/read.ts +127 -25
  60. package/src/core/tools/render-utils.ts +241 -0
  61. package/src/core/tools/renderers.ts +40 -828
  62. package/src/core/tools/review.ts +26 -25
  63. package/src/core/tools/rulebook.ts +11 -3
  64. package/src/core/tools/task/agents.ts +28 -7
  65. package/src/core/tools/task/discovery.ts +0 -6
  66. package/src/core/tools/task/executor.ts +264 -254
  67. package/src/core/tools/task/index.ts +48 -208
  68. package/src/core/tools/task/render.ts +26 -11
  69. package/src/core/tools/task/types.ts +7 -12
  70. package/src/core/tools/task/worker-protocol.ts +17 -0
  71. package/src/core/tools/task/worker.ts +238 -0
  72. package/src/core/tools/truncate.ts +27 -1
  73. package/src/core/tools/web-fetch.ts +25 -49
  74. package/src/core/tools/web-search/index.ts +132 -46
  75. package/src/core/tools/web-search/providers/anthropic.ts +7 -2
  76. package/src/core/tools/web-search/providers/exa.ts +2 -1
  77. package/src/core/tools/web-search/providers/perplexity.ts +6 -1
  78. package/src/core/tools/web-search/render.ts +6 -4
  79. package/src/core/tools/web-search/types.ts +13 -0
  80. package/src/core/tools/write.ts +96 -14
  81. package/src/core/voice.ts +1 -1
  82. package/src/discovery/helpers.test.ts +1 -1
  83. package/src/index.ts +5 -16
  84. package/src/main.ts +5 -5
  85. package/src/modes/interactive/components/assistant-message.ts +1 -1
  86. package/src/modes/interactive/components/custom-message.ts +1 -1
  87. package/src/modes/interactive/components/extensions/inspector-panel.ts +25 -22
  88. package/src/modes/interactive/components/extensions/state-manager.ts +12 -0
  89. package/src/modes/interactive/components/footer.ts +1 -1
  90. package/src/modes/interactive/components/hook-message.ts +1 -1
  91. package/src/modes/interactive/components/model-selector.ts +1 -1
  92. package/src/modes/interactive/components/oauth-selector.ts +1 -1
  93. package/src/modes/interactive/components/settings-defs.ts +49 -0
  94. package/src/modes/interactive/components/status-line.ts +1 -1
  95. package/src/modes/interactive/components/tool-execution.ts +93 -538
  96. package/src/modes/interactive/interactive-mode.ts +19 -7
  97. package/src/modes/interactive/theme/theme.ts +4 -4
  98. package/src/modes/print-mode.ts +1 -1
  99. package/src/modes/rpc/rpc-client.ts +1 -1
  100. package/src/modes/rpc/rpc-types.ts +1 -1
  101. package/src/prompts/system-prompt.md +4 -0
  102. package/src/prompts/task.md +0 -7
  103. package/src/prompts/tools/gemini-image.md +5 -1
  104. package/src/prompts/tools/output.md +6 -2
  105. package/src/prompts/tools/task.md +68 -0
  106. package/src/prompts/tools/web-fetch.md +1 -0
  107. package/src/prompts/tools/web-search.md +2 -0
  108. package/src/utils/image-convert.ts +8 -2
  109. package/src/utils/image-magick.ts +247 -0
  110. package/src/utils/image-resize.ts +53 -13
  111. package/examples/custom-tools/question/index.ts +0 -84
  112. package/examples/custom-tools/subagent/README.md +0 -172
  113. package/examples/custom-tools/subagent/agents/planner.md +0 -37
  114. package/examples/custom-tools/subagent/agents/scout.md +0 -50
  115. package/examples/custom-tools/subagent/agents/worker.md +0 -24
  116. package/examples/custom-tools/subagent/agents.ts +0 -156
  117. package/examples/custom-tools/subagent/commands/implement-and-review.md +0 -10
  118. package/examples/custom-tools/subagent/commands/implement.md +0 -10
  119. package/examples/custom-tools/subagent/commands/scout-and-plan.md +0 -9
  120. package/examples/custom-tools/subagent/index.ts +0 -1002
  121. package/examples/sdk/05-tools.ts +0 -94
  122. package/examples/sdk/12-full-control.ts +0 -95
  123. 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
- | `@oh-my-pi/pi-ai` | AI utilities |
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 @oh-my-pi/pi-ai complete()
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 "@oh-my-pi/pi-ai";
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
- ```typescript
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
- // Use built-in tool set
364
- const { session } = await createAgentSession({
365
- tools: readOnlyTools,
366
- });
352
+ ```typescript
353
+ // Use all built-in tools (default)
354
+ const { session } = await createAgentSession();
367
355
 
368
- // Pick specific tools
356
+ // Filter to specific tools
369
357
  const { session } = await createAgentSession({
370
- tools: [readTool, bashTool, grepTool],
358
+ toolNames: ["read", "grep", "find", "ls"], // Read-only tools
371
359
  });
372
360
  ```
373
361
 
374
- #### Tools with Custom cwd
362
+ #### Available Built-in Tools
363
+
364
+ All tools are defined in `BUILTIN_TOOLS`:
375
365
 
376
- **Important:** The pre-built tool instances (`readTool`, `bashTool`, etc.) use `process.cwd()` for path resolution. When you specify a custom `cwd` AND provide explicit `tools`, you must use the tool factory functions to ensure paths resolve correctly:
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
- createCodingTools, // Creates [read, bash, edit, write] for specific cwd
381
- createReadOnlyTools, // Creates [read, grep, find, ls] for specific cwd
382
- createReadTool,
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 cwd = "/path/to/project";
392
-
393
- // Use factory for tool sets
394
- const { session } = await createAgentSession({
395
- cwd,
396
- tools: createCodingTools(cwd), // Tools resolve paths relative to cwd
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
- // Or pick specific tools
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 "@oh-my-pi/pi-ai";
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 "@oh-my-pi/pi-ai";
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
- // Built-in tools (use process.cwd())
947
- codingTools
948
- readOnlyTools
949
- readTool, bashTool, editTool, writeTool
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
- // Tool factories (for custom cwd)
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 "@oh-my-pi/pi-ai";
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 "@oh-my-pi/pi-ai";
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 | 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 |
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 | 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 |
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 | 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 |
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 | 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 |
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 | Description |
56
- |-----------|-------------|
57
- | `pirate.ts` | Demonstrates `systemPromptAppend` to dynamically modify system prompt |
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 | Description |
63
- |-----------|-------------|
62
+ | Extension | Description |
63
+ | ----------------- | ------------------------------------------------------------------------- |
64
64
  | `chalk-logger.ts` | Uses chalk from parent node_modules (demonstrates jiti module resolution) |
65
- | `with-deps/` | Extension with its own package.json and dependencies |
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
- // 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
- });
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 "@oh-my-pi/pi-ai";
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
- content: [{ type: "text", text: "Done" }],
129
- details: { todos: [...todos], nextId }, // Persisted in session
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
- for (const entry of ctx.sessionManager.getBranch()) {
135
- if (entry.type === "message" && entry.message.toolName === "my_tool") {
136
- const details = entry.message.details;
137
- // Reconstruct state from details
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 "@oh-my-pi/pi-ai";
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 "@oh-my-pi/pi-ai";
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 "@oh-my-pi/pi-ai";
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
 
@@ -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 "@oh-my-pi/pi-ai";
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 "@oh-my-pi/pi-ai";
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
@@ -29,7 +29,7 @@ npx tsx examples/sdk/01-minimal.ts
29
29
  ## Quick Reference
30
30
 
31
31
  ```typescript
32
- import { getModel } from "@oh-my-pi/pi-ai";
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
- codingTools,
48
- readOnlyTools,
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({ tools: readOnlyTools, authStorage, modelRegistry });
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
- tools: [readTool, bashTool],
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
- | `tools` | `codingTools` | Built-in tools |
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.20.1",
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 --noEmit",
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
- "@oh-my-pi/pi-agent-core": "3.20.1",
43
- "@oh-my-pi/pi-ai": "3.20.1",
44
- "@oh-my-pi/pi-git-tool": "3.20.1",
45
- "@oh-my-pi/pi-tui": "3.20.1",
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 { allTools, type ToolName } from "../core/tools/index";
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?: ToolName[];
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: ToolName[] = [];
98
+ const validTools: string[] = [];
98
99
  for (const name of toolNames) {
99
- if (name in allTools) {
100
- validTools.push(name as ToolName);
100
+ if (name in BUILTIN_TOOLS) {
101
+ validTools.push(name);
101
102
  } else {
102
103
  console.error(
103
- chalk.yellow(`Warning: Unknown tool "${name}". Valid tools: ${Object.keys(allTools).join(", ")}`),
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 "@oh-my-pi/pi-ai";
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";
@@ -2,7 +2,7 @@
2
2
  * List available models with optional fuzzy search
3
3
  */
4
4
 
5
- import type { Api, Model } from "@oh-my-pi/pi-ai";
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