@f5xc-salesdemos/xcsh 2.2.0 → 14.0.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 (1518) hide show
  1. package/CHANGELOG.md +6854 -24
  2. package/README.md +11 -610
  3. package/examples/README.md +8 -15
  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 +78 -143
  8. package/examples/extensions/api-demo.ts +89 -0
  9. package/examples/extensions/chalk-logger.ts +25 -0
  10. package/examples/extensions/hello.ts +24 -18
  11. package/examples/extensions/pirate.ts +5 -9
  12. package/examples/extensions/plan-mode.ts +551 -0
  13. package/examples/extensions/reload-runtime.ts +1 -1
  14. package/examples/extensions/todo.ts +18 -19
  15. package/examples/extensions/tools.ts +23 -19
  16. package/examples/extensions/with-deps/index.ts +5 -1
  17. package/examples/extensions/with-deps/package-lock.json +2 -2
  18. package/examples/extensions/with-deps/package.json +2 -8
  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 +3 -4
  32. package/examples/sdk/02-custom-model.ts +9 -9
  33. package/examples/sdk/03-custom-prompt.ts +11 -23
  34. package/examples/sdk/04-skills.ts +23 -32
  35. package/examples/sdk/06-extensions.ts +14 -22
  36. package/examples/sdk/06-hooks.ts +61 -0
  37. package/examples/sdk/07-context-files.ts +18 -23
  38. package/examples/sdk/08-prompt-templates.ts +14 -21
  39. package/examples/sdk/08-slash-commands.ts +46 -0
  40. package/examples/sdk/09-api-keys-and-oauth.ts +15 -9
  41. package/examples/sdk/11-sessions.ts +3 -4
  42. package/examples/sdk/README.md +117 -92
  43. package/package.json +507 -82
  44. package/scripts/format-prompts.ts +68 -0
  45. package/scripts/generate-docs-index.ts +40 -0
  46. package/scripts/generate-template.ts +32 -0
  47. package/src/async/index.ts +1 -0
  48. package/src/async/job-manager.ts +383 -0
  49. package/src/autoresearch/apply-contract-to-state.ts +24 -0
  50. package/src/autoresearch/command-resume.md +17 -0
  51. package/src/autoresearch/contract.ts +288 -0
  52. package/src/autoresearch/dashboard.ts +446 -0
  53. package/src/autoresearch/git.ts +329 -0
  54. package/src/autoresearch/helpers.ts +507 -0
  55. package/src/autoresearch/index.ts +534 -0
  56. package/src/autoresearch/prompt.md +244 -0
  57. package/src/autoresearch/resume-message.md +16 -0
  58. package/src/autoresearch/state.ts +380 -0
  59. package/src/autoresearch/tools/init-experiment.ts +395 -0
  60. package/src/autoresearch/tools/log-experiment.ts +778 -0
  61. package/src/autoresearch/tools/run-experiment.ts +678 -0
  62. package/src/autoresearch/types.ts +218 -0
  63. package/src/bun-imports.d.ts +22 -0
  64. package/src/capability/context-file.ts +44 -0
  65. package/src/capability/extension-module.ts +34 -0
  66. package/src/capability/extension.ts +47 -0
  67. package/src/capability/fs.ts +107 -0
  68. package/src/capability/hook.ts +40 -0
  69. package/src/capability/index.ts +436 -0
  70. package/src/capability/instruction.ts +37 -0
  71. package/src/capability/mcp.ts +74 -0
  72. package/src/capability/prompt.ts +35 -0
  73. package/src/capability/rule.ts +224 -0
  74. package/src/capability/settings.ts +34 -0
  75. package/src/capability/skill.ts +49 -0
  76. package/src/capability/slash-command.ts +40 -0
  77. package/src/capability/ssh.ts +41 -0
  78. package/src/capability/system-prompt.ts +34 -0
  79. package/src/capability/tool.ts +38 -0
  80. package/src/capability/types.ts +168 -0
  81. package/src/cli/agents-cli.ts +138 -0
  82. package/src/cli/args.ts +283 -0
  83. package/src/cli/classify-install-target.ts +50 -0
  84. package/src/cli/commands/init-xdg.ts +27 -0
  85. package/src/cli/config-cli.ts +418 -0
  86. package/src/cli/file-processor.ts +123 -0
  87. package/src/cli/grep-cli.ts +160 -0
  88. package/src/cli/grievances-cli.ts +78 -0
  89. package/src/cli/initial-message.ts +58 -0
  90. package/src/cli/jupyter-cli.ts +106 -0
  91. package/src/cli/list-models.ts +89 -0
  92. package/src/cli/plugin-cli.ts +964 -0
  93. package/src/cli/read-cli.ts +67 -0
  94. package/src/cli/session-picker.ts +52 -0
  95. package/src/cli/setup-cli.ts +376 -0
  96. package/src/cli/shell-cli.ts +174 -0
  97. package/src/cli/ssh-cli.ts +179 -0
  98. package/src/cli/stats-cli.ts +182 -0
  99. package/src/cli/update-cli.ts +342 -0
  100. package/src/cli/web-search-cli.ts +133 -0
  101. package/src/cli.ts +96 -0
  102. package/src/commands/agents.ts +57 -0
  103. package/src/commands/commit.ts +36 -0
  104. package/src/commands/config.ts +51 -0
  105. package/src/commands/grep.ts +48 -0
  106. package/src/commands/grievances.ts +20 -0
  107. package/src/commands/jupyter.ts +32 -0
  108. package/src/commands/launch.ts +141 -0
  109. package/src/commands/plugin.ts +78 -0
  110. package/src/commands/read.ts +33 -0
  111. package/src/commands/setup.ts +42 -0
  112. package/src/commands/shell.ts +29 -0
  113. package/src/commands/ssh.ts +60 -0
  114. package/src/commands/stats.ts +29 -0
  115. package/src/commands/update.ts +21 -0
  116. package/src/commands/web-search.ts +42 -0
  117. package/src/commit/agentic/agent.ts +314 -0
  118. package/src/commit/agentic/fallback.ts +96 -0
  119. package/src/commit/agentic/index.ts +354 -0
  120. package/src/commit/agentic/prompts/analyze-file.md +22 -0
  121. package/src/commit/agentic/prompts/session-user.md +25 -0
  122. package/src/commit/agentic/prompts/split-confirm.md +1 -0
  123. package/src/commit/agentic/prompts/system.md +38 -0
  124. package/src/commit/agentic/state.ts +60 -0
  125. package/src/commit/agentic/tools/analyze-file.ts +128 -0
  126. package/src/commit/agentic/tools/git-file-diff.ts +191 -0
  127. package/src/commit/agentic/tools/git-hunk.ts +50 -0
  128. package/src/commit/agentic/tools/git-overview.ts +81 -0
  129. package/src/commit/agentic/tools/index.ts +54 -0
  130. package/src/commit/agentic/tools/propose-changelog.ts +139 -0
  131. package/src/commit/agentic/tools/propose-commit.ts +122 -0
  132. package/src/commit/agentic/tools/recent-commits.ts +81 -0
  133. package/src/commit/agentic/tools/schemas.ts +31 -0
  134. package/src/commit/agentic/tools/split-commit.ts +251 -0
  135. package/src/commit/agentic/topo-sort.ts +44 -0
  136. package/src/commit/agentic/trivial.ts +51 -0
  137. package/src/commit/agentic/validation.ts +183 -0
  138. package/src/commit/analysis/conventional.ts +122 -0
  139. package/src/commit/analysis/index.ts +4 -0
  140. package/src/commit/analysis/scope.ts +242 -0
  141. package/src/commit/analysis/summary.ts +105 -0
  142. package/src/commit/analysis/validation.ts +66 -0
  143. package/src/commit/changelog/detect.ts +40 -0
  144. package/src/commit/changelog/generate.ts +101 -0
  145. package/src/commit/changelog/index.ts +234 -0
  146. package/src/commit/changelog/parse.ts +44 -0
  147. package/src/commit/cli.ts +85 -0
  148. package/src/commit/git/diff.ts +148 -0
  149. package/src/commit/index.ts +5 -0
  150. package/src/commit/map-reduce/index.ts +69 -0
  151. package/src/commit/map-reduce/map-phase.ts +193 -0
  152. package/src/commit/map-reduce/reduce-phase.ts +108 -0
  153. package/src/commit/map-reduce/utils.ts +9 -0
  154. package/src/commit/message.ts +11 -0
  155. package/src/commit/model-selection.ts +63 -0
  156. package/src/commit/pipeline.ts +242 -0
  157. package/src/commit/prompts/analysis-system.md +148 -0
  158. package/src/commit/prompts/analysis-user.md +38 -0
  159. package/src/commit/prompts/changelog-system.md +50 -0
  160. package/src/commit/prompts/changelog-user.md +18 -0
  161. package/src/commit/prompts/file-observer-system.md +24 -0
  162. package/src/commit/prompts/file-observer-user.md +8 -0
  163. package/src/commit/prompts/reduce-system.md +50 -0
  164. package/src/commit/prompts/reduce-user.md +17 -0
  165. package/src/commit/prompts/summary-retry.md +3 -0
  166. package/src/commit/prompts/summary-system.md +38 -0
  167. package/src/commit/prompts/summary-user.md +13 -0
  168. package/src/commit/prompts/types-description.md +2 -0
  169. package/src/commit/types.ts +118 -0
  170. package/src/commit/utils/exclusions.ts +42 -0
  171. package/src/commit/utils.ts +44 -0
  172. package/src/config/file-lock.ts +121 -0
  173. package/src/config/keybindings.ts +493 -0
  174. package/src/config/mcp-schema.json +230 -0
  175. package/src/config/model-registry.ts +1917 -0
  176. package/src/config/model-resolver.ts +1064 -0
  177. package/src/config/prompt-templates.ts +255 -0
  178. package/src/config/resolve-config-value.ts +94 -0
  179. package/src/config/settings-schema.ts +1929 -0
  180. package/src/config/settings.ts +701 -0
  181. package/src/config.ts +419 -0
  182. package/src/cursor.ts +304 -0
  183. package/src/dap/client.ts +674 -0
  184. package/src/dap/config.ts +150 -0
  185. package/src/dap/defaults.json +211 -0
  186. package/src/dap/index.ts +4 -0
  187. package/src/dap/session.ts +1255 -0
  188. package/src/dap/types.ts +600 -0
  189. package/src/debug/index.ts +438 -0
  190. package/src/debug/log-formatting.ts +58 -0
  191. package/src/debug/log-viewer.ts +908 -0
  192. package/src/debug/profiler.ts +158 -0
  193. package/src/debug/report-bundle.ts +365 -0
  194. package/src/debug/system-info.ts +107 -0
  195. package/src/discovery/agents-md.ts +67 -0
  196. package/src/discovery/agents.ts +219 -0
  197. package/src/discovery/builtin.ts +851 -0
  198. package/src/discovery/claude-plugins.ts +296 -0
  199. package/src/discovery/claude.ts +543 -0
  200. package/src/discovery/cline.ts +83 -0
  201. package/src/discovery/codex.ts +535 -0
  202. package/src/discovery/cursor.ts +220 -0
  203. package/src/discovery/gemini.ts +396 -0
  204. package/src/discovery/github.ts +118 -0
  205. package/src/discovery/helpers.ts +968 -0
  206. package/src/discovery/index.ts +79 -0
  207. package/src/discovery/mcp-json.ts +171 -0
  208. package/src/discovery/opencode.ts +393 -0
  209. package/src/discovery/plugin-dir-roots.ts +28 -0
  210. package/src/discovery/ssh.ts +153 -0
  211. package/src/discovery/substitute-plugin-root.ts +29 -0
  212. package/src/discovery/vscode.ts +105 -0
  213. package/src/discovery/windsurf.ts +147 -0
  214. package/src/edit/diff.ts +818 -0
  215. package/src/edit/index.ts +314 -0
  216. package/src/edit/line-hash.ts +67 -0
  217. package/src/edit/modes/chunk.ts +454 -0
  218. package/src/edit/modes/hashline.ts +1341 -0
  219. package/src/edit/modes/patch.ts +1785 -0
  220. package/src/edit/modes/replace.ts +1107 -0
  221. package/src/edit/normalize.ts +375 -0
  222. package/src/edit/renderer.ts +467 -0
  223. package/src/exa/factory.ts +59 -0
  224. package/src/exa/index.ts +27 -0
  225. package/src/exa/mcp-client.ts +291 -0
  226. package/src/exa/render.ts +244 -0
  227. package/src/exa/researcher.ts +47 -0
  228. package/src/exa/search.ts +86 -0
  229. package/src/exa/types.ts +166 -0
  230. package/src/exa/websets.ts +247 -0
  231. package/src/exec/bash-executor.ts +240 -0
  232. package/src/exec/exec.ts +53 -0
  233. package/src/exec/idle-timeout-watchdog.ts +126 -0
  234. package/src/exec/non-interactive-env.ts +48 -0
  235. package/src/export/custom-share.ts +65 -0
  236. package/src/export/html/index.ts +161 -0
  237. package/src/export/html/template.css +919 -0
  238. package/src/export/html/template.generated.ts +2 -0
  239. package/src/export/html/template.html +46 -0
  240. package/src/export/html/template.js +1458 -0
  241. package/src/export/html/template.macro.ts +24 -0
  242. package/src/export/ttsr.ts +434 -0
  243. package/src/extensibility/custom-commands/bundled/ci-green/index.ts +25 -0
  244. package/src/extensibility/custom-commands/bundled/review/index.ts +435 -0
  245. package/src/extensibility/custom-commands/index.ts +2 -0
  246. package/src/extensibility/custom-commands/loader.ts +236 -0
  247. package/src/extensibility/custom-commands/types.ts +111 -0
  248. package/src/extensibility/custom-tools/index.ts +7 -0
  249. package/src/extensibility/custom-tools/loader.ts +238 -0
  250. package/src/extensibility/custom-tools/types.ts +255 -0
  251. package/src/extensibility/custom-tools/wrapper.ts +47 -0
  252. package/src/extensibility/extensions/index.ts +15 -0
  253. package/src/extensibility/extensions/loader.ts +516 -0
  254. package/src/extensibility/extensions/runner.ts +841 -0
  255. package/src/extensibility/extensions/types.ts +1366 -0
  256. package/src/extensibility/extensions/wrapper.ts +191 -0
  257. package/src/extensibility/hooks/index.ts +5 -0
  258. package/src/extensibility/hooks/loader.ts +255 -0
  259. package/src/extensibility/hooks/runner.ts +425 -0
  260. package/src/extensibility/hooks/tool-wrapper.ts +108 -0
  261. package/src/extensibility/hooks/types.ts +822 -0
  262. package/src/extensibility/plugins/doctor.ts +66 -0
  263. package/src/extensibility/plugins/git-url.ts +281 -0
  264. package/src/extensibility/plugins/index.ts +9 -0
  265. package/src/extensibility/plugins/installer.ts +192 -0
  266. package/src/extensibility/plugins/loader.ts +267 -0
  267. package/src/extensibility/plugins/manager.ts +731 -0
  268. package/src/extensibility/plugins/marketplace/cache.ts +136 -0
  269. package/src/extensibility/plugins/marketplace/fetcher.ts +317 -0
  270. package/src/extensibility/plugins/marketplace/index.ts +6 -0
  271. package/src/extensibility/plugins/marketplace/manager.ts +751 -0
  272. package/src/extensibility/plugins/marketplace/registry.ts +196 -0
  273. package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
  274. package/src/extensibility/plugins/marketplace/types.ts +191 -0
  275. package/src/extensibility/plugins/parser.ts +105 -0
  276. package/src/extensibility/plugins/types.ts +194 -0
  277. package/src/extensibility/skills.ts +252 -0
  278. package/src/extensibility/slash-commands.ts +227 -0
  279. package/src/extensibility/tool-proxy.ts +25 -0
  280. package/src/extensibility/utils.ts +38 -0
  281. package/src/index.ts +61 -0
  282. package/src/internal-urls/agent-protocol.ts +136 -0
  283. package/src/internal-urls/artifact-protocol.ts +97 -0
  284. package/src/internal-urls/docs-index.generated.ts +57 -0
  285. package/src/internal-urls/index.ts +35 -0
  286. package/src/internal-urls/jobs-protocol.ts +118 -0
  287. package/src/internal-urls/json-query.ts +126 -0
  288. package/src/internal-urls/local-protocol.ts +206 -0
  289. package/src/internal-urls/mcp-protocol.ts +156 -0
  290. package/src/internal-urls/memory-protocol.ts +133 -0
  291. package/src/internal-urls/parse.ts +72 -0
  292. package/src/internal-urls/pi-protocol.ts +84 -0
  293. package/src/internal-urls/router.ts +54 -0
  294. package/src/internal-urls/rule-protocol.ts +55 -0
  295. package/src/internal-urls/skill-protocol.ts +111 -0
  296. package/src/internal-urls/types.ts +52 -0
  297. package/src/ipy/cancellation.ts +28 -0
  298. package/src/ipy/executor.ts +762 -0
  299. package/src/ipy/gateway-coordinator.ts +424 -0
  300. package/src/ipy/kernel.ts +1065 -0
  301. package/src/ipy/modules.ts +144 -0
  302. package/src/ipy/prelude.py +849 -0
  303. package/src/ipy/prelude.ts +3 -0
  304. package/src/ipy/runtime.ts +221 -0
  305. package/src/lsp/client.ts +878 -0
  306. package/src/lsp/clients/biome-client.ts +202 -0
  307. package/src/lsp/clients/index.ts +50 -0
  308. package/src/lsp/clients/lsp-linter-client.ts +93 -0
  309. package/src/lsp/clients/swiftlint-client.ts +120 -0
  310. package/src/lsp/config.ts +402 -0
  311. package/src/lsp/defaults.json +998 -0
  312. package/src/lsp/edits.ts +109 -0
  313. package/src/lsp/index.ts +1743 -0
  314. package/src/lsp/lspmux.ts +233 -0
  315. package/src/lsp/render.ts +683 -0
  316. package/src/lsp/startup-events.ts +13 -0
  317. package/src/lsp/types.ts +438 -0
  318. package/src/lsp/utils.ts +807 -0
  319. package/src/main.ts +914 -0
  320. package/src/mcp/client.ts +482 -0
  321. package/src/mcp/config-writer.ts +225 -0
  322. package/src/mcp/config.ts +365 -0
  323. package/src/mcp/discoverable-tool-metadata.ts +202 -0
  324. package/src/mcp/index.ts +29 -0
  325. package/src/mcp/json-rpc.ts +84 -0
  326. package/src/mcp/loader.ts +124 -0
  327. package/src/mcp/manager.ts +1152 -0
  328. package/src/mcp/oauth-discovery.ts +349 -0
  329. package/src/mcp/oauth-flow.ts +387 -0
  330. package/src/mcp/render.ts +130 -0
  331. package/src/mcp/smithery-auth.ts +104 -0
  332. package/src/mcp/smithery-connect.ts +145 -0
  333. package/src/mcp/smithery-registry.ts +477 -0
  334. package/src/mcp/tool-bridge.ts +417 -0
  335. package/src/mcp/tool-cache.ts +117 -0
  336. package/src/mcp/transports/http.ts +475 -0
  337. package/src/mcp/transports/index.ts +6 -0
  338. package/src/mcp/transports/stdio.ts +325 -0
  339. package/src/mcp/types.ts +423 -0
  340. package/src/memories/index.ts +1114 -0
  341. package/src/memories/storage.ts +577 -0
  342. package/src/modes/acp/acp-agent.ts +1358 -0
  343. package/src/modes/acp/acp-event-mapper.ts +538 -0
  344. package/src/modes/acp/acp-mode.ts +15 -0
  345. package/src/modes/acp/index.ts +2 -0
  346. package/src/modes/components/agent-dashboard.ts +1120 -0
  347. package/src/modes/components/assistant-message.ts +206 -0
  348. package/src/modes/components/bash-execution.ts +247 -0
  349. package/src/modes/components/bordered-loader.ts +41 -0
  350. package/src/modes/components/branch-summary-message.ts +45 -0
  351. package/src/modes/components/btw-panel.ts +104 -0
  352. package/src/modes/components/compaction-summary-message.ts +51 -0
  353. package/src/modes/components/countdown-timer.ts +75 -0
  354. package/src/modes/components/custom-editor.ts +238 -0
  355. package/src/modes/components/custom-message.ts +91 -0
  356. package/src/modes/components/diff.ts +210 -0
  357. package/src/modes/components/dynamic-border.ts +25 -0
  358. package/src/modes/components/extensions/extension-dashboard.ts +326 -0
  359. package/src/modes/components/extensions/extension-list.ts +492 -0
  360. package/src/modes/components/extensions/index.ts +9 -0
  361. package/src/modes/components/extensions/inspector-panel.ts +317 -0
  362. package/src/modes/components/extensions/state-manager.ts +587 -0
  363. package/src/modes/components/extensions/types.ts +191 -0
  364. package/src/modes/components/footer.ts +262 -0
  365. package/src/modes/components/history-search.ts +158 -0
  366. package/src/modes/components/hook-editor.ts +151 -0
  367. package/src/modes/components/hook-input.ts +79 -0
  368. package/src/modes/components/hook-message.ts +100 -0
  369. package/src/modes/components/hook-selector.ts +190 -0
  370. package/src/modes/components/index.ts +36 -0
  371. package/src/modes/components/keybinding-hints.ts +65 -0
  372. package/src/modes/components/login-dialog.ts +164 -0
  373. package/src/modes/components/mcp-add-wizard.ts +1314 -0
  374. package/src/modes/components/model-selector.ts +789 -0
  375. package/src/modes/components/oauth-selector.ts +211 -0
  376. package/src/modes/components/plugin-selector.ts +95 -0
  377. package/src/modes/components/plugin-settings.ts +477 -0
  378. package/src/modes/components/python-execution.ts +181 -0
  379. package/src/modes/components/queue-mode-selector.ts +56 -0
  380. package/src/modes/components/read-tool-group.ts +152 -0
  381. package/src/modes/components/session-observer-overlay.ts +472 -0
  382. package/src/modes/components/session-selector.ts +343 -0
  383. package/src/modes/components/settings-defs.ts +547 -0
  384. package/src/modes/components/settings-selector.ts +624 -0
  385. package/src/modes/components/show-images-selector.ts +45 -0
  386. package/src/modes/components/skill-message.ts +90 -0
  387. package/src/modes/components/status-line/context-thresholds.ts +68 -0
  388. package/src/modes/components/status-line/git-utils.ts +42 -0
  389. package/src/modes/components/status-line/index.ts +4 -0
  390. package/src/modes/components/status-line/presets.ts +94 -0
  391. package/src/modes/components/status-line/segments.ts +392 -0
  392. package/src/modes/components/status-line/separators.ts +55 -0
  393. package/src/modes/components/status-line/token-rate.ts +66 -0
  394. package/src/modes/components/status-line/types.ts +82 -0
  395. package/src/modes/components/status-line-segment-editor.ts +358 -0
  396. package/src/modes/components/status-line.ts +499 -0
  397. package/src/modes/components/theme-selector.ts +63 -0
  398. package/src/modes/components/thinking-selector.ts +52 -0
  399. package/src/modes/components/todo-reminder.ts +47 -0
  400. package/src/modes/components/tool-execution.ts +697 -0
  401. package/src/modes/components/tree-selector.ts +908 -0
  402. package/src/modes/components/ttsr-notification.ts +80 -0
  403. package/src/modes/components/user-message-selector.ts +141 -0
  404. package/src/modes/components/user-message.ts +38 -0
  405. package/src/modes/components/visual-truncate.ts +63 -0
  406. package/src/modes/components/welcome.ts +248 -0
  407. package/src/modes/controllers/btw-controller.ts +193 -0
  408. package/src/modes/controllers/command-controller.ts +1195 -0
  409. package/src/modes/controllers/event-controller.ts +644 -0
  410. package/src/modes/controllers/extension-ui-controller.ts +960 -0
  411. package/src/modes/controllers/input-controller.ts +762 -0
  412. package/src/modes/controllers/mcp-command-controller.ts +1926 -0
  413. package/src/modes/controllers/selector-controller.ts +991 -0
  414. package/src/modes/controllers/ssh-command-controller.ts +421 -0
  415. package/src/modes/index.ts +34 -0
  416. package/src/modes/interactive-mode.ts +1664 -0
  417. package/src/modes/oauth-manual-input.ts +42 -0
  418. package/src/modes/print-mode.ts +192 -0
  419. package/src/modes/prompt-action-autocomplete.ts +233 -0
  420. package/src/modes/rpc/host-tools.ts +186 -0
  421. package/src/modes/rpc/rpc-client.ts +750 -0
  422. package/src/modes/rpc/rpc-mode.ts +825 -0
  423. package/src/modes/rpc/rpc-types.ts +297 -0
  424. package/src/modes/session-observer-registry.ts +146 -0
  425. package/src/modes/shared.ts +30 -0
  426. package/src/modes/theme/dark.json +95 -0
  427. package/src/modes/theme/defaults/alabaster.json +93 -0
  428. package/src/modes/theme/defaults/amethyst.json +96 -0
  429. package/src/modes/theme/defaults/anthracite.json +93 -0
  430. package/src/modes/theme/defaults/basalt.json +91 -0
  431. package/src/modes/theme/defaults/birch.json +95 -0
  432. package/src/modes/theme/defaults/dark-abyss.json +91 -0
  433. package/src/modes/theme/defaults/dark-arctic.json +104 -0
  434. package/src/modes/theme/defaults/dark-aurora.json +95 -0
  435. package/src/modes/theme/defaults/dark-catppuccin.json +107 -0
  436. package/src/modes/theme/defaults/dark-cavern.json +91 -0
  437. package/src/modes/theme/defaults/dark-copper.json +95 -0
  438. package/src/modes/theme/defaults/dark-cosmos.json +90 -0
  439. package/src/modes/theme/defaults/dark-cyberpunk.json +102 -0
  440. package/src/modes/theme/defaults/dark-dracula.json +98 -0
  441. package/src/modes/theme/defaults/dark-eclipse.json +91 -0
  442. package/src/modes/theme/defaults/dark-ember.json +95 -0
  443. package/src/modes/theme/defaults/dark-equinox.json +90 -0
  444. package/src/modes/theme/defaults/dark-forest.json +96 -0
  445. package/src/modes/theme/defaults/dark-github.json +105 -0
  446. package/src/modes/theme/defaults/dark-gruvbox.json +112 -0
  447. package/src/modes/theme/defaults/dark-lavender.json +95 -0
  448. package/src/modes/theme/defaults/dark-lunar.json +89 -0
  449. package/src/modes/theme/defaults/dark-midnight.json +95 -0
  450. package/src/modes/theme/defaults/dark-monochrome.json +94 -0
  451. package/src/modes/theme/defaults/dark-monokai.json +98 -0
  452. package/src/modes/theme/defaults/dark-nebula.json +90 -0
  453. package/src/modes/theme/defaults/dark-nord.json +97 -0
  454. package/src/modes/theme/defaults/dark-ocean.json +101 -0
  455. package/src/modes/theme/defaults/dark-one.json +100 -0
  456. package/src/modes/theme/defaults/dark-poimandres.json +138 -0
  457. package/src/modes/theme/defaults/dark-rainforest.json +91 -0
  458. package/src/modes/theme/defaults/dark-reef.json +91 -0
  459. package/src/modes/theme/defaults/dark-retro.json +92 -0
  460. package/src/modes/theme/defaults/dark-rose-pine.json +96 -0
  461. package/src/modes/theme/defaults/dark-sakura.json +95 -0
  462. package/src/modes/theme/defaults/dark-slate.json +95 -0
  463. package/src/modes/theme/defaults/dark-solarized.json +97 -0
  464. package/src/modes/theme/defaults/dark-solstice.json +90 -0
  465. package/src/modes/theme/defaults/dark-starfall.json +91 -0
  466. package/src/modes/theme/defaults/dark-sunset.json +99 -0
  467. package/src/modes/theme/defaults/dark-swamp.json +90 -0
  468. package/src/modes/theme/defaults/dark-synthwave.json +103 -0
  469. package/src/modes/theme/defaults/dark-taiga.json +91 -0
  470. package/src/modes/theme/defaults/dark-terminal.json +95 -0
  471. package/src/modes/theme/defaults/dark-tokyo-night.json +101 -0
  472. package/src/modes/theme/defaults/dark-tundra.json +91 -0
  473. package/src/modes/theme/defaults/dark-twilight.json +91 -0
  474. package/src/modes/theme/defaults/dark-volcanic.json +91 -0
  475. package/src/modes/theme/defaults/graphite.json +92 -0
  476. package/src/modes/theme/defaults/index.ts +203 -0
  477. package/src/modes/theme/defaults/light-arctic.json +107 -0
  478. package/src/modes/theme/defaults/light-aurora-day.json +91 -0
  479. package/src/modes/theme/defaults/light-canyon.json +91 -0
  480. package/src/modes/theme/defaults/light-catppuccin.json +106 -0
  481. package/src/modes/theme/defaults/light-cirrus.json +90 -0
  482. package/src/modes/theme/defaults/light-coral.json +95 -0
  483. package/src/modes/theme/defaults/light-cyberpunk.json +96 -0
  484. package/src/modes/theme/defaults/light-dawn.json +90 -0
  485. package/src/modes/theme/defaults/light-dunes.json +91 -0
  486. package/src/modes/theme/defaults/light-eucalyptus.json +95 -0
  487. package/src/modes/theme/defaults/light-forest.json +100 -0
  488. package/src/modes/theme/defaults/light-frost.json +95 -0
  489. package/src/modes/theme/defaults/light-github.json +115 -0
  490. package/src/modes/theme/defaults/light-glacier.json +91 -0
  491. package/src/modes/theme/defaults/light-gruvbox.json +108 -0
  492. package/src/modes/theme/defaults/light-haze.json +90 -0
  493. package/src/modes/theme/defaults/light-honeycomb.json +95 -0
  494. package/src/modes/theme/defaults/light-lagoon.json +91 -0
  495. package/src/modes/theme/defaults/light-lavender.json +95 -0
  496. package/src/modes/theme/defaults/light-meadow.json +91 -0
  497. package/src/modes/theme/defaults/light-mint.json +95 -0
  498. package/src/modes/theme/defaults/light-monochrome.json +101 -0
  499. package/src/modes/theme/defaults/light-ocean.json +99 -0
  500. package/src/modes/theme/defaults/light-one.json +99 -0
  501. package/src/modes/theme/defaults/light-opal.json +91 -0
  502. package/src/modes/theme/defaults/light-orchard.json +91 -0
  503. package/src/modes/theme/defaults/light-paper.json +95 -0
  504. package/src/modes/theme/defaults/light-poimandres.json +138 -0
  505. package/src/modes/theme/defaults/light-prism.json +90 -0
  506. package/src/modes/theme/defaults/light-retro.json +98 -0
  507. package/src/modes/theme/defaults/light-sand.json +95 -0
  508. package/src/modes/theme/defaults/light-savanna.json +91 -0
  509. package/src/modes/theme/defaults/light-solarized.json +102 -0
  510. package/src/modes/theme/defaults/light-soleil.json +90 -0
  511. package/src/modes/theme/defaults/light-sunset.json +99 -0
  512. package/src/modes/theme/defaults/light-synthwave.json +98 -0
  513. package/src/modes/theme/defaults/light-tokyo-night.json +111 -0
  514. package/src/modes/theme/defaults/light-wetland.json +91 -0
  515. package/src/modes/theme/defaults/light-zenith.json +89 -0
  516. package/src/modes/theme/defaults/limestone.json +94 -0
  517. package/src/modes/theme/defaults/mahogany.json +97 -0
  518. package/src/modes/theme/defaults/marble.json +93 -0
  519. package/src/modes/theme/defaults/obsidian.json +91 -0
  520. package/src/modes/theme/defaults/onyx.json +91 -0
  521. package/src/modes/theme/defaults/pearl.json +93 -0
  522. package/src/modes/theme/defaults/porcelain.json +91 -0
  523. package/src/modes/theme/defaults/quartz.json +96 -0
  524. package/src/modes/theme/defaults/sandstone.json +95 -0
  525. package/src/modes/theme/defaults/titanium.json +90 -0
  526. package/src/modes/theme/defaults/xcsh-dark.json +89 -0
  527. package/src/modes/theme/defaults/xcsh-light.json +91 -0
  528. package/src/modes/theme/light.json +93 -0
  529. package/src/modes/theme/mermaid-cache.ts +70 -0
  530. package/src/modes/theme/theme-schema.json +429 -0
  531. package/src/modes/theme/theme.ts +2541 -0
  532. package/src/modes/types.ts +269 -0
  533. package/src/modes/utils/hotkeys-markdown.ts +59 -0
  534. package/src/modes/utils/keybinding-matchers.ts +30 -0
  535. package/src/modes/utils/tools-markdown.ts +27 -0
  536. package/src/modes/utils/ui-helpers.ts +620 -0
  537. package/src/plan-mode/approved-plan.ts +55 -0
  538. package/src/plan-mode/state.ts +6 -0
  539. package/src/priority.json +29 -0
  540. package/src/prompts/agents/designer.md +68 -0
  541. package/src/prompts/agents/explore.md +60 -0
  542. package/src/prompts/agents/frontmatter.md +10 -0
  543. package/src/prompts/agents/init.md +36 -0
  544. package/src/prompts/agents/librarian.md +121 -0
  545. package/src/prompts/agents/plan.md +49 -0
  546. package/src/prompts/agents/reviewer.md +127 -0
  547. package/src/prompts/agents/task.md +16 -0
  548. package/src/prompts/ci-green-request.md +36 -0
  549. package/src/prompts/compaction/branch-summary-context.md +5 -0
  550. package/src/prompts/compaction/branch-summary-preamble.md +2 -0
  551. package/src/prompts/compaction/branch-summary.md +30 -0
  552. package/src/prompts/compaction/compaction-short-summary.md +9 -0
  553. package/src/prompts/compaction/compaction-summary-context.md +5 -0
  554. package/src/prompts/compaction/compaction-summary.md +38 -0
  555. package/src/prompts/compaction/compaction-turn-prefix.md +17 -0
  556. package/src/prompts/compaction/compaction-update-summary.md +45 -0
  557. package/src/prompts/memories/consolidation.md +30 -0
  558. package/src/prompts/memories/read-path.md +11 -0
  559. package/src/prompts/memories/stage_one_input.md +6 -0
  560. package/src/prompts/memories/stage_one_system.md +21 -0
  561. package/src/prompts/review-request.md +64 -0
  562. package/src/prompts/system/agent-creation-architect.md +65 -0
  563. package/src/prompts/system/agent-creation-user.md +6 -0
  564. package/src/prompts/system/auto-handoff-threshold-focus.md +1 -0
  565. package/src/prompts/system/btw-user.md +8 -0
  566. package/src/prompts/system/commit-message-system.md +2 -0
  567. package/src/prompts/system/custom-system-prompt.md +68 -0
  568. package/src/prompts/system/eager-todo.md +13 -0
  569. package/src/prompts/system/file-operations.md +10 -0
  570. package/src/prompts/system/handoff-document.md +46 -0
  571. package/src/prompts/system/plan-mode-active.md +107 -0
  572. package/src/prompts/system/plan-mode-approved.md +23 -0
  573. package/src/prompts/system/plan-mode-reference.md +14 -0
  574. package/src/prompts/system/plan-mode-subagent.md +34 -0
  575. package/src/prompts/system/plan-mode-tool-decision-reminder.md +9 -0
  576. package/src/prompts/system/subagent-submit-reminder.md +11 -0
  577. package/src/prompts/system/subagent-system-prompt.md +35 -0
  578. package/src/prompts/system/subagent-user-prompt.md +12 -0
  579. package/src/prompts/system/summarization-system.md +3 -0
  580. package/src/prompts/system/system-prompt.md +333 -0
  581. package/src/prompts/system/title-system.md +2 -0
  582. package/src/prompts/system/ttsr-interrupt.md +7 -0
  583. package/src/prompts/system/web-search.md +28 -0
  584. package/src/prompts/tools/ask.md +28 -0
  585. package/src/prompts/tools/ast-edit.md +48 -0
  586. package/src/prompts/tools/ast-grep.md +54 -0
  587. package/src/prompts/tools/async-result.md +5 -0
  588. package/src/prompts/tools/await.md +5 -0
  589. package/src/prompts/tools/bash.md +47 -0
  590. package/src/prompts/tools/browser.md +24 -0
  591. package/src/prompts/tools/calculator.md +10 -0
  592. package/src/prompts/tools/cancel-job.md +5 -0
  593. package/src/prompts/tools/checkpoint.md +16 -0
  594. package/src/prompts/tools/chunk-edit.md +219 -0
  595. package/src/prompts/tools/debug.md +43 -0
  596. package/src/prompts/tools/exit-plan-mode.md +41 -0
  597. package/src/prompts/tools/find.md +26 -0
  598. package/src/prompts/tools/gemini-image.md +7 -0
  599. package/src/prompts/tools/gh-issue-view.md +11 -0
  600. package/src/prompts/tools/gh-pr-checkout.md +12 -0
  601. package/src/prompts/tools/gh-pr-diff.md +12 -0
  602. package/src/prompts/tools/gh-pr-push.md +11 -0
  603. package/src/prompts/tools/gh-pr-view.md +11 -0
  604. package/src/prompts/tools/gh-repo-view.md +11 -0
  605. package/src/prompts/tools/gh-run-watch.md +12 -0
  606. package/src/prompts/tools/gh-search-issues.md +11 -0
  607. package/src/prompts/tools/gh-search-prs.md +11 -0
  608. package/src/prompts/tools/grep.md +29 -0
  609. package/src/prompts/tools/hashline.md +131 -0
  610. package/src/prompts/tools/inspect-image-system.md +20 -0
  611. package/src/prompts/tools/inspect-image.md +32 -0
  612. package/src/prompts/tools/lsp.md +33 -0
  613. package/src/prompts/tools/patch.md +72 -0
  614. package/src/prompts/tools/python.md +60 -0
  615. package/src/prompts/tools/read-chunk.md +17 -0
  616. package/src/prompts/tools/read.md +54 -0
  617. package/src/prompts/tools/render-mermaid.md +9 -0
  618. package/src/prompts/tools/replace.md +36 -0
  619. package/src/prompts/tools/resolve.md +8 -0
  620. package/src/prompts/tools/rewind.md +13 -0
  621. package/src/prompts/tools/search-tool-bm25.md +34 -0
  622. package/src/prompts/tools/ssh.md +44 -0
  623. package/src/prompts/tools/task-summary.md +28 -0
  624. package/src/prompts/tools/task.md +131 -0
  625. package/src/prompts/tools/todo-write.md +89 -0
  626. package/src/prompts/tools/web-search.md +10 -0
  627. package/src/prompts/tools/write.md +13 -0
  628. package/src/sdk.ts +1694 -0
  629. package/src/secrets/index.ts +116 -0
  630. package/src/secrets/obfuscator.ts +277 -0
  631. package/src/secrets/regex.ts +21 -0
  632. package/src/session/agent-session.ts +6506 -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 +373 -0
  644. package/src/session/session-dump-format.ts +203 -0
  645. package/src/session/session-manager.ts +2728 -0
  646. package/src/session/session-storage.ts +367 -0
  647. package/src/session/streaming-output.ts +752 -0
  648. package/src/session/tool-choice-queue.ts +213 -0
  649. package/src/slash-commands/builtin-registry.ts +981 -0
  650. package/src/slash-commands/marketplace-install-parser.ts +99 -0
  651. package/src/ssh/config-writer.ts +183 -0
  652. package/src/ssh/connection-manager.ts +445 -0
  653. package/src/ssh/ssh-executor.ts +128 -0
  654. package/src/ssh/sshfs-mount.ts +137 -0
  655. package/src/ssh/utils.ts +8 -0
  656. package/src/stt/downloader.ts +71 -0
  657. package/src/stt/index.ts +3 -0
  658. package/src/stt/recorder.ts +351 -0
  659. package/src/stt/setup.ts +52 -0
  660. package/src/stt/stt-controller.ts +160 -0
  661. package/src/stt/transcribe.py +70 -0
  662. package/src/stt/transcriber.ts +91 -0
  663. package/src/system-prompt.ts +620 -0
  664. package/src/task/agents.ts +166 -0
  665. package/src/task/commands.ts +131 -0
  666. package/src/task/discovery.ts +126 -0
  667. package/src/task/executor.ts +1293 -0
  668. package/src/task/index.ts +1199 -0
  669. package/src/task/isolation-backend.ts +72 -0
  670. package/src/task/name-generator.ts +1577 -0
  671. package/src/task/output-manager.ts +107 -0
  672. package/src/task/parallel.ts +116 -0
  673. package/src/task/render.ts +1021 -0
  674. package/src/task/subprocess-tool-registry.ts +88 -0
  675. package/src/task/template.ts +33 -0
  676. package/src/task/types.ts +230 -0
  677. package/src/task/worktree.ts +580 -0
  678. package/src/task/xcsh-command.ts +26 -0
  679. package/src/thinking.ts +87 -0
  680. package/src/tools/archive-reader.ts +315 -0
  681. package/src/tools/ask.ts +795 -0
  682. package/src/tools/ast-edit.ts +495 -0
  683. package/src/tools/ast-grep.ts +456 -0
  684. package/src/tools/auto-generated-guard.ts +305 -0
  685. package/src/tools/await-tool.ts +170 -0
  686. package/src/tools/bash-interactive.ts +377 -0
  687. package/src/tools/bash-interceptor.ts +67 -0
  688. package/src/tools/bash-normalize.ts +107 -0
  689. package/src/tools/bash-skill-urls.ts +246 -0
  690. package/src/tools/bash.ts +600 -0
  691. package/src/tools/browser.ts +1473 -0
  692. package/src/tools/calculator.ts +537 -0
  693. package/src/tools/cancel-job.ts +99 -0
  694. package/src/tools/checkpoint.ts +133 -0
  695. package/src/tools/context.ts +39 -0
  696. package/src/tools/debug.ts +1007 -0
  697. package/src/tools/exit-plan-mode.ts +101 -0
  698. package/src/tools/fetch.ts +1463 -0
  699. package/src/tools/find.ts +495 -0
  700. package/src/tools/fs-cache-invalidation.ts +33 -0
  701. package/src/tools/gemini-image.ts +896 -0
  702. package/src/tools/gh-renderer.ts +305 -0
  703. package/src/tools/gh.ts +2546 -0
  704. package/src/tools/grep.ts +625 -0
  705. package/src/tools/index.ts +426 -0
  706. package/src/tools/inspect-image-renderer.ts +103 -0
  707. package/src/tools/inspect-image.ts +173 -0
  708. package/src/tools/json-tree.ts +243 -0
  709. package/src/tools/jtd-to-json-schema.ts +199 -0
  710. package/src/tools/jtd-to-typescript.ts +136 -0
  711. package/src/tools/jtd-utils.ts +102 -0
  712. package/src/tools/list-limit.ts +40 -0
  713. package/src/tools/notebook.ts +288 -0
  714. package/src/tools/output-meta.ts +588 -0
  715. package/src/tools/path-utils.ts +560 -0
  716. package/src/tools/plan-mode-guard.ts +41 -0
  717. package/src/tools/puppeteer/00_stealth_tampering.txt +63 -0
  718. package/src/tools/puppeteer/01_stealth_activity.txt +20 -0
  719. package/src/tools/puppeteer/02_stealth_hairline.txt +11 -0
  720. package/src/tools/puppeteer/03_stealth_botd.txt +384 -0
  721. package/src/tools/puppeteer/04_stealth_iframe.txt +81 -0
  722. package/src/tools/puppeteer/05_stealth_webgl.txt +75 -0
  723. package/src/tools/puppeteer/06_stealth_screen.txt +72 -0
  724. package/src/tools/puppeteer/07_stealth_fonts.txt +97 -0
  725. package/src/tools/puppeteer/08_stealth_audio.txt +51 -0
  726. package/src/tools/puppeteer/09_stealth_locale.txt +46 -0
  727. package/src/tools/puppeteer/10_stealth_plugins.txt +206 -0
  728. package/src/tools/puppeteer/11_stealth_hardware.txt +8 -0
  729. package/src/tools/puppeteer/12_stealth_codecs.txt +40 -0
  730. package/src/tools/puppeteer/13_stealth_worker.txt +74 -0
  731. package/src/tools/python.ts +1135 -0
  732. package/src/tools/read.ts +1375 -0
  733. package/src/tools/render-mermaid.ts +71 -0
  734. package/src/tools/render-utils.ts +618 -0
  735. package/src/tools/renderers.ts +68 -0
  736. package/src/tools/report-tool-issue.ts +80 -0
  737. package/src/tools/resolve.ts +192 -0
  738. package/src/tools/review.ts +238 -0
  739. package/src/tools/search-tool-bm25.ts +283 -0
  740. package/src/tools/ssh.ts +320 -0
  741. package/src/tools/submit-result.ts +226 -0
  742. package/src/tools/todo-write.ts +450 -0
  743. package/src/tools/tool-errors.ts +62 -0
  744. package/src/tools/tool-result.ts +86 -0
  745. package/src/tools/tool-timeouts.ts +30 -0
  746. package/src/tools/write.ts +479 -0
  747. package/src/tui/code-cell.ts +113 -0
  748. package/src/tui/file-list.ts +47 -0
  749. package/src/tui/index.ts +11 -0
  750. package/src/tui/output-block.ts +150 -0
  751. package/src/tui/status-line.ts +39 -0
  752. package/src/tui/tree-list.ts +84 -0
  753. package/src/tui/types.ts +15 -0
  754. package/src/tui/utils.ts +103 -0
  755. package/src/utils/changelog.ts +98 -0
  756. package/src/utils/clipboard.ts +80 -0
  757. package/src/utils/command-args.ts +76 -0
  758. package/src/utils/commit-message-generator.ts +136 -0
  759. package/src/utils/edit-mode.ts +49 -0
  760. package/src/utils/event-bus.ts +33 -0
  761. package/src/utils/external-editor.ts +65 -0
  762. package/src/utils/file-display-mode.ts +37 -0
  763. package/src/utils/file-mentions.ts +376 -0
  764. package/src/utils/fuzzy.ts +108 -0
  765. package/src/utils/git.ts +1400 -0
  766. package/src/utils/image-convert.ts +27 -0
  767. package/src/utils/image-loading.ts +98 -0
  768. package/src/utils/image-resize.ts +236 -0
  769. package/src/utils/markit.ts +81 -0
  770. package/src/utils/open.ts +20 -0
  771. package/src/utils/shell-snapshot.ts +188 -0
  772. package/src/utils/sixel.ts +69 -0
  773. package/src/utils/title-generator.ts +184 -0
  774. package/src/utils/tool-choice.ts +28 -0
  775. package/src/utils/tools-manager.ts +356 -0
  776. package/src/web/kagi.ts +174 -0
  777. package/src/web/parallel.ts +346 -0
  778. package/src/web/scrapers/artifacthub.ts +207 -0
  779. package/src/web/scrapers/arxiv.ts +83 -0
  780. package/src/web/scrapers/aur.ts +162 -0
  781. package/src/web/scrapers/biorxiv.ts +133 -0
  782. package/src/web/scrapers/bluesky.ts +262 -0
  783. package/src/web/scrapers/brew.ts +172 -0
  784. package/src/web/scrapers/cheatsh.ts +68 -0
  785. package/src/web/scrapers/chocolatey.ts +196 -0
  786. package/src/web/scrapers/choosealicense.ts +95 -0
  787. package/src/web/scrapers/cisa-kev.ts +87 -0
  788. package/src/web/scrapers/clojars.ts +154 -0
  789. package/src/web/scrapers/coingecko.ts +177 -0
  790. package/src/web/scrapers/crates-io.ts +110 -0
  791. package/src/web/scrapers/crossref.ts +136 -0
  792. package/src/web/scrapers/devto.ts +147 -0
  793. package/src/web/scrapers/discogs.ts +306 -0
  794. package/src/web/scrapers/discourse.ts +197 -0
  795. package/src/web/scrapers/dockerhub.ts +138 -0
  796. package/src/web/scrapers/docs-rs.ts +653 -0
  797. package/src/web/scrapers/fdroid.ts +134 -0
  798. package/src/web/scrapers/firefox-addons.ts +191 -0
  799. package/src/web/scrapers/flathub.ts +223 -0
  800. package/src/web/scrapers/github-gist.ts +58 -0
  801. package/src/web/scrapers/github.ts +452 -0
  802. package/src/web/scrapers/gitlab.ts +401 -0
  803. package/src/web/scrapers/go-pkg.ts +266 -0
  804. package/src/web/scrapers/hackage.ts +140 -0
  805. package/src/web/scrapers/hackernews.ts +189 -0
  806. package/src/web/scrapers/hex.ts +105 -0
  807. package/src/web/scrapers/huggingface.ts +321 -0
  808. package/src/web/scrapers/iacr.ts +89 -0
  809. package/src/web/scrapers/index.ts +252 -0
  810. package/src/web/scrapers/jetbrains-marketplace.ts +159 -0
  811. package/src/web/scrapers/lemmy.ts +203 -0
  812. package/src/web/scrapers/lobsters.ts +175 -0
  813. package/src/web/scrapers/mastodon.ts +292 -0
  814. package/src/web/scrapers/maven.ts +138 -0
  815. package/src/web/scrapers/mdn.ts +169 -0
  816. package/src/web/scrapers/metacpan.ts +222 -0
  817. package/src/web/scrapers/musicbrainz.ts +250 -0
  818. package/src/web/scrapers/npm.ts +98 -0
  819. package/src/web/scrapers/nuget.ts +183 -0
  820. package/src/web/scrapers/nvd.ts +222 -0
  821. package/src/web/scrapers/ollama.ts +239 -0
  822. package/src/web/scrapers/open-vsx.ts +106 -0
  823. package/src/web/scrapers/opencorporates.ts +292 -0
  824. package/src/web/scrapers/openlibrary.ts +336 -0
  825. package/src/web/scrapers/orcid.ts +286 -0
  826. package/src/web/scrapers/osv.ts +176 -0
  827. package/src/web/scrapers/packagist.ts +160 -0
  828. package/src/web/scrapers/pub-dev.ts +143 -0
  829. package/src/web/scrapers/pubmed.ts +211 -0
  830. package/src/web/scrapers/pypi.ts +112 -0
  831. package/src/web/scrapers/rawg.ts +110 -0
  832. package/src/web/scrapers/readthedocs.ts +120 -0
  833. package/src/web/scrapers/reddit.ts +95 -0
  834. package/src/web/scrapers/repology.ts +251 -0
  835. package/src/web/scrapers/rfc.ts +201 -0
  836. package/src/web/scrapers/rubygems.ts +103 -0
  837. package/src/web/scrapers/searchcode.ts +190 -0
  838. package/src/web/scrapers/sec-edgar.ts +261 -0
  839. package/src/web/scrapers/semantic-scholar.ts +171 -0
  840. package/src/web/scrapers/snapcraft.ts +187 -0
  841. package/src/web/scrapers/sourcegraph.ts +336 -0
  842. package/src/web/scrapers/spdx.ts +108 -0
  843. package/src/web/scrapers/spotify.ts +198 -0
  844. package/src/web/scrapers/stackoverflow.ts +120 -0
  845. package/src/web/scrapers/terraform.ts +277 -0
  846. package/src/web/scrapers/tldr.ts +47 -0
  847. package/src/web/scrapers/twitter.ts +93 -0
  848. package/src/web/scrapers/types.ts +267 -0
  849. package/src/web/scrapers/utils.ts +109 -0
  850. package/src/web/scrapers/vimeo.ts +133 -0
  851. package/src/web/scrapers/vscode-marketplace.ts +187 -0
  852. package/src/web/scrapers/w3c.ts +156 -0
  853. package/src/web/scrapers/wikidata.ts +344 -0
  854. package/src/web/scrapers/wikipedia.ts +84 -0
  855. package/src/web/scrapers/youtube.ts +313 -0
  856. package/src/web/search/index.ts +268 -0
  857. package/src/web/search/provider.ts +86 -0
  858. package/src/web/search/providers/anthropic.ts +286 -0
  859. package/src/web/search/providers/base.ts +25 -0
  860. package/src/web/search/providers/brave.ts +150 -0
  861. package/src/web/search/providers/codex.ts +383 -0
  862. package/src/web/search/providers/exa.ts +264 -0
  863. package/src/web/search/providers/gemini.ts +566 -0
  864. package/src/web/search/providers/jina.ts +99 -0
  865. package/src/web/search/providers/kagi.ts +70 -0
  866. package/src/web/search/providers/kimi.ts +157 -0
  867. package/src/web/search/providers/parallel.ts +63 -0
  868. package/src/web/search/providers/perplexity.ts +546 -0
  869. package/src/web/search/providers/synthetic.ts +113 -0
  870. package/src/web/search/providers/tavily.ts +162 -0
  871. package/src/web/search/providers/utils.ts +36 -0
  872. package/src/web/search/providers/zai.ts +311 -0
  873. package/src/web/search/render.ts +299 -0
  874. package/src/web/search/types.ts +434 -0
  875. package/src/web/search/utils.ts +17 -0
  876. package/dist/bun/cli.d.ts +0 -3
  877. package/dist/bun/cli.d.ts.map +0 -1
  878. package/dist/bun/cli.js +0 -7
  879. package/dist/bun/cli.js.map +0 -1
  880. package/dist/bun/register-bedrock.d.ts +0 -2
  881. package/dist/bun/register-bedrock.d.ts.map +0 -1
  882. package/dist/bun/register-bedrock.js +0 -4
  883. package/dist/bun/register-bedrock.js.map +0 -1
  884. package/dist/cli/args.d.ts +0 -52
  885. package/dist/cli/args.d.ts.map +0 -1
  886. package/dist/cli/args.js +0 -326
  887. package/dist/cli/args.js.map +0 -1
  888. package/dist/cli/config-selector.d.ts +0 -14
  889. package/dist/cli/config-selector.d.ts.map +0 -1
  890. package/dist/cli/config-selector.js +0 -31
  891. package/dist/cli/config-selector.js.map +0 -1
  892. package/dist/cli/file-processor.d.ts +0 -15
  893. package/dist/cli/file-processor.d.ts.map +0 -1
  894. package/dist/cli/file-processor.js +0 -83
  895. package/dist/cli/file-processor.js.map +0 -1
  896. package/dist/cli/initial-message.d.ts +0 -18
  897. package/dist/cli/initial-message.d.ts.map +0 -1
  898. package/dist/cli/initial-message.js +0 -22
  899. package/dist/cli/initial-message.js.map +0 -1
  900. package/dist/cli/list-models.d.ts +0 -9
  901. package/dist/cli/list-models.d.ts.map +0 -1
  902. package/dist/cli/list-models.js +0 -92
  903. package/dist/cli/list-models.js.map +0 -1
  904. package/dist/cli/session-picker.d.ts +0 -9
  905. package/dist/cli/session-picker.d.ts.map +0 -1
  906. package/dist/cli/session-picker.js +0 -35
  907. package/dist/cli/session-picker.js.map +0 -1
  908. package/dist/cli.d.ts +0 -3
  909. package/dist/cli.d.ts.map +0 -1
  910. package/dist/cli.js +0 -14
  911. package/dist/cli.js.map +0 -1
  912. package/dist/config.d.ts +0 -68
  913. package/dist/config.d.ts.map +0 -1
  914. package/dist/config.js +0 -203
  915. package/dist/config.js.map +0 -1
  916. package/dist/core/agent-session-runtime.d.ts +0 -83
  917. package/dist/core/agent-session-runtime.d.ts.map +0 -1
  918. package/dist/core/agent-session-runtime.js +0 -236
  919. package/dist/core/agent-session-runtime.js.map +0 -1
  920. package/dist/core/agent-session-services.d.ts +0 -86
  921. package/dist/core/agent-session-services.d.ts.map +0 -1
  922. package/dist/core/agent-session-services.js +0 -116
  923. package/dist/core/agent-session-services.js.map +0 -1
  924. package/dist/core/agent-session.d.ts +0 -585
  925. package/dist/core/agent-session.d.ts.map +0 -1
  926. package/dist/core/agent-session.js +0 -2497
  927. package/dist/core/agent-session.js.map +0 -1
  928. package/dist/core/auth-storage.d.ts +0 -132
  929. package/dist/core/auth-storage.d.ts.map +0 -1
  930. package/dist/core/auth-storage.js +0 -422
  931. package/dist/core/auth-storage.js.map +0 -1
  932. package/dist/core/bash-executor.d.ts +0 -46
  933. package/dist/core/bash-executor.d.ts.map +0 -1
  934. package/dist/core/bash-executor.js +0 -125
  935. package/dist/core/bash-executor.js.map +0 -1
  936. package/dist/core/compaction/branch-summarization.d.ts +0 -88
  937. package/dist/core/compaction/branch-summarization.d.ts.map +0 -1
  938. package/dist/core/compaction/branch-summarization.js +0 -243
  939. package/dist/core/compaction/branch-summarization.js.map +0 -1
  940. package/dist/core/compaction/compaction.d.ts +0 -121
  941. package/dist/core/compaction/compaction.d.ts.map +0 -1
  942. package/dist/core/compaction/compaction.js +0 -613
  943. package/dist/core/compaction/compaction.js.map +0 -1
  944. package/dist/core/compaction/index.d.ts +0 -7
  945. package/dist/core/compaction/index.d.ts.map +0 -1
  946. package/dist/core/compaction/index.js +0 -7
  947. package/dist/core/compaction/index.js.map +0 -1
  948. package/dist/core/compaction/utils.d.ts +0 -38
  949. package/dist/core/compaction/utils.d.ts.map +0 -1
  950. package/dist/core/compaction/utils.js +0 -153
  951. package/dist/core/compaction/utils.js.map +0 -1
  952. package/dist/core/defaults.d.ts +0 -3
  953. package/dist/core/defaults.d.ts.map +0 -1
  954. package/dist/core/defaults.js +0 -2
  955. package/dist/core/defaults.js.map +0 -1
  956. package/dist/core/diagnostics.d.ts +0 -15
  957. package/dist/core/diagnostics.d.ts.map +0 -1
  958. package/dist/core/diagnostics.js +0 -2
  959. package/dist/core/diagnostics.js.map +0 -1
  960. package/dist/core/event-bus.d.ts +0 -9
  961. package/dist/core/event-bus.d.ts.map +0 -1
  962. package/dist/core/event-bus.js +0 -25
  963. package/dist/core/event-bus.js.map +0 -1
  964. package/dist/core/exec.d.ts +0 -29
  965. package/dist/core/exec.d.ts.map +0 -1
  966. package/dist/core/exec.js +0 -75
  967. package/dist/core/exec.js.map +0 -1
  968. package/dist/core/export-html/ansi-to-html.d.ts +0 -22
  969. package/dist/core/export-html/ansi-to-html.d.ts.map +0 -1
  970. package/dist/core/export-html/ansi-to-html.js +0 -249
  971. package/dist/core/export-html/ansi-to-html.js.map +0 -1
  972. package/dist/core/export-html/index.d.ts +0 -37
  973. package/dist/core/export-html/index.d.ts.map +0 -1
  974. package/dist/core/export-html/index.js +0 -224
  975. package/dist/core/export-html/index.js.map +0 -1
  976. package/dist/core/export-html/template.css +0 -1001
  977. package/dist/core/export-html/template.html +0 -55
  978. package/dist/core/export-html/template.js +0 -1690
  979. package/dist/core/export-html/tool-renderer.d.ts +0 -40
  980. package/dist/core/export-html/tool-renderer.d.ts.map +0 -1
  981. package/dist/core/export-html/tool-renderer.js +0 -95
  982. package/dist/core/export-html/tool-renderer.js.map +0 -1
  983. package/dist/core/extensions/index.d.ts +0 -12
  984. package/dist/core/extensions/index.d.ts.map +0 -1
  985. package/dist/core/extensions/index.js +0 -9
  986. package/dist/core/extensions/index.js.map +0 -1
  987. package/dist/core/extensions/loader.d.ts +0 -25
  988. package/dist/core/extensions/loader.d.ts.map +0 -1
  989. package/dist/core/extensions/loader.js +0 -436
  990. package/dist/core/extensions/loader.js.map +0 -1
  991. package/dist/core/extensions/runner.d.ts +0 -148
  992. package/dist/core/extensions/runner.d.ts.map +0 -1
  993. package/dist/core/extensions/runner.js +0 -700
  994. package/dist/core/extensions/runner.js.map +0 -1
  995. package/dist/core/extensions/types.d.ts +0 -1073
  996. package/dist/core/extensions/types.d.ts.map +0 -1
  997. package/dist/core/extensions/types.js +0 -45
  998. package/dist/core/extensions/types.js.map +0 -1
  999. package/dist/core/extensions/wrapper.d.ts +0 -20
  1000. package/dist/core/extensions/wrapper.d.ts.map +0 -1
  1001. package/dist/core/extensions/wrapper.js +0 -22
  1002. package/dist/core/extensions/wrapper.js.map +0 -1
  1003. package/dist/core/footer-data-provider.d.ts +0 -48
  1004. package/dist/core/footer-data-provider.d.ts.map +0 -1
  1005. package/dist/core/footer-data-provider.js +0 -314
  1006. package/dist/core/footer-data-provider.js.map +0 -1
  1007. package/dist/core/index.d.ts +0 -12
  1008. package/dist/core/index.d.ts.map +0 -1
  1009. package/dist/core/index.js +0 -12
  1010. package/dist/core/index.js.map +0 -1
  1011. package/dist/core/keybindings.d.ts +0 -288
  1012. package/dist/core/keybindings.d.ts.map +0 -1
  1013. package/dist/core/keybindings.js +0 -240
  1014. package/dist/core/keybindings.js.map +0 -1
  1015. package/dist/core/messages.d.ts +0 -77
  1016. package/dist/core/messages.d.ts.map +0 -1
  1017. package/dist/core/messages.js +0 -123
  1018. package/dist/core/messages.js.map +0 -1
  1019. package/dist/core/model-registry.d.ts +0 -132
  1020. package/dist/core/model-registry.d.ts.map +0 -1
  1021. package/dist/core/model-registry.js +0 -583
  1022. package/dist/core/model-registry.js.map +0 -1
  1023. package/dist/core/model-resolver.d.ts +0 -110
  1024. package/dist/core/model-resolver.d.ts.map +0 -1
  1025. package/dist/core/model-resolver.js +0 -486
  1026. package/dist/core/model-resolver.js.map +0 -1
  1027. package/dist/core/output-guard.d.ts +0 -6
  1028. package/dist/core/output-guard.d.ts.map +0 -1
  1029. package/dist/core/output-guard.js +0 -59
  1030. package/dist/core/output-guard.js.map +0 -1
  1031. package/dist/core/package-manager.d.ts +0 -192
  1032. package/dist/core/package-manager.d.ts.map +0 -1
  1033. package/dist/core/package-manager.js +0 -1832
  1034. package/dist/core/package-manager.js.map +0 -1
  1035. package/dist/core/prompt-templates.d.ts +0 -51
  1036. package/dist/core/prompt-templates.d.ts.map +0 -1
  1037. package/dist/core/prompt-templates.js +0 -249
  1038. package/dist/core/prompt-templates.js.map +0 -1
  1039. package/dist/core/resolve-config-value.d.ts +0 -23
  1040. package/dist/core/resolve-config-value.d.ts.map +0 -1
  1041. package/dist/core/resolve-config-value.js +0 -126
  1042. package/dist/core/resolve-config-value.js.map +0 -1
  1043. package/dist/core/resource-loader.d.ts +0 -185
  1044. package/dist/core/resource-loader.d.ts.map +0 -1
  1045. package/dist/core/resource-loader.js +0 -720
  1046. package/dist/core/resource-loader.js.map +0 -1
  1047. package/dist/core/sdk.d.ts +0 -93
  1048. package/dist/core/sdk.d.ts.map +0 -1
  1049. package/dist/core/sdk.js +0 -236
  1050. package/dist/core/sdk.js.map +0 -1
  1051. package/dist/core/session-cwd.d.ts +0 -19
  1052. package/dist/core/session-cwd.d.ts.map +0 -1
  1053. package/dist/core/session-cwd.js +0 -38
  1054. package/dist/core/session-cwd.js.map +0 -1
  1055. package/dist/core/session-manager.d.ts +0 -333
  1056. package/dist/core/session-manager.d.ts.map +0 -1
  1057. package/dist/core/session-manager.js +0 -1105
  1058. package/dist/core/session-manager.js.map +0 -1
  1059. package/dist/core/settings-manager.d.ts +0 -237
  1060. package/dist/core/settings-manager.d.ts.map +0 -1
  1061. package/dist/core/settings-manager.js +0 -703
  1062. package/dist/core/settings-manager.js.map +0 -1
  1063. package/dist/core/skills.d.ts +0 -60
  1064. package/dist/core/skills.d.ts.map +0 -1
  1065. package/dist/core/skills.js +0 -409
  1066. package/dist/core/skills.js.map +0 -1
  1067. package/dist/core/slash-commands.d.ts +0 -14
  1068. package/dist/core/slash-commands.d.ts.map +0 -1
  1069. package/dist/core/slash-commands.js +0 -23
  1070. package/dist/core/slash-commands.js.map +0 -1
  1071. package/dist/core/source-info.d.ts +0 -18
  1072. package/dist/core/source-info.d.ts.map +0 -1
  1073. package/dist/core/source-info.js +0 -19
  1074. package/dist/core/source-info.js.map +0 -1
  1075. package/dist/core/system-prompt.d.ts +0 -28
  1076. package/dist/core/system-prompt.d.ts.map +0 -1
  1077. package/dist/core/system-prompt.js +0 -116
  1078. package/dist/core/system-prompt.js.map +0 -1
  1079. package/dist/core/timings.d.ts +0 -8
  1080. package/dist/core/timings.d.ts.map +0 -1
  1081. package/dist/core/timings.js +0 -31
  1082. package/dist/core/timings.js.map +0 -1
  1083. package/dist/core/tools/bash.d.ts +0 -73
  1084. package/dist/core/tools/bash.d.ts.map +0 -1
  1085. package/dist/core/tools/bash.js +0 -352
  1086. package/dist/core/tools/bash.js.map +0 -1
  1087. package/dist/core/tools/edit-diff.d.ts +0 -85
  1088. package/dist/core/tools/edit-diff.d.ts.map +0 -1
  1089. package/dist/core/tools/edit-diff.js +0 -337
  1090. package/dist/core/tools/edit-diff.js.map +0 -1
  1091. package/dist/core/tools/edit.d.ts +0 -53
  1092. package/dist/core/tools/edit.d.ts.map +0 -1
  1093. package/dist/core/tools/edit.js +0 -196
  1094. package/dist/core/tools/edit.js.map +0 -1
  1095. package/dist/core/tools/file-mutation-queue.d.ts +0 -6
  1096. package/dist/core/tools/file-mutation-queue.d.ts.map +0 -1
  1097. package/dist/core/tools/file-mutation-queue.js +0 -37
  1098. package/dist/core/tools/file-mutation-queue.js.map +0 -1
  1099. package/dist/core/tools/find.d.ts +0 -46
  1100. package/dist/core/tools/find.d.ts.map +0 -1
  1101. package/dist/core/tools/find.js +0 -258
  1102. package/dist/core/tools/find.js.map +0 -1
  1103. package/dist/core/tools/grep.d.ts +0 -56
  1104. package/dist/core/tools/grep.d.ts.map +0 -1
  1105. package/dist/core/tools/grep.js +0 -293
  1106. package/dist/core/tools/grep.js.map +0 -1
  1107. package/dist/core/tools/index.d.ts +0 -115
  1108. package/dist/core/tools/index.d.ts.map +0 -1
  1109. package/dist/core/tools/index.js +0 -86
  1110. package/dist/core/tools/index.js.map +0 -1
  1111. package/dist/core/tools/ls.d.ts +0 -46
  1112. package/dist/core/tools/ls.d.ts.map +0 -1
  1113. package/dist/core/tools/ls.js +0 -172
  1114. package/dist/core/tools/ls.js.map +0 -1
  1115. package/dist/core/tools/path-utils.d.ts +0 -8
  1116. package/dist/core/tools/path-utils.d.ts.map +0 -1
  1117. package/dist/core/tools/path-utils.js +0 -81
  1118. package/dist/core/tools/path-utils.js.map +0 -1
  1119. package/dist/core/tools/read.d.ts +0 -46
  1120. package/dist/core/tools/read.d.ts.map +0 -1
  1121. package/dist/core/tools/read.js +0 -225
  1122. package/dist/core/tools/read.js.map +0 -1
  1123. package/dist/core/tools/render-utils.d.ts +0 -21
  1124. package/dist/core/tools/render-utils.d.ts.map +0 -1
  1125. package/dist/core/tools/render-utils.js +0 -49
  1126. package/dist/core/tools/render-utils.js.map +0 -1
  1127. package/dist/core/tools/tool-definition-wrapper.d.ts +0 -14
  1128. package/dist/core/tools/tool-definition-wrapper.d.ts.map +0 -1
  1129. package/dist/core/tools/tool-definition-wrapper.js +0 -32
  1130. package/dist/core/tools/tool-definition-wrapper.js.map +0 -1
  1131. package/dist/core/tools/truncate.d.ts +0 -70
  1132. package/dist/core/tools/truncate.d.ts.map +0 -1
  1133. package/dist/core/tools/truncate.js +0 -205
  1134. package/dist/core/tools/truncate.js.map +0 -1
  1135. package/dist/core/tools/write.d.ts +0 -35
  1136. package/dist/core/tools/write.d.ts.map +0 -1
  1137. package/dist/core/tools/write.js +0 -216
  1138. package/dist/core/tools/write.js.map +0 -1
  1139. package/dist/index.d.ts +0 -28
  1140. package/dist/index.d.ts.map +0 -1
  1141. package/dist/index.js +0 -43
  1142. package/dist/index.js.map +0 -1
  1143. package/dist/main.d.ts +0 -8
  1144. package/dist/main.d.ts.map +0 -1
  1145. package/dist/main.js +0 -593
  1146. package/dist/main.js.map +0 -1
  1147. package/dist/migrations.d.ts +0 -33
  1148. package/dist/migrations.d.ts.map +0 -1
  1149. package/dist/migrations.js +0 -281
  1150. package/dist/migrations.js.map +0 -1
  1151. package/dist/modes/index.d.ts +0 -9
  1152. package/dist/modes/index.d.ts.map +0 -1
  1153. package/dist/modes/index.js +0 -8
  1154. package/dist/modes/index.js.map +0 -1
  1155. package/dist/modes/interactive/components/armin.d.ts +0 -34
  1156. package/dist/modes/interactive/components/armin.d.ts.map +0 -1
  1157. package/dist/modes/interactive/components/armin.js +0 -333
  1158. package/dist/modes/interactive/components/armin.js.map +0 -1
  1159. package/dist/modes/interactive/components/assistant-message.d.ts +0 -18
  1160. package/dist/modes/interactive/components/assistant-message.d.ts.map +0 -1
  1161. package/dist/modes/interactive/components/assistant-message.js +0 -107
  1162. package/dist/modes/interactive/components/assistant-message.js.map +0 -1
  1163. package/dist/modes/interactive/components/bash-execution.d.ts +0 -34
  1164. package/dist/modes/interactive/components/bash-execution.d.ts.map +0 -1
  1165. package/dist/modes/interactive/components/bash-execution.js +0 -175
  1166. package/dist/modes/interactive/components/bash-execution.js.map +0 -1
  1167. package/dist/modes/interactive/components/bordered-loader.d.ts +0 -16
  1168. package/dist/modes/interactive/components/bordered-loader.d.ts.map +0 -1
  1169. package/dist/modes/interactive/components/bordered-loader.js +0 -51
  1170. package/dist/modes/interactive/components/bordered-loader.js.map +0 -1
  1171. package/dist/modes/interactive/components/branch-summary-message.d.ts +0 -16
  1172. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +0 -1
  1173. package/dist/modes/interactive/components/branch-summary-message.js +0 -44
  1174. package/dist/modes/interactive/components/branch-summary-message.js.map +0 -1
  1175. package/dist/modes/interactive/components/compaction-summary-message.d.ts +0 -16
  1176. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +0 -1
  1177. package/dist/modes/interactive/components/compaction-summary-message.js +0 -45
  1178. package/dist/modes/interactive/components/compaction-summary-message.js.map +0 -1
  1179. package/dist/modes/interactive/components/config-selector.d.ts +0 -71
  1180. package/dist/modes/interactive/components/config-selector.d.ts.map +0 -1
  1181. package/dist/modes/interactive/components/config-selector.js +0 -479
  1182. package/dist/modes/interactive/components/config-selector.js.map +0 -1
  1183. package/dist/modes/interactive/components/countdown-timer.d.ts +0 -14
  1184. package/dist/modes/interactive/components/countdown-timer.d.ts.map +0 -1
  1185. package/dist/modes/interactive/components/countdown-timer.js +0 -33
  1186. package/dist/modes/interactive/components/countdown-timer.js.map +0 -1
  1187. package/dist/modes/interactive/components/custom-editor.d.ts +0 -21
  1188. package/dist/modes/interactive/components/custom-editor.d.ts.map +0 -1
  1189. package/dist/modes/interactive/components/custom-editor.js +0 -70
  1190. package/dist/modes/interactive/components/custom-editor.js.map +0 -1
  1191. package/dist/modes/interactive/components/custom-message.d.ts +0 -20
  1192. package/dist/modes/interactive/components/custom-message.d.ts.map +0 -1
  1193. package/dist/modes/interactive/components/custom-message.js +0 -79
  1194. package/dist/modes/interactive/components/custom-message.js.map +0 -1
  1195. package/dist/modes/interactive/components/daxnuts.d.ts +0 -23
  1196. package/dist/modes/interactive/components/daxnuts.d.ts.map +0 -1
  1197. package/dist/modes/interactive/components/daxnuts.js +0 -140
  1198. package/dist/modes/interactive/components/daxnuts.js.map +0 -1
  1199. package/dist/modes/interactive/components/diff.d.ts +0 -12
  1200. package/dist/modes/interactive/components/diff.d.ts.map +0 -1
  1201. package/dist/modes/interactive/components/diff.js +0 -133
  1202. package/dist/modes/interactive/components/diff.js.map +0 -1
  1203. package/dist/modes/interactive/components/dynamic-border.d.ts +0 -15
  1204. package/dist/modes/interactive/components/dynamic-border.d.ts.map +0 -1
  1205. package/dist/modes/interactive/components/dynamic-border.js +0 -21
  1206. package/dist/modes/interactive/components/dynamic-border.js.map +0 -1
  1207. package/dist/modes/interactive/components/extension-editor.d.ts +0 -20
  1208. package/dist/modes/interactive/components/extension-editor.d.ts.map +0 -1
  1209. package/dist/modes/interactive/components/extension-editor.js +0 -111
  1210. package/dist/modes/interactive/components/extension-editor.js.map +0 -1
  1211. package/dist/modes/interactive/components/extension-input.d.ts +0 -23
  1212. package/dist/modes/interactive/components/extension-input.d.ts.map +0 -1
  1213. package/dist/modes/interactive/components/extension-input.js +0 -61
  1214. package/dist/modes/interactive/components/extension-input.js.map +0 -1
  1215. package/dist/modes/interactive/components/extension-selector.d.ts +0 -24
  1216. package/dist/modes/interactive/components/extension-selector.d.ts.map +0 -1
  1217. package/dist/modes/interactive/components/extension-selector.js +0 -78
  1218. package/dist/modes/interactive/components/extension-selector.js.map +0 -1
  1219. package/dist/modes/interactive/components/footer.d.ts +0 -27
  1220. package/dist/modes/interactive/components/footer.d.ts.map +0 -1
  1221. package/dist/modes/interactive/components/footer.js +0 -201
  1222. package/dist/modes/interactive/components/footer.js.map +0 -1
  1223. package/dist/modes/interactive/components/index.d.ts +0 -32
  1224. package/dist/modes/interactive/components/index.d.ts.map +0 -1
  1225. package/dist/modes/interactive/components/index.js +0 -33
  1226. package/dist/modes/interactive/components/index.js.map +0 -1
  1227. package/dist/modes/interactive/components/keybinding-hints.d.ts +0 -8
  1228. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +0 -1
  1229. package/dist/modes/interactive/components/keybinding-hints.js +0 -22
  1230. package/dist/modes/interactive/components/keybinding-hints.js.map +0 -1
  1231. package/dist/modes/interactive/components/login-dialog.d.ts +0 -42
  1232. package/dist/modes/interactive/components/login-dialog.d.ts.map +0 -1
  1233. package/dist/modes/interactive/components/login-dialog.js +0 -145
  1234. package/dist/modes/interactive/components/login-dialog.js.map +0 -1
  1235. package/dist/modes/interactive/components/model-selector.d.ts +0 -47
  1236. package/dist/modes/interactive/components/model-selector.d.ts.map +0 -1
  1237. package/dist/modes/interactive/components/model-selector.js +0 -275
  1238. package/dist/modes/interactive/components/model-selector.js.map +0 -1
  1239. package/dist/modes/interactive/components/oauth-selector.d.ts +0 -19
  1240. package/dist/modes/interactive/components/oauth-selector.d.ts.map +0 -1
  1241. package/dist/modes/interactive/components/oauth-selector.js +0 -97
  1242. package/dist/modes/interactive/components/oauth-selector.js.map +0 -1
  1243. package/dist/modes/interactive/components/scoped-models-selector.d.ts +0 -49
  1244. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +0 -1
  1245. package/dist/modes/interactive/components/scoped-models-selector.js +0 -275
  1246. package/dist/modes/interactive/components/scoped-models-selector.js.map +0 -1
  1247. package/dist/modes/interactive/components/session-selector-search.d.ts +0 -23
  1248. package/dist/modes/interactive/components/session-selector-search.d.ts.map +0 -1
  1249. package/dist/modes/interactive/components/session-selector-search.js +0 -155
  1250. package/dist/modes/interactive/components/session-selector-search.js.map +0 -1
  1251. package/dist/modes/interactive/components/session-selector.d.ts +0 -95
  1252. package/dist/modes/interactive/components/session-selector.d.ts.map +0 -1
  1253. package/dist/modes/interactive/components/session-selector.js +0 -848
  1254. package/dist/modes/interactive/components/session-selector.js.map +0 -1
  1255. package/dist/modes/interactive/components/settings-selector.d.ts +0 -58
  1256. package/dist/modes/interactive/components/settings-selector.d.ts.map +0 -1
  1257. package/dist/modes/interactive/components/settings-selector.js +0 -301
  1258. package/dist/modes/interactive/components/settings-selector.js.map +0 -1
  1259. package/dist/modes/interactive/components/show-images-selector.d.ts +0 -10
  1260. package/dist/modes/interactive/components/show-images-selector.d.ts.map +0 -1
  1261. package/dist/modes/interactive/components/show-images-selector.js +0 -39
  1262. package/dist/modes/interactive/components/show-images-selector.js.map +0 -1
  1263. package/dist/modes/interactive/components/skill-invocation-message.d.ts +0 -17
  1264. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +0 -1
  1265. package/dist/modes/interactive/components/skill-invocation-message.js +0 -47
  1266. package/dist/modes/interactive/components/skill-invocation-message.js.map +0 -1
  1267. package/dist/modes/interactive/components/theme-selector.d.ts +0 -11
  1268. package/dist/modes/interactive/components/theme-selector.d.ts.map +0 -1
  1269. package/dist/modes/interactive/components/theme-selector.js +0 -50
  1270. package/dist/modes/interactive/components/theme-selector.js.map +0 -1
  1271. package/dist/modes/interactive/components/thinking-selector.d.ts +0 -11
  1272. package/dist/modes/interactive/components/thinking-selector.d.ts.map +0 -1
  1273. package/dist/modes/interactive/components/thinking-selector.js +0 -51
  1274. package/dist/modes/interactive/components/thinking-selector.js.map +0 -1
  1275. package/dist/modes/interactive/components/tool-execution.d.ts +0 -58
  1276. package/dist/modes/interactive/components/tool-execution.d.ts.map +0 -1
  1277. package/dist/modes/interactive/components/tool-execution.js +0 -274
  1278. package/dist/modes/interactive/components/tool-execution.js.map +0 -1
  1279. package/dist/modes/interactive/components/tree-selector.d.ts +0 -89
  1280. package/dist/modes/interactive/components/tree-selector.d.ts.map +0 -1
  1281. package/dist/modes/interactive/components/tree-selector.js +0 -1084
  1282. package/dist/modes/interactive/components/tree-selector.js.map +0 -1
  1283. package/dist/modes/interactive/components/user-message-selector.d.ts +0 -30
  1284. package/dist/modes/interactive/components/user-message-selector.d.ts.map +0 -1
  1285. package/dist/modes/interactive/components/user-message-selector.js +0 -113
  1286. package/dist/modes/interactive/components/user-message-selector.js.map +0 -1
  1287. package/dist/modes/interactive/components/user-message.d.ts +0 -9
  1288. package/dist/modes/interactive/components/user-message.d.ts.map +0 -1
  1289. package/dist/modes/interactive/components/user-message.js +0 -28
  1290. package/dist/modes/interactive/components/user-message.js.map +0 -1
  1291. package/dist/modes/interactive/components/visual-truncate.d.ts +0 -24
  1292. package/dist/modes/interactive/components/visual-truncate.d.ts.map +0 -1
  1293. package/dist/modes/interactive/components/visual-truncate.js +0 -33
  1294. package/dist/modes/interactive/components/visual-truncate.js.map +0 -1
  1295. package/dist/modes/interactive/interactive-mode.d.ts +0 -320
  1296. package/dist/modes/interactive/interactive-mode.d.ts.map +0 -1
  1297. package/dist/modes/interactive/interactive-mode.js +0 -3970
  1298. package/dist/modes/interactive/interactive-mode.js.map +0 -1
  1299. package/dist/modes/interactive/theme/dark.json +0 -85
  1300. package/dist/modes/interactive/theme/light.json +0 -84
  1301. package/dist/modes/interactive/theme/theme-schema.json +0 -335
  1302. package/dist/modes/interactive/theme/theme.d.ts +0 -81
  1303. package/dist/modes/interactive/theme/theme.d.ts.map +0 -1
  1304. package/dist/modes/interactive/theme/theme.js +0 -979
  1305. package/dist/modes/interactive/theme/theme.js.map +0 -1
  1306. package/dist/modes/print-mode.d.ts +0 -28
  1307. package/dist/modes/print-mode.d.ts.map +0 -1
  1308. package/dist/modes/print-mode.js +0 -112
  1309. package/dist/modes/print-mode.js.map +0 -1
  1310. package/dist/modes/rpc/jsonl.d.ts +0 -17
  1311. package/dist/modes/rpc/jsonl.d.ts.map +0 -1
  1312. package/dist/modes/rpc/jsonl.js +0 -49
  1313. package/dist/modes/rpc/jsonl.js.map +0 -1
  1314. package/dist/modes/rpc/rpc-client.d.ts +0 -217
  1315. package/dist/modes/rpc/rpc-client.d.ts.map +0 -1
  1316. package/dist/modes/rpc/rpc-client.js +0 -402
  1317. package/dist/modes/rpc/rpc-client.js.map +0 -1
  1318. package/dist/modes/rpc/rpc-mode.d.ts +0 -20
  1319. package/dist/modes/rpc/rpc-mode.d.ts.map +0 -1
  1320. package/dist/modes/rpc/rpc-mode.js +0 -550
  1321. package/dist/modes/rpc/rpc-mode.js.map +0 -1
  1322. package/dist/modes/rpc/rpc-types.d.ts +0 -408
  1323. package/dist/modes/rpc/rpc-types.d.ts.map +0 -1
  1324. package/dist/modes/rpc/rpc-types.js +0 -8
  1325. package/dist/modes/rpc/rpc-types.js.map +0 -1
  1326. package/dist/package-manager-cli.d.ts +0 -4
  1327. package/dist/package-manager-cli.d.ts.map +0 -1
  1328. package/dist/package-manager-cli.js +0 -234
  1329. package/dist/package-manager-cli.js.map +0 -1
  1330. package/dist/utils/changelog.d.ts +0 -21
  1331. package/dist/utils/changelog.d.ts.map +0 -1
  1332. package/dist/utils/changelog.js +0 -87
  1333. package/dist/utils/changelog.js.map +0 -1
  1334. package/dist/utils/child-process.d.ts +0 -11
  1335. package/dist/utils/child-process.d.ts.map +0 -1
  1336. package/dist/utils/child-process.js +0 -78
  1337. package/dist/utils/child-process.js.map +0 -1
  1338. package/dist/utils/clipboard-image.d.ts +0 -11
  1339. package/dist/utils/clipboard-image.d.ts.map +0 -1
  1340. package/dist/utils/clipboard-image.js +0 -245
  1341. package/dist/utils/clipboard-image.js.map +0 -1
  1342. package/dist/utils/clipboard-native.d.ts +0 -8
  1343. package/dist/utils/clipboard-native.d.ts.map +0 -1
  1344. package/dist/utils/clipboard-native.js +0 -14
  1345. package/dist/utils/clipboard-native.js.map +0 -1
  1346. package/dist/utils/clipboard.d.ts +0 -2
  1347. package/dist/utils/clipboard.d.ts.map +0 -1
  1348. package/dist/utils/clipboard.js +0 -78
  1349. package/dist/utils/clipboard.js.map +0 -1
  1350. package/dist/utils/exif-orientation.d.ts +0 -5
  1351. package/dist/utils/exif-orientation.d.ts.map +0 -1
  1352. package/dist/utils/exif-orientation.js +0 -158
  1353. package/dist/utils/exif-orientation.js.map +0 -1
  1354. package/dist/utils/frontmatter.d.ts +0 -8
  1355. package/dist/utils/frontmatter.d.ts.map +0 -1
  1356. package/dist/utils/frontmatter.js +0 -26
  1357. package/dist/utils/frontmatter.js.map +0 -1
  1358. package/dist/utils/git.d.ts +0 -26
  1359. package/dist/utils/git.d.ts.map +0 -1
  1360. package/dist/utils/git.js +0 -163
  1361. package/dist/utils/git.js.map +0 -1
  1362. package/dist/utils/image-convert.d.ts +0 -9
  1363. package/dist/utils/image-convert.d.ts.map +0 -1
  1364. package/dist/utils/image-convert.js +0 -39
  1365. package/dist/utils/image-convert.js.map +0 -1
  1366. package/dist/utils/image-resize.d.ts +0 -36
  1367. package/dist/utils/image-resize.d.ts.map +0 -1
  1368. package/dist/utils/image-resize.js +0 -137
  1369. package/dist/utils/image-resize.js.map +0 -1
  1370. package/dist/utils/mime.d.ts +0 -2
  1371. package/dist/utils/mime.d.ts.map +0 -1
  1372. package/dist/utils/mime.js +0 -26
  1373. package/dist/utils/mime.js.map +0 -1
  1374. package/dist/utils/paths.d.ts +0 -7
  1375. package/dist/utils/paths.d.ts.map +0 -1
  1376. package/dist/utils/paths.js +0 -19
  1377. package/dist/utils/paths.js.map +0 -1
  1378. package/dist/utils/photon.d.ts +0 -21
  1379. package/dist/utils/photon.d.ts.map +0 -1
  1380. package/dist/utils/photon.js +0 -121
  1381. package/dist/utils/photon.js.map +0 -1
  1382. package/dist/utils/shell.d.ts +0 -26
  1383. package/dist/utils/shell.d.ts.map +0 -1
  1384. package/dist/utils/shell.js +0 -186
  1385. package/dist/utils/shell.js.map +0 -1
  1386. package/dist/utils/sleep.d.ts +0 -5
  1387. package/dist/utils/sleep.d.ts.map +0 -1
  1388. package/dist/utils/sleep.js +0 -17
  1389. package/dist/utils/sleep.js.map +0 -1
  1390. package/dist/utils/tools-manager.d.ts +0 -3
  1391. package/dist/utils/tools-manager.d.ts.map +0 -1
  1392. package/dist/utils/tools-manager.js +0 -252
  1393. package/dist/utils/tools-manager.js.map +0 -1
  1394. package/docs/compaction.md +0 -398
  1395. package/docs/custom-provider.md +0 -597
  1396. package/docs/development.md +0 -72
  1397. package/docs/extensions.md +0 -2288
  1398. package/docs/images/doom-extension.png +0 -0
  1399. package/docs/images/exy.png +0 -0
  1400. package/docs/images/interactive-mode.png +0 -0
  1401. package/docs/images/tree-view.png +0 -0
  1402. package/docs/json.md +0 -84
  1403. package/docs/keybindings.md +0 -175
  1404. package/docs/models.md +0 -349
  1405. package/docs/packages.md +0 -219
  1406. package/docs/prompt-templates.md +0 -67
  1407. package/docs/providers.md +0 -200
  1408. package/docs/rpc.md +0 -1425
  1409. package/docs/sdk.md +0 -1136
  1410. package/docs/session.md +0 -423
  1411. package/docs/settings.md +0 -246
  1412. package/docs/shell-aliases.md +0 -13
  1413. package/docs/skills.md +0 -236
  1414. package/docs/terminal-setup.md +0 -108
  1415. package/docs/termux.md +0 -137
  1416. package/docs/themes.md +0 -296
  1417. package/docs/tmux.md +0 -61
  1418. package/docs/tree.md +0 -239
  1419. package/docs/tui.md +0 -890
  1420. package/docs/windows.md +0 -17
  1421. package/examples/extensions/antigravity-image-gen.ts +0 -418
  1422. package/examples/extensions/auto-commit-on-exit.ts +0 -49
  1423. package/examples/extensions/bash-spawn-hook.ts +0 -30
  1424. package/examples/extensions/bookmark.ts +0 -50
  1425. package/examples/extensions/built-in-tool-renderer.ts +0 -246
  1426. package/examples/extensions/claude-rules.ts +0 -86
  1427. package/examples/extensions/commands.ts +0 -72
  1428. package/examples/extensions/confirm-destructive.ts +0 -59
  1429. package/examples/extensions/custom-compaction.ts +0 -127
  1430. package/examples/extensions/custom-footer.ts +0 -64
  1431. package/examples/extensions/custom-header.ts +0 -73
  1432. package/examples/extensions/custom-provider-anthropic/index.ts +0 -604
  1433. package/examples/extensions/custom-provider-anthropic/package-lock.json +0 -24
  1434. package/examples/extensions/custom-provider-anthropic/package.json +0 -19
  1435. package/examples/extensions/custom-provider-gitlab-duo/index.ts +0 -349
  1436. package/examples/extensions/custom-provider-gitlab-duo/package.json +0 -16
  1437. package/examples/extensions/custom-provider-gitlab-duo/test.ts +0 -82
  1438. package/examples/extensions/custom-provider-qwen-cli/index.ts +0 -345
  1439. package/examples/extensions/custom-provider-qwen-cli/package.json +0 -16
  1440. package/examples/extensions/dirty-repo-guard.ts +0 -56
  1441. package/examples/extensions/doom-overlay/README.md +0 -48
  1442. package/examples/extensions/doom-overlay/doom/build/doom.js +0 -21
  1443. package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
  1444. package/examples/extensions/doom-overlay/doom/build.sh +0 -152
  1445. package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +0 -72
  1446. package/examples/extensions/doom-overlay/doom-component.ts +0 -132
  1447. package/examples/extensions/doom-overlay/doom-engine.ts +0 -173
  1448. package/examples/extensions/doom-overlay/doom-keys.ts +0 -104
  1449. package/examples/extensions/doom-overlay/index.ts +0 -74
  1450. package/examples/extensions/doom-overlay/wad-finder.ts +0 -51
  1451. package/examples/extensions/dynamic-resources/SKILL.md +0 -8
  1452. package/examples/extensions/dynamic-resources/dynamic.json +0 -79
  1453. package/examples/extensions/dynamic-resources/dynamic.md +0 -5
  1454. package/examples/extensions/dynamic-resources/index.ts +0 -15
  1455. package/examples/extensions/dynamic-tools.ts +0 -74
  1456. package/examples/extensions/event-bus.ts +0 -43
  1457. package/examples/extensions/file-trigger.ts +0 -41
  1458. package/examples/extensions/git-checkpoint.ts +0 -53
  1459. package/examples/extensions/handoff.ts +0 -153
  1460. package/examples/extensions/hidden-thinking-label.ts +0 -53
  1461. package/examples/extensions/inline-bash.ts +0 -94
  1462. package/examples/extensions/input-transform.ts +0 -43
  1463. package/examples/extensions/interactive-shell.ts +0 -196
  1464. package/examples/extensions/mac-system-theme.ts +0 -47
  1465. package/examples/extensions/message-renderer.ts +0 -59
  1466. package/examples/extensions/minimal-mode.ts +0 -426
  1467. package/examples/extensions/modal-editor.ts +0 -85
  1468. package/examples/extensions/model-status.ts +0 -31
  1469. package/examples/extensions/notify.ts +0 -55
  1470. package/examples/extensions/overlay-qa-tests.ts +0 -1348
  1471. package/examples/extensions/overlay-test.ts +0 -150
  1472. package/examples/extensions/permission-gate.ts +0 -34
  1473. package/examples/extensions/plan-mode/README.md +0 -69
  1474. package/examples/extensions/plan-mode/index.ts +0 -340
  1475. package/examples/extensions/plan-mode/utils.ts +0 -168
  1476. package/examples/extensions/preset.ts +0 -403
  1477. package/examples/extensions/protected-paths.ts +0 -30
  1478. package/examples/extensions/provider-payload.ts +0 -14
  1479. package/examples/extensions/qna.ts +0 -122
  1480. package/examples/extensions/question.ts +0 -264
  1481. package/examples/extensions/questionnaire.ts +0 -427
  1482. package/examples/extensions/rainbow-editor.ts +0 -88
  1483. package/examples/extensions/rpc-demo.ts +0 -118
  1484. package/examples/extensions/sandbox/index.ts +0 -321
  1485. package/examples/extensions/sandbox/package-lock.json +0 -92
  1486. package/examples/extensions/sandbox/package.json +0 -19
  1487. package/examples/extensions/send-user-message.ts +0 -97
  1488. package/examples/extensions/session-name.ts +0 -27
  1489. package/examples/extensions/shutdown-command.ts +0 -63
  1490. package/examples/extensions/snake.ts +0 -343
  1491. package/examples/extensions/space-invaders.ts +0 -560
  1492. package/examples/extensions/ssh.ts +0 -220
  1493. package/examples/extensions/status-line.ts +0 -32
  1494. package/examples/extensions/subagent/README.md +0 -181
  1495. package/examples/extensions/subagent/agents/planner.md +0 -37
  1496. package/examples/extensions/subagent/agents/reviewer.md +0 -35
  1497. package/examples/extensions/subagent/agents/scout.md +0 -50
  1498. package/examples/extensions/subagent/agents/worker.md +0 -24
  1499. package/examples/extensions/subagent/agents.ts +0 -126
  1500. package/examples/extensions/subagent/index.ts +0 -986
  1501. package/examples/extensions/subagent/prompts/implement-and-review.md +0 -10
  1502. package/examples/extensions/subagent/prompts/implement.md +0 -10
  1503. package/examples/extensions/subagent/prompts/scout-and-plan.md +0 -9
  1504. package/examples/extensions/summarize.ts +0 -206
  1505. package/examples/extensions/system-prompt-header.ts +0 -17
  1506. package/examples/extensions/timed-confirm.ts +0 -70
  1507. package/examples/extensions/titlebar-spinner.ts +0 -58
  1508. package/examples/extensions/tool-override.ts +0 -144
  1509. package/examples/extensions/trigger-compact.ts +0 -50
  1510. package/examples/extensions/truncated-tool.ts +0 -195
  1511. package/examples/extensions/widget-placement.ts +0 -9
  1512. package/examples/rpc-extension-ui.ts +0 -640
  1513. package/examples/sdk/05-tools.ts +0 -56
  1514. package/examples/sdk/10-settings.ts +0 -51
  1515. package/examples/sdk/12-full-control.ts +0 -81
  1516. package/examples/sdk/13-session-runtime.ts +0 -67
  1517. /package/{dist/core/export-html → src/export/html}/vendor/highlight.min.js +0 -0
  1518. /package/{dist/core/export-html → src/export/html}/vendor/marked.min.js +0 -0
@@ -0,0 +1,2546 @@
1
+ import * as fs from "node:fs/promises";
2
+ import * as path from "node:path";
3
+ import type {
4
+ AgentTool,
5
+ AgentToolContext,
6
+ AgentToolResult,
7
+ AgentToolUpdateCallback,
8
+ } from "@f5xc-salesdemos/pi-agent-core";
9
+ import { abortableSleep, isEnoent, prompt, untilAborted } from "@f5xc-salesdemos/pi-utils";
10
+ import { type Static, Type } from "@sinclair/typebox";
11
+ import ghIssueViewDescription from "../prompts/tools/gh-issue-view.md" with { type: "text" };
12
+ import ghPrCheckoutDescription from "../prompts/tools/gh-pr-checkout.md" with { type: "text" };
13
+ import ghPrDiffDescription from "../prompts/tools/gh-pr-diff.md" with { type: "text" };
14
+ import ghPrPushDescription from "../prompts/tools/gh-pr-push.md" with { type: "text" };
15
+ import ghPrViewDescription from "../prompts/tools/gh-pr-view.md" with { type: "text" };
16
+ import ghRepoViewDescription from "../prompts/tools/gh-repo-view.md" with { type: "text" };
17
+ import ghRunWatchDescription from "../prompts/tools/gh-run-watch.md" with { type: "text" };
18
+ import ghSearchIssuesDescription from "../prompts/tools/gh-search-issues.md" with { type: "text" };
19
+ import ghSearchPrsDescription from "../prompts/tools/gh-search-prs.md" with { type: "text" };
20
+ import * as git from "../utils/git";
21
+ import type { ToolSession } from ".";
22
+ import type { OutputMeta } from "./output-meta";
23
+ import { ToolError, throwIfAborted } from "./tool-errors";
24
+ import { toolResult } from "./tool-result";
25
+
26
+ const GH_REPO_FIELDS = [
27
+ "nameWithOwner",
28
+ "description",
29
+ "url",
30
+ "defaultBranchRef",
31
+ "homepageUrl",
32
+ "forkCount",
33
+ "isArchived",
34
+ "isFork",
35
+ "primaryLanguage",
36
+ "repositoryTopics",
37
+ "stargazerCount",
38
+ "updatedAt",
39
+ "viewerPermission",
40
+ "visibility",
41
+ ];
42
+ const GH_ISSUE_FIELDS = [
43
+ "author",
44
+ "body",
45
+ "comments",
46
+ "createdAt",
47
+ "labels",
48
+ "number",
49
+ "state",
50
+ "stateReason",
51
+ "title",
52
+ "updatedAt",
53
+ "url",
54
+ ];
55
+ const GH_ISSUE_FIELDS_NO_COMMENTS = [
56
+ "author",
57
+ "body",
58
+ "createdAt",
59
+ "labels",
60
+ "number",
61
+ "state",
62
+ "stateReason",
63
+ "title",
64
+ "updatedAt",
65
+ "url",
66
+ ];
67
+ const GH_PR_FIELDS = [
68
+ "author",
69
+ "baseRefName",
70
+ "body",
71
+ "comments",
72
+ "createdAt",
73
+ "files",
74
+ "headRefName",
75
+ "isDraft",
76
+ "labels",
77
+ "mergeStateStatus",
78
+ "number",
79
+ "reviewDecision",
80
+ "state",
81
+ "title",
82
+ "updatedAt",
83
+ "url",
84
+ ];
85
+ const GH_PR_FIELDS_NO_COMMENTS = [
86
+ "author",
87
+ "baseRefName",
88
+ "body",
89
+ "createdAt",
90
+ "files",
91
+ "headRefName",
92
+ "isDraft",
93
+ "labels",
94
+ "mergeStateStatus",
95
+ "number",
96
+ "reviews",
97
+ "reviewDecision",
98
+ "state",
99
+ "title",
100
+ "updatedAt",
101
+ "url",
102
+ ];
103
+ const GH_REPO_CLONE_FIELDS = ["nameWithOwner", "sshUrl", "url"];
104
+ const GH_PR_CHECKOUT_FIELDS = [
105
+ "baseRefName",
106
+ "headRefName",
107
+ "headRefOid",
108
+ "headRepository",
109
+ "headRepositoryOwner",
110
+ "isCrossRepository",
111
+ "maintainerCanModify",
112
+ "number",
113
+ "title",
114
+ "url",
115
+ ];
116
+ const GH_SEARCH_FIELDS = [
117
+ "author",
118
+ "createdAt",
119
+ "labels",
120
+ "number",
121
+ "repository",
122
+ "state",
123
+ "title",
124
+ "updatedAt",
125
+ "url",
126
+ ];
127
+ const SEARCH_LIMIT_DEFAULT = 10;
128
+ const SEARCH_LIMIT_MAX = 50;
129
+ const FILE_PREVIEW_LIMIT = 50;
130
+ const RUN_WATCH_INTERVAL_DEFAULT = 3;
131
+ const RUN_WATCH_GRACE_DEFAULT = 5;
132
+ const RUN_WATCH_TAIL_DEFAULT = 15;
133
+ const RUN_WATCH_TAIL_MAX = 200;
134
+ const REVIEW_COMMENTS_PAGE_SIZE = 100;
135
+ const RUN_JOBS_PAGE_SIZE = 100;
136
+ const PR_URL_PATTERN = /^https:\/\/github\.com\/([^/]+\/[^/]+)\/pull\/(\d+)(?:\/.*)?$/;
137
+ const RUN_URL_PATTERN = /^https:\/\/github\.com\/([^/]+\/[^/]+)\/actions\/runs\/(\d+)(?:\/.*)?$/;
138
+ const RUN_SUCCESS_CONCLUSIONS = new Set(["success", "neutral", "skipped"]);
139
+ const RUN_FAILURE_CONCLUSIONS = new Set(["failure", "timed_out", "cancelled", "action_required", "startup_failure"]);
140
+ const JOB_FAILURE_CONCLUSIONS = new Set(["failure", "timed_out", "cancelled", "action_required"]);
141
+
142
+ const ghRepoViewSchema = Type.Object({
143
+ repo: Type.Optional(
144
+ Type.String({
145
+ description: "Repository in OWNER/REPO format. Defaults to the current GitHub repository context.",
146
+ }),
147
+ ),
148
+ branch: Type.Optional(Type.String({ description: "Branch name to inspect instead of the default branch." })),
149
+ });
150
+
151
+ const ghIssueViewSchema = Type.Object({
152
+ issue: Type.String({ description: "Issue number or full GitHub issue URL." }),
153
+ repo: Type.Optional(
154
+ Type.String({ description: "Repository in OWNER/REPO format. Omit when passing a full issue URL." }),
155
+ ),
156
+ comments: Type.Optional(Type.Boolean({ description: "Include issue comments (default: true)." })),
157
+ });
158
+
159
+ const ghPrViewSchema = Type.Object({
160
+ pr: Type.Optional(
161
+ Type.String({
162
+ description:
163
+ "Pull request number, full GitHub pull request URL, or branch name. Defaults to the current branch PR.",
164
+ }),
165
+ ),
166
+ repo: Type.Optional(
167
+ Type.String({ description: "Repository in OWNER/REPO format. Omit when passing a full pull request URL." }),
168
+ ),
169
+ comments: Type.Optional(Type.Boolean({ description: "Include pull request comments (default: true)." })),
170
+ });
171
+
172
+ const ghPrDiffSchema = Type.Object({
173
+ pr: Type.Optional(
174
+ Type.String({
175
+ description:
176
+ "Pull request number, full GitHub pull request URL, or branch name. Defaults to the current branch PR.",
177
+ }),
178
+ ),
179
+ repo: Type.Optional(
180
+ Type.String({ description: "Repository in OWNER/REPO format. Omit when passing a full pull request URL." }),
181
+ ),
182
+ nameOnly: Type.Optional(
183
+ Type.Boolean({ description: "Return only changed file names instead of unified diff output." }),
184
+ ),
185
+ exclude: Type.Optional(
186
+ Type.Array(Type.String({ description: "Glob pattern for files to exclude from the diff." }), {
187
+ description: "File globs to exclude from the diff output.",
188
+ }),
189
+ ),
190
+ });
191
+
192
+ const ghPrCheckoutSchema = Type.Object({
193
+ pr: Type.Optional(
194
+ Type.String({
195
+ description:
196
+ "Pull request number, full GitHub pull request URL, or branch name. Defaults to the current branch PR.",
197
+ }),
198
+ ),
199
+ repo: Type.Optional(
200
+ Type.String({ description: "Repository in OWNER/REPO format. Omit when passing a full pull request URL." }),
201
+ ),
202
+ branch: Type.Optional(Type.String({ description: "Local branch name to create or reuse (default: pr-<number>)." })),
203
+ worktree: Type.Optional(
204
+ Type.String({ description: "Worktree path to create. Defaults to <repo>/.worktrees/<branch>." }),
205
+ ),
206
+ force: Type.Optional(
207
+ Type.Boolean({
208
+ description: "Reset an existing local branch to the PR head when it is not already checked out elsewhere.",
209
+ }),
210
+ ),
211
+ });
212
+
213
+ const ghPrPushSchema = Type.Object({
214
+ branch: Type.Optional(
215
+ Type.String({
216
+ description: "Local branch name to push. Defaults to the current checked-out git branch.",
217
+ }),
218
+ ),
219
+ forceWithLease: Type.Optional(Type.Boolean({ description: "Use --force-with-lease when pushing the PR branch." })),
220
+ });
221
+
222
+ const ghSearchIssuesSchema = Type.Object({
223
+ query: Type.String({ description: "GitHub issue search query. Supports GitHub search syntax." }),
224
+ repo: Type.Optional(Type.String({ description: "Repository in OWNER/REPO format to scope the search." })),
225
+ limit: Type.Optional(Type.Number({ description: "Maximum results to return (default: 10, max: 50)." })),
226
+ });
227
+
228
+ const ghSearchPrsSchema = Type.Object({
229
+ query: Type.String({ description: "GitHub pull request search query. Supports GitHub search syntax." }),
230
+ repo: Type.Optional(Type.String({ description: "Repository in OWNER/REPO format to scope the search." })),
231
+ limit: Type.Optional(Type.Number({ description: "Maximum results to return (default: 10, max: 50)." })),
232
+ });
233
+
234
+ const ghRunWatchSchema = Type.Object({
235
+ run: Type.Optional(
236
+ Type.String({
237
+ description:
238
+ "GitHub Actions run ID or full run URL. Omitting this watches the workflow runs for the current HEAD commit on the selected branch.",
239
+ }),
240
+ ),
241
+ branch: Type.Optional(
242
+ Type.String({
243
+ description: "Branch to inspect when omitting `run`. Defaults to the current checked-out git branch.",
244
+ }),
245
+ ),
246
+ tail: Type.Optional(
247
+ Type.Number({ description: "Number of log lines to include per failed job (default: 15, max: 200)." }),
248
+ ),
249
+ });
250
+
251
+ type GhRepoViewInput = Static<typeof ghRepoViewSchema>;
252
+ type GhIssueViewInput = Static<typeof ghIssueViewSchema>;
253
+ type GhPrViewInput = Static<typeof ghPrViewSchema>;
254
+ type GhPrDiffInput = Static<typeof ghPrDiffSchema>;
255
+ type GhPrCheckoutInput = Static<typeof ghPrCheckoutSchema>;
256
+ type GhPrPushInput = Static<typeof ghPrPushSchema>;
257
+ type GhSearchIssuesInput = Static<typeof ghSearchIssuesSchema>;
258
+ type GhSearchPrsInput = Static<typeof ghSearchPrsSchema>;
259
+ type GhRunWatchInput = Static<typeof ghRunWatchSchema>;
260
+
261
+ export interface GhToolDetails {
262
+ meta?: OutputMeta;
263
+ artifactId?: string;
264
+ repo?: string;
265
+ branch?: string;
266
+ worktreePath?: string;
267
+ remote?: string;
268
+ remoteBranch?: string;
269
+ headSha?: string;
270
+ runId?: number;
271
+ runIds?: number[];
272
+ status?: string;
273
+ conclusion?: string;
274
+ failedJobs?: string[];
275
+ watch?: GhRunWatchViewDetails;
276
+ }
277
+
278
+ export interface GhRunWatchJobDetails {
279
+ id: number;
280
+ name: string;
281
+ status?: string;
282
+ conclusion?: string;
283
+ durationSeconds?: number;
284
+ url?: string;
285
+ }
286
+
287
+ export interface GhRunWatchRunDetails {
288
+ id: number;
289
+ workflowName?: string;
290
+ displayTitle?: string;
291
+ status?: string;
292
+ conclusion?: string;
293
+ branch?: string;
294
+ headSha?: string;
295
+ url?: string;
296
+ jobs: GhRunWatchJobDetails[];
297
+ }
298
+
299
+ export interface GhRunWatchFailedLogDetails {
300
+ runId: number;
301
+ workflowName?: string;
302
+ jobName: string;
303
+ conclusion?: string;
304
+ tail?: string;
305
+ available: boolean;
306
+ }
307
+
308
+ export interface GhRunWatchViewDetails {
309
+ mode: "run" | "commit";
310
+ state: "watching" | "completed";
311
+ repo: string;
312
+ branch?: string;
313
+ headSha?: string;
314
+ pollCount?: number;
315
+ note?: string;
316
+ run?: GhRunWatchRunDetails;
317
+ runs?: GhRunWatchRunDetails[];
318
+ failedLogs?: GhRunWatchFailedLogDetails[];
319
+ }
320
+
321
+ interface GhUser {
322
+ login?: string;
323
+ name?: string | null;
324
+ }
325
+
326
+ interface GhLabel {
327
+ name?: string;
328
+ }
329
+
330
+ interface GhComment {
331
+ author?: GhUser | null;
332
+ body?: string;
333
+ createdAt?: string;
334
+ url?: string;
335
+ isMinimized?: boolean;
336
+ minimizedReason?: string | null;
337
+ }
338
+
339
+ interface GhRepoTopic {
340
+ name?: string;
341
+ topic?: { name?: string };
342
+ }
343
+
344
+ interface GhRepoLanguage {
345
+ name?: string;
346
+ }
347
+
348
+ interface GhRepoBranch {
349
+ name?: string;
350
+ }
351
+
352
+ interface GhRepoViewData {
353
+ nameWithOwner?: string;
354
+ description?: string | null;
355
+ url?: string;
356
+ sshUrl?: string;
357
+ defaultBranchRef?: GhRepoBranch | null;
358
+ homepageUrl?: string | null;
359
+ forkCount?: number;
360
+ isArchived?: boolean;
361
+ isFork?: boolean;
362
+ primaryLanguage?: GhRepoLanguage | null;
363
+ repositoryTopics?: GhRepoTopic[];
364
+ stargazerCount?: number;
365
+ updatedAt?: string;
366
+ viewerPermission?: string | null;
367
+ visibility?: string | null;
368
+ }
369
+
370
+ interface GhIssueViewData {
371
+ author?: GhUser | null;
372
+ body?: string | null;
373
+ comments?: GhComment[];
374
+ createdAt?: string;
375
+ labels?: GhLabel[];
376
+ number?: number;
377
+ state?: string;
378
+ stateReason?: string | null;
379
+ title?: string;
380
+ updatedAt?: string;
381
+ url?: string;
382
+ }
383
+
384
+ interface GhPrFile {
385
+ path?: string;
386
+ additions?: number;
387
+ deletions?: number;
388
+ changeType?: string;
389
+ }
390
+
391
+ interface GhPrViewData extends GhIssueViewData {
392
+ baseRefName?: string;
393
+ files?: GhPrFile[];
394
+ headRefName?: string;
395
+ headRefOid?: string;
396
+ headRepository?: GhRepoViewData | null;
397
+ headRepositoryOwner?: GhUser | null;
398
+ isCrossRepository?: boolean;
399
+ isDraft?: boolean;
400
+ maintainerCanModify?: boolean;
401
+ mergeStateStatus?: string;
402
+ reviewComments?: GhPrReviewComment[];
403
+ reviews?: GhPrReview[];
404
+ reviewDecision?: string;
405
+ }
406
+
407
+ interface GhPrReviewCommit {
408
+ oid?: string | null;
409
+ }
410
+
411
+ interface GhPrReview {
412
+ author?: GhUser | null;
413
+ body?: string | null;
414
+ commit?: GhPrReviewCommit | null;
415
+ state?: string | null;
416
+ submittedAt?: string | null;
417
+ }
418
+
419
+ interface GhPrReviewCommentApi {
420
+ body?: string | null;
421
+ created_at?: string | null;
422
+ html_url?: string | null;
423
+ id?: number;
424
+ in_reply_to_id?: number | null;
425
+ line?: number | null;
426
+ original_line?: number | null;
427
+ path?: string | null;
428
+ side?: string | null;
429
+ user?: GhUser | null;
430
+ }
431
+
432
+ interface GhPrReviewComment {
433
+ author?: GhUser | null;
434
+ body?: string | null;
435
+ createdAt?: string;
436
+ id: number;
437
+ inReplyToId?: number;
438
+ line?: number;
439
+ originalLine?: number;
440
+ path?: string;
441
+ side?: string;
442
+ url?: string;
443
+ }
444
+
445
+ interface GhBranchApiResponse {
446
+ commit?: {
447
+ sha?: string | null;
448
+ } | null;
449
+ }
450
+
451
+ interface GhSearchRepository {
452
+ nameWithOwner?: string;
453
+ }
454
+
455
+ interface GhSearchResult {
456
+ author?: GhUser | null;
457
+ createdAt?: string;
458
+ labels?: GhLabel[];
459
+ number?: number;
460
+ repository?: GhSearchRepository | null;
461
+ state?: string;
462
+ title?: string;
463
+ updatedAt?: string;
464
+ url?: string;
465
+ }
466
+
467
+ interface GhRunReference {
468
+ repo?: string;
469
+ runId?: number;
470
+ }
471
+
472
+ interface GhActionsRunListResponse {
473
+ workflow_runs?: GhActionsRunApi[];
474
+ }
475
+
476
+ interface GhActionsRunApi {
477
+ id?: number;
478
+ name?: string | null;
479
+ display_title?: string | null;
480
+ status?: string | null;
481
+ conclusion?: string | null;
482
+ head_branch?: string | null;
483
+ head_sha?: string | null;
484
+ created_at?: string | null;
485
+ updated_at?: string | null;
486
+ html_url?: string | null;
487
+ }
488
+
489
+ interface GhActionsJobsResponse {
490
+ total_count?: number;
491
+ jobs?: GhActionsJobApi[];
492
+ }
493
+
494
+ interface GhActionsJobApi {
495
+ id?: number;
496
+ name?: string | null;
497
+ status?: string | null;
498
+ conclusion?: string | null;
499
+ started_at?: string | null;
500
+ completed_at?: string | null;
501
+ html_url?: string | null;
502
+ }
503
+
504
+ interface GhRunJobSnapshot {
505
+ id: number;
506
+ name: string;
507
+ status?: string;
508
+ conclusion?: string;
509
+ startedAt?: string;
510
+ completedAt?: string;
511
+ url?: string;
512
+ }
513
+
514
+ interface GhRunSnapshot {
515
+ id: number;
516
+ workflowName?: string;
517
+ displayTitle?: string;
518
+ status?: string;
519
+ conclusion?: string;
520
+ branch?: string;
521
+ headSha?: string;
522
+ createdAt?: string;
523
+ updatedAt?: string;
524
+ url?: string;
525
+ jobs: GhRunJobSnapshot[];
526
+ }
527
+
528
+ interface GhFailedJobLog {
529
+ run: GhRunSnapshot;
530
+ job: GhRunJobSnapshot;
531
+ full?: string;
532
+ tail?: string;
533
+ available: boolean;
534
+ }
535
+
536
+ function normalizeText(value: string | null | undefined): string {
537
+ return (value ?? "").replaceAll("\r\n", "\n").replaceAll("\r", "\n").replaceAll("\t", " ").trim();
538
+ }
539
+
540
+ function normalizeBlock(value: string | null | undefined): string {
541
+ return (value ?? "").replaceAll("\r\n", "\n").replaceAll("\r", "\n").replaceAll("\t", " ").trimEnd();
542
+ }
543
+
544
+ function looksLikeGitHubUrl(value: string | undefined): boolean {
545
+ return value?.startsWith("https://github.com/") ?? false;
546
+ }
547
+
548
+ function normalizeOptionalString(value: string | null | undefined): string | undefined {
549
+ const normalized = value?.trim();
550
+ return normalized ? normalized : undefined;
551
+ }
552
+
553
+ function formatShortSha(value: string | undefined): string | undefined {
554
+ if (!value) {
555
+ return undefined;
556
+ }
557
+
558
+ return value.slice(0, 12);
559
+ }
560
+
561
+ function requireNonEmpty(value: string | null | undefined, label: string): string {
562
+ const normalized = normalizeOptionalString(value);
563
+ if (!normalized) {
564
+ throw new ToolError(`${label} must not be empty`);
565
+ }
566
+ return normalized;
567
+ }
568
+
569
+ function resolveSearchLimit(value: number | undefined): number {
570
+ if (value === undefined) {
571
+ return SEARCH_LIMIT_DEFAULT;
572
+ }
573
+
574
+ if (!Number.isFinite(value) || value <= 0) {
575
+ throw new ToolError("limit must be a positive number");
576
+ }
577
+
578
+ return Math.min(Math.floor(value), SEARCH_LIMIT_MAX);
579
+ }
580
+
581
+ function resolveTailLimit(value: number | undefined): number {
582
+ if (value === undefined) {
583
+ return RUN_WATCH_TAIL_DEFAULT;
584
+ }
585
+
586
+ if (!Number.isFinite(value) || value <= 0) {
587
+ throw new ToolError("tail must be a positive number");
588
+ }
589
+
590
+ return Math.min(Math.floor(value), RUN_WATCH_TAIL_MAX);
591
+ }
592
+
593
+ function appendRepoFlag(args: string[], repo: string | undefined, identifier?: string): void {
594
+ if (!repo || looksLikeGitHubUrl(identifier)) {
595
+ return;
596
+ }
597
+
598
+ args.push("--repo", repo);
599
+ }
600
+
601
+ function buildGhSearchArgs(
602
+ command: "issues" | "prs",
603
+ query: string,
604
+ limit: number,
605
+ repo: string | undefined,
606
+ ): string[] {
607
+ const args = ["search", command, "--limit", String(limit), "--json", GH_SEARCH_FIELDS.join(",")];
608
+ appendRepoFlag(args, repo);
609
+ args.push("--", query);
610
+ return args;
611
+ }
612
+
613
+ function sanitizeRemoteName(value: string): string {
614
+ const sanitized = value
615
+ .toLowerCase()
616
+ .replace(/[^a-z0-9]+/g, "-")
617
+ .replace(/^-+/g, "")
618
+ .replace(/-+$/g, "");
619
+ return sanitized.length > 0 ? `fork-${sanitized}` : "fork";
620
+ }
621
+
622
+ function toLocalBranchRef(value: string): string {
623
+ return `refs/heads/${value}`;
624
+ }
625
+
626
+ function stripHeadsRef(value: string | undefined): string | undefined {
627
+ if (!value) {
628
+ return undefined;
629
+ }
630
+
631
+ return value.startsWith("refs/heads/") ? value.slice("refs/heads/".length) : value;
632
+ }
633
+
634
+ async function requireGitRepoRoot(cwd: string, signal?: AbortSignal): Promise<string> {
635
+ const repoRoot = await git.repo.root(cwd, signal);
636
+ if (!repoRoot) {
637
+ throw new ToolError("Current git repository is unavailable.");
638
+ }
639
+
640
+ return repoRoot;
641
+ }
642
+
643
+ async function requirePrimaryGitRepoRoot(cwd: string, signal?: AbortSignal): Promise<string> {
644
+ const primaryRepoRoot = await git.repo.primaryRoot(cwd, signal);
645
+ if (!primaryRepoRoot) {
646
+ throw new ToolError("Current git repository is unavailable.");
647
+ }
648
+
649
+ return primaryRepoRoot;
650
+ }
651
+
652
+ async function requireCurrentGitBranch(cwd: string, signal?: AbortSignal): Promise<string> {
653
+ const branch = await git.branch.current(cwd, signal);
654
+ if (!branch) {
655
+ throw new ToolError("Current git branch is unavailable. Pass `branch` or `run` explicitly.");
656
+ }
657
+
658
+ return branch;
659
+ }
660
+
661
+ async function requireCurrentGitHead(cwd: string, signal?: AbortSignal): Promise<string> {
662
+ const headSha = await git.head.sha(cwd, signal);
663
+ if (!headSha) {
664
+ throw new ToolError("Current git HEAD is unavailable. Pass `run` explicitly.");
665
+ }
666
+
667
+ return headSha;
668
+ }
669
+
670
+ async function ensureGitWorktreePathAvailable(
671
+ worktreePath: string,
672
+ existingWorktrees: git.GitWorktreeEntry[],
673
+ ): Promise<void> {
674
+ const normalizedTarget = path.resolve(worktreePath);
675
+ const conflictingWorktree = existingWorktrees.find(entry => path.resolve(entry.path) === normalizedTarget);
676
+ if (conflictingWorktree) {
677
+ throw new ToolError(`worktree path is already registered: ${conflictingWorktree.path}`);
678
+ }
679
+
680
+ try {
681
+ await fs.stat(normalizedTarget);
682
+ throw new ToolError(`worktree path already exists: ${normalizedTarget}`);
683
+ } catch (error) {
684
+ if (isEnoent(error)) {
685
+ return;
686
+ }
687
+ throw error;
688
+ }
689
+ }
690
+
691
+ function selectPrCloneUrl(originUrl: string | undefined, repo: Pick<GhRepoViewData, "url" | "sshUrl">): string {
692
+ if (originUrl?.startsWith("http://") || originUrl?.startsWith("https://")) {
693
+ return normalizeOptionalString(repo.url) ?? normalizeOptionalString(repo.sshUrl) ?? "";
694
+ }
695
+
696
+ return normalizeOptionalString(repo.sshUrl) ?? normalizeOptionalString(repo.url) ?? "";
697
+ }
698
+
699
+ async function getRemoteUrls(repoRoot: string, signal?: AbortSignal): Promise<Map<string, string>> {
700
+ const remotes = await git.remote.list(repoRoot, signal);
701
+ const urls = new Map<string, string>();
702
+ for (const remoteName of remotes) {
703
+ const remoteUrl = await git.remote.url(repoRoot, remoteName, signal);
704
+ if (remoteUrl) {
705
+ urls.set(remoteName, remoteUrl);
706
+ }
707
+ }
708
+ return urls;
709
+ }
710
+
711
+ async function ensurePrRemote(
712
+ repoRoot: string,
713
+ data: GhPrViewData,
714
+ signal?: AbortSignal,
715
+ ): Promise<{ name: string; url: string }> {
716
+ if (!data.isCrossRepository) {
717
+ const originUrl = await git.remote.url(repoRoot, "origin", signal);
718
+ if (!originUrl) {
719
+ throw new ToolError("origin remote is unavailable for this repository.");
720
+ }
721
+
722
+ return {
723
+ name: "origin",
724
+ url: originUrl,
725
+ };
726
+ }
727
+
728
+ const headRepository = requireNonEmpty(data.headRepository?.nameWithOwner, "head repository");
729
+ const repoSummary = await git.github.json<GhRepoViewData>(
730
+ repoRoot,
731
+ ["repo", "view", headRepository, "--json", GH_REPO_CLONE_FIELDS.join(",")],
732
+ signal,
733
+ { repoProvided: true },
734
+ );
735
+ const originUrl = await git.remote.url(repoRoot, "origin", signal);
736
+ const remoteUrl = selectPrCloneUrl(originUrl, repoSummary);
737
+ if (!remoteUrl) {
738
+ throw new ToolError(`Could not determine a clone URL for ${headRepository}.`);
739
+ }
740
+
741
+ const remotes = await getRemoteUrls(repoRoot, signal);
742
+ for (const [remoteName, url] of remotes) {
743
+ if (url === remoteUrl) {
744
+ return { name: remoteName, url };
745
+ }
746
+ }
747
+
748
+ const preferredRemoteName = sanitizeRemoteName(
749
+ data.headRepositoryOwner?.login ?? headRepository.split("/")[0] ?? "fork",
750
+ );
751
+ let remoteName = preferredRemoteName;
752
+ let suffix = 2;
753
+ while (remotes.has(remoteName)) {
754
+ remoteName = `${preferredRemoteName}-${suffix}`;
755
+ suffix += 1;
756
+ }
757
+
758
+ await git.remote.add(repoRoot, remoteName, remoteUrl, signal);
759
+
760
+ return {
761
+ name: remoteName,
762
+ url: remoteUrl,
763
+ };
764
+ }
765
+
766
+ async function resolvePrBranchPushTarget(
767
+ repoRoot: string,
768
+ localBranch: string,
769
+ signal?: AbortSignal,
770
+ ): Promise<{
771
+ remoteName: string;
772
+ remoteBranch: string;
773
+ remoteUrl?: string;
774
+ prUrl?: string;
775
+ maintainerCanModify?: boolean;
776
+ isCrossRepository: boolean;
777
+ }> {
778
+ const pushRemote = await git.config.getBranch(repoRoot, localBranch, "pushRemote", signal);
779
+ const remote = await git.config.getBranch(repoRoot, localBranch, "remote", signal);
780
+ const mergeRef = await git.config.getBranch(repoRoot, localBranch, "merge", signal);
781
+ const headRef = await git.config.getBranch(repoRoot, localBranch, "ompPrHeadRef", signal);
782
+ const prUrl = await git.config.getBranch(repoRoot, localBranch, "ompPrUrl", signal);
783
+ const maintainerCanModifyValue = await git.config.getBranch(
784
+ repoRoot,
785
+ localBranch,
786
+ "ompPrMaintainerCanModify",
787
+ signal,
788
+ );
789
+ const isCrossRepositoryValue = await git.config.getBranch(repoRoot, localBranch, "ompPrIsCrossRepository", signal);
790
+
791
+ const remoteName = pushRemote ?? remote;
792
+ if (!remoteName) {
793
+ throw new ToolError(`branch ${localBranch} has no configured push remote`);
794
+ }
795
+
796
+ const remoteBranch = headRef ?? stripHeadsRef(mergeRef);
797
+ if (!remoteBranch) {
798
+ throw new ToolError(`branch ${localBranch} has no tracked PR head ref`);
799
+ }
800
+
801
+ return {
802
+ remoteName,
803
+ remoteBranch,
804
+ remoteUrl: await git.remote.url(repoRoot, remoteName, signal),
805
+ prUrl,
806
+ maintainerCanModify:
807
+ maintainerCanModifyValue === undefined
808
+ ? undefined
809
+ : ["1", "true", "yes", "on"].includes(maintainerCanModifyValue.toLowerCase()),
810
+ isCrossRepository: ["1", "true", "yes", "on"].includes((isCrossRepositoryValue ?? "").toLowerCase()),
811
+ };
812
+ }
813
+
814
+ function formatAuthor(author: GhUser | null | undefined): string | undefined {
815
+ if (!author) return undefined;
816
+ if (author.login) return `@${author.login}`;
817
+ if (author.name) return author.name;
818
+ return undefined;
819
+ }
820
+
821
+ function formatLabels(labels: GhLabel[] | undefined): string | undefined {
822
+ const names = labels?.map(label => label.name).filter((value): value is string => Boolean(value)) ?? [];
823
+ if (names.length === 0) return undefined;
824
+ return names.join(", ");
825
+ }
826
+
827
+ function pushLine(lines: string[], label: string, value: string | number | boolean | undefined): void {
828
+ if (value === undefined || value === "") return;
829
+ lines.push(`${label}: ${value}`);
830
+ }
831
+
832
+ function parseRunReference(value: string | undefined): GhRunReference {
833
+ const run = normalizeOptionalString(value);
834
+ if (!run) {
835
+ return {};
836
+ }
837
+
838
+ if (/^\d+$/.test(run)) {
839
+ return { runId: Number(run) };
840
+ }
841
+
842
+ const match = run.match(RUN_URL_PATTERN);
843
+ if (!match) {
844
+ throw new ToolError("run must be a numeric workflow run ID or a full GitHub Actions run URL");
845
+ }
846
+
847
+ return {
848
+ repo: match[1],
849
+ runId: Number(match[2]),
850
+ };
851
+ }
852
+
853
+ function parsePullRequestUrl(value: string | undefined): { repo?: string; prNumber?: number } {
854
+ const normalized = normalizeOptionalString(value);
855
+ if (!normalized) {
856
+ return {};
857
+ }
858
+
859
+ const match = normalized.match(PR_URL_PATTERN);
860
+ if (!match) {
861
+ return {};
862
+ }
863
+
864
+ return {
865
+ repo: match[1],
866
+ prNumber: Number(match[2]),
867
+ };
868
+ }
869
+
870
+ function normalizePrReviewComment(comment: GhPrReviewCommentApi): GhPrReviewComment | null {
871
+ if (typeof comment.id !== "number") {
872
+ return null;
873
+ }
874
+
875
+ return {
876
+ author: comment.user ?? null,
877
+ body: comment.body,
878
+ createdAt: normalizeOptionalString(comment.created_at),
879
+ id: comment.id,
880
+ inReplyToId: typeof comment.in_reply_to_id === "number" ? comment.in_reply_to_id : undefined,
881
+ line: typeof comment.line === "number" ? comment.line : undefined,
882
+ originalLine: typeof comment.original_line === "number" ? comment.original_line : undefined,
883
+ path: normalizeOptionalString(comment.path),
884
+ side: normalizeOptionalString(comment.side),
885
+ url: normalizeOptionalString(comment.html_url),
886
+ };
887
+ }
888
+
889
+ function normalizeRunJob(job: GhActionsJobApi): GhRunJobSnapshot | null {
890
+ if (typeof job.id !== "number") {
891
+ return null;
892
+ }
893
+
894
+ return {
895
+ id: job.id,
896
+ name: normalizeOptionalString(job.name) ?? `job-${job.id}`,
897
+ status: normalizeOptionalString(job.status),
898
+ conclusion: normalizeOptionalString(job.conclusion),
899
+ startedAt: normalizeOptionalString(job.started_at),
900
+ completedAt: normalizeOptionalString(job.completed_at),
901
+ url: normalizeOptionalString(job.html_url),
902
+ };
903
+ }
904
+
905
+ function normalizeRunSnapshot(run: GhActionsRunApi, jobs: GhRunJobSnapshot[]): GhRunSnapshot {
906
+ if (typeof run.id !== "number") {
907
+ throw new ToolError("GitHub Actions run response did not include a run ID.");
908
+ }
909
+
910
+ return {
911
+ id: run.id,
912
+ workflowName: normalizeOptionalString(run.name),
913
+ displayTitle: normalizeOptionalString(run.display_title),
914
+ status: normalizeOptionalString(run.status),
915
+ conclusion: normalizeOptionalString(run.conclusion),
916
+ branch: normalizeOptionalString(run.head_branch),
917
+ headSha: normalizeOptionalString(run.head_sha),
918
+ createdAt: normalizeOptionalString(run.created_at),
919
+ updatedAt: normalizeOptionalString(run.updated_at),
920
+ url: normalizeOptionalString(run.html_url),
921
+ jobs,
922
+ };
923
+ }
924
+
925
+ function getRunOutcome(value: string | undefined): "success" | "failure" | "pending" {
926
+ if (!value) {
927
+ return "pending";
928
+ }
929
+
930
+ if (RUN_SUCCESS_CONCLUSIONS.has(value)) {
931
+ return "success";
932
+ }
933
+
934
+ if (RUN_FAILURE_CONCLUSIONS.has(value)) {
935
+ return "failure";
936
+ }
937
+
938
+ return "pending";
939
+ }
940
+
941
+ function getRunSnapshotOutcome(run: GhRunSnapshot): "success" | "failure" | "pending" {
942
+ if (run.status !== "completed") {
943
+ return "pending";
944
+ }
945
+
946
+ return getRunOutcome(run.conclusion);
947
+ }
948
+
949
+ function getRunCollectionOutcome(runs: GhRunSnapshot[]): "success" | "failure" | "pending" {
950
+ if (runs.length === 0) {
951
+ return "pending";
952
+ }
953
+
954
+ let pending = false;
955
+ for (const run of runs) {
956
+ if (run.jobs.some(isFailedJob)) {
957
+ return "failure";
958
+ }
959
+
960
+ const outcome = getRunSnapshotOutcome(run);
961
+ if (outcome === "failure") {
962
+ return "failure";
963
+ }
964
+ if (outcome === "pending") {
965
+ pending = true;
966
+ }
967
+ }
968
+
969
+ return pending ? "pending" : "success";
970
+ }
971
+
972
+ function getRunCollectionSignature(runs: GhRunSnapshot[]): string {
973
+ return runs
974
+ .map(run => run.id)
975
+ .sort((left, right) => left - right)
976
+ .join(",");
977
+ }
978
+
979
+ function isFailedJob(job: GhRunJobSnapshot): boolean {
980
+ return job.conclusion !== undefined && JOB_FAILURE_CONCLUSIONS.has(job.conclusion);
981
+ }
982
+
983
+ function formatJobState(job: GhRunJobSnapshot): string {
984
+ return job.conclusion ?? job.status ?? "unknown";
985
+ }
986
+
987
+ function parseTimestampMs(value: string | undefined): number | undefined {
988
+ if (!value) {
989
+ return undefined;
990
+ }
991
+
992
+ const timestamp = Date.parse(value);
993
+ return Number.isNaN(timestamp) ? undefined : timestamp;
994
+ }
995
+
996
+ function getJobDurationSeconds(job: GhRunJobSnapshot, observedAtMs: number): number | undefined {
997
+ const startedAtMs = parseTimestampMs(job.startedAt);
998
+ if (startedAtMs === undefined) {
999
+ return undefined;
1000
+ }
1001
+
1002
+ const completedAtMs = parseTimestampMs(job.completedAt) ?? observedAtMs;
1003
+ return Math.max(0, Math.floor((completedAtMs - startedAtMs) / 1000));
1004
+ }
1005
+
1006
+ function buildRunWatchJobDetails(job: GhRunJobSnapshot, observedAtMs: number): GhRunWatchJobDetails {
1007
+ return {
1008
+ id: job.id,
1009
+ name: job.name,
1010
+ status: job.status,
1011
+ conclusion: job.conclusion,
1012
+ durationSeconds: getJobDurationSeconds(job, observedAtMs),
1013
+ url: job.url,
1014
+ };
1015
+ }
1016
+
1017
+ function buildRunWatchRunDetails(run: GhRunSnapshot, observedAtMs: number): GhRunWatchRunDetails {
1018
+ return {
1019
+ id: run.id,
1020
+ workflowName: run.workflowName,
1021
+ displayTitle: run.displayTitle,
1022
+ status: run.status,
1023
+ conclusion: run.conclusion,
1024
+ branch: run.branch,
1025
+ headSha: run.headSha,
1026
+ url: run.url,
1027
+ jobs: run.jobs.map(job => buildRunWatchJobDetails(job, observedAtMs)),
1028
+ };
1029
+ }
1030
+
1031
+ function buildFailedLogDetails(failedJobLogs: GhFailedJobLog[]): GhRunWatchFailedLogDetails[] {
1032
+ return failedJobLogs.map(entry => ({
1033
+ runId: entry.run.id,
1034
+ workflowName: entry.run.workflowName,
1035
+ jobName: entry.job.name,
1036
+ conclusion: entry.job.conclusion,
1037
+ tail: entry.tail,
1038
+ available: entry.available,
1039
+ }));
1040
+ }
1041
+
1042
+ function renderJobsSection(jobs: GhRunJobSnapshot[]): string[] {
1043
+ if (jobs.length === 0) {
1044
+ return ["## Jobs", "", "No jobs reported yet."];
1045
+ }
1046
+
1047
+ const lines: string[] = [`## Jobs (${jobs.length})`, ""];
1048
+ for (const job of jobs) {
1049
+ lines.push(`- [${formatJobState(job)}] ${job.name}`);
1050
+ if (job.startedAt) {
1051
+ pushLine(lines, " Started", job.startedAt);
1052
+ }
1053
+ if (job.completedAt) {
1054
+ pushLine(lines, " Completed", job.completedAt);
1055
+ }
1056
+ if (job.url) {
1057
+ pushLine(lines, " URL", job.url);
1058
+ }
1059
+ }
1060
+
1061
+ return lines;
1062
+ }
1063
+
1064
+ function renderFailedJobLogs(
1065
+ failedJobLogs: GhFailedJobLog[],
1066
+ options: { mode: "tail"; tail: number } | { mode: "full" },
1067
+ ): string[] {
1068
+ if (failedJobLogs.length === 0) {
1069
+ return [];
1070
+ }
1071
+
1072
+ const lines: string[] = ["## Failed Jobs", ""];
1073
+ for (const entry of failedJobLogs) {
1074
+ lines.push(`### ${entry.job.name} [${entry.job.conclusion ?? "failed"}]`);
1075
+ pushLine(lines, "Run", `#${entry.run.id}`);
1076
+ pushLine(lines, "Workflow", entry.run.workflowName ?? undefined);
1077
+ if (entry.job.startedAt) {
1078
+ pushLine(lines, "Started", entry.job.startedAt);
1079
+ }
1080
+ if (entry.job.completedAt) {
1081
+ pushLine(lines, "Completed", entry.job.completedAt);
1082
+ }
1083
+ if (entry.job.url) {
1084
+ pushLine(lines, "URL", entry.job.url);
1085
+ }
1086
+ lines.push("");
1087
+ const logText = options.mode === "full" ? entry.full : entry.tail;
1088
+ if (entry.available && logText) {
1089
+ lines.push(options.mode === "full" ? "Full log:" : `Last ${options.tail} log lines:`);
1090
+ lines.push("```text");
1091
+ lines.push(logText);
1092
+ lines.push("```");
1093
+ } else {
1094
+ lines.push(options.mode === "full" ? "Full log unavailable." : "Log tail unavailable.");
1095
+ }
1096
+ lines.push("");
1097
+ }
1098
+
1099
+ return lines;
1100
+ }
1101
+
1102
+ function renderRunSection(run: GhRunSnapshot): string[] {
1103
+ const label = run.workflowName ? `### Run #${run.id} - ${run.workflowName}` : `### Run #${run.id}`;
1104
+ const lines: string[] = [label, ""];
1105
+ pushLine(lines, "Title", run.displayTitle ?? undefined);
1106
+ pushLine(lines, "Branch", run.branch ?? undefined);
1107
+ pushLine(lines, "Commit", formatShortSha(run.headSha));
1108
+ pushLine(lines, "Status", run.status);
1109
+ pushLine(lines, "Conclusion", run.conclusion ?? undefined);
1110
+ pushLine(lines, "Created", run.createdAt);
1111
+ pushLine(lines, "Updated", run.updatedAt);
1112
+ pushLine(lines, "URL", run.url);
1113
+ lines.push("");
1114
+ lines.push(...renderJobsSection(run.jobs));
1115
+ return lines;
1116
+ }
1117
+
1118
+ function formatRunWatchSnapshot(
1119
+ repo: string,
1120
+ run: GhRunSnapshot,
1121
+ pollCount: number,
1122
+ note?: string,
1123
+ includeOutcome: boolean = false,
1124
+ ): string {
1125
+ const failedJobs = run.jobs.filter(isFailedJob);
1126
+ const lines: string[] = [`# Watching GitHub Actions Run #${run.id}`, ""];
1127
+ pushLine(lines, "Repository", repo);
1128
+ pushLine(lines, "Workflow", run.workflowName ?? undefined);
1129
+ pushLine(lines, "Title", run.displayTitle ?? undefined);
1130
+ pushLine(lines, "Branch", run.branch ?? undefined);
1131
+ pushLine(lines, "Status", run.status);
1132
+ pushLine(lines, "Conclusion", run.conclusion ?? undefined);
1133
+ pushLine(lines, "Created", run.createdAt);
1134
+ pushLine(lines, "Updated", run.updatedAt);
1135
+ pushLine(lines, "URL", run.url);
1136
+ pushLine(lines, "Poll", pollCount);
1137
+ pushLine(lines, "Failed jobs", failedJobs.length || undefined);
1138
+
1139
+ if (note) {
1140
+ lines.push("");
1141
+ lines.push(`Note: ${note}`);
1142
+ }
1143
+
1144
+ lines.push("");
1145
+ lines.push(...renderJobsSection(run.jobs));
1146
+
1147
+ if (includeOutcome) {
1148
+ lines.push("");
1149
+ lines.push(failedJobs.length > 0 ? "Failures detected." : "All jobs passed.");
1150
+ }
1151
+
1152
+ return lines.join("\n").trim();
1153
+ }
1154
+
1155
+ function formatRunWatchResult(
1156
+ repo: string,
1157
+ run: GhRunSnapshot,
1158
+ failedJobLogs: GhFailedJobLog[],
1159
+ tail: number,
1160
+ options?: { mode?: "tail" | "full" },
1161
+ ): string {
1162
+ const failedJobs = run.jobs.filter(isFailedJob);
1163
+ const lines: string[] = [`# GitHub Actions Run #${run.id}`, ""];
1164
+ pushLine(lines, "Repository", repo);
1165
+ pushLine(lines, "Workflow", run.workflowName ?? undefined);
1166
+ pushLine(lines, "Title", run.displayTitle ?? undefined);
1167
+ pushLine(lines, "Branch", run.branch ?? undefined);
1168
+ pushLine(lines, "Status", run.status);
1169
+ pushLine(lines, "Conclusion", run.conclusion ?? undefined);
1170
+ pushLine(lines, "Created", run.createdAt);
1171
+ pushLine(lines, "Updated", run.updatedAt);
1172
+ pushLine(lines, "URL", run.url);
1173
+ lines.push("");
1174
+ lines.push(...renderJobsSection(run.jobs));
1175
+
1176
+ if (failedJobs.length > 0) {
1177
+ lines.push("");
1178
+ lines.push(
1179
+ ...renderFailedJobLogs(failedJobLogs, options?.mode === "full" ? { mode: "full" } : { mode: "tail", tail }),
1180
+ );
1181
+ lines.push("Run failed.");
1182
+ } else if (getRunOutcome(run.conclusion) === "success") {
1183
+ lines.push("");
1184
+ lines.push("All jobs passed.");
1185
+ } else {
1186
+ lines.push("");
1187
+ lines.push("Run completed without successful jobs, but no failed job logs were available.");
1188
+ }
1189
+
1190
+ return lines.join("\n").trim();
1191
+ }
1192
+
1193
+ function formatCommitRunWatchSnapshot(
1194
+ repo: string,
1195
+ headSha: string,
1196
+ branch: string | undefined,
1197
+ runs: GhRunSnapshot[],
1198
+ pollCount: number,
1199
+ note?: string,
1200
+ ): string {
1201
+ const failedJobs = runs.flatMap(run => run.jobs.filter(isFailedJob));
1202
+ const completedRuns = runs.filter(run => run.status === "completed").length;
1203
+ const lines: string[] = [`# Watching GitHub Actions for ${formatShortSha(headSha) ?? headSha}`, ""];
1204
+ pushLine(lines, "Repository", repo);
1205
+ pushLine(lines, "Branch", branch);
1206
+ pushLine(lines, "Commit", headSha);
1207
+ pushLine(lines, "Poll", pollCount);
1208
+ pushLine(lines, "Runs", runs.length);
1209
+ pushLine(lines, "Completed runs", `${completedRuns}/${runs.length}`);
1210
+ pushLine(lines, "Failed jobs", failedJobs.length || undefined);
1211
+
1212
+ if (note) {
1213
+ lines.push("");
1214
+ lines.push(`Note: ${note}`);
1215
+ }
1216
+
1217
+ if (runs.length === 0) {
1218
+ lines.push("");
1219
+ lines.push("Waiting for workflow runs for this commit.");
1220
+ return lines.join("\n").trim();
1221
+ }
1222
+
1223
+ for (const run of runs) {
1224
+ lines.push("");
1225
+ lines.push(...renderRunSection(run));
1226
+ }
1227
+
1228
+ return lines.join("\n").trim();
1229
+ }
1230
+
1231
+ function formatCommitRunWatchResult(
1232
+ repo: string,
1233
+ headSha: string,
1234
+ branch: string | undefined,
1235
+ runs: GhRunSnapshot[],
1236
+ failedJobLogs: GhFailedJobLog[],
1237
+ tail: number,
1238
+ options?: { mode?: "tail" | "full" },
1239
+ ): string {
1240
+ const outcome = getRunCollectionOutcome(runs);
1241
+ const lines: string[] = [`# GitHub Actions for ${formatShortSha(headSha) ?? headSha}`, ""];
1242
+ pushLine(lines, "Repository", repo);
1243
+ pushLine(lines, "Branch", branch);
1244
+ pushLine(lines, "Commit", headSha);
1245
+ pushLine(lines, "Runs", runs.length);
1246
+
1247
+ for (const run of runs) {
1248
+ lines.push("");
1249
+ lines.push(...renderRunSection(run));
1250
+ }
1251
+
1252
+ if (failedJobLogs.length > 0) {
1253
+ lines.push("");
1254
+ lines.push(
1255
+ ...renderFailedJobLogs(failedJobLogs, options?.mode === "full" ? { mode: "full" } : { mode: "tail", tail }),
1256
+ );
1257
+ lines.push("Workflow runs for this commit failed.");
1258
+ } else if (outcome === "success") {
1259
+ lines.push("");
1260
+ lines.push("All workflow runs for this commit passed.");
1261
+ } else {
1262
+ lines.push("");
1263
+ lines.push("Workflow runs for this commit did not complete successfully.");
1264
+ }
1265
+
1266
+ return lines.join("\n").trim();
1267
+ }
1268
+
1269
+ function buildGhDetails(repo: string, run: GhRunSnapshot): GhToolDetails {
1270
+ return {
1271
+ repo,
1272
+ branch: run.branch,
1273
+ headSha: run.headSha,
1274
+ runId: run.id,
1275
+ runIds: [run.id],
1276
+ status: run.status,
1277
+ conclusion: run.conclusion,
1278
+ failedJobs: run.jobs.filter(isFailedJob).map(job => job.name),
1279
+ };
1280
+ }
1281
+
1282
+ function buildRunWatchDetails(
1283
+ repo: string,
1284
+ run: GhRunSnapshot,
1285
+ options?: {
1286
+ state?: GhRunWatchViewDetails["state"];
1287
+ pollCount?: number;
1288
+ note?: string;
1289
+ failedJobLogs?: GhFailedJobLog[];
1290
+ },
1291
+ ): GhToolDetails {
1292
+ const observedAtMs = Date.now();
1293
+ return {
1294
+ ...buildGhDetails(repo, run),
1295
+ watch: {
1296
+ mode: "run",
1297
+ state: options?.state ?? "completed",
1298
+ repo,
1299
+ branch: run.branch,
1300
+ headSha: run.headSha,
1301
+ pollCount: options?.pollCount,
1302
+ note: options?.note,
1303
+ run: buildRunWatchRunDetails(run, observedAtMs),
1304
+ failedLogs: buildFailedLogDetails(options?.failedJobLogs ?? []),
1305
+ },
1306
+ };
1307
+ }
1308
+
1309
+ function buildGhRunCollectionDetails(
1310
+ repo: string,
1311
+ headSha: string,
1312
+ branch: string | undefined,
1313
+ runs: GhRunSnapshot[],
1314
+ ): GhToolDetails {
1315
+ const outcome = getRunCollectionOutcome(runs);
1316
+ return {
1317
+ repo,
1318
+ branch,
1319
+ headSha,
1320
+ runIds: runs.map(run => run.id),
1321
+ status: runs.length > 0 && runs.every(run => run.status === "completed") ? "completed" : "in_progress",
1322
+ conclusion: outcome,
1323
+ failedJobs: runs.flatMap(run =>
1324
+ run.jobs.filter(isFailedJob).map(job => `${run.workflowName ?? `run ${run.id}`}: ${job.name}`),
1325
+ ),
1326
+ };
1327
+ }
1328
+
1329
+ function buildCommitRunWatchDetails(
1330
+ repo: string,
1331
+ headSha: string,
1332
+ branch: string | undefined,
1333
+ runs: GhRunSnapshot[],
1334
+ options?: {
1335
+ state?: GhRunWatchViewDetails["state"];
1336
+ pollCount?: number;
1337
+ note?: string;
1338
+ failedJobLogs?: GhFailedJobLog[];
1339
+ },
1340
+ ): GhToolDetails {
1341
+ const observedAtMs = Date.now();
1342
+ return {
1343
+ ...buildGhRunCollectionDetails(repo, headSha, branch, runs),
1344
+ watch: {
1345
+ mode: "commit",
1346
+ state: options?.state ?? "completed",
1347
+ repo,
1348
+ branch,
1349
+ headSha,
1350
+ pollCount: options?.pollCount,
1351
+ note: options?.note,
1352
+ runs: runs.map(run => buildRunWatchRunDetails(run, observedAtMs)),
1353
+ failedLogs: buildFailedLogDetails(options?.failedJobLogs ?? []),
1354
+ },
1355
+ };
1356
+ }
1357
+
1358
+ async function resolveGitHubRepo(
1359
+ cwd: string,
1360
+ repo: string | undefined,
1361
+ runRepo: string | undefined,
1362
+ signal?: AbortSignal,
1363
+ ): Promise<string> {
1364
+ if (repo && runRepo && repo !== runRepo) {
1365
+ throw new ToolError("run URL repository does not match the provided repo");
1366
+ }
1367
+
1368
+ if (repo) {
1369
+ return repo;
1370
+ }
1371
+
1372
+ if (runRepo) {
1373
+ return runRepo;
1374
+ }
1375
+
1376
+ const resolved = await git.github.text(
1377
+ cwd,
1378
+ ["repo", "view", "--json", "nameWithOwner", "-q", ".nameWithOwner"],
1379
+ signal,
1380
+ );
1381
+ return requireNonEmpty(resolved, "repo");
1382
+ }
1383
+
1384
+ async function resolveGitHubBranchHead(
1385
+ cwd: string,
1386
+ repo: string,
1387
+ branch: string,
1388
+ signal?: AbortSignal,
1389
+ ): Promise<string> {
1390
+ const response = await git.github.json<GhBranchApiResponse>(
1391
+ cwd,
1392
+ ["api", "--method", "GET", `/repos/${repo}/branches/${encodeURIComponent(branch)}`],
1393
+ signal,
1394
+ { repoProvided: true },
1395
+ );
1396
+ return requireNonEmpty(response.commit?.sha, `head SHA for branch ${branch}`);
1397
+ }
1398
+
1399
+ async function fetchRunsForCommit(
1400
+ cwd: string,
1401
+ repo: string,
1402
+ headSha: string,
1403
+ branch: string | undefined,
1404
+ signal?: AbortSignal,
1405
+ ): Promise<GhRunSnapshot[]> {
1406
+ const response = await git.github.json<GhActionsRunListResponse>(
1407
+ cwd,
1408
+ [
1409
+ "api",
1410
+ "--method",
1411
+ "GET",
1412
+ `/repos/${repo}/actions/runs`,
1413
+ "-F",
1414
+ `head_sha=${headSha}`,
1415
+ "-F",
1416
+ `per_page=${RUN_JOBS_PAGE_SIZE}`,
1417
+ ...(branch ? ["-F", `branch=${branch}`] : []),
1418
+ ],
1419
+ signal,
1420
+ { repoProvided: true },
1421
+ );
1422
+
1423
+ return Promise.all(
1424
+ (response.workflow_runs ?? [])
1425
+ .filter((run): run is GhActionsRunApi & { id: number } => typeof run.id === "number")
1426
+ .map(async run => {
1427
+ const jobs = await fetchRunJobs(cwd, repo, run.id, signal);
1428
+ return normalizeRunSnapshot(run, jobs);
1429
+ }),
1430
+ );
1431
+ }
1432
+
1433
+ async function fetchRunJobs(
1434
+ cwd: string,
1435
+ repo: string,
1436
+ runId: number,
1437
+ signal?: AbortSignal,
1438
+ ): Promise<GhRunJobSnapshot[]> {
1439
+ const jobs: GhRunJobSnapshot[] = [];
1440
+ let page = 1;
1441
+
1442
+ while (true) {
1443
+ const response = await git.github.json<GhActionsJobsResponse>(
1444
+ cwd,
1445
+ [
1446
+ "api",
1447
+ "--method",
1448
+ "GET",
1449
+ `/repos/${repo}/actions/runs/${runId}/jobs`,
1450
+ "-F",
1451
+ `per_page=${RUN_JOBS_PAGE_SIZE}`,
1452
+ "-F",
1453
+ `page=${page}`,
1454
+ ],
1455
+ signal,
1456
+ { repoProvided: true },
1457
+ );
1458
+ const pageJobs = (response.jobs ?? [])
1459
+ .map(job => normalizeRunJob(job))
1460
+ .filter((job): job is GhRunJobSnapshot => job !== null);
1461
+ jobs.push(...pageJobs);
1462
+
1463
+ if (pageJobs.length < RUN_JOBS_PAGE_SIZE) {
1464
+ break;
1465
+ }
1466
+
1467
+ if ((response.total_count ?? 0) <= jobs.length) {
1468
+ break;
1469
+ }
1470
+
1471
+ page += 1;
1472
+ }
1473
+
1474
+ return jobs;
1475
+ }
1476
+
1477
+ async function fetchPrReviewComments(
1478
+ cwd: string,
1479
+ repo: string,
1480
+ prNumber: number,
1481
+ signal?: AbortSignal,
1482
+ ): Promise<GhPrReviewComment[]> {
1483
+ const reviewComments: GhPrReviewComment[] = [];
1484
+ let page = 1;
1485
+
1486
+ while (true) {
1487
+ const response = await git.github.json<GhPrReviewCommentApi[]>(
1488
+ cwd,
1489
+ [
1490
+ "api",
1491
+ "--method",
1492
+ "GET",
1493
+ `/repos/${repo}/pulls/${prNumber}/comments`,
1494
+ "-F",
1495
+ `per_page=${REVIEW_COMMENTS_PAGE_SIZE}`,
1496
+ "-F",
1497
+ `page=${page}`,
1498
+ ],
1499
+ signal,
1500
+ { repoProvided: true },
1501
+ );
1502
+
1503
+ const pageComments = response
1504
+ .map(comment => normalizePrReviewComment(comment))
1505
+ .filter((comment): comment is GhPrReviewComment => comment !== null);
1506
+ reviewComments.push(...pageComments);
1507
+
1508
+ if (pageComments.length < REVIEW_COMMENTS_PAGE_SIZE) {
1509
+ break;
1510
+ }
1511
+
1512
+ page += 1;
1513
+ }
1514
+
1515
+ return reviewComments;
1516
+ }
1517
+
1518
+ async function fetchRunSnapshot(
1519
+ cwd: string,
1520
+ repo: string,
1521
+ runId: number,
1522
+ signal?: AbortSignal,
1523
+ ): Promise<GhRunSnapshot> {
1524
+ const [run, jobs] = await Promise.all([
1525
+ git.github.json<GhActionsRunApi>(
1526
+ cwd,
1527
+ ["api", "--method", "GET", `/repos/${repo}/actions/runs/${runId}`],
1528
+ signal,
1529
+ {
1530
+ repoProvided: true,
1531
+ },
1532
+ ),
1533
+ fetchRunJobs(cwd, repo, runId, signal),
1534
+ ]);
1535
+
1536
+ return normalizeRunSnapshot(run, jobs);
1537
+ }
1538
+
1539
+ function tailLogLines(log: string, tail: number): string | undefined {
1540
+ const normalized = normalizeBlock(log);
1541
+ if (!normalized) {
1542
+ return undefined;
1543
+ }
1544
+
1545
+ const lines = normalized.split("\n");
1546
+ return lines.slice(-tail).join("\n").trimEnd();
1547
+ }
1548
+
1549
+ async function fetchFailedJobLogs(
1550
+ cwd: string,
1551
+ repo: string,
1552
+ failedJobs: Array<{ run: GhRunSnapshot; job: GhRunJobSnapshot }>,
1553
+ tail: number,
1554
+ signal?: AbortSignal,
1555
+ ): Promise<GhFailedJobLog[]> {
1556
+ return Promise.all(
1557
+ failedJobs.map(async entry => {
1558
+ const result = await git.github.run(cwd, ["api", `/repos/${repo}/actions/jobs/${entry.job.id}/logs`], signal);
1559
+ const fullLog = result.exitCode === 0 ? normalizeBlock(result.stdout) : undefined;
1560
+ const logTail = fullLog ? tailLogLines(fullLog, tail) : undefined;
1561
+ return {
1562
+ run: entry.run,
1563
+ job: entry.job,
1564
+ full: fullLog,
1565
+ tail: logTail,
1566
+ available: Boolean(fullLog),
1567
+ };
1568
+ }),
1569
+ );
1570
+ }
1571
+
1572
+ function formatCommentsSection(comments: GhComment[] | undefined): string[] {
1573
+ if (!comments || comments.length === 0) {
1574
+ return [];
1575
+ }
1576
+
1577
+ const visible = comments.filter(comment => !comment.isMinimized);
1578
+ const hiddenCount = comments.length - visible.length;
1579
+ const lines: string[] = ["## Comments", ""];
1580
+
1581
+ if (visible.length === 0) {
1582
+ lines.push(`No visible comments. Minimized comments omitted: ${hiddenCount}.`);
1583
+ return lines;
1584
+ }
1585
+
1586
+ lines[0] = `## Comments (${visible.length})`;
1587
+
1588
+ for (const comment of visible) {
1589
+ const author = formatAuthor(comment.author) ?? "unknown";
1590
+ const createdAt = comment.createdAt ? ` · ${comment.createdAt}` : "";
1591
+ lines.push(`### ${author}${createdAt}`);
1592
+ lines.push("");
1593
+ lines.push(normalizeText(comment.body) || "No comment body.");
1594
+ if (comment.url) {
1595
+ lines.push("");
1596
+ lines.push(`URL: ${comment.url}`);
1597
+ }
1598
+ lines.push("");
1599
+ }
1600
+
1601
+ if (hiddenCount > 0) {
1602
+ lines.push(`Minimized comments omitted: ${hiddenCount}.`);
1603
+ }
1604
+
1605
+ return lines;
1606
+ }
1607
+
1608
+ function formatReviewsSection(reviews: GhPrReview[] | undefined): string[] {
1609
+ if (!reviews || reviews.length === 0) {
1610
+ return [];
1611
+ }
1612
+
1613
+ const lines: string[] = [`## Reviews (${reviews.length})`, ""];
1614
+ for (const review of reviews) {
1615
+ const author = formatAuthor(review.author) ?? "unknown";
1616
+ const submittedAt = review.submittedAt ? ` - ${review.submittedAt}` : "";
1617
+ const state = review.state ? ` [${review.state}]` : "";
1618
+ lines.push(`### ${author}${submittedAt}${state}`);
1619
+ if (review.commit?.oid) {
1620
+ lines.push("");
1621
+ lines.push(`Commit: ${formatShortSha(review.commit.oid)}`);
1622
+ }
1623
+ lines.push("");
1624
+ lines.push(normalizeText(review.body) || "No review body.");
1625
+ lines.push("");
1626
+ }
1627
+
1628
+ return lines;
1629
+ }
1630
+
1631
+ function formatReviewCommentLocation(comment: GhPrReviewComment): string | undefined {
1632
+ if (!comment.path) {
1633
+ return undefined;
1634
+ }
1635
+
1636
+ const line = comment.line ?? comment.originalLine;
1637
+ return line === undefined ? comment.path : `${comment.path}:${line}`;
1638
+ }
1639
+
1640
+ function formatReviewCommentsSection(comments: GhPrReviewComment[] | undefined): string[] {
1641
+ if (!comments || comments.length === 0) {
1642
+ return [];
1643
+ }
1644
+
1645
+ const lines: string[] = [`## Review Comments (${comments.length})`, ""];
1646
+ for (const comment of comments) {
1647
+ const author = formatAuthor(comment.author) ?? "unknown";
1648
+ const createdAt = comment.createdAt ? ` · ${comment.createdAt}` : "";
1649
+ lines.push(`### ${author}${createdAt}`);
1650
+ lines.push("");
1651
+ pushLine(lines, "Location", formatReviewCommentLocation(comment));
1652
+ pushLine(lines, "Side", comment.side);
1653
+ pushLine(lines, "Reply to", comment.inReplyToId);
1654
+ pushLine(lines, "URL", comment.url);
1655
+ lines.push("");
1656
+ lines.push(normalizeText(comment.body) || "No review comment body.");
1657
+ lines.push("");
1658
+ }
1659
+
1660
+ return lines;
1661
+ }
1662
+
1663
+ function formatRepoView(data: GhRepoViewData, input: GhRepoViewInput): string {
1664
+ const lines: string[] = [];
1665
+ const name = data.nameWithOwner ?? input.repo ?? "GitHub Repository";
1666
+ lines.push(`# ${name}`);
1667
+ lines.push("");
1668
+ lines.push(normalizeText(data.description) || "No description provided.");
1669
+ lines.push("");
1670
+ pushLine(lines, "URL", data.url);
1671
+ pushLine(lines, "Default branch", data.defaultBranchRef?.name);
1672
+ pushLine(lines, "Branch", normalizeOptionalString(input.branch));
1673
+ pushLine(lines, "Visibility", data.visibility ?? undefined);
1674
+ pushLine(lines, "Viewer permission", data.viewerPermission ?? undefined);
1675
+ pushLine(lines, "Primary language", data.primaryLanguage?.name);
1676
+ pushLine(lines, "Stars", data.stargazerCount);
1677
+ pushLine(lines, "Forks", data.forkCount);
1678
+ pushLine(lines, "Archived", data.isArchived);
1679
+ pushLine(lines, "Fork", data.isFork);
1680
+ pushLine(lines, "Updated", data.updatedAt);
1681
+ pushLine(lines, "Homepage", data.homepageUrl ?? undefined);
1682
+ const topics = data.repositoryTopics
1683
+ ?.map(topic => topic.name ?? topic.topic?.name)
1684
+ .filter((value): value is string => Boolean(value))
1685
+ .join(", ");
1686
+ pushLine(lines, "Topics", topics || undefined);
1687
+ return lines.join("\n").trim();
1688
+ }
1689
+
1690
+ function formatIssueView(data: GhIssueViewData, input: GhIssueViewInput): string {
1691
+ const lines: string[] = [];
1692
+ const issueNumber = data.number ?? input.issue;
1693
+ lines.push(`# Issue #${issueNumber}: ${data.title ?? "Untitled"}`);
1694
+ lines.push("");
1695
+ pushLine(lines, "State", data.state);
1696
+ pushLine(lines, "State reason", data.stateReason ?? undefined);
1697
+ pushLine(lines, "Author", formatAuthor(data.author));
1698
+ pushLine(lines, "Created", data.createdAt);
1699
+ pushLine(lines, "Updated", data.updatedAt);
1700
+ pushLine(lines, "Labels", formatLabels(data.labels));
1701
+ pushLine(lines, "URL", data.url);
1702
+ lines.push("");
1703
+ lines.push("## Body");
1704
+ lines.push("");
1705
+ lines.push(normalizeText(data.body) || "No description provided.");
1706
+
1707
+ if ((input.comments ?? true) && data.comments) {
1708
+ const commentSection = formatCommentsSection(data.comments);
1709
+ if (commentSection.length > 0) {
1710
+ lines.push("");
1711
+ lines.push(...commentSection);
1712
+ }
1713
+ }
1714
+
1715
+ return lines.join("\n").trim();
1716
+ }
1717
+
1718
+ function formatPrFiles(files: GhPrFile[] | undefined): string[] {
1719
+ if (!files || files.length === 0) return [];
1720
+
1721
+ const lines: string[] = [`## Files (${files.length})`, ""];
1722
+ for (const file of files.slice(0, FILE_PREVIEW_LIMIT)) {
1723
+ const changeType = file.changeType ?? "CHANGED";
1724
+ const additions = file.additions ?? 0;
1725
+ const deletions = file.deletions ?? 0;
1726
+ lines.push(`- ${file.path ?? "(unknown file)"} [${changeType}] (+${additions} -${deletions})`);
1727
+ }
1728
+
1729
+ if (files.length > FILE_PREVIEW_LIMIT) {
1730
+ lines.push(`- ... ${files.length - FILE_PREVIEW_LIMIT} more files`);
1731
+ }
1732
+
1733
+ return lines;
1734
+ }
1735
+
1736
+ function formatPrView(data: GhPrViewData, input: GhPrViewInput): string {
1737
+ const lines: string[] = [];
1738
+ const prIdentifier = data.number ?? input.pr ?? "current";
1739
+ lines.push(`# Pull Request #${prIdentifier}: ${data.title ?? "Untitled"}`);
1740
+ lines.push("");
1741
+ pushLine(lines, "State", data.state);
1742
+ pushLine(lines, "Draft", data.isDraft);
1743
+ pushLine(lines, "Author", formatAuthor(data.author));
1744
+ pushLine(lines, "Base", data.baseRefName);
1745
+ pushLine(lines, "Head", data.headRefName);
1746
+ pushLine(lines, "Review decision", data.reviewDecision ?? undefined);
1747
+ pushLine(lines, "Merge state", data.mergeStateStatus);
1748
+ pushLine(lines, "Created", data.createdAt);
1749
+ pushLine(lines, "Updated", data.updatedAt);
1750
+ pushLine(lines, "Labels", formatLabels(data.labels));
1751
+ pushLine(lines, "URL", data.url);
1752
+ lines.push("");
1753
+ lines.push("## Body");
1754
+ lines.push("");
1755
+ lines.push(normalizeText(data.body) || "No description provided.");
1756
+
1757
+ const fileSection = formatPrFiles(data.files);
1758
+ if (fileSection.length > 0) {
1759
+ lines.push("");
1760
+ lines.push(...fileSection);
1761
+ }
1762
+
1763
+ if ((input.comments ?? true) && data.reviews) {
1764
+ const reviewSection = formatReviewsSection(data.reviews);
1765
+ if (reviewSection.length > 0) {
1766
+ lines.push("");
1767
+ lines.push(...reviewSection);
1768
+ }
1769
+ }
1770
+
1771
+ if ((input.comments ?? true) && data.reviewComments) {
1772
+ const reviewCommentsSection = formatReviewCommentsSection(data.reviewComments);
1773
+ if (reviewCommentsSection.length > 0) {
1774
+ lines.push("");
1775
+ lines.push(...reviewCommentsSection);
1776
+ }
1777
+ }
1778
+
1779
+ if ((input.comments ?? true) && data.comments) {
1780
+ const commentSection = formatCommentsSection(data.comments);
1781
+ if (commentSection.length > 0) {
1782
+ lines.push("");
1783
+ lines.push(...commentSection);
1784
+ }
1785
+ }
1786
+
1787
+ return lines.join("\n").trim();
1788
+ }
1789
+
1790
+ function formatPrCheckoutResult(options: {
1791
+ data: GhPrViewData;
1792
+ localBranch: string;
1793
+ worktreePath: string;
1794
+ remoteName: string;
1795
+ remoteUrl: string;
1796
+ reused: boolean;
1797
+ }): string {
1798
+ const { data, localBranch, worktreePath, remoteName, remoteUrl, reused } = options;
1799
+ const lines: string[] = [
1800
+ reused ? `# Pull Request #${data.number ?? "?"} Worktree` : `# Checked Out Pull Request #${data.number ?? "?"}`,
1801
+ "",
1802
+ ];
1803
+ pushLine(lines, "Title", data.title ?? undefined);
1804
+ pushLine(lines, "URL", data.url);
1805
+ pushLine(lines, "Base", data.baseRefName);
1806
+ pushLine(lines, "Head", data.headRefName);
1807
+ pushLine(lines, "Local branch", localBranch);
1808
+ pushLine(lines, "Worktree", worktreePath);
1809
+ pushLine(lines, "Remote", remoteName);
1810
+ pushLine(lines, "Remote URL", remoteUrl);
1811
+ pushLine(lines, "Cross repository", data.isCrossRepository);
1812
+ pushLine(lines, "Maintainer can modify", data.maintainerCanModify);
1813
+ lines.push("");
1814
+ lines.push(
1815
+ reused
1816
+ ? "Reused the existing PR worktree."
1817
+ : "Created a dedicated worktree for this PR and configured the local branch to push back to the PR head branch.",
1818
+ );
1819
+ return lines.join("\n").trim();
1820
+ }
1821
+
1822
+ function formatPrPushResult(options: {
1823
+ localBranch: string;
1824
+ remoteName: string;
1825
+ remoteBranch: string;
1826
+ remoteUrl?: string;
1827
+ prUrl?: string;
1828
+ forceWithLease: boolean;
1829
+ }): string {
1830
+ const lines: string[] = ["# Pushed Pull Request Branch", ""];
1831
+ pushLine(lines, "Local branch", options.localBranch);
1832
+ pushLine(lines, "Remote", options.remoteName);
1833
+ pushLine(lines, "Remote branch", options.remoteBranch);
1834
+ pushLine(lines, "Remote URL", options.remoteUrl);
1835
+ pushLine(lines, "PR", options.prUrl);
1836
+ pushLine(lines, "Force with lease", options.forceWithLease);
1837
+ lines.push("");
1838
+ lines.push(`Pushed ${options.localBranch} to ${options.remoteName}:${options.remoteBranch}.`);
1839
+ return lines.join("\n").trim();
1840
+ }
1841
+
1842
+ function formatSearchResults(
1843
+ kind: "issues" | "pull requests",
1844
+ query: string,
1845
+ repo: string | undefined,
1846
+ items: GhSearchResult[],
1847
+ ): string {
1848
+ const lines: string[] = [`# GitHub ${kind} search`, "", `Query: ${query}`];
1849
+ pushLine(lines, "Repository", repo);
1850
+ pushLine(lines, "Results", items.length);
1851
+
1852
+ if (items.length === 0) {
1853
+ lines.push("");
1854
+ lines.push(`No ${kind} found.`);
1855
+ return lines.join("\n").trim();
1856
+ }
1857
+
1858
+ for (const item of items) {
1859
+ lines.push("");
1860
+ lines.push(`- #${item.number ?? "?"} ${item.title ?? "Untitled"}`);
1861
+ pushLine(lines, " Repo", item.repository?.nameWithOwner);
1862
+ pushLine(lines, " State", item.state);
1863
+ pushLine(lines, " Author", formatAuthor(item.author));
1864
+ pushLine(lines, " Labels", formatLabels(item.labels));
1865
+ pushLine(lines, " Created", item.createdAt);
1866
+ pushLine(lines, " Updated", item.updatedAt);
1867
+ pushLine(lines, " URL", item.url);
1868
+ }
1869
+
1870
+ return lines.join("\n").trim();
1871
+ }
1872
+
1873
+ async function saveArtifactText(session: ToolSession, toolType: string, text: string): Promise<string | undefined> {
1874
+ const { path: artifactPath, id: artifactId } = (await session.allocateOutputArtifact?.(toolType)) ?? {};
1875
+ if (!artifactPath || !artifactId) {
1876
+ return undefined;
1877
+ }
1878
+
1879
+ await Bun.write(artifactPath, text);
1880
+ return artifactId;
1881
+ }
1882
+
1883
+ function appendArtifactReference(text: string, artifactId: string | undefined, label: string): string {
1884
+ if (!artifactId) {
1885
+ return text;
1886
+ }
1887
+
1888
+ return `${text}\n\n${label}: artifact://${artifactId}`;
1889
+ }
1890
+
1891
+ function buildTextResult(
1892
+ text: string,
1893
+ sourceUrl?: string,
1894
+ details?: GhToolDetails,
1895
+ options?: { artifactId?: string; artifactLabel?: string },
1896
+ ): AgentToolResult<GhToolDetails> {
1897
+ const builder = toolResult<GhToolDetails>(details).text(
1898
+ appendArtifactReference(text, options?.artifactId, options?.artifactLabel ?? "Saved artifact"),
1899
+ );
1900
+ if (sourceUrl) {
1901
+ builder.sourceUrl(sourceUrl);
1902
+ }
1903
+ return builder.done();
1904
+ }
1905
+
1906
+ export class GhRepoViewTool implements AgentTool<typeof ghRepoViewSchema, GhToolDetails> {
1907
+ readonly name = "gh_repo_view";
1908
+ readonly label = "GitHub Repo";
1909
+ readonly description = prompt.render(ghRepoViewDescription);
1910
+ readonly parameters = ghRepoViewSchema;
1911
+ readonly strict = true;
1912
+
1913
+ constructor(private readonly session: ToolSession) {}
1914
+
1915
+ static createIf(session: ToolSession): GhRepoViewTool | null {
1916
+ if (!git.github.available()) return null;
1917
+ return new GhRepoViewTool(session);
1918
+ }
1919
+
1920
+ async execute(
1921
+ _toolCallId: string,
1922
+ params: GhRepoViewInput,
1923
+ signal?: AbortSignal,
1924
+ _onUpdate?: AgentToolUpdateCallback<GhToolDetails>,
1925
+ _context?: AgentToolContext,
1926
+ ): Promise<AgentToolResult<GhToolDetails>> {
1927
+ return untilAborted(signal, async () => {
1928
+ const repo = normalizeOptionalString(params.repo);
1929
+ const branch = normalizeOptionalString(params.branch);
1930
+ const args = ["repo", "view"];
1931
+ if (repo) {
1932
+ args.push(repo);
1933
+ }
1934
+ if (branch) {
1935
+ args.push("--branch", branch);
1936
+ }
1937
+ args.push("--json", GH_REPO_FIELDS.join(","));
1938
+
1939
+ const data = await git.github.json<GhRepoViewData>(this.session.cwd, args, signal, {
1940
+ repoProvided: Boolean(repo),
1941
+ });
1942
+ return buildTextResult(formatRepoView(data, { repo, branch }), data.url);
1943
+ });
1944
+ }
1945
+ }
1946
+
1947
+ export class GhIssueViewTool implements AgentTool<typeof ghIssueViewSchema, GhToolDetails> {
1948
+ readonly name = "gh_issue_view";
1949
+ readonly label = "GitHub Issue";
1950
+ readonly description = prompt.render(ghIssueViewDescription);
1951
+ readonly parameters = ghIssueViewSchema;
1952
+ readonly strict = true;
1953
+
1954
+ constructor(private readonly session: ToolSession) {}
1955
+
1956
+ static createIf(session: ToolSession): GhIssueViewTool | null {
1957
+ if (!git.github.available()) return null;
1958
+ return new GhIssueViewTool(session);
1959
+ }
1960
+
1961
+ async execute(
1962
+ _toolCallId: string,
1963
+ params: GhIssueViewInput,
1964
+ signal?: AbortSignal,
1965
+ _onUpdate?: AgentToolUpdateCallback<GhToolDetails>,
1966
+ _context?: AgentToolContext,
1967
+ ): Promise<AgentToolResult<GhToolDetails>> {
1968
+ return untilAborted(signal, async () => {
1969
+ const issue = requireNonEmpty(params.issue, "issue");
1970
+ const repo = normalizeOptionalString(params.repo);
1971
+ const includeComments = params.comments ?? true;
1972
+ const args = ["issue", "view", issue];
1973
+ appendRepoFlag(args, repo, issue);
1974
+ args.push("--json", (includeComments ? GH_ISSUE_FIELDS : GH_ISSUE_FIELDS_NO_COMMENTS).join(","));
1975
+
1976
+ const data = await git.github.json<GhIssueViewData>(this.session.cwd, args, signal, {
1977
+ repoProvided: Boolean(repo),
1978
+ });
1979
+ return buildTextResult(formatIssueView(data, { issue, repo, comments: includeComments }), data.url);
1980
+ });
1981
+ }
1982
+ }
1983
+
1984
+ export class GhPrViewTool implements AgentTool<typeof ghPrViewSchema, GhToolDetails> {
1985
+ readonly name = "gh_pr_view";
1986
+ readonly label = "GitHub PR";
1987
+ readonly description = prompt.render(ghPrViewDescription);
1988
+ readonly parameters = ghPrViewSchema;
1989
+ readonly strict = true;
1990
+
1991
+ constructor(private readonly session: ToolSession) {}
1992
+
1993
+ static createIf(session: ToolSession): GhPrViewTool | null {
1994
+ if (!git.github.available()) return null;
1995
+ return new GhPrViewTool(session);
1996
+ }
1997
+
1998
+ async execute(
1999
+ _toolCallId: string,
2000
+ params: GhPrViewInput,
2001
+ signal?: AbortSignal,
2002
+ _onUpdate?: AgentToolUpdateCallback<GhToolDetails>,
2003
+ _context?: AgentToolContext,
2004
+ ): Promise<AgentToolResult<GhToolDetails>> {
2005
+ return untilAborted(signal, async () => {
2006
+ const pr = normalizeOptionalString(params.pr);
2007
+ const repo = normalizeOptionalString(params.repo);
2008
+ const includeComments = params.comments ?? true;
2009
+ const args = ["pr", "view"];
2010
+ if (pr) {
2011
+ args.push(pr);
2012
+ }
2013
+ appendRepoFlag(args, repo, pr);
2014
+ args.push("--json", (includeComments ? GH_PR_FIELDS : GH_PR_FIELDS_NO_COMMENTS).join(","));
2015
+
2016
+ const data = await git.github.json<GhPrViewData>(this.session.cwd, args, signal, {
2017
+ repoProvided: Boolean(repo),
2018
+ });
2019
+ const resolvedRepo = repo ?? parsePullRequestUrl(data.url).repo;
2020
+ if (includeComments && resolvedRepo && typeof data.number === "number") {
2021
+ data.reviewComments = await fetchPrReviewComments(this.session.cwd, resolvedRepo, data.number, signal);
2022
+ }
2023
+ return buildTextResult(formatPrView(data, { pr, repo, comments: includeComments }), data.url);
2024
+ });
2025
+ }
2026
+ }
2027
+
2028
+ export class GhPrDiffTool implements AgentTool<typeof ghPrDiffSchema, GhToolDetails> {
2029
+ readonly name = "gh_pr_diff";
2030
+ readonly label = "GitHub PR Diff";
2031
+ readonly description = prompt.render(ghPrDiffDescription);
2032
+ readonly parameters = ghPrDiffSchema;
2033
+ readonly strict = true;
2034
+
2035
+ constructor(private readonly session: ToolSession) {}
2036
+
2037
+ static createIf(session: ToolSession): GhPrDiffTool | null {
2038
+ if (!git.github.available()) return null;
2039
+ return new GhPrDiffTool(session);
2040
+ }
2041
+
2042
+ async execute(
2043
+ _toolCallId: string,
2044
+ params: GhPrDiffInput,
2045
+ signal?: AbortSignal,
2046
+ _onUpdate?: AgentToolUpdateCallback<GhToolDetails>,
2047
+ _context?: AgentToolContext,
2048
+ ): Promise<AgentToolResult<GhToolDetails>> {
2049
+ return untilAborted(signal, async () => {
2050
+ const pr = normalizeOptionalString(params.pr);
2051
+ const repo = normalizeOptionalString(params.repo);
2052
+ const args = ["pr", "diff"];
2053
+ if (pr) {
2054
+ args.push(pr);
2055
+ }
2056
+ appendRepoFlag(args, repo, pr);
2057
+ args.push("--color", "never");
2058
+ if (params.nameOnly) {
2059
+ args.push("--name-only");
2060
+ }
2061
+ for (const pattern of params.exclude ?? []) {
2062
+ const normalizedPattern = requireNonEmpty(pattern, "exclude pattern");
2063
+ args.push("--exclude", normalizedPattern);
2064
+ }
2065
+
2066
+ const output = await git.github.text(this.session.cwd, args, signal, {
2067
+ repoProvided: Boolean(repo),
2068
+ trimOutput: false,
2069
+ });
2070
+ const title = params.nameOnly ? "# Pull Request Files" : "# Pull Request Diff";
2071
+ const body = output.length > 0 ? output : params.nameOnly ? "No changed files." : "No diff output.";
2072
+ return buildTextResult(`${title}\n\n${body}`);
2073
+ });
2074
+ }
2075
+ }
2076
+
2077
+ export class GhPrCheckoutTool implements AgentTool<typeof ghPrCheckoutSchema, GhToolDetails> {
2078
+ readonly name = "gh_pr_checkout";
2079
+ readonly label = "GitHub PR Checkout";
2080
+ readonly description = prompt.render(ghPrCheckoutDescription);
2081
+ readonly parameters = ghPrCheckoutSchema;
2082
+ readonly strict = true;
2083
+
2084
+ constructor(private readonly session: ToolSession) {}
2085
+
2086
+ static createIf(session: ToolSession): GhPrCheckoutTool | null {
2087
+ if (!git.github.available()) return null;
2088
+ return new GhPrCheckoutTool(session);
2089
+ }
2090
+
2091
+ async execute(
2092
+ _toolCallId: string,
2093
+ params: GhPrCheckoutInput,
2094
+ signal?: AbortSignal,
2095
+ _onUpdate?: AgentToolUpdateCallback<GhToolDetails>,
2096
+ _context?: AgentToolContext,
2097
+ ): Promise<AgentToolResult<GhToolDetails>> {
2098
+ return untilAborted(signal, async () => {
2099
+ const pr = normalizeOptionalString(params.pr);
2100
+ const repo = normalizeOptionalString(params.repo);
2101
+ const requestedBranch = normalizeOptionalString(params.branch);
2102
+ const requestedWorktree = normalizeOptionalString(params.worktree);
2103
+ const force = params.force ?? false;
2104
+ const args = ["pr", "view"];
2105
+ if (pr) {
2106
+ args.push(pr);
2107
+ }
2108
+ appendRepoFlag(args, repo, pr);
2109
+ args.push("--json", GH_PR_CHECKOUT_FIELDS.join(","));
2110
+
2111
+ const data = await git.github.json<GhPrViewData>(this.session.cwd, args, signal, {
2112
+ repoProvided: Boolean(repo),
2113
+ });
2114
+ const prNumber = data.number;
2115
+ if (typeof prNumber !== "number") {
2116
+ throw new ToolError("GitHub CLI did not return a pull request number.");
2117
+ }
2118
+
2119
+ const headRefName = requireNonEmpty(data.headRefName, "head branch");
2120
+ const headRefOid = requireNonEmpty(data.headRefOid, "head commit");
2121
+ const repoRoot = await requireGitRepoRoot(this.session.cwd, signal);
2122
+ const primaryRepoRoot = await requirePrimaryGitRepoRoot(repoRoot, signal);
2123
+ const localBranch = requestedBranch ?? `pr-${prNumber}`;
2124
+ const worktreePath = requestedWorktree
2125
+ ? path.resolve(this.session.cwd, requestedWorktree)
2126
+ : path.join(primaryRepoRoot, ".worktrees", localBranch);
2127
+ const existingWorktrees = await git.worktree.list(repoRoot, signal);
2128
+ const existingWorktree = existingWorktrees.find(entry => entry.branch === toLocalBranchRef(localBranch));
2129
+
2130
+ const remote = await ensurePrRemote(repoRoot, data, signal);
2131
+ await git.fetch(
2132
+ repoRoot,
2133
+ remote.name,
2134
+ `refs/heads/${headRefName}`,
2135
+ `refs/remotes/${remote.name}/${headRefName}`,
2136
+ signal,
2137
+ );
2138
+
2139
+ if (!existingWorktree) {
2140
+ const localBranchRef = toLocalBranchRef(localBranch);
2141
+ const localBranchExists = await git.ref.exists(repoRoot, localBranchRef, signal);
2142
+ if (localBranchExists) {
2143
+ const existingOid = await git.ref.resolve(repoRoot, localBranchRef, signal);
2144
+ if (existingOid !== headRefOid) {
2145
+ if (!force) {
2146
+ throw new ToolError(
2147
+ `local branch ${localBranch} already exists at ${formatShortSha(existingOid ?? undefined) ?? existingOid ?? "unknown commit"}; pass force=true to reset it`,
2148
+ );
2149
+ }
2150
+
2151
+ await git.branch.force(repoRoot, localBranch, `refs/remotes/${remote.name}/${headRefName}`, signal);
2152
+ }
2153
+ } else {
2154
+ await git.branch.create(repoRoot, localBranch, `refs/remotes/${remote.name}/${headRefName}`, signal);
2155
+ }
2156
+ }
2157
+
2158
+ await git.config.setBranch(repoRoot, localBranch, "remote", remote.name, signal);
2159
+ await git.config.setBranch(repoRoot, localBranch, "merge", `refs/heads/${headRefName}`, signal);
2160
+ await git.config.setBranch(repoRoot, localBranch, "pushRemote", remote.name, signal);
2161
+ await git.config.setBranch(repoRoot, localBranch, "ompPrHeadRef", headRefName, signal);
2162
+ await git.config.setBranch(repoRoot, localBranch, "ompPrUrl", data.url ?? "", signal);
2163
+ await git.config.setBranch(
2164
+ repoRoot,
2165
+ localBranch,
2166
+ "ompPrIsCrossRepository",
2167
+ String(Boolean(data.isCrossRepository)),
2168
+ signal,
2169
+ );
2170
+ await git.config.setBranch(
2171
+ repoRoot,
2172
+ localBranch,
2173
+ "ompPrMaintainerCanModify",
2174
+ String(Boolean(data.maintainerCanModify)),
2175
+ signal,
2176
+ );
2177
+
2178
+ const finalWorktreePath = existingWorktree?.path ?? worktreePath;
2179
+ if (!existingWorktree) {
2180
+ await ensureGitWorktreePathAvailable(finalWorktreePath, existingWorktrees);
2181
+ await fs.mkdir(path.dirname(finalWorktreePath), { recursive: true });
2182
+ await git.worktree.add(repoRoot, finalWorktreePath, localBranch, { signal });
2183
+ }
2184
+ const resolvedWorktreePath = await fs.realpath(finalWorktreePath);
2185
+
2186
+ return buildTextResult(
2187
+ formatPrCheckoutResult({
2188
+ data,
2189
+ localBranch,
2190
+ worktreePath: resolvedWorktreePath,
2191
+ remoteName: remote.name,
2192
+ remoteUrl: remote.url,
2193
+ reused: Boolean(existingWorktree),
2194
+ }),
2195
+ data.url,
2196
+ {
2197
+ repo: repo ?? data.headRepository?.nameWithOwner,
2198
+ branch: localBranch,
2199
+ worktreePath: resolvedWorktreePath,
2200
+ remote: remote.name,
2201
+ remoteBranch: headRefName,
2202
+ },
2203
+ );
2204
+ });
2205
+ }
2206
+ }
2207
+
2208
+ export class GhPrPushTool implements AgentTool<typeof ghPrPushSchema, GhToolDetails> {
2209
+ readonly name = "gh_pr_push";
2210
+ readonly label = "GitHub PR Push";
2211
+ readonly description = prompt.render(ghPrPushDescription);
2212
+ readonly parameters = ghPrPushSchema;
2213
+ readonly strict = true;
2214
+
2215
+ constructor(private readonly session: ToolSession) {}
2216
+
2217
+ static createIf(session: ToolSession): GhPrPushTool | null {
2218
+ if (!git.github.available()) return null;
2219
+ return new GhPrPushTool(session);
2220
+ }
2221
+
2222
+ async execute(
2223
+ _toolCallId: string,
2224
+ params: GhPrPushInput,
2225
+ signal?: AbortSignal,
2226
+ _onUpdate?: AgentToolUpdateCallback<GhToolDetails>,
2227
+ _context?: AgentToolContext,
2228
+ ): Promise<AgentToolResult<GhToolDetails>> {
2229
+ return untilAborted(signal, async () => {
2230
+ const repoRoot = await requireGitRepoRoot(this.session.cwd, signal);
2231
+ const localBranch =
2232
+ normalizeOptionalString(params.branch) ?? (await requireCurrentGitBranch(repoRoot, signal));
2233
+ const refExists = await git.ref.exists(repoRoot, toLocalBranchRef(localBranch), signal);
2234
+ if (!refExists) {
2235
+ throw new ToolError(`local branch ${localBranch} does not exist`);
2236
+ }
2237
+
2238
+ const target = await resolvePrBranchPushTarget(repoRoot, localBranch, signal);
2239
+ const currentBranch = await git.branch.current(repoRoot, signal);
2240
+ const sourceRef = currentBranch === localBranch ? "HEAD" : toLocalBranchRef(localBranch);
2241
+ const refspec = `${sourceRef}:refs/heads/${target.remoteBranch}`;
2242
+ await git.push(repoRoot, {
2243
+ forceWithLease: params.forceWithLease,
2244
+ refspec,
2245
+ remote: target.remoteName,
2246
+ signal,
2247
+ });
2248
+
2249
+ return buildTextResult(
2250
+ formatPrPushResult({
2251
+ localBranch,
2252
+ remoteName: target.remoteName,
2253
+ remoteBranch: target.remoteBranch,
2254
+ remoteUrl: target.remoteUrl,
2255
+ prUrl: target.prUrl,
2256
+ forceWithLease: params.forceWithLease ?? false,
2257
+ }),
2258
+ target.prUrl,
2259
+ {
2260
+ branch: localBranch,
2261
+ remote: target.remoteName,
2262
+ remoteBranch: target.remoteBranch,
2263
+ },
2264
+ );
2265
+ });
2266
+ }
2267
+ }
2268
+
2269
+ export class GhSearchIssuesTool implements AgentTool<typeof ghSearchIssuesSchema, GhToolDetails> {
2270
+ readonly name = "gh_search_issues";
2271
+ readonly label = "GitHub Issue Search";
2272
+ readonly description = prompt.render(ghSearchIssuesDescription);
2273
+ readonly parameters = ghSearchIssuesSchema;
2274
+ readonly strict = true;
2275
+
2276
+ constructor(private readonly session: ToolSession) {}
2277
+
2278
+ static createIf(session: ToolSession): GhSearchIssuesTool | null {
2279
+ if (!git.github.available()) return null;
2280
+ return new GhSearchIssuesTool(session);
2281
+ }
2282
+
2283
+ async execute(
2284
+ _toolCallId: string,
2285
+ params: GhSearchIssuesInput,
2286
+ signal?: AbortSignal,
2287
+ _onUpdate?: AgentToolUpdateCallback<GhToolDetails>,
2288
+ _context?: AgentToolContext,
2289
+ ): Promise<AgentToolResult<GhToolDetails>> {
2290
+ return untilAborted(signal, async () => {
2291
+ const query = requireNonEmpty(params.query, "query");
2292
+ const repo = normalizeOptionalString(params.repo);
2293
+ const limit = resolveSearchLimit(params.limit);
2294
+ const args = buildGhSearchArgs("issues", query, limit, repo);
2295
+
2296
+ const items = await git.github.json<GhSearchResult[]>(this.session.cwd, args, signal, {
2297
+ repoProvided: Boolean(repo),
2298
+ });
2299
+ return buildTextResult(formatSearchResults("issues", query, repo, items));
2300
+ });
2301
+ }
2302
+ }
2303
+
2304
+ export class GhSearchPrsTool implements AgentTool<typeof ghSearchPrsSchema, GhToolDetails> {
2305
+ readonly name = "gh_search_prs";
2306
+ readonly label = "GitHub PR Search";
2307
+ readonly description = prompt.render(ghSearchPrsDescription);
2308
+ readonly parameters = ghSearchPrsSchema;
2309
+ readonly strict = true;
2310
+
2311
+ constructor(private readonly session: ToolSession) {}
2312
+
2313
+ static createIf(session: ToolSession): GhSearchPrsTool | null {
2314
+ if (!git.github.available()) return null;
2315
+ return new GhSearchPrsTool(session);
2316
+ }
2317
+
2318
+ async execute(
2319
+ _toolCallId: string,
2320
+ params: GhSearchPrsInput,
2321
+ signal?: AbortSignal,
2322
+ _onUpdate?: AgentToolUpdateCallback<GhToolDetails>,
2323
+ _context?: AgentToolContext,
2324
+ ): Promise<AgentToolResult<GhToolDetails>> {
2325
+ return untilAborted(signal, async () => {
2326
+ const query = requireNonEmpty(params.query, "query");
2327
+ const repo = normalizeOptionalString(params.repo);
2328
+ const limit = resolveSearchLimit(params.limit);
2329
+ const args = buildGhSearchArgs("prs", query, limit, repo);
2330
+
2331
+ const items = await git.github.json<GhSearchResult[]>(this.session.cwd, args, signal, {
2332
+ repoProvided: Boolean(repo),
2333
+ });
2334
+ return buildTextResult(formatSearchResults("pull requests", query, repo, items));
2335
+ });
2336
+ }
2337
+ }
2338
+
2339
+ export class GhRunWatchTool implements AgentTool<typeof ghRunWatchSchema, GhToolDetails> {
2340
+ readonly name = "gh_run_watch";
2341
+ readonly label = "GitHub Run Watch";
2342
+ readonly description = prompt.render(ghRunWatchDescription);
2343
+ readonly parameters = ghRunWatchSchema;
2344
+ readonly strict = true;
2345
+
2346
+ constructor(private readonly session: ToolSession) {}
2347
+
2348
+ static createIf(session: ToolSession): GhRunWatchTool | null {
2349
+ if (!git.github.available()) return null;
2350
+ return new GhRunWatchTool(session);
2351
+ }
2352
+
2353
+ async execute(
2354
+ _toolCallId: string,
2355
+ params: GhRunWatchInput,
2356
+ signal?: AbortSignal,
2357
+ onUpdate?: AgentToolUpdateCallback<GhToolDetails>,
2358
+ _context?: AgentToolContext,
2359
+ ): Promise<AgentToolResult<GhToolDetails>> {
2360
+ return untilAborted(signal, async () => {
2361
+ const branchInput = normalizeOptionalString(params.branch);
2362
+ const runReference = parseRunReference(params.run);
2363
+ const repo = await resolveGitHubRepo(this.session.cwd, undefined, runReference.repo, signal);
2364
+ const intervalSeconds = RUN_WATCH_INTERVAL_DEFAULT;
2365
+ const graceSeconds = RUN_WATCH_GRACE_DEFAULT;
2366
+ const tail = resolveTailLimit(params.tail);
2367
+ if (runReference.runId !== undefined) {
2368
+ const runId = runReference.runId;
2369
+ let pollCount = 0;
2370
+
2371
+ while (true) {
2372
+ throwIfAborted(signal);
2373
+ pollCount += 1;
2374
+
2375
+ let run = await fetchRunSnapshot(this.session.cwd, repo, runId, signal);
2376
+ const details = buildRunWatchDetails(repo, run, {
2377
+ state: "watching",
2378
+ pollCount,
2379
+ });
2380
+ onUpdate?.({
2381
+ content: [{ type: "text", text: formatRunWatchSnapshot(repo, run, pollCount) }],
2382
+ details,
2383
+ });
2384
+
2385
+ const failedJobs = run.jobs.filter(isFailedJob);
2386
+ const runCompleted = run.status === "completed";
2387
+
2388
+ if (failedJobs.length > 0) {
2389
+ if (!runCompleted && graceSeconds > 0) {
2390
+ const note = `Failure detected. Waiting ${graceSeconds}s to capture concurrent failures before fetching logs.`;
2391
+ onUpdate?.({
2392
+ content: [
2393
+ {
2394
+ type: "text",
2395
+ text: formatRunWatchSnapshot(repo, run, pollCount, note),
2396
+ },
2397
+ ],
2398
+ details: buildRunWatchDetails(repo, run, {
2399
+ state: "watching",
2400
+ pollCount,
2401
+ note,
2402
+ }),
2403
+ });
2404
+ await abortableSleep(graceSeconds * 1000, signal);
2405
+ run = await fetchRunSnapshot(this.session.cwd, repo, runId, signal);
2406
+ }
2407
+
2408
+ const failedJobLogs = await fetchFailedJobLogs(
2409
+ this.session.cwd,
2410
+ repo,
2411
+ run.jobs.filter(isFailedJob).map(job => ({ run, job })),
2412
+ tail,
2413
+ signal,
2414
+ );
2415
+ const finalDetails = buildRunWatchDetails(repo, run, {
2416
+ state: "completed",
2417
+ failedJobLogs,
2418
+ });
2419
+ const artifactId = await saveArtifactText(
2420
+ this.session,
2421
+ this.name,
2422
+ formatRunWatchResult(repo, run, failedJobLogs, tail, { mode: "full" }),
2423
+ );
2424
+ return buildTextResult(
2425
+ formatRunWatchResult(repo, run, failedJobLogs, tail),
2426
+ run.url,
2427
+ { ...finalDetails, artifactId },
2428
+ { artifactId, artifactLabel: "Full failed-job logs" },
2429
+ );
2430
+ }
2431
+
2432
+ if (runCompleted) {
2433
+ const finalDetails = buildRunWatchDetails(repo, run, {
2434
+ state: "completed",
2435
+ });
2436
+ return buildTextResult(formatRunWatchResult(repo, run, [], tail), run.url, finalDetails);
2437
+ }
2438
+
2439
+ await abortableSleep(intervalSeconds * 1000, signal);
2440
+ }
2441
+ }
2442
+
2443
+ const branch = branchInput ?? (await requireCurrentGitBranch(this.session.cwd, signal));
2444
+ const headSha = branchInput
2445
+ ? await resolveGitHubBranchHead(this.session.cwd, repo, branch, signal)
2446
+ : await requireCurrentGitHead(this.session.cwd, signal);
2447
+ let pollCount = 0;
2448
+ let settledSuccessSignature: string | undefined;
2449
+
2450
+ while (true) {
2451
+ throwIfAborted(signal);
2452
+ pollCount += 1;
2453
+
2454
+ let runs = await fetchRunsForCommit(this.session.cwd, repo, headSha, branch, signal);
2455
+ const details = buildCommitRunWatchDetails(repo, headSha, branch, runs, {
2456
+ state: "watching",
2457
+ pollCount,
2458
+ });
2459
+ onUpdate?.({
2460
+ content: [{ type: "text", text: formatCommitRunWatchSnapshot(repo, headSha, branch, runs, pollCount) }],
2461
+ details,
2462
+ });
2463
+
2464
+ const outcome = getRunCollectionOutcome(runs);
2465
+ if (outcome === "failure") {
2466
+ if (graceSeconds > 0) {
2467
+ const note = `Failure detected. Waiting ${graceSeconds}s to capture concurrent failures before fetching logs.`;
2468
+ onUpdate?.({
2469
+ content: [
2470
+ {
2471
+ type: "text",
2472
+ text: formatCommitRunWatchSnapshot(repo, headSha, branch, runs, pollCount, note),
2473
+ },
2474
+ ],
2475
+ details: buildCommitRunWatchDetails(repo, headSha, branch, runs, {
2476
+ state: "watching",
2477
+ pollCount,
2478
+ note,
2479
+ }),
2480
+ });
2481
+ await abortableSleep(graceSeconds * 1000, signal);
2482
+ runs = await fetchRunsForCommit(this.session.cwd, repo, headSha, branch, signal);
2483
+ }
2484
+
2485
+ const failedJobLogs = await fetchFailedJobLogs(
2486
+ this.session.cwd,
2487
+ repo,
2488
+ runs.flatMap(run => run.jobs.filter(isFailedJob).map(job => ({ run, job }))),
2489
+ tail,
2490
+ signal,
2491
+ );
2492
+ const finalDetails = buildCommitRunWatchDetails(repo, headSha, branch, runs, {
2493
+ state: "completed",
2494
+ failedJobLogs,
2495
+ });
2496
+ const artifactId = await saveArtifactText(
2497
+ this.session,
2498
+ this.name,
2499
+ formatCommitRunWatchResult(repo, headSha, branch, runs, failedJobLogs, tail, { mode: "full" }),
2500
+ );
2501
+ return buildTextResult(
2502
+ formatCommitRunWatchResult(repo, headSha, branch, runs, failedJobLogs, tail),
2503
+ undefined,
2504
+ { ...finalDetails, artifactId },
2505
+ { artifactId, artifactLabel: "Full failed-job logs" },
2506
+ );
2507
+ }
2508
+
2509
+ if (outcome === "success") {
2510
+ const signature = getRunCollectionSignature(runs);
2511
+ if (signature === settledSuccessSignature) {
2512
+ const finalDetails = buildCommitRunWatchDetails(repo, headSha, branch, runs, {
2513
+ state: "completed",
2514
+ });
2515
+ return buildTextResult(
2516
+ formatCommitRunWatchResult(repo, headSha, branch, runs, [], tail),
2517
+ undefined,
2518
+ finalDetails,
2519
+ );
2520
+ }
2521
+
2522
+ settledSuccessSignature = signature;
2523
+ const note = `All known workflow runs completed successfully. Waiting ${intervalSeconds}s to ensure no additional runs appear for this commit.`;
2524
+ onUpdate?.({
2525
+ content: [
2526
+ {
2527
+ type: "text",
2528
+ text: formatCommitRunWatchSnapshot(repo, headSha, branch, runs, pollCount, note),
2529
+ },
2530
+ ],
2531
+ details: buildCommitRunWatchDetails(repo, headSha, branch, runs, {
2532
+ state: "watching",
2533
+ pollCount,
2534
+ note,
2535
+ }),
2536
+ });
2537
+ await abortableSleep(intervalSeconds * 1000, signal);
2538
+ continue;
2539
+ }
2540
+
2541
+ settledSuccessSignature = undefined;
2542
+ await abortableSleep(intervalSeconds * 1000, signal);
2543
+ }
2544
+ });
2545
+ }
2546
+ }