@oh-my-pi/pi-coding-agent 3.24.0 → 3.30.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 (97) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/package.json +4 -4
  3. package/src/core/custom-commands/bundled/wt/index.ts +3 -0
  4. package/src/core/sdk.ts +7 -0
  5. package/src/core/tools/complete.ts +129 -0
  6. package/src/core/tools/index.test.ts +9 -1
  7. package/src/core/tools/index.ts +18 -5
  8. package/src/core/tools/jtd-to-json-schema.ts +252 -0
  9. package/src/core/tools/output.ts +125 -14
  10. package/src/core/tools/read.ts +4 -4
  11. package/src/core/tools/task/artifacts.ts +6 -9
  12. package/src/core/tools/task/executor.ts +189 -24
  13. package/src/core/tools/task/index.ts +23 -18
  14. package/src/core/tools/task/name-generator.ts +1577 -0
  15. package/src/core/tools/task/render.ts +137 -8
  16. package/src/core/tools/task/types.ts +26 -5
  17. package/src/core/tools/task/worker-protocol.ts +1 -0
  18. package/src/core/tools/task/worker.ts +136 -14
  19. package/src/core/tools/web-fetch-handlers/academic.test.ts +239 -0
  20. package/src/core/tools/web-fetch-handlers/artifacthub.ts +210 -0
  21. package/src/core/tools/web-fetch-handlers/arxiv.ts +84 -0
  22. package/src/core/tools/web-fetch-handlers/aur.ts +171 -0
  23. package/src/core/tools/web-fetch-handlers/biorxiv.ts +136 -0
  24. package/src/core/tools/web-fetch-handlers/bluesky.ts +277 -0
  25. package/src/core/tools/web-fetch-handlers/brew.ts +173 -0
  26. package/src/core/tools/web-fetch-handlers/business.test.ts +82 -0
  27. package/src/core/tools/web-fetch-handlers/cheatsh.ts +73 -0
  28. package/src/core/tools/web-fetch-handlers/chocolatey.ts +153 -0
  29. package/src/core/tools/web-fetch-handlers/coingecko.ts +179 -0
  30. package/src/core/tools/web-fetch-handlers/crates-io.ts +123 -0
  31. package/src/core/tools/web-fetch-handlers/dev-platforms.test.ts +254 -0
  32. package/src/core/tools/web-fetch-handlers/devto.ts +173 -0
  33. package/src/core/tools/web-fetch-handlers/discogs.ts +303 -0
  34. package/src/core/tools/web-fetch-handlers/dockerhub.ts +156 -0
  35. package/src/core/tools/web-fetch-handlers/documentation.test.ts +85 -0
  36. package/src/core/tools/web-fetch-handlers/finance-media.test.ts +144 -0
  37. package/src/core/tools/web-fetch-handlers/git-hosting.test.ts +272 -0
  38. package/src/core/tools/web-fetch-handlers/github-gist.ts +64 -0
  39. package/src/core/tools/web-fetch-handlers/github.ts +424 -0
  40. package/src/core/tools/web-fetch-handlers/gitlab.ts +444 -0
  41. package/src/core/tools/web-fetch-handlers/go-pkg.ts +271 -0
  42. package/src/core/tools/web-fetch-handlers/hackage.ts +89 -0
  43. package/src/core/tools/web-fetch-handlers/hackernews.ts +208 -0
  44. package/src/core/tools/web-fetch-handlers/hex.ts +121 -0
  45. package/src/core/tools/web-fetch-handlers/huggingface.ts +385 -0
  46. package/src/core/tools/web-fetch-handlers/iacr.ts +82 -0
  47. package/src/core/tools/web-fetch-handlers/index.ts +69 -0
  48. package/src/core/tools/web-fetch-handlers/lobsters.ts +186 -0
  49. package/src/core/tools/web-fetch-handlers/mastodon.ts +302 -0
  50. package/src/core/tools/web-fetch-handlers/maven.ts +147 -0
  51. package/src/core/tools/web-fetch-handlers/mdn.ts +174 -0
  52. package/src/core/tools/web-fetch-handlers/media.test.ts +138 -0
  53. package/src/core/tools/web-fetch-handlers/metacpan.ts +247 -0
  54. package/src/core/tools/web-fetch-handlers/npm.ts +107 -0
  55. package/src/core/tools/web-fetch-handlers/nuget.ts +201 -0
  56. package/src/core/tools/web-fetch-handlers/nvd.ts +238 -0
  57. package/src/core/tools/web-fetch-handlers/opencorporates.ts +273 -0
  58. package/src/core/tools/web-fetch-handlers/openlibrary.ts +313 -0
  59. package/src/core/tools/web-fetch-handlers/osv.ts +184 -0
  60. package/src/core/tools/web-fetch-handlers/package-managers-2.test.ts +199 -0
  61. package/src/core/tools/web-fetch-handlers/package-managers.test.ts +171 -0
  62. package/src/core/tools/web-fetch-handlers/package-registries.test.ts +259 -0
  63. package/src/core/tools/web-fetch-handlers/packagist.ts +170 -0
  64. package/src/core/tools/web-fetch-handlers/pub-dev.ts +185 -0
  65. package/src/core/tools/web-fetch-handlers/pubmed.ts +174 -0
  66. package/src/core/tools/web-fetch-handlers/pypi.ts +125 -0
  67. package/src/core/tools/web-fetch-handlers/readthedocs.ts +122 -0
  68. package/src/core/tools/web-fetch-handlers/reddit.ts +100 -0
  69. package/src/core/tools/web-fetch-handlers/repology.ts +257 -0
  70. package/src/core/tools/web-fetch-handlers/research.test.ts +107 -0
  71. package/src/core/tools/web-fetch-handlers/rfc.ts +205 -0
  72. package/src/core/tools/web-fetch-handlers/rubygems.ts +112 -0
  73. package/src/core/tools/web-fetch-handlers/sec-edgar.ts +269 -0
  74. package/src/core/tools/web-fetch-handlers/security.test.ts +103 -0
  75. package/src/core/tools/web-fetch-handlers/semantic-scholar.ts +190 -0
  76. package/src/core/tools/web-fetch-handlers/social-extended.test.ts +192 -0
  77. package/src/core/tools/web-fetch-handlers/social.test.ts +259 -0
  78. package/src/core/tools/web-fetch-handlers/spotify.ts +218 -0
  79. package/src/core/tools/web-fetch-handlers/stackexchange.test.ts +120 -0
  80. package/src/core/tools/web-fetch-handlers/stackoverflow.ts +123 -0
  81. package/src/core/tools/web-fetch-handlers/standards.test.ts +122 -0
  82. package/src/core/tools/web-fetch-handlers/terraform.ts +296 -0
  83. package/src/core/tools/web-fetch-handlers/tldr.ts +47 -0
  84. package/src/core/tools/web-fetch-handlers/twitter.ts +84 -0
  85. package/src/core/tools/web-fetch-handlers/types.ts +163 -0
  86. package/src/core/tools/web-fetch-handlers/utils.ts +91 -0
  87. package/src/core/tools/web-fetch-handlers/vimeo.ts +152 -0
  88. package/src/core/tools/web-fetch-handlers/wikidata.ts +349 -0
  89. package/src/core/tools/web-fetch-handlers/wikipedia.test.ts +73 -0
  90. package/src/core/tools/web-fetch-handlers/wikipedia.ts +91 -0
  91. package/src/core/tools/web-fetch-handlers/youtube.test.ts +198 -0
  92. package/src/core/tools/web-fetch-handlers/youtube.ts +319 -0
  93. package/src/core/tools/web-fetch.ts +152 -1324
  94. package/src/prompts/task.md +14 -50
  95. package/src/prompts/tools/output.md +2 -1
  96. package/src/prompts/tools/task.md +3 -1
  97. package/src/utils/tools-manager.ts +110 -8
@@ -1,50 +1,14 @@
1
- You are a worker agent for delegated tasks. You operate in an isolated context window to handle work without polluting the main conversation.
2
-
3
- Do what has been asked; nothing more, nothing less. Work autonomously using all available tools.
4
-
5
- Your strengths:
6
-
7
- - Searching for code, configurations, and patterns across large codebases
8
- - Analyzing multiple files to understand system architecture
9
- - Investigating complex questions that require exploring many files
10
- - Performing multi-step research and implementation tasks
11
-
12
- Guidelines:
13
-
14
- - Persist until the task is fully resolved end-to-end when feasible.
15
- - Verify with tools; ask for clarification when required.
16
- - For file searches: Use grep/glob when you need to search broadly. Use read when you know the specific file path.
17
- - For analysis: Start broad and narrow down. Use multiple search strategies if the first doesn't yield results.
18
- - Be thorough: Check multiple locations, consider different naming conventions, look for related files.
19
- - When spawning subagents with the Task tool, include a short, user-facing `description` for each task (5-8 words) that summarizes the approach.
20
- - NEVER create files unless absolutely necessary. ALWAYS prefer editing existing files.
21
- - NEVER proactively create documentation files (\*.md) or README files unless explicitly requested.
22
- - Any file paths in your response MUST be absolute. Do NOT use relative paths.
23
- - Include relevant code snippets in your final response.
24
-
25
- Output format when finished:
26
-
27
- ## Completed
28
-
29
- What was done.
30
-
31
- ## Files Changed
32
-
33
- - `/absolute/path/to/file.ts` - what changed
34
-
35
- ## Key Code
36
-
37
- Relevant snippets or signatures touched:
38
-
39
- ```language
40
- // actual code
41
- ```
42
-
43
- ## Notes (if any)
44
-
45
- Anything the main agent should know.
46
-
47
- If handing off to another agent (e.g. reviewer), include:
48
-
49
- - Exact file paths changed
50
- - Key functions/types touched (short list)
1
+ You are a worker agent for delegated tasks in an isolated context. Finish only the assigned work and return the minimum useful result.
2
+
3
+ Principles:
4
+
5
+ - Be concise. No filler, repetition, or tool transcripts.
6
+ - If blocked, ask a single focused question; otherwise proceed autonomously.
7
+ - Prefer narrow search (grep/glob) then read only needed ranges.
8
+ - Avoid full-file reads unless necessary.
9
+ - NEVER create files unless absolutely required. Prefer edits to existing files.
10
+ - NEVER create documentation files (\*.md) unless explicitly requested.
11
+ - Any file paths in your response MUST be absolute.
12
+ - When spawning subagents with the Task tool, include a 5-8 word user-facing description.
13
+ - Include the smallest relevant code snippet when discussing code or config.
14
+ - Follow the main agent's instructions.
@@ -21,7 +21,8 @@ Do NOT use when:
21
21
  - `"raw"` (default): Full output with ANSI codes preserved
22
22
  - `"json"`: Structured object with metadata
23
23
  - `"stripped"`: Plain text with ANSI codes removed for parsing
24
+ - `query` (optional): jq-like query for JSON outputs (e.g., `.result.items[0].name`)
24
25
  - `offset` (optional): Line number to start reading from (1-indexed)
25
26
  - `limit` (optional): Maximum number of lines to read
26
27
 
27
- Use offset/limit for line ranges to reduce context usage on large outputs.
28
+ Use offset/limit for line ranges to reduce context usage on large outputs. Use `query` for JSON outputs (for example, subagent `complete` results).
@@ -16,8 +16,9 @@ The Task tool launches specialized agents (workers) that autonomously handle com
16
16
  ## Usage Notes
17
17
 
18
18
  - Always include a short description of the task in the task parameter
19
- - **Plan-then-execute**: Put shared constraints in `context`, keep each task focused, specify output format and acceptance criteria
19
+ - **Plan-then-execute**: Put shared constraints in `context`, keep each task focused, specify acceptance criteria; use `output_schema` when you need structured output
20
20
  - **Minimize tool chatter**: Avoid repeating large context; use Output tool with output ids for full logs
21
+ - **Structured completion**: If `output_schema` is provided, subagents must call `complete` to finish
21
22
  - **Parallelize**: Launch multiple agents concurrently whenever possible
22
23
  - **Results are intermediate data**: Agent findings provide context for YOU to perform actual work. Do not treat agent reports as "task complete" signals.
23
24
  - **Stateless invocations**: Each agent runs autonomously and returns a single final message. Include all necessary context and specify exactly what information to return.
@@ -30,6 +31,7 @@ The Task tool launches specialized agents (workers) that autonomously handle com
30
31
  - `tasks`: Array of `{agent, task, description?, model?}` - tasks to run in parallel (max {{MAX_PARALLEL_TASKS}}, {{MAX_CONCURRENCY}} concurrent)
31
32
  - `model`: (optional) Override the agent's default model with fuzzy matching (e.g., "sonnet", "codex", "5.2"). Supports comma-separated fallbacks: "gpt, opus" tries gpt first, then opus. Use "default" for omp's default model
32
33
  - `context`: (optional) Shared context string prepended to all task prompts - use this to avoid repeating instructions
34
+ - `output_schema`: (optional) JSON schema for structured subagent output (used by the complete tool)
33
35
 
34
36
  ## Examples
35
37
 
@@ -11,6 +11,7 @@ interface ToolConfig {
11
11
  repo: string; // GitHub repo (e.g., "sharkdp/fd")
12
12
  binaryName: string; // Name of the binary inside the archive
13
13
  tagPrefix: string; // Prefix for tags (e.g., "v" for v1.0.0, "" for 1.0.0)
14
+ isDirectBinary?: boolean; // If true, asset is a direct binary (not an archive)
14
15
  getAssetName: (version: string, plat: string, architecture: string) => string | null;
15
16
  }
16
17
 
@@ -93,6 +94,43 @@ const TOOLS: Record<string, ToolConfig> = {
93
94
  return null;
94
95
  },
95
96
  },
97
+ "yt-dlp": {
98
+ name: "yt-dlp",
99
+ repo: "yt-dlp/yt-dlp",
100
+ binaryName: "yt-dlp",
101
+ tagPrefix: "",
102
+ isDirectBinary: true,
103
+ getAssetName: (_version, plat, architecture) => {
104
+ if (plat === "darwin") {
105
+ return "yt-dlp_macos"; // Universal binary
106
+ } else if (plat === "linux") {
107
+ return architecture === "arm64" ? "yt-dlp_linux_aarch64" : "yt-dlp_linux";
108
+ } else if (plat === "win32") {
109
+ return architecture === "arm64" ? "yt-dlp_arm64.exe" : "yt-dlp.exe";
110
+ }
111
+ return null;
112
+ },
113
+ },
114
+ };
115
+
116
+ // Python packages installed via uv/pip
117
+ interface PythonToolConfig {
118
+ name: string;
119
+ package: string; // PyPI package name
120
+ binaryName: string; // CLI command name after install
121
+ }
122
+
123
+ const PYTHON_TOOLS: Record<string, PythonToolConfig> = {
124
+ markitdown: {
125
+ name: "markitdown",
126
+ package: "markitdown",
127
+ binaryName: "markitdown",
128
+ },
129
+ html2text: {
130
+ name: "html2text",
131
+ package: "html2text",
132
+ binaryName: "html2text",
133
+ },
96
134
  };
97
135
 
98
136
  // Check if a command exists in PATH
@@ -100,8 +138,16 @@ function commandExists(cmd: string): string | null {
100
138
  return Bun.which(cmd);
101
139
  }
102
140
 
141
+ export type ToolName = "fd" | "rg" | "sd" | "sg" | "yt-dlp" | "markitdown" | "html2text";
142
+
103
143
  // Get the path to a tool (system-wide or in our tools dir)
104
- export function getToolPath(tool: "fd" | "rg" | "sd" | "sg"): string | null {
144
+ export function getToolPath(tool: ToolName): string | null {
145
+ // Check Python tools first
146
+ const pythonConfig = PYTHON_TOOLS[tool];
147
+ if (pythonConfig) {
148
+ return commandExists(pythonConfig.binaryName);
149
+ }
150
+
105
151
  const config = TOOLS[tool];
106
152
  if (!config) return null;
107
153
 
@@ -156,7 +202,7 @@ async function downloadFile(url: string, dest: string): Promise<void> {
156
202
  }
157
203
 
158
204
  // Download and install a tool
159
- async function downloadTool(tool: "fd" | "rg" | "sd" | "sg"): Promise<string> {
205
+ async function downloadTool(tool: ToolName): Promise<string> {
160
206
  const config = TOOLS[tool];
161
207
  if (!config) throw new Error(`Unknown tool: ${tool}`);
162
208
 
@@ -176,11 +222,20 @@ async function downloadTool(tool: "fd" | "rg" | "sd" | "sg"): Promise<string> {
176
222
  mkdirSync(TOOLS_DIR, { recursive: true });
177
223
 
178
224
  const downloadUrl = `https://github.com/${config.repo}/releases/download/${config.tagPrefix}${version}/${assetName}`;
179
- const archivePath = join(TOOLS_DIR, assetName);
180
225
  const binaryExt = plat === "win32" ? ".exe" : "";
181
226
  const binaryPath = join(TOOLS_DIR, config.binaryName + binaryExt);
182
227
 
183
- // Download
228
+ // Handle direct binary downloads (no archive extraction needed)
229
+ if (config.isDirectBinary) {
230
+ await downloadFile(downloadUrl, binaryPath);
231
+ if (plat !== "win32") {
232
+ chmodSync(binaryPath, 0o755);
233
+ }
234
+ return binaryPath;
235
+ }
236
+
237
+ // Download archive
238
+ const archivePath = join(TOOLS_DIR, assetName);
184
239
  await downloadFile(downloadUrl, archivePath);
185
240
 
186
241
  // Extract
@@ -231,17 +286,64 @@ async function downloadTool(tool: "fd" | "rg" | "sd" | "sg"): Promise<string> {
231
286
  return binaryPath;
232
287
  }
233
288
 
289
+ // Install a Python package via uv (preferred) or pip
290
+ function installPythonPackage(pkg: string): boolean {
291
+ // Try uv first (faster, better isolation)
292
+ const uv = commandExists("uv");
293
+ if (uv) {
294
+ const result = Bun.spawnSync([uv, "tool", "install", pkg], {
295
+ stdin: "ignore",
296
+ stdout: "pipe",
297
+ stderr: "pipe",
298
+ });
299
+ if (result.exitCode === 0) return true;
300
+ }
301
+
302
+ // Fall back to pip
303
+ const pip = commandExists("pip3") || commandExists("pip");
304
+ if (pip) {
305
+ const result = Bun.spawnSync([pip, "install", "--user", pkg], {
306
+ stdin: "ignore",
307
+ stdout: "pipe",
308
+ stderr: "pipe",
309
+ });
310
+ return result.exitCode === 0;
311
+ }
312
+
313
+ return false;
314
+ }
315
+
234
316
  // Ensure a tool is available, downloading if necessary
235
317
  // Returns the path to the tool, or null if unavailable
236
- export async function ensureTool(
237
- tool: "fd" | "rg" | "sd" | "sg",
238
- silent: boolean = false,
239
- ): Promise<string | undefined> {
318
+ export async function ensureTool(tool: ToolName, silent: boolean = false): Promise<string | undefined> {
240
319
  const existingPath = getToolPath(tool);
241
320
  if (existingPath) {
242
321
  return existingPath;
243
322
  }
244
323
 
324
+ // Handle Python tools
325
+ const pythonConfig = PYTHON_TOOLS[tool];
326
+ if (pythonConfig) {
327
+ if (!silent) {
328
+ console.log(chalk.dim(`${pythonConfig.name} not found. Installing via uv/pip...`));
329
+ }
330
+ const success = installPythonPackage(pythonConfig.package);
331
+ if (success) {
332
+ // Re-check for the command after installation
333
+ const path = commandExists(pythonConfig.binaryName);
334
+ if (path) {
335
+ if (!silent) {
336
+ console.log(chalk.dim(`${pythonConfig.name} installed successfully`));
337
+ }
338
+ return path;
339
+ }
340
+ }
341
+ if (!silent) {
342
+ console.log(chalk.yellow(`Failed to install ${pythonConfig.name}`));
343
+ }
344
+ return undefined;
345
+ }
346
+
245
347
  const config = TOOLS[tool];
246
348
  if (!config) return undefined;
247
349