@oh-my-pi/pi-coding-agent 1.341.0 → 2.1.1337

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 (158) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/README.md +1 -1
  3. package/examples/custom-tools/subagent/index.ts +1 -1
  4. package/package.json +10 -9
  5. package/src/bun-imports.d.ts +16 -0
  6. package/src/cli/args.ts +5 -6
  7. package/src/cli/file-processor.ts +3 -3
  8. package/src/cli/list-models.ts +2 -2
  9. package/src/cli/plugin-cli.ts +1 -1
  10. package/src/cli/session-picker.ts +2 -2
  11. package/src/cli/update-cli.ts +273 -0
  12. package/src/cli.ts +1 -1
  13. package/src/config.ts +23 -75
  14. package/src/core/agent-session.ts +158 -16
  15. package/src/core/auth-storage.ts +2 -3
  16. package/src/core/bash-executor.ts +50 -10
  17. package/src/core/compaction/branch-summarization.ts +5 -5
  18. package/src/core/compaction/compaction.ts +3 -3
  19. package/src/core/compaction/index.ts +3 -3
  20. package/src/core/custom-commands/bundled/review/index.ts +156 -0
  21. package/src/core/custom-commands/index.ts +15 -0
  22. package/src/core/custom-commands/loader.ts +232 -0
  23. package/src/core/custom-commands/types.ts +112 -0
  24. package/src/core/custom-tools/index.ts +3 -3
  25. package/src/core/custom-tools/loader.ts +10 -8
  26. package/src/core/custom-tools/types.ts +11 -6
  27. package/src/core/custom-tools/wrapper.ts +2 -1
  28. package/src/core/exec.ts +22 -12
  29. package/src/core/export-html/index.ts +38 -123
  30. package/src/core/export-html/template.css +0 -7
  31. package/src/core/export-html/template.html +3 -4
  32. package/src/core/export-html/template.macro.ts +24 -0
  33. package/src/core/file-mentions.ts +54 -0
  34. package/src/core/hooks/index.ts +5 -5
  35. package/src/core/hooks/loader.ts +21 -16
  36. package/src/core/hooks/runner.ts +6 -6
  37. package/src/core/hooks/tool-wrapper.ts +2 -2
  38. package/src/core/hooks/types.ts +12 -15
  39. package/src/core/index.ts +6 -6
  40. package/src/core/logger.ts +112 -0
  41. package/src/core/mcp/client.ts +3 -3
  42. package/src/core/mcp/config.ts +1 -1
  43. package/src/core/mcp/index.ts +12 -12
  44. package/src/core/mcp/loader.ts +2 -2
  45. package/src/core/mcp/manager.ts +6 -6
  46. package/src/core/mcp/tool-bridge.ts +3 -3
  47. package/src/core/mcp/transports/http.ts +1 -1
  48. package/src/core/mcp/transports/index.ts +2 -2
  49. package/src/core/mcp/transports/stdio.ts +1 -1
  50. package/src/core/messages.ts +22 -0
  51. package/src/core/model-registry.ts +2 -2
  52. package/src/core/model-resolver.ts +2 -2
  53. package/src/core/plugins/doctor.ts +1 -1
  54. package/src/core/plugins/index.ts +6 -6
  55. package/src/core/plugins/installer.ts +4 -4
  56. package/src/core/plugins/loader.ts +4 -9
  57. package/src/core/plugins/manager.ts +5 -5
  58. package/src/core/plugins/paths.ts +3 -3
  59. package/src/core/sdk.ts +77 -35
  60. package/src/core/session-manager.ts +6 -6
  61. package/src/core/settings-manager.ts +16 -3
  62. package/src/core/skills.ts +5 -5
  63. package/src/core/slash-commands.ts +60 -45
  64. package/src/core/system-prompt.ts +6 -6
  65. package/src/core/title-generator.ts +2 -2
  66. package/src/core/tools/bash.ts +32 -155
  67. package/src/core/tools/context.ts +2 -2
  68. package/src/core/tools/edit-diff.ts +3 -3
  69. package/src/core/tools/edit.ts +18 -5
  70. package/src/core/tools/exa/company.ts +3 -3
  71. package/src/core/tools/exa/index.ts +16 -17
  72. package/src/core/tools/exa/linkedin.ts +3 -3
  73. package/src/core/tools/exa/mcp-client.ts +9 -9
  74. package/src/core/tools/exa/render.ts +5 -5
  75. package/src/core/tools/exa/researcher.ts +3 -3
  76. package/src/core/tools/exa/search.ts +6 -5
  77. package/src/core/tools/exa/types.ts +5 -6
  78. package/src/core/tools/exa/websets.ts +3 -3
  79. package/src/core/tools/find.ts +3 -3
  80. package/src/core/tools/grep.ts +3 -3
  81. package/src/core/tools/index.ts +48 -34
  82. package/src/core/tools/ls.ts +4 -4
  83. package/src/core/tools/lsp/client.ts +161 -90
  84. package/src/core/tools/lsp/config.ts +1 -1
  85. package/src/core/tools/lsp/edits.ts +2 -2
  86. package/src/core/tools/lsp/index.ts +15 -13
  87. package/src/core/tools/lsp/render.ts +2 -2
  88. package/src/core/tools/lsp/rust-analyzer.ts +3 -3
  89. package/src/core/tools/lsp/utils.ts +1 -1
  90. package/src/core/tools/notebook.ts +1 -1
  91. package/src/core/tools/output.ts +175 -0
  92. package/src/core/tools/read.ts +7 -7
  93. package/src/core/tools/renderers.ts +92 -13
  94. package/src/core/tools/review.ts +268 -0
  95. package/src/core/tools/task/agents.ts +22 -38
  96. package/src/core/tools/task/bundled-agents/reviewer.md +52 -37
  97. package/src/core/tools/task/commands.ts +31 -10
  98. package/src/core/tools/task/discovery.ts +2 -2
  99. package/src/core/tools/task/executor.ts +145 -28
  100. package/src/core/tools/task/index.ts +78 -30
  101. package/src/core/tools/task/model-resolver.ts +30 -20
  102. package/src/core/tools/task/parallel.ts +1 -1
  103. package/src/core/tools/task/render.ts +219 -30
  104. package/src/core/tools/task/subprocess-tool-registry.ts +89 -0
  105. package/src/core/tools/task/types.ts +36 -2
  106. package/src/core/tools/web-fetch.ts +5 -3
  107. package/src/core/tools/web-search/auth.ts +1 -1
  108. package/src/core/tools/web-search/index.ts +17 -15
  109. package/src/core/tools/web-search/providers/anthropic.ts +2 -2
  110. package/src/core/tools/web-search/providers/exa.ts +3 -5
  111. package/src/core/tools/web-search/providers/perplexity.ts +1 -1
  112. package/src/core/tools/web-search/render.ts +3 -3
  113. package/src/core/tools/write.ts +4 -4
  114. package/src/index.ts +29 -18
  115. package/src/main.ts +50 -33
  116. package/src/migrations.ts +3 -3
  117. package/src/modes/index.ts +5 -5
  118. package/src/modes/interactive/components/armin.ts +1 -1
  119. package/src/modes/interactive/components/assistant-message.ts +1 -1
  120. package/src/modes/interactive/components/bash-execution.ts +4 -4
  121. package/src/modes/interactive/components/bordered-loader.ts +2 -2
  122. package/src/modes/interactive/components/branch-summary-message.ts +2 -2
  123. package/src/modes/interactive/components/compaction-summary-message.ts +2 -2
  124. package/src/modes/interactive/components/diff.ts +1 -1
  125. package/src/modes/interactive/components/dynamic-border.ts +1 -1
  126. package/src/modes/interactive/components/footer.ts +5 -5
  127. package/src/modes/interactive/components/hook-editor.ts +2 -2
  128. package/src/modes/interactive/components/hook-input.ts +2 -2
  129. package/src/modes/interactive/components/hook-message.ts +3 -3
  130. package/src/modes/interactive/components/hook-selector.ts +2 -2
  131. package/src/modes/interactive/components/model-selector.ts +281 -59
  132. package/src/modes/interactive/components/oauth-selector.ts +3 -3
  133. package/src/modes/interactive/components/plugin-settings.ts +4 -4
  134. package/src/modes/interactive/components/queue-mode-selector.ts +2 -2
  135. package/src/modes/interactive/components/session-selector.ts +4 -4
  136. package/src/modes/interactive/components/settings-defs.ts +1 -1
  137. package/src/modes/interactive/components/settings-selector.ts +5 -5
  138. package/src/modes/interactive/components/show-images-selector.ts +2 -2
  139. package/src/modes/interactive/components/theme-selector.ts +2 -2
  140. package/src/modes/interactive/components/thinking-selector.ts +2 -2
  141. package/src/modes/interactive/components/tool-execution.ts +26 -8
  142. package/src/modes/interactive/components/tree-selector.ts +3 -3
  143. package/src/modes/interactive/components/user-message-selector.ts +2 -2
  144. package/src/modes/interactive/components/user-message.ts +1 -1
  145. package/src/modes/interactive/components/welcome.ts +2 -2
  146. package/src/modes/interactive/interactive-mode.ts +86 -42
  147. package/src/modes/interactive/theme/theme.ts +15 -17
  148. package/src/modes/print-mode.ts +4 -3
  149. package/src/modes/rpc/rpc-client.ts +4 -4
  150. package/src/modes/rpc/rpc-mode.ts +22 -12
  151. package/src/modes/rpc/rpc-types.ts +3 -3
  152. package/src/utils/changelog.ts +2 -2
  153. package/src/utils/clipboard.ts +1 -1
  154. package/src/utils/shell-snapshot.ts +218 -0
  155. package/src/utils/shell.ts +93 -13
  156. package/src/utils/tools-manager.ts +1 -1
  157. package/examples/custom-tools/subagent/agents/reviewer.md +0 -35
  158. package/src/core/tools/exa/logger.ts +0 -56
@@ -5,8 +5,8 @@
5
5
  */
6
6
 
7
7
  import { Type } from "@sinclair/typebox";
8
- import type { CustomTool } from "../../custom-tools/types.js";
9
- import type { ExaRenderDetails } from "./types.js";
8
+ import type { CustomTool } from "../../custom-tools/types";
9
+ import type { ExaRenderDetails } from "./types";
10
10
 
11
11
  /** exa_linkedin - LinkedIn search */
12
12
  export const linkedinTool: CustomTool<any, ExaRenderDetails> = {
@@ -34,7 +34,7 @@ Parameters:
34
34
  details: { error: "EXA_API_KEY not found", toolName: "exa_linkedin" },
35
35
  };
36
36
  }
37
- const response = await callExaTool("linkedin_search_exa", params, apiKey);
37
+ const response = await callExaTool("linkedin_search", params, apiKey);
38
38
 
39
39
  if (isSearchResponse(response)) {
40
40
  const formatted = formatSearchResults(response);
@@ -5,8 +5,8 @@
5
5
  */
6
6
 
7
7
  import type { TSchema } from "@sinclair/typebox";
8
- import type { CustomTool } from "../../custom-tools/types.js";
9
- import { logExaError } from "./logger.js";
8
+ import type { CustomTool } from "../../custom-tools/types";
9
+ import { logger } from "../../logger";
10
10
  import type {
11
11
  ExaRenderDetails,
12
12
  ExaSearchResponse,
@@ -15,7 +15,7 @@ import type {
15
15
  MCPTool,
16
16
  MCPToolsResponse,
17
17
  MCPToolWrapperConfig,
18
- } from "./types.js";
18
+ } from "./types";
19
19
 
20
20
  /** Find EXA_API_KEY from process.env or .env files */
21
21
  export async function findApiKey(): Promise<string | null> {
@@ -89,7 +89,7 @@ export async function callMCP(url: string, method: string, params?: Record<strin
89
89
 
90
90
  if (!response.ok) {
91
91
  const errorMsg = `MCP request failed: ${response.status} ${response.statusText}`;
92
- logExaError(errorMsg, { url, method, params });
92
+ logger.error(errorMsg, { url, method, params });
93
93
  throw new Error(errorMsg);
94
94
  }
95
95
 
@@ -97,7 +97,7 @@ export async function callMCP(url: string, method: string, params?: Record<strin
97
97
  const result = parseSSE(text);
98
98
 
99
99
  if (!result) {
100
- logExaError("Failed to parse MCP response", { url, method, responseText: text.slice(0, 500) });
100
+ logger.error("Failed to parse MCP response", { url, method, responseText: text.slice(0, 500) });
101
101
  throw new Error("Failed to parse MCP response");
102
102
  }
103
103
 
@@ -110,7 +110,7 @@ export async function fetchExaTools(apiKey: string, toolNames: string[]): Promis
110
110
  const response = (await callMCP(url, "tools/list")) as MCPToolsResponse;
111
111
 
112
112
  if (response.error) {
113
- logExaError("MCP tools/list error", { toolNames, error: response.error });
113
+ logger.error("MCP tools/list error", { toolNames, error: response.error });
114
114
  throw new Error(`MCP error: ${response.error.message}`);
115
115
  }
116
116
 
@@ -123,7 +123,7 @@ export async function fetchWebsetsTools(apiKey: string): Promise<MCPTool[]> {
123
123
  const response = (await callMCP(url, "tools/list")) as MCPToolsResponse;
124
124
 
125
125
  if (response.error) {
126
- logExaError("Websets MCP tools/list error", { error: response.error });
126
+ logger.error("Websets MCP tools/list error", { error: response.error });
127
127
  throw new Error(`MCP error: ${response.error.message}`);
128
128
  }
129
129
 
@@ -139,7 +139,7 @@ export async function callExaTool(toolName: string, args: Record<string, unknown
139
139
  })) as MCPCallResponse;
140
140
 
141
141
  if (response.error) {
142
- logExaError("MCP tools/call error", { toolName, args, error: response.error });
142
+ logger.error("MCP tools/call error", { toolName, args, error: response.error });
143
143
  throw new Error(`MCP error: ${response.error.message}`);
144
144
  }
145
145
 
@@ -159,7 +159,7 @@ export async function callWebsetsTool(
159
159
  })) as MCPCallResponse;
160
160
 
161
161
  if (response.error) {
162
- logExaError("Websets MCP tools/call error", { toolName, args, error: response.error });
162
+ logger.error("Websets MCP tools/call error", { toolName, args, error: response.error });
163
163
  throw new Error(`MCP error: ${response.error.message}`);
164
164
  }
165
165
 
@@ -6,10 +6,10 @@
6
6
 
7
7
  import type { Component } from "@oh-my-pi/pi-tui";
8
8
  import { Text } from "@oh-my-pi/pi-tui";
9
- import type { Theme } from "../../../modes/interactive/theme/theme.js";
10
- import type { RenderResultOptions } from "../../custom-tools/types.js";
11
- import { logViewError } from "./logger.js";
12
- import type { ExaRenderDetails } from "./types.js";
9
+ import type { Theme } from "../../../modes/interactive/theme/theme";
10
+ import type { RenderResultOptions } from "../../custom-tools/types";
11
+ import { logger } from "../../logger";
12
+ import type { ExaRenderDetails } from "./types";
13
13
 
14
14
  // Tree formatting constants
15
15
  const TREE_MID = "├─";
@@ -51,7 +51,7 @@ export function renderExaResult(
51
51
 
52
52
  // Handle error case
53
53
  if (details?.error) {
54
- logViewError("Exa render error", { error: details.error, toolName: details.toolName });
54
+ logger.error("Exa render error", { error: details.error, toolName: details.toolName });
55
55
  return new Text(theme.fg("error", `Error: ${details.error}`), 0, 0);
56
56
  }
57
57
 
@@ -5,9 +5,9 @@
5
5
  */
6
6
 
7
7
  import { Type } from "@sinclair/typebox";
8
- import type { CustomTool } from "../../custom-tools/types.js";
9
- import { callExaTool, findApiKey } from "./mcp-client.js";
10
- import type { ExaRenderDetails } from "./types.js";
8
+ import type { CustomTool } from "../../custom-tools/types";
9
+ import { callExaTool, findApiKey } from "./mcp-client";
10
+ import type { ExaRenderDetails } from "./types";
11
11
 
12
12
  const researcherStartTool: CustomTool<any, ExaRenderDetails> = {
13
13
  name: "exa_researcher_start",
@@ -5,8 +5,8 @@
5
5
  */
6
6
 
7
7
  import { Type } from "@sinclair/typebox";
8
- import type { CustomTool } from "../../custom-tools/types.js";
9
- import type { ExaRenderDetails } from "./types.js";
8
+ import type { CustomTool } from "../../custom-tools/types";
9
+ import type { ExaRenderDetails } from "./types";
10
10
 
11
11
  /** exa_search - Basic neural/keyword search */
12
12
  const exaSearchTool: CustomTool<any, ExaRenderDetails> = {
@@ -91,7 +91,7 @@ Parameters:
91
91
  details: { error: "EXA_API_KEY not found", toolName: "exa_search" },
92
92
  };
93
93
  }
94
- const response = await callExaTool("web_search", params, apiKey);
94
+ const response = await callExaTool("web_search_exa", params, apiKey);
95
95
 
96
96
  if (isSearchResponse(response)) {
97
97
  const formatted = formatSearchResults(response);
@@ -187,7 +187,8 @@ Similar parameters to exa_search, optimized for research depth.`,
187
187
  details: { error: "EXA_API_KEY not found", toolName: "exa_search_deep" },
188
188
  };
189
189
  }
190
- const response = await callExaTool("deep_search_exa", params, apiKey);
190
+ const args = { ...params, type: "deep" };
191
+ const response = await callExaTool("web_search_exa", args, apiKey);
191
192
 
192
193
  if (isSearchResponse(response)) {
193
194
  const formatted = formatSearchResults(response);
@@ -305,7 +306,7 @@ Parameters:
305
306
  details: { error: "EXA_API_KEY not found", toolName: "exa_crawl" },
306
307
  };
307
308
  }
308
- const response = await callExaTool("crawling_exa", params, apiKey);
309
+ const response = await callExaTool("crawling", params, apiKey);
309
310
 
310
311
  if (isSearchResponse(response)) {
311
312
  const formatted = formatSearchResults(response);
@@ -23,7 +23,7 @@ export interface MCPToolWrapperConfig {
23
23
  name: string;
24
24
  /** Display label for UI */
25
25
  label: string;
26
- /** MCP tool name to call (e.g., "web_search") */
26
+ /** MCP tool name to call (e.g., "web_search_exa") */
27
27
  mcpToolName: string;
28
28
  /** Whether this is a websets tool (uses different MCP endpoint) */
29
29
  isWebsetsTool?: boolean;
@@ -121,14 +121,13 @@ export interface WebsetEnrichment {
121
121
  /** Tool name mappings: MCP name -> our tool name */
122
122
  export const EXA_TOOL_MAPPINGS = {
123
123
  // Search tools
124
- web_search: "exa_search",
125
- deep_search_exa: "exa_search_deep",
124
+ web_search_exa: "exa_search",
126
125
  get_code_context_exa: "exa_search_code",
127
- crawling_exa: "exa_crawl",
126
+ crawling: "exa_crawl",
128
127
  // LinkedIn
129
- linkedin_search_exa: "exa_linkedin",
128
+ linkedin_search: "exa_linkedin",
130
129
  // Company
131
- company_research_exa: "exa_company",
130
+ company_research: "exa_company",
132
131
  // Researcher
133
132
  deep_researcher_start: "exa_researcher_start",
134
133
  deep_researcher_check: "exa_researcher_poll",
@@ -5,9 +5,9 @@
5
5
  */
6
6
 
7
7
  import { Type } from "@sinclair/typebox";
8
- import type { CustomTool } from "../../custom-tools/types.js";
9
- import { callWebsetsTool, findApiKey } from "./mcp-client.js";
10
- import type { ExaRenderDetails } from "./types.js";
8
+ import type { CustomTool } from "../../custom-tools/types";
9
+ import { callWebsetsTool, findApiKey } from "./mcp-client";
10
+ import type { ExaRenderDetails } from "./types";
11
11
 
12
12
  /** Helper to create a websets tool with proper execute signature */
13
13
  function createWebsetTool(
@@ -3,9 +3,9 @@ import path from "node:path";
3
3
  import type { AgentTool } from "@oh-my-pi/pi-agent-core";
4
4
  import { Type } from "@sinclair/typebox";
5
5
  import { globSync } from "glob";
6
- import { ensureTool } from "../../utils/tools-manager.js";
7
- import { resolveToCwd } from "./path-utils.js";
8
- import { DEFAULT_MAX_BYTES, formatSize, type TruncationResult, truncateHead } from "./truncate.js";
6
+ import { ensureTool } from "../../utils/tools-manager";
7
+ import { resolveToCwd } from "./path-utils";
8
+ import { DEFAULT_MAX_BYTES, formatSize, type TruncationResult, truncateHead } from "./truncate";
9
9
 
10
10
  const findSchema = Type.Object({
11
11
  pattern: Type.String({
@@ -3,8 +3,8 @@ import nodePath from "node:path";
3
3
  import type { AgentTool } from "@oh-my-pi/pi-agent-core";
4
4
  import { Type } from "@sinclair/typebox";
5
5
  import type { Subprocess } from "bun";
6
- import { ensureTool } from "../../utils/tools-manager.js";
7
- import { resolveToCwd } from "./path-utils.js";
6
+ import { ensureTool } from "../../utils/tools-manager";
7
+ import { resolveToCwd } from "./path-utils";
8
8
  import {
9
9
  DEFAULT_MAX_BYTES,
10
10
  formatSize,
@@ -12,7 +12,7 @@ import {
12
12
  type TruncationResult,
13
13
  truncateHead,
14
14
  truncateLine,
15
- } from "./truncate.js";
15
+ } from "./truncate";
16
16
 
17
17
  const grepSchema = Type.Object({
18
18
  pattern: Type.String({ description: "Search pattern (regex or literal string)" }),
@@ -1,12 +1,12 @@
1
- export { type AskToolDetails, askTool, createAskTool } from "./ask.js";
2
- export { type BashToolDetails, bashTool, createBashTool } from "./bash.js";
3
- export { createEditTool, type EditToolOptions, editTool } from "./edit.js";
1
+ export { type AskToolDetails, askTool, createAskTool } from "./ask";
2
+ export { type BashToolDetails, bashTool, createBashTool } from "./bash";
3
+ export { createEditTool, type EditToolOptions, editTool } from "./edit";
4
4
  // Exa MCP tools (22 tools)
5
- export { exaTools } from "./exa/index.js";
6
- export type { ExaRenderDetails, ExaSearchResponse, ExaSearchResult } from "./exa/types.js";
7
- export { createFindTool, type FindToolDetails, findTool } from "./find.js";
8
- export { createGrepTool, type GrepToolDetails, grepTool } from "./grep.js";
9
- export { createLsTool, type LsToolDetails, lsTool } from "./ls.js";
5
+ export { exaTools } from "./exa/index";
6
+ export type { ExaRenderDetails, ExaSearchResponse, ExaSearchResult } from "./exa/types";
7
+ export { createFindTool, type FindToolDetails, findTool } from "./find";
8
+ export { createGrepTool, type GrepToolDetails, grepTool } from "./grep";
9
+ export { createLsTool, type LsToolDetails, lsTool } from "./ls";
10
10
  export {
11
11
  createLspTool,
12
12
  type FileDiagnosticsResult,
@@ -19,12 +19,14 @@ export {
19
19
  type LspWarmupResult,
20
20
  lspTool,
21
21
  warmupLspServers,
22
- } from "./lsp/index.js";
23
- export { createNotebookTool, type NotebookToolDetails, notebookTool } from "./notebook.js";
24
- export { createReadTool, type ReadToolDetails, readTool } from "./read.js";
25
- export { BUNDLED_AGENTS, createTaskTool, taskTool } from "./task/index.js";
26
- export type { TruncationResult } from "./truncate.js";
27
- export { createWebFetchTool, type WebFetchToolDetails, webFetchCustomTool, webFetchTool } from "./web-fetch.js";
22
+ } from "./lsp/index";
23
+ export { createNotebookTool, type NotebookToolDetails, notebookTool } from "./notebook";
24
+ export { createOutputTool, type OutputToolDetails, outputTool } from "./output";
25
+ export { createReadTool, type ReadToolDetails, readTool } from "./read";
26
+ export { createReportFindingTool, createSubmitReviewTool, reportFindingTool, submitReviewTool } from "./review";
27
+ export { BUNDLED_AGENTS, createTaskTool, taskTool } from "./task/index";
28
+ export type { TruncationResult } from "./truncate";
29
+ export { createWebFetchTool, type WebFetchToolDetails, webFetchCustomTool, webFetchTool } from "./web-fetch";
28
30
  export {
29
31
  companyWebSearchTools,
30
32
  createWebSearchTool,
@@ -42,24 +44,26 @@ export {
42
44
  webSearchDeepTool,
43
45
  webSearchLinkedinTool,
44
46
  webSearchTool,
45
- } from "./web-search/index.js";
46
- export { createWriteTool, type WriteToolDetails, type WriteToolOptions, writeTool } from "./write.js";
47
+ } from "./web-search/index";
48
+ export { createWriteTool, type WriteToolDetails, type WriteToolOptions, writeTool } from "./write";
47
49
 
48
50
  import type { AgentTool } from "@oh-my-pi/pi-agent-core";
49
- import { askTool, createAskTool } from "./ask.js";
50
- import { bashTool, createBashTool } from "./bash.js";
51
- import { checkBashInterception, checkSimpleLsInterception } from "./bash-interceptor.js";
52
- import { createEditTool, editTool } from "./edit.js";
53
- import { createFindTool, findTool } from "./find.js";
54
- import { createGrepTool, grepTool } from "./grep.js";
55
- import { createLsTool, lsTool } from "./ls.js";
56
- import { createLspTool, formatFile, getDiagnosticsForFile, lspTool } from "./lsp/index.js";
57
- import { createNotebookTool, notebookTool } from "./notebook.js";
58
- import { createReadTool, readTool } from "./read.js";
59
- import { createTaskTool, taskTool } from "./task/index.js";
60
- import { createWebFetchTool, webFetchTool } from "./web-fetch.js";
61
- import { createWebSearchTool, webSearchTool } from "./web-search/index.js";
62
- import { createWriteTool, writeTool } from "./write.js";
51
+ import { askTool, createAskTool } from "./ask";
52
+ import { bashTool, createBashTool } from "./bash";
53
+ import { checkBashInterception, checkSimpleLsInterception } from "./bash-interceptor";
54
+ import { createEditTool, editTool } from "./edit";
55
+ import { createFindTool, findTool } from "./find";
56
+ import { createGrepTool, grepTool } from "./grep";
57
+ import { createLsTool, lsTool } from "./ls";
58
+ import { createLspTool, formatFile, getDiagnosticsForFile, lspTool } from "./lsp/index";
59
+ import { createNotebookTool, notebookTool } from "./notebook";
60
+ import { createOutputTool, outputTool } from "./output";
61
+ import { createReadTool, readTool } from "./read";
62
+ import { createReportFindingTool, createSubmitReviewTool, reportFindingTool, submitReviewTool } from "./review";
63
+ import { createTaskTool, taskTool } from "./task/index";
64
+ import { createWebFetchTool, webFetchTool } from "./web-fetch";
65
+ import { createWebSearchTool, webSearchTool } from "./web-search/index";
66
+ import { createWriteTool, writeTool } from "./write";
63
67
 
64
68
  /** Tool type (AgentTool from pi-ai) */
65
69
  export type Tool = AgentTool<any, any, any>;
@@ -79,6 +83,8 @@ export interface CodingToolsOptions {
79
83
  lspFormatOnWrite?: boolean;
80
84
  /** Whether to accept high-confidence fuzzy matches in edit tool (default: true) */
81
85
  editFuzzyMatch?: boolean;
86
+ /** Set of tool names available to the agent (for cross-tool awareness) */
87
+ availableTools?: Set<string>;
82
88
  }
83
89
 
84
90
  // Factory function type
@@ -115,9 +121,12 @@ const toolDefs: Record<string, { tool: Tool; create: ToolFactory }> = {
115
121
  ls: { tool: lsTool, create: createLsTool },
116
122
  lsp: { tool: lspTool, create: createLspTool },
117
123
  notebook: { tool: notebookTool, create: createNotebookTool },
118
- task: { tool: taskTool, create: (cwd, ctx) => createTaskTool(cwd, ctx) },
124
+ output: { tool: outputTool, create: (cwd, ctx) => createOutputTool(cwd, ctx) },
125
+ task: { tool: taskTool, create: (cwd, ctx, opts) => createTaskTool(cwd, ctx, opts) },
119
126
  web_fetch: { tool: webFetchTool, create: createWebFetchTool },
120
127
  web_search: { tool: webSearchTool, create: createWebSearchTool },
128
+ report_finding: { tool: reportFindingTool, create: createReportFindingTool },
129
+ submit_review: { tool: submitReviewTool, create: createSubmitReviewTool },
121
130
  };
122
131
 
123
132
  export type ToolName = keyof typeof toolDefs;
@@ -136,6 +145,7 @@ const baseCodingToolNames: ToolName[] = [
136
145
  "ls",
137
146
  "lsp",
138
147
  "notebook",
148
+ "output",
139
149
  "task",
140
150
  "web_fetch",
141
151
  "web_search",
@@ -168,7 +178,8 @@ export function createCodingTools(
168
178
  options?: CodingToolsOptions,
169
179
  ): Tool[] {
170
180
  const names = hasUI ? [...baseCodingToolNames, ...uiToolNames] : baseCodingToolNames;
171
- return names.map((name) => toolDefs[name].create(cwd, sessionContext, options));
181
+ const optionsWithTools = { ...options, availableTools: new Set(names) };
182
+ return names.map((name) => toolDefs[name].create(cwd, sessionContext, optionsWithTools));
172
183
  }
173
184
 
174
185
  /**
@@ -185,7 +196,8 @@ export function createReadOnlyTools(
185
196
  options?: CodingToolsOptions,
186
197
  ): Tool[] {
187
198
  const names = hasUI ? [...baseReadOnlyToolNames, ...uiToolNames] : baseReadOnlyToolNames;
188
- return names.map((name) => toolDefs[name].create(cwd, sessionContext, options));
199
+ const optionsWithTools = { ...options, availableTools: new Set(names) };
200
+ return names.map((name) => toolDefs[name].create(cwd, sessionContext, optionsWithTools));
189
201
  }
190
202
 
191
203
  /**
@@ -199,8 +211,10 @@ export function createAllTools(
199
211
  sessionContext?: SessionContext,
200
212
  options?: CodingToolsOptions,
201
213
  ): Record<ToolName, Tool> {
214
+ const names = Object.keys(toolDefs);
215
+ const optionsWithTools = { ...options, availableTools: new Set(names) };
202
216
  return Object.fromEntries(
203
- Object.entries(toolDefs).map(([name, def]) => [name, def.create(cwd, sessionContext, options)]),
217
+ Object.entries(toolDefs).map(([name, def]) => [name, def.create(cwd, sessionContext, optionsWithTools)]),
204
218
  ) as Record<ToolName, Tool>;
205
219
  }
206
220
 
@@ -1,9 +1,9 @@
1
+ import { existsSync, readdirSync, statSync } from "node:fs";
2
+ import nodePath from "node:path";
1
3
  import type { AgentTool } from "@oh-my-pi/pi-agent-core";
2
4
  import { Type } from "@sinclair/typebox";
3
- import { existsSync, readdirSync, statSync } from "fs";
4
- import nodePath from "path";
5
- import { resolveToCwd } from "./path-utils.js";
6
- import { DEFAULT_MAX_BYTES, formatSize, type TruncationResult, truncateHead } from "./truncate.js";
5
+ import { resolveToCwd } from "./path-utils";
6
+ import { DEFAULT_MAX_BYTES, formatSize, type TruncationResult, truncateHead } from "./truncate";
7
7
 
8
8
  const lsSchema = Type.Object({
9
9
  path: Type.Optional(Type.String({ description: "Directory to list (default: current directory)" })),