@f5-sales-demo/xcsh 19.51.2

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 (899) hide show
  1. package/CHANGELOG.md +7073 -0
  2. package/README.md +14 -0
  3. package/examples/README.md +21 -0
  4. package/examples/custom-tools/README.md +109 -0
  5. package/examples/custom-tools/hello/index.ts +20 -0
  6. package/examples/custom-tools/todo/index.ts +206 -0
  7. package/examples/extensions/README.md +143 -0
  8. package/examples/extensions/api-demo.ts +89 -0
  9. package/examples/extensions/chalk-logger.ts +25 -0
  10. package/examples/extensions/hello.ts +32 -0
  11. package/examples/extensions/pirate.ts +43 -0
  12. package/examples/extensions/plan-mode.ts +551 -0
  13. package/examples/extensions/reload-runtime.ts +37 -0
  14. package/examples/extensions/todo.ts +296 -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 +16 -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 +43 -0
  34. package/examples/sdk/04-skills.ts +43 -0
  35. package/examples/sdk/06-extensions.ts +80 -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/README.md +172 -0
  43. package/package.json +539 -0
  44. package/scripts/build-info/resolvers.ts +51 -0
  45. package/scripts/capture-ax-fixture.ts +84 -0
  46. package/scripts/capture-login-fixture.ts +30 -0
  47. package/scripts/check-workflow-field-coverage.ts +101 -0
  48. package/scripts/extension-uat-harness.ts +340 -0
  49. package/scripts/format-prompts.ts +68 -0
  50. package/scripts/generate-api-spec-index.ts +580 -0
  51. package/scripts/generate-branding-index.ts +81 -0
  52. package/scripts/generate-build-info.ts +106 -0
  53. package/scripts/generate-console-catalog.ts +88 -0
  54. package/scripts/generate-console-field-metadata.ts +74 -0
  55. package/scripts/generate-docs-index.ts +40 -0
  56. package/scripts/generate-template.ts +32 -0
  57. package/scripts/generate-terraform-index.ts +81 -0
  58. package/scripts/mermaid-gallery.ts +132 -0
  59. package/scripts/uat-matrix-modalities.ts +451 -0
  60. package/scripts/uat-matrix-report.ts +175 -0
  61. package/scripts/uat-matrix.ts +353 -0
  62. package/src/async/index.ts +2 -0
  63. package/src/async/job-manager.ts +416 -0
  64. package/src/async/support.ts +5 -0
  65. package/src/autoresearch/apply-contract-to-state.ts +1 -0
  66. package/src/autoresearch/command-resume.md +17 -0
  67. package/src/autoresearch/contract.ts +205 -0
  68. package/src/autoresearch/dashboard.ts +374 -0
  69. package/src/autoresearch/git.ts +191 -0
  70. package/src/autoresearch/helpers.ts +328 -0
  71. package/src/autoresearch/index.ts +402 -0
  72. package/src/autoresearch/prompt.md +236 -0
  73. package/src/autoresearch/resume-message.md +16 -0
  74. package/src/autoresearch/state.ts +303 -0
  75. package/src/autoresearch/tools/init-experiment.ts +400 -0
  76. package/src/autoresearch/tools/log-experiment.ts +793 -0
  77. package/src/autoresearch/tools/run-experiment.ts +679 -0
  78. package/src/autoresearch/types.ts +114 -0
  79. package/src/browser/acquire.ts +249 -0
  80. package/src/browser/actions.ts +126 -0
  81. package/src/browser/auth.ts +176 -0
  82. package/src/browser/ax.ts +134 -0
  83. package/src/browser/cdp-core.ts +45 -0
  84. package/src/browser/cdp-page-actions.ts +51 -0
  85. package/src/browser/chrome-locate.ts +66 -0
  86. package/src/browser/dom-context.ts +89 -0
  87. package/src/browser/dt-context.ts +100 -0
  88. package/src/browser/extension-bridge.ts +182 -0
  89. package/src/browser/extension-page-actions.ts +397 -0
  90. package/src/browser/extension-provider.ts +373 -0
  91. package/src/browser/index.ts +17 -0
  92. package/src/browser/input-commit.ts +74 -0
  93. package/src/browser/native-messaging.ts +20 -0
  94. package/src/browser/page-actions.ts +18 -0
  95. package/src/browser/provider.ts +155 -0
  96. package/src/browser/resolver.ts +126 -0
  97. package/src/browser/selector.ts +40 -0
  98. package/src/bun-imports.d.ts +22 -0
  99. package/src/capability/context-file.ts +43 -0
  100. package/src/capability/extension-module.ts +34 -0
  101. package/src/capability/extension.ts +47 -0
  102. package/src/capability/fs.ts +107 -0
  103. package/src/capability/hook.ts +40 -0
  104. package/src/capability/index.ts +438 -0
  105. package/src/capability/instruction.ts +37 -0
  106. package/src/capability/mcp.ts +74 -0
  107. package/src/capability/prompt.ts +35 -0
  108. package/src/capability/rule.ts +224 -0
  109. package/src/capability/settings.ts +34 -0
  110. package/src/capability/skill.ts +50 -0
  111. package/src/capability/slash-command.ts +40 -0
  112. package/src/capability/ssh.ts +41 -0
  113. package/src/capability/system-prompt.ts +34 -0
  114. package/src/capability/tool.ts +38 -0
  115. package/src/capability/types.ts +168 -0
  116. package/src/cli/agents-cli.ts +138 -0
  117. package/src/cli/args.ts +286 -0
  118. package/src/cli/chrome-cli.ts +88 -0
  119. package/src/cli/classify-install-target.ts +50 -0
  120. package/src/cli/commands/init-xdg.ts +27 -0
  121. package/src/cli/config-cli.ts +418 -0
  122. package/src/cli/file-processor.ts +121 -0
  123. package/src/cli/grep-cli.ts +160 -0
  124. package/src/cli/grievances-cli.ts +78 -0
  125. package/src/cli/initial-message.ts +58 -0
  126. package/src/cli/jupyter-cli.ts +106 -0
  127. package/src/cli/list-models.ts +128 -0
  128. package/src/cli/plugin-cli.ts +964 -0
  129. package/src/cli/read-cli.ts +68 -0
  130. package/src/cli/session-picker.ts +52 -0
  131. package/src/cli/setup-cli.ts +479 -0
  132. package/src/cli/shell-cli.ts +174 -0
  133. package/src/cli/ssh-cli.ts +179 -0
  134. package/src/cli/stats-cli.ts +182 -0
  135. package/src/cli/update-cli.ts +446 -0
  136. package/src/cli/web-search-cli.ts +203 -0
  137. package/src/cli.ts +123 -0
  138. package/src/commands/agents.ts +57 -0
  139. package/src/commands/chrome-host.ts +71 -0
  140. package/src/commands/chrome.ts +28 -0
  141. package/src/commands/commit.ts +36 -0
  142. package/src/commands/config.ts +51 -0
  143. package/src/commands/grep.ts +48 -0
  144. package/src/commands/grievances.ts +20 -0
  145. package/src/commands/jupyter.ts +32 -0
  146. package/src/commands/launch.ts +144 -0
  147. package/src/commands/plugin.ts +78 -0
  148. package/src/commands/read.ts +33 -0
  149. package/src/commands/setup.ts +42 -0
  150. package/src/commands/shell.ts +29 -0
  151. package/src/commands/ssh.ts +60 -0
  152. package/src/commands/stats.ts +29 -0
  153. package/src/commands/update.ts +21 -0
  154. package/src/commands/web-search.ts +46 -0
  155. package/src/commit/agentic/agent.ts +314 -0
  156. package/src/commit/agentic/fallback.ts +96 -0
  157. package/src/commit/agentic/index.ts +354 -0
  158. package/src/commit/agentic/prompts/analyze-file.md +22 -0
  159. package/src/commit/agentic/prompts/session-user.md +25 -0
  160. package/src/commit/agentic/prompts/split-confirm.md +1 -0
  161. package/src/commit/agentic/prompts/system.md +38 -0
  162. package/src/commit/agentic/state.ts +60 -0
  163. package/src/commit/agentic/tools/analyze-file.ts +127 -0
  164. package/src/commit/agentic/tools/git-file-diff.ts +191 -0
  165. package/src/commit/agentic/tools/git-hunk.ts +50 -0
  166. package/src/commit/agentic/tools/git-overview.ts +81 -0
  167. package/src/commit/agentic/tools/index.ts +54 -0
  168. package/src/commit/agentic/tools/propose-changelog.ts +139 -0
  169. package/src/commit/agentic/tools/propose-commit.ts +122 -0
  170. package/src/commit/agentic/tools/recent-commits.ts +81 -0
  171. package/src/commit/agentic/tools/schemas.ts +31 -0
  172. package/src/commit/agentic/tools/split-commit.ts +251 -0
  173. package/src/commit/agentic/topo-sort.ts +44 -0
  174. package/src/commit/agentic/trivial.ts +51 -0
  175. package/src/commit/agentic/validation.ts +183 -0
  176. package/src/commit/analysis/conventional.ts +122 -0
  177. package/src/commit/analysis/index.ts +4 -0
  178. package/src/commit/analysis/scope.ts +242 -0
  179. package/src/commit/analysis/summary.ts +105 -0
  180. package/src/commit/analysis/validation.ts +66 -0
  181. package/src/commit/changelog/detect.ts +40 -0
  182. package/src/commit/changelog/generate.ts +101 -0
  183. package/src/commit/changelog/index.ts +234 -0
  184. package/src/commit/changelog/parse.ts +44 -0
  185. package/src/commit/cli.ts +85 -0
  186. package/src/commit/git/diff.ts +148 -0
  187. package/src/commit/index.ts +5 -0
  188. package/src/commit/map-reduce/index.ts +69 -0
  189. package/src/commit/map-reduce/map-phase.ts +193 -0
  190. package/src/commit/map-reduce/reduce-phase.ts +108 -0
  191. package/src/commit/map-reduce/utils.ts +9 -0
  192. package/src/commit/message.ts +11 -0
  193. package/src/commit/model-selection.ts +66 -0
  194. package/src/commit/pipeline.ts +242 -0
  195. package/src/commit/prompts/analysis-system.md +148 -0
  196. package/src/commit/prompts/analysis-user.md +38 -0
  197. package/src/commit/prompts/changelog-system.md +50 -0
  198. package/src/commit/prompts/changelog-user.md +18 -0
  199. package/src/commit/prompts/file-observer-system.md +24 -0
  200. package/src/commit/prompts/file-observer-user.md +8 -0
  201. package/src/commit/prompts/reduce-system.md +50 -0
  202. package/src/commit/prompts/reduce-user.md +17 -0
  203. package/src/commit/prompts/summary-retry.md +3 -0
  204. package/src/commit/prompts/summary-system.md +38 -0
  205. package/src/commit/prompts/summary-user.md +13 -0
  206. package/src/commit/prompts/types-description.md +2 -0
  207. package/src/commit/types.ts +118 -0
  208. package/src/commit/utils/exclusions.ts +42 -0
  209. package/src/commit/utils.ts +44 -0
  210. package/src/config/auto-config.ts +698 -0
  211. package/src/config/context-schema.json +115 -0
  212. package/src/config/file-lock.ts +121 -0
  213. package/src/config/keybindings.ts +493 -0
  214. package/src/config/mcp-schema.json +230 -0
  215. package/src/config/model-equivalence.ts +675 -0
  216. package/src/config/model-registry.ts +2265 -0
  217. package/src/config/model-resolver.ts +1289 -0
  218. package/src/config/prompt-templates.ts +271 -0
  219. package/src/config/resolve-config-value.ts +110 -0
  220. package/src/config/settings-schema.ts +2155 -0
  221. package/src/config/settings.ts +730 -0
  222. package/src/config.ts +418 -0
  223. package/src/cursor.ts +323 -0
  224. package/src/dap/client.ts +674 -0
  225. package/src/dap/config.ts +150 -0
  226. package/src/dap/defaults.json +211 -0
  227. package/src/dap/index.ts +4 -0
  228. package/src/dap/session.ts +1255 -0
  229. package/src/dap/types.ts +600 -0
  230. package/src/debug/index.ts +440 -0
  231. package/src/debug/log-formatting.ts +58 -0
  232. package/src/debug/log-viewer.ts +908 -0
  233. package/src/debug/profiler.ts +158 -0
  234. package/src/debug/report-bundle.ts +365 -0
  235. package/src/debug/system-info.ts +107 -0
  236. package/src/discovery/agents-md.ts +67 -0
  237. package/src/discovery/agents.ts +219 -0
  238. package/src/discovery/builtin.ts +851 -0
  239. package/src/discovery/claude-plugins.ts +297 -0
  240. package/src/discovery/claude.ts +543 -0
  241. package/src/discovery/cline.ts +83 -0
  242. package/src/discovery/codex.ts +535 -0
  243. package/src/discovery/cursor.ts +220 -0
  244. package/src/discovery/gemini.ts +396 -0
  245. package/src/discovery/github.ts +118 -0
  246. package/src/discovery/helpers.ts +934 -0
  247. package/src/discovery/index.ts +79 -0
  248. package/src/discovery/language.ts +46 -0
  249. package/src/discovery/mcp-json.ts +171 -0
  250. package/src/discovery/opencode.ts +393 -0
  251. package/src/discovery/plugin-dir-roots.ts +28 -0
  252. package/src/discovery/ssh.ts +153 -0
  253. package/src/discovery/substitute-plugin-root.ts +29 -0
  254. package/src/discovery/vscode.ts +105 -0
  255. package/src/discovery/windsurf.ts +147 -0
  256. package/src/edit/diff.ts +818 -0
  257. package/src/edit/index.ts +481 -0
  258. package/src/edit/line-hash.ts +67 -0
  259. package/src/edit/modes/chunk.ts +762 -0
  260. package/src/edit/modes/hashline.ts +1366 -0
  261. package/src/edit/modes/patch.ts +1791 -0
  262. package/src/edit/modes/replace.ts +1115 -0
  263. package/src/edit/normalize.ts +375 -0
  264. package/src/edit/renderer.ts +627 -0
  265. package/src/exa/factory.ts +61 -0
  266. package/src/exa/index.ts +27 -0
  267. package/src/exa/mcp-client.ts +293 -0
  268. package/src/exa/render.ts +232 -0
  269. package/src/exa/researcher.ts +47 -0
  270. package/src/exa/search.ts +86 -0
  271. package/src/exa/types.ts +166 -0
  272. package/src/exa/websets.ts +247 -0
  273. package/src/exec/bash-executor.ts +332 -0
  274. package/src/exec/exec.ts +53 -0
  275. package/src/exec/idle-timeout-watchdog.ts +126 -0
  276. package/src/exec/non-interactive-env.ts +48 -0
  277. package/src/export/custom-share.ts +65 -0
  278. package/src/export/html/index.ts +161 -0
  279. package/src/export/html/template.css +1001 -0
  280. package/src/export/html/template.generated.ts +2 -0
  281. package/src/export/html/template.html +46 -0
  282. package/src/export/html/template.js +1950 -0
  283. package/src/export/html/template.macro.ts +24 -0
  284. package/src/export/html/vendor/highlight.min.js +1213 -0
  285. package/src/export/html/vendor/marked.min.js +6 -0
  286. package/src/export/ttsr.ts +434 -0
  287. package/src/extensibility/custom-commands/bundled/ci-green/index.ts +25 -0
  288. package/src/extensibility/custom-commands/bundled/review/index.ts +456 -0
  289. package/src/extensibility/custom-commands/index.ts +2 -0
  290. package/src/extensibility/custom-commands/loader.ts +236 -0
  291. package/src/extensibility/custom-commands/types.ts +111 -0
  292. package/src/extensibility/custom-tools/index.ts +7 -0
  293. package/src/extensibility/custom-tools/loader.ts +238 -0
  294. package/src/extensibility/custom-tools/types.ts +251 -0
  295. package/src/extensibility/custom-tools/wrapper.ts +47 -0
  296. package/src/extensibility/extensions/index.ts +15 -0
  297. package/src/extensibility/extensions/loader.ts +572 -0
  298. package/src/extensibility/extensions/runner.ts +848 -0
  299. package/src/extensibility/extensions/types.ts +1394 -0
  300. package/src/extensibility/extensions/wrapper.ts +191 -0
  301. package/src/extensibility/hooks/index.ts +5 -0
  302. package/src/extensibility/hooks/loader.ts +255 -0
  303. package/src/extensibility/hooks/runner.ts +425 -0
  304. package/src/extensibility/hooks/tool-wrapper.ts +108 -0
  305. package/src/extensibility/hooks/types.ts +826 -0
  306. package/src/extensibility/plugins/doctor.ts +66 -0
  307. package/src/extensibility/plugins/git-url.ts +281 -0
  308. package/src/extensibility/plugins/index.ts +9 -0
  309. package/src/extensibility/plugins/installer.ts +192 -0
  310. package/src/extensibility/plugins/loader.ts +267 -0
  311. package/src/extensibility/plugins/manager.ts +731 -0
  312. package/src/extensibility/plugins/marketplace/cache.ts +136 -0
  313. package/src/extensibility/plugins/marketplace/fetcher.ts +318 -0
  314. package/src/extensibility/plugins/marketplace/index.ts +6 -0
  315. package/src/extensibility/plugins/marketplace/manager.ts +781 -0
  316. package/src/extensibility/plugins/marketplace/prerequisites.ts +255 -0
  317. package/src/extensibility/plugins/marketplace/registry.ts +196 -0
  318. package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
  319. package/src/extensibility/plugins/marketplace/types.ts +201 -0
  320. package/src/extensibility/plugins/parser.ts +105 -0
  321. package/src/extensibility/plugins/types.ts +194 -0
  322. package/src/extensibility/skills.ts +269 -0
  323. package/src/extensibility/slash-commands.ts +246 -0
  324. package/src/extensibility/tool-proxy.ts +25 -0
  325. package/src/extensibility/utils.ts +38 -0
  326. package/src/index.ts +61 -0
  327. package/src/internal-urls/agent-protocol.ts +136 -0
  328. package/src/internal-urls/api-catalog-resolve.ts +495 -0
  329. package/src/internal-urls/api-catalog-types.ts +94 -0
  330. package/src/internal-urls/api-spec-resolve.ts +1036 -0
  331. package/src/internal-urls/api-spec-types.ts +239 -0
  332. package/src/internal-urls/artifact-protocol.ts +97 -0
  333. package/src/internal-urls/branding-index.generated.ts +88 -0
  334. package/src/internal-urls/build-info-runtime.ts +302 -0
  335. package/src/internal-urls/build-info.generated.ts +33 -0
  336. package/src/internal-urls/computer-profile.ts +692 -0
  337. package/src/internal-urls/console-catalog-types.ts +21 -0
  338. package/src/internal-urls/console-catalog.generated.ts +532 -0
  339. package/src/internal-urls/console-field-metadata-types.ts +59 -0
  340. package/src/internal-urls/console-field-metadata.generated.ts +4841 -0
  341. package/src/internal-urls/console-resolve.ts +178 -0
  342. package/src/internal-urls/docs-index.generated.ts +698 -0
  343. package/src/internal-urls/extension-api.md +147 -0
  344. package/src/internal-urls/index.ts +46 -0
  345. package/src/internal-urls/jobs-protocol.ts +119 -0
  346. package/src/internal-urls/json-query.ts +126 -0
  347. package/src/internal-urls/local-protocol.ts +206 -0
  348. package/src/internal-urls/mcp-protocol.ts +156 -0
  349. package/src/internal-urls/memory-protocol.ts +133 -0
  350. package/src/internal-urls/parse.ts +72 -0
  351. package/src/internal-urls/profile-collectors.ts +106 -0
  352. package/src/internal-urls/router.ts +55 -0
  353. package/src/internal-urls/rule-protocol.ts +55 -0
  354. package/src/internal-urls/skill-protocol.ts +111 -0
  355. package/src/internal-urls/terraform-index.generated.ts +1852 -0
  356. package/src/internal-urls/terraform-resolve.ts +184 -0
  357. package/src/internal-urls/terraform-types.ts +45 -0
  358. package/src/internal-urls/types.ts +52 -0
  359. package/src/internal-urls/user-profile.ts +363 -0
  360. package/src/internal-urls/xcsh-protocol.ts +644 -0
  361. package/src/ipy/cancellation.ts +28 -0
  362. package/src/ipy/executor.ts +1155 -0
  363. package/src/ipy/gateway-coordinator.ts +424 -0
  364. package/src/ipy/kernel.ts +1091 -0
  365. package/src/ipy/modules.ts +144 -0
  366. package/src/ipy/prelude.py +849 -0
  367. package/src/ipy/prelude.ts +3 -0
  368. package/src/ipy/runtime.ts +221 -0
  369. package/src/locales/ar.json +512 -0
  370. package/src/locales/de.json +512 -0
  371. package/src/locales/en.json +549 -0
  372. package/src/locales/es.json +512 -0
  373. package/src/locales/fr.json +512 -0
  374. package/src/locales/hi.json +512 -0
  375. package/src/locales/index.ts +29 -0
  376. package/src/locales/it.json +512 -0
  377. package/src/locales/ja.json +512 -0
  378. package/src/locales/ko.json +512 -0
  379. package/src/locales/pt-br.json +512 -0
  380. package/src/locales/th.json +512 -0
  381. package/src/locales/zh-cn.json +512 -0
  382. package/src/locales/zh-tw.json +512 -0
  383. package/src/lsp/client.ts +941 -0
  384. package/src/lsp/clients/biome-client.ts +202 -0
  385. package/src/lsp/clients/index.ts +50 -0
  386. package/src/lsp/clients/lsp-linter-client.ts +93 -0
  387. package/src/lsp/clients/swiftlint-client.ts +120 -0
  388. package/src/lsp/config.ts +418 -0
  389. package/src/lsp/defaults.json +999 -0
  390. package/src/lsp/edits.ts +109 -0
  391. package/src/lsp/index.ts +1746 -0
  392. package/src/lsp/lspmux.ts +233 -0
  393. package/src/lsp/render.ts +692 -0
  394. package/src/lsp/startup-events.ts +13 -0
  395. package/src/lsp/types.ts +444 -0
  396. package/src/lsp/utils.ts +691 -0
  397. package/src/main.ts +944 -0
  398. package/src/mcp/client.ts +482 -0
  399. package/src/mcp/config-writer.ts +225 -0
  400. package/src/mcp/config.ts +365 -0
  401. package/src/mcp/discoverable-tool-metadata.ts +202 -0
  402. package/src/mcp/index.ts +29 -0
  403. package/src/mcp/json-rpc.ts +84 -0
  404. package/src/mcp/loader.ts +124 -0
  405. package/src/mcp/manager.ts +1152 -0
  406. package/src/mcp/oauth-discovery.ts +349 -0
  407. package/src/mcp/oauth-flow.ts +387 -0
  408. package/src/mcp/render.ts +157 -0
  409. package/src/mcp/smithery-auth.ts +104 -0
  410. package/src/mcp/smithery-connect.ts +145 -0
  411. package/src/mcp/smithery-registry.ts +477 -0
  412. package/src/mcp/tool-bridge.ts +417 -0
  413. package/src/mcp/tool-cache.ts +117 -0
  414. package/src/mcp/transports/http.ts +475 -0
  415. package/src/mcp/transports/index.ts +6 -0
  416. package/src/mcp/transports/stdio.ts +325 -0
  417. package/src/mcp/types.ts +423 -0
  418. package/src/memories/index.ts +1115 -0
  419. package/src/memories/storage.ts +577 -0
  420. package/src/modes/acp/acp-agent.ts +1361 -0
  421. package/src/modes/acp/acp-event-mapper.ts +538 -0
  422. package/src/modes/acp/acp-mode.ts +15 -0
  423. package/src/modes/acp/index.ts +2 -0
  424. package/src/modes/components/agent-dashboard.ts +1124 -0
  425. package/src/modes/components/assistant-message.ts +213 -0
  426. package/src/modes/components/bash-execution.ts +345 -0
  427. package/src/modes/components/bordered-loader.ts +41 -0
  428. package/src/modes/components/branch-summary-message.ts +45 -0
  429. package/src/modes/components/btw-panel.ts +103 -0
  430. package/src/modes/components/compaction-summary-message.ts +51 -0
  431. package/src/modes/components/context-add-wizard.ts +534 -0
  432. package/src/modes/components/countdown-timer.ts +75 -0
  433. package/src/modes/components/custom-editor.ts +238 -0
  434. package/src/modes/components/custom-message.ts +91 -0
  435. package/src/modes/components/diff.ts +210 -0
  436. package/src/modes/components/dynamic-border.ts +25 -0
  437. package/src/modes/components/extensions/extension-dashboard.ts +326 -0
  438. package/src/modes/components/extensions/extension-list.ts +492 -0
  439. package/src/modes/components/extensions/index.ts +9 -0
  440. package/src/modes/components/extensions/inspector-panel.ts +317 -0
  441. package/src/modes/components/extensions/state-manager.ts +587 -0
  442. package/src/modes/components/extensions/types.ts +191 -0
  443. package/src/modes/components/footer.ts +262 -0
  444. package/src/modes/components/gutter-block.ts +315 -0
  445. package/src/modes/components/history-search.ts +158 -0
  446. package/src/modes/components/hook-editor.ts +151 -0
  447. package/src/modes/components/hook-input.ts +81 -0
  448. package/src/modes/components/hook-message.ts +100 -0
  449. package/src/modes/components/hook-selector.ts +192 -0
  450. package/src/modes/components/index.ts +36 -0
  451. package/src/modes/components/keybinding-hints.ts +65 -0
  452. package/src/modes/components/login-dialog.ts +164 -0
  453. package/src/modes/components/mcp-add-wizard.ts +1314 -0
  454. package/src/modes/components/model-selector.ts +946 -0
  455. package/src/modes/components/oauth-selector.ts +211 -0
  456. package/src/modes/components/plugin-selector.ts +95 -0
  457. package/src/modes/components/plugin-settings.ts +477 -0
  458. package/src/modes/components/plugins/index.ts +5 -0
  459. package/src/modes/components/plugins/plugin-dashboard.ts +523 -0
  460. package/src/modes/components/plugins/plugin-inspector-pane.ts +84 -0
  461. package/src/modes/components/plugins/plugin-list-pane.ts +109 -0
  462. package/src/modes/components/plugins/state-manager.ts +229 -0
  463. package/src/modes/components/plugins/types.ts +51 -0
  464. package/src/modes/components/plugins/utils.ts +6 -0
  465. package/src/modes/components/python-execution.ts +244 -0
  466. package/src/modes/components/queue-mode-selector.ts +56 -0
  467. package/src/modes/components/read-tool-group.ts +137 -0
  468. package/src/modes/components/session-observer-overlay.ts +483 -0
  469. package/src/modes/components/session-selector.ts +343 -0
  470. package/src/modes/components/settings-defs.ts +568 -0
  471. package/src/modes/components/settings-selector.ts +641 -0
  472. package/src/modes/components/show-images-selector.ts +45 -0
  473. package/src/modes/components/skill-message.ts +90 -0
  474. package/src/modes/components/status-line/context-gradient.ts +64 -0
  475. package/src/modes/components/status-line/git-utils.ts +42 -0
  476. package/src/modes/components/status-line/hex-ansi.ts +29 -0
  477. package/src/modes/components/status-line/index.ts +4 -0
  478. package/src/modes/components/status-line/presets.ts +174 -0
  479. package/src/modes/components/status-line/segments.ts +494 -0
  480. package/src/modes/components/status-line/separators.ts +55 -0
  481. package/src/modes/components/status-line/token-rate.ts +66 -0
  482. package/src/modes/components/status-line/types.ts +96 -0
  483. package/src/modes/components/status-line-segment-editor.ts +361 -0
  484. package/src/modes/components/status-line.ts +729 -0
  485. package/src/modes/components/theme-selector.ts +63 -0
  486. package/src/modes/components/thinking-selector.ts +52 -0
  487. package/src/modes/components/todo-reminder.ts +54 -0
  488. package/src/modes/components/tool-execution.ts +781 -0
  489. package/src/modes/components/tree-selector.ts +908 -0
  490. package/src/modes/components/ttsr-notification.ts +80 -0
  491. package/src/modes/components/user-message-selector.ts +141 -0
  492. package/src/modes/components/user-message.ts +100 -0
  493. package/src/modes/components/visual-truncate.ts +63 -0
  494. package/src/modes/components/welcome-checks.ts +313 -0
  495. package/src/modes/components/welcome.ts +270 -0
  496. package/src/modes/controllers/btw-controller.ts +193 -0
  497. package/src/modes/controllers/chord-routing.ts +37 -0
  498. package/src/modes/controllers/command-controller.ts +1293 -0
  499. package/src/modes/controllers/context-command-controller.ts +61 -0
  500. package/src/modes/controllers/event-controller.ts +743 -0
  501. package/src/modes/controllers/extension-ui-controller.ts +983 -0
  502. package/src/modes/controllers/input-controller.ts +877 -0
  503. package/src/modes/controllers/mcp-command-controller.ts +1940 -0
  504. package/src/modes/controllers/selector-controller.ts +1292 -0
  505. package/src/modes/controllers/ssh-command-controller.ts +421 -0
  506. package/src/modes/index.ts +34 -0
  507. package/src/modes/interactive-mode.ts +1781 -0
  508. package/src/modes/oauth-manual-input.ts +42 -0
  509. package/src/modes/print-mode.ts +196 -0
  510. package/src/modes/prompt-action-autocomplete.ts +231 -0
  511. package/src/modes/rpc/host-tools.ts +186 -0
  512. package/src/modes/rpc/rpc-client.ts +762 -0
  513. package/src/modes/rpc/rpc-mode.ts +877 -0
  514. package/src/modes/rpc/rpc-types.ts +322 -0
  515. package/src/modes/session-observer-registry.ts +146 -0
  516. package/src/modes/shared.ts +30 -0
  517. package/src/modes/theme/defaults/index.ts +7 -0
  518. package/src/modes/theme/defaults/xcsh-dark.json +113 -0
  519. package/src/modes/theme/defaults/xcsh-light.json +115 -0
  520. package/src/modes/theme/mermaid-cache.ts +151 -0
  521. package/src/modes/theme/mermaid-palette.ts +39 -0
  522. package/src/modes/theme/theme-schema.json +553 -0
  523. package/src/modes/theme/theme.ts +2563 -0
  524. package/src/modes/types.ts +273 -0
  525. package/src/modes/utils/hotkeys-markdown.ts +60 -0
  526. package/src/modes/utils/keybinding-matchers.ts +30 -0
  527. package/src/modes/utils/read-group-outcome-aggregator.ts +55 -0
  528. package/src/modes/utils/sanitize-error-message.ts +60 -0
  529. package/src/modes/utils/tools-markdown.ts +28 -0
  530. package/src/modes/utils/ui-helpers.ts +734 -0
  531. package/src/plan-mode/approved-plan.ts +55 -0
  532. package/src/plan-mode/state.ts +6 -0
  533. package/src/priority.json +37 -0
  534. package/src/prompts/agents/designer.md +67 -0
  535. package/src/prompts/agents/explore.md +61 -0
  536. package/src/prompts/agents/frontmatter.md +10 -0
  537. package/src/prompts/agents/init.md +36 -0
  538. package/src/prompts/agents/librarian.md +121 -0
  539. package/src/prompts/agents/plan.md +49 -0
  540. package/src/prompts/agents/reviewer.md +127 -0
  541. package/src/prompts/agents/task.md +16 -0
  542. package/src/prompts/ci-green-request.md +35 -0
  543. package/src/prompts/compaction/branch-summary-context.md +5 -0
  544. package/src/prompts/compaction/branch-summary-preamble.md +2 -0
  545. package/src/prompts/compaction/branch-summary.md +30 -0
  546. package/src/prompts/compaction/compaction-short-summary.md +9 -0
  547. package/src/prompts/compaction/compaction-summary-context.md +5 -0
  548. package/src/prompts/compaction/compaction-summary.md +38 -0
  549. package/src/prompts/compaction/compaction-turn-prefix.md +17 -0
  550. package/src/prompts/compaction/compaction-update-summary.md +45 -0
  551. package/src/prompts/memories/consolidation.md +30 -0
  552. package/src/prompts/memories/read-path.md +11 -0
  553. package/src/prompts/memories/stage_one_input.md +6 -0
  554. package/src/prompts/memories/stage_one_system.md +21 -0
  555. package/src/prompts/review-request.md +70 -0
  556. package/src/prompts/system/agent-creation-architect.md +65 -0
  557. package/src/prompts/system/agent-creation-user.md +6 -0
  558. package/src/prompts/system/auto-handoff-threshold-focus.md +1 -0
  559. package/src/prompts/system/btw-user.md +8 -0
  560. package/src/prompts/system/commit-message-system.md +2 -0
  561. package/src/prompts/system/custom-system-prompt.md +82 -0
  562. package/src/prompts/system/eager-todo.md +13 -0
  563. package/src/prompts/system/file-operations.md +10 -0
  564. package/src/prompts/system/handoff-document.md +48 -0
  565. package/src/prompts/system/plan-mode-active.md +114 -0
  566. package/src/prompts/system/plan-mode-approved.md +23 -0
  567. package/src/prompts/system/plan-mode-reference.md +14 -0
  568. package/src/prompts/system/plan-mode-subagent.md +34 -0
  569. package/src/prompts/system/plan-mode-tool-decision-reminder.md +9 -0
  570. package/src/prompts/system/subagent-submit-reminder.md +7 -0
  571. package/src/prompts/system/subagent-system-prompt.md +36 -0
  572. package/src/prompts/system/subagent-user-prompt.md +12 -0
  573. package/src/prompts/system/summarization-system.md +3 -0
  574. package/src/prompts/system/system-prompt.md +698 -0
  575. package/src/prompts/system/title-system.md +2 -0
  576. package/src/prompts/system/ttsr-interrupt.md +7 -0
  577. package/src/prompts/system/web-search.md +28 -0
  578. package/src/prompts/tools/ask.md +28 -0
  579. package/src/prompts/tools/ast-edit.md +48 -0
  580. package/src/prompts/tools/ast-grep.md +54 -0
  581. package/src/prompts/tools/async-result.md +5 -0
  582. package/src/prompts/tools/bash.md +67 -0
  583. package/src/prompts/tools/browser.md +26 -0
  584. package/src/prompts/tools/calculator.md +10 -0
  585. package/src/prompts/tools/cancel-job.md +5 -0
  586. package/src/prompts/tools/catalog-workflow-runner.md +13 -0
  587. package/src/prompts/tools/checkpoint.md +16 -0
  588. package/src/prompts/tools/chunk-edit.md +279 -0
  589. package/src/prompts/tools/debug.md +43 -0
  590. package/src/prompts/tools/display-image.md +23 -0
  591. package/src/prompts/tools/exit-plan-mode.md +41 -0
  592. package/src/prompts/tools/find.md +26 -0
  593. package/src/prompts/tools/gemini-image.md +7 -0
  594. package/src/prompts/tools/grep.md +29 -0
  595. package/src/prompts/tools/hashline.md +131 -0
  596. package/src/prompts/tools/inspect-image-system.md +20 -0
  597. package/src/prompts/tools/inspect-image.md +32 -0
  598. package/src/prompts/tools/lsp.md +33 -0
  599. package/src/prompts/tools/patch.md +77 -0
  600. package/src/prompts/tools/poll.md +5 -0
  601. package/src/prompts/tools/python.md +60 -0
  602. package/src/prompts/tools/read-chunk.md +35 -0
  603. package/src/prompts/tools/read.md +63 -0
  604. package/src/prompts/tools/render-mermaid.md +9 -0
  605. package/src/prompts/tools/replace.md +36 -0
  606. package/src/prompts/tools/resolve.md +8 -0
  607. package/src/prompts/tools/rewind.md +13 -0
  608. package/src/prompts/tools/search-tool-bm25.md +34 -0
  609. package/src/prompts/tools/ssh.md +44 -0
  610. package/src/prompts/tools/task-summary.md +28 -0
  611. package/src/prompts/tools/task.md +131 -0
  612. package/src/prompts/tools/todo-write.md +89 -0
  613. package/src/prompts/tools/vim.md +98 -0
  614. package/src/prompts/tools/web-search.md +10 -0
  615. package/src/prompts/tools/write.md +14 -0
  616. package/src/prompts/tools/xcsh-api.md +283 -0
  617. package/src/resource-management/index.ts +42 -0
  618. package/src/sdk.ts +2123 -0
  619. package/src/secrets/index.ts +146 -0
  620. package/src/secrets/obfuscator.ts +290 -0
  621. package/src/secrets/regex.ts +21 -0
  622. package/src/services/context-env.ts +102 -0
  623. package/src/services/xcsh-api-client.ts +230 -0
  624. package/src/services/xcsh-context-command.ts +803 -0
  625. package/src/services/xcsh-context-display.ts +49 -0
  626. package/src/services/xcsh-context-indicators.ts +17 -0
  627. package/src/services/xcsh-context-segment.ts +39 -0
  628. package/src/services/xcsh-context.ts +1410 -0
  629. package/src/services/xcsh-env.ts +107 -0
  630. package/src/services/xcsh-knowledge.ts +177 -0
  631. package/src/services/xcsh-table.ts +164 -0
  632. package/src/session/agent-session.ts +6690 -0
  633. package/src/session/agent-storage.ts +451 -0
  634. package/src/session/artifacts.ts +132 -0
  635. package/src/session/auth-storage.ts +17 -0
  636. package/src/session/blob-store.ts +135 -0
  637. package/src/session/compaction/branch-summarization.ts +322 -0
  638. package/src/session/compaction/compaction.ts +1388 -0
  639. package/src/session/compaction/index.ts +7 -0
  640. package/src/session/compaction/pruning.ts +91 -0
  641. package/src/session/compaction/utils.ts +184 -0
  642. package/src/session/history-storage.ts +253 -0
  643. package/src/session/messages.ts +597 -0
  644. package/src/session/session-dump-format.ts +203 -0
  645. package/src/session/session-manager.ts +2816 -0
  646. package/src/session/session-storage.ts +370 -0
  647. package/src/session/streaming-output.ts +770 -0
  648. package/src/session/tool-choice-queue.ts +213 -0
  649. package/src/slash-commands/builtin-registry.ts +1614 -0
  650. package/src/slash-commands/export-command.ts +178 -0
  651. package/src/slash-commands/marketplace-install-parser.ts +99 -0
  652. package/src/slash-commands/resource-commands.ts +250 -0
  653. package/src/ssh/config-writer.ts +183 -0
  654. package/src/ssh/connection-manager.ts +445 -0
  655. package/src/ssh/ssh-executor.ts +131 -0
  656. package/src/ssh/sshfs-mount.ts +137 -0
  657. package/src/ssh/utils.ts +8 -0
  658. package/src/stt/downloader.ts +71 -0
  659. package/src/stt/index.ts +3 -0
  660. package/src/stt/recorder.ts +351 -0
  661. package/src/stt/setup.ts +52 -0
  662. package/src/stt/stt-controller.ts +160 -0
  663. package/src/stt/transcribe.py +70 -0
  664. package/src/stt/transcriber.ts +91 -0
  665. package/src/system-prompt.ts +688 -0
  666. package/src/task/agents.ts +166 -0
  667. package/src/task/commands.ts +131 -0
  668. package/src/task/discovery.ts +126 -0
  669. package/src/task/executor.ts +1324 -0
  670. package/src/task/index.ts +1197 -0
  671. package/src/task/isolation-backend.ts +72 -0
  672. package/src/task/name-generator.ts +1577 -0
  673. package/src/task/output-manager.ts +107 -0
  674. package/src/task/parallel.ts +116 -0
  675. package/src/task/render.ts +1035 -0
  676. package/src/task/subprocess-tool-registry.ts +88 -0
  677. package/src/task/template.ts +33 -0
  678. package/src/task/types.ts +230 -0
  679. package/src/task/worktree.ts +580 -0
  680. package/src/task/xcsh-command.ts +26 -0
  681. package/src/thinking.ts +87 -0
  682. package/src/tools/action-renderer.ts +198 -0
  683. package/src/tools/archive-reader.ts +315 -0
  684. package/src/tools/ask.ts +791 -0
  685. package/src/tools/ast-edit.ts +492 -0
  686. package/src/tools/ast-grep.ts +453 -0
  687. package/src/tools/auto-generated-guard.ts +305 -0
  688. package/src/tools/bash-interactive.ts +383 -0
  689. package/src/tools/bash-interceptor.ts +67 -0
  690. package/src/tools/bash-normalize.ts +107 -0
  691. package/src/tools/bash-skill-urls.ts +246 -0
  692. package/src/tools/bash.ts +878 -0
  693. package/src/tools/browser-renderer.ts +129 -0
  694. package/src/tools/browser.ts +1366 -0
  695. package/src/tools/calculator.ts +543 -0
  696. package/src/tools/cancel-job.ts +100 -0
  697. package/src/tools/catalog-workflow-runner.ts +718 -0
  698. package/src/tools/checkpoint.ts +133 -0
  699. package/src/tools/context.ts +39 -0
  700. package/src/tools/debug.ts +1004 -0
  701. package/src/tools/display-image-renderer.ts +96 -0
  702. package/src/tools/display-image.ts +109 -0
  703. package/src/tools/exit-plan-mode.ts +101 -0
  704. package/src/tools/fetch.ts +1462 -0
  705. package/src/tools/find.ts +437 -0
  706. package/src/tools/fs-cache-invalidation.ts +33 -0
  707. package/src/tools/gemini-image.ts +1004 -0
  708. package/src/tools/grep.ts +705 -0
  709. package/src/tools/index.ts +442 -0
  710. package/src/tools/inspect-image-renderer.ts +101 -0
  711. package/src/tools/inspect-image.ts +176 -0
  712. package/src/tools/json-tree.ts +266 -0
  713. package/src/tools/jtd-to-json-schema.ts +199 -0
  714. package/src/tools/jtd-to-typescript.ts +136 -0
  715. package/src/tools/jtd-utils.ts +102 -0
  716. package/src/tools/list-limit.ts +40 -0
  717. package/src/tools/mermaid-renderer.ts +127 -0
  718. package/src/tools/notebook.ts +288 -0
  719. package/src/tools/output-meta.ts +588 -0
  720. package/src/tools/path-utils.ts +560 -0
  721. package/src/tools/plan-mode-guard.ts +41 -0
  722. package/src/tools/poll-tool.ts +177 -0
  723. package/src/tools/puppeteer/00_stealth_tampering.txt +63 -0
  724. package/src/tools/puppeteer/01_stealth_activity.txt +20 -0
  725. package/src/tools/puppeteer/02_stealth_hairline.txt +11 -0
  726. package/src/tools/puppeteer/03_stealth_botd.txt +384 -0
  727. package/src/tools/puppeteer/04_stealth_iframe.txt +81 -0
  728. package/src/tools/puppeteer/05_stealth_webgl.txt +75 -0
  729. package/src/tools/puppeteer/06_stealth_screen.txt +72 -0
  730. package/src/tools/puppeteer/07_stealth_fonts.txt +97 -0
  731. package/src/tools/puppeteer/08_stealth_audio.txt +51 -0
  732. package/src/tools/puppeteer/09_stealth_locale.txt +46 -0
  733. package/src/tools/puppeteer/10_stealth_plugins.txt +206 -0
  734. package/src/tools/puppeteer/11_stealth_hardware.txt +8 -0
  735. package/src/tools/puppeteer/12_stealth_codecs.txt +40 -0
  736. package/src/tools/puppeteer/13_stealth_worker.txt +74 -0
  737. package/src/tools/python.ts +1184 -0
  738. package/src/tools/read.ts +1591 -0
  739. package/src/tools/render-mermaid.ts +93 -0
  740. package/src/tools/render-utils.ts +677 -0
  741. package/src/tools/renderers.ts +82 -0
  742. package/src/tools/report-tool-issue.ts +80 -0
  743. package/src/tools/resolve.ts +196 -0
  744. package/src/tools/review.ts +238 -0
  745. package/src/tools/search-tool-bm25.ts +288 -0
  746. package/src/tools/sqlite-reader.ts +623 -0
  747. package/src/tools/ssh.ts +322 -0
  748. package/src/tools/submit-result.ts +229 -0
  749. package/src/tools/todo-render.ts +33 -0
  750. package/src/tools/todo-write.ts +440 -0
  751. package/src/tools/tool-errors.ts +62 -0
  752. package/src/tools/tool-result.ts +93 -0
  753. package/src/tools/tool-timeouts.ts +30 -0
  754. package/src/tools/vim.ts +981 -0
  755. package/src/tools/write.ts +671 -0
  756. package/src/tools/xcsh-api-renderer.ts +402 -0
  757. package/src/tools/xcsh-api.ts +887 -0
  758. package/src/tui/code-cell.ts +101 -0
  759. package/src/tui/file-list.ts +47 -0
  760. package/src/tui/index.ts +11 -0
  761. package/src/tui/output-block.ts +175 -0
  762. package/src/tui/status-line.ts +39 -0
  763. package/src/tui/tree-list.ts +84 -0
  764. package/src/tui/types.ts +15 -0
  765. package/src/tui/utils.ts +103 -0
  766. package/src/utils/changelog.ts +98 -0
  767. package/src/utils/clipboard.ts +80 -0
  768. package/src/utils/command-args.ts +76 -0
  769. package/src/utils/commit-message-generator.ts +137 -0
  770. package/src/utils/edit-mode.ts +50 -0
  771. package/src/utils/event-bus.ts +33 -0
  772. package/src/utils/external-editor.ts +65 -0
  773. package/src/utils/file-display-mode.ts +37 -0
  774. package/src/utils/file-mentions.ts +376 -0
  775. package/src/utils/fuzzy.ts +108 -0
  776. package/src/utils/git.ts +1495 -0
  777. package/src/utils/gitstatus.ts +140 -0
  778. package/src/utils/image-convert.ts +27 -0
  779. package/src/utils/image-loading.ts +98 -0
  780. package/src/utils/image-passthrough.ts +118 -0
  781. package/src/utils/image-resize.ts +272 -0
  782. package/src/utils/image-viewer.ts +17 -0
  783. package/src/utils/lang-from-path.ts +239 -0
  784. package/src/utils/markit.ts +81 -0
  785. package/src/utils/open.ts +20 -0
  786. package/src/utils/session-color.ts +55 -0
  787. package/src/utils/shell-snapshot.ts +188 -0
  788. package/src/utils/title-generator.ts +193 -0
  789. package/src/utils/tool-choice.ts +28 -0
  790. package/src/utils/tools-manager.ts +356 -0
  791. package/src/vim/buffer.ts +309 -0
  792. package/src/vim/commands.ts +382 -0
  793. package/src/vim/engine.ts +2426 -0
  794. package/src/vim/parser.ts +151 -0
  795. package/src/vim/render.ts +252 -0
  796. package/src/vim/types.ts +197 -0
  797. package/src/web/kagi.ts +174 -0
  798. package/src/web/parallel.ts +346 -0
  799. package/src/web/scrapers/artifacthub.ts +207 -0
  800. package/src/web/scrapers/arxiv.ts +83 -0
  801. package/src/web/scrapers/aur.ts +162 -0
  802. package/src/web/scrapers/biorxiv.ts +133 -0
  803. package/src/web/scrapers/bluesky.ts +262 -0
  804. package/src/web/scrapers/brew.ts +172 -0
  805. package/src/web/scrapers/cheatsh.ts +68 -0
  806. package/src/web/scrapers/chocolatey.ts +196 -0
  807. package/src/web/scrapers/choosealicense.ts +95 -0
  808. package/src/web/scrapers/cisa-kev.ts +87 -0
  809. package/src/web/scrapers/clojars.ts +154 -0
  810. package/src/web/scrapers/coingecko.ts +177 -0
  811. package/src/web/scrapers/crates-io.ts +110 -0
  812. package/src/web/scrapers/crossref.ts +136 -0
  813. package/src/web/scrapers/devto.ts +147 -0
  814. package/src/web/scrapers/discogs.ts +306 -0
  815. package/src/web/scrapers/discourse.ts +197 -0
  816. package/src/web/scrapers/dockerhub.ts +138 -0
  817. package/src/web/scrapers/docs-rs.ts +653 -0
  818. package/src/web/scrapers/fdroid.ts +134 -0
  819. package/src/web/scrapers/firefox-addons.ts +191 -0
  820. package/src/web/scrapers/flathub.ts +223 -0
  821. package/src/web/scrapers/github-gist.ts +58 -0
  822. package/src/web/scrapers/github.ts +452 -0
  823. package/src/web/scrapers/gitlab.ts +401 -0
  824. package/src/web/scrapers/go-pkg.ts +266 -0
  825. package/src/web/scrapers/hackage.ts +140 -0
  826. package/src/web/scrapers/hackernews.ts +189 -0
  827. package/src/web/scrapers/hex.ts +105 -0
  828. package/src/web/scrapers/huggingface.ts +321 -0
  829. package/src/web/scrapers/iacr.ts +89 -0
  830. package/src/web/scrapers/index.ts +252 -0
  831. package/src/web/scrapers/jetbrains-marketplace.ts +159 -0
  832. package/src/web/scrapers/lemmy.ts +203 -0
  833. package/src/web/scrapers/lobsters.ts +175 -0
  834. package/src/web/scrapers/mastodon.ts +292 -0
  835. package/src/web/scrapers/maven.ts +138 -0
  836. package/src/web/scrapers/mdn.ts +169 -0
  837. package/src/web/scrapers/metacpan.ts +222 -0
  838. package/src/web/scrapers/musicbrainz.ts +250 -0
  839. package/src/web/scrapers/npm.ts +98 -0
  840. package/src/web/scrapers/nuget.ts +183 -0
  841. package/src/web/scrapers/nvd.ts +222 -0
  842. package/src/web/scrapers/ollama.ts +239 -0
  843. package/src/web/scrapers/open-vsx.ts +106 -0
  844. package/src/web/scrapers/opencorporates.ts +292 -0
  845. package/src/web/scrapers/openlibrary.ts +336 -0
  846. package/src/web/scrapers/orcid.ts +286 -0
  847. package/src/web/scrapers/osv.ts +176 -0
  848. package/src/web/scrapers/packagist.ts +160 -0
  849. package/src/web/scrapers/pub-dev.ts +143 -0
  850. package/src/web/scrapers/pubmed.ts +211 -0
  851. package/src/web/scrapers/pypi.ts +112 -0
  852. package/src/web/scrapers/rawg.ts +110 -0
  853. package/src/web/scrapers/readthedocs.ts +120 -0
  854. package/src/web/scrapers/reddit.ts +95 -0
  855. package/src/web/scrapers/repology.ts +251 -0
  856. package/src/web/scrapers/rfc.ts +201 -0
  857. package/src/web/scrapers/rubygems.ts +103 -0
  858. package/src/web/scrapers/searchcode.ts +190 -0
  859. package/src/web/scrapers/sec-edgar.ts +261 -0
  860. package/src/web/scrapers/semantic-scholar.ts +171 -0
  861. package/src/web/scrapers/snapcraft.ts +187 -0
  862. package/src/web/scrapers/sourcegraph.ts +336 -0
  863. package/src/web/scrapers/spdx.ts +108 -0
  864. package/src/web/scrapers/spotify.ts +198 -0
  865. package/src/web/scrapers/stackoverflow.ts +120 -0
  866. package/src/web/scrapers/terraform.ts +277 -0
  867. package/src/web/scrapers/tldr.ts +47 -0
  868. package/src/web/scrapers/twitter.ts +93 -0
  869. package/src/web/scrapers/types.ts +267 -0
  870. package/src/web/scrapers/utils.ts +109 -0
  871. package/src/web/scrapers/vimeo.ts +133 -0
  872. package/src/web/scrapers/vscode-marketplace.ts +187 -0
  873. package/src/web/scrapers/w3c.ts +156 -0
  874. package/src/web/scrapers/wikidata.ts +344 -0
  875. package/src/web/scrapers/wikipedia.ts +84 -0
  876. package/src/web/scrapers/youtube.ts +313 -0
  877. package/src/web/search/errors.ts +120 -0
  878. package/src/web/search/index.ts +346 -0
  879. package/src/web/search/params.ts +129 -0
  880. package/src/web/search/provider.ts +97 -0
  881. package/src/web/search/providers/anthropic.ts +339 -0
  882. package/src/web/search/providers/base.ts +35 -0
  883. package/src/web/search/providers/brave.ts +150 -0
  884. package/src/web/search/providers/codex.ts +402 -0
  885. package/src/web/search/providers/exa.ts +264 -0
  886. package/src/web/search/providers/firecrawl.ts +115 -0
  887. package/src/web/search/providers/gemini.ts +566 -0
  888. package/src/web/search/providers/jina.ts +99 -0
  889. package/src/web/search/providers/kagi.ts +70 -0
  890. package/src/web/search/providers/kimi.ts +157 -0
  891. package/src/web/search/providers/parallel.ts +63 -0
  892. package/src/web/search/providers/perplexity.ts +546 -0
  893. package/src/web/search/providers/synthetic.ts +113 -0
  894. package/src/web/search/providers/tavily.ts +162 -0
  895. package/src/web/search/providers/utils.ts +36 -0
  896. package/src/web/search/providers/zai.ts +311 -0
  897. package/src/web/search/render.ts +348 -0
  898. package/src/web/search/types.ts +438 -0
  899. package/src/web/search/utils.ts +17 -0
@@ -0,0 +1,1324 @@
1
+ /**
2
+ * In-process execution for subagents.
3
+ *
4
+ * Runs each subagent on the main thread and forwards AgentEvents for progress tracking.
5
+ */
6
+ import path from "node:path";
7
+ import type { AgentEvent, ThinkingLevel } from "@f5xc-salesdemos/pi-agent-core";
8
+ import { logger, prompt, untilAborted } from "@f5xc-salesdemos/pi-utils";
9
+ import type { TSchema } from "@sinclair/typebox";
10
+ import Ajv, { type ValidateFunction } from "ajv";
11
+ import { ModelRegistry } from "../config/model-registry";
12
+ import { resolveModelOverride } from "../config/model-resolver";
13
+ import type { PromptTemplate } from "../config/prompt-templates";
14
+ import { Settings } from "../config/settings";
15
+ import { SETTINGS_SCHEMA, type SettingPath } from "../config/settings-schema";
16
+ import type { CustomTool } from "../extensibility/custom-tools/types";
17
+ import type { Skill } from "../extensibility/skills";
18
+ import { callTool } from "../mcp/client";
19
+ import type { MCPManager } from "../mcp/manager";
20
+ import submitReminderTemplate from "../prompts/system/subagent-submit-reminder.md" with { type: "text" };
21
+ import subagentSystemPromptTemplate from "../prompts/system/subagent-system-prompt.md" with { type: "text" };
22
+ import { createAgentSession, discoverAuthStorage } from "../sdk";
23
+ import type { AgentSession, AgentSessionEvent } from "../session/agent-session";
24
+ import type { AuthStorage } from "../session/auth-storage";
25
+ import { SessionManager } from "../session/session-manager";
26
+ import { type ContextFileEntry, truncateTail } from "../tools";
27
+ import { jtdToJsonSchema } from "../tools/jtd-to-json-schema";
28
+ import { ToolAbortError } from "../tools/tool-errors";
29
+ import type { EventBus } from "../utils/event-bus";
30
+ import { buildNamedToolChoice } from "../utils/tool-choice";
31
+ import { subprocessToolRegistry } from "./subprocess-tool-registry";
32
+ import {
33
+ type AgentDefinition,
34
+ type AgentProgress,
35
+ MAX_OUTPUT_BYTES,
36
+ MAX_OUTPUT_LINES,
37
+ type ReviewFinding,
38
+ type SingleResult,
39
+ TASK_SUBAGENT_EVENT_CHANNEL,
40
+ TASK_SUBAGENT_LIFECYCLE_CHANNEL,
41
+ TASK_SUBAGENT_PROGRESS_CHANNEL,
42
+ } from "./types";
43
+
44
+ /** Opaque handle for the fuzzy-search database (removed from pi-natives in upstream). */
45
+ type SearchDb = unknown;
46
+
47
+ const MCP_CALL_TIMEOUT_MS = 60_000;
48
+ const ajv = new Ajv({ allErrors: true, strict: false, logger: false });
49
+
50
+ /** Agent event types to forward for progress tracking. */
51
+ const agentEventTypes = new Set<AgentEvent["type"]>([
52
+ "agent_start",
53
+ "agent_end",
54
+ "turn_start",
55
+ "turn_end",
56
+ "message_start",
57
+ "message_update",
58
+ "message_end",
59
+ "tool_execution_start",
60
+ "tool_execution_update",
61
+ "tool_execution_end",
62
+ ]);
63
+
64
+ const isAgentEvent = (event: AgentSessionEvent): event is AgentEvent =>
65
+ agentEventTypes.has(event.type as AgentEvent["type"]);
66
+
67
+ function normalizeModelPatterns(value: string | string[] | undefined): string[] {
68
+ if (!value) return [];
69
+ if (Array.isArray(value)) {
70
+ return value.map(entry => entry.trim()).filter(Boolean);
71
+ }
72
+ return value
73
+ .split(",")
74
+ .map(entry => entry.trim())
75
+ .filter(Boolean);
76
+ }
77
+
78
+ function withAbortTimeout<T>(promise: Promise<T>, timeoutMs: number, signal?: AbortSignal): Promise<T> {
79
+ if (signal?.aborted) {
80
+ return Promise.reject(new ToolAbortError());
81
+ }
82
+
83
+ const { promise: wrappedPromise, resolve, reject } = Promise.withResolvers<T>();
84
+ let settled = false;
85
+ const timeoutId = setTimeout(() => {
86
+ if (settled) return;
87
+ settled = true;
88
+ reject(new Error(`MCP tool call timed out after ${timeoutMs}ms`));
89
+ }, timeoutMs);
90
+
91
+ const onAbort = () => {
92
+ if (settled) return;
93
+ settled = true;
94
+ clearTimeout(timeoutId);
95
+ reject(new ToolAbortError());
96
+ };
97
+
98
+ if (signal) {
99
+ signal.addEventListener("abort", onAbort, { once: true });
100
+ }
101
+
102
+ promise.then(resolve, reject).finally(() => {
103
+ if (signal) signal.removeEventListener("abort", onAbort);
104
+ clearTimeout(timeoutId);
105
+ });
106
+
107
+ return wrappedPromise;
108
+ }
109
+
110
+ function getReportFindingKey(value: unknown): string | null {
111
+ if (!value || typeof value !== "object") return null;
112
+ const record = value as Record<string, unknown>;
113
+ const title = typeof record.title === "string" ? record.title : null;
114
+ const filePath = typeof record.file_path === "string" ? record.file_path : null;
115
+ const lineStart = typeof record.line_start === "number" ? record.line_start : null;
116
+ const lineEnd = typeof record.line_end === "number" ? record.line_end : null;
117
+ const priority = typeof record.priority === "string" ? record.priority : null;
118
+ if (!title || !filePath || lineStart === null || lineEnd === null) {
119
+ return null;
120
+ }
121
+ return `${filePath}:${lineStart}:${lineEnd}:${priority ?? ""}:${title}`;
122
+ }
123
+
124
+ /** Options for subagent execution */
125
+ export interface ExecutorOptions {
126
+ cwd: string;
127
+ worktree?: string;
128
+ agent: AgentDefinition;
129
+ task: string;
130
+ assignment?: string;
131
+ description?: string;
132
+ index: number;
133
+ id: string;
134
+ modelOverride?: string | string[];
135
+ thinkingLevel?: ThinkingLevel;
136
+ outputSchema?: unknown;
137
+ /** Parent task recursion depth (0 = top-level, 1 = first child, etc.) */
138
+ taskDepth?: number;
139
+ enableLsp?: boolean;
140
+ signal?: AbortSignal;
141
+ onProgress?: (progress: AgentProgress) => void;
142
+ sessionFile?: string | null;
143
+ persistArtifacts?: boolean;
144
+ artifactsDir?: string;
145
+ /** Path to parent conversation context file */
146
+ contextFile?: string;
147
+ eventBus?: EventBus;
148
+ contextFiles?: ContextFileEntry[];
149
+ skills?: Skill[];
150
+ promptTemplates?: PromptTemplate[];
151
+ mcpManager?: MCPManager;
152
+ authStorage?: AuthStorage;
153
+ modelRegistry?: ModelRegistry;
154
+ searchDb?: SearchDb;
155
+ settings?: Settings;
156
+ }
157
+
158
+ function parseStringifiedJson(value: unknown): unknown {
159
+ if (typeof value !== "string") return value;
160
+ const trimmed = value.trim();
161
+ if (!trimmed) return value;
162
+ if (!(trimmed.startsWith("{") || trimmed.startsWith("["))) return value;
163
+ try {
164
+ return JSON.parse(trimmed);
165
+ } catch {
166
+ return value;
167
+ }
168
+ }
169
+
170
+ function normalizeOutputSchema(schema: unknown): { normalized?: unknown; error?: string } {
171
+ if (schema === undefined || schema === null) return {};
172
+ if (typeof schema === "string") {
173
+ try {
174
+ return { normalized: JSON.parse(schema) };
175
+ } catch (err) {
176
+ return { error: err instanceof Error ? err.message : String(err) };
177
+ }
178
+ }
179
+ return { normalized: schema };
180
+ }
181
+
182
+ function buildOutputValidator(schema: unknown): { validate?: ValidateFunction; error?: string } {
183
+ const { normalized, error } = normalizeOutputSchema(schema);
184
+ if (error) return { error };
185
+ if (normalized === undefined) return {};
186
+ const jsonSchema = jtdToJsonSchema(normalized);
187
+ try {
188
+ return { validate: ajv.compile(jsonSchema as any) };
189
+ } catch (err) {
190
+ return { error: err instanceof Error ? err.message : String(err) };
191
+ }
192
+ }
193
+
194
+ function tryParseJsonOutput(text: string): unknown | undefined {
195
+ const trimmed = text.trim();
196
+ if (!trimmed) return undefined;
197
+ try {
198
+ return JSON.parse(trimmed);
199
+ } catch {
200
+ return undefined;
201
+ }
202
+ }
203
+
204
+ function extractCompletionData(parsed: unknown): unknown {
205
+ if (!parsed || typeof parsed !== "object") return parsed;
206
+ const record = parsed as Record<string, unknown>;
207
+ if ("data" in record) {
208
+ return record.data;
209
+ }
210
+ return parsed;
211
+ }
212
+
213
+ function normalizeCompleteData(data: unknown, reportFindings?: ReviewFinding[]): unknown {
214
+ let normalized = parseStringifiedJson(data ?? null);
215
+ if (
216
+ Array.isArray(reportFindings) &&
217
+ reportFindings.length > 0 &&
218
+ normalized &&
219
+ typeof normalized === "object" &&
220
+ !Array.isArray(normalized)
221
+ ) {
222
+ const record = normalized as Record<string, unknown>;
223
+ if (!("findings" in record)) {
224
+ normalized = { ...record, findings: reportFindings };
225
+ }
226
+ }
227
+ return normalized;
228
+ }
229
+
230
+ function resolveFallbackCompletion(rawOutput: string, outputSchema: unknown): { data: unknown } | null {
231
+ const parsed = tryParseJsonOutput(rawOutput);
232
+ if (parsed === undefined) return null;
233
+ const candidate = parseStringifiedJson(extractCompletionData(parsed));
234
+ if (candidate === undefined) return null;
235
+ const { validate, error } = buildOutputValidator(outputSchema);
236
+ if (error) return null;
237
+ if (validate && !validate(candidate)) return null;
238
+ return { data: candidate };
239
+ }
240
+
241
+ export interface SubmitResultItem {
242
+ data?: unknown;
243
+ status?: "success" | "aborted";
244
+ error?: string;
245
+ }
246
+
247
+ interface FinalizeSubprocessOutputArgs {
248
+ rawOutput: string;
249
+ exitCode: number;
250
+ stderr: string;
251
+ doneAborted: boolean;
252
+ signalAborted: boolean;
253
+ submitResultItems?: SubmitResultItem[];
254
+ reportFindings?: ReviewFinding[];
255
+ outputSchema: unknown;
256
+ }
257
+
258
+ interface FinalizeSubprocessOutputResult {
259
+ rawOutput: string;
260
+ exitCode: number;
261
+ stderr: string;
262
+ abortedViaSubmitResult: boolean;
263
+ hasSubmitResult: boolean;
264
+ }
265
+
266
+ export const SUBAGENT_WARNING_NULL_SUBMIT_RESULT = "SYSTEM WARNING: Subagent called submit_result with null data.";
267
+ export const SUBAGENT_WARNING_MISSING_SUBMIT_RESULT =
268
+ "SYSTEM WARNING: Subagent exited without calling submit_result tool after 3 reminders.";
269
+
270
+ export function finalizeSubprocessOutput(args: FinalizeSubprocessOutputArgs): FinalizeSubprocessOutputResult {
271
+ let { rawOutput, exitCode, stderr } = args;
272
+ const { submitResultItems, reportFindings, doneAborted, signalAborted, outputSchema } = args;
273
+ let abortedViaSubmitResult = false;
274
+ const hasSubmitResult = Array.isArray(submitResultItems) && submitResultItems.length > 0;
275
+
276
+ if (hasSubmitResult) {
277
+ const lastSubmitResult = submitResultItems[submitResultItems.length - 1];
278
+ if (lastSubmitResult?.status === "aborted") {
279
+ abortedViaSubmitResult = true;
280
+ exitCode = 0;
281
+ stderr = lastSubmitResult.error || "Subagent aborted task";
282
+ try {
283
+ rawOutput = JSON.stringify({ aborted: true, error: lastSubmitResult.error }, null, 2);
284
+ } catch {
285
+ rawOutput = `{"aborted":true,"error":"${lastSubmitResult.error || "Unknown error"}"}`;
286
+ }
287
+ } else {
288
+ const submitData = lastSubmitResult?.data;
289
+ if (submitData === null || submitData === undefined) {
290
+ rawOutput = rawOutput
291
+ ? `${SUBAGENT_WARNING_NULL_SUBMIT_RESULT}\n\n${rawOutput}`
292
+ : SUBAGENT_WARNING_NULL_SUBMIT_RESULT;
293
+ } else {
294
+ const completeData = normalizeCompleteData(submitData, reportFindings);
295
+ try {
296
+ rawOutput = JSON.stringify(completeData, null, 2) ?? "null";
297
+ } catch (err) {
298
+ const errorMessage = err instanceof Error ? err.message : String(err);
299
+ rawOutput = `{"error":"Failed to serialize submit_result data: ${errorMessage}"}`;
300
+ }
301
+ exitCode = 0;
302
+ stderr = "";
303
+ }
304
+ }
305
+ } else {
306
+ const allowFallback = exitCode === 0 && !doneAborted && !signalAborted;
307
+ const { normalized: normalizedSchema, error: schemaError } = normalizeOutputSchema(outputSchema);
308
+ const hasOutputSchema = normalizedSchema !== undefined && !schemaError;
309
+ const fallback = allowFallback ? resolveFallbackCompletion(rawOutput, outputSchema) : null;
310
+ if (fallback) {
311
+ const completeData = normalizeCompleteData(fallback.data, reportFindings);
312
+ try {
313
+ rawOutput = JSON.stringify(completeData, null, 2) ?? "null";
314
+ } catch (err) {
315
+ const errorMessage = err instanceof Error ? err.message : String(err);
316
+ rawOutput = `{"error":"Failed to serialize fallback completion: ${errorMessage}"}`;
317
+ }
318
+ exitCode = 0;
319
+ stderr = "";
320
+ } else if (!hasOutputSchema && allowFallback && rawOutput.trim().length > 0) {
321
+ exitCode = 0;
322
+ stderr = "";
323
+ } else if (exitCode === 0) {
324
+ rawOutput = rawOutput
325
+ ? `${SUBAGENT_WARNING_MISSING_SUBMIT_RESULT}\n\n${rawOutput}`
326
+ : SUBAGENT_WARNING_MISSING_SUBMIT_RESULT;
327
+ }
328
+
329
+ // Salvage output from aborted runs that produced content without calling submit_result
330
+ if (exitCode !== 0 && doneAborted && !signalAborted && rawOutput.trim().length > 0) {
331
+ if (hasOutputSchema) {
332
+ // Try schema-validated fallback: if the model produced valid JSON matching the schema,
333
+ // use it even though submit_result was never called
334
+ const abortFallback = resolveFallbackCompletion(rawOutput, outputSchema);
335
+ if (abortFallback) {
336
+ const completeData = normalizeCompleteData(abortFallback.data, reportFindings);
337
+ try {
338
+ rawOutput = JSON.stringify(completeData, null, 2) ?? "null";
339
+ } catch {
340
+ // Keep rawOutput as-is if serialization fails
341
+ }
342
+ exitCode = 0;
343
+ stderr = "";
344
+ }
345
+ } else {
346
+ // No schema required — raw text output is directly useful
347
+ exitCode = 0;
348
+ stderr = "";
349
+ }
350
+ }
351
+ }
352
+
353
+ return { rawOutput, exitCode, stderr, abortedViaSubmitResult, hasSubmitResult };
354
+ }
355
+
356
+ /**
357
+ * Extract a short preview from tool args for display.
358
+ */
359
+ function extractToolArgsPreview(args: Record<string, unknown>): string {
360
+ // Priority order for preview
361
+ const previewKeys = ["command", "file_path", "path", "pattern", "query", "url", "task", "prompt"];
362
+
363
+ for (const key of previewKeys) {
364
+ if (args[key] && typeof args[key] === "string") {
365
+ const value = args[key] as string;
366
+ return value.length > 60 ? `${value.slice(0, 59)}…` : value;
367
+ }
368
+ }
369
+
370
+ return "";
371
+ }
372
+
373
+ function getNumberField(record: Record<string, unknown>, key: string): number | undefined {
374
+ if (!Object.hasOwn(record, key)) return undefined;
375
+ const value = record[key];
376
+ return typeof value === "number" && Number.isFinite(value) ? value : 0;
377
+ }
378
+
379
+ function firstNumberField(record: Record<string, unknown>, keys: string[]): number | undefined {
380
+ for (const key of keys) {
381
+ const value = getNumberField(record, key);
382
+ if (value !== undefined) return value;
383
+ }
384
+ return undefined;
385
+ }
386
+
387
+ /**
388
+ * Normalize usage objects from different event formats.
389
+ */
390
+ function getUsageTokens(usage: unknown): number {
391
+ if (!usage || typeof usage !== "object") return 0;
392
+ const record = usage as Record<string, unknown>;
393
+
394
+ const totalTokens = firstNumberField(record, ["totalTokens", "total_tokens"]);
395
+ if (totalTokens !== undefined && totalTokens > 0) return totalTokens;
396
+
397
+ const input = firstNumberField(record, ["input", "input_tokens", "inputTokens"]) ?? 0;
398
+ const output = firstNumberField(record, ["output", "output_tokens", "outputTokens"]) ?? 0;
399
+ const cacheRead = firstNumberField(record, ["cacheRead", "cache_read", "cacheReadTokens"]) ?? 0;
400
+ const cacheWrite = firstNumberField(record, ["cacheWrite", "cache_write", "cacheWriteTokens"]) ?? 0;
401
+
402
+ return input + output + cacheRead + cacheWrite;
403
+ }
404
+
405
+ /**
406
+ * Create proxy tools that reuse the parent's MCP connections.
407
+ */
408
+ function createMCPProxyTools(mcpManager: MCPManager): CustomTool<TSchema>[] {
409
+ return mcpManager.getTools().map(tool => {
410
+ const mcpTool = tool as { mcpToolName?: string; mcpServerName?: string };
411
+ return {
412
+ name: tool.name,
413
+ label: tool.label ?? tool.name,
414
+ description: tool.description ?? "",
415
+ parameters: tool.parameters as TSchema,
416
+ execute: async (_toolCallId, params, _onUpdate, _ctx, signal) => {
417
+ if (signal?.aborted) {
418
+ throw new ToolAbortError();
419
+ }
420
+ const serverName = mcpTool.mcpServerName ?? "";
421
+ const mcpToolName = mcpTool.mcpToolName ?? "";
422
+ try {
423
+ const result = await withAbortTimeout(
424
+ (async () => {
425
+ const connection = await mcpManager.waitForConnection(serverName);
426
+ return callTool(connection, mcpToolName, params as Record<string, unknown>, { signal });
427
+ })(),
428
+ MCP_CALL_TIMEOUT_MS,
429
+ signal,
430
+ );
431
+ return {
432
+ content: (result.content ?? []).map(item =>
433
+ item.type === "text"
434
+ ? { type: "text" as const, text: item.text ?? "" }
435
+ : { type: "text" as const, text: JSON.stringify(item) },
436
+ ),
437
+ details: { serverName, mcpToolName, isError: result.isError },
438
+ };
439
+ } catch (error) {
440
+ if (error instanceof ToolAbortError) {
441
+ throw error;
442
+ }
443
+ return {
444
+ content: [
445
+ {
446
+ type: "text" as const,
447
+ text: `MCP error: ${error instanceof Error ? error.message : String(error)}`,
448
+ },
449
+ ],
450
+ details: { serverName, mcpToolName, isError: true },
451
+ };
452
+ }
453
+ },
454
+ };
455
+ });
456
+ }
457
+
458
+ function createSubagentSettings(baseSettings: Settings): Settings {
459
+ const snapshot: Partial<Record<SettingPath, unknown>> = {};
460
+ for (const key of Object.keys(SETTINGS_SCHEMA) as SettingPath[]) {
461
+ snapshot[key] = baseSettings.get(key);
462
+ }
463
+ return Settings.isolated({ ...snapshot, "async.enabled": false });
464
+ }
465
+
466
+ /**
467
+ * Run a single agent in-process.
468
+ */
469
+ export async function runSubprocess(options: ExecutorOptions): Promise<SingleResult> {
470
+ const {
471
+ cwd,
472
+ agent,
473
+ task,
474
+ assignment,
475
+ index,
476
+ id,
477
+ worktree,
478
+ modelOverride,
479
+ thinkingLevel,
480
+ outputSchema,
481
+ enableLsp,
482
+ signal,
483
+ onProgress,
484
+ } = options;
485
+ const startTime = Date.now();
486
+
487
+ // Initialize progress
488
+ const progress: AgentProgress = {
489
+ index,
490
+ id,
491
+ agent: agent.name,
492
+ agentSource: agent.source,
493
+ status: "running",
494
+ task,
495
+ assignment,
496
+ description: options.description,
497
+ lastIntent: undefined,
498
+ recentTools: [],
499
+ recentOutput: [],
500
+ toolCount: 0,
501
+ tokens: 0,
502
+ durationMs: 0,
503
+ modelOverride,
504
+ };
505
+
506
+ // Check if already aborted
507
+ if (signal?.aborted) {
508
+ return {
509
+ index,
510
+ id,
511
+ agent: agent.name,
512
+ agentSource: agent.source,
513
+ task,
514
+ assignment,
515
+ description: options.description,
516
+ exitCode: 1,
517
+ output: "",
518
+ stderr: "Cancelled before start",
519
+ truncated: false,
520
+ durationMs: 0,
521
+ tokens: 0,
522
+ modelOverride,
523
+ error: "Cancelled before start",
524
+ aborted: true,
525
+ abortReason: "Cancelled before start",
526
+ };
527
+ }
528
+
529
+ // Set up artifact paths and write input file upfront if artifacts dir provided
530
+ let subtaskSessionFile: string | undefined;
531
+ if (options.artifactsDir) {
532
+ subtaskSessionFile = path.join(options.artifactsDir, `${id}.jsonl`);
533
+ }
534
+
535
+ const settings = options.settings ?? Settings.isolated();
536
+ const subagentSettings = createSubagentSettings(settings);
537
+ const maxRecursionDepth = settings.get("task.maxRecursionDepth") ?? 2;
538
+ const parentDepth = options.taskDepth ?? 0;
539
+ const childDepth = parentDepth + 1;
540
+ const atMaxDepth = maxRecursionDepth >= 0 && childDepth >= maxRecursionDepth;
541
+
542
+ // Add tools if specified
543
+ let toolNames: string[] | undefined;
544
+ if (agent.tools && agent.tools.length > 0) {
545
+ toolNames = agent.tools;
546
+ // Auto-include task tool if spawns defined but task not in tools
547
+ if (agent.spawns !== undefined && !toolNames.includes("task") && !atMaxDepth) {
548
+ toolNames = [...toolNames, "task"];
549
+ }
550
+ }
551
+
552
+ if (atMaxDepth && toolNames?.includes("task")) {
553
+ toolNames = toolNames.filter(name => name !== "task");
554
+ }
555
+ const pythonToolMode = settings.get("python.toolMode") ?? "both";
556
+ if (toolNames?.includes("exec")) {
557
+ const expanded = toolNames.filter(name => name !== "exec");
558
+ if (pythonToolMode === "bash-only") {
559
+ expanded.push("bash");
560
+ } else if (pythonToolMode === "ipy-only") {
561
+ expanded.push("python");
562
+ } else {
563
+ expanded.push("python", "bash");
564
+ }
565
+ toolNames = Array.from(new Set(expanded));
566
+ }
567
+
568
+ const modelPatterns = normalizeModelPatterns(modelOverride ?? agent.model);
569
+ const sessionFile = subtaskSessionFile ?? null;
570
+ const spawnsEnv = atMaxDepth
571
+ ? ""
572
+ : agent.spawns === undefined
573
+ ? ""
574
+ : agent.spawns === "*"
575
+ ? "*"
576
+ : agent.spawns.join(",");
577
+
578
+ const lspEnabled = enableLsp ?? true;
579
+ const skipPythonPreflight = Array.isArray(toolNames) && !toolNames.includes("python");
580
+
581
+ const outputChunks: string[] = [];
582
+ const finalOutputChunks: string[] = [];
583
+ const RECENT_OUTPUT_TAIL_BYTES = 8 * 1024;
584
+ let recentOutputTail = "";
585
+ let stderr = "";
586
+ let resolved = false;
587
+ type AbortReason = "signal" | "terminate";
588
+ let abortSent = false;
589
+ let abortReason: AbortReason | undefined;
590
+ const listenerController = new AbortController();
591
+ const listenerSignal = listenerController.signal;
592
+ const abortController = new AbortController();
593
+ const abortSignal = abortController.signal;
594
+ let activeSession: AgentSession | null = null;
595
+ let unsubscribe: (() => void) | null = null;
596
+ let submitResultCalled = false;
597
+
598
+ // Accumulate usage incrementally from message_end events (no memory for streaming events)
599
+ const accumulatedUsage = {
600
+ input: 0,
601
+ output: 0,
602
+ cacheRead: 0,
603
+ cacheWrite: 0,
604
+ totalTokens: 0,
605
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
606
+ };
607
+ let hasUsage = false;
608
+
609
+ const requestAbort = (reason: AbortReason) => {
610
+ if (abortSent) {
611
+ if (reason === "signal" && abortReason !== "signal") {
612
+ abortReason = "signal";
613
+ }
614
+ return;
615
+ }
616
+ if (resolved) return;
617
+ abortSent = true;
618
+ abortReason = reason;
619
+ abortController.abort();
620
+ if (activeSession) {
621
+ void activeSession.abort();
622
+ }
623
+ };
624
+
625
+ // Handle abort signal
626
+ const onAbort = () => {
627
+ if (!resolved) requestAbort("signal");
628
+ };
629
+ if (signal) {
630
+ signal.addEventListener("abort", onAbort, { once: true, signal: listenerSignal });
631
+ }
632
+
633
+ const resolveSignalAbortReason = (): string => {
634
+ const reason = signal?.reason;
635
+ if (reason instanceof Error) {
636
+ const message = reason.message.trim();
637
+ if (message.length > 0) return message;
638
+ } else if (typeof reason === "string") {
639
+ const message = reason.trim();
640
+ if (message.length > 0) return message;
641
+ }
642
+ return "Cancelled by caller";
643
+ };
644
+ const PROGRESS_COALESCE_MS = 150;
645
+ let lastProgressEmitMs = 0;
646
+ let progressTimeoutId: NodeJS.Timeout | null = null;
647
+
648
+ const emitProgressNow = () => {
649
+ progress.durationMs = Date.now() - startTime;
650
+ onProgress?.({ ...progress });
651
+ if (options.eventBus) {
652
+ options.eventBus.emit(TASK_SUBAGENT_PROGRESS_CHANNEL, {
653
+ index,
654
+ agent: agent.name,
655
+ agentSource: agent.source,
656
+ task,
657
+ assignment,
658
+ progress: { ...progress },
659
+ sessionFile: subtaskSessionFile,
660
+ });
661
+ }
662
+ lastProgressEmitMs = Date.now();
663
+ };
664
+
665
+ const scheduleProgress = (flush = false) => {
666
+ if (flush) {
667
+ if (progressTimeoutId) {
668
+ clearTimeout(progressTimeoutId);
669
+ progressTimeoutId = null;
670
+ }
671
+ emitProgressNow();
672
+ return;
673
+ }
674
+ const now = Date.now();
675
+ const elapsed = now - lastProgressEmitMs;
676
+ if (lastProgressEmitMs === 0 || elapsed >= PROGRESS_COALESCE_MS) {
677
+ if (progressTimeoutId) {
678
+ clearTimeout(progressTimeoutId);
679
+ progressTimeoutId = null;
680
+ }
681
+ emitProgressNow();
682
+ return;
683
+ }
684
+ if (progressTimeoutId) return;
685
+ progressTimeoutId = setTimeout(() => {
686
+ progressTimeoutId = null;
687
+ emitProgressNow();
688
+ }, PROGRESS_COALESCE_MS - elapsed);
689
+ };
690
+
691
+ const getMessageContent = (message: unknown): unknown => {
692
+ if (message && typeof message === "object" && "content" in message) {
693
+ return (message as { content?: unknown }).content;
694
+ }
695
+ return undefined;
696
+ };
697
+
698
+ const getMessageUsage = (message: unknown): unknown => {
699
+ if (message && typeof message === "object" && "usage" in message) {
700
+ return (message as { usage?: unknown }).usage;
701
+ }
702
+ return undefined;
703
+ };
704
+
705
+ const updateRecentOutputLines = () => {
706
+ const lines = recentOutputTail.split("\n").filter(line => line.trim());
707
+ progress.recentOutput = lines.slice(-8).reverse();
708
+ };
709
+
710
+ const appendRecentOutputTail = (text: string) => {
711
+ if (!text) return;
712
+ recentOutputTail += text;
713
+ if (recentOutputTail.length > RECENT_OUTPUT_TAIL_BYTES) {
714
+ recentOutputTail = recentOutputTail.slice(-RECENT_OUTPUT_TAIL_BYTES);
715
+ }
716
+ updateRecentOutputLines();
717
+ };
718
+
719
+ const replaceRecentOutputFromContent = (content: unknown[]) => {
720
+ recentOutputTail = "";
721
+ for (const block of content) {
722
+ if (!block || typeof block !== "object") continue;
723
+ const record = block as { type?: unknown; text?: unknown };
724
+ if (record.type !== "text" || typeof record.text !== "string") continue;
725
+ if (!record.text) continue;
726
+ recentOutputTail += record.text;
727
+ if (recentOutputTail.length > RECENT_OUTPUT_TAIL_BYTES) {
728
+ recentOutputTail = recentOutputTail.slice(-RECENT_OUTPUT_TAIL_BYTES);
729
+ }
730
+ }
731
+ updateRecentOutputLines();
732
+ };
733
+
734
+ const resetRecentOutput = () => {
735
+ recentOutputTail = "";
736
+ progress.recentOutput = [];
737
+ };
738
+
739
+ const processEvent = (event: AgentEvent) => {
740
+ if (resolved) return;
741
+
742
+ if (options.eventBus) {
743
+ options.eventBus.emit(TASK_SUBAGENT_EVENT_CHANNEL, {
744
+ index,
745
+ agent: agent.name,
746
+ agentSource: agent.source,
747
+ task,
748
+ assignment,
749
+ event,
750
+ });
751
+ }
752
+
753
+ const now = Date.now();
754
+ let flushProgress = false;
755
+
756
+ switch (event.type) {
757
+ case "message_start":
758
+ if (event.message?.role === "assistant") {
759
+ resetRecentOutput();
760
+ }
761
+ break;
762
+
763
+ case "tool_execution_start": {
764
+ progress.toolCount++;
765
+ progress.currentTool = event.toolName;
766
+ progress.currentToolArgs = extractToolArgsPreview(
767
+ (event as { toolArgs?: Record<string, unknown> }).toolArgs || event.args || {},
768
+ );
769
+ progress.currentToolStartMs = now;
770
+ const intent = event.intent?.trim();
771
+ if (intent) {
772
+ progress.lastIntent = intent;
773
+ }
774
+ break;
775
+ }
776
+
777
+ case "tool_execution_end": {
778
+ if (progress.currentTool) {
779
+ progress.recentTools.unshift({
780
+ tool: progress.currentTool,
781
+ args: progress.currentToolArgs || "",
782
+ endMs: now,
783
+ });
784
+ // Keep only last 5
785
+ if (progress.recentTools.length > 5) {
786
+ progress.recentTools.pop();
787
+ }
788
+ }
789
+ progress.currentTool = undefined;
790
+ progress.currentToolArgs = undefined;
791
+ progress.currentToolStartMs = undefined;
792
+
793
+ // Check for registered subagent tool handler
794
+ const handler = subprocessToolRegistry.getHandler(event.toolName);
795
+ const eventArgs = (event as { args?: Record<string, unknown> }).args ?? {};
796
+ if (handler) {
797
+ // Extract data using handler
798
+ if (handler.extractData) {
799
+ const data = handler.extractData({
800
+ toolName: event.toolName,
801
+ toolCallId: event.toolCallId,
802
+ args: eventArgs,
803
+ result: event.result,
804
+ isError: event.isError,
805
+ });
806
+ if (data !== undefined) {
807
+ progress.extractedToolData = progress.extractedToolData || {};
808
+ const existing = progress.extractedToolData[event.toolName] || [];
809
+ const findingKey = event.toolName === "report_finding" ? getReportFindingKey(data) : null;
810
+ if (findingKey) {
811
+ const existingIndex = existing.findIndex(item => getReportFindingKey(item) === findingKey);
812
+ if (existingIndex >= 0) {
813
+ existing[existingIndex] = data;
814
+ } else {
815
+ existing.push(data);
816
+ }
817
+ } else {
818
+ existing.push(data);
819
+ }
820
+ progress.extractedToolData[event.toolName] = existing;
821
+ if (event.toolName === "submit_result") {
822
+ submitResultCalled = true;
823
+ }
824
+ }
825
+ }
826
+
827
+ // Check if handler wants to terminate the session
828
+ if (
829
+ handler.shouldTerminate?.({
830
+ toolName: event.toolName,
831
+ toolCallId: event.toolCallId,
832
+ args: eventArgs,
833
+ result: event.result,
834
+ isError: event.isError,
835
+ })
836
+ ) {
837
+ requestAbort("terminate");
838
+ }
839
+ }
840
+ flushProgress = true;
841
+ break;
842
+ }
843
+
844
+ case "message_update": {
845
+ if (event.message?.role !== "assistant") break;
846
+ const assistantEvent = (
847
+ event as AgentEvent & {
848
+ assistantMessageEvent?: { type?: string; delta?: string };
849
+ }
850
+ ).assistantMessageEvent;
851
+ if (assistantEvent?.type === "text_delta" && typeof assistantEvent.delta === "string") {
852
+ appendRecentOutputTail(assistantEvent.delta);
853
+ break;
854
+ }
855
+ if (assistantEvent && assistantEvent.type !== "text_delta") {
856
+ break;
857
+ }
858
+ const updateContent =
859
+ getMessageContent(event.message) || (event as AgentEvent & { content?: unknown }).content;
860
+ if (updateContent && Array.isArray(updateContent)) {
861
+ replaceRecentOutputFromContent(updateContent);
862
+ }
863
+ break;
864
+ }
865
+
866
+ case "message_end": {
867
+ // Extract text from assistant and toolResult messages (not user prompts)
868
+ const role = event.message?.role;
869
+ if (role === "assistant") {
870
+ const messageContent =
871
+ getMessageContent(event.message) || (event as AgentEvent & { content?: unknown }).content;
872
+ if (messageContent && Array.isArray(messageContent)) {
873
+ for (const block of messageContent) {
874
+ if (block.type === "text" && block.text) {
875
+ outputChunks.push(block.text);
876
+ }
877
+ }
878
+ }
879
+ }
880
+ // Extract and accumulate usage (prefer message.usage, fallback to event.usage)
881
+ const messageUsage = getMessageUsage(event.message) || (event as AgentEvent & { usage?: unknown }).usage;
882
+ if (messageUsage && typeof messageUsage === "object") {
883
+ // Only count assistant messages (not tool results, etc.)
884
+ if (role === "assistant") {
885
+ const usageRecord = messageUsage as Record<string, unknown>;
886
+ const costRecord = (messageUsage as { cost?: Record<string, unknown> }).cost;
887
+ hasUsage = true;
888
+ accumulatedUsage.input += getNumberField(usageRecord, "input") ?? 0;
889
+ accumulatedUsage.output += getNumberField(usageRecord, "output") ?? 0;
890
+ accumulatedUsage.cacheRead += getNumberField(usageRecord, "cacheRead") ?? 0;
891
+ accumulatedUsage.cacheWrite += getNumberField(usageRecord, "cacheWrite") ?? 0;
892
+ accumulatedUsage.totalTokens += getNumberField(usageRecord, "totalTokens") ?? 0;
893
+ if (costRecord) {
894
+ accumulatedUsage.cost.input += getNumberField(costRecord, "input") ?? 0;
895
+ accumulatedUsage.cost.output += getNumberField(costRecord, "output") ?? 0;
896
+ accumulatedUsage.cost.cacheRead += getNumberField(costRecord, "cacheRead") ?? 0;
897
+ accumulatedUsage.cost.cacheWrite += getNumberField(costRecord, "cacheWrite") ?? 0;
898
+ accumulatedUsage.cost.total += getNumberField(costRecord, "total") ?? 0;
899
+ }
900
+ }
901
+ // Accumulate tokens for progress display
902
+ progress.tokens += getUsageTokens(messageUsage);
903
+ }
904
+ break;
905
+ }
906
+
907
+ case "agent_end":
908
+ // Extract final content from assistant messages only (not user prompts)
909
+ if (event.messages && Array.isArray(event.messages)) {
910
+ for (const msg of event.messages) {
911
+ if ((msg as { role?: string })?.role !== "assistant") continue;
912
+ const messageContent = getMessageContent(msg);
913
+ if (messageContent && Array.isArray(messageContent)) {
914
+ for (const block of messageContent) {
915
+ if (block.type === "text" && block.text) {
916
+ finalOutputChunks.push(block.text);
917
+ }
918
+ }
919
+ }
920
+ }
921
+ }
922
+ flushProgress = true;
923
+ break;
924
+ }
925
+
926
+ scheduleProgress(flushProgress);
927
+ };
928
+
929
+ const runSubagent = async (): Promise<{
930
+ exitCode: number;
931
+ error?: string;
932
+ aborted?: boolean;
933
+ abortReason?: string;
934
+ durationMs: number;
935
+ }> => {
936
+ const sessionAbortController = new AbortController();
937
+ let exitCode = 0;
938
+ let error: string | undefined;
939
+ let aborted = false;
940
+ let abortReasonText: string | undefined;
941
+ const checkAbort = () => {
942
+ if (abortSignal.aborted) {
943
+ aborted = abortReason === "signal" || abortReason === undefined;
944
+ if (aborted) {
945
+ abortReasonText ??= resolveSignalAbortReason();
946
+ }
947
+ exitCode = 1;
948
+ throw new ToolAbortError();
949
+ }
950
+ };
951
+
952
+ try {
953
+ checkAbort();
954
+ const authStorage = options.authStorage ?? (await discoverAuthStorage());
955
+ checkAbort();
956
+ const modelRegistry = options.modelRegistry ?? new ModelRegistry(authStorage);
957
+ await modelRegistry.refresh();
958
+ checkAbort();
959
+
960
+ const {
961
+ model,
962
+ thinkingLevel: resolvedThinkingLevel,
963
+ explicitThinkingLevel,
964
+ } = resolveModelOverride(modelPatterns, modelRegistry, settings);
965
+ const effectiveThinkingLevel = explicitThinkingLevel
966
+ ? resolvedThinkingLevel
967
+ : (thinkingLevel ?? resolvedThinkingLevel);
968
+
969
+ const sessionManager = sessionFile
970
+ ? await SessionManager.open(sessionFile)
971
+ : SessionManager.inMemory(worktree ?? cwd);
972
+
973
+ const mcpProxyTools = options.mcpManager ? createMCPProxyTools(options.mcpManager) : [];
974
+ const enableMCP = !options.mcpManager;
975
+
976
+ const { normalized: normalizedOutputSchema } = normalizeOutputSchema(outputSchema);
977
+
978
+ const { session } = await createAgentSession({
979
+ cwd: worktree ?? cwd,
980
+ authStorage,
981
+ modelRegistry,
982
+ searchDb: options.searchDb,
983
+ settings: subagentSettings,
984
+ model,
985
+ thinkingLevel: effectiveThinkingLevel,
986
+ toolNames,
987
+ outputSchema,
988
+ requireSubmitResultTool: true,
989
+ contextFiles: options.contextFiles,
990
+ skills: options.skills,
991
+ promptTemplates: options.promptTemplates,
992
+ systemPrompt: defaultPrompt =>
993
+ prompt.render(subagentSystemPromptTemplate, {
994
+ base: defaultPrompt,
995
+ agent: agent.systemPrompt,
996
+ worktree: worktree ?? "",
997
+ outputSchema: normalizedOutputSchema,
998
+ contextFile: options.contextFile,
999
+ }),
1000
+ sessionManager,
1001
+ hasUI: false,
1002
+ spawns: spawnsEnv,
1003
+ taskDepth: childDepth,
1004
+ parentTaskPrefix: id,
1005
+ enableLsp: lspEnabled,
1006
+ skipPythonPreflight,
1007
+ enableMCP,
1008
+ customTools: mcpProxyTools.length > 0 ? mcpProxyTools : undefined,
1009
+ });
1010
+
1011
+ activeSession = session;
1012
+
1013
+ // Emit lifecycle start event
1014
+ if (options.eventBus) {
1015
+ options.eventBus.emit(TASK_SUBAGENT_LIFECYCLE_CHANNEL, {
1016
+ id,
1017
+ agent: agent.name,
1018
+ agentSource: agent.source,
1019
+ description: options.description,
1020
+ status: "started",
1021
+ sessionFile: subtaskSessionFile,
1022
+ index,
1023
+ });
1024
+ }
1025
+
1026
+ const subagentToolNames = session.getActiveToolNames();
1027
+ const parentOwnedToolNames = new Set(["todo_write"]);
1028
+ const filteredSubagentTools = subagentToolNames.filter(name => !parentOwnedToolNames.has(name));
1029
+ if (filteredSubagentTools.length !== subagentToolNames.length) {
1030
+ await session.setActiveToolsByName(filteredSubagentTools);
1031
+ }
1032
+
1033
+ session.sessionManager.appendSessionInit({
1034
+ systemPrompt: session.agent.state.systemPrompt,
1035
+ task,
1036
+ tools: session.getActiveToolNames(),
1037
+ outputSchema,
1038
+ });
1039
+
1040
+ abortSignal.addEventListener(
1041
+ "abort",
1042
+ () => {
1043
+ void session.abort();
1044
+ },
1045
+ { once: true, signal: sessionAbortController.signal },
1046
+ );
1047
+
1048
+ const extensionRunner = session.extensionRunner;
1049
+ if (extensionRunner) {
1050
+ extensionRunner.initialize(
1051
+ {
1052
+ sendMessage: (message, options) => {
1053
+ session.sendCustomMessage(message, options).catch(e => {
1054
+ logger.error("Extension sendMessage failed", {
1055
+ error: e instanceof Error ? e.message : String(e),
1056
+ });
1057
+ });
1058
+ },
1059
+ sendUserMessage: (content, options) => {
1060
+ session.sendUserMessage(content, options).catch(e => {
1061
+ logger.error("Extension sendUserMessage failed", {
1062
+ error: e instanceof Error ? e.message : String(e),
1063
+ });
1064
+ });
1065
+ },
1066
+ appendEntry: (customType, data) => {
1067
+ session.sessionManager.appendCustomEntry(customType, data);
1068
+ },
1069
+ setLabel: (targetId, label) => {
1070
+ session.sessionManager.appendLabelChange(targetId, label);
1071
+ },
1072
+ getActiveTools: () => session.getActiveToolNames(),
1073
+ getAllTools: () => session.getAllToolNames(),
1074
+ setActiveTools: (toolNames: string[]) =>
1075
+ session.setActiveToolsByName(toolNames.filter(name => !parentOwnedToolNames.has(name))),
1076
+ getCommands: () => [],
1077
+ setModel: async model => {
1078
+ const key = await session.modelRegistry.getApiKey(model);
1079
+ if (!key) return false;
1080
+ await session.setModel(model);
1081
+ return true;
1082
+ },
1083
+ getThinkingLevel: () => session.thinkingLevel,
1084
+ setThinkingLevel: level => session.setThinkingLevel(level),
1085
+ getSessionName: () => session.sessionName,
1086
+ setSessionName: async (name: string) => {
1087
+ await session.setSessionName(name);
1088
+ },
1089
+ },
1090
+ {
1091
+ getModel: () => session.model,
1092
+ getSearchDb: () => session.searchDb,
1093
+ isIdle: () => !session.isStreaming,
1094
+ abort: () => session.abort(),
1095
+ hasPendingMessages: () => session.queuedMessageCount > 0,
1096
+ shutdown: () => {},
1097
+ getContextUsage: () => session.getContextUsage(),
1098
+ getSystemPrompt: () => session.systemPrompt,
1099
+ compact: async instructionsOrOptions => {
1100
+ const instructions = typeof instructionsOrOptions === "string" ? instructionsOrOptions : undefined;
1101
+ const options =
1102
+ instructionsOrOptions && typeof instructionsOrOptions === "object"
1103
+ ? instructionsOrOptions
1104
+ : undefined;
1105
+ await session.compact(instructions, options);
1106
+ },
1107
+ },
1108
+ );
1109
+ extensionRunner.onError(err => {
1110
+ logger.error("Extension error", { path: err.extensionPath, error: err.error });
1111
+ });
1112
+ await extensionRunner.emit({ type: "session_start" });
1113
+ }
1114
+
1115
+ const MAX_SUBMIT_RESULT_RETRIES = 3;
1116
+ unsubscribe = session.subscribe(event => {
1117
+ if (isAgentEvent(event)) {
1118
+ try {
1119
+ processEvent(event);
1120
+ } catch (err) {
1121
+ logger.error("Subagent event processing failed", {
1122
+ error: err instanceof Error ? err.message : String(err),
1123
+ });
1124
+ requestAbort("terminate");
1125
+ }
1126
+ }
1127
+ });
1128
+
1129
+ await session.prompt(task, { attribution: "agent" });
1130
+ await session.waitForIdle();
1131
+
1132
+ const reminderToolChoice = buildNamedToolChoice("submit_result", session.model);
1133
+
1134
+ let retryCount = 0;
1135
+ while (!submitResultCalled && retryCount < MAX_SUBMIT_RESULT_RETRIES && !abortSignal.aborted) {
1136
+ try {
1137
+ retryCount++;
1138
+ const reminder = prompt.render(submitReminderTemplate, {
1139
+ retryCount,
1140
+ maxRetries: MAX_SUBMIT_RESULT_RETRIES,
1141
+ });
1142
+
1143
+ await session.prompt(reminder, {
1144
+ attribution: "agent",
1145
+ ...(reminderToolChoice ? { toolChoice: reminderToolChoice } : {}),
1146
+ });
1147
+ await session.waitForIdle();
1148
+ } catch (err) {
1149
+ logger.error("Subagent prompt failed", {
1150
+ error: err instanceof Error ? err.message : String(err),
1151
+ });
1152
+ }
1153
+ }
1154
+
1155
+ await session.waitForIdle();
1156
+ if (!submitResultCalled && !abortSignal.aborted) {
1157
+ aborted = true;
1158
+ exitCode = 1;
1159
+ abortReasonText ??= SUBAGENT_WARNING_MISSING_SUBMIT_RESULT;
1160
+ error ??= SUBAGENT_WARNING_MISSING_SUBMIT_RESULT;
1161
+ }
1162
+
1163
+ const lastAssistant = session.getLastAssistantMessage();
1164
+ if (lastAssistant) {
1165
+ if (lastAssistant.stopReason === "aborted") {
1166
+ aborted = abortReason === "signal" || abortReason === undefined;
1167
+ if (aborted) {
1168
+ abortReasonText ??= resolveSignalAbortReason();
1169
+ }
1170
+ exitCode = 1;
1171
+ } else if (lastAssistant.stopReason === "error") {
1172
+ exitCode = 1;
1173
+ error ??= lastAssistant.errorMessage || "Subagent failed";
1174
+ }
1175
+ }
1176
+ } catch (err) {
1177
+ exitCode = 1;
1178
+ if (!abortSignal.aborted) {
1179
+ error = err instanceof Error ? err.stack || err.message : String(err);
1180
+ }
1181
+ } finally {
1182
+ if (abortSignal.aborted) {
1183
+ aborted = abortReason === "signal" || abortReason === undefined;
1184
+ if (aborted) {
1185
+ abortReasonText ??= resolveSignalAbortReason();
1186
+ }
1187
+ if (exitCode === 0) exitCode = 1;
1188
+ }
1189
+ sessionAbortController.abort();
1190
+ if (unsubscribe) {
1191
+ try {
1192
+ unsubscribe();
1193
+ } catch {
1194
+ // Ignore unsubscribe errors
1195
+ }
1196
+ unsubscribe = null;
1197
+ }
1198
+ if (activeSession) {
1199
+ const session = activeSession;
1200
+ activeSession = null;
1201
+ try {
1202
+ await untilAborted(AbortSignal.timeout(5000), () => session.dispose());
1203
+ } catch {
1204
+ // Ignore cleanup errors
1205
+ }
1206
+ }
1207
+ }
1208
+
1209
+ return {
1210
+ exitCode,
1211
+ error,
1212
+ aborted,
1213
+ abortReason: aborted ? abortReasonText : undefined,
1214
+ durationMs: Date.now() - startTime,
1215
+ };
1216
+ };
1217
+
1218
+ const done = await runSubagent();
1219
+ resolved = true;
1220
+ listenerController.abort();
1221
+
1222
+ if (progressTimeoutId) {
1223
+ clearTimeout(progressTimeoutId);
1224
+ progressTimeoutId = null;
1225
+ }
1226
+
1227
+ let exitCode = done.exitCode;
1228
+ if (done.error) {
1229
+ stderr = done.error;
1230
+ }
1231
+
1232
+ // Use final output if available, otherwise accumulated output
1233
+ let rawOutput = finalOutputChunks.length > 0 ? finalOutputChunks.join("") : outputChunks.join("");
1234
+ const submitResultItems = progress.extractedToolData?.submit_result as SubmitResultItem[] | undefined;
1235
+ const reportFindings = progress.extractedToolData?.report_finding as ReviewFinding[] | undefined;
1236
+ const finalized = finalizeSubprocessOutput({
1237
+ rawOutput,
1238
+ exitCode,
1239
+ stderr,
1240
+ doneAborted: Boolean(done.aborted),
1241
+ signalAborted: Boolean(signal?.aborted),
1242
+ submitResultItems,
1243
+ reportFindings,
1244
+ outputSchema,
1245
+ });
1246
+ rawOutput = finalized.rawOutput;
1247
+ exitCode = finalized.exitCode;
1248
+ stderr = finalized.stderr;
1249
+ const lastSubmitResult = submitResultItems?.[submitResultItems.length - 1];
1250
+ const submitResultAbortReason =
1251
+ lastSubmitResult?.status === "aborted" ? lastSubmitResult.error || "Subagent aborted task" : undefined;
1252
+ const { abortedViaSubmitResult, hasSubmitResult } = finalized;
1253
+ const { content: truncatedOutput, truncated } = truncateTail(rawOutput, {
1254
+ maxBytes: MAX_OUTPUT_BYTES,
1255
+ maxLines: MAX_OUTPUT_LINES,
1256
+ });
1257
+
1258
+ // Write output artifact (input and jsonl already written in real-time)
1259
+ // Compute output metadata for agent:// URL integration
1260
+ let outputMeta: { lineCount: number; charCount: number } | undefined;
1261
+ let outputPath: string | undefined;
1262
+ if (options.artifactsDir) {
1263
+ outputPath = path.join(options.artifactsDir, `${id}.md`);
1264
+ try {
1265
+ await Bun.write(outputPath, rawOutput);
1266
+ outputMeta = {
1267
+ lineCount: rawOutput.split("\n").length,
1268
+ charCount: rawOutput.length,
1269
+ };
1270
+ } catch {
1271
+ // Non-fatal
1272
+ }
1273
+ }
1274
+
1275
+ // Update final progress
1276
+ // When salvage recovered the output (exitCode became 0), the result is not aborted.
1277
+ const wasAborted =
1278
+ abortedViaSubmitResult || (!hasSubmitResult && exitCode !== 0 && (done.aborted || signal?.aborted || false));
1279
+ const finalAbortReason = wasAborted
1280
+ ? abortedViaSubmitResult
1281
+ ? submitResultAbortReason
1282
+ : (done.abortReason ?? (signal?.aborted ? resolveSignalAbortReason() : "Subagent aborted task"))
1283
+ : undefined;
1284
+ progress.status = wasAborted ? "aborted" : exitCode === 0 ? "completed" : "failed";
1285
+ scheduleProgress(true);
1286
+
1287
+ // Emit lifecycle end event after finalization so submit_result status is reflected
1288
+ if (options.eventBus) {
1289
+ options.eventBus.emit(TASK_SUBAGENT_LIFECYCLE_CHANNEL, {
1290
+ id,
1291
+ agent: agent.name,
1292
+ agentSource: agent.source,
1293
+ description: options.description,
1294
+ status: progress.status as "completed" | "failed" | "aborted",
1295
+ sessionFile: subtaskSessionFile,
1296
+ index,
1297
+ });
1298
+ }
1299
+
1300
+ return {
1301
+ index,
1302
+ id,
1303
+ agent: agent.name,
1304
+ agentSource: agent.source,
1305
+ task,
1306
+ assignment,
1307
+ description: options.description,
1308
+ lastIntent: progress.lastIntent,
1309
+ exitCode,
1310
+ output: truncatedOutput,
1311
+ stderr,
1312
+ truncated: Boolean(truncated),
1313
+ durationMs: Date.now() - startTime,
1314
+ tokens: progress.tokens,
1315
+ modelOverride,
1316
+ error: exitCode !== 0 && stderr ? stderr : undefined,
1317
+ aborted: wasAborted,
1318
+ abortReason: finalAbortReason,
1319
+ usage: hasUsage ? accumulatedUsage : undefined,
1320
+ outputPath,
1321
+ extractedToolData: progress.extractedToolData,
1322
+ outputMeta,
1323
+ };
1324
+ }