@oh-my-pi/pi-coding-agent 3.21.0 → 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 (66) hide show
  1. package/CHANGELOG.md +40 -1
  2. package/docs/sdk.md +47 -50
  3. package/examples/custom-tools/README.md +0 -15
  4. package/examples/hooks/custom-compaction.ts +1 -3
  5. package/examples/sdk/README.md +6 -10
  6. package/package.json +5 -5
  7. package/src/cli/args.ts +9 -6
  8. package/src/core/agent-session.ts +3 -3
  9. package/src/core/custom-tools/wrapper.ts +0 -1
  10. package/src/core/extensions/index.ts +1 -6
  11. package/src/core/extensions/wrapper.ts +0 -7
  12. package/src/core/file-mentions.ts +5 -8
  13. package/src/core/sdk.ts +41 -111
  14. package/src/core/session-manager.ts +7 -0
  15. package/src/core/system-prompt.ts +22 -33
  16. package/src/core/tools/ask.ts +14 -7
  17. package/src/core/tools/bash-interceptor.ts +4 -4
  18. package/src/core/tools/bash.ts +19 -9
  19. package/src/core/tools/context.ts +7 -0
  20. package/src/core/tools/edit.ts +8 -15
  21. package/src/core/tools/exa/render.ts +4 -16
  22. package/src/core/tools/find.ts +7 -18
  23. package/src/core/tools/git.ts +13 -3
  24. package/src/core/tools/grep.ts +7 -18
  25. package/src/core/tools/index.test.ts +180 -0
  26. package/src/core/tools/index.ts +94 -237
  27. package/src/core/tools/ls.ts +4 -9
  28. package/src/core/tools/lsp/index.ts +32 -29
  29. package/src/core/tools/lsp/render.ts +7 -28
  30. package/src/core/tools/notebook.ts +3 -5
  31. package/src/core/tools/output.ts +5 -17
  32. package/src/core/tools/read.ts +8 -19
  33. package/src/core/tools/review.ts +0 -18
  34. package/src/core/tools/rulebook.ts +8 -2
  35. package/src/core/tools/task/agents.ts +28 -7
  36. package/src/core/tools/task/discovery.ts +0 -6
  37. package/src/core/tools/task/executor.ts +264 -254
  38. package/src/core/tools/task/index.ts +45 -220
  39. package/src/core/tools/task/render.ts +21 -11
  40. package/src/core/tools/task/types.ts +6 -11
  41. package/src/core/tools/task/worker-protocol.ts +17 -0
  42. package/src/core/tools/task/worker.ts +238 -0
  43. package/src/core/tools/web-fetch.ts +4 -36
  44. package/src/core/tools/web-search/index.ts +2 -1
  45. package/src/core/tools/web-search/render.ts +1 -4
  46. package/src/core/tools/write.ts +7 -15
  47. package/src/discovery/helpers.test.ts +1 -1
  48. package/src/index.ts +5 -16
  49. package/src/main.ts +4 -4
  50. package/src/modes/interactive/theme/theme.ts +4 -4
  51. package/src/prompts/task.md +0 -7
  52. package/src/prompts/tools/output.md +2 -2
  53. package/src/prompts/tools/task.md +68 -0
  54. package/examples/custom-tools/question/index.ts +0 -84
  55. package/examples/custom-tools/subagent/README.md +0 -172
  56. package/examples/custom-tools/subagent/agents/planner.md +0 -37
  57. package/examples/custom-tools/subagent/agents/scout.md +0 -50
  58. package/examples/custom-tools/subagent/agents/worker.md +0 -24
  59. package/examples/custom-tools/subagent/agents.ts +0 -156
  60. package/examples/custom-tools/subagent/commands/implement-and-review.md +0 -10
  61. package/examples/custom-tools/subagent/commands/implement.md +0 -10
  62. package/examples/custom-tools/subagent/commands/scout-and-plan.md +0 -9
  63. package/examples/custom-tools/subagent/index.ts +0 -1002
  64. package/examples/sdk/05-tools.ts +0 -94
  65. package/examples/sdk/12-full-control.ts +0 -95
  66. package/src/prompts/browser.md +0 -71
package/CHANGELOG.md CHANGED
@@ -2,6 +2,45 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [3.24.0] - 2026-01-07
6
+ ### Added
7
+
8
+ - Added `ToolSession` interface to unify tool creation with session context including cwd, UI availability, and rulebook rules
9
+ - Added Bun Worker-based execution for subagent tasks, replacing subprocess spawning for improved performance and event streaming
10
+ - Added `toolNames` option to filter which built-in tools are included in agent sessions
11
+ - Added `BUILTIN_TOOLS` registry constant for programmatic access to available tool factories
12
+ - Added unit tests for `createTools` function covering tool filtering and conditional tool creation
13
+
14
+ ### Changed
15
+
16
+ - Changed subagent execution from spawning separate `omp` processes to running in Bun Workers with direct event streaming
17
+ - Changed tool factories to accept `ToolSession` parameter instead of separate cwd and options arguments
18
+ - Changed `createTools` to return tools as a Map and support conditional tool creation based on session context
19
+ - Changed system prompt builder to dynamically generate tool descriptions from the tool registry
20
+ - Changed task tool description to be generated from a template with dynamic agent list injection
21
+ - Changed tool creation to use a unified `ToolSession` interface instead of separate parameters for cwd, options, and callbacks
22
+ - Changed `createTools` to return tools as a Map instead of an array for consistent tool registry access
23
+ - Changed system prompt builder to receive tool registry Map for dynamic tool description generation
24
+ - Changed subprocess usage tracking to accumulate incrementally from message_end events rather than parsing stored events after completion
25
+
26
+ ### Removed
27
+
28
+ - Removed `browser` embedded agent from task tool agent discovery
29
+ - Removed `recursive` property from agent definitions
30
+ - Removed environment variables `OMP_NO_SUBAGENTS`, `OMP_BLOCKED_AGENT`, and `OMP_SPAWNS` for subagent control
31
+ - Removed pre-instantiated tool exports (`readTool`, `bashTool`, `editTool`, `writeTool`, `grepTool`, `findTool`, `lsTool`) in favor of factory functions
32
+ - Removed `createCodingTools` and `createReadOnlyTools` helper functions
33
+ - Removed `codingTools` and `readOnlyTools` convenience exports
34
+ - Removed `wrapToolsWithExtensions` function from extensions API
35
+ - Removed `hidden` property support from custom tools
36
+ - Removed subagent and question custom tool examples
37
+
38
+ ### Fixed
39
+
40
+ - Fixed memory accumulation in task subprocess by streaming events directly to disk instead of storing in memory
41
+ - Fixed session persistence to exclude transient streaming data (partialJson, jsonlEvents) that was causing unnecessary storage bloat
42
+ - Fixed createTools respecting explicit tool lists instead of returning all non-hidden tools
43
+
5
44
  ## [3.21.0] - 2026-01-06
6
45
 
7
46
  ### Changed
@@ -1756,4 +1795,4 @@ Initial public release.
1756
1795
  - Git branch display in footer
1757
1796
  - Message queueing during streaming responses
1758
1797
  - OAuth integration for Gmail and Google Calendar access
1759
- - HTML export with syntax highlighting and collapsible sections
1798
+ - HTML export with syntax highlighting and collapsible sections
package/docs/sdk.md CHANGED
@@ -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:**
@@ -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
@@ -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
 
@@ -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.21.0",
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",
@@ -40,9 +40,9 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@mariozechner/pi-ai": "^0.37.4",
43
- "@oh-my-pi/pi-agent-core": "3.21.0",
44
- "@oh-my-pi/pi-git-tool": "3.21.0",
45
- "@oh-my-pi/pi-tui": "3.21.0",
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
  }
@@ -90,7 +90,7 @@ export interface AgentSessionConfig {
90
90
  /** Tool registry for LSP and settings */
91
91
  toolRegistry?: Map<string, AgentTool>;
92
92
  /** System prompt builder that can consider tool availability */
93
- rebuildSystemPrompt?: (toolNames: string[]) => string;
93
+ rebuildSystemPrompt?: (toolNames: string[], tools: Map<string, AgentTool>) => string;
94
94
  /** TTSR manager for time-traveling stream rules */
95
95
  ttsrManager?: TtsrManager;
96
96
  }
@@ -222,7 +222,7 @@ export class AgentSession {
222
222
 
223
223
  // Tool registry and prompt builder for extensions
224
224
  private _toolRegistry: Map<string, AgentTool>;
225
- private _rebuildSystemPrompt: ((toolNames: string[]) => string) | undefined;
225
+ private _rebuildSystemPrompt: ((toolNames: string[], tools: Map<string, AgentTool>) => string) | undefined;
226
226
  private _baseSystemPrompt: string;
227
227
 
228
228
  // TTSR manager for time-traveling stream rules
@@ -603,7 +603,7 @@ export class AgentSession {
603
603
 
604
604
  // Rebuild base system prompt with new tool set
605
605
  if (this._rebuildSystemPrompt) {
606
- this._baseSystemPrompt = this._rebuildSystemPrompt(validToolNames);
606
+ this._baseSystemPrompt = this._rebuildSystemPrompt(validToolNames, this._toolRegistry);
607
607
  this.agent.setSystemPrompt(this._baseSystemPrompt);
608
608
  }
609
609
  }
@@ -16,7 +16,6 @@ export function wrapCustomTool(tool: CustomTool, getContext: () => CustomToolCon
16
16
  label: tool.label,
17
17
  description: tool.description,
18
18
  parameters: tool.parameters,
19
- hidden: tool.hidden,
20
19
  execute: (toolCallId, params, signal, onUpdate, context) =>
21
20
  tool.execute(toolCallId, params, onUpdate, context ?? getContext(), signal),
22
21
  renderCall: tool.renderCall ? (args, theme) => tool.renderCall?.(args, theme as Theme) : undefined,
@@ -92,9 +92,4 @@ export {
92
92
  isReadToolResult,
93
93
  isWriteToolResult,
94
94
  } from "./types";
95
- export {
96
- wrapRegisteredTool,
97
- wrapRegisteredTools,
98
- wrapToolsWithExtensions,
99
- wrapToolWithExtensions,
100
- } from "./wrapper";
95
+ export { wrapRegisteredTool, wrapRegisteredTools, wrapToolWithExtensions } from "./wrapper";
@@ -138,10 +138,3 @@ export function wrapToolWithExtensions<T>(tool: AgentTool<any, T>, runner: Exten
138
138
  },
139
139
  };
140
140
  }
141
-
142
- /**
143
- * Wrap all tools with extension callbacks.
144
- */
145
- export function wrapToolsWithExtensions<T>(tools: AgentTool<any, T>[], runner: ExtensionRunner): AgentTool<any, T>[] {
146
- return tools.map((tool) => wrapToolWithExtensions(tool, runner));
147
- }
@@ -6,9 +6,9 @@
6
6
  * so the agent doesn't need to read them manually.
7
7
  */
8
8
 
9
+ import path from "node:path";
9
10
  import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
10
11
  import type { FileMentionMessage } from "./messages";
11
- import { createReadTool } from "./tools/read";
12
12
 
13
13
  /** Regex to match @filepath patterns in text */
14
14
  const FILE_MENTION_REGEX = /@((?:[^\s@]+\/)*[^\s@]+\.[a-zA-Z0-9]+)/g;
@@ -26,17 +26,14 @@ export function extractFileMentions(text: string): string[] {
26
26
  export async function generateFileMentionMessages(filePaths: string[], cwd: string): Promise<AgentMessage[]> {
27
27
  if (filePaths.length === 0) return [];
28
28
 
29
- const readTool = createReadTool(cwd);
30
29
  const files: FileMentionMessage["files"] = [];
31
30
 
32
31
  for (const filePath of filePaths) {
33
32
  try {
34
- const result = await readTool.execute("auto-read", { path: filePath });
35
- const textContent = result.content.find((c) => c.type === "text");
36
- if (textContent && textContent.type === "text") {
37
- const lineCount = textContent.text.split("\n").length;
38
- files.push({ path: filePath, content: textContent.text, lineCount });
39
- }
33
+ const absolutePath = path.resolve(cwd, filePath);
34
+ const content = await Bun.file(absolutePath).text();
35
+ const lineCount = content.split("\n").length;
36
+ files.push({ path: filePath, content, lineCount });
40
37
  } catch {
41
38
  // File doesn't exist or isn't readable - skip silently
42
39
  }