@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,1785 @@
1
+ /**
2
+ * Patch application logic for the edit tool.
3
+ *
4
+ * Applies parsed diff hunks to file content using fuzzy matching
5
+ * for robust handling of whitespace and formatting differences.
6
+ */
7
+
8
+ import * as fs from "node:fs";
9
+ import * as path from "node:path";
10
+ import type { AgentToolResult } from "@f5xc-salesdemos/pi-agent-core";
11
+ import { StringEnum } from "@f5xc-salesdemos/pi-ai";
12
+ import { isEnoent } from "@f5xc-salesdemos/pi-utils";
13
+ import { type Static, Type } from "@sinclair/typebox";
14
+ import {
15
+ type FileDiagnosticsResult,
16
+ flushLspWritethroughBatch,
17
+ type WritethroughCallback,
18
+ type WritethroughDeferredHandle,
19
+ } from "../../lsp";
20
+ import type { ToolSession } from "../../tools";
21
+ import { assertEditableFile } from "../../tools/auto-generated-guard";
22
+ import {
23
+ invalidateFsScanAfterDelete,
24
+ invalidateFsScanAfterRename,
25
+ invalidateFsScanAfterWrite,
26
+ } from "../../tools/fs-cache-invalidation";
27
+ import { outputMeta } from "../../tools/output-meta";
28
+ import { resolveToCwd } from "../../tools/path-utils";
29
+ import { enforcePlanModeWrite, resolvePlanPath } from "../../tools/plan-mode-guard";
30
+ import {
31
+ ApplyPatchError,
32
+ type DiffHunk,
33
+ generateUnifiedDiffString,
34
+ normalizeCreateContent,
35
+ parseDiffHunks,
36
+ } from "../diff";
37
+ import {
38
+ adjustIndentation,
39
+ convertLeadingTabsToSpaces,
40
+ countLeadingWhitespace,
41
+ detectLineEnding,
42
+ getLeadingWhitespace,
43
+ normalizeToLF,
44
+ restoreLineEndings,
45
+ stripBom,
46
+ } from "../normalize";
47
+ import type { EditToolDetails, LspBatchRequest } from "../renderer";
48
+ import {
49
+ type ContextLineResult,
50
+ DEFAULT_FUZZY_THRESHOLD,
51
+ findClosestSequenceMatch,
52
+ findContextLine,
53
+ findMatch,
54
+ type SequenceSearchResult,
55
+ seekSequence,
56
+ } from "./replace";
57
+
58
+ export type Operation = "create" | "delete" | "update";
59
+
60
+ export interface PatchInput {
61
+ path: string;
62
+ op: Operation;
63
+ rename?: string;
64
+ diff?: string;
65
+ }
66
+
67
+ export interface FileSystem {
68
+ exists(path: string): Promise<boolean>;
69
+ read(path: string): Promise<string>;
70
+ readBinary?: (path: string) => Promise<Uint8Array>;
71
+ write(path: string, content: string): Promise<void>;
72
+ delete(path: string): Promise<void>;
73
+ mkdir(path: string): Promise<void>;
74
+ }
75
+
76
+ interface FileChange {
77
+ type: Operation;
78
+ path: string;
79
+ newPath?: string;
80
+ oldContent?: string;
81
+ newContent?: string;
82
+ }
83
+
84
+ export interface ApplyPatchResult {
85
+ change: FileChange;
86
+ warnings?: string[];
87
+ }
88
+
89
+ export interface ApplyPatchOptions {
90
+ cwd: string;
91
+ dryRun?: boolean;
92
+ fuzzyThreshold?: number;
93
+ allowFuzzy?: boolean;
94
+ fs?: FileSystem;
95
+ }
96
+
97
+ // ═══════════════════════════════════════════════════════════════════════════
98
+ // Default File System
99
+ // ═══════════════════════════════════════════════════════════════════════════
100
+
101
+ /** Default filesystem implementation using Bun APIs */
102
+ export const defaultFileSystem: FileSystem = {
103
+ async exists(path: string): Promise<boolean> {
104
+ return Bun.file(path).exists();
105
+ },
106
+ async read(path: string): Promise<string> {
107
+ return Bun.file(path).text();
108
+ },
109
+ async readBinary(path: string): Promise<Uint8Array> {
110
+ return fs.promises.readFile(path);
111
+ },
112
+ async write(path: string, content: string): Promise<void> {
113
+ await Bun.write(path, content);
114
+ },
115
+ async delete(path: string): Promise<void> {
116
+ await fs.promises.unlink(path);
117
+ },
118
+ async mkdir(path: string): Promise<void> {
119
+ await fs.promises.mkdir(path, { recursive: true });
120
+ },
121
+ };
122
+
123
+ // ═══════════════════════════════════════════════════════════════════════════
124
+ // Internal Types
125
+ // ═══════════════════════════════════════════════════════════════════════════
126
+
127
+ interface Replacement {
128
+ startIndex: number;
129
+ oldLen: number;
130
+ newLines: string[];
131
+ }
132
+
133
+ type HunkVariantKind = "trim-common" | "dedupe-shared" | "collapse-repeated" | "single-line";
134
+
135
+ interface HunkVariant {
136
+ oldLines: string[];
137
+ newLines: string[];
138
+ kind: HunkVariantKind;
139
+ }
140
+
141
+ function isBlankLine(line: string): boolean {
142
+ return line.trim().length === 0;
143
+ }
144
+
145
+ function areEqualLines(left: string[], right: string[]): boolean {
146
+ if (left.length !== right.length) return false;
147
+ for (let i = 0; i < left.length; i++) {
148
+ if (left[i] !== right[i]) return false;
149
+ }
150
+ return true;
151
+ }
152
+
153
+ function areEqualTrimmedLines(left: string[], right: string[]): boolean {
154
+ if (left.length !== right.length) return false;
155
+ for (let i = 0; i < left.length; i++) {
156
+ if (left[i].trim() !== right[i].trim()) return false;
157
+ }
158
+ return true;
159
+ }
160
+
161
+ function getIndentChar(lines: string[]): string {
162
+ for (const line of lines) {
163
+ const ws = getLeadingWhitespace(line);
164
+ if (ws.length > 0) return ws[0];
165
+ }
166
+ return " ";
167
+ }
168
+
169
+ function collectIndentDeltas(oldLines: string[], actualLines: string[]): number[] {
170
+ const deltas: number[] = [];
171
+ const lineCount = Math.min(oldLines.length, actualLines.length);
172
+ for (let i = 0; i < lineCount; i++) {
173
+ const oldLine = oldLines[i];
174
+ const actualLine = actualLines[i];
175
+ if (isBlankLine(oldLine) || isBlankLine(actualLine)) continue;
176
+ deltas.push(countLeadingWhitespace(actualLine) - countLeadingWhitespace(oldLine));
177
+ }
178
+ return deltas;
179
+ }
180
+
181
+ function applyIndentDelta(lines: string[], delta: number, indentChar: string): string[] {
182
+ return lines.map(line => {
183
+ if (isBlankLine(line)) return line;
184
+ if (delta > 0) return indentChar.repeat(delta) + line;
185
+ const toRemove = Math.min(-delta, countLeadingWhitespace(line));
186
+ return line.slice(toRemove);
187
+ });
188
+ }
189
+
190
+ function canConvertTabsToSpaces(oldLines: string[], actualLines: string[], spacesPerTab: number): boolean {
191
+ const lineCount = Math.min(oldLines.length, actualLines.length);
192
+ for (let i = 0; i < lineCount; i++) {
193
+ const oldLine = oldLines[i];
194
+ const actualLine = actualLines[i];
195
+ if (isBlankLine(oldLine) || isBlankLine(actualLine)) continue;
196
+ const oldIndent = getLeadingWhitespace(oldLine);
197
+ const actualIndent = getLeadingWhitespace(actualLine);
198
+ if (oldIndent.length === 0) continue;
199
+ if (actualIndent.length !== oldIndent.length * spacesPerTab) {
200
+ return false;
201
+ }
202
+ }
203
+ return true;
204
+ }
205
+
206
+ // ═══════════════════════════════════════════════════════════════════════════
207
+ // Replacement Computation
208
+ // ═══════════════════════════════════════════════════════════════════════════
209
+
210
+ /** Adjust indentation of newLines to match the delta between patternLines and actualLines */
211
+ function adjustLinesIndentation(patternLines: string[], actualLines: string[], newLines: string[]): string[] {
212
+ if (patternLines.length === 0 || actualLines.length === 0 || newLines.length === 0) {
213
+ return newLines;
214
+ }
215
+
216
+ // If pattern already matches actual exactly (including indentation), preserve agent's intended changes
217
+ if (areEqualLines(patternLines, actualLines)) {
218
+ return newLines;
219
+ }
220
+
221
+ // If the patch is purely an indentation change (same trimmed content), apply exactly as specified
222
+ if (areEqualTrimmedLines(patternLines, newLines)) {
223
+ return newLines;
224
+ }
225
+
226
+ // Detect indent character from actual content
227
+ const indentChar = getIndentChar(actualLines);
228
+
229
+ let patternTabOnly = true;
230
+ let actualSpaceOnly = true;
231
+ let patternSpaceOnly = true;
232
+ let actualTabOnly = true;
233
+ let patternMixed = false;
234
+ let actualMixed = false;
235
+
236
+ for (const line of patternLines) {
237
+ if (line.trim().length === 0) continue;
238
+ const ws = getLeadingWhitespace(line);
239
+ if (ws.includes(" ")) patternTabOnly = false;
240
+ if (ws.includes("\t")) patternSpaceOnly = false;
241
+ if (ws.includes(" ") && ws.includes("\t")) patternMixed = true;
242
+ }
243
+
244
+ for (const line of actualLines) {
245
+ if (line.trim().length === 0) continue;
246
+ const ws = getLeadingWhitespace(line);
247
+ if (ws.includes("\t")) actualSpaceOnly = false;
248
+ if (ws.includes(" ")) actualTabOnly = false;
249
+ if (ws.includes(" ") && ws.includes("\t")) actualMixed = true;
250
+ }
251
+
252
+ if (!patternMixed && !actualMixed && patternTabOnly && actualSpaceOnly) {
253
+ let ratio: number | undefined;
254
+ const lineCount = Math.min(patternLines.length, actualLines.length);
255
+ let consistent = true;
256
+ for (let i = 0; i < lineCount; i++) {
257
+ const patternLine = patternLines[i];
258
+ const actualLine = actualLines[i];
259
+ if (patternLine.trim().length === 0 || actualLine.trim().length === 0) continue;
260
+ const patternIndent = countLeadingWhitespace(patternLine);
261
+ const actualIndent = countLeadingWhitespace(actualLine);
262
+ if (patternIndent === 0) continue;
263
+ if (actualIndent % patternIndent !== 0) {
264
+ consistent = false;
265
+ break;
266
+ }
267
+ const nextRatio = actualIndent / patternIndent;
268
+ if (!ratio) {
269
+ ratio = nextRatio;
270
+ } else if (ratio !== nextRatio) {
271
+ consistent = false;
272
+ break;
273
+ }
274
+ }
275
+
276
+ if (consistent && ratio && canConvertTabsToSpaces(patternLines, actualLines, ratio)) {
277
+ return convertLeadingTabsToSpaces(newLines.join("\n"), ratio).split("\n");
278
+ }
279
+ }
280
+
281
+ // Reverse: pattern uses spaces, actual uses tabs — infer spaces = tabs * width + offset
282
+ // Collect (tabs, spaces) pairs from matched lines to solve for the model's tab rendering.
283
+ // With one data point: spaces = tabs * width (offset=0).
284
+ // With two+: solve ax + b via pairs with distinct tab counts.
285
+ if (!patternMixed && !actualMixed && patternSpaceOnly && actualTabOnly) {
286
+ const samples = new Map<number, number>(); // tabs -> spaces
287
+ const lineCount = Math.min(patternLines.length, actualLines.length);
288
+ let consistent = true;
289
+ for (let i = 0; i < lineCount; i++) {
290
+ const patternLine = patternLines[i];
291
+ const actualLine = actualLines[i];
292
+ if (patternLine.trim().length === 0 || actualLine.trim().length === 0) continue;
293
+ const spaces = countLeadingWhitespace(patternLine);
294
+ const tabs = countLeadingWhitespace(actualLine);
295
+ if (tabs === 0) continue;
296
+ const existing = samples.get(tabs);
297
+ if (existing !== undefined && existing !== spaces) {
298
+ consistent = false;
299
+ break;
300
+ }
301
+ samples.set(tabs, spaces);
302
+ }
303
+
304
+ if (consistent && samples.size > 0) {
305
+ let tabWidth: number | undefined;
306
+ let offset = 0;
307
+
308
+ if (samples.size === 1) {
309
+ // One level: assume offset=0, width = spaces / tabs
310
+ const [[tabs, spaces]] = samples;
311
+ if (spaces % tabs === 0) {
312
+ tabWidth = spaces / tabs;
313
+ }
314
+ } else {
315
+ // Two+ levels: solve via any two distinct pairs
316
+ // spaces = tabs * width + offset => width = (s2 - s1) / (t2 - t1)
317
+ const entries = [...samples.entries()];
318
+ const [t1, s1] = entries[0];
319
+ const [t2, s2] = entries[1];
320
+ if (t1 !== t2) {
321
+ const w = (s2 - s1) / (t2 - t1);
322
+ if (w > 0 && Number.isInteger(w)) {
323
+ const b = s1 - t1 * w;
324
+ // Validate all samples against this model
325
+ let valid = true;
326
+ for (const [t, s] of samples) {
327
+ if (t * w + b !== s) {
328
+ valid = false;
329
+ break;
330
+ }
331
+ }
332
+ if (valid) {
333
+ tabWidth = w;
334
+ offset = b;
335
+ }
336
+ }
337
+ }
338
+ }
339
+
340
+ if (tabWidth !== undefined && tabWidth > 0) {
341
+ const converted = newLines.map(line => {
342
+ if (line.trim().length === 0) return line;
343
+ const ws = countLeadingWhitespace(line);
344
+ if (ws === 0) return line;
345
+ // Reverse: tabs = (spaces - offset) / width
346
+ const adjusted = ws - offset;
347
+ if (adjusted >= 0 && adjusted % tabWidth! === 0) {
348
+ return "\t".repeat(adjusted / tabWidth!) + line.slice(ws);
349
+ }
350
+ // Partial tab — keep remainder as spaces
351
+ const tabCount = Math.floor(adjusted / tabWidth!);
352
+ const remainder = adjusted - tabCount * tabWidth!;
353
+ if (tabCount >= 0) {
354
+ return "\t".repeat(tabCount) + " ".repeat(remainder) + line.slice(ws);
355
+ }
356
+ return line;
357
+ });
358
+ return converted;
359
+ }
360
+ }
361
+ }
362
+
363
+ // Build a map from trimmed content to actual lines (by content, not position)
364
+ // This handles fuzzy matches where pattern and actual may not be positionally aligned
365
+ const contentToActualLines = new Map<string, string[]>();
366
+ for (const line of actualLines) {
367
+ const trimmed = line.trim();
368
+ if (trimmed.length === 0) continue;
369
+ const arr = contentToActualLines.get(trimmed);
370
+ if (arr) {
371
+ arr.push(line);
372
+ } else {
373
+ contentToActualLines.set(trimmed, [line]);
374
+ }
375
+ }
376
+
377
+ let patternMin = Infinity;
378
+ for (const line of patternLines) {
379
+ if (line.trim().length === 0) continue;
380
+ patternMin = Math.min(patternMin, countLeadingWhitespace(line));
381
+ }
382
+ if (patternMin === Infinity) {
383
+ patternMin = 0;
384
+ }
385
+
386
+ const deltas = collectIndentDeltas(patternLines, actualLines);
387
+ const delta = deltas.length > 0 && deltas.every(value => value === deltas[0]) ? deltas[0] : undefined;
388
+
389
+ // Track which actual lines we've used to handle duplicate content correctly
390
+ const usedActualLines = new Map<string, number>(); // trimmed content -> count used
391
+
392
+ return newLines.map(newLine => {
393
+ if (newLine.trim().length === 0) {
394
+ return newLine;
395
+ }
396
+
397
+ const trimmed = newLine.trim();
398
+ const matchingActualLines = contentToActualLines.get(trimmed);
399
+
400
+ // Check if this is a context line (same trimmed content exists in actual)
401
+ if (matchingActualLines && matchingActualLines.length > 0) {
402
+ if (matchingActualLines.length === 1) {
403
+ return matchingActualLines[0];
404
+ }
405
+ if (matchingActualLines.includes(newLine)) {
406
+ return newLine;
407
+ }
408
+ const usedCount = usedActualLines.get(trimmed) ?? 0;
409
+ if (usedCount < matchingActualLines.length) {
410
+ usedActualLines.set(trimmed, usedCount + 1);
411
+ // Use actual file content directly for context lines
412
+ return matchingActualLines[usedCount];
413
+ }
414
+ }
415
+
416
+ // This is a new/added line - apply consistent delta if safe
417
+ if (delta && delta !== 0) {
418
+ const newIndent = countLeadingWhitespace(newLine);
419
+ if (newIndent === patternMin) {
420
+ return applyIndentDelta([newLine], delta, indentChar)[0];
421
+ }
422
+ }
423
+ return newLine;
424
+ });
425
+ }
426
+
427
+ function trimCommonContext(oldLines: string[], newLines: string[]): HunkVariant | undefined {
428
+ let start = 0;
429
+ let endOld = oldLines.length;
430
+ let endNew = newLines.length;
431
+
432
+ while (start < endOld && start < endNew && oldLines[start] === newLines[start]) {
433
+ start++;
434
+ }
435
+
436
+ while (endOld > start && endNew > start && oldLines[endOld - 1] === newLines[endNew - 1]) {
437
+ endOld--;
438
+ endNew--;
439
+ }
440
+
441
+ if (start === 0 && endOld === oldLines.length && endNew === newLines.length) {
442
+ return undefined;
443
+ }
444
+
445
+ const trimmedOld = oldLines.slice(start, endOld);
446
+ const trimmedNew = newLines.slice(start, endNew);
447
+ if (trimmedOld.length === 0 && trimmedNew.length === 0) {
448
+ return undefined;
449
+ }
450
+ return { oldLines: trimmedOld, newLines: trimmedNew, kind: "trim-common" };
451
+ }
452
+
453
+ function collapseConsecutiveSharedLines(oldLines: string[], newLines: string[]): HunkVariant | undefined {
454
+ const shared = new Set(oldLines.filter(line => newLines.includes(line)));
455
+ const collapse = (lines: string[]): string[] => {
456
+ const out: string[] = [];
457
+ let i = 0;
458
+ while (i < lines.length) {
459
+ const line = lines[i];
460
+ out.push(line);
461
+ let j = i + 1;
462
+ while (j < lines.length && lines[j] === line && shared.has(line)) {
463
+ j++;
464
+ }
465
+ i = j;
466
+ }
467
+ return out;
468
+ };
469
+
470
+ const collapsedOld = collapse(oldLines);
471
+ const collapsedNew = collapse(newLines);
472
+ if (collapsedOld.length === oldLines.length && collapsedNew.length === newLines.length) {
473
+ return undefined;
474
+ }
475
+ return { oldLines: collapsedOld, newLines: collapsedNew, kind: "dedupe-shared" };
476
+ }
477
+
478
+ function collapseRepeatedBlocks(oldLines: string[], newLines: string[]): HunkVariant | undefined {
479
+ const shared = new Set(oldLines.filter(line => newLines.includes(line)));
480
+ const collapse = (lines: string[]): string[] => {
481
+ const output = [...lines];
482
+ let changed = false;
483
+ let i = 0;
484
+ while (i < output.length) {
485
+ let collapsed = false;
486
+ for (let size = Math.floor((output.length - i) / 2); size >= 2; size--) {
487
+ const first = output.slice(i, i + size);
488
+ const second = output.slice(i + size, i + size * 2);
489
+ if (first.length !== second.length || first.length === 0) continue;
490
+ if (!first.every(line => shared.has(line))) continue;
491
+ let same = true;
492
+ for (let idx = 0; idx < size; idx++) {
493
+ if (first[idx] !== second[idx]) {
494
+ same = false;
495
+ break;
496
+ }
497
+ }
498
+ if (same) {
499
+ output.splice(i + size, size);
500
+ changed = true;
501
+ collapsed = true;
502
+ break;
503
+ }
504
+ }
505
+ if (!collapsed) {
506
+ i++;
507
+ }
508
+ }
509
+ return changed ? output : lines;
510
+ };
511
+
512
+ const collapsedOld = collapse(oldLines);
513
+ const collapsedNew = collapse(newLines);
514
+ if (collapsedOld.length === oldLines.length && collapsedNew.length === newLines.length) {
515
+ return undefined;
516
+ }
517
+ return { oldLines: collapsedOld, newLines: collapsedNew, kind: "collapse-repeated" };
518
+ }
519
+
520
+ function reduceToSingleLineChange(oldLines: string[], newLines: string[]): HunkVariant | undefined {
521
+ if (oldLines.length !== newLines.length || oldLines.length === 0) return undefined;
522
+ let changedIndex: number | undefined;
523
+ for (let i = 0; i < oldLines.length; i++) {
524
+ if (oldLines[i] !== newLines[i]) {
525
+ if (changedIndex !== undefined) return undefined;
526
+ changedIndex = i;
527
+ }
528
+ }
529
+ if (changedIndex === undefined) return undefined;
530
+ return { oldLines: [oldLines[changedIndex]], newLines: [newLines[changedIndex]], kind: "single-line" };
531
+ }
532
+
533
+ function buildFallbackVariants(hunk: DiffHunk): HunkVariant[] {
534
+ const variants: HunkVariant[] = [];
535
+ const base: HunkVariant = { oldLines: hunk.oldLines, newLines: hunk.newLines, kind: "trim-common" };
536
+
537
+ const trimmed = trimCommonContext(base.oldLines, base.newLines);
538
+ if (trimmed) variants.push(trimmed);
539
+
540
+ const deduped = collapseConsecutiveSharedLines(
541
+ trimmed?.oldLines ?? base.oldLines,
542
+ trimmed?.newLines ?? base.newLines,
543
+ );
544
+ if (deduped) variants.push(deduped);
545
+
546
+ const collapsed = collapseRepeatedBlocks(
547
+ deduped?.oldLines ?? trimmed?.oldLines ?? base.oldLines,
548
+ deduped?.newLines ?? trimmed?.newLines ?? base.newLines,
549
+ );
550
+ if (collapsed) variants.push(collapsed);
551
+
552
+ const singleLine = reduceToSingleLineChange(trimmed?.oldLines ?? base.oldLines, trimmed?.newLines ?? base.newLines);
553
+ if (singleLine) variants.push(singleLine);
554
+
555
+ const seen = new Set<string>();
556
+ return variants.filter(variant => {
557
+ if (variant.oldLines.length === 0 && variant.newLines.length === 0) return false;
558
+ const key = `${variant.oldLines.join("\n")}||${variant.newLines.join("\n")}`;
559
+ if (seen.has(key)) return false;
560
+ seen.add(key);
561
+ return true;
562
+ });
563
+ }
564
+
565
+ function filterFallbackVariants(variants: HunkVariant[], allowAggressive: boolean): HunkVariant[] {
566
+ if (allowAggressive) return variants;
567
+ return variants.filter(variant => variant.kind !== "collapse-repeated" && variant.kind !== "single-line");
568
+ }
569
+
570
+ function findContextRelativeMatch(
571
+ lines: string[],
572
+ patternLine: string,
573
+ contextIndex: number,
574
+ preferSecondForwardMatch: boolean,
575
+ ): number | undefined {
576
+ const trimmed = patternLine.trim();
577
+ const forwardMatches: number[] = [];
578
+ for (let i = contextIndex + 1; i < lines.length; i++) {
579
+ if (lines[i].trim() === trimmed) {
580
+ forwardMatches.push(i);
581
+ }
582
+ }
583
+ if (forwardMatches.length > 0) {
584
+ if (preferSecondForwardMatch && forwardMatches.length > 1) {
585
+ return forwardMatches[1];
586
+ }
587
+ return forwardMatches[0];
588
+ }
589
+ for (let i = contextIndex - 1; i >= 0; i--) {
590
+ if (lines[i].trim() === trimmed) {
591
+ return i;
592
+ }
593
+ }
594
+ return undefined;
595
+ }
596
+
597
+ const AMBIGUITY_HINT_WINDOW = 200;
598
+ const MATCH_PREVIEW_CONTEXT = 2;
599
+ const MATCH_PREVIEW_MAX_LEN = 80;
600
+
601
+ function formatSequenceMatchPreview(lines: string[], startIdx: number): string {
602
+ const start = Math.max(0, startIdx - MATCH_PREVIEW_CONTEXT);
603
+ const end = Math.min(lines.length, startIdx + MATCH_PREVIEW_CONTEXT + 1);
604
+ const previewLines = lines.slice(start, end);
605
+ return previewLines
606
+ .map((line, i) => {
607
+ const num = start + i + 1;
608
+ const truncated = line.length > MATCH_PREVIEW_MAX_LEN ? `${line.slice(0, MATCH_PREVIEW_MAX_LEN - 1)}…` : line;
609
+ return ` ${num} | ${truncated}`;
610
+ })
611
+ .join("\n");
612
+ }
613
+
614
+ function formatSequenceMatchPreviews(
615
+ lines: string[],
616
+ matchIndices: number[] | undefined,
617
+ matchCount: number | undefined,
618
+ ): string | undefined {
619
+ if (!matchIndices || matchIndices.length === 0) return undefined;
620
+ const previews = matchIndices.map(index => formatSequenceMatchPreview(lines, index));
621
+ const moreMsg =
622
+ matchCount && matchCount > matchIndices.length ? ` (showing first ${matchIndices.length} of ${matchCount})` : "";
623
+ return `${previews.join("\n\n")}${moreMsg}`;
624
+ }
625
+
626
+ function chooseHintedMatch(
627
+ matchIndices: number[] | undefined,
628
+ hintIndex: number | undefined,
629
+ window: number,
630
+ ): number | undefined {
631
+ if (!matchIndices || matchIndices.length === 0 || hintIndex === undefined) return undefined;
632
+ const candidates = matchIndices.filter(index => Math.abs(index - hintIndex) <= window);
633
+ if (candidates.length === 1) return candidates[0];
634
+ return undefined;
635
+ }
636
+
637
+ /** Get hint index from hunk's line number */
638
+ function getHunkHintIndex(hunk: DiffHunk, currentIndex: number): number | undefined {
639
+ if (hunk.oldStartLine === undefined) return undefined;
640
+ const hintIndex = Math.max(0, hunk.oldStartLine - 1);
641
+ return hintIndex >= currentIndex ? hintIndex : undefined;
642
+ }
643
+
644
+ /**
645
+ * Find hierarchical context in file lines.
646
+ *
647
+ * Handles three formats:
648
+ * 1. Simple context: "function foo" - find this line
649
+ * 2. Hierarchical (newline): "class Foo\nmethod" - find class, then method after it
650
+ * 3. Hierarchical (space): "class Foo method" - try as literal first, then split and search
651
+ *
652
+ * @returns The result from finding the final (innermost) context, or undefined if not found
653
+ */
654
+ function findHierarchicalContext(
655
+ lines: string[],
656
+ context: string,
657
+ startFrom: number,
658
+ lineHint: number | undefined,
659
+ allowFuzzy: boolean,
660
+ ): ContextLineResult {
661
+ // Check for newline-separated hierarchical contexts (from nested @@ anchors)
662
+ if (context.includes("\n")) {
663
+ const parts = context
664
+ .split("\n")
665
+ .map(p => p.trim())
666
+ .filter(p => p.length > 0);
667
+ let currentStart = startFrom;
668
+
669
+ for (let i = 0; i < parts.length; i++) {
670
+ const part = parts[i];
671
+ const isLast = i === parts.length - 1;
672
+
673
+ const result = findContextLine(lines, part, currentStart, { allowFuzzy });
674
+
675
+ if (result.matchCount !== undefined && result.matchCount > 1) {
676
+ if (isLast && lineHint !== undefined) {
677
+ const hintStart = Math.max(0, lineHint - 1);
678
+ if (hintStart >= currentStart) {
679
+ const hintedResult = findContextLine(lines, part, hintStart, { allowFuzzy });
680
+ if (hintedResult.index !== undefined) {
681
+ return { ...hintedResult, matchCount: 1, matchIndices: [hintedResult.index] };
682
+ }
683
+ }
684
+ }
685
+ return {
686
+ index: undefined,
687
+ confidence: result.confidence,
688
+ matchCount: result.matchCount,
689
+ matchIndices: result.matchIndices,
690
+ strategy: result.strategy,
691
+ };
692
+ }
693
+
694
+ if (result.index === undefined) {
695
+ if (isLast && lineHint !== undefined) {
696
+ const hintStart = Math.max(0, lineHint - 1);
697
+ if (hintStart >= currentStart) {
698
+ const hintedResult = findContextLine(lines, part, hintStart, { allowFuzzy });
699
+ if (hintedResult.index !== undefined) {
700
+ return { ...hintedResult, matchCount: 1, matchIndices: [hintedResult.index] };
701
+ }
702
+ }
703
+ }
704
+ return { index: undefined, confidence: result.confidence };
705
+ }
706
+
707
+ if (isLast) {
708
+ return result;
709
+ }
710
+ currentStart = result.index + 1;
711
+ }
712
+ return { index: undefined, confidence: 0 };
713
+ }
714
+
715
+ // Try literal context first
716
+ const spaceParts = context.split(/\s+/).filter(p => p.length > 0);
717
+ const hasSignatureChars = /[(){}[\]]/.test(context);
718
+ if (!hasSignatureChars && spaceParts.length > 2) {
719
+ const outer = spaceParts.slice(0, -1).join(" ");
720
+ const inner = spaceParts[spaceParts.length - 1];
721
+ const outerResult = findContextLine(lines, outer, startFrom, { allowFuzzy });
722
+ if (outerResult.matchCount !== undefined && outerResult.matchCount > 1) {
723
+ return {
724
+ index: undefined,
725
+ confidence: outerResult.confidence,
726
+ matchCount: outerResult.matchCount,
727
+ matchIndices: outerResult.matchIndices,
728
+ strategy: outerResult.strategy,
729
+ };
730
+ }
731
+ if (outerResult.index !== undefined) {
732
+ const innerResult = findContextLine(lines, inner, outerResult.index + 1, { allowFuzzy });
733
+ if (innerResult.index !== undefined) {
734
+ return innerResult.matchCount && innerResult.matchCount > 1
735
+ ? { ...innerResult, matchCount: 1, matchIndices: [innerResult.index] }
736
+ : innerResult;
737
+ }
738
+ if (innerResult.matchCount !== undefined && innerResult.matchCount > 1) {
739
+ return {
740
+ ...innerResult,
741
+ matchCount: 1,
742
+ matchIndices: innerResult.index !== undefined ? [innerResult.index] : innerResult.matchIndices,
743
+ };
744
+ }
745
+ }
746
+ }
747
+
748
+ const result = findContextLine(lines, context, startFrom, { allowFuzzy });
749
+
750
+ // If line hint exists and result is ambiguous or missing, try from hint
751
+ if ((result.index === undefined || (result.matchCount ?? 0) > 1) && lineHint !== undefined) {
752
+ const hintStart = Math.max(0, lineHint - 1);
753
+ const hintedResult = findContextLine(lines, context, hintStart, { allowFuzzy });
754
+ if (hintedResult.index !== undefined) {
755
+ return { ...hintedResult, matchCount: 1, matchIndices: [hintedResult.index] };
756
+ }
757
+ }
758
+
759
+ // If found uniquely, return it
760
+ if (result.index !== undefined && (result.matchCount ?? 0) <= 1) {
761
+ return result;
762
+ }
763
+ if (result.matchCount !== undefined && result.matchCount > 1) {
764
+ return result;
765
+ }
766
+
767
+ // Try from beginning if not found from current position
768
+ if (result.index === undefined && startFrom !== 0) {
769
+ const fromStartResult = findContextLine(lines, context, 0, { allowFuzzy });
770
+ if (fromStartResult.index !== undefined && (fromStartResult.matchCount ?? 0) <= 1) {
771
+ return fromStartResult;
772
+ }
773
+ if (fromStartResult.matchCount !== undefined && fromStartResult.matchCount > 1) {
774
+ return fromStartResult;
775
+ }
776
+ }
777
+
778
+ // Fallback: try space-separated hierarchical matching
779
+ // e.g., "class PatchTool constructor" -> find "class PatchTool", then "constructor" after it
780
+ if (!hasSignatureChars && spaceParts.length > 1) {
781
+ const outer = spaceParts.slice(0, -1).join(" ");
782
+ const inner = spaceParts[spaceParts.length - 1];
783
+ const outerResult = findContextLine(lines, outer, startFrom, { allowFuzzy });
784
+
785
+ if (outerResult.matchCount !== undefined && outerResult.matchCount > 1) {
786
+ return {
787
+ index: undefined,
788
+ confidence: outerResult.confidence,
789
+ matchCount: outerResult.matchCount,
790
+ matchIndices: outerResult.matchIndices,
791
+ strategy: outerResult.strategy,
792
+ };
793
+ }
794
+
795
+ if (outerResult.index === undefined) {
796
+ return { index: undefined, confidence: outerResult.confidence };
797
+ }
798
+
799
+ const innerResult = findContextLine(lines, inner, outerResult.index + 1, { allowFuzzy });
800
+ if (innerResult.index !== undefined) {
801
+ return innerResult.matchCount && innerResult.matchCount > 1
802
+ ? { ...innerResult, matchCount: 1, matchIndices: [innerResult.index] }
803
+ : innerResult;
804
+ }
805
+ if (innerResult.matchCount !== undefined && innerResult.matchCount > 1) {
806
+ return {
807
+ ...innerResult,
808
+ matchCount: 1,
809
+ matchIndices: innerResult.index !== undefined ? [innerResult.index] : innerResult.matchIndices,
810
+ };
811
+ }
812
+ }
813
+
814
+ return result;
815
+ }
816
+
817
+ /** Find sequence with optional hint position, returning full search result */
818
+ function findSequenceWithHint(
819
+ lines: string[],
820
+ pattern: string[],
821
+ currentIndex: number,
822
+ hintIndex: number | undefined,
823
+ eof: boolean,
824
+ allowFuzzy: boolean,
825
+ ): SequenceSearchResult {
826
+ // Prefer content-based search starting from currentIndex
827
+ const primaryResult = seekSequence(lines, pattern, currentIndex, eof, { allowFuzzy });
828
+ if (
829
+ primaryResult.matchCount &&
830
+ primaryResult.matchCount > 1 &&
831
+ hintIndex !== undefined &&
832
+ hintIndex !== currentIndex
833
+ ) {
834
+ const hintedResult = seekSequence(lines, pattern, hintIndex, eof, { allowFuzzy });
835
+ if (hintedResult.index !== undefined && (hintedResult.matchCount ?? 1) <= 1) {
836
+ return hintedResult;
837
+ }
838
+ if (hintedResult.matchCount && hintedResult.matchCount > 1) {
839
+ return hintedResult;
840
+ }
841
+ }
842
+ if (primaryResult.index !== undefined || (primaryResult.matchCount && primaryResult.matchCount > 1)) {
843
+ return primaryResult;
844
+ }
845
+
846
+ // Use line hint as a secondary bias only if needed
847
+ if (hintIndex !== undefined && hintIndex !== currentIndex) {
848
+ const hintedResult = seekSequence(lines, pattern, hintIndex, eof, { allowFuzzy });
849
+ if (hintedResult.index !== undefined || (hintedResult.matchCount && hintedResult.matchCount > 1)) {
850
+ return hintedResult;
851
+ }
852
+ }
853
+
854
+ // Last resort: search from beginning (handles out-of-order hunks)
855
+ if (currentIndex !== 0) {
856
+ const fromStartResult = seekSequence(lines, pattern, 0, eof, { allowFuzzy });
857
+ if (fromStartResult.index !== undefined || (fromStartResult.matchCount && fromStartResult.matchCount > 1)) {
858
+ return fromStartResult;
859
+ }
860
+ }
861
+
862
+ return primaryResult;
863
+ }
864
+
865
+ function attemptSequenceFallback(
866
+ lines: string[],
867
+ hunk: DiffHunk,
868
+ currentIndex: number,
869
+ lineHint: number | undefined,
870
+ allowFuzzy: boolean,
871
+ allowAggressiveFallbacks: boolean,
872
+ ): number | undefined {
873
+ if (hunk.oldLines.length === 0) return undefined;
874
+ const matchHint = getHunkHintIndex(hunk, currentIndex);
875
+ const fallbackResult = findSequenceWithHint(
876
+ lines,
877
+ hunk.oldLines,
878
+ currentIndex,
879
+ matchHint ?? lineHint,
880
+ false,
881
+ allowFuzzy,
882
+ );
883
+ if (fallbackResult.index !== undefined && (fallbackResult.matchCount ?? 1) <= 1) {
884
+ const nextIndex = fallbackResult.index + 1;
885
+ if (nextIndex <= lines.length - hunk.oldLines.length) {
886
+ const secondMatch = seekSequence(lines, hunk.oldLines, nextIndex, false, { allowFuzzy });
887
+ if (secondMatch.index !== undefined) {
888
+ return undefined;
889
+ }
890
+ }
891
+ return fallbackResult.index;
892
+ }
893
+
894
+ for (const variant of filterFallbackVariants(buildFallbackVariants(hunk), allowAggressiveFallbacks)) {
895
+ if (variant.oldLines.length === 0) continue;
896
+ const variantResult = findSequenceWithHint(
897
+ lines,
898
+ variant.oldLines,
899
+ currentIndex,
900
+ matchHint ?? lineHint,
901
+ false,
902
+ allowFuzzy,
903
+ );
904
+ if (variantResult.index !== undefined && (variantResult.matchCount ?? 1) <= 1) {
905
+ return variantResult.index;
906
+ }
907
+ }
908
+ return undefined;
909
+ }
910
+
911
+ /**
912
+ * Apply a hunk using character-based fuzzy matching.
913
+ * Used when the hunk contains only -/+ lines without context.
914
+ */
915
+ function applyCharacterMatch(
916
+ originalContent: string,
917
+ path: string,
918
+ hunk: DiffHunk,
919
+ fuzzyThreshold: number,
920
+ allowFuzzy: boolean,
921
+ ): { content: string; warnings: string[] } {
922
+ const oldText = hunk.oldLines.join("\n");
923
+ const newText = hunk.newLines.join("\n");
924
+
925
+ const normalizedContent = normalizeToLF(originalContent);
926
+ const normalizedOldText = normalizeToLF(oldText);
927
+
928
+ let matchOutcome = findMatch(normalizedContent, normalizedOldText, {
929
+ allowFuzzy,
930
+ threshold: fuzzyThreshold,
931
+ });
932
+ if (!matchOutcome.match && allowFuzzy) {
933
+ const relaxedThreshold = Math.min(fuzzyThreshold, 0.92);
934
+ if (relaxedThreshold < fuzzyThreshold) {
935
+ const relaxedOutcome = findMatch(normalizedContent, normalizedOldText, {
936
+ allowFuzzy,
937
+ threshold: relaxedThreshold,
938
+ });
939
+ if (relaxedOutcome.match) {
940
+ matchOutcome = relaxedOutcome;
941
+ }
942
+ }
943
+ }
944
+
945
+ // Check for multiple exact occurrences
946
+ if (matchOutcome.occurrences && matchOutcome.occurrences > 1) {
947
+ const previews = matchOutcome.occurrencePreviews?.join("\n\n") ?? "";
948
+ const moreMsg = matchOutcome.occurrences > 5 ? ` (showing first 5 of ${matchOutcome.occurrences})` : "";
949
+ throw new ApplyPatchError(
950
+ `Found ${matchOutcome.occurrences} occurrences in ${path}${moreMsg}:\n\n${previews}\n\n` +
951
+ `Add more context lines to disambiguate.`,
952
+ );
953
+ }
954
+
955
+ if (matchOutcome.fuzzyMatches && matchOutcome.fuzzyMatches > 1) {
956
+ throw new ApplyPatchError(
957
+ `Found ${matchOutcome.fuzzyMatches} high-confidence matches in ${path}. ` +
958
+ `The text must be unique. Please provide more context to make it unique.`,
959
+ );
960
+ }
961
+
962
+ if (!matchOutcome.match) {
963
+ const closest = matchOutcome.closest;
964
+ if (closest) {
965
+ const similarity = Math.round(closest.confidence * 100);
966
+ throw new ApplyPatchError(
967
+ `Could not find a close enough match in ${path}. ` +
968
+ `Closest match (${similarity}% similar) at line ${closest.startLine}.`,
969
+ );
970
+ }
971
+ throw new ApplyPatchError(`Failed to find expected lines in ${path}:\n${oldText}`);
972
+ }
973
+
974
+ // Adjust indentation to match what was actually found
975
+ const adjustedNewText = adjustIndentation(normalizedOldText, matchOutcome.match.actualText, newText);
976
+
977
+ const warnings: string[] = [];
978
+ if (matchOutcome.dominantFuzzy && matchOutcome.match) {
979
+ const similarity = Math.round(matchOutcome.match.confidence * 100);
980
+ warnings.push(
981
+ `Dominant fuzzy match selected in ${path} near line ${matchOutcome.match.startLine} (${similarity}% similar).`,
982
+ );
983
+ }
984
+
985
+ // Apply the replacement
986
+ const before = normalizedContent.substring(0, matchOutcome.match.startIndex);
987
+ const after = normalizedContent.substring(matchOutcome.match.startIndex + matchOutcome.match.actualText.length);
988
+ return { content: before + adjustedNewText + after, warnings };
989
+ }
990
+
991
+ function applyTrailingNewlinePolicy(content: string, hadFinalNewline: boolean): string {
992
+ if (hadFinalNewline) {
993
+ return content.endsWith("\n") ? content : `${content}\n`;
994
+ }
995
+ return content.replace(/\n+$/u, "");
996
+ }
997
+
998
+ async function readExistingPatchFile(fileSystem: FileSystem, absolutePath: string, path: string): Promise<string> {
999
+ try {
1000
+ return await fileSystem.read(absolutePath);
1001
+ } catch (error) {
1002
+ if (isEnoent(error)) {
1003
+ throw new ApplyPatchError(`File not found: ${path}`);
1004
+ }
1005
+ throw error;
1006
+ }
1007
+ }
1008
+
1009
+ /**
1010
+ * Compute replacements needed to transform originalLines using the diff hunks.
1011
+ */
1012
+ function computeReplacements(
1013
+ originalLines: string[],
1014
+ path: string,
1015
+ hunks: DiffHunk[],
1016
+ allowFuzzy: boolean,
1017
+ ): { replacements: Replacement[]; warnings: string[] } {
1018
+ const replacements: Replacement[] = [];
1019
+ const warnings: string[] = [];
1020
+ let lineIndex = 0;
1021
+
1022
+ for (const hunk of hunks) {
1023
+ let contextIndex: number | undefined;
1024
+ if (hunk.oldStartLine !== undefined && hunk.oldStartLine < 1) {
1025
+ throw new ApplyPatchError(
1026
+ `Line hint ${hunk.oldStartLine} is out of range for ${path} (line numbers start at 1)`,
1027
+ );
1028
+ }
1029
+ if (hunk.newStartLine !== undefined && hunk.newStartLine < 1) {
1030
+ throw new ApplyPatchError(
1031
+ `Line hint ${hunk.newStartLine} is out of range for ${path} (line numbers start at 1)`,
1032
+ );
1033
+ }
1034
+ const lineHint = hunk.oldStartLine;
1035
+ const allowAggressiveFallbacks = hunk.changeContext !== undefined || lineHint !== undefined || hunk.isEndOfFile;
1036
+ const fallbackVariants = filterFallbackVariants(buildFallbackVariants(hunk), allowAggressiveFallbacks);
1037
+ if (lineHint !== undefined && hunk.changeContext === undefined && !hunk.hasContextLines) {
1038
+ lineIndex = Math.max(0, Math.min(lineHint - 1, originalLines.length - 1));
1039
+ }
1040
+
1041
+ // If hunk has a changeContext, find it and adjust lineIndex
1042
+ if (hunk.changeContext !== undefined) {
1043
+ // Use hierarchical context matching for nested @@ anchors and space-separated contexts
1044
+ const result = findHierarchicalContext(originalLines, hunk.changeContext, lineIndex, lineHint, allowFuzzy);
1045
+ const idx = result.index;
1046
+ contextIndex = idx;
1047
+
1048
+ if (idx === undefined || (result.matchCount !== undefined && result.matchCount > 1)) {
1049
+ const fallback = attemptSequenceFallback(
1050
+ originalLines,
1051
+ hunk,
1052
+ lineIndex,
1053
+ lineHint,
1054
+ allowFuzzy,
1055
+ allowAggressiveFallbacks,
1056
+ );
1057
+ if (fallback !== undefined) {
1058
+ lineIndex = fallback;
1059
+ } else if (result.matchCount !== undefined && result.matchCount > 1) {
1060
+ const displayContext = hunk.changeContext.includes("\n")
1061
+ ? hunk.changeContext.split("\n").pop()
1062
+ : hunk.changeContext;
1063
+ const previews = formatSequenceMatchPreviews(originalLines, result.matchIndices, result.matchCount);
1064
+ const strategyHint = result.strategy ? ` Matching strategy: ${result.strategy}.` : "";
1065
+ const previewText = previews ? `\n\n${previews}` : "";
1066
+ throw new ApplyPatchError(
1067
+ `Found ${result.matchCount} matches for context '${displayContext}' in ${path}.${strategyHint}` +
1068
+ `${previewText}\n\nAdd more surrounding context or additional @@ anchors to make it unique.`,
1069
+ );
1070
+ } else {
1071
+ const displayContext = hunk.changeContext.includes("\n")
1072
+ ? hunk.changeContext.split("\n").join(" > ")
1073
+ : hunk.changeContext;
1074
+ throw new ApplyPatchError(`Failed to find context '${displayContext}' in ${path}`);
1075
+ }
1076
+ } else {
1077
+ // If oldLines[0] matches the final context, start search at idx (not idx+1)
1078
+ // This handles the common case where @@ scope and first context line are identical
1079
+ const firstOldLine = hunk.oldLines[0];
1080
+ const finalContext = hunk.changeContext.includes("\n")
1081
+ ? hunk.changeContext.split("\n").pop()?.trim()
1082
+ : hunk.changeContext.trim();
1083
+ const isHierarchicalContext =
1084
+ hunk.changeContext.includes("\n") || hunk.changeContext.trim().split(/\s+/).length > 2;
1085
+ if (firstOldLine !== undefined && (firstOldLine.trim() === finalContext || isHierarchicalContext)) {
1086
+ lineIndex = idx;
1087
+ } else {
1088
+ lineIndex = idx + 1;
1089
+ }
1090
+ }
1091
+ }
1092
+
1093
+ if (hunk.oldLines.length === 0) {
1094
+ // Pure addition - prefer changeContext position, then line hint, then end of file
1095
+ let insertionIdx: number;
1096
+ if (hunk.changeContext !== undefined) {
1097
+ // changeContext was processed above; lineIndex is set to the context line or after it
1098
+ insertionIdx = lineIndex;
1099
+ } else {
1100
+ const lineHintForInsertion = hunk.oldStartLine ?? hunk.newStartLine;
1101
+ if (lineHintForInsertion !== undefined) {
1102
+ // Reject if line hint is out of range for insertion
1103
+ // Valid insertion points are 1 to (file length + 1) for 1-indexed hints
1104
+ if (lineHintForInsertion < 1) {
1105
+ throw new ApplyPatchError(
1106
+ `Line hint ${lineHintForInsertion} is out of range for insertion in ${path} ` +
1107
+ `(line numbers start at 1)`,
1108
+ );
1109
+ }
1110
+ if (lineHintForInsertion > originalLines.length + 1) {
1111
+ throw new ApplyPatchError(
1112
+ `Line hint ${lineHintForInsertion} is out of range for insertion in ${path} ` +
1113
+ `(file has ${originalLines.length} lines)`,
1114
+ );
1115
+ }
1116
+ insertionIdx = Math.max(0, lineHintForInsertion - 1);
1117
+ } else {
1118
+ insertionIdx =
1119
+ originalLines.length > 0 && originalLines[originalLines.length - 1] === ""
1120
+ ? originalLines.length - 1
1121
+ : originalLines.length;
1122
+ }
1123
+ }
1124
+
1125
+ replacements.push({ startIndex: insertionIdx, oldLen: 0, newLines: [...hunk.newLines] });
1126
+ continue;
1127
+ }
1128
+
1129
+ // Try to find the old lines in the file
1130
+ let pattern = [...hunk.oldLines];
1131
+ const matchHint = getHunkHintIndex(hunk, lineIndex);
1132
+ let searchResult = findSequenceWithHint(
1133
+ originalLines,
1134
+ pattern,
1135
+ lineIndex,
1136
+ matchHint,
1137
+ hunk.isEndOfFile,
1138
+ allowFuzzy,
1139
+ );
1140
+ let newSlice = [...hunk.newLines];
1141
+
1142
+ // Retry without trailing empty line if present
1143
+ if (searchResult.index === undefined && pattern.length > 0 && pattern[pattern.length - 1] === "") {
1144
+ pattern = pattern.slice(0, -1);
1145
+ if (newSlice.length > 0 && newSlice[newSlice.length - 1] === "") {
1146
+ newSlice = newSlice.slice(0, -1);
1147
+ }
1148
+ searchResult = findSequenceWithHint(
1149
+ originalLines,
1150
+ pattern,
1151
+ lineIndex,
1152
+ matchHint,
1153
+ hunk.isEndOfFile,
1154
+ allowFuzzy,
1155
+ );
1156
+ }
1157
+
1158
+ if (searchResult.index === undefined || (searchResult.matchCount ?? 0) > 1) {
1159
+ for (const variant of fallbackVariants) {
1160
+ if (variant.oldLines.length === 0) continue;
1161
+ const variantResult = findSequenceWithHint(
1162
+ originalLines,
1163
+ variant.oldLines,
1164
+ lineIndex,
1165
+ matchHint,
1166
+ hunk.isEndOfFile,
1167
+ allowFuzzy,
1168
+ );
1169
+ if (variantResult.index !== undefined && (variantResult.matchCount ?? 1) <= 1) {
1170
+ pattern = variant.oldLines;
1171
+ newSlice = variant.newLines;
1172
+ searchResult = variantResult;
1173
+ break;
1174
+ }
1175
+ }
1176
+ }
1177
+
1178
+ if (searchResult.index === undefined && contextIndex !== undefined) {
1179
+ for (const variant of fallbackVariants) {
1180
+ if (variant.oldLines.length !== 1 || variant.newLines.length !== 1) continue;
1181
+ const removedLine = variant.oldLines[0];
1182
+ const hasSharedDuplicate = hunk.newLines.some(line => line.trim() === removedLine.trim());
1183
+ const adjacentIndex = findContextRelativeMatch(
1184
+ originalLines,
1185
+ removedLine,
1186
+ contextIndex,
1187
+ hasSharedDuplicate,
1188
+ );
1189
+ if (adjacentIndex !== undefined) {
1190
+ pattern = variant.oldLines;
1191
+ newSlice = variant.newLines;
1192
+ searchResult = { index: adjacentIndex, confidence: 0.95 };
1193
+ break;
1194
+ }
1195
+ }
1196
+ }
1197
+
1198
+ if (searchResult.index !== undefined && contextIndex !== undefined && pattern.length === 1) {
1199
+ const trimmed = pattern[0].trim();
1200
+ let occurrenceCount = 0;
1201
+ for (const line of originalLines) {
1202
+ if (line.trim() === trimmed) occurrenceCount++;
1203
+ }
1204
+ if (occurrenceCount > 1) {
1205
+ const hasSharedDuplicate = hunk.newLines.some(line => line.trim() === trimmed);
1206
+ const contextMatch = findContextRelativeMatch(originalLines, pattern[0], contextIndex, hasSharedDuplicate);
1207
+ if (contextMatch !== undefined) {
1208
+ searchResult = { index: contextMatch, confidence: searchResult.confidence ?? 0.95 };
1209
+ }
1210
+ }
1211
+ }
1212
+
1213
+ if ((searchResult.matchCount ?? 0) > 1) {
1214
+ const hintIndex = matchHint ?? (lineHint ? lineHint - 1 : undefined);
1215
+ const hinted = chooseHintedMatch(searchResult.matchIndices, hintIndex, AMBIGUITY_HINT_WINDOW);
1216
+ if (hinted !== undefined) {
1217
+ searchResult = { ...searchResult, index: hinted, matchCount: 1 };
1218
+ }
1219
+ }
1220
+
1221
+ if (searchResult.index === undefined) {
1222
+ if (searchResult.matchCount !== undefined && searchResult.matchCount > 1) {
1223
+ const previews = formatSequenceMatchPreviews(
1224
+ originalLines,
1225
+ searchResult.matchIndices,
1226
+ searchResult.matchCount,
1227
+ );
1228
+ const strategyHint = searchResult.strategy ? ` Matching strategy: ${searchResult.strategy}.` : "";
1229
+ const previewText = previews ? `\n\n${previews}` : "";
1230
+ throw new ApplyPatchError(
1231
+ `Found ${searchResult.matchCount} matches for the text in ${path}.${strategyHint}` +
1232
+ `${previewText}\n\nAdd more surrounding context or additional @@ anchors to make it unique.`,
1233
+ );
1234
+ }
1235
+ const closest = findClosestSequenceMatch(originalLines, pattern, {
1236
+ start: lineIndex,
1237
+ eof: hunk.isEndOfFile,
1238
+ });
1239
+ if (closest.index !== undefined && closest.confidence > 0) {
1240
+ const similarity = Math.round(closest.confidence * 100);
1241
+ const preview = formatSequenceMatchPreview(originalLines, closest.index);
1242
+ throw new ApplyPatchError(
1243
+ `Failed to find expected lines in ${path}:\n${hunk.oldLines.join("\n")}\n\n` +
1244
+ `Closest match (${similarity}% similar) near line ${closest.index + 1}:\n${preview}`,
1245
+ );
1246
+ }
1247
+ throw new ApplyPatchError(`Failed to find expected lines in ${path}:\n${hunk.oldLines.join("\n")}`);
1248
+ }
1249
+
1250
+ const found = searchResult.index;
1251
+
1252
+ if (searchResult.strategy === "fuzzy-dominant") {
1253
+ const similarity = Math.round(searchResult.confidence * 100);
1254
+ warnings.push(`Dominant fuzzy match selected in ${path} near line ${found + 1} (${similarity}% similar).`);
1255
+ }
1256
+
1257
+ // Reject if match is ambiguous (prefix/substring matching found multiple matches)
1258
+ if (searchResult.matchCount !== undefined && searchResult.matchCount > 1) {
1259
+ const previews = formatSequenceMatchPreviews(
1260
+ originalLines,
1261
+ searchResult.matchIndices,
1262
+ searchResult.matchCount,
1263
+ );
1264
+ const strategyHint = searchResult.strategy ? ` Matching strategy: ${searchResult.strategy}.` : "";
1265
+ const previewText = previews ? `\n\n${previews}` : "";
1266
+ throw new ApplyPatchError(
1267
+ `Found ${searchResult.matchCount} matches for the text in ${path}.${strategyHint}` +
1268
+ `${previewText}\n\nAdd more surrounding context or additional @@ anchors to make it unique.`,
1269
+ );
1270
+ }
1271
+
1272
+ // For simple diffs (no context marker, no context lines), check for multiple occurrences
1273
+ // This ensures ambiguous replacements are rejected
1274
+ // Skip this check if isEndOfFile is set (EOF marker provides disambiguation)
1275
+ if (hunk.changeContext === undefined && !hunk.hasContextLines && !hunk.isEndOfFile && lineHint === undefined) {
1276
+ const secondMatch = seekSequence(originalLines, pattern, found + 1, false, { allowFuzzy });
1277
+ if (secondMatch.index !== undefined) {
1278
+ const preview1 = formatSequenceMatchPreview(originalLines, found);
1279
+ const preview2 = formatSequenceMatchPreview(originalLines, secondMatch.index);
1280
+ throw new ApplyPatchError(
1281
+ `Found 2 occurrences in ${path}:\n\n${preview1}\n\n${preview2}\n\n` +
1282
+ `Add more context lines to disambiguate.`,
1283
+ );
1284
+ }
1285
+ }
1286
+
1287
+ // Adjust indentation if needed (handles fuzzy matches where indentation differs)
1288
+ const actualMatchedLines = originalLines.slice(found, found + pattern.length);
1289
+
1290
+ // Skip pure-context hunks (no +/- lines — oldLines === newLines).
1291
+ // They serve only to advance lineIndex for subsequent hunks.
1292
+ let isNoOp = pattern.length === newSlice.length;
1293
+ if (isNoOp) {
1294
+ for (let i = 0; i < pattern.length; i++) {
1295
+ if (pattern[i] !== newSlice[i]) {
1296
+ isNoOp = false;
1297
+ break;
1298
+ }
1299
+ }
1300
+ }
1301
+
1302
+ if (isNoOp) {
1303
+ lineIndex = found + pattern.length;
1304
+ continue;
1305
+ }
1306
+
1307
+ const adjustedNewLines = adjustLinesIndentation(pattern, actualMatchedLines, newSlice);
1308
+ replacements.push({ startIndex: found, oldLen: pattern.length, newLines: adjustedNewLines });
1309
+ lineIndex = found + pattern.length;
1310
+ }
1311
+
1312
+ // Sort by start index
1313
+ replacements.sort((a, b) => a.startIndex - b.startIndex);
1314
+
1315
+ for (let i = 1; i < replacements.length; i++) {
1316
+ const prev = replacements[i - 1];
1317
+ const next = replacements[i];
1318
+ const prevEnd = prev.startIndex + prev.oldLen;
1319
+ if (next.startIndex < prevEnd) {
1320
+ const formatRange = (replacement: Replacement): string => {
1321
+ if (replacement.oldLen === 0) {
1322
+ return `${replacement.startIndex + 1} (insertion)`;
1323
+ }
1324
+ return `${replacement.startIndex + 1}-${replacement.startIndex + replacement.oldLen}`;
1325
+ };
1326
+ const prevRange = formatRange(prev);
1327
+ const nextRange = formatRange(next);
1328
+ throw new ApplyPatchError(
1329
+ `Overlapping hunks detected in ${path} at lines ${prevRange} and ${nextRange}. ` +
1330
+ `Split hunks or add more context to avoid overlap.`,
1331
+ );
1332
+ }
1333
+ }
1334
+
1335
+ return { replacements, warnings };
1336
+ }
1337
+
1338
+ /**
1339
+ * Apply replacements to lines, returning the modified content.
1340
+ */
1341
+ function applyReplacements(lines: string[], replacements: Replacement[]): string[] {
1342
+ const result = [...lines];
1343
+
1344
+ // Apply in reverse order to maintain indices
1345
+ for (let i = replacements.length - 1; i >= 0; i--) {
1346
+ const { startIndex, oldLen, newLines } = replacements[i];
1347
+ result.splice(startIndex, oldLen);
1348
+ result.splice(startIndex, 0, ...newLines);
1349
+ }
1350
+
1351
+ return result;
1352
+ }
1353
+
1354
+ /**
1355
+ * Apply diff hunks to file content.
1356
+ */
1357
+ function applyHunksToContent(
1358
+ originalContent: string,
1359
+ path: string,
1360
+ hunks: DiffHunk[],
1361
+ fuzzyThreshold: number,
1362
+ allowFuzzy: boolean,
1363
+ ): { content: string; warnings: string[] } {
1364
+ const hadFinalNewline = originalContent.endsWith("\n");
1365
+
1366
+ // Detect simple replace pattern: single hunk, no @@ context, no context lines, has old lines to match
1367
+ // Only use character-based matching when there are no hints to disambiguate
1368
+ if (hunks.length === 1) {
1369
+ const hunk = hunks[0];
1370
+ if (
1371
+ hunk.changeContext === undefined &&
1372
+ !hunk.hasContextLines &&
1373
+ hunk.oldLines.length > 0 &&
1374
+ hunk.oldStartLine === undefined && // No line hint to use for positioning
1375
+ !hunk.isEndOfFile // No EOF targeting (prefer end of file)
1376
+ ) {
1377
+ const { content, warnings } = applyCharacterMatch(originalContent, path, hunk, fuzzyThreshold, allowFuzzy);
1378
+ return { content: applyTrailingNewlinePolicy(content, hadFinalNewline), warnings };
1379
+ }
1380
+ }
1381
+
1382
+ let originalLines = originalContent.split("\n");
1383
+
1384
+ // Track if we have a trailing empty element from the final newline
1385
+ // Only strip ONE trailing empty (the newline marker), preserve actual blank lines
1386
+ let strippedTrailingEmpty = false;
1387
+ if (hadFinalNewline && originalLines.length > 0 && originalLines[originalLines.length - 1] === "") {
1388
+ // Check if the second-to-last is also empty (actual blank line) - if so, only strip one
1389
+ originalLines = originalLines.slice(0, -1);
1390
+ strippedTrailingEmpty = true;
1391
+ }
1392
+
1393
+ const { replacements, warnings } = computeReplacements(originalLines, path, hunks, allowFuzzy);
1394
+ const newLines = applyReplacements(originalLines, replacements);
1395
+
1396
+ // Restore the trailing empty element if we stripped it
1397
+ if (strippedTrailingEmpty) {
1398
+ newLines.push("");
1399
+ }
1400
+
1401
+ const content = newLines.join("\n");
1402
+ return { content: applyTrailingNewlinePolicy(content, hadFinalNewline), warnings };
1403
+ }
1404
+
1405
+ // ═══════════════════════════════════════════════════════════════════════════
1406
+ // Public API
1407
+ // ═══════════════════════════════════════════════════════════════════════════
1408
+
1409
+ /**
1410
+ * Apply a patch operation to the filesystem.
1411
+ */
1412
+ export async function applyPatch(input: PatchInput, options: ApplyPatchOptions): Promise<ApplyPatchResult> {
1413
+ return applyNormalizedPatch(input, options);
1414
+ }
1415
+
1416
+ /**
1417
+ * Apply a normalized patch operation to the filesystem.
1418
+ * @internal
1419
+ */
1420
+ async function applyNormalizedPatch(input: PatchInput, options: ApplyPatchOptions): Promise<ApplyPatchResult> {
1421
+ const {
1422
+ cwd,
1423
+ dryRun = false,
1424
+ fs = defaultFileSystem,
1425
+ fuzzyThreshold = DEFAULT_FUZZY_THRESHOLD,
1426
+ allowFuzzy = true,
1427
+ } = options;
1428
+
1429
+ const resolvePath = (p: string): string => resolveToCwd(p, cwd);
1430
+ const absolutePath = resolvePath(input.path);
1431
+ const op = input.op ?? "update";
1432
+
1433
+ if (input.rename) {
1434
+ const destPath = resolvePath(input.rename);
1435
+ if (destPath === absolutePath) {
1436
+ throw new ApplyPatchError("rename path is the same as source path");
1437
+ }
1438
+ }
1439
+
1440
+ // Handle CREATE operation
1441
+ if (op === "create") {
1442
+ if (!input.diff) {
1443
+ throw new ApplyPatchError("Create operation requires diff (file content)");
1444
+ }
1445
+ // Strip + prefixes if present (handles diffs formatted as additions)
1446
+ const normalizedContent = normalizeCreateContent(input.diff);
1447
+ const content = normalizedContent.endsWith("\n") ? normalizedContent : `${normalizedContent}\n`;
1448
+
1449
+ if (!dryRun) {
1450
+ const parentDir = path.dirname(absolutePath);
1451
+ if (parentDir && parentDir !== ".") {
1452
+ await fs.mkdir(parentDir);
1453
+ }
1454
+ await fs.write(absolutePath, content);
1455
+ }
1456
+
1457
+ return {
1458
+ change: {
1459
+ type: "create",
1460
+ path: absolutePath,
1461
+ newContent: content,
1462
+ },
1463
+ };
1464
+ }
1465
+
1466
+ // Handle DELETE operation
1467
+ if (op === "delete") {
1468
+ const oldContent = await readExistingPatchFile(fs, absolutePath, input.path);
1469
+ if (!dryRun) {
1470
+ await fs.delete(absolutePath);
1471
+ }
1472
+
1473
+ return {
1474
+ change: {
1475
+ type: "delete",
1476
+ path: absolutePath,
1477
+ oldContent,
1478
+ },
1479
+ };
1480
+ }
1481
+
1482
+ // Handle UPDATE operation
1483
+ if (!input.diff) {
1484
+ throw new ApplyPatchError("Update operation requires diff (hunks)");
1485
+ }
1486
+
1487
+ const originalContent = await readExistingPatchFile(fs, absolutePath, input.path);
1488
+ const { bom: bomFromText, text: strippedContent } = stripBom(originalContent);
1489
+ let bom = bomFromText;
1490
+ if (!bom && fs.readBinary) {
1491
+ const bytes = await fs.readBinary(absolutePath);
1492
+ if (bytes.length >= 3 && bytes[0] === 0xef && bytes[1] === 0xbb && bytes[2] === 0xbf) {
1493
+ bom = "\uFEFF";
1494
+ }
1495
+ }
1496
+ const lineEnding = detectLineEnding(strippedContent);
1497
+ const normalizedContent = normalizeToLF(strippedContent);
1498
+ const hunks = parseDiffHunks(input.diff);
1499
+
1500
+ if (hunks.length === 0) {
1501
+ throw new ApplyPatchError("Diff contains no hunks");
1502
+ }
1503
+
1504
+ const { content: newContent, warnings } = applyHunksToContent(
1505
+ normalizedContent,
1506
+ input.path,
1507
+ hunks,
1508
+ fuzzyThreshold,
1509
+ allowFuzzy,
1510
+ );
1511
+ const finalContent = bom + restoreLineEndings(newContent, lineEnding);
1512
+ const destPath = input.rename ? resolvePath(input.rename) : absolutePath;
1513
+ const isMove = Boolean(input.rename) && destPath !== absolutePath;
1514
+
1515
+ if (!dryRun) {
1516
+ if (isMove) {
1517
+ const parentDir = path.dirname(destPath);
1518
+ if (parentDir && parentDir !== ".") {
1519
+ await fs.mkdir(parentDir);
1520
+ }
1521
+ await fs.write(destPath, finalContent);
1522
+ await fs.delete(absolutePath);
1523
+ } else {
1524
+ await fs.write(absolutePath, finalContent);
1525
+ }
1526
+ }
1527
+
1528
+ return {
1529
+ change: {
1530
+ type: "update",
1531
+ path: absolutePath,
1532
+ newPath: isMove ? destPath : undefined,
1533
+ oldContent: originalContent,
1534
+ newContent: finalContent,
1535
+ },
1536
+ warnings: warnings.length > 0 ? warnings : undefined,
1537
+ };
1538
+ }
1539
+
1540
+ /**
1541
+ * Preview what changes a patch would make without applying it.
1542
+ */
1543
+ export async function previewPatch(input: PatchInput, options: ApplyPatchOptions): Promise<ApplyPatchResult> {
1544
+ return applyPatch(input, { ...options, dryRun: true });
1545
+ }
1546
+
1547
+ export async function computePatchDiff(
1548
+ input: PatchInput,
1549
+ cwd: string,
1550
+ options?: { fuzzyThreshold?: number; allowFuzzy?: boolean },
1551
+ ): Promise<
1552
+ | {
1553
+ diff: string;
1554
+ firstChangedLine: number | undefined;
1555
+ }
1556
+ | {
1557
+ error: string;
1558
+ }
1559
+ > {
1560
+ try {
1561
+ const result = await previewPatch(input, {
1562
+ cwd,
1563
+ fuzzyThreshold: options?.fuzzyThreshold,
1564
+ allowFuzzy: options?.allowFuzzy,
1565
+ });
1566
+ const oldContent = result.change.oldContent ?? "";
1567
+ const newContent = result.change.newContent ?? "";
1568
+ const normalizedOld = normalizeToLF(stripBom(oldContent).text);
1569
+ const normalizedNew = normalizeToLF(stripBom(newContent).text);
1570
+ if (!normalizedOld && !normalizedNew) {
1571
+ return { diff: "", firstChangedLine: undefined };
1572
+ }
1573
+ return generateUnifiedDiffString(normalizedOld, normalizedNew);
1574
+ } catch (err) {
1575
+ return { error: err instanceof Error ? err.message : String(err) };
1576
+ }
1577
+ }
1578
+
1579
+ export const patchEditSchema = Type.Object({
1580
+ path: Type.String({ description: "File path" }),
1581
+ op: Type.Optional(
1582
+ StringEnum(["create", "delete", "update"], {
1583
+ description: "Operation (default: update)",
1584
+ }),
1585
+ ),
1586
+ rename: Type.Optional(Type.String({ description: "New path for move" })),
1587
+ diff: Type.Optional(Type.String({ description: "Diff hunks (update) or full content (create)" })),
1588
+ });
1589
+
1590
+ export type PatchParams = Static<typeof patchEditSchema>;
1591
+
1592
+ interface ExecutePatchModeOptions {
1593
+ session: ToolSession;
1594
+ params: PatchParams;
1595
+ signal?: AbortSignal;
1596
+ batchRequest?: LspBatchRequest;
1597
+ allowFuzzy: boolean;
1598
+ fuzzyThreshold: number;
1599
+ writethrough: WritethroughCallback;
1600
+ beginDeferredDiagnosticsForPath: (path: string) => WritethroughDeferredHandle;
1601
+ }
1602
+
1603
+ export function isPatchParams(params: unknown): params is PatchParams {
1604
+ if (typeof params !== "object" || params === null || !("path" in params)) {
1605
+ return false;
1606
+ }
1607
+ return !("old_text" in params) && !("new_text" in params) && !("edits" in params);
1608
+ }
1609
+
1610
+ class LspFileSystem implements FileSystem {
1611
+ #lastDiagnostics: FileDiagnosticsResult | undefined;
1612
+ #fileCache: Record<string, Bun.BunFile> = {};
1613
+
1614
+ constructor(
1615
+ private readonly writethrough: WritethroughCallback,
1616
+ private readonly signal?: AbortSignal,
1617
+ private readonly batchRequest?: LspBatchRequest,
1618
+ private readonly deferredForPath?: (path: string) => WritethroughDeferredHandle,
1619
+ ) {}
1620
+
1621
+ #getFile(path: string): Bun.BunFile {
1622
+ if (this.#fileCache[path]) {
1623
+ return this.#fileCache[path];
1624
+ }
1625
+ const file = Bun.file(path);
1626
+ this.#fileCache[path] = file;
1627
+ return file;
1628
+ }
1629
+
1630
+ async exists(path: string): Promise<boolean> {
1631
+ return this.#getFile(path).exists();
1632
+ }
1633
+
1634
+ async read(path: string): Promise<string> {
1635
+ return this.#getFile(path).text();
1636
+ }
1637
+
1638
+ async readBinary(path: string): Promise<Uint8Array> {
1639
+ const bytes = await fs.promises.readFile(path);
1640
+ return bytes;
1641
+ }
1642
+
1643
+ async write(path: string, content: string): Promise<void> {
1644
+ const file = this.#getFile(path);
1645
+ const deferredForPath = this.deferredForPath;
1646
+ const result = await this.writethrough(
1647
+ path,
1648
+ content,
1649
+ this.signal,
1650
+ file,
1651
+ this.batchRequest,
1652
+ deferredForPath ? (dst: string) => deferredForPath(dst) : undefined,
1653
+ );
1654
+ if (result) {
1655
+ this.#lastDiagnostics = result;
1656
+ }
1657
+ }
1658
+
1659
+ async delete(path: string): Promise<void> {
1660
+ await this.#getFile(path).unlink();
1661
+ }
1662
+
1663
+ async mkdir(path: string): Promise<void> {
1664
+ await fs.promises.mkdir(path, { recursive: true });
1665
+ }
1666
+
1667
+ getDiagnostics(): FileDiagnosticsResult | undefined {
1668
+ return this.#lastDiagnostics;
1669
+ }
1670
+ }
1671
+
1672
+ function mergeDiagnosticsWithWarnings(
1673
+ diagnostics: FileDiagnosticsResult | undefined,
1674
+ warnings: string[],
1675
+ ): FileDiagnosticsResult | undefined {
1676
+ if (warnings.length === 0) return diagnostics;
1677
+ const warningMessages = warnings.map(warning => `patch: ${warning}`);
1678
+ if (!diagnostics) {
1679
+ return {
1680
+ server: "patch",
1681
+ messages: warningMessages,
1682
+ summary: `Patch warnings: ${warnings.length}`,
1683
+ errored: false,
1684
+ };
1685
+ }
1686
+ return {
1687
+ ...diagnostics,
1688
+ messages: [...warningMessages, ...diagnostics.messages],
1689
+ summary: `${diagnostics.summary}; Patch warnings: ${warnings.length}`,
1690
+ };
1691
+ }
1692
+
1693
+ export async function executePatchMode(
1694
+ options: ExecutePatchModeOptions,
1695
+ ): Promise<AgentToolResult<EditToolDetails, typeof patchEditSchema>> {
1696
+ const {
1697
+ session,
1698
+ params,
1699
+ signal,
1700
+ batchRequest,
1701
+ allowFuzzy,
1702
+ fuzzyThreshold,
1703
+ writethrough,
1704
+ beginDeferredDiagnosticsForPath,
1705
+ } = options;
1706
+ const { path, op: rawOp, rename, diff } = params;
1707
+
1708
+ const op: Operation = rawOp === "create" || rawOp === "delete" ? rawOp : "update";
1709
+
1710
+ enforcePlanModeWrite(session, path, { op, move: rename });
1711
+ const resolvedPath = resolvePlanPath(session, path);
1712
+ const resolvedRename = rename ? resolvePlanPath(session, rename) : undefined;
1713
+
1714
+ if (path.endsWith(".ipynb")) {
1715
+ throw new Error("Cannot edit Jupyter notebooks with the Edit tool. Use the NotebookEdit tool instead.");
1716
+ }
1717
+ if (rename?.endsWith(".ipynb")) {
1718
+ throw new Error("Cannot edit Jupyter notebooks with the Edit tool. Use the NotebookEdit tool instead.");
1719
+ }
1720
+
1721
+ await assertEditableFile(resolvedPath, path);
1722
+
1723
+ const input: PatchInput = { path: resolvedPath, op, rename: resolvedRename, diff };
1724
+ const patchFileSystem = new LspFileSystem(writethrough, signal, batchRequest, beginDeferredDiagnosticsForPath);
1725
+ const result = await applyPatch(input, {
1726
+ cwd: session.cwd,
1727
+ fs: patchFileSystem,
1728
+ fuzzyThreshold,
1729
+ allowFuzzy,
1730
+ });
1731
+
1732
+ if (resolvedRename) {
1733
+ invalidateFsScanAfterRename(resolvedPath, resolvedRename);
1734
+ } else if (result.change.type === "delete") {
1735
+ invalidateFsScanAfterDelete(resolvedPath);
1736
+ } else {
1737
+ invalidateFsScanAfterWrite(resolvedPath);
1738
+ }
1739
+ const effectiveRename = result.change.newPath ? rename : undefined;
1740
+
1741
+ let diffResult: { diff: string; firstChangedLine: number | undefined } = {
1742
+ diff: "",
1743
+ firstChangedLine: undefined,
1744
+ };
1745
+ if (result.change.type === "update" && result.change.oldContent && result.change.newContent) {
1746
+ const normalizedOld = normalizeToLF(stripBom(result.change.oldContent).text);
1747
+ const normalizedNew = normalizeToLF(stripBom(result.change.newContent).text);
1748
+ diffResult = generateUnifiedDiffString(normalizedOld, normalizedNew);
1749
+ }
1750
+
1751
+ let resultText: string;
1752
+ switch (result.change.type) {
1753
+ case "create":
1754
+ resultText = `Created ${path}`;
1755
+ break;
1756
+ case "delete":
1757
+ resultText = `Deleted ${path}`;
1758
+ break;
1759
+ case "update":
1760
+ resultText = effectiveRename ? `Updated and moved ${path} to ${effectiveRename}` : `Updated ${path}`;
1761
+ break;
1762
+ }
1763
+
1764
+ let diagnostics = patchFileSystem.getDiagnostics();
1765
+ if (op === "delete" && batchRequest?.flush) {
1766
+ const flushedDiagnostics = await flushLspWritethroughBatch(batchRequest.id, session.cwd, signal);
1767
+ diagnostics ??= flushedDiagnostics;
1768
+ }
1769
+ const mergedDiagnostics = mergeDiagnosticsWithWarnings(diagnostics, result.warnings ?? []);
1770
+ const meta = outputMeta()
1771
+ .diagnostics(mergedDiagnostics?.summary ?? "", mergedDiagnostics?.messages ?? [])
1772
+ .get();
1773
+
1774
+ return {
1775
+ content: [{ type: "text", text: resultText }],
1776
+ details: {
1777
+ diff: diffResult.diff,
1778
+ firstChangedLine: diffResult.firstChangedLine,
1779
+ diagnostics: mergedDiagnostics,
1780
+ op,
1781
+ move: effectiveRename,
1782
+ meta,
1783
+ },
1784
+ };
1785
+ }