oma-coding-agent 1.1.4

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 (1298) hide show
  1. package/CHANGELOG.md +12164 -0
  2. package/README.md +35 -0
  3. package/dist/cli.js +18266 -0
  4. package/examples/README.md +21 -0
  5. package/examples/custom-tools/README.md +104 -0
  6. package/examples/custom-tools/hello/index.ts +20 -0
  7. package/examples/extensions/README.md +142 -0
  8. package/examples/extensions/api-demo.ts +79 -0
  9. package/examples/extensions/chalk-logger.ts +25 -0
  10. package/examples/extensions/hello.ts +31 -0
  11. package/examples/extensions/pirate.ts +43 -0
  12. package/examples/extensions/plan-mode.ts +549 -0
  13. package/examples/extensions/reload-runtime.ts +38 -0
  14. package/examples/extensions/thinking-note.ts +13 -0
  15. package/examples/extensions/tools.ts +145 -0
  16. package/examples/extensions/with-deps/index.ts +36 -0
  17. package/examples/extensions/with-deps/package-lock.json +31 -0
  18. package/examples/extensions/with-deps/package.json +17 -0
  19. package/examples/hooks/README.md +56 -0
  20. package/examples/hooks/auto-commit-on-exit.ts +48 -0
  21. package/examples/hooks/confirm-destructive.ts +58 -0
  22. package/examples/hooks/custom-compaction.ts +115 -0
  23. package/examples/hooks/dirty-repo-guard.ts +51 -0
  24. package/examples/hooks/file-trigger.ts +40 -0
  25. package/examples/hooks/git-checkpoint.ts +52 -0
  26. package/examples/hooks/handoff.ts +149 -0
  27. package/examples/hooks/permission-gate.ts +33 -0
  28. package/examples/hooks/protected-paths.ts +29 -0
  29. package/examples/hooks/qna.ts +118 -0
  30. package/examples/hooks/status-line.ts +39 -0
  31. package/examples/sdk/01-minimal.ts +21 -0
  32. package/examples/sdk/02-custom-model.ts +49 -0
  33. package/examples/sdk/03-custom-prompt.ts +46 -0
  34. package/examples/sdk/04-skills.ts +43 -0
  35. package/examples/sdk/06-extensions.ts +82 -0
  36. package/examples/sdk/06-hooks.ts +61 -0
  37. package/examples/sdk/07-context-files.ts +35 -0
  38. package/examples/sdk/08-prompt-templates.ts +41 -0
  39. package/examples/sdk/08-slash-commands.ts +46 -0
  40. package/examples/sdk/09-api-keys-and-oauth.ts +54 -0
  41. package/examples/sdk/11-sessions.ts +47 -0
  42. package/examples/sdk/12-redis-sessions.ts +54 -0
  43. package/examples/sdk/13-sql-sessions.ts +61 -0
  44. package/examples/sdk/README.md +172 -0
  45. package/package.json +573 -0
  46. package/scripts/bench-guard.ts +71 -0
  47. package/scripts/build-binary.ts +108 -0
  48. package/scripts/bundle-dist.ts +110 -0
  49. package/scripts/embed-mupdf-wasm.ts +67 -0
  50. package/scripts/format-prompts.ts +68 -0
  51. package/scripts/generate-docs-index.ts +56 -0
  52. package/scripts/generate-share-viewer.ts +34 -0
  53. package/scripts/measure-prompt-tokens.ts +63 -0
  54. package/scripts/omp +42 -0
  55. package/scripts/omp.ts +19 -0
  56. package/src/advisor/__tests__/advisor.test.ts +915 -0
  57. package/src/advisor/advise-tool.ts +165 -0
  58. package/src/advisor/index.ts +4 -0
  59. package/src/advisor/runtime.ts +270 -0
  60. package/src/advisor/transcript-recorder.ts +136 -0
  61. package/src/advisor/watchdog.ts +83 -0
  62. package/src/async/index.ts +1 -0
  63. package/src/async/job-manager.ts +674 -0
  64. package/src/auto-thinking/classifier.ts +190 -0
  65. package/src/autolearn/controller.ts +139 -0
  66. package/src/autolearn/managed-skills.ts +255 -0
  67. package/src/autoresearch/command-resume.md +14 -0
  68. package/src/autoresearch/dashboard.ts +436 -0
  69. package/src/autoresearch/git.ts +319 -0
  70. package/src/autoresearch/helpers.ts +218 -0
  71. package/src/autoresearch/index.ts +536 -0
  72. package/src/autoresearch/prompt-setup.md +43 -0
  73. package/src/autoresearch/prompt.md +103 -0
  74. package/src/autoresearch/resume-message.md +10 -0
  75. package/src/autoresearch/state.ts +273 -0
  76. package/src/autoresearch/storage.ts +700 -0
  77. package/src/autoresearch/tools/init-experiment.ts +269 -0
  78. package/src/autoresearch/tools/log-experiment.ts +521 -0
  79. package/src/autoresearch/tools/run-experiment.ts +407 -0
  80. package/src/autoresearch/tools/update-notes.ts +109 -0
  81. package/src/autoresearch/types.ts +168 -0
  82. package/src/capability/context-file.ts +44 -0
  83. package/src/capability/extension-module.ts +34 -0
  84. package/src/capability/extension.ts +47 -0
  85. package/src/capability/fs.ts +117 -0
  86. package/src/capability/hook.ts +40 -0
  87. package/src/capability/index.ts +436 -0
  88. package/src/capability/instruction.ts +37 -0
  89. package/src/capability/mcp.ts +76 -0
  90. package/src/capability/prompt.ts +35 -0
  91. package/src/capability/rule-buckets.ts +66 -0
  92. package/src/capability/rule.ts +261 -0
  93. package/src/capability/settings.ts +34 -0
  94. package/src/capability/skill.ts +63 -0
  95. package/src/capability/slash-command.ts +40 -0
  96. package/src/capability/ssh.ts +41 -0
  97. package/src/capability/system-prompt.ts +34 -0
  98. package/src/capability/tool.ts +38 -0
  99. package/src/capability/types.ts +168 -0
  100. package/src/cli/agents-cli.ts +138 -0
  101. package/src/cli/args.ts +361 -0
  102. package/src/cli/auth-broker-cli.ts +893 -0
  103. package/src/cli/auth-gateway-cli.ts +608 -0
  104. package/src/cli/bench-cli.ts +552 -0
  105. package/src/cli/classify-install-target.ts +76 -0
  106. package/src/cli/claude-trace-cli.ts +795 -0
  107. package/src/cli/commands/init-xdg.ts +27 -0
  108. package/src/cli/completion-gen.ts +550 -0
  109. package/src/cli/config-cli.ts +418 -0
  110. package/src/cli/dry-balance-cli.ts +858 -0
  111. package/src/cli/extension-flags.ts +48 -0
  112. package/src/cli/file-processor.ts +133 -0
  113. package/src/cli/flag-tables.ts +280 -0
  114. package/src/cli/gallery-cli.ts +231 -0
  115. package/src/cli/gallery-fixtures/agentic.ts +407 -0
  116. package/src/cli/gallery-fixtures/codeintel.ts +187 -0
  117. package/src/cli/gallery-fixtures/edit.ts +194 -0
  118. package/src/cli/gallery-fixtures/fs.ts +220 -0
  119. package/src/cli/gallery-fixtures/index.ts +40 -0
  120. package/src/cli/gallery-fixtures/interaction.ts +49 -0
  121. package/src/cli/gallery-fixtures/memory.ts +81 -0
  122. package/src/cli/gallery-fixtures/misc.ts +250 -0
  123. package/src/cli/gallery-fixtures/search.ts +213 -0
  124. package/src/cli/gallery-fixtures/shell.ts +167 -0
  125. package/src/cli/gallery-fixtures/types.ts +57 -0
  126. package/src/cli/gallery-fixtures/web.ts +158 -0
  127. package/src/cli/gallery-screenshot.ts +279 -0
  128. package/src/cli/grep-cli.ts +160 -0
  129. package/src/cli/grievances-cli.ts +256 -0
  130. package/src/cli/initial-message.ts +58 -0
  131. package/src/cli/models-cli.ts +427 -0
  132. package/src/cli/plugin-cli.ts +996 -0
  133. package/src/cli/profile-alias.ts +338 -0
  134. package/src/cli/profile-bootstrap.ts +243 -0
  135. package/src/cli/read-cli.ts +57 -0
  136. package/src/cli/session-picker.ts +80 -0
  137. package/src/cli/setup-cli.ts +332 -0
  138. package/src/cli/setup-model-picker.ts +43 -0
  139. package/src/cli/shell-cli.ts +176 -0
  140. package/src/cli/ssh-cli.ts +179 -0
  141. package/src/cli/startup-cwd.ts +58 -0
  142. package/src/cli/stats-cli.ts +229 -0
  143. package/src/cli/tiny-models-cli.ts +127 -0
  144. package/src/cli/ttsr-cli.ts +995 -0
  145. package/src/cli/update-cli.ts +671 -0
  146. package/src/cli/usage-cli.ts +774 -0
  147. package/src/cli/web-search-cli.ts +132 -0
  148. package/src/cli/worktree-cli.ts +291 -0
  149. package/src/cli-commands.ts +85 -0
  150. package/src/cli.ts +326 -0
  151. package/src/collab/crypto.ts +63 -0
  152. package/src/collab/guest.ts +450 -0
  153. package/src/collab/host.ts +577 -0
  154. package/src/collab/protocol.ts +274 -0
  155. package/src/collab/relay-client.ts +216 -0
  156. package/src/commands/acp.ts +24 -0
  157. package/src/commands/agents.ts +57 -0
  158. package/src/commands/auth-broker.ts +99 -0
  159. package/src/commands/auth-gateway.ts +69 -0
  160. package/src/commands/bench.ts +42 -0
  161. package/src/commands/commit.ts +46 -0
  162. package/src/commands/complete.ts +66 -0
  163. package/src/commands/completions.ts +60 -0
  164. package/src/commands/config.ts +51 -0
  165. package/src/commands/dry-balance.ts +43 -0
  166. package/src/commands/gallery.ts +52 -0
  167. package/src/commands/grep.ts +48 -0
  168. package/src/commands/grievances.ts +51 -0
  169. package/src/commands/install.ts +107 -0
  170. package/src/commands/join.ts +39 -0
  171. package/src/commands/launch.ts +182 -0
  172. package/src/commands/models.ts +61 -0
  173. package/src/commands/plugin.ts +78 -0
  174. package/src/commands/read.ts +38 -0
  175. package/src/commands/say.ts +102 -0
  176. package/src/commands/setup.ts +67 -0
  177. package/src/commands/shell.ts +29 -0
  178. package/src/commands/ssh.ts +60 -0
  179. package/src/commands/stats.ts +29 -0
  180. package/src/commands/tiny-models.ts +36 -0
  181. package/src/commands/token.ts +108 -0
  182. package/src/commands/ttsr.ts +125 -0
  183. package/src/commands/update.ts +21 -0
  184. package/src/commands/usage.ts +43 -0
  185. package/src/commands/web-search.ts +42 -0
  186. package/src/commands/worktree.ts +56 -0
  187. package/src/commit/agentic/agent.ts +318 -0
  188. package/src/commit/agentic/fallback.ts +96 -0
  189. package/src/commit/agentic/index.ts +355 -0
  190. package/src/commit/agentic/prompts/analyze-file.md +22 -0
  191. package/src/commit/agentic/prompts/session-user.md +25 -0
  192. package/src/commit/agentic/prompts/split-confirm.md +1 -0
  193. package/src/commit/agentic/prompts/system.md +38 -0
  194. package/src/commit/agentic/state.ts +60 -0
  195. package/src/commit/agentic/tools/analyze-file.ts +149 -0
  196. package/src/commit/agentic/tools/git-file-diff.ts +191 -0
  197. package/src/commit/agentic/tools/git-hunk.ts +52 -0
  198. package/src/commit/agentic/tools/git-overview.ts +81 -0
  199. package/src/commit/agentic/tools/index.ts +54 -0
  200. package/src/commit/agentic/tools/propose-changelog.ts +147 -0
  201. package/src/commit/agentic/tools/propose-commit.ts +109 -0
  202. package/src/commit/agentic/tools/recent-commits.ts +81 -0
  203. package/src/commit/agentic/tools/schemas.ts +11 -0
  204. package/src/commit/agentic/tools/split-commit.ts +241 -0
  205. package/src/commit/agentic/topo-sort.ts +44 -0
  206. package/src/commit/agentic/trivial.ts +51 -0
  207. package/src/commit/agentic/validation.ts +183 -0
  208. package/src/commit/analysis/conventional.ts +64 -0
  209. package/src/commit/analysis/index.ts +4 -0
  210. package/src/commit/analysis/scope.ts +242 -0
  211. package/src/commit/analysis/summary.ts +107 -0
  212. package/src/commit/analysis/validation.ts +66 -0
  213. package/src/commit/changelog/detect.ts +40 -0
  214. package/src/commit/changelog/generate.ts +101 -0
  215. package/src/commit/changelog/index.ts +234 -0
  216. package/src/commit/changelog/parse.ts +44 -0
  217. package/src/commit/cli.ts +85 -0
  218. package/src/commit/git/diff.ts +148 -0
  219. package/src/commit/index.ts +5 -0
  220. package/src/commit/map-reduce/index.ts +69 -0
  221. package/src/commit/map-reduce/map-phase.ts +193 -0
  222. package/src/commit/map-reduce/reduce-phase.ts +49 -0
  223. package/src/commit/map-reduce/utils.ts +9 -0
  224. package/src/commit/message.ts +11 -0
  225. package/src/commit/model-selection.ts +89 -0
  226. package/src/commit/pipeline.ts +243 -0
  227. package/src/commit/prompts/analysis-system.md +148 -0
  228. package/src/commit/prompts/analysis-user.md +38 -0
  229. package/src/commit/prompts/changelog-system.md +50 -0
  230. package/src/commit/prompts/changelog-user.md +18 -0
  231. package/src/commit/prompts/file-observer-system.md +24 -0
  232. package/src/commit/prompts/file-observer-user.md +8 -0
  233. package/src/commit/prompts/reduce-system.md +50 -0
  234. package/src/commit/prompts/reduce-user.md +17 -0
  235. package/src/commit/prompts/summary-retry.md +3 -0
  236. package/src/commit/prompts/summary-system.md +38 -0
  237. package/src/commit/prompts/summary-user.md +13 -0
  238. package/src/commit/prompts/types-description.md +2 -0
  239. package/src/commit/shared-llm.ts +70 -0
  240. package/src/commit/types.ts +118 -0
  241. package/src/commit/utils/exclusions.ts +42 -0
  242. package/src/commit/utils.ts +58 -0
  243. package/src/config/api-key-resolver.ts +67 -0
  244. package/src/config/append-only-context-mode.ts +76 -0
  245. package/src/config/config-file.ts +315 -0
  246. package/src/config/file-lock.ts +164 -0
  247. package/src/config/keybindings.ts +634 -0
  248. package/src/config/mcp-schema.json +238 -0
  249. package/src/config/model-discovery.ts +589 -0
  250. package/src/config/model-registry.ts +2260 -0
  251. package/src/config/model-resolver.ts +1819 -0
  252. package/src/config/model-roles.ts +99 -0
  253. package/src/config/models-config-schema.ts +266 -0
  254. package/src/config/models-config.ts +131 -0
  255. package/src/config/prompt-templates.ts +185 -0
  256. package/src/config/resolve-config-value.ts +94 -0
  257. package/src/config/settings-schema.ts +4740 -0
  258. package/src/config/settings.ts +1243 -0
  259. package/src/config.ts +242 -0
  260. package/src/cursor.ts +340 -0
  261. package/src/dap/client.ts +760 -0
  262. package/src/dap/config.ts +189 -0
  263. package/src/dap/defaults.json +212 -0
  264. package/src/dap/index.ts +4 -0
  265. package/src/dap/session.ts +1441 -0
  266. package/src/dap/types.ts +610 -0
  267. package/src/debug/index.ts +559 -0
  268. package/src/debug/log-formatting.ts +58 -0
  269. package/src/debug/log-viewer.ts +908 -0
  270. package/src/debug/profiler.ts +162 -0
  271. package/src/debug/protocol-probe.ts +267 -0
  272. package/src/debug/raw-sse-buffer.ts +294 -0
  273. package/src/debug/raw-sse.ts +292 -0
  274. package/src/debug/remote-debugger.ts +151 -0
  275. package/src/debug/report-bundle.ts +375 -0
  276. package/src/debug/system-info.ts +111 -0
  277. package/src/debug/terminal-info.ts +124 -0
  278. package/src/discovery/agents-md.ts +67 -0
  279. package/src/discovery/agents.ts +230 -0
  280. package/src/discovery/at-imports.ts +273 -0
  281. package/src/discovery/builtin-defaults.ts +39 -0
  282. package/src/discovery/builtin-rules/index.ts +63 -0
  283. package/src/discovery/builtin-rules/low-end/no-hallucinated-apis.md +14 -0
  284. package/src/discovery/builtin-rules/low-end/no-hallucinated-paths.md +14 -0
  285. package/src/discovery/builtin-rules/low-end/no-premature-completion.md +14 -0
  286. package/src/discovery/builtin-rules/rs-box-leak.md +48 -0
  287. package/src/discovery/builtin-rules/rs-future-prelude.md +23 -0
  288. package/src/discovery/builtin-rules/rs-lazylock.md +51 -0
  289. package/src/discovery/builtin-rules/rs-match-ergonomics.md +67 -0
  290. package/src/discovery/builtin-rules/rs-parking-lot.md +44 -0
  291. package/src/discovery/builtin-rules/rs-result-type.md +19 -0
  292. package/src/discovery/builtin-rules/ts-bare-catch.md +38 -0
  293. package/src/discovery/builtin-rules/ts-import-type.md +42 -0
  294. package/src/discovery/builtin-rules/ts-no-any.md +65 -0
  295. package/src/discovery/builtin-rules/ts-no-deprecated-leftovers.md +44 -0
  296. package/src/discovery/builtin-rules/ts-no-dynamic-import.md +39 -0
  297. package/src/discovery/builtin-rules/ts-no-inline-cast-access.md +55 -0
  298. package/src/discovery/builtin-rules/ts-no-return-type.md +44 -0
  299. package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
  300. package/src/discovery/builtin-rules/ts-no-tiny-functions.md +51 -0
  301. package/src/discovery/builtin-rules/ts-promise-with-resolvers.md +65 -0
  302. package/src/discovery/builtin-rules/ts-redundant-clear-guard.md +75 -0
  303. package/src/discovery/builtin-rules/ts-set-map.md +28 -0
  304. package/src/discovery/builtin.ts +934 -0
  305. package/src/discovery/claude-plugins.ts +386 -0
  306. package/src/discovery/claude.ts +584 -0
  307. package/src/discovery/cline.ts +83 -0
  308. package/src/discovery/codex.ts +522 -0
  309. package/src/discovery/cursor.ts +220 -0
  310. package/src/discovery/gemini.ts +383 -0
  311. package/src/discovery/github.ts +337 -0
  312. package/src/discovery/helpers.ts +1092 -0
  313. package/src/discovery/index.ts +81 -0
  314. package/src/discovery/mcp-json.ts +172 -0
  315. package/src/discovery/omp-extension-roots.ts +190 -0
  316. package/src/discovery/omp-plugins.ts +383 -0
  317. package/src/discovery/opencode.ts +398 -0
  318. package/src/discovery/plugin-dir-roots.ts +28 -0
  319. package/src/discovery/ssh.ts +153 -0
  320. package/src/discovery/substitute-plugin-root.ts +29 -0
  321. package/src/discovery/vscode.ts +105 -0
  322. package/src/discovery/windsurf.ts +147 -0
  323. package/src/edit/apply-patch/index.ts +87 -0
  324. package/src/edit/apply-patch/parser.ts +174 -0
  325. package/src/edit/diff.ts +999 -0
  326. package/src/edit/file-snapshot-store.ts +143 -0
  327. package/src/edit/hashline/block-resolver.ts +33 -0
  328. package/src/edit/hashline/diff.ts +290 -0
  329. package/src/edit/hashline/execute.ts +237 -0
  330. package/src/edit/hashline/filesystem.ts +130 -0
  331. package/src/edit/hashline/index.ts +5 -0
  332. package/src/edit/hashline/noop-loop-guard.ts +99 -0
  333. package/src/edit/hashline/params.ts +19 -0
  334. package/src/edit/index.ts +620 -0
  335. package/src/edit/modes/apply-patch.lark +19 -0
  336. package/src/edit/modes/apply-patch.ts +53 -0
  337. package/src/edit/modes/patch.ts +1888 -0
  338. package/src/edit/modes/replace.ts +1133 -0
  339. package/src/edit/normalize.ts +345 -0
  340. package/src/edit/notebook.ts +242 -0
  341. package/src/edit/read-file.ts +25 -0
  342. package/src/edit/renderer.ts +823 -0
  343. package/src/edit/streaming.ts +517 -0
  344. package/src/eval/__tests__/agent-bridge.test.ts +769 -0
  345. package/src/eval/__tests__/bridge-timeout.test.ts +64 -0
  346. package/src/eval/__tests__/budget-bridge.test.ts +69 -0
  347. package/src/eval/__tests__/completion-bridge.test.ts +412 -0
  348. package/src/eval/__tests__/helpers-local-roots.test.ts +58 -0
  349. package/src/eval/__tests__/idle-timeout.test.ts +80 -0
  350. package/src/eval/__tests__/js-context-manager.test.ts +291 -0
  351. package/src/eval/__tests__/kernel-spawn.test.ts +103 -0
  352. package/src/eval/__tests__/prelude-agent.test.ts +73 -0
  353. package/src/eval/agent-bridge.ts +319 -0
  354. package/src/eval/backend.ts +71 -0
  355. package/src/eval/bridge-timeout.ts +44 -0
  356. package/src/eval/budget-bridge.ts +48 -0
  357. package/src/eval/completion-bridge.ts +211 -0
  358. package/src/eval/concurrency-bridge.ts +34 -0
  359. package/src/eval/idle-timeout.ts +91 -0
  360. package/src/eval/index.ts +4 -0
  361. package/src/eval/js/context-manager.ts +621 -0
  362. package/src/eval/js/executor.ts +173 -0
  363. package/src/eval/js/index.ts +51 -0
  364. package/src/eval/js/shared/helpers.ts +283 -0
  365. package/src/eval/js/shared/indirect-eval.ts +30 -0
  366. package/src/eval/js/shared/local-module-loader.ts +342 -0
  367. package/src/eval/js/shared/prelude.ts +2 -0
  368. package/src/eval/js/shared/prelude.txt +307 -0
  369. package/src/eval/js/shared/rewrite-imports.ts +532 -0
  370. package/src/eval/js/shared/runtime.ts +580 -0
  371. package/src/eval/js/shared/types.ts +18 -0
  372. package/src/eval/js/tool-bridge.ts +163 -0
  373. package/src/eval/js/worker-core.ts +151 -0
  374. package/src/eval/js/worker-entry.ts +37 -0
  375. package/src/eval/js/worker-protocol.ts +47 -0
  376. package/src/eval/py/__tests__/prelude.test.ts +19 -0
  377. package/src/eval/py/display.ts +71 -0
  378. package/src/eval/py/executor.ts +742 -0
  379. package/src/eval/py/index.ts +68 -0
  380. package/src/eval/py/kernel.ts +748 -0
  381. package/src/eval/py/prelude.py +683 -0
  382. package/src/eval/py/prelude.ts +3 -0
  383. package/src/eval/py/runner.py +1177 -0
  384. package/src/eval/py/runtime.ts +276 -0
  385. package/src/eval/py/spawn-options.ts +126 -0
  386. package/src/eval/py/tool-bridge.ts +182 -0
  387. package/src/eval/session-id.ts +8 -0
  388. package/src/eval/types.ts +48 -0
  389. package/src/exa/index.ts +2 -0
  390. package/src/exa/mcp-client.ts +370 -0
  391. package/src/exa/types.ts +69 -0
  392. package/src/exec/bash-executor.ts +434 -0
  393. package/src/exec/exec.ts +53 -0
  394. package/src/exec/non-interactive-env.ts +119 -0
  395. package/src/export/custom-share.ts +65 -0
  396. package/src/export/html/index.ts +266 -0
  397. package/src/export/html/share-loader.js +102 -0
  398. package/src/export/html/template.css +1337 -0
  399. package/src/export/html/template.html +49 -0
  400. package/src/export/html/template.js +1626 -0
  401. package/src/export/html/tool-views.generated.js +37 -0
  402. package/src/export/html/vendor/highlight.min.js +1213 -0
  403. package/src/export/html/vendor/marked.min.js +6 -0
  404. package/src/export/share.ts +268 -0
  405. package/src/export/ttsr.ts +583 -0
  406. package/src/extensibility/custom-commands/bundled/ci-green/index.ts +54 -0
  407. package/src/extensibility/custom-commands/bundled/review/index.ts +698 -0
  408. package/src/extensibility/custom-commands/index.ts +2 -0
  409. package/src/extensibility/custom-commands/loader.ts +242 -0
  410. package/src/extensibility/custom-commands/types.ts +119 -0
  411. package/src/extensibility/custom-tools/index.ts +7 -0
  412. package/src/extensibility/custom-tools/loader.ts +268 -0
  413. package/src/extensibility/custom-tools/types.ts +277 -0
  414. package/src/extensibility/custom-tools/wrapper.ts +47 -0
  415. package/src/extensibility/extensions/compact-handler.ts +40 -0
  416. package/src/extensibility/extensions/get-commands-handler.ts +78 -0
  417. package/src/extensibility/extensions/index.ts +16 -0
  418. package/src/extensibility/extensions/loader.ts +587 -0
  419. package/src/extensibility/extensions/model-api.ts +41 -0
  420. package/src/extensibility/extensions/runner.ts +989 -0
  421. package/src/extensibility/extensions/types.ts +1394 -0
  422. package/src/extensibility/extensions/wrapper.ts +259 -0
  423. package/src/extensibility/hooks/index.ts +6 -0
  424. package/src/extensibility/hooks/loader.ts +262 -0
  425. package/src/extensibility/hooks/runner.ts +425 -0
  426. package/src/extensibility/hooks/tool-wrapper.ts +107 -0
  427. package/src/extensibility/hooks/types.ts +613 -0
  428. package/src/extensibility/legacy-pi-ai-shim.ts +61 -0
  429. package/src/extensibility/legacy-pi-coding-agent-shim.ts +128 -0
  430. package/src/extensibility/plugins/doctor.ts +65 -0
  431. package/src/extensibility/plugins/git-url.ts +367 -0
  432. package/src/extensibility/plugins/index.ts +9 -0
  433. package/src/extensibility/plugins/installer.ts +192 -0
  434. package/src/extensibility/plugins/legacy-pi-compat.ts +712 -0
  435. package/src/extensibility/plugins/loader.ts +458 -0
  436. package/src/extensibility/plugins/manager.ts +1026 -0
  437. package/src/extensibility/plugins/marketplace/cache.ts +136 -0
  438. package/src/extensibility/plugins/marketplace/fetcher.ts +315 -0
  439. package/src/extensibility/plugins/marketplace/index.ts +6 -0
  440. package/src/extensibility/plugins/marketplace/manager.ts +770 -0
  441. package/src/extensibility/plugins/marketplace/registry.ts +196 -0
  442. package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
  443. package/src/extensibility/plugins/marketplace/types.ts +191 -0
  444. package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
  445. package/src/extensibility/plugins/parser.ts +105 -0
  446. package/src/extensibility/plugins/runtime-config.ts +9 -0
  447. package/src/extensibility/plugins/types.ts +194 -0
  448. package/src/extensibility/shared-events.ts +367 -0
  449. package/src/extensibility/skills.ts +408 -0
  450. package/src/extensibility/slash-commands.ts +131 -0
  451. package/src/extensibility/tool-proxy.ts +28 -0
  452. package/src/extensibility/typebox.ts +945 -0
  453. package/src/extensibility/utils.ts +44 -0
  454. package/src/goals/guided-setup.ts +142 -0
  455. package/src/goals/index.ts +3 -0
  456. package/src/goals/runtime.ts +521 -0
  457. package/src/goals/state.ts +37 -0
  458. package/src/goals/tools/goal-tool.ts +251 -0
  459. package/src/hindsight/backend.ts +354 -0
  460. package/src/hindsight/bank.ts +156 -0
  461. package/src/hindsight/client.ts +623 -0
  462. package/src/hindsight/config.ts +175 -0
  463. package/src/hindsight/content.ts +210 -0
  464. package/src/hindsight/index.ts +8 -0
  465. package/src/hindsight/mental-models.ts +429 -0
  466. package/src/hindsight/seeds.json +32 -0
  467. package/src/hindsight/state.ts +492 -0
  468. package/src/hindsight/transcript.ts +71 -0
  469. package/src/index.ts +66 -0
  470. package/src/internal-urls/agent-protocol.ts +146 -0
  471. package/src/internal-urls/artifact-protocol.ts +107 -0
  472. package/src/internal-urls/docs-index.generated.txt +2 -0
  473. package/src/internal-urls/docs-index.ts +102 -0
  474. package/src/internal-urls/history-protocol.ts +118 -0
  475. package/src/internal-urls/index.ts +25 -0
  476. package/src/internal-urls/issue-pr-protocol.ts +594 -0
  477. package/src/internal-urls/json-query.ts +126 -0
  478. package/src/internal-urls/local-protocol.ts +309 -0
  479. package/src/internal-urls/mcp-protocol.ts +151 -0
  480. package/src/internal-urls/memory-protocol.ts +169 -0
  481. package/src/internal-urls/omp-protocol.ts +94 -0
  482. package/src/internal-urls/parse.ts +72 -0
  483. package/src/internal-urls/registry-helpers.ts +25 -0
  484. package/src/internal-urls/router.ts +105 -0
  485. package/src/internal-urls/rule-protocol.ts +45 -0
  486. package/src/internal-urls/skill-protocol.ts +96 -0
  487. package/src/internal-urls/types.ts +152 -0
  488. package/src/internal-urls/vault-protocol.ts +936 -0
  489. package/src/irc/bus.ts +311 -0
  490. package/src/lib/xai-http.ts +124 -0
  491. package/src/lsp/client.ts +1217 -0
  492. package/src/lsp/clients/biome-client.ts +264 -0
  493. package/src/lsp/clients/index.ts +50 -0
  494. package/src/lsp/clients/lsp-linter-client.ts +85 -0
  495. package/src/lsp/clients/swiftlint-client.ts +120 -0
  496. package/src/lsp/config.ts +502 -0
  497. package/src/lsp/defaults.json +499 -0
  498. package/src/lsp/diagnostics-ledger.ts +51 -0
  499. package/src/lsp/edits.ts +267 -0
  500. package/src/lsp/format-options.ts +119 -0
  501. package/src/lsp/index.ts +2480 -0
  502. package/src/lsp/lspmux.ts +233 -0
  503. package/src/lsp/render.ts +668 -0
  504. package/src/lsp/startup-events.ts +13 -0
  505. package/src/lsp/types.ts +444 -0
  506. package/src/lsp/utils.ts +718 -0
  507. package/src/main.ts +1421 -0
  508. package/src/markit/NOTICE +32 -0
  509. package/src/markit/converters/docx.ts +56 -0
  510. package/src/markit/converters/epub.ts +136 -0
  511. package/src/markit/converters/mammoth.d.ts +24 -0
  512. package/src/markit/converters/pdf/columns.ts +103 -0
  513. package/src/markit/converters/pdf/extract.ts +574 -0
  514. package/src/markit/converters/pdf/grid.ts +780 -0
  515. package/src/markit/converters/pdf/headers.ts +106 -0
  516. package/src/markit/converters/pdf/index.ts +146 -0
  517. package/src/markit/converters/pdf/render.ts +501 -0
  518. package/src/markit/converters/pdf/types.ts +84 -0
  519. package/src/markit/converters/pptx.ts +325 -0
  520. package/src/markit/converters/xlsx.ts +173 -0
  521. package/src/markit/index.ts +2 -0
  522. package/src/markit/registry.ts +59 -0
  523. package/src/markit/types.ts +35 -0
  524. package/src/mcp/client.ts +509 -0
  525. package/src/mcp/config-writer.ts +229 -0
  526. package/src/mcp/config.ts +365 -0
  527. package/src/mcp/index.ts +29 -0
  528. package/src/mcp/json-rpc.ts +122 -0
  529. package/src/mcp/loader.ts +124 -0
  530. package/src/mcp/manager.ts +1326 -0
  531. package/src/mcp/oauth-credentials.ts +104 -0
  532. package/src/mcp/oauth-discovery.ts +467 -0
  533. package/src/mcp/oauth-flow.ts +555 -0
  534. package/src/mcp/render.ts +155 -0
  535. package/src/mcp/smithery-auth.ts +104 -0
  536. package/src/mcp/smithery-connect.ts +145 -0
  537. package/src/mcp/smithery-registry.ts +477 -0
  538. package/src/mcp/startup-events.ts +21 -0
  539. package/src/mcp/timeout.ts +59 -0
  540. package/src/mcp/tool-bridge.ts +429 -0
  541. package/src/mcp/tool-cache.ts +117 -0
  542. package/src/mcp/transports/http.ts +519 -0
  543. package/src/mcp/transports/index.ts +6 -0
  544. package/src/mcp/transports/stdio.ts +606 -0
  545. package/src/mcp/types.ts +427 -0
  546. package/src/memories/index.ts +1281 -0
  547. package/src/memories/storage.ts +578 -0
  548. package/src/memory-backend/index.ts +18 -0
  549. package/src/memory-backend/local-backend.ts +45 -0
  550. package/src/memory-backend/off-backend.ts +25 -0
  551. package/src/memory-backend/resolve.ts +25 -0
  552. package/src/memory-backend/runtime.ts +66 -0
  553. package/src/memory-backend/types.ts +166 -0
  554. package/src/mnemopi/backend.ts +612 -0
  555. package/src/mnemopi/config.ts +265 -0
  556. package/src/mnemopi/embed-client.ts +401 -0
  557. package/src/mnemopi/embed-protocol.ts +35 -0
  558. package/src/mnemopi/embed-worker.ts +113 -0
  559. package/src/mnemopi/index.ts +3 -0
  560. package/src/mnemopi/state.ts +657 -0
  561. package/src/modes/acp/acp-agent.ts +2362 -0
  562. package/src/modes/acp/acp-client-bridge.ts +154 -0
  563. package/src/modes/acp/acp-event-mapper.ts +933 -0
  564. package/src/modes/acp/acp-mode.ts +23 -0
  565. package/src/modes/acp/index.ts +2 -0
  566. package/src/modes/acp/terminal-auth.ts +37 -0
  567. package/src/modes/components/__tests__/skill-message.test.ts +92 -0
  568. package/src/modes/components/advisor-message.ts +99 -0
  569. package/src/modes/components/agent-dashboard.ts +1206 -0
  570. package/src/modes/components/agent-hub.ts +566 -0
  571. package/src/modes/components/agent-transcript-viewer.ts +461 -0
  572. package/src/modes/components/assistant-message.ts +612 -0
  573. package/src/modes/components/background-tan-message.ts +36 -0
  574. package/src/modes/components/bash-execution.ts +220 -0
  575. package/src/modes/components/bordered-loader.ts +41 -0
  576. package/src/modes/components/btw-panel.ts +112 -0
  577. package/src/modes/components/cache-invalidation-marker.ts +110 -0
  578. package/src/modes/components/chat-block.ts +111 -0
  579. package/src/modes/components/chat-transcript-builder.ts +476 -0
  580. package/src/modes/components/collab-prompt-message.ts +32 -0
  581. package/src/modes/components/compaction-summary-message.ts +215 -0
  582. package/src/modes/components/copy-selector.ts +206 -0
  583. package/src/modes/components/countdown-timer.ts +75 -0
  584. package/src/modes/components/custom-editor.test.ts +142 -0
  585. package/src/modes/components/custom-editor.ts +620 -0
  586. package/src/modes/components/custom-message.ts +67 -0
  587. package/src/modes/components/diff.ts +254 -0
  588. package/src/modes/components/dynamic-border.ts +34 -0
  589. package/src/modes/components/error-banner.ts +33 -0
  590. package/src/modes/components/eval-execution.ts +158 -0
  591. package/src/modes/components/execution-shared.ts +101 -0
  592. package/src/modes/components/extensions/extension-dashboard.ts +399 -0
  593. package/src/modes/components/extensions/extension-list.ts +502 -0
  594. package/src/modes/components/extensions/index.ts +9 -0
  595. package/src/modes/components/extensions/inspector-panel.ts +321 -0
  596. package/src/modes/components/extensions/state-manager.ts +627 -0
  597. package/src/modes/components/extensions/types.ts +186 -0
  598. package/src/modes/components/footer.ts +275 -0
  599. package/src/modes/components/history-search.ts +280 -0
  600. package/src/modes/components/hook-editor.ts +167 -0
  601. package/src/modes/components/hook-input.ts +87 -0
  602. package/src/modes/components/hook-message.ts +67 -0
  603. package/src/modes/components/hook-selector.ts +659 -0
  604. package/src/modes/components/index.ts +38 -0
  605. package/src/modes/components/keybinding-hints.ts +65 -0
  606. package/src/modes/components/late-diagnostics-message.ts +60 -0
  607. package/src/modes/components/login-dialog.ts +164 -0
  608. package/src/modes/components/logout-account-selector.ts +130 -0
  609. package/src/modes/components/mcp-add-wizard.ts +1360 -0
  610. package/src/modes/components/message-frame.ts +92 -0
  611. package/src/modes/components/model-selector.ts +1315 -0
  612. package/src/modes/components/oauth-selector.ts +457 -0
  613. package/src/modes/components/omfg-panel.ts +141 -0
  614. package/src/modes/components/overlay-box.ts +109 -0
  615. package/src/modes/components/plan-review-overlay.ts +847 -0
  616. package/src/modes/components/plan-toc.ts +138 -0
  617. package/src/modes/components/plugin-selector.ts +95 -0
  618. package/src/modes/components/plugin-settings.ts +739 -0
  619. package/src/modes/components/queue-mode-selector.ts +56 -0
  620. package/src/modes/components/read-tool-group.ts +676 -0
  621. package/src/modes/components/reset-usage-selector.ts +161 -0
  622. package/src/modes/components/segment-track.ts +89 -0
  623. package/src/modes/components/session-selector.ts +631 -0
  624. package/src/modes/components/settings-defs.ts +225 -0
  625. package/src/modes/components/settings-selector.ts +1095 -0
  626. package/src/modes/components/show-images-selector.ts +45 -0
  627. package/src/modes/components/skill-message.ts +110 -0
  628. package/src/modes/components/snapcompact-shape-preview-doc.md +18 -0
  629. package/src/modes/components/snapcompact-shape-preview.ts +192 -0
  630. package/src/modes/components/status-line/component.ts +1001 -0
  631. package/src/modes/components/status-line/context-thresholds.ts +78 -0
  632. package/src/modes/components/status-line/git-utils.ts +42 -0
  633. package/src/modes/components/status-line/index.ts +5 -0
  634. package/src/modes/components/status-line/presets.ts +106 -0
  635. package/src/modes/components/status-line/segments.ts +616 -0
  636. package/src/modes/components/status-line/separators.ts +55 -0
  637. package/src/modes/components/status-line/token-rate.ts +66 -0
  638. package/src/modes/components/status-line/types.ts +124 -0
  639. package/src/modes/components/theme-selector.ts +63 -0
  640. package/src/modes/components/thinking-selector.ts +52 -0
  641. package/src/modes/components/tiny-title-download-progress.ts +90 -0
  642. package/src/modes/components/tips.txt +24 -0
  643. package/src/modes/components/todo-reminder.ts +39 -0
  644. package/src/modes/components/tool-execution.ts +1165 -0
  645. package/src/modes/components/transcript-container.ts +806 -0
  646. package/src/modes/components/tree-selector.ts +994 -0
  647. package/src/modes/components/ttsr-notification.ts +123 -0
  648. package/src/modes/components/usage-row.ts +18 -0
  649. package/src/modes/components/user-message-selector.ts +227 -0
  650. package/src/modes/components/user-message.ts +68 -0
  651. package/src/modes/components/visual-truncate.ts +63 -0
  652. package/src/modes/components/welcome.ts +581 -0
  653. package/src/modes/controllers/btw-controller.ts +173 -0
  654. package/src/modes/controllers/command-controller-shared.ts +109 -0
  655. package/src/modes/controllers/command-controller.ts +1653 -0
  656. package/src/modes/controllers/event-controller.ts +1153 -0
  657. package/src/modes/controllers/extension-ui-controller.ts +893 -0
  658. package/src/modes/controllers/input-controller.ts +1627 -0
  659. package/src/modes/controllers/mcp-command-controller.ts +2162 -0
  660. package/src/modes/controllers/omfg-controller.ts +283 -0
  661. package/src/modes/controllers/omfg-rule.ts +647 -0
  662. package/src/modes/controllers/selector-controller.ts +1285 -0
  663. package/src/modes/controllers/session-focus-controller.ts +112 -0
  664. package/src/modes/controllers/ssh-command-controller.ts +384 -0
  665. package/src/modes/controllers/streaming-reveal.ts +295 -0
  666. package/src/modes/controllers/tan-command-controller.ts +190 -0
  667. package/src/modes/controllers/todo-command-controller.ts +485 -0
  668. package/src/modes/controllers/tool-args-reveal.ts +174 -0
  669. package/src/modes/data/emojis.json +1 -0
  670. package/src/modes/emoji-autocomplete.ts +285 -0
  671. package/src/modes/gradient-highlight.ts +99 -0
  672. package/src/modes/image-references.ts +137 -0
  673. package/src/modes/index.ts +17 -0
  674. package/src/modes/interactive-mode.ts +3940 -0
  675. package/src/modes/internal-url-autocomplete.ts +143 -0
  676. package/src/modes/loop-limit.ts +192 -0
  677. package/src/modes/magic-keywords.ts +42 -0
  678. package/src/modes/markdown-prose.ts +247 -0
  679. package/src/modes/oauth-manual-input.ts +69 -0
  680. package/src/modes/orchestrate.ts +42 -0
  681. package/src/modes/print-mode.ts +130 -0
  682. package/src/modes/prompt-action-autocomplete.ts +260 -0
  683. package/src/modes/rpc/host-tools.ts +186 -0
  684. package/src/modes/rpc/host-uris.ts +235 -0
  685. package/src/modes/rpc/rpc-client.ts +995 -0
  686. package/src/modes/rpc/rpc-mode.ts +1156 -0
  687. package/src/modes/rpc/rpc-subagents.ts +265 -0
  688. package/src/modes/rpc/rpc-types.ts +487 -0
  689. package/src/modes/runtime-init.ts +142 -0
  690. package/src/modes/session-observer-registry.ts +215 -0
  691. package/src/modes/setup-version.ts +11 -0
  692. package/src/modes/setup-wizard/index.ts +101 -0
  693. package/src/modes/setup-wizard/lazy.ts +16 -0
  694. package/src/modes/setup-wizard/scenes/glyph.ts +114 -0
  695. package/src/modes/setup-wizard/scenes/outro.ts +35 -0
  696. package/src/modes/setup-wizard/scenes/providers.ts +103 -0
  697. package/src/modes/setup-wizard/scenes/sign-in.ts +286 -0
  698. package/src/modes/setup-wizard/scenes/splash.ts +201 -0
  699. package/src/modes/setup-wizard/scenes/theme.ts +326 -0
  700. package/src/modes/setup-wizard/scenes/types.ts +57 -0
  701. package/src/modes/setup-wizard/scenes/web-search.ts +145 -0
  702. package/src/modes/setup-wizard/startup-splash.ts +107 -0
  703. package/src/modes/setup-wizard/wizard-overlay.ts +334 -0
  704. package/src/modes/shared.ts +49 -0
  705. package/src/modes/theme/dark.json +95 -0
  706. package/src/modes/theme/defaults/alabaster.json +93 -0
  707. package/src/modes/theme/defaults/amethyst.json +96 -0
  708. package/src/modes/theme/defaults/anthracite.json +93 -0
  709. package/src/modes/theme/defaults/basalt.json +91 -0
  710. package/src/modes/theme/defaults/birch.json +95 -0
  711. package/src/modes/theme/defaults/dark-abyss.json +91 -0
  712. package/src/modes/theme/defaults/dark-arctic.json +104 -0
  713. package/src/modes/theme/defaults/dark-aurora.json +95 -0
  714. package/src/modes/theme/defaults/dark-catppuccin.json +107 -0
  715. package/src/modes/theme/defaults/dark-cavern.json +91 -0
  716. package/src/modes/theme/defaults/dark-copper.json +95 -0
  717. package/src/modes/theme/defaults/dark-cosmos.json +90 -0
  718. package/src/modes/theme/defaults/dark-cyberpunk.json +102 -0
  719. package/src/modes/theme/defaults/dark-dracula.json +98 -0
  720. package/src/modes/theme/defaults/dark-eclipse.json +91 -0
  721. package/src/modes/theme/defaults/dark-ember.json +95 -0
  722. package/src/modes/theme/defaults/dark-equinox.json +90 -0
  723. package/src/modes/theme/defaults/dark-forest.json +96 -0
  724. package/src/modes/theme/defaults/dark-github.json +105 -0
  725. package/src/modes/theme/defaults/dark-gruvbox.json +112 -0
  726. package/src/modes/theme/defaults/dark-lavender.json +95 -0
  727. package/src/modes/theme/defaults/dark-lunar.json +89 -0
  728. package/src/modes/theme/defaults/dark-midnight.json +95 -0
  729. package/src/modes/theme/defaults/dark-monochrome.json +94 -0
  730. package/src/modes/theme/defaults/dark-monokai.json +98 -0
  731. package/src/modes/theme/defaults/dark-nebula.json +90 -0
  732. package/src/modes/theme/defaults/dark-nord.json +97 -0
  733. package/src/modes/theme/defaults/dark-ocean.json +101 -0
  734. package/src/modes/theme/defaults/dark-one.json +100 -0
  735. package/src/modes/theme/defaults/dark-poimandres.json +142 -0
  736. package/src/modes/theme/defaults/dark-rainforest.json +91 -0
  737. package/src/modes/theme/defaults/dark-reef.json +91 -0
  738. package/src/modes/theme/defaults/dark-retro.json +92 -0
  739. package/src/modes/theme/defaults/dark-rose-pine.json +96 -0
  740. package/src/modes/theme/defaults/dark-sakura.json +95 -0
  741. package/src/modes/theme/defaults/dark-slate.json +95 -0
  742. package/src/modes/theme/defaults/dark-solarized.json +97 -0
  743. package/src/modes/theme/defaults/dark-solstice.json +90 -0
  744. package/src/modes/theme/defaults/dark-starfall.json +91 -0
  745. package/src/modes/theme/defaults/dark-sunset.json +99 -0
  746. package/src/modes/theme/defaults/dark-swamp.json +90 -0
  747. package/src/modes/theme/defaults/dark-synthwave.json +103 -0
  748. package/src/modes/theme/defaults/dark-taiga.json +91 -0
  749. package/src/modes/theme/defaults/dark-terminal.json +95 -0
  750. package/src/modes/theme/defaults/dark-tokyo-night.json +101 -0
  751. package/src/modes/theme/defaults/dark-tundra.json +91 -0
  752. package/src/modes/theme/defaults/dark-twilight.json +91 -0
  753. package/src/modes/theme/defaults/dark-volcanic.json +91 -0
  754. package/src/modes/theme/defaults/graphite.json +92 -0
  755. package/src/modes/theme/defaults/index.ts +199 -0
  756. package/src/modes/theme/defaults/light-arctic.json +107 -0
  757. package/src/modes/theme/defaults/light-aurora-day.json +91 -0
  758. package/src/modes/theme/defaults/light-canyon.json +91 -0
  759. package/src/modes/theme/defaults/light-catppuccin.json +106 -0
  760. package/src/modes/theme/defaults/light-cirrus.json +90 -0
  761. package/src/modes/theme/defaults/light-coral.json +95 -0
  762. package/src/modes/theme/defaults/light-cyberpunk.json +96 -0
  763. package/src/modes/theme/defaults/light-dawn.json +90 -0
  764. package/src/modes/theme/defaults/light-dunes.json +91 -0
  765. package/src/modes/theme/defaults/light-eucalyptus.json +95 -0
  766. package/src/modes/theme/defaults/light-forest.json +100 -0
  767. package/src/modes/theme/defaults/light-frost.json +95 -0
  768. package/src/modes/theme/defaults/light-github.json +115 -0
  769. package/src/modes/theme/defaults/light-glacier.json +91 -0
  770. package/src/modes/theme/defaults/light-gruvbox.json +108 -0
  771. package/src/modes/theme/defaults/light-haze.json +90 -0
  772. package/src/modes/theme/defaults/light-honeycomb.json +95 -0
  773. package/src/modes/theme/defaults/light-lagoon.json +91 -0
  774. package/src/modes/theme/defaults/light-lavender.json +95 -0
  775. package/src/modes/theme/defaults/light-meadow.json +91 -0
  776. package/src/modes/theme/defaults/light-mint.json +95 -0
  777. package/src/modes/theme/defaults/light-monochrome.json +101 -0
  778. package/src/modes/theme/defaults/light-ocean.json +99 -0
  779. package/src/modes/theme/defaults/light-one.json +99 -0
  780. package/src/modes/theme/defaults/light-opal.json +91 -0
  781. package/src/modes/theme/defaults/light-orchard.json +91 -0
  782. package/src/modes/theme/defaults/light-paper.json +95 -0
  783. package/src/modes/theme/defaults/light-poimandres.json +142 -0
  784. package/src/modes/theme/defaults/light-prism.json +90 -0
  785. package/src/modes/theme/defaults/light-retro.json +98 -0
  786. package/src/modes/theme/defaults/light-sand.json +95 -0
  787. package/src/modes/theme/defaults/light-savanna.json +91 -0
  788. package/src/modes/theme/defaults/light-solarized.json +102 -0
  789. package/src/modes/theme/defaults/light-soleil.json +90 -0
  790. package/src/modes/theme/defaults/light-sunset.json +99 -0
  791. package/src/modes/theme/defaults/light-synthwave.json +98 -0
  792. package/src/modes/theme/defaults/light-tokyo-night.json +111 -0
  793. package/src/modes/theme/defaults/light-wetland.json +91 -0
  794. package/src/modes/theme/defaults/light-zenith.json +89 -0
  795. package/src/modes/theme/defaults/limestone.json +94 -0
  796. package/src/modes/theme/defaults/mahogany.json +97 -0
  797. package/src/modes/theme/defaults/marble.json +93 -0
  798. package/src/modes/theme/defaults/obsidian.json +91 -0
  799. package/src/modes/theme/defaults/onyx.json +91 -0
  800. package/src/modes/theme/defaults/pearl.json +93 -0
  801. package/src/modes/theme/defaults/porcelain.json +91 -0
  802. package/src/modes/theme/defaults/quartz.json +96 -0
  803. package/src/modes/theme/defaults/sandstone.json +95 -0
  804. package/src/modes/theme/defaults/titanium.json +90 -0
  805. package/src/modes/theme/light.json +93 -0
  806. package/src/modes/theme/mermaid-cache.ts +92 -0
  807. package/src/modes/theme/shimmer.ts +235 -0
  808. package/src/modes/theme/theme-schema.json +459 -0
  809. package/src/modes/theme/theme.ts +2915 -0
  810. package/src/modes/turn-budget.ts +31 -0
  811. package/src/modes/types.ts +406 -0
  812. package/src/modes/ultrathink.ts +41 -0
  813. package/src/modes/utils/context-usage.ts +432 -0
  814. package/src/modes/utils/copy-targets.ts +360 -0
  815. package/src/modes/utils/hotkeys-markdown.ts +62 -0
  816. package/src/modes/utils/keybinding-matchers.ts +51 -0
  817. package/src/modes/utils/tools-markdown.ts +27 -0
  818. package/src/modes/utils/ui-helpers.ts +886 -0
  819. package/src/modes/workflow.ts +42 -0
  820. package/src/plan-mode/approved-plan.ts +186 -0
  821. package/src/plan-mode/plan-handoff.ts +37 -0
  822. package/src/plan-mode/plan-protection.ts +31 -0
  823. package/src/plan-mode/state.ts +6 -0
  824. package/src/priority.json +45 -0
  825. package/src/prompts/advisor/advise-tool.md +3 -0
  826. package/src/prompts/advisor/system.md +113 -0
  827. package/src/prompts/agents/designer.md +74 -0
  828. package/src/prompts/agents/explore.md +58 -0
  829. package/src/prompts/agents/frontmatter.md +11 -0
  830. package/src/prompts/agents/init.md +33 -0
  831. package/src/prompts/agents/librarian.md +119 -0
  832. package/src/prompts/agents/oracle.md +54 -0
  833. package/src/prompts/agents/plan.md +48 -0
  834. package/src/prompts/agents/reviewer.md +139 -0
  835. package/src/prompts/agents/task.md +17 -0
  836. package/src/prompts/bench.md +12 -0
  837. package/src/prompts/ci-green-request.md +36 -0
  838. package/src/prompts/dry-balance-bench.md +8 -0
  839. package/src/prompts/goals/goal-budget-limit.md +16 -0
  840. package/src/prompts/goals/goal-continuation.md +28 -0
  841. package/src/prompts/goals/goal-mode-active.md +23 -0
  842. package/src/prompts/goals/guided-goal-interview.md +8 -0
  843. package/src/prompts/goals/guided-goal-system.md +12 -0
  844. package/src/prompts/low-end/system.md +47 -0
  845. package/src/prompts/memories/consolidation.md +30 -0
  846. package/src/prompts/memories/consolidation_system.md +4 -0
  847. package/src/prompts/memories/read-path.md +17 -0
  848. package/src/prompts/memories/stage_one_input.md +6 -0
  849. package/src/prompts/memories/stage_one_system.md +21 -0
  850. package/src/prompts/review-custom-request.md +22 -0
  851. package/src/prompts/review-headless-request.md +16 -0
  852. package/src/prompts/review-request.md +69 -0
  853. package/src/prompts/steering/user-interjection.md +9 -0
  854. package/src/prompts/system/agent-creation-architect.md +50 -0
  855. package/src/prompts/system/agent-creation-user.md +6 -0
  856. package/src/prompts/system/auto-continue.md +1 -0
  857. package/src/prompts/system/auto-thinking-difficulty-local.md +14 -0
  858. package/src/prompts/system/auto-thinking-difficulty.md +12 -0
  859. package/src/prompts/system/autolearn-guidance-learn.md +1 -0
  860. package/src/prompts/system/autolearn-guidance.md +7 -0
  861. package/src/prompts/system/autolearn-nudge.md +3 -0
  862. package/src/prompts/system/background-tan-dispatch.md +8 -0
  863. package/src/prompts/system/btw-user.md +8 -0
  864. package/src/prompts/system/commit-message-system.md +14 -0
  865. package/src/prompts/system/custom-system-prompt.md +64 -0
  866. package/src/prompts/system/eager-task.md +7 -0
  867. package/src/prompts/system/eager-todo.md +18 -0
  868. package/src/prompts/system/empty-stop-retry.md +4 -0
  869. package/src/prompts/system/irc-autoreply.md +6 -0
  870. package/src/prompts/system/irc-incoming.md +7 -0
  871. package/src/prompts/system/manual-continue.md +7 -0
  872. package/src/prompts/system/memory-consolidation-system.md +8 -0
  873. package/src/prompts/system/memory-extraction-system.md +26 -0
  874. package/src/prompts/system/omfg-user.md +50 -0
  875. package/src/prompts/system/orchestrate-notice.md +40 -0
  876. package/src/prompts/system/personalities/default.md +18 -0
  877. package/src/prompts/system/personalities/friendly.md +17 -0
  878. package/src/prompts/system/personalities/pragmatic.md +15 -0
  879. package/src/prompts/system/plan-mode-active.md +109 -0
  880. package/src/prompts/system/plan-mode-approved.md +25 -0
  881. package/src/prompts/system/plan-mode-compact-instructions.md +16 -0
  882. package/src/prompts/system/plan-mode-reference.md +11 -0
  883. package/src/prompts/system/plan-mode-subagent.md +33 -0
  884. package/src/prompts/system/plan-mode-tool-decision-reminder.md +9 -0
  885. package/src/prompts/system/project-prompt.md +52 -0
  886. package/src/prompts/system/snapcompact-context-frames-note.md +1 -0
  887. package/src/prompts/system/snapcompact-context-stub.md +1 -0
  888. package/src/prompts/system/snapcompact-system-frames-note.md +1 -0
  889. package/src/prompts/system/snapcompact-system-stub.md +1 -0
  890. package/src/prompts/system/snapcompact-toolresult-note.md +1 -0
  891. package/src/prompts/system/subagent-system-prompt.md +71 -0
  892. package/src/prompts/system/subagent-user-prompt.md +3 -0
  893. package/src/prompts/system/subagent-yield-reminder.md +12 -0
  894. package/src/prompts/system/system-prompt.md +251 -0
  895. package/src/prompts/system/tiny-title-system.md +8 -0
  896. package/src/prompts/system/title-marker-instruction.md +1 -0
  897. package/src/prompts/system/title-system-marker.md +16 -0
  898. package/src/prompts/system/title-system.md +16 -0
  899. package/src/prompts/system/ttsr-interrupt.md +7 -0
  900. package/src/prompts/system/ttsr-tool-reminder.md +5 -0
  901. package/src/prompts/system/ultrathink-notice.md +3 -0
  902. package/src/prompts/system/unexpected-stop-classifier.md +17 -0
  903. package/src/prompts/system/unexpected-stop-retry.md +4 -0
  904. package/src/prompts/system/web-search.md +25 -0
  905. package/src/prompts/system/workflow-notice.md +70 -0
  906. package/src/prompts/tools/apply-patch.md +65 -0
  907. package/src/prompts/tools/ask.md +22 -0
  908. package/src/prompts/tools/ast-edit.md +22 -0
  909. package/src/prompts/tools/ast-grep.md +25 -0
  910. package/src/prompts/tools/async-result.md +8 -0
  911. package/src/prompts/tools/bash.md +45 -0
  912. package/src/prompts/tools/browser.md +42 -0
  913. package/src/prompts/tools/checkpoint.md +15 -0
  914. package/src/prompts/tools/debug.md +17 -0
  915. package/src/prompts/tools/eval.md +70 -0
  916. package/src/prompts/tools/find.md +19 -0
  917. package/src/prompts/tools/github.md +17 -0
  918. package/src/prompts/tools/goal.md +11 -0
  919. package/src/prompts/tools/image-attachment-describe-system.md +8 -0
  920. package/src/prompts/tools/image-attachment-describe.md +10 -0
  921. package/src/prompts/tools/image-gen.md +7 -0
  922. package/src/prompts/tools/inspect-image-system.md +20 -0
  923. package/src/prompts/tools/inspect-image.md +22 -0
  924. package/src/prompts/tools/irc.md +33 -0
  925. package/src/prompts/tools/job.md +17 -0
  926. package/src/prompts/tools/learn.md +7 -0
  927. package/src/prompts/tools/lsp-late-diagnostic.md +8 -0
  928. package/src/prompts/tools/lsp.md +39 -0
  929. package/src/prompts/tools/manage-skill.md +9 -0
  930. package/src/prompts/tools/memory-edit.md +8 -0
  931. package/src/prompts/tools/patch.md +57 -0
  932. package/src/prompts/tools/read.md +76 -0
  933. package/src/prompts/tools/recall.md +5 -0
  934. package/src/prompts/tools/reflect.md +5 -0
  935. package/src/prompts/tools/replace.md +29 -0
  936. package/src/prompts/tools/resolve.md +4 -0
  937. package/src/prompts/tools/retain.md +6 -0
  938. package/src/prompts/tools/rewind.md +13 -0
  939. package/src/prompts/tools/search-tool-bm25.md +32 -0
  940. package/src/prompts/tools/search.md +22 -0
  941. package/src/prompts/tools/ssh.md +22 -0
  942. package/src/prompts/tools/task-summary.md +17 -0
  943. package/src/prompts/tools/task.md +91 -0
  944. package/src/prompts/tools/todo.md +39 -0
  945. package/src/prompts/tools/web-search.md +6 -0
  946. package/src/prompts/tools/write.md +14 -0
  947. package/src/registry/agent-lifecycle.ts +270 -0
  948. package/src/registry/agent-registry.ts +190 -0
  949. package/src/sdk.ts +2919 -0
  950. package/src/secrets/index.ts +123 -0
  951. package/src/secrets/obfuscator.ts +298 -0
  952. package/src/secrets/regex.ts +21 -0
  953. package/src/session/agent-session.ts +12539 -0
  954. package/src/session/agent-storage.ts +478 -0
  955. package/src/session/artifacts.ts +153 -0
  956. package/src/session/auth-broker-config.ts +92 -0
  957. package/src/session/auth-storage.ts +24 -0
  958. package/src/session/blob-store.ts +255 -0
  959. package/src/session/client-bridge.ts +85 -0
  960. package/src/session/codex-auto-reset.ts +202 -0
  961. package/src/session/compact-modes.ts +105 -0
  962. package/src/session/history-storage.ts +361 -0
  963. package/src/session/indexed-session-storage.ts +427 -0
  964. package/src/session/messages.ts +546 -0
  965. package/src/session/redis-session-storage.ts +170 -0
  966. package/src/session/session-context.ts +399 -0
  967. package/src/session/session-dump-format.ts +216 -0
  968. package/src/session/session-entries.ts +198 -0
  969. package/src/session/session-history-format.ts +308 -0
  970. package/src/session/session-listing.ts +588 -0
  971. package/src/session/session-loader.ts +93 -0
  972. package/src/session/session-manager.ts +1748 -0
  973. package/src/session/session-migrations.ts +78 -0
  974. package/src/session/session-paths.ts +193 -0
  975. package/src/session/session-persistence.ts +147 -0
  976. package/src/session/session-storage.ts +590 -0
  977. package/src/session/shake-types.ts +43 -0
  978. package/src/session/snapcompact-inline.ts +542 -0
  979. package/src/session/snapcompact-savings-journal.ts +113 -0
  980. package/src/session/sql-session-storage.ts +314 -0
  981. package/src/session/streaming-output.ts +1330 -0
  982. package/src/session/tool-choice-queue.ts +290 -0
  983. package/src/session/unexpected-stop-classifier.ts +129 -0
  984. package/src/session/yield-queue.ts +183 -0
  985. package/src/slash-commands/acp-builtins.ts +70 -0
  986. package/src/slash-commands/available-commands.ts +105 -0
  987. package/src/slash-commands/builtin-registry.ts +2332 -0
  988. package/src/slash-commands/helpers/active-oauth-account.ts +44 -0
  989. package/src/slash-commands/helpers/collab-qrcode.ts +28 -0
  990. package/src/slash-commands/helpers/context-report.ts +66 -0
  991. package/src/slash-commands/helpers/format.ts +46 -0
  992. package/src/slash-commands/helpers/logout.ts +88 -0
  993. package/src/slash-commands/helpers/marketplace-manager.ts +25 -0
  994. package/src/slash-commands/helpers/mcp.ts +532 -0
  995. package/src/slash-commands/helpers/parse.ts +85 -0
  996. package/src/slash-commands/helpers/reset-usage.ts +66 -0
  997. package/src/slash-commands/helpers/ssh.ts +195 -0
  998. package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
  999. package/src/slash-commands/helpers/todo.ts +279 -0
  1000. package/src/slash-commands/helpers/usage-report.ts +128 -0
  1001. package/src/slash-commands/marketplace-install-parser.ts +99 -0
  1002. package/src/slash-commands/types.ts +135 -0
  1003. package/src/ssh/config-writer.ts +183 -0
  1004. package/src/ssh/connection-manager.ts +510 -0
  1005. package/src/ssh/ssh-executor.ts +189 -0
  1006. package/src/ssh/sshfs-mount.ts +140 -0
  1007. package/src/ssh/utils.ts +8 -0
  1008. package/src/startup-splash.ts +19 -0
  1009. package/src/stt/asr-client.ts +521 -0
  1010. package/src/stt/asr-protocol.ts +65 -0
  1011. package/src/stt/asr-worker.ts +790 -0
  1012. package/src/stt/downloader.ts +138 -0
  1013. package/src/stt/endpointer.ts +259 -0
  1014. package/src/stt/index.ts +7 -0
  1015. package/src/stt/models.ts +150 -0
  1016. package/src/stt/recorder.ts +538 -0
  1017. package/src/stt/stt-controller.ts +380 -0
  1018. package/src/stt/transcriber.ts +60 -0
  1019. package/src/stt/wav.ts +173 -0
  1020. package/src/system-prompt.ts +709 -0
  1021. package/src/task/agents.ts +166 -0
  1022. package/src/task/commands.ts +132 -0
  1023. package/src/task/discovery.ts +122 -0
  1024. package/src/task/executor.ts +2356 -0
  1025. package/src/task/index.ts +1580 -0
  1026. package/src/task/name-generator.ts +1577 -0
  1027. package/src/task/omp-command.ts +26 -0
  1028. package/src/task/output-manager.ts +93 -0
  1029. package/src/task/parallel.ts +116 -0
  1030. package/src/task/persisted-revive.ts +128 -0
  1031. package/src/task/render.ts +1558 -0
  1032. package/src/task/repair-args.ts +129 -0
  1033. package/src/task/subprocess-tool-registry.ts +88 -0
  1034. package/src/task/types.ts +401 -0
  1035. package/src/task/worktree.ts +514 -0
  1036. package/src/telemetry-export.ts +144 -0
  1037. package/src/thinking.ts +187 -0
  1038. package/src/tiny/device.ts +111 -0
  1039. package/src/tiny/dtype.ts +101 -0
  1040. package/src/tiny/models.ts +252 -0
  1041. package/src/tiny/text.ts +169 -0
  1042. package/src/tiny/title-client.ts +538 -0
  1043. package/src/tiny/title-protocol.ts +56 -0
  1044. package/src/tiny/worker.ts +491 -0
  1045. package/src/tool-discovery/mode.ts +24 -0
  1046. package/src/tool-discovery/tool-index.ts +271 -0
  1047. package/src/tools/__tests__/json-tree.test.ts +35 -0
  1048. package/src/tools/approval.ts +189 -0
  1049. package/src/tools/ask.ts +977 -0
  1050. package/src/tools/ast-edit.ts +700 -0
  1051. package/src/tools/ast-grep.ts +483 -0
  1052. package/src/tools/auto-generated-guard.ts +322 -0
  1053. package/src/tools/bash-command-fixup.ts +37 -0
  1054. package/src/tools/bash-interactive.ts +408 -0
  1055. package/src/tools/bash-interceptor.ts +67 -0
  1056. package/src/tools/bash-pty-selection.ts +14 -0
  1057. package/src/tools/bash-skill-urls.ts +248 -0
  1058. package/src/tools/bash.ts +1405 -0
  1059. package/src/tools/browser/attach.ts +194 -0
  1060. package/src/tools/browser/cmux/cmux-tab.ts +1264 -0
  1061. package/src/tools/browser/cmux/rpc.ts +156 -0
  1062. package/src/tools/browser/cmux/socket-client.ts +309 -0
  1063. package/src/tools/browser/launch.ts +673 -0
  1064. package/src/tools/browser/readable.ts +112 -0
  1065. package/src/tools/browser/registry.ts +241 -0
  1066. package/src/tools/browser/render.ts +221 -0
  1067. package/src/tools/browser/tab-protocol.ts +107 -0
  1068. package/src/tools/browser/tab-supervisor.ts +799 -0
  1069. package/src/tools/browser/tab-worker-entry.ts +29 -0
  1070. package/src/tools/browser/tab-worker.ts +1226 -0
  1071. package/src/tools/browser.ts +403 -0
  1072. package/src/tools/builtin-names.ts +34 -0
  1073. package/src/tools/checkpoint.ts +136 -0
  1074. package/src/tools/conflict-detect.ts +718 -0
  1075. package/src/tools/context.ts +39 -0
  1076. package/src/tools/debug.ts +1087 -0
  1077. package/src/tools/eval-backends.ts +27 -0
  1078. package/src/tools/eval-render.ts +762 -0
  1079. package/src/tools/eval.ts +600 -0
  1080. package/src/tools/fetch.ts +1902 -0
  1081. package/src/tools/file-recorder.ts +35 -0
  1082. package/src/tools/find.ts +629 -0
  1083. package/src/tools/fs-cache-invalidation.ts +28 -0
  1084. package/src/tools/gh-cache-invalidation.ts +255 -0
  1085. package/src/tools/gh-format.ts +12 -0
  1086. package/src/tools/gh-renderer.ts +481 -0
  1087. package/src/tools/gh.ts +3752 -0
  1088. package/src/tools/github-cache.ts +663 -0
  1089. package/src/tools/grouped-file-output.ts +210 -0
  1090. package/src/tools/image-gen.ts +1586 -0
  1091. package/src/tools/index.ts +649 -0
  1092. package/src/tools/inspect-image-renderer.ts +132 -0
  1093. package/src/tools/inspect-image.ts +260 -0
  1094. package/src/tools/irc.ts +788 -0
  1095. package/src/tools/job.ts +612 -0
  1096. package/src/tools/json-tree.ts +260 -0
  1097. package/src/tools/jtd-to-json-schema.ts +219 -0
  1098. package/src/tools/jtd-to-typescript.ts +136 -0
  1099. package/src/tools/jtd-utils.ts +102 -0
  1100. package/src/tools/learn.ts +141 -0
  1101. package/src/tools/list-limit.ts +40 -0
  1102. package/src/tools/manage-skill.ts +100 -0
  1103. package/src/tools/match-line-format.ts +20 -0
  1104. package/src/tools/memory-edit.ts +59 -0
  1105. package/src/tools/memory-recall.ts +102 -0
  1106. package/src/tools/memory-reflect.ts +88 -0
  1107. package/src/tools/memory-render.ts +202 -0
  1108. package/src/tools/memory-retain.ts +89 -0
  1109. package/src/tools/output-meta.ts +768 -0
  1110. package/src/tools/output-schema-validator.ts +132 -0
  1111. package/src/tools/path-utils.ts +1116 -0
  1112. package/src/tools/plan-mode-guard.ts +142 -0
  1113. package/src/tools/puppeteer/00_stealth_tampering.txt +63 -0
  1114. package/src/tools/puppeteer/01_stealth_activity.txt +20 -0
  1115. package/src/tools/puppeteer/02_stealth_hairline.txt +11 -0
  1116. package/src/tools/puppeteer/03_stealth_botd.txt +384 -0
  1117. package/src/tools/puppeteer/04_stealth_iframe.txt +81 -0
  1118. package/src/tools/puppeteer/05_stealth_webgl.txt +75 -0
  1119. package/src/tools/puppeteer/06_stealth_screen.txt +72 -0
  1120. package/src/tools/puppeteer/07_stealth_fonts.txt +97 -0
  1121. package/src/tools/puppeteer/08_stealth_audio.txt +51 -0
  1122. package/src/tools/puppeteer/09_stealth_locale.txt +46 -0
  1123. package/src/tools/puppeteer/10_stealth_plugins.txt +208 -0
  1124. package/src/tools/puppeteer/11_stealth_hardware.txt +8 -0
  1125. package/src/tools/puppeteer/12_stealth_codecs.txt +40 -0
  1126. package/src/tools/puppeteer/13_stealth_worker.txt +74 -0
  1127. package/src/tools/read.ts +3124 -0
  1128. package/src/tools/render-utils.ts +895 -0
  1129. package/src/tools/renderers.ts +86 -0
  1130. package/src/tools/report-tool-issue.ts +530 -0
  1131. package/src/tools/resolve.ts +302 -0
  1132. package/src/tools/review.ts +251 -0
  1133. package/src/tools/search-tool-bm25.ts +351 -0
  1134. package/src/tools/search.ts +1583 -0
  1135. package/src/tools/sqlite-reader.ts +828 -0
  1136. package/src/tools/ssh.ts +369 -0
  1137. package/src/tools/todo.ts +938 -0
  1138. package/src/tools/tool-errors.ts +62 -0
  1139. package/src/tools/tool-result.ts +102 -0
  1140. package/src/tools/tool-timeouts.ts +30 -0
  1141. package/src/tools/tts.ts +265 -0
  1142. package/src/tools/write.ts +1182 -0
  1143. package/src/tools/yield.ts +269 -0
  1144. package/src/tts/downloader.ts +64 -0
  1145. package/src/tts/index.ts +8 -0
  1146. package/src/tts/models.ts +137 -0
  1147. package/src/tts/player.ts +137 -0
  1148. package/src/tts/runtime.ts +21 -0
  1149. package/src/tts/streaming-player.ts +266 -0
  1150. package/src/tts/tts-client.ts +642 -0
  1151. package/src/tts/tts-protocol.ts +60 -0
  1152. package/src/tts/tts-worker.ts +505 -0
  1153. package/src/tts/vocalizer.ts +162 -0
  1154. package/src/tts/wav.ts +58 -0
  1155. package/src/tui/code-cell.ts +257 -0
  1156. package/src/tui/file-list.ts +55 -0
  1157. package/src/tui/hyperlink.ts +178 -0
  1158. package/src/tui/index.ts +13 -0
  1159. package/src/tui/output-block.ts +240 -0
  1160. package/src/tui/status-line.ts +54 -0
  1161. package/src/tui/tree-list.ts +133 -0
  1162. package/src/tui/types.ts +15 -0
  1163. package/src/tui/utils.ts +103 -0
  1164. package/src/tui/width-aware-text.ts +58 -0
  1165. package/src/utils/block-context.ts +312 -0
  1166. package/src/utils/changelog.ts +132 -0
  1167. package/src/utils/clipboard.ts +262 -0
  1168. package/src/utils/command-args.ts +76 -0
  1169. package/src/utils/commit-message-generator.ts +147 -0
  1170. package/src/utils/edit-mode.ts +41 -0
  1171. package/src/utils/enhanced-paste.ts +230 -0
  1172. package/src/utils/event-bus.ts +33 -0
  1173. package/src/utils/external-editor.ts +78 -0
  1174. package/src/utils/file-display-mode.ts +45 -0
  1175. package/src/utils/file-mentions.ts +284 -0
  1176. package/src/utils/git.ts +1838 -0
  1177. package/src/utils/image-loading.ts +231 -0
  1178. package/src/utils/image-resize.ts +309 -0
  1179. package/src/utils/image-vision-fallback.ts +197 -0
  1180. package/src/utils/ipc.ts +38 -0
  1181. package/src/utils/jj.ts +248 -0
  1182. package/src/utils/lang-from-path.ts +244 -0
  1183. package/src/utils/markit.ts +143 -0
  1184. package/src/utils/mupdf-wasm-embed.ts +12 -0
  1185. package/src/utils/open.ts +55 -0
  1186. package/src/utils/qrcode.ts +535 -0
  1187. package/src/utils/session-color.ts +142 -0
  1188. package/src/utils/shell-snapshot.ts +187 -0
  1189. package/src/utils/sixel.ts +69 -0
  1190. package/src/utils/thinking-display.ts +11 -0
  1191. package/src/utils/title-generator.ts +416 -0
  1192. package/src/utils/tool-choice.ts +49 -0
  1193. package/src/utils/tools-manager.ts +372 -0
  1194. package/src/utils/turndown.ts +83 -0
  1195. package/src/utils/zip.ts +1091 -0
  1196. package/src/web/kagi.ts +304 -0
  1197. package/src/web/parallel.ts +353 -0
  1198. package/src/web/scrapers/artifacthub.ts +207 -0
  1199. package/src/web/scrapers/arxiv.ts +83 -0
  1200. package/src/web/scrapers/aur.ts +162 -0
  1201. package/src/web/scrapers/biorxiv.ts +133 -0
  1202. package/src/web/scrapers/bluesky.ts +262 -0
  1203. package/src/web/scrapers/brew.ts +172 -0
  1204. package/src/web/scrapers/cheatsh.ts +68 -0
  1205. package/src/web/scrapers/chocolatey.ts +196 -0
  1206. package/src/web/scrapers/choosealicense.ts +95 -0
  1207. package/src/web/scrapers/cisa-kev.ts +87 -0
  1208. package/src/web/scrapers/clojars.ts +154 -0
  1209. package/src/web/scrapers/coingecko.ts +177 -0
  1210. package/src/web/scrapers/crates-io.ts +97 -0
  1211. package/src/web/scrapers/crossref.ts +136 -0
  1212. package/src/web/scrapers/devto.ts +147 -0
  1213. package/src/web/scrapers/discogs.ts +306 -0
  1214. package/src/web/scrapers/discourse.ts +197 -0
  1215. package/src/web/scrapers/dockerhub.ts +138 -0
  1216. package/src/web/scrapers/docs-rs.ts +652 -0
  1217. package/src/web/scrapers/fdroid.ts +134 -0
  1218. package/src/web/scrapers/firefox-addons.ts +191 -0
  1219. package/src/web/scrapers/flathub.ts +223 -0
  1220. package/src/web/scrapers/github-gist.ts +58 -0
  1221. package/src/web/scrapers/github.ts +800 -0
  1222. package/src/web/scrapers/gitlab.ts +401 -0
  1223. package/src/web/scrapers/go-pkg.ts +266 -0
  1224. package/src/web/scrapers/hackage.ts +140 -0
  1225. package/src/web/scrapers/hackernews.ts +189 -0
  1226. package/src/web/scrapers/hex.ts +105 -0
  1227. package/src/web/scrapers/huggingface.ts +321 -0
  1228. package/src/web/scrapers/iacr.ts +89 -0
  1229. package/src/web/scrapers/index.ts +252 -0
  1230. package/src/web/scrapers/jetbrains-marketplace.ts +159 -0
  1231. package/src/web/scrapers/lemmy.ts +203 -0
  1232. package/src/web/scrapers/lobsters.ts +175 -0
  1233. package/src/web/scrapers/mastodon.ts +292 -0
  1234. package/src/web/scrapers/maven.ts +138 -0
  1235. package/src/web/scrapers/mdn.ts +173 -0
  1236. package/src/web/scrapers/metacpan.ts +222 -0
  1237. package/src/web/scrapers/musicbrainz.ts +250 -0
  1238. package/src/web/scrapers/npm.ts +98 -0
  1239. package/src/web/scrapers/nuget.ts +183 -0
  1240. package/src/web/scrapers/nvd.ts +222 -0
  1241. package/src/web/scrapers/ollama.ts +239 -0
  1242. package/src/web/scrapers/open-vsx.ts +106 -0
  1243. package/src/web/scrapers/opencorporates.ts +292 -0
  1244. package/src/web/scrapers/openlibrary.ts +336 -0
  1245. package/src/web/scrapers/orcid.ts +286 -0
  1246. package/src/web/scrapers/osv.ts +176 -0
  1247. package/src/web/scrapers/packagist.ts +160 -0
  1248. package/src/web/scrapers/pub-dev.ts +143 -0
  1249. package/src/web/scrapers/pubmed.ts +211 -0
  1250. package/src/web/scrapers/pypi.ts +112 -0
  1251. package/src/web/scrapers/rawg.ts +110 -0
  1252. package/src/web/scrapers/readthedocs.ts +120 -0
  1253. package/src/web/scrapers/reddit.ts +95 -0
  1254. package/src/web/scrapers/repology.ts +251 -0
  1255. package/src/web/scrapers/rfc.ts +201 -0
  1256. package/src/web/scrapers/rubygems.ts +103 -0
  1257. package/src/web/scrapers/searchcode.ts +189 -0
  1258. package/src/web/scrapers/sec-edgar.ts +261 -0
  1259. package/src/web/scrapers/semantic-scholar.ts +171 -0
  1260. package/src/web/scrapers/snapcraft.ts +187 -0
  1261. package/src/web/scrapers/sourcegraph.ts +336 -0
  1262. package/src/web/scrapers/spdx.ts +108 -0
  1263. package/src/web/scrapers/spotify.ts +198 -0
  1264. package/src/web/scrapers/stackoverflow.ts +120 -0
  1265. package/src/web/scrapers/terraform.ts +277 -0
  1266. package/src/web/scrapers/tldr.ts +47 -0
  1267. package/src/web/scrapers/twitter.ts +94 -0
  1268. package/src/web/scrapers/types.ts +354 -0
  1269. package/src/web/scrapers/utils.ts +109 -0
  1270. package/src/web/scrapers/vimeo.ts +133 -0
  1271. package/src/web/scrapers/vscode-marketplace.ts +187 -0
  1272. package/src/web/scrapers/w3c.ts +156 -0
  1273. package/src/web/scrapers/wikidata.ts +344 -0
  1274. package/src/web/scrapers/wikipedia.ts +84 -0
  1275. package/src/web/scrapers/youtube.ts +325 -0
  1276. package/src/web/search/index.ts +317 -0
  1277. package/src/web/search/provider.ts +169 -0
  1278. package/src/web/search/providers/anthropic.ts +343 -0
  1279. package/src/web/search/providers/base.ts +90 -0
  1280. package/src/web/search/providers/brave.ts +152 -0
  1281. package/src/web/search/providers/codex.ts +593 -0
  1282. package/src/web/search/providers/exa.ts +400 -0
  1283. package/src/web/search/providers/gemini.ts +518 -0
  1284. package/src/web/search/providers/jina.ts +111 -0
  1285. package/src/web/search/providers/kagi.ts +86 -0
  1286. package/src/web/search/providers/kimi.ts +196 -0
  1287. package/src/web/search/providers/parallel.ts +225 -0
  1288. package/src/web/search/providers/perplexity-auth.ts +133 -0
  1289. package/src/web/search/providers/perplexity.ts +866 -0
  1290. package/src/web/search/providers/searxng.ts +325 -0
  1291. package/src/web/search/providers/synthetic.ts +114 -0
  1292. package/src/web/search/providers/tavily.ts +176 -0
  1293. package/src/web/search/providers/utils.ts +128 -0
  1294. package/src/web/search/providers/zai.ts +333 -0
  1295. package/src/web/search/render.ts +262 -0
  1296. package/src/web/search/types.ts +462 -0
  1297. package/src/web/search/utils.ts +17 -0
  1298. package/src/workspace-tree.ts +326 -0
@@ -0,0 +1,1580 @@
1
+ /**
2
+ * Task tool - Delegate tasks to specialized agents.
3
+ *
4
+ * Discovers agent definitions from:
5
+ * - Bundled agents (shipped with omp-coding-agent)
6
+ * - ~/.omp/agent/agents/*.md (user-level)
7
+ * - .omp/agents/*.md (project-level)
8
+ *
9
+ * Supports:
10
+ * - Single agent spawn per call (parallelism = parallel task calls)
11
+ * - Batch spawning + shared context per call when `task.batch` is enabled
12
+ * - Background execution through AsyncJobManager when `async.enabled` is enabled
13
+ * - Progress tracking via JSON events
14
+ * - Session artifacts for debugging
15
+ */
16
+ import * as fs from "node:fs/promises";
17
+ import * as os from "node:os";
18
+ import path from "node:path";
19
+ import type { AgentTool, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
20
+ import type { Usage } from "@oh-my-pi/pi-ai";
21
+ import { $env, logger, prompt, Snowflake } from "@oh-my-pi/pi-utils";
22
+ import type { ToolSession } from "..";
23
+ import { resolveAgentModelPatterns } from "../config/model-resolver";
24
+ import { MCPManager } from "../mcp/manager";
25
+ import type { Theme } from "../modes/theme/theme";
26
+ import planModeSubagentPrompt from "../prompts/system/plan-mode-subagent.md" with { type: "text" };
27
+ import subagentUserPromptTemplate from "../prompts/system/subagent-user-prompt.md" with { type: "text" };
28
+ import taskDescriptionTemplate from "../prompts/tools/task.md" with { type: "text" };
29
+ import taskSummaryTemplate from "../prompts/tools/task-summary.md" with { type: "text" };
30
+ import { truncateForPrompt } from "../tools/approval";
31
+ import { isIrcEnabled } from "../tools/irc";
32
+ import { formatBytes, formatDuration } from "../tools/render-utils";
33
+ import {
34
+ type AgentDefinition,
35
+ type AgentProgress,
36
+ canSpawnAtDepth,
37
+ getTaskSchema,
38
+ type SingleResult,
39
+ type TaskItem,
40
+ type TaskParams,
41
+ type TaskToolDetails,
42
+ type TaskToolSchemaInstance,
43
+ } from "./types";
44
+ // Import review tools for side effects (registers subagent tool handlers)
45
+ import "../tools/review";
46
+ import type { AsyncJobManager } from "../async";
47
+ import type { LocalProtocolOptions } from "../internal-urls";
48
+ import { loadOverallPlanReference } from "../plan-mode/plan-handoff";
49
+ import { AgentRegistry, MAIN_AGENT_ID } from "../registry/agent-registry";
50
+ import { generateCommitMessage } from "../utils/commit-message-generator";
51
+ import * as git from "../utils/git";
52
+ import { type DiscoveryResult, discoverAgents, getAgent } from "./discovery";
53
+ import { runSubprocess } from "./executor";
54
+ import { generateTaskName } from "./name-generator";
55
+ import { AgentOutputManager } from "./output-manager";
56
+ import { mapWithConcurrencyLimit, Semaphore } from "./parallel";
57
+ import { renderResult, renderCall as renderTaskCall } from "./render";
58
+ import { repairTaskParams } from "./repair-args";
59
+ import {
60
+ applyNestedPatches,
61
+ captureBaseline,
62
+ captureDeltaPatch,
63
+ cleanupIsolation,
64
+ cleanupTaskBranches,
65
+ commitToBranch,
66
+ ensureIsolation,
67
+ getRepoRoot,
68
+ type IsolationHandle,
69
+ mergeTaskBranches,
70
+ parseIsolationMode,
71
+ type WorktreeBaseline,
72
+ } from "./worktree";
73
+
74
+ function renderSubagentUserPrompt(assignment: string): string {
75
+ return prompt.render(subagentUserPromptTemplate, {
76
+ assignment: assignment.trim(),
77
+ });
78
+ }
79
+
80
+ function createUsageTotals(): Usage {
81
+ return {
82
+ input: 0,
83
+ output: 0,
84
+ cacheRead: 0,
85
+ cacheWrite: 0,
86
+ totalTokens: 0,
87
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
88
+ };
89
+ }
90
+
91
+ function addUsageTotals(target: Usage, usage: Partial<Usage>): void {
92
+ const input = usage.input ?? 0;
93
+ const output = usage.output ?? 0;
94
+ const cacheRead = usage.cacheRead ?? 0;
95
+ const cacheWrite = usage.cacheWrite ?? 0;
96
+ const totalTokens = usage.totalTokens ?? input + output + cacheRead + cacheWrite;
97
+ const cost =
98
+ usage.cost ??
99
+ ({
100
+ input: 0,
101
+ output: 0,
102
+ cacheRead: 0,
103
+ cacheWrite: 0,
104
+ total: 0,
105
+ } satisfies Usage["cost"]);
106
+
107
+ target.input += input;
108
+ target.output += output;
109
+ target.cacheRead += cacheRead;
110
+ target.cacheWrite += cacheWrite;
111
+ target.totalTokens += totalTokens;
112
+ target.cost.input += cost.input;
113
+ target.cost.output += cost.output;
114
+ target.cost.cacheRead += cost.cacheRead;
115
+ target.cost.cacheWrite += cost.cacheWrite;
116
+ target.cost.total += cost.total;
117
+ }
118
+
119
+ // Re-export types and utilities
120
+ export { loadBundledAgents as BUNDLED_AGENTS } from "./agents";
121
+ export { discoverCommands, expandCommand, getCommand } from "./commands";
122
+ export { discoverAgents, getAgent } from "./discovery";
123
+ export { AgentOutputManager } from "./output-manager";
124
+ export type {
125
+ AgentDefinition,
126
+ AgentProgress,
127
+ SingleResult,
128
+ SubagentEventPayload,
129
+ SubagentLifecyclePayload,
130
+ SubagentProgressPayload,
131
+ TaskParams,
132
+ TaskToolDetails,
133
+ } from "./types";
134
+ export {
135
+ TASK_SUBAGENT_EVENT_CHANNEL,
136
+ TASK_SUBAGENT_LIFECYCLE_CHANNEL,
137
+ TASK_SUBAGENT_PROGRESS_CHANNEL,
138
+ taskSchema,
139
+ } from "./types";
140
+
141
+ // Built-in tools whose approval tier is "read" (see tool classes' `approval`).
142
+ // An agent is read-only iff its declared tools are a non-empty subset of this set.
143
+ // Fail-safe: any unknown tool makes the agent not read-only.
144
+ export const READ_ONLY_TOOL_NAMES: ReadonlySet<string> = new Set([
145
+ "read",
146
+ "search",
147
+ "find",
148
+ "web_search",
149
+ "ast_grep",
150
+ "yield",
151
+ "irc",
152
+ "ask",
153
+ "job",
154
+ "todo",
155
+ "recall",
156
+ "reflect",
157
+ "retain",
158
+ "memory_edit",
159
+ "inspect_image",
160
+ "checkpoint",
161
+ "rewind",
162
+ "resolve",
163
+ "report_finding",
164
+ "search_tool_bm25",
165
+ ]);
166
+
167
+ const PLAN_MODE_AGENT_TOOL_ALLOWLIST: ReadonlySet<string> = new Set(["ast_grep", "report_finding"]);
168
+
169
+ export function isReadOnlyAgent(agent: AgentDefinition): boolean {
170
+ return !!agent.tools?.length && agent.tools.every(tool => READ_ONLY_TOOL_NAMES.has(tool));
171
+ }
172
+
173
+ /**
174
+ * Preview text for a child result. Falls back to "(no output)" — annotated
175
+ * with the request count when the child actually did work, so the parent can
176
+ * tell a no-op child from one that burned requests before being cancelled.
177
+ */
178
+ export function formatResultOutputFallback(result: Pick<SingleResult, "output" | "stderr" | "requests">): string {
179
+ const base = result.output.trim() || result.stderr.trim();
180
+ if (base) return base;
181
+ return result.requests > 0 ? `(no output) after ${result.requests} req` : "(no output)";
182
+ }
183
+
184
+ /**
185
+ * Render the tool description from a cached agent list and current settings.
186
+ */
187
+ function renderDescription(
188
+ agents: AgentDefinition[],
189
+ maxConcurrency: number,
190
+ isolationEnabled: boolean,
191
+ disabledAgents: string[],
192
+ batchEnabled: boolean,
193
+ asyncEnabled: boolean,
194
+ ircEnabled: boolean,
195
+ parentSpawns: string,
196
+ ): string {
197
+ const spawningDisabled = parentSpawns === "";
198
+ let filteredAgents = disabledAgents.length > 0 ? agents.filter(a => !disabledAgents.includes(a.name)) : agents;
199
+ if (spawningDisabled) {
200
+ filteredAgents = [];
201
+ } else if (parentSpawns !== "*") {
202
+ const allowed = new Set(
203
+ parentSpawns
204
+ .split(",")
205
+ .map(s => s.trim())
206
+ .filter(Boolean),
207
+ );
208
+ filteredAgents = filteredAgents.filter(a => allowed.has(a.name));
209
+ }
210
+ const renderedAgents = filteredAgents.map(agent => ({
211
+ name: agent.name,
212
+ description: agent.description,
213
+ readOnly: isReadOnlyAgent(agent),
214
+ }));
215
+ return prompt.render(taskDescriptionTemplate, {
216
+ agents: renderedAgents,
217
+ spawningDisabled,
218
+ MAX_CONCURRENCY: maxConcurrency,
219
+ isolationEnabled,
220
+ batchEnabled,
221
+ asyncEnabled,
222
+ ircEnabled,
223
+ });
224
+ }
225
+
226
+ function createTaskModeError(text: string): AgentToolResult<TaskToolDetails> {
227
+ return {
228
+ content: [{ type: "text", text }],
229
+ details: { projectAgentsDir: null, results: [], totalDurationMs: 0 },
230
+ };
231
+ }
232
+
233
+ /**
234
+ * Reject fields the current configuration does not accept. `schema` is never
235
+ * accepted (structured output comes from the agent definition's `output`
236
+ * frontmatter, the inherited session schema, or an eval-workflow
237
+ * `agent(..., schema)` call); `tasks`/`context` require `task.batch`.
238
+ */
239
+ function validateShapeParams(batchEnabled: boolean, params: TaskParams): string | undefined {
240
+ if ((params as Record<string, unknown>).schema !== undefined) {
241
+ return "The task tool does not accept `schema`. Rely on the selected agent definition's `output` schema or the inherited session schema; workflows needing ad-hoc structured output use eval `agent(prompt, schema)`.";
242
+ }
243
+ if (!batchEnabled) {
244
+ const disallowed = (["tasks", "context"] as const).filter(field => params[field] !== undefined);
245
+ if (disallowed.length > 0) {
246
+ return `task.batch is disabled, so the task tool does not accept ${disallowed.map(f => `\`${f}\``).join(" or ")}. Spawn one agent per call with \`assignment\`, or enable the task.batch setting.`;
247
+ }
248
+ }
249
+ return undefined;
250
+ }
251
+
252
+ /**
253
+ * Validate the spawn parameter contract against the wire shapes. `agent` is
254
+ * always required. With `task.batch` the model-facing shape is
255
+ * `{ agent, context, tasks[] }` — `tasks` non-empty with per-item assignments
256
+ * and unique ids, `context` non-empty, no top-level `assignment` alongside.
257
+ * The flat `{ agent, ...item }` form stays accepted at runtime under either
258
+ * setting (internal callers, stale transcripts). Returns a problem
259
+ * description, or undefined when valid.
260
+ */
261
+ function validateSpawnParams(params: TaskParams, batchEnabled: boolean): string | undefined {
262
+ const agent = typeof params.agent === "string" ? params.agent.trim() : "";
263
+ if (!agent) {
264
+ return "Missing `agent`. Provide an agent type to spawn.";
265
+ }
266
+ const hasAssignment = typeof params.assignment === "string" && params.assignment.trim() !== "";
267
+ const tasks = params.tasks;
268
+ if (batchEnabled && tasks !== undefined) {
269
+ if (!Array.isArray(tasks) || tasks.length === 0) {
270
+ return "Missing `tasks`. Provide at least one task item ({ id?, description?, assignment }).";
271
+ }
272
+ if (hasAssignment) {
273
+ return "Top-level `assignment` is not part of the batch shape. Put the work in `tasks[]` items.";
274
+ }
275
+ for (let i = 0; i < tasks.length; i++) {
276
+ const item = tasks[i];
277
+ if (!item || typeof item.assignment !== "string" || item.assignment.trim() === "") {
278
+ return `Task ${i + 1}${item?.id ? ` (\`${item.id}\`)` : ""} is missing \`assignment\`. Every task needs complete, self-contained instructions.`;
279
+ }
280
+ }
281
+ const seen = new Map<string, string>();
282
+ for (const item of tasks) {
283
+ const id = item.id?.trim();
284
+ if (!id) continue;
285
+ const key = id.toLowerCase();
286
+ const existing = seen.get(key);
287
+ if (existing !== undefined) {
288
+ return `Duplicate task id ${existing === id ? `\`${id}\`` : `\`${existing}\` / \`${id}\``}. Provided ids must be unique within a call (case-insensitive).`;
289
+ }
290
+ seen.set(key, id);
291
+ }
292
+ if (typeof params.context !== "string" || params.context.trim() === "") {
293
+ return "Missing `context`. Provide the shared background for this batch — goal, constraints, and any contract the tasks share.";
294
+ }
295
+ return undefined;
296
+ }
297
+ if (!hasAssignment) {
298
+ return batchEnabled
299
+ ? "Missing `tasks`. Provide a `tasks` array (one subagent per item) with a shared `context`."
300
+ : "Missing `assignment`. Provide complete, self-contained instructions for the agent.";
301
+ }
302
+ return undefined;
303
+ }
304
+
305
+ /**
306
+ * Normalize a validated call into its spawn list: the `tasks[]` batch when
307
+ * provided, otherwise the single top-level spawn.
308
+ */
309
+ function resolveSpawnItems(params: TaskParams): TaskItem[] {
310
+ if (Array.isArray(params.tasks) && params.tasks.length > 0) {
311
+ return params.tasks;
312
+ }
313
+ return [{ id: params.id, description: params.description, role: params.role, assignment: params.assignment }];
314
+ }
315
+
316
+ /**
317
+ * Per-spawn params handed to the executor path: top-level call fields with the
318
+ * item's identity substituted in. `tasks` never leaks into a spawn; the shared
319
+ * `context` rides along unchanged. Keys are only materialized when present —
320
+ * `#runSpawn` distinguishes an absent `isolated` from an explicit one. The
321
+ * item's `isolated` (batch form) wins over the top-level flag (flat form).
322
+ */
323
+ function spawnParamsFor(params: TaskParams, item: TaskItem): TaskParams {
324
+ const spawn: TaskParams = { agent: params.agent };
325
+ if (item.id !== undefined) spawn.id = item.id;
326
+ if (item.description !== undefined) spawn.description = item.description;
327
+ if (item.role !== undefined) spawn.role = item.role;
328
+ if (item.assignment !== undefined) spawn.assignment = item.assignment;
329
+ if (params.context !== undefined) spawn.context = params.context;
330
+ if (item.isolated !== undefined) {
331
+ spawn.isolated = item.isolated;
332
+ } else if ("isolated" in params) {
333
+ spawn.isolated = params.isolated;
334
+ }
335
+ return spawn;
336
+ }
337
+
338
+ /** Generic worker agents whose output sharpens with a tailored `role` rather than the bare type. */
339
+ const GENERIC_SPAWN_AGENTS: ReadonlySet<string> = new Set(["task", "quick_task"]);
340
+
341
+ /**
342
+ * Advisory — never a rejection — nudging the spawner toward tailored
343
+ * specialists when it spawns generic role-less workers and still holds spawn
344
+ * capacity (DepthCapacity: it currently has the `task` tool). Fires when a
345
+ * generic `task`/`quick_task` spawn carries no `role`, or when one call clones
346
+ * the same agent ≥2× all without roles. Returns undefined when no nudge applies.
347
+ */
348
+ export function buildSpecializationAdvisory(
349
+ agentName: string | undefined,
350
+ items: TaskItem[],
351
+ depthCapacity: boolean,
352
+ ): string | undefined {
353
+ if (!depthCapacity) return undefined;
354
+ const rolelessCount = items.filter(item => !item.role?.trim()).length;
355
+ if (rolelessCount === 0) return undefined;
356
+ const generic = agentName !== undefined && GENERIC_SPAWN_AGENTS.has(agentName);
357
+ const cloned = items.length >= 2 && rolelessCount === items.length;
358
+ if (!generic && !cloned) return undefined;
359
+ const label = agentName ?? "task";
360
+ return (
361
+ `Tip: spawned ${rolelessCount} \`${label}\` worker${rolelessCount === 1 ? "" : "s"} without a \`role\`. ` +
362
+ `Tailored specialists outperform generic workers — give each spawn a \`role\` naming its expertise ` +
363
+ `(e.g. "Auth-flow security reviewer"). Depth budget remains, so decompose into named specialists ` +
364
+ `rather than cloning one generic worker.`
365
+ );
366
+ }
367
+
368
+ /**
369
+ * Suggestion — never a rejection — nudging the spawner to coordinate via `irc`
370
+ * when one call creates ≥2 live siblings and it still holds spawn capacity.
371
+ * Returns undefined when there is nothing to coordinate or IRC is unavailable.
372
+ */
373
+ export function buildCoordinationAdvisory(
374
+ items: TaskItem[],
375
+ depthCapacity: boolean,
376
+ ircEnabled: boolean,
377
+ ): string | undefined {
378
+ if (!depthCapacity || !ircEnabled || items.length < 2) return undefined;
379
+ return (
380
+ `Coordinate: ${items.length} siblings are running together. If their work overlaps, have them ` +
381
+ `message each other via \`irc\` (by id, or "all" to broadcast) before editing shared files — ` +
382
+ `live coordination beats a serial handoff. Check \`irc\` op:"list" to see who is doing what.`
383
+ );
384
+ }
385
+
386
+ /**
387
+ * Compose the non-blocking advisory appended to a `task` result: the
388
+ * specialization nudge, plus — only when the siblings keep running after this
389
+ * call (`willRunAsync`) — the coordination suggestion. Coordination is gated on
390
+ * async because a sync fanout's siblings have already finished, so a
391
+ * "coordinate while they run" hint would misfire. Returns undefined when
392
+ * neither applies.
393
+ */
394
+ export function composeSpawnAdvisory(args: {
395
+ agentName: string | undefined;
396
+ items: TaskItem[];
397
+ depthCapacity: boolean;
398
+ ircEnabled: boolean;
399
+ willRunAsync: boolean;
400
+ }): string | undefined {
401
+ return (
402
+ [
403
+ buildSpecializationAdvisory(args.agentName, args.items, args.depthCapacity),
404
+ args.willRunAsync ? buildCoordinationAdvisory(args.items, args.depthCapacity, args.ircEnabled) : undefined,
405
+ ]
406
+ .filter(Boolean)
407
+ .join("\n\n") || undefined
408
+ );
409
+ }
410
+
411
+ /** Sentinel for async jobs whose subagent finished with a failing result; progress is already updated. */
412
+ class TaskJobError extends Error {}
413
+
414
+ /**
415
+ * Process-level memo for create-time agent discovery, keyed by resolved cwd.
416
+ *
417
+ * `TaskTool.create` runs for every (sub)agent session in this process and the
418
+ * walk-up + plugin-registry scan in `discoverAgents` is identical for a given
419
+ * cwd, so repeat creations reuse the first scan. Execution-time discovery
420
+ * (`#runSpawn`) intentionally stays fresh. The memo also tracks the live
421
+ * `discoverAgents` binding: test spies swap that binding, which invalidates
422
+ * the memo automatically.
423
+ */
424
+ const discoveryMemo = new Map<string, Promise<DiscoveryResult>>();
425
+ let discoveryMemoFn: typeof discoverAgents | undefined;
426
+
427
+ function discoverAgentsForCreate(cwd: string): Promise<DiscoveryResult> {
428
+ const fn = discoverAgents;
429
+ if (discoveryMemoFn !== fn) {
430
+ discoveryMemoFn = fn;
431
+ discoveryMemo.clear();
432
+ }
433
+ const key = path.resolve(cwd);
434
+ let pending = discoveryMemo.get(key);
435
+ if (!pending) {
436
+ pending = fn(cwd);
437
+ discoveryMemo.set(key, pending);
438
+ pending.catch(() => {
439
+ if (discoveryMemo.get(key) === pending) discoveryMemo.delete(key);
440
+ });
441
+ }
442
+ return pending;
443
+ }
444
+
445
+ // ═══════════════════════════════════════════════════════════════════════════
446
+ // Tool Class
447
+ // ═══════════════════════════════════════════════════════════════════════════
448
+
449
+ /**
450
+ * Task tool - Delegate tasks to specialized agents.
451
+ *
452
+ * Each call spawns one subagent — or, with `task.batch`, one per `tasks[]`
453
+ * item. When `async.enabled` is on, spawns run as AsyncJobManager jobs; when
454
+ * disabled, the tool blocks until every spawn finishes.
455
+ */
456
+ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetails, Theme> {
457
+ readonly name = "task";
458
+ readonly approval = "exec" as const;
459
+ readonly formatApprovalDetails = (args: unknown): string[] => {
460
+ const params = args as Partial<TaskParams>;
461
+ const lines: string[] = [];
462
+ if (typeof params.agent === "string") {
463
+ lines.push(`Agent: ${truncateForPrompt(params.agent)}`);
464
+ }
465
+ if (typeof params.role === "string" && params.role.trim()) {
466
+ lines.push(`Role: ${truncateForPrompt(params.role)}`);
467
+ }
468
+ if (typeof params.id === "string" && params.id.trim()) {
469
+ lines.push(`Task: ${truncateForPrompt(params.id)}`);
470
+ }
471
+ if (typeof params.assignment === "string") {
472
+ lines.push(`Assignment:\n${truncateForPrompt(params.assignment)}`);
473
+ }
474
+ if (typeof params.context === "string" && params.context.trim()) {
475
+ lines.push(`Context:\n${truncateForPrompt(params.context)}`);
476
+ }
477
+ const tasks = Array.isArray(params.tasks) ? params.tasks : [];
478
+ const firstTask = tasks[0];
479
+ if (firstTask) {
480
+ if (typeof firstTask.id === "string" && firstTask.id.trim()) {
481
+ lines.push(`Task: ${truncateForPrompt(firstTask.id)}`);
482
+ }
483
+ if (typeof firstTask.role === "string" && firstTask.role.trim()) {
484
+ lines.push(`Role: ${truncateForPrompt(firstTask.role)}`);
485
+ }
486
+ if (typeof firstTask.assignment === "string") {
487
+ lines.push(`Assignment:\n${truncateForPrompt(firstTask.assignment)}`);
488
+ }
489
+ if (tasks.length > 1) {
490
+ lines.push(`+${tasks.length - 1} more task${tasks.length === 2 ? "" : "s"}`);
491
+ }
492
+ }
493
+ return lines;
494
+ };
495
+ readonly label = "Task";
496
+ readonly summary = "Spawn subagents to complete delegated tasks";
497
+ readonly strict = true;
498
+ readonly loadMode = "discoverable";
499
+ readonly renderResult = renderResult;
500
+ // Suppress the streaming call preview once a (partial or final) result exists
501
+ // so the task renders as ONE block that transitions in place — not a pending
502
+ // call frame stacked above the result frame. Mirrors `taskToolRenderer`.
503
+ readonly mergeCallAndResult = true;
504
+ readonly #discoveredAgents: AgentDefinition[];
505
+ readonly #blockedAgent: string | undefined;
506
+ /**
507
+ * One semaphore per TaskTool instance (i.e. per session): bounds concurrent
508
+ * subagents across parallel `task` calls within the session. Sized from
509
+ * `task.maxConcurrency` at first use; later setting changes do not resize it.
510
+ */
511
+ #spawnSemaphore: Semaphore | undefined;
512
+
513
+ get parameters(): TaskToolSchemaInstance {
514
+ const isolationEnabled = this.session.settings.get("task.isolation.mode") !== "none";
515
+ return getTaskSchema({ isolationEnabled, batchEnabled: this.#isBatchEnabled() });
516
+ }
517
+
518
+ renderCall(args: unknown, options: Parameters<typeof renderTaskCall>[1], theme: Theme) {
519
+ return renderTaskCall(repairTaskParams(args as TaskParams), options, theme);
520
+ }
521
+
522
+ /** Dynamic description that reflects current disabled-agent settings */
523
+ get description(): string {
524
+ const disabledAgents = this.session.settings.get("task.disabledAgents") as string[];
525
+ const maxConcurrency = this.session.settings.get("task.maxConcurrency");
526
+ const isolationMode = this.session.settings.get("task.isolation.mode");
527
+ return renderDescription(
528
+ this.#discoveredAgents,
529
+ maxConcurrency,
530
+ isolationMode !== "none",
531
+ disabledAgents,
532
+ this.#isBatchEnabled(),
533
+ this.session.settings.get("async.enabled"),
534
+ isIrcEnabled(this.session.settings, this.session.taskDepth ?? 0),
535
+ this.session.getSessionSpawns() ?? "*",
536
+ );
537
+ }
538
+ private constructor(
539
+ private readonly session: ToolSession,
540
+ discoveredAgents: AgentDefinition[],
541
+ ) {
542
+ this.#blockedAgent = $env.PI_BLOCKED_AGENT;
543
+ this.#discoveredAgents = discoveredAgents;
544
+ }
545
+
546
+ #isBatchEnabled(): boolean {
547
+ return this.session.settings.get("task.batch");
548
+ }
549
+
550
+ #getSpawnSemaphore(): Semaphore {
551
+ this.#spawnSemaphore ??= new Semaphore(this.session.settings.get("task.maxConcurrency"));
552
+ return this.#spawnSemaphore;
553
+ }
554
+
555
+ /**
556
+ * Create a TaskTool instance with async agent discovery.
557
+ */
558
+ static async create(session: ToolSession): Promise<TaskTool> {
559
+ const { agents } = await discoverAgentsForCreate(session.cwd);
560
+ return new TaskTool(session, agents);
561
+ }
562
+
563
+ async execute(
564
+ toolCallId: string,
565
+ rawParams: unknown,
566
+ signal?: AbortSignal,
567
+ onUpdate?: AgentToolUpdateCallback<TaskToolDetails>,
568
+ ): Promise<AgentToolResult<TaskToolDetails>> {
569
+ const params = repairTaskParams(rawParams as TaskParams);
570
+ const batchEnabled = this.#isBatchEnabled();
571
+ const validationError = validateShapeParams(batchEnabled, params) ?? validateSpawnParams(params, batchEnabled);
572
+ if (validationError) {
573
+ return createTaskModeError(validationError);
574
+ }
575
+
576
+ const spawnItems = resolveSpawnItems(params);
577
+ const selectedAgent = this.#discoveredAgents.find(agent => agent.name === params.agent);
578
+ const asyncEnabled = this.session.settings.get("async.enabled");
579
+ const manager = asyncEnabled ? this.session.asyncJobManager : undefined;
580
+ const depthCapacity = canSpawnAtDepth(
581
+ this.session.settings.get("task.maxRecursionDepth") ?? 2,
582
+ this.session.taskDepth ?? 0,
583
+ );
584
+ const ircEnabled = isIrcEnabled(this.session.settings, this.session.taskDepth ?? 0);
585
+ // Coordination only makes sense when the siblings keep running after this
586
+ // call returns (async). In the sync fallback they have already completed,
587
+ // so a "coordinate while they run" hint would misfire.
588
+ const willRunAsync = !!manager && selectedAgent?.blocking !== true;
589
+ const advisory = this.session.suppressSpawnAdvisory
590
+ ? undefined
591
+ : composeSpawnAdvisory({
592
+ agentName: params.agent,
593
+ items: spawnItems,
594
+ depthCapacity,
595
+ ircEnabled,
596
+ willRunAsync,
597
+ });
598
+ // Returns a fresh result (copied content array, copied text part) rather
599
+ // than mutating the caller's — task results are short-lived here, but an
600
+ // in-place edit on a shared/cached AgentToolResult would be a hidden trap.
601
+ const withAdvisory = (result: AgentToolResult<TaskToolDetails>): AgentToolResult<TaskToolDetails> => {
602
+ if (!advisory) return result;
603
+ let appended = false;
604
+ const content = result.content.map(part => {
605
+ if (!appended && part.type === "text" && typeof part.text === "string") {
606
+ appended = true;
607
+ return { ...part, text: `${part.text}\n\n${advisory}` };
608
+ }
609
+ return part;
610
+ });
611
+ if (!appended) content.push({ type: "text", text: advisory });
612
+ return { ...result, content };
613
+ };
614
+ if (!asyncEnabled || !manager || selectedAgent?.blocking === true) {
615
+ // Sync fallback: async execution disabled, orphaned host that never
616
+ // wired a job manager, or an agent definition that declares
617
+ // `blocking: true`. The session-scoped semaphore still bounds fan-out
618
+ // across parallel task calls.
619
+ if (asyncEnabled && !manager) {
620
+ logger.warn("task: no AsyncJobManager registered; falling back to sync execution");
621
+ }
622
+ return withAdvisory(await this.#executeSyncFanout(toolCallId, params, spawnItems, signal, onUpdate));
623
+ }
624
+
625
+ // Resolve agent ids up front so the immediate result can name them.
626
+ const outputManager =
627
+ this.session.agentOutputManager ?? new AgentOutputManager(this.session.getArtifactsDir ?? (() => null));
628
+ const agentLabel = params.agent ?? "task";
629
+ const agentSource = selectedAgent?.source ?? "bundled";
630
+ const spawns: Array<{ agentId: string; item: TaskItem; progress: AgentProgress }> = [];
631
+ for (let index = 0; index < spawnItems.length; index++) {
632
+ const item = spawnItems[index];
633
+ const agentId = await outputManager.allocate(item.id?.trim() || generateTaskName());
634
+ const assignment = (item.assignment ?? "").trim();
635
+ spawns.push({
636
+ agentId,
637
+ item,
638
+ progress: {
639
+ index,
640
+ id: agentId,
641
+ agent: agentLabel,
642
+ agentSource,
643
+ status: "pending",
644
+ task: renderSubagentUserPrompt(assignment),
645
+ assignment,
646
+ description: item.description,
647
+ recentTools: [],
648
+ recentOutput: [],
649
+ toolCount: 0,
650
+ requests: 0,
651
+ tokens: 0,
652
+ cost: 0,
653
+ durationMs: 0,
654
+ },
655
+ });
656
+ }
657
+
658
+ // Aggregate async state for the one tool call: every spawn's job reports
659
+ // into the shared progress snapshot; the call stays "running" until all
660
+ // jobs settle, then turns "failed" if any spawn failed. The single-spawn
661
+ // case passes the job's own suggestion through (pre-batch behavior).
662
+ const single = spawns.length === 1;
663
+ let settledCount = 0;
664
+ let failedCount = 0;
665
+ let primaryJobId = spawns[0].agentId;
666
+ const buildAsyncDetails = (state: "running" | "completed" | "failed", jobId: string): TaskToolDetails => ({
667
+ projectAgentsDir: null,
668
+ results: [],
669
+ totalDurationMs: 0,
670
+ progress: spawns.map(spawn => ({ ...spawn.progress })),
671
+ async: {
672
+ state: single ? state : settledCount < spawns.length ? "running" : failedCount > 0 ? "failed" : "completed",
673
+ jobId: single ? jobId : primaryJobId,
674
+ type: "task",
675
+ },
676
+ });
677
+
678
+ const started: Array<{ agentId: string; jobId: string; description?: string }> = [];
679
+ const failedSchedules: string[] = [];
680
+ for (const spawn of spawns) {
681
+ try {
682
+ const jobId = this.#registerSpawnJob({
683
+ manager,
684
+ toolCallId,
685
+ spawnParams: spawnParamsFor(params, spawn.item),
686
+ agentId: spawn.agentId,
687
+ progress: spawn.progress,
688
+ ircEnabled,
689
+ buildDetails: buildAsyncDetails,
690
+ onUpdate,
691
+ onSettled: failed => {
692
+ settledCount += 1;
693
+ if (failed) failedCount += 1;
694
+ },
695
+ });
696
+ if (started.length === 0) primaryJobId = jobId;
697
+ started.push({ agentId: spawn.agentId, jobId, description: spawn.item.description });
698
+ } catch (error) {
699
+ const message = error instanceof Error ? error.message : String(error);
700
+ failedSchedules.push(`${spawn.agentId}: ${message}`);
701
+ spawn.progress.status = "failed";
702
+ settledCount += 1;
703
+ failedCount += 1;
704
+ }
705
+ }
706
+
707
+ if (started.length === 0) {
708
+ return {
709
+ content: [
710
+ {
711
+ type: "text",
712
+ text: `Failed to start background task job${single ? "" : "s"}: ${failedSchedules.join("; ")}`,
713
+ },
714
+ ],
715
+ details: { projectAgentsDir: null, results: [], totalDurationMs: 0 },
716
+ };
717
+ }
718
+
719
+ if (single) {
720
+ const { agentId, jobId, description } = started[0];
721
+ const coordinationHint = ircEnabled
722
+ ? `DM \`${agentId}\` via \`irc\` to coordinate while it runs; use \`job\` only to inspect (\`list\`), wait (\`poll\`), or cancel a stuck task.`
723
+ : `Use \`job\` to inspect (\`list\`), wait (\`poll\`), or cancel a stuck task.`;
724
+ const descriptionSuffix = description ? ` — ${description}` : "";
725
+ onUpdate?.({
726
+ content: [{ type: "text", text: `Spawned agent \`${agentId}\`...` }],
727
+ details: buildAsyncDetails("running", jobId),
728
+ });
729
+ return withAdvisory({
730
+ content: [
731
+ {
732
+ type: "text",
733
+ text: `Spawned agent \`${agentId}\` (job \`${jobId}\`)${descriptionSuffix}. The result will be delivered when it yields. ${coordinationHint}`,
734
+ },
735
+ ],
736
+ details: buildAsyncDetails("running", jobId),
737
+ });
738
+ }
739
+
740
+ const coordinationHint = ircEnabled
741
+ ? `DM these ids via \`irc\` to coordinate while they run; use \`job\` only to inspect (\`list\`), wait (\`poll\`), or cancel a stuck task.`
742
+ : `Use \`job\` to inspect (\`list\`), wait (\`poll\`), or cancel a stuck task by id.`;
743
+ const scheduleFailureSummary =
744
+ failedSchedules.length > 0
745
+ ? ` Failed to schedule ${failedSchedules.length} spawn${failedSchedules.length === 1 ? "" : "s"}: ${failedSchedules.join("; ")}.`
746
+ : "";
747
+ const startedListing = started
748
+ .map(({ agentId, jobId, description }) => {
749
+ const prefix = `- \`${agentId}\` (job \`${jobId}\`)`;
750
+ return description ? `${prefix} — ${description}` : prefix;
751
+ })
752
+ .join("\n");
753
+ onUpdate?.({
754
+ content: [{ type: "text", text: `Spawned ${started.length} agents...` }],
755
+ details: buildAsyncDetails("running", primaryJobId),
756
+ });
757
+ return withAdvisory({
758
+ content: [
759
+ {
760
+ type: "text",
761
+ text: `Spawned ${started.length} background agents using ${agentLabel}.${scheduleFailureSummary} Each result will be delivered when that agent yields.\n${startedListing}\n${coordinationHint}`,
762
+ },
763
+ ],
764
+ details: buildAsyncDetails("running", primaryJobId),
765
+ });
766
+ }
767
+
768
+ /**
769
+ * Register one background job that runs a single spawn to completion and
770
+ * delivers its yield text. The job body mirrors the sync path; `buildDetails`
771
+ * supplies the (possibly batch-shared) progress snapshot and `onSettled`
772
+ * feeds the caller's aggregate counters.
773
+ */
774
+ #registerSpawnJob(options: {
775
+ manager: AsyncJobManager;
776
+ toolCallId: string;
777
+ spawnParams: TaskParams;
778
+ agentId: string;
779
+ progress: AgentProgress;
780
+ ircEnabled: boolean;
781
+ buildDetails: (state: "running" | "completed" | "failed", jobId: string) => TaskToolDetails;
782
+ onUpdate?: AgentToolUpdateCallback<TaskToolDetails>;
783
+ onSettled?: (failed: boolean) => void;
784
+ }): string {
785
+ const { manager, toolCallId, spawnParams, agentId, progress, ircEnabled, buildDetails, onUpdate, onSettled } =
786
+ options;
787
+ const buildFollowUpHint = (aborted: boolean): string => {
788
+ if (aborted) {
789
+ return `\n\n${agentId} was aborted — transcript at history://${agentId}`;
790
+ }
791
+ const followUp = ircEnabled ? "message it via `irc` to follow up; " : "";
792
+ return `\n\n${agentId} is now idle — ${followUp}transcript at history://${agentId}`;
793
+ };
794
+ return manager.register(
795
+ "task",
796
+ agentId,
797
+ async ({ jobId: ownJobId, signal: runSignal, reportProgress, markRunning }) => {
798
+ const startedAt = Date.now();
799
+ const semaphore = this.#getSpawnSemaphore();
800
+ await semaphore.acquire();
801
+ const acquiredAt = Date.now();
802
+ if (runSignal.aborted) {
803
+ semaphore.release();
804
+ progress.status = "aborted";
805
+ onSettled?.(true);
806
+ throw new Error("Aborted before execution");
807
+ }
808
+ markRunning();
809
+ progress.status = "running";
810
+ await reportProgress(
811
+ `Running background task ${agentId}...`,
812
+ buildDetails("running", ownJobId) as unknown as Record<string, unknown>,
813
+ );
814
+ try {
815
+ const result = await this.#executeSync(
816
+ toolCallId,
817
+ spawnParams,
818
+ runSignal,
819
+ undefined,
820
+ agentId,
821
+ progress.index,
822
+ true,
823
+ { invokedAt: startedAt, acquiredAt },
824
+ );
825
+ const finalText = result.content.find(part => part.type === "text")?.text ?? "(no output)";
826
+ const singleResult = result.details?.results[0];
827
+ // A missing result means the sync path failed at the tool level
828
+ // (results: []) — treat it as a failure, not success.
829
+ const resultFailed = !singleResult || (singleResult.aborted ?? false) || singleResult.exitCode !== 0;
830
+ progress.status = singleResult?.aborted ? "aborted" : resultFailed ? "failed" : "completed";
831
+ progress.durationMs = singleResult?.durationMs ?? Math.max(0, Date.now() - startedAt);
832
+ progress.tokens = singleResult?.tokens ?? 0;
833
+ progress.requests = singleResult?.requests ?? 0;
834
+ progress.contextTokens = singleResult?.contextTokens;
835
+ progress.contextWindow = singleResult?.contextWindow;
836
+ progress.cost = singleResult?.usage?.cost.total ?? 0;
837
+ progress.extractedToolData = singleResult?.extractedToolData;
838
+ progress.retryFailure = singleResult?.retryFailure;
839
+ progress.retryState = undefined;
840
+ onSettled?.(resultFailed);
841
+ const statusText = resultFailed
842
+ ? `Background task ${agentId} failed.`
843
+ : `Background task ${agentId} complete.`;
844
+ await reportProgress(
845
+ statusText,
846
+ buildDetails(resultFailed ? "failed" : "completed", ownJobId) as unknown as Record<string, unknown>,
847
+ );
848
+ onUpdate?.({
849
+ content: [{ type: "text", text: statusText }],
850
+ details: buildDetails(resultFailed ? "failed" : "completed", ownJobId),
851
+ });
852
+ const deliveryText = `${finalText}${buildFollowUpHint(singleResult?.aborted === true)}`;
853
+ if (resultFailed) {
854
+ // Mark the job itself failed; the failed agent stays interrogable.
855
+ throw new TaskJobError(deliveryText);
856
+ }
857
+ return deliveryText;
858
+ } catch (error) {
859
+ if (error instanceof TaskJobError) {
860
+ throw error;
861
+ }
862
+ progress.status = "failed";
863
+ progress.durationMs = Math.max(0, Date.now() - startedAt);
864
+ onSettled?.(true);
865
+ const statusText = `Background task ${agentId} failed.`;
866
+ await reportProgress(statusText, buildDetails("failed", ownJobId) as unknown as Record<string, unknown>);
867
+ onUpdate?.({
868
+ content: [{ type: "text", text: statusText }],
869
+ details: buildDetails("failed", ownJobId),
870
+ });
871
+ const message = error instanceof Error ? error.message : String(error);
872
+ const hint = AgentRegistry.global().get(agentId) ? buildFollowUpHint(false) : "";
873
+ throw new TaskJobError(`${message}${hint}`);
874
+ } finally {
875
+ semaphore.release();
876
+ }
877
+ },
878
+ {
879
+ id: agentId,
880
+ queued: true,
881
+ ownerId: this.session.getAgentId?.() ?? undefined,
882
+ onProgress: (text, details) => {
883
+ const progressDetails = (details as TaskToolDetails | undefined) ?? buildDetails("running", agentId);
884
+ onUpdate?.({ content: [{ type: "text", text }], details: progressDetails });
885
+ },
886
+ },
887
+ );
888
+ }
889
+
890
+ /**
891
+ * Sync fallback fan-out (no job manager, or a `blocking: true` agent): run
892
+ * every spawn to completion inline and merge the per-spawn payloads into a
893
+ * single tool result. The session-scoped semaphore still bounds concurrency
894
+ * across parallel task calls.
895
+ */
896
+ async #executeSyncFanout(
897
+ toolCallId: string,
898
+ params: TaskParams,
899
+ spawnItems: TaskItem[],
900
+ signal?: AbortSignal,
901
+ onUpdate?: AgentToolUpdateCallback<TaskToolDetails>,
902
+ ): Promise<AgentToolResult<TaskToolDetails>> {
903
+ const semaphore = this.#getSpawnSemaphore();
904
+ if (spawnItems.length === 1) {
905
+ const invokedAt = Date.now();
906
+ await semaphore.acquire();
907
+ const acquiredAt = Date.now();
908
+ try {
909
+ return await this.#executeSync(
910
+ toolCallId,
911
+ spawnParamsFor(params, spawnItems[0]),
912
+ signal,
913
+ onUpdate,
914
+ undefined,
915
+ 0,
916
+ false,
917
+ { invokedAt, acquiredAt },
918
+ );
919
+ } finally {
920
+ semaphore.release();
921
+ }
922
+ }
923
+
924
+ const startTime = Date.now();
925
+ const latestProgress = new Map<number, AgentProgress>();
926
+ const emitCombined = () => {
927
+ onUpdate?.({
928
+ content: [{ type: "text", text: `Running ${spawnItems.length} agents...` }],
929
+ details: {
930
+ projectAgentsDir: null,
931
+ results: [],
932
+ totalDurationMs: Date.now() - startTime,
933
+ progress: Array.from(latestProgress.entries())
934
+ .sort((a, b) => a[0] - b[0])
935
+ .map(([, progress]) => progress),
936
+ },
937
+ });
938
+ };
939
+
940
+ const { results: payloads } = await mapWithConcurrencyLimit(
941
+ spawnItems,
942
+ spawnItems.length,
943
+ async (item, index, workerSignal) => {
944
+ const invokedAt = Date.now();
945
+ await semaphore.acquire();
946
+ const acquiredAt = Date.now();
947
+ try {
948
+ const itemOnUpdate: AgentToolUpdateCallback<TaskToolDetails> | undefined = onUpdate
949
+ ? update => {
950
+ const progress = update.details?.progress?.[0];
951
+ if (progress) {
952
+ latestProgress.set(index, { ...progress, index });
953
+ emitCombined();
954
+ }
955
+ }
956
+ : undefined;
957
+ return await this.#executeSync(
958
+ toolCallId,
959
+ spawnParamsFor(params, item),
960
+ workerSignal,
961
+ itemOnUpdate,
962
+ undefined,
963
+ index,
964
+ false,
965
+ { invokedAt, acquiredAt },
966
+ );
967
+ } finally {
968
+ semaphore.release();
969
+ }
970
+ },
971
+ signal,
972
+ );
973
+
974
+ const results: SingleResult[] = [];
975
+ const contentParts: string[] = [];
976
+ const outputPaths: string[] = [];
977
+ const usageTotals = createUsageTotals();
978
+ let hasUsage = false;
979
+ let projectAgentsDir: string | null = null;
980
+ for (let index = 0; index < spawnItems.length; index++) {
981
+ const payload = payloads[index];
982
+ if (!payload) {
983
+ contentParts.push(`Task ${spawnItems[index].id?.trim() || `#${index + 1}`}: cancelled before start.`);
984
+ continue;
985
+ }
986
+ projectAgentsDir ??= payload.details?.projectAgentsDir ?? null;
987
+ const text = payload.content.find(part => part.type === "text")?.text;
988
+ if (text) contentParts.push(text);
989
+ for (const result of payload.details?.results ?? []) {
990
+ results.push({ ...result, index });
991
+ if (result.usage) {
992
+ addUsageTotals(usageTotals, result.usage);
993
+ hasUsage = true;
994
+ }
995
+ if (result.outputPath) outputPaths.push(result.outputPath);
996
+ }
997
+ }
998
+
999
+ return {
1000
+ content: [{ type: "text", text: contentParts.join("\n\n") }],
1001
+ details: {
1002
+ projectAgentsDir,
1003
+ results,
1004
+ totalDurationMs: Date.now() - startTime,
1005
+ usage: hasUsage ? usageTotals : undefined,
1006
+ outputPaths: outputPaths.length > 0 ? outputPaths : undefined,
1007
+ },
1008
+ };
1009
+ }
1010
+
1011
+ /**
1012
+ * Synchronous execution of one spawn. Used as the body of every
1013
+ * async job and directly by the sync fallback (no job manager / blocking
1014
+ * agent) and by in-process callers that need the result inline (e.g. the
1015
+ * commit flow's analyze_files tool).
1016
+ */
1017
+ async #executeSync(
1018
+ toolCallId: string,
1019
+ params: TaskParams,
1020
+ signal?: AbortSignal,
1021
+ onUpdate?: AgentToolUpdateCallback<TaskToolDetails>,
1022
+ preAllocatedId?: string,
1023
+ spawnIndex = 0,
1024
+ detached = false,
1025
+ launchTiming?: { invokedAt: number; acquiredAt: number },
1026
+ ): Promise<AgentToolResult<TaskToolDetails>> {
1027
+ return this.#runSpawn(toolCallId, params, signal, onUpdate, preAllocatedId, spawnIndex, detached, launchTiming);
1028
+ }
1029
+
1030
+ /** Spawn a fresh subagent and run it to completion. */
1031
+ async #runSpawn(
1032
+ toolCallId: string,
1033
+ params: TaskParams,
1034
+ signal?: AbortSignal,
1035
+ onUpdate?: AgentToolUpdateCallback<TaskToolDetails>,
1036
+ preAllocatedId?: string,
1037
+ spawnIndex = 0,
1038
+ detached = false,
1039
+ launchTiming?: { invokedAt: number; acquiredAt: number },
1040
+ ): Promise<AgentToolResult<TaskToolDetails>> {
1041
+ const startTime = Date.now();
1042
+ const { agents, projectAgentsDir } = await discoverAgents(this.session.cwd);
1043
+ const agentName = params.agent ?? "";
1044
+ const sharedContext = this.#isBatchEnabled() ? params.context?.trim() || undefined : undefined;
1045
+ const assignment = (params.assignment ?? "").trim();
1046
+ const isolationMode = this.session.settings.get("task.isolation.mode");
1047
+ const isolationRequested = "isolated" in params ? params.isolated === true : false;
1048
+ const isIsolated = isolationMode !== "none" && isolationRequested;
1049
+ const mergeMode = this.session.settings.get("task.isolation.merge");
1050
+ const commitStyle = this.session.settings.get("task.isolation.commits");
1051
+ const taskDepth = this.session.taskDepth ?? 0;
1052
+ const subagentLspEnabled = (this.session.enableLsp ?? true) && this.session.settings.get("task.enableLsp");
1053
+
1054
+ if (isolationMode === "none" && "isolated" in params) {
1055
+ return {
1056
+ content: [{ type: "text", text: "Task isolation is disabled." }],
1057
+ details: { projectAgentsDir, results: [], totalDurationMs: 0 },
1058
+ };
1059
+ }
1060
+
1061
+ // Validate agent exists
1062
+ const agent = getAgent(agents, agentName);
1063
+ if (!agent) {
1064
+ const available = agents.map(a => a.name).join(", ") || "none";
1065
+ return {
1066
+ content: [{ type: "text", text: `Unknown agent "${agentName}". Available: ${available}` }],
1067
+ details: { projectAgentsDir, results: [], totalDurationMs: 0 },
1068
+ };
1069
+ }
1070
+
1071
+ // Check if agent is disabled in settings
1072
+ const disabledAgents = this.session.settings.get("task.disabledAgents") as string[];
1073
+ if (disabledAgents.length > 0 && disabledAgents.includes(agentName)) {
1074
+ const enabled = agents.filter(a => !disabledAgents.includes(a.name)).map(a => a.name);
1075
+ return {
1076
+ content: [
1077
+ {
1078
+ type: "text",
1079
+ text: `Agent "${agentName}" is disabled in settings. Enable it via /agents, or use a different agent type.${enabled.length > 0 ? ` Available: ${enabled.join(", ")}` : ""}`,
1080
+ },
1081
+ ],
1082
+ details: { projectAgentsDir, results: [], totalDurationMs: 0 },
1083
+ };
1084
+ }
1085
+
1086
+ const planModeState = this.session.getPlanModeState?.();
1087
+ const planModeBaseTools = ["read", "search", "find", "lsp", "web_search"];
1088
+ const planModeTools = [
1089
+ ...planModeBaseTools,
1090
+ ...(agent.tools ?? []).filter(
1091
+ tool => PLAN_MODE_AGENT_TOOL_ALLOWLIST.has(tool) && !planModeBaseTools.includes(tool),
1092
+ ),
1093
+ ];
1094
+ const effectiveAgent: typeof agent = planModeState?.enabled
1095
+ ? {
1096
+ ...agent,
1097
+ systemPrompt: `${planModeSubagentPrompt}\n\n${agent.systemPrompt}`,
1098
+ tools: planModeTools,
1099
+ spawns: undefined,
1100
+ }
1101
+ : agent;
1102
+
1103
+ // Apply per-agent model override from settings (highest priority)
1104
+ const agentModelOverrides = this.session.settings.get("task.agentModelOverrides");
1105
+ const settingsModelOverride = agentModelOverrides[agentName];
1106
+ const parentActiveModelPattern = this.session.getActiveModelString?.();
1107
+ const modelOverride = resolveAgentModelPatterns({
1108
+ settingsOverride: settingsModelOverride,
1109
+ agentModel: effectiveAgent.model,
1110
+ settings: this.session.settings,
1111
+ activeModelPattern: parentActiveModelPattern,
1112
+ fallbackModelPattern: this.session.getModelString?.(),
1113
+ });
1114
+ const thinkingLevelOverride = effectiveAgent.thinkingLevel;
1115
+
1116
+ // Output schema priority: agent frontmatter > inherited parent session.
1117
+ // The task call itself never carries a schema; workflows needing ad-hoc
1118
+ // structured output go through eval agent(prompt, schema).
1119
+ const effectiveOutputSchema = effectiveAgent.output ?? this.session.outputSchema;
1120
+
1121
+ let repoRoot: string | null = null;
1122
+ let baseline: WorktreeBaseline | null = null;
1123
+ if (isIsolated) {
1124
+ try {
1125
+ repoRoot = await getRepoRoot(this.session.cwd);
1126
+ baseline = await captureBaseline(repoRoot);
1127
+ } catch (err) {
1128
+ const message = err instanceof Error ? err.message : String(err);
1129
+ return {
1130
+ content: [{ type: "text", text: `Isolated task execution requires a git repository. ${message}` }],
1131
+ details: { projectAgentsDir, results: [], totalDurationMs: Date.now() - startTime },
1132
+ };
1133
+ }
1134
+ }
1135
+
1136
+ const preferredIsolationBackend = parseIsolationMode(isolationMode);
1137
+
1138
+ // Derive artifacts directory
1139
+ const sessionFile = this.session.getSessionFile();
1140
+ const artifactsDir = sessionFile ? sessionFile.slice(0, -6) : null;
1141
+ const tempArtifactsDir = artifactsDir ? null : path.join(os.tmpdir(), `omp-task-${Snowflake.next()}`);
1142
+ const effectiveArtifactsDir = artifactsDir || tempArtifactsDir!;
1143
+
1144
+ const localProtocolOptions: LocalProtocolOptions = this.session.localProtocolOptions ?? {
1145
+ getArtifactsDir: this.session.getArtifactsDir ?? (() => null),
1146
+ getSessionId: this.session.getSessionId ?? (() => null),
1147
+ };
1148
+
1149
+ // Subagents adopt the parent's ArtifactManager so artifact IDs are unique
1150
+ // across the whole tree and outputs land flat in the parent's dir.
1151
+ const parentArtifactManager = this.session.getArtifactManager?.() ?? undefined;
1152
+
1153
+ // When the session is executing an approved plan, hand the overall plan to
1154
+ // every subagent so they share the main agent's plan context. Skipped in
1155
+ // plan mode (read-only exploration uses planModeSubagentPrompt instead) and
1156
+ // when no plan file exists at the session's reference path.
1157
+ const planReference = planModeState?.enabled
1158
+ ? undefined
1159
+ : await loadOverallPlanReference(
1160
+ this.session.getPlanReferencePath?.() ?? "local://PLAN.md",
1161
+ localProtocolOptions,
1162
+ );
1163
+
1164
+ try {
1165
+ // Check self-recursion prevention
1166
+ if (this.#blockedAgent && agentName === this.#blockedAgent) {
1167
+ return {
1168
+ content: [
1169
+ {
1170
+ type: "text",
1171
+ text: `Cannot spawn ${this.#blockedAgent} agent from within itself (recursion prevention). Use a different agent type.`,
1172
+ },
1173
+ ],
1174
+ details: { projectAgentsDir, results: [], totalDurationMs: Date.now() - startTime },
1175
+ };
1176
+ }
1177
+
1178
+ // Check spawn restrictions from parent
1179
+ const parentSpawns = this.session.getSessionSpawns() ?? "*";
1180
+ const allowedSpawns = parentSpawns.split(",").map(s => s.trim());
1181
+ const isSpawnAllowed = (): boolean => {
1182
+ if (parentSpawns === "") return false; // Empty = deny all
1183
+ if (parentSpawns === "*") return true; // Wildcard = allow all
1184
+ return allowedSpawns.includes(agentName);
1185
+ };
1186
+
1187
+ if (!isSpawnAllowed()) {
1188
+ const allowed = parentSpawns === "" ? "none (spawns disabled for this agent)" : parentSpawns;
1189
+ return {
1190
+ content: [{ type: "text", text: `Cannot spawn '${agentName}'. Allowed: ${allowed}` }],
1191
+ details: { projectAgentsDir, results: [], totalDurationMs: Date.now() - startTime },
1192
+ };
1193
+ }
1194
+
1195
+ await fs.mkdir(effectiveArtifactsDir, { recursive: true });
1196
+
1197
+ // Allocate a unique ID across the session to prevent artifact collisions
1198
+ let agentId: string;
1199
+ if (preAllocatedId) {
1200
+ agentId = preAllocatedId;
1201
+ } else {
1202
+ const outputManager =
1203
+ this.session.agentOutputManager ?? new AgentOutputManager(this.session.getArtifactsDir ?? (() => null));
1204
+ agentId = await outputManager.allocate(params.id?.trim() || generateTaskName());
1205
+ }
1206
+
1207
+ const availableSkills = [...(this.session.skills ?? [])];
1208
+ // Resolve autoload skills from agent definition against available skills
1209
+ const resolvedAutoloadSkills =
1210
+ agent.autoloadSkills?.length && availableSkills.length > 0
1211
+ ? agent.autoloadSkills
1212
+ .map(name => availableSkills.find(s => s.name === name))
1213
+ .filter((s): s is NonNullable<typeof s> => s !== undefined)
1214
+ : [];
1215
+ const contextFiles = this.session.contextFiles?.filter(
1216
+ file => path.basename(file.path).toLowerCase() !== "agents.md",
1217
+ );
1218
+ const promptTemplates = this.session.promptTemplates;
1219
+ const parentEvalSessionId = this.session.getEvalSessionId?.() ?? undefined;
1220
+ const mcpManager = this.session.mcpManager ?? MCPManager.instance();
1221
+
1222
+ // Progress tracking for the single agent
1223
+ let latestProgress: AgentProgress = {
1224
+ index: spawnIndex,
1225
+ id: agentId,
1226
+ agent: agentName,
1227
+ agentSource: agent.source,
1228
+ status: "pending",
1229
+ task: renderSubagentUserPrompt(assignment),
1230
+ assignment,
1231
+ recentTools: [],
1232
+ recentOutput: [],
1233
+ toolCount: 0,
1234
+ requests: 0,
1235
+ tokens: 0,
1236
+ cost: 0,
1237
+ durationMs: 0,
1238
+ modelOverride,
1239
+ description: params.description,
1240
+ };
1241
+ const emitProgress = () => {
1242
+ onUpdate?.({
1243
+ content: [{ type: "text", text: `Running agent ${agentId}...` }],
1244
+ details: {
1245
+ projectAgentsDir,
1246
+ results: [],
1247
+ totalDurationMs: Date.now() - startTime,
1248
+ progress: [latestProgress],
1249
+ },
1250
+ });
1251
+ };
1252
+ emitProgress();
1253
+
1254
+ const buildCommitMessageFn = () =>
1255
+ commitStyle === "ai" && this.session.modelRegistry
1256
+ ? async (diff: string) => {
1257
+ return generateCommitMessage(
1258
+ diff,
1259
+ this.session.modelRegistry!,
1260
+ this.session.settings,
1261
+ this.session.getSessionId?.() ?? undefined,
1262
+ );
1263
+ }
1264
+ : undefined;
1265
+
1266
+ const sharedRunOptions = {
1267
+ cwd: this.session.cwd,
1268
+ agent: effectiveAgent,
1269
+ task: renderSubagentUserPrompt(assignment),
1270
+ assignment,
1271
+ context: sharedContext,
1272
+ planReference,
1273
+ description: params.description,
1274
+ role: params.role,
1275
+ index: spawnIndex,
1276
+ parentToolCallId: toolCallId,
1277
+ detached,
1278
+ id: agentId,
1279
+ taskDepth,
1280
+ invokedAt: launchTiming?.invokedAt,
1281
+ acquiredAt: launchTiming?.acquiredAt,
1282
+ modelOverride,
1283
+ parentActiveModelPattern,
1284
+ thinkingLevel: thinkingLevelOverride,
1285
+ outputSchema: effectiveOutputSchema,
1286
+ sessionFile,
1287
+ persistArtifacts: !!artifactsDir,
1288
+ artifactsDir: effectiveArtifactsDir,
1289
+ enableLsp: subagentLspEnabled,
1290
+ signal,
1291
+ eventBus: this.session.eventBus,
1292
+ onProgress: (progress: AgentProgress) => {
1293
+ // Shallow snapshot; recentTools is mutated in place by the
1294
+ // executor, the rest is reassigned or immutable. A deep clone
1295
+ // here cost O(extractedToolData) per progress event.
1296
+ latestProgress = { ...progress, recentTools: progress.recentTools.slice() };
1297
+ emitProgress();
1298
+ },
1299
+ authStorage: this.session.authStorage,
1300
+ modelRegistry: this.session.modelRegistry,
1301
+ settings: this.session.settings,
1302
+ mcpManager,
1303
+ contextFiles,
1304
+ skills: availableSkills,
1305
+ autoloadSkills: resolvedAutoloadSkills,
1306
+ workspaceTree: this.session.workspaceTree,
1307
+ promptTemplates,
1308
+ rules: this.session.rules,
1309
+ preloadedExtensionPaths: this.session.extensionPaths,
1310
+ preloadedCustomToolPaths: this.session.customToolPaths,
1311
+ localProtocolOptions,
1312
+ parentArtifactManager,
1313
+ parentHindsightSessionState: this.session.getHindsightSessionState?.(),
1314
+ parentMnemopiSessionState: this.session.getMnemopiSessionState?.(),
1315
+ parentTelemetry: this.session.getTelemetry?.(),
1316
+ parentEvalSessionId,
1317
+ parentAgentId: this.session.getAgentId?.() ?? MAIN_AGENT_ID,
1318
+ };
1319
+
1320
+ const runTask = async (): Promise<SingleResult> => {
1321
+ if (!isIsolated) {
1322
+ return runSubprocess(sharedRunOptions);
1323
+ }
1324
+
1325
+ const taskStart = Date.now();
1326
+ let isolationHandle: IsolationHandle | undefined;
1327
+ try {
1328
+ if (!repoRoot || !baseline) {
1329
+ throw new Error("Isolated task execution not initialized.");
1330
+ }
1331
+ const taskBaseline = structuredClone(baseline);
1332
+
1333
+ isolationHandle = await ensureIsolation(repoRoot, agentId, preferredIsolationBackend);
1334
+ const isolationDir = isolationHandle.mergedDir;
1335
+
1336
+ // Isolated runs re-discover extensions/custom tools inside the
1337
+ // worktree instead of reusing the parent's source paths.
1338
+ const result = await runSubprocess({
1339
+ ...sharedRunOptions,
1340
+ worktree: isolationDir,
1341
+ preloadedExtensionPaths: undefined,
1342
+ preloadedCustomToolPaths: undefined,
1343
+ });
1344
+ if (mergeMode === "branch" && result.exitCode === 0) {
1345
+ try {
1346
+ const commitResult = await commitToBranch(
1347
+ isolationDir,
1348
+ taskBaseline,
1349
+ agentId,
1350
+ params.description,
1351
+ buildCommitMessageFn(),
1352
+ );
1353
+ return {
1354
+ ...result,
1355
+ branchName: commitResult?.branchName,
1356
+ nestedPatches: commitResult?.nestedPatches,
1357
+ };
1358
+ } catch (mergeErr) {
1359
+ // Agent succeeded but branch commit failed — clean up stale branch
1360
+ const branchName = `omp/task/${agentId}`;
1361
+ await git.branch.tryDelete(repoRoot, branchName);
1362
+ const msg = mergeErr instanceof Error ? mergeErr.message : String(mergeErr);
1363
+ return { ...result, error: `Merge failed: ${msg}` };
1364
+ }
1365
+ }
1366
+ if (result.exitCode === 0) {
1367
+ try {
1368
+ const delta = await captureDeltaPatch(isolationDir, taskBaseline);
1369
+ const patchPath = path.join(effectiveArtifactsDir, `${agentId}.patch`);
1370
+ await Bun.write(patchPath, delta.rootPatch);
1371
+ return {
1372
+ ...result,
1373
+ patchPath,
1374
+ nestedPatches: delta.nestedPatches,
1375
+ };
1376
+ } catch (patchErr) {
1377
+ const msg = patchErr instanceof Error ? patchErr.message : String(patchErr);
1378
+ return { ...result, error: `Patch capture failed: ${msg}` };
1379
+ }
1380
+ }
1381
+ return result;
1382
+ } catch (err) {
1383
+ const message = err instanceof Error ? err.message : String(err);
1384
+ return {
1385
+ index: spawnIndex,
1386
+ id: agentId,
1387
+ agent: agent.name,
1388
+ agentSource: agent.source,
1389
+ task: renderSubagentUserPrompt(assignment),
1390
+ assignment,
1391
+ description: params.description,
1392
+ exitCode: 1,
1393
+ output: "",
1394
+ stderr: message,
1395
+ truncated: false,
1396
+ durationMs: Date.now() - taskStart,
1397
+ tokens: 0,
1398
+ requests: 0,
1399
+ modelOverride,
1400
+ error: message,
1401
+ };
1402
+ } finally {
1403
+ if (isolationHandle) {
1404
+ await cleanupIsolation(isolationHandle);
1405
+ }
1406
+ }
1407
+ };
1408
+
1409
+ const result = await runTask();
1410
+
1411
+ let mergeSummary = "";
1412
+ let changesApplied: boolean | null = null;
1413
+ let hadAnyChanges = false;
1414
+ let mergedBranchForNestedPatches = false;
1415
+ if (isIsolated && repoRoot) {
1416
+ try {
1417
+ if (mergeMode === "branch") {
1418
+ if (!result.branchName || result.exitCode !== 0 || result.aborted) {
1419
+ changesApplied = true;
1420
+ mergeSummary = "\n\nNo changes to apply.";
1421
+ } else {
1422
+ const mergeResult = await mergeTaskBranches(repoRoot, [
1423
+ { branchName: result.branchName, taskId: result.id, description: result.description },
1424
+ ]);
1425
+ mergedBranchForNestedPatches = mergeResult.merged.includes(result.branchName);
1426
+ changesApplied = mergeResult.failed.length === 0;
1427
+ hadAnyChanges = changesApplied && mergeResult.merged.length > 0;
1428
+
1429
+ if (changesApplied) {
1430
+ mergeSummary = hadAnyChanges
1431
+ ? `\n\nMerged branch: ${result.branchName}`
1432
+ : "\n\nNo changes to apply.";
1433
+ } else {
1434
+ const conflictPart = mergeResult.conflict ? `\nConflict: ${mergeResult.conflict}` : "";
1435
+ mergeSummary = `\n\n<system-notification>Branch merge failed: ${result.branchName}.${conflictPart}\nThe unmerged branch remains for manual resolution.</system-notification>`;
1436
+ }
1437
+ if (mergeResult.stashConflict) {
1438
+ mergeSummary += `\n\n<system-notification>${mergeResult.stashConflict}</system-notification>`;
1439
+ }
1440
+
1441
+ // Clean up the merged branch (keep failed ones for manual resolution)
1442
+ if (changesApplied) {
1443
+ await cleanupTaskBranches(repoRoot, [result.branchName]);
1444
+ }
1445
+ }
1446
+ } else {
1447
+ // Patch mode: apply the patch from a successful run. A failed or
1448
+ // aborted run has nothing to apply and must not block the result.
1449
+ const succeeded = result.exitCode === 0 && !result.error && !result.aborted;
1450
+ if (!succeeded) {
1451
+ changesApplied = true;
1452
+ hadAnyChanges = false;
1453
+ } else if (!result.patchPath) {
1454
+ changesApplied = false;
1455
+ hadAnyChanges = false;
1456
+ } else {
1457
+ const patchText = await Bun.file(result.patchPath).text();
1458
+ if (!patchText.trim()) {
1459
+ changesApplied = true;
1460
+ hadAnyChanges = false;
1461
+ } else {
1462
+ const normalized = patchText.endsWith("\n") ? patchText : `${patchText}\n`;
1463
+ changesApplied = await git.patch.canApplyText(repoRoot, normalized);
1464
+ if (changesApplied) {
1465
+ try {
1466
+ await git.patch.applyText(repoRoot, normalized);
1467
+ hadAnyChanges = true;
1468
+ } catch {
1469
+ changesApplied = false;
1470
+ hadAnyChanges = false;
1471
+ }
1472
+ }
1473
+ }
1474
+ }
1475
+
1476
+ if (changesApplied) {
1477
+ mergeSummary = hadAnyChanges ? "\n\nApplied patches: yes" : "\n\nNo changes to apply.";
1478
+ } else {
1479
+ const notification =
1480
+ "<system-notification>Patches were not applied and must be handled manually.</system-notification>";
1481
+ const patchList = result.patchPath ? `\n\nPatch artifact:\n- ${result.patchPath}` : "";
1482
+ mergeSummary = `\n\n${notification}${patchList}`;
1483
+ }
1484
+ }
1485
+ } catch (mergeErr) {
1486
+ const msg = mergeErr instanceof Error ? mergeErr.message : String(mergeErr);
1487
+ changesApplied = false;
1488
+ hadAnyChanges = false;
1489
+ mergeSummary = `\n\n<system-notification>Merge phase failed: ${msg}\nTask outputs are preserved but changes were not applied.</system-notification>`;
1490
+ }
1491
+ }
1492
+
1493
+ // Apply nested repo patches (separate from parent git)
1494
+ if (isIsolated && repoRoot && (mergeMode === "branch" || changesApplied !== false)) {
1495
+ const nestedPatches = result.nestedPatches ?? [];
1496
+ const eligible =
1497
+ nestedPatches.length > 0 &&
1498
+ result.exitCode === 0 &&
1499
+ !result.aborted &&
1500
+ (mergeMode !== "branch" || mergedBranchForNestedPatches);
1501
+ if (eligible) {
1502
+ try {
1503
+ await applyNestedPatches(repoRoot, nestedPatches, buildCommitMessageFn());
1504
+ } catch {
1505
+ // Nested patch failures are non-fatal to the parent merge
1506
+ mergeSummary +=
1507
+ "\n\n<system-notification>Some nested repository patches failed to apply.</system-notification>";
1508
+ }
1509
+ }
1510
+ }
1511
+
1512
+ // Cleanup temp directory if used
1513
+ const shouldCleanupTempArtifacts =
1514
+ tempArtifactsDir && (!isIsolated || changesApplied === true || changesApplied === null);
1515
+ if (shouldCleanupTempArtifacts) {
1516
+ await fs.rm(tempArtifactsDir, { recursive: true, force: true });
1517
+ }
1518
+
1519
+ return this.#buildResultPayload(result, projectAgentsDir, Date.now() - startTime, mergeSummary);
1520
+ } catch (err) {
1521
+ return {
1522
+ content: [{ type: "text", text: `Task execution failed: ${err}` }],
1523
+ details: { projectAgentsDir, results: [], totalDurationMs: Date.now() - startTime },
1524
+ };
1525
+ }
1526
+ }
1527
+
1528
+ /** Build the tool result (summary text + details) for a settled run. */
1529
+ #buildResultPayload(
1530
+ result: SingleResult,
1531
+ projectAgentsDir: string | null,
1532
+ totalDurationMs: number,
1533
+ mergeSummary: string,
1534
+ ): AgentToolResult<TaskToolDetails> {
1535
+ const status = result.aborted
1536
+ ? "cancelled"
1537
+ : result.exitCode === 0 && result.error
1538
+ ? "merge failed"
1539
+ : result.exitCode === 0
1540
+ ? "completed"
1541
+ : `failed (exit ${result.exitCode})`;
1542
+ const output = formatResultOutputFallback(result);
1543
+ const outputCharCount = result.outputMeta?.charCount ?? output.length;
1544
+ const fullOutputThreshold = 5000;
1545
+ let preview = output;
1546
+ let truncated = false;
1547
+ if (outputCharCount > fullOutputThreshold) {
1548
+ const slice = output.slice(0, fullOutputThreshold);
1549
+ const lastNewline = slice.lastIndexOf("\n");
1550
+ preview = lastNewline >= 0 ? slice.slice(0, lastNewline) : slice;
1551
+ truncated = true;
1552
+ }
1553
+ const summary = prompt.render(taskSummaryTemplate, {
1554
+ agentName: result.agent,
1555
+ id: result.id,
1556
+ status,
1557
+ duration: formatDuration(totalDurationMs),
1558
+ preview,
1559
+ truncated,
1560
+ meta: result.outputMeta
1561
+ ? {
1562
+ lineCount: result.outputMeta.lineCount,
1563
+ charSize: formatBytes(result.outputMeta.charCount),
1564
+ }
1565
+ : undefined,
1566
+ mergeSummary,
1567
+ });
1568
+
1569
+ return {
1570
+ content: [{ type: "text", text: summary }],
1571
+ details: {
1572
+ projectAgentsDir,
1573
+ results: [result],
1574
+ totalDurationMs,
1575
+ usage: result.usage,
1576
+ outputPaths: result.outputPath ? [result.outputPath] : undefined,
1577
+ },
1578
+ };
1579
+ }
1580
+ }