apex-code 0.4.0 → 0.5.1

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 (573) hide show
  1. package/CHANGELOG.md +280 -6
  2. package/README.md +624 -0
  3. package/dist/bun/cli.d.ts +3 -1
  4. package/dist/bun/cli.d.ts.map +1 -1
  5. package/dist/bun/cli.js +3 -9
  6. package/dist/bun/cli.js.map +1 -1
  7. package/dist/bun/runtime-setup.d.ts +2 -0
  8. package/dist/bun/runtime-setup.d.ts.map +1 -0
  9. package/dist/bun/runtime-setup.js +9 -0
  10. package/dist/bun/runtime-setup.js.map +1 -0
  11. package/dist/bun/sandbox-env-setup.d.ts +2 -0
  12. package/dist/bun/sandbox-env-setup.d.ts.map +1 -0
  13. package/dist/bun/sandbox-env-setup.js +4 -0
  14. package/dist/bun/sandbox-env-setup.js.map +1 -0
  15. package/dist/cli/args.d.ts.map +1 -1
  16. package/dist/cli/args.js +16 -5
  17. package/dist/cli/args.js.map +1 -1
  18. package/dist/cli/config-selector.d.ts.map +1 -1
  19. package/dist/cli/config-selector.js +2 -1
  20. package/dist/cli/config-selector.js.map +1 -1
  21. package/dist/cli/file-processor.d.ts +1 -1
  22. package/dist/cli/file-processor.d.ts.map +1 -1
  23. package/dist/cli/file-processor.js.map +1 -1
  24. package/dist/cli/session-picker.d.ts +1 -1
  25. package/dist/cli/session-picker.d.ts.map +1 -1
  26. package/dist/cli/session-picker.js.map +1 -1
  27. package/dist/cli/setup.d.ts +2 -0
  28. package/dist/cli/setup.d.ts.map +1 -0
  29. package/dist/cli/setup.js +13 -0
  30. package/dist/cli/setup.js.map +1 -0
  31. package/dist/config.d.ts +1 -0
  32. package/dist/config.d.ts.map +1 -1
  33. package/dist/config.js +1 -0
  34. package/dist/config.js.map +1 -1
  35. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  36. package/dist/core/agent-session-runtime.js +16 -8
  37. package/dist/core/agent-session-runtime.js.map +1 -1
  38. package/dist/core/agent-session.d.ts +85 -15
  39. package/dist/core/agent-session.d.ts.map +1 -1
  40. package/dist/core/agent-session.js +685 -266
  41. package/dist/core/agent-session.js.map +1 -1
  42. package/dist/core/auth-storage.d.ts +4 -0
  43. package/dist/core/auth-storage.d.ts.map +1 -1
  44. package/dist/core/auth-storage.js +55 -0
  45. package/dist/core/auth-storage.js.map +1 -1
  46. package/dist/core/bug-report.d.ts +176 -0
  47. package/dist/core/bug-report.d.ts.map +1 -0
  48. package/dist/core/bug-report.js +291 -0
  49. package/dist/core/bug-report.js.map +1 -0
  50. package/dist/core/cache-stats.d.ts.map +1 -1
  51. package/dist/core/cache-stats.js +12 -1
  52. package/dist/core/cache-stats.js.map +1 -1
  53. package/dist/core/cache-warmer.d.ts +103 -0
  54. package/dist/core/cache-warmer.d.ts.map +1 -0
  55. package/dist/core/cache-warmer.js +356 -0
  56. package/dist/core/cache-warmer.js.map +1 -0
  57. package/dist/core/compaction/branch-summarization.d.ts +1 -1
  58. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  59. package/dist/core/compaction/branch-summarization.js +4 -3
  60. package/dist/core/compaction/branch-summarization.js.map +1 -1
  61. package/dist/core/compaction/compaction.d.ts +5 -3
  62. package/dist/core/compaction/compaction.d.ts.map +1 -1
  63. package/dist/core/compaction/compaction.js +163 -66
  64. package/dist/core/compaction/compaction.js.map +1 -1
  65. package/dist/core/context/pipeline.d.ts +8 -8
  66. package/dist/core/context/pipeline.d.ts.map +1 -1
  67. package/dist/core/context/pipeline.js +21 -12
  68. package/dist/core/context/pipeline.js.map +1 -1
  69. package/dist/core/crash-log.d.ts +27 -0
  70. package/dist/core/crash-log.d.ts.map +1 -0
  71. package/dist/core/crash-log.js +139 -0
  72. package/dist/core/crash-log.js.map +1 -0
  73. package/dist/core/export-html/template.js +6 -1
  74. package/dist/core/extensions/index.d.ts +1 -1
  75. package/dist/core/extensions/index.d.ts.map +1 -1
  76. package/dist/core/extensions/index.js.map +1 -1
  77. package/dist/core/extensions/jiti-loader.d.ts +2 -0
  78. package/dist/core/extensions/jiti-loader.d.ts.map +1 -0
  79. package/dist/core/extensions/jiti-loader.js +4 -0
  80. package/dist/core/extensions/jiti-loader.js.map +1 -0
  81. package/dist/core/extensions/jiti-static-loader.d.ts +2 -0
  82. package/dist/core/extensions/jiti-static-loader.d.ts.map +1 -0
  83. package/dist/core/extensions/jiti-static-loader.js +4 -0
  84. package/dist/core/extensions/jiti-static-loader.js.map +1 -0
  85. package/dist/core/extensions/loader.d.ts.map +1 -1
  86. package/dist/core/extensions/loader.js +40 -59
  87. package/dist/core/extensions/loader.js.map +1 -1
  88. package/dist/core/extensions/runner.d.ts +24 -8
  89. package/dist/core/extensions/runner.d.ts.map +1 -1
  90. package/dist/core/extensions/runner.js +195 -72
  91. package/dist/core/extensions/runner.js.map +1 -1
  92. package/dist/core/extensions/types.d.ts +142 -55
  93. package/dist/core/extensions/types.d.ts.map +1 -1
  94. package/dist/core/extensions/types.js.map +1 -1
  95. package/dist/core/extensions/virtual-modules.d.ts +3 -0
  96. package/dist/core/extensions/virtual-modules.d.ts.map +1 -0
  97. package/dist/core/extensions/virtual-modules.js +41 -0
  98. package/dist/core/extensions/virtual-modules.js.map +1 -0
  99. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  100. package/dist/core/extensions/wrapper.js +1 -20
  101. package/dist/core/extensions/wrapper.js.map +1 -1
  102. package/dist/core/http-dispatcher.d.ts.map +1 -1
  103. package/dist/core/http-dispatcher.js +2 -0
  104. package/dist/core/http-dispatcher.js.map +1 -1
  105. package/dist/core/index.d.ts +2 -1
  106. package/dist/core/index.d.ts.map +1 -1
  107. package/dist/core/index.js.map +1 -1
  108. package/dist/core/keybindings.d.ts +6 -1
  109. package/dist/core/keybindings.d.ts.map +1 -1
  110. package/dist/core/keybindings.js +5 -1
  111. package/dist/core/keybindings.js.map +1 -1
  112. package/dist/core/messages.d.ts +1 -1
  113. package/dist/core/messages.d.ts.map +1 -1
  114. package/dist/core/messages.js +1 -0
  115. package/dist/core/messages.js.map +1 -1
  116. package/dist/core/model-config.d.ts +168 -20
  117. package/dist/core/model-config.d.ts.map +1 -1
  118. package/dist/core/model-config.js +44 -18
  119. package/dist/core/model-config.js.map +1 -1
  120. package/dist/core/model-registry.d.ts +5 -1
  121. package/dist/core/model-registry.d.ts.map +1 -1
  122. package/dist/core/model-registry.js +8 -0
  123. package/dist/core/model-registry.js.map +1 -1
  124. package/dist/core/model-resolver.d.ts.map +1 -1
  125. package/dist/core/model-resolver.js +4 -3
  126. package/dist/core/model-resolver.js.map +1 -1
  127. package/dist/core/model-runtime.d.ts +1 -0
  128. package/dist/core/model-runtime.d.ts.map +1 -1
  129. package/dist/core/model-runtime.js +12 -6
  130. package/dist/core/model-runtime.js.map +1 -1
  131. package/dist/core/permissions/store.d.ts.map +1 -1
  132. package/dist/core/permissions/store.js +11 -8
  133. package/dist/core/permissions/store.js.map +1 -1
  134. package/dist/core/prompt-templates.d.ts +6 -1
  135. package/dist/core/prompt-templates.d.ts.map +1 -1
  136. package/dist/core/prompt-templates.js +61 -35
  137. package/dist/core/prompt-templates.js.map +1 -1
  138. package/dist/core/provider-composer.d.ts +4 -2
  139. package/dist/core/provider-composer.d.ts.map +1 -1
  140. package/dist/core/provider-composer.js +29 -2
  141. package/dist/core/provider-composer.js.map +1 -1
  142. package/dist/core/radius.d.ts +3 -0
  143. package/dist/core/radius.d.ts.map +1 -1
  144. package/dist/core/radius.js +6 -0
  145. package/dist/core/radius.js.map +1 -1
  146. package/dist/core/resource-loader.d.ts.map +1 -1
  147. package/dist/core/resource-loader.js +6 -2
  148. package/dist/core/resource-loader.js.map +1 -1
  149. package/dist/core/sdk.d.ts.map +1 -1
  150. package/dist/core/sdk.js +63 -42
  151. package/dist/core/sdk.js.map +1 -1
  152. package/dist/core/session-export.d.ts +6 -2
  153. package/dist/core/session-export.d.ts.map +1 -1
  154. package/dist/core/session-export.js +14 -13
  155. package/dist/core/session-export.js.map +1 -1
  156. package/dist/core/session-manager.d.ts +66 -15
  157. package/dist/core/session-manager.d.ts.map +1 -1
  158. package/dist/core/session-manager.js +295 -115
  159. package/dist/core/session-manager.js.map +1 -1
  160. package/dist/core/settings-manager.d.ts +27 -4
  161. package/dist/core/settings-manager.d.ts.map +1 -1
  162. package/dist/core/settings-manager.js +56 -8
  163. package/dist/core/settings-manager.js.map +1 -1
  164. package/dist/core/skills.d.ts +1 -1
  165. package/dist/core/skills.d.ts.map +1 -1
  166. package/dist/core/skills.js +5 -4
  167. package/dist/core/skills.js.map +1 -1
  168. package/dist/core/slash-commands.d.ts.map +1 -1
  169. package/dist/core/slash-commands.js +1 -0
  170. package/dist/core/slash-commands.js.map +1 -1
  171. package/dist/core/system-prompt.d.ts +49 -6
  172. package/dist/core/system-prompt.d.ts.map +1 -1
  173. package/dist/core/system-prompt.js +140 -79
  174. package/dist/core/system-prompt.js.map +1 -1
  175. package/dist/core/tools/bash.d.ts +9 -15
  176. package/dist/core/tools/bash.d.ts.map +1 -1
  177. package/dist/core/tools/bash.js +20 -137
  178. package/dist/core/tools/bash.js.map +1 -1
  179. package/dist/core/tools/delegate.d.ts.map +1 -1
  180. package/dist/core/tools/delegate.js +2 -2
  181. package/dist/core/tools/delegate.js.map +1 -1
  182. package/dist/core/tools/edit.d.ts +1 -12
  183. package/dist/core/tools/edit.d.ts.map +1 -1
  184. package/dist/core/tools/edit.js +6 -204
  185. package/dist/core/tools/edit.js.map +1 -1
  186. package/dist/core/tools/find.d.ts.map +1 -1
  187. package/dist/core/tools/find.js +4 -55
  188. package/dist/core/tools/find.js.map +1 -1
  189. package/dist/core/tools/grep.d.ts.map +1 -1
  190. package/dist/core/tools/grep.js +4 -60
  191. package/dist/core/tools/grep.js.map +1 -1
  192. package/dist/core/tools/ls.d.ts.map +1 -1
  193. package/dist/core/tools/ls.js +4 -49
  194. package/dist/core/tools/ls.js.map +1 -1
  195. package/dist/core/tools/read.d.ts +4 -1
  196. package/dist/core/tools/read.d.ts.map +1 -1
  197. package/dist/core/tools/read.js +10 -122
  198. package/dist/core/tools/read.js.map +1 -1
  199. package/dist/core/tools/renderers/bash.d.ts +18 -0
  200. package/dist/core/tools/renderers/bash.d.ts.map +1 -0
  201. package/dist/core/tools/renderers/bash.js +126 -0
  202. package/dist/core/tools/renderers/bash.js.map +1 -0
  203. package/dist/core/tools/renderers/edit.d.ts +23 -0
  204. package/dist/core/tools/renderers/edit.d.ts.map +1 -0
  205. package/dist/core/tools/renderers/edit.js +207 -0
  206. package/dist/core/tools/renderers/edit.js.map +1 -0
  207. package/dist/core/tools/renderers/find.d.ts +10 -0
  208. package/dist/core/tools/renderers/find.d.ts.map +1 -0
  209. package/dist/core/tools/renderers/find.js +64 -0
  210. package/dist/core/tools/renderers/find.js.map +1 -0
  211. package/dist/core/tools/renderers/grep.d.ts +10 -0
  212. package/dist/core/tools/renderers/grep.d.ts.map +1 -0
  213. package/dist/core/tools/renderers/grep.js +69 -0
  214. package/dist/core/tools/renderers/grep.js.map +1 -0
  215. package/dist/core/tools/renderers/index.d.ts +34 -0
  216. package/dist/core/tools/renderers/index.d.ts.map +1 -0
  217. package/dist/core/tools/renderers/index.js +47 -0
  218. package/dist/core/tools/renderers/index.js.map +1 -0
  219. package/dist/core/tools/renderers/ls.d.ts +10 -0
  220. package/dist/core/tools/renderers/ls.d.ts.map +1 -0
  221. package/dist/core/tools/renderers/ls.js +58 -0
  222. package/dist/core/tools/renderers/ls.js.map +1 -0
  223. package/dist/core/tools/renderers/read.d.ts +11 -0
  224. package/dist/core/tools/renderers/read.d.ts.map +1 -0
  225. package/dist/core/tools/renderers/read.js +132 -0
  226. package/dist/core/tools/renderers/read.js.map +1 -0
  227. package/dist/core/tools/renderers/write.d.ts +10 -0
  228. package/dist/core/tools/renderers/write.d.ts.map +1 -0
  229. package/dist/core/tools/renderers/write.js +152 -0
  230. package/dist/core/tools/renderers/write.js.map +1 -0
  231. package/dist/core/tools/write.d.ts.map +1 -1
  232. package/dist/core/tools/write.js +6 -147
  233. package/dist/core/tools/write.js.map +1 -1
  234. package/dist/core/usage-totals.d.ts +1 -1
  235. package/dist/core/usage-totals.d.ts.map +1 -1
  236. package/dist/core/usage-totals.js +5 -1
  237. package/dist/core/usage-totals.js.map +1 -1
  238. package/dist/extensions/llama/client.d.ts +2 -0
  239. package/dist/extensions/llama/client.d.ts.map +1 -1
  240. package/dist/extensions/llama/client.js +7 -3
  241. package/dist/extensions/llama/client.js.map +1 -1
  242. package/dist/extensions/llama/provider.d.ts.map +1 -1
  243. package/dist/extensions/llama/provider.js +20 -5
  244. package/dist/extensions/llama/provider.js.map +1 -1
  245. package/dist/extensions/llama/ui.d.ts.map +1 -1
  246. package/dist/extensions/llama/ui.js +3 -2
  247. package/dist/extensions/llama/ui.js.map +1 -1
  248. package/dist/index.d.ts +5 -4
  249. package/dist/index.d.ts.map +1 -1
  250. package/dist/index.js +1 -1
  251. package/dist/index.js.map +1 -1
  252. package/dist/main.d.ts.map +1 -1
  253. package/dist/main.js +21 -13
  254. package/dist/main.js.map +1 -1
  255. package/dist/modes/interactive/bug-report.d.ts +16 -0
  256. package/dist/modes/interactive/bug-report.d.ts.map +1 -0
  257. package/dist/modes/interactive/bug-report.js +167 -0
  258. package/dist/modes/interactive/bug-report.js.map +1 -0
  259. package/dist/modes/interactive/chat-viewport.d.ts +20 -0
  260. package/dist/modes/interactive/chat-viewport.d.ts.map +1 -0
  261. package/dist/modes/interactive/chat-viewport.js +28 -0
  262. package/dist/modes/interactive/chat-viewport.js.map +1 -0
  263. package/dist/modes/interactive/components/assistant-message.d.ts +7 -0
  264. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  265. package/dist/modes/interactive/components/assistant-message.js +63 -27
  266. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  267. package/dist/modes/interactive/components/autocomplete-source.d.ts +8 -0
  268. package/dist/modes/interactive/components/autocomplete-source.d.ts.map +1 -0
  269. package/dist/modes/interactive/components/autocomplete-source.js +23 -0
  270. package/dist/modes/interactive/components/autocomplete-source.js.map +1 -0
  271. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  272. package/dist/modes/interactive/components/bash-execution.js +6 -4
  273. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  274. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  275. package/dist/modes/interactive/components/bordered-loader.js +1 -1
  276. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  277. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  278. package/dist/modes/interactive/components/branch-summary-message.js +12 -5
  279. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  280. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  281. package/dist/modes/interactive/components/compaction-summary-message.js +12 -5
  282. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  283. package/dist/modes/interactive/components/composer-dock.d.ts +12 -0
  284. package/dist/modes/interactive/components/composer-dock.d.ts.map +1 -0
  285. package/dist/modes/interactive/components/composer-dock.js +24 -0
  286. package/dist/modes/interactive/components/composer-dock.js.map +1 -0
  287. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  288. package/dist/modes/interactive/components/config-selector.js +11 -9
  289. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  290. package/dist/modes/interactive/components/custom-editor.d.ts +12 -0
  291. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  292. package/dist/modes/interactive/components/custom-editor.js +38 -0
  293. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  294. package/dist/modes/interactive/components/error-summary.d.ts +11 -0
  295. package/dist/modes/interactive/components/error-summary.d.ts.map +1 -0
  296. package/dist/modes/interactive/components/error-summary.js +31 -0
  297. package/dist/modes/interactive/components/error-summary.js.map +1 -0
  298. package/dist/modes/interactive/components/extension-editor.d.ts +4 -1
  299. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  300. package/dist/modes/interactive/components/extension-editor.js +15 -10
  301. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  302. package/dist/modes/interactive/components/extension-input.d.ts +2 -0
  303. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  304. package/dist/modes/interactive/components/extension-input.js +15 -5
  305. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  306. package/dist/modes/interactive/components/extension-selector.d.ts +2 -0
  307. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  308. package/dist/modes/interactive/components/extension-selector.js +15 -10
  309. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  310. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  311. package/dist/modes/interactive/components/first-time-setup.js +6 -6
  312. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  313. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  314. package/dist/modes/interactive/components/footer.js +12 -4
  315. package/dist/modes/interactive/components/footer.js.map +1 -1
  316. package/dist/modes/interactive/components/index.d.ts +1 -1
  317. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  318. package/dist/modes/interactive/components/index.js.map +1 -1
  319. package/dist/modes/interactive/components/keybinding-hints.d.ts +21 -0
  320. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  321. package/dist/modes/interactive/components/keybinding-hints.js +34 -0
  322. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  323. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  324. package/dist/modes/interactive/components/login-dialog.js +27 -23
  325. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  326. package/dist/modes/interactive/components/model-selector.d.ts +1 -1
  327. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  328. package/dist/modes/interactive/components/model-selector.js +16 -20
  329. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  330. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  331. package/dist/modes/interactive/components/oauth-selector.js +7 -6
  332. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  333. package/dist/modes/interactive/components/permission-preview.d.ts.map +1 -1
  334. package/dist/modes/interactive/components/permission-preview.js +3 -3
  335. package/dist/modes/interactive/components/permission-preview.js.map +1 -1
  336. package/dist/modes/interactive/components/prompt-input.d.ts +12 -0
  337. package/dist/modes/interactive/components/prompt-input.d.ts.map +1 -0
  338. package/dist/modes/interactive/components/prompt-input.js +18 -0
  339. package/dist/modes/interactive/components/prompt-input.js.map +1 -0
  340. package/dist/modes/interactive/components/scoped-models-selector.d.ts +1 -1
  341. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  342. package/dist/modes/interactive/components/scoped-models-selector.js +17 -18
  343. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  344. package/dist/modes/interactive/components/session-selector.d.ts +5 -5
  345. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  346. package/dist/modes/interactive/components/session-selector.js +100 -67
  347. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  348. package/dist/modes/interactive/components/settings-selector.d.ts +5 -1
  349. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  350. package/dist/modes/interactive/components/settings-selector.js +74 -16
  351. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  352. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -1
  353. package/dist/modes/interactive/components/settings-submenu.js +8 -6
  354. package/dist/modes/interactive/components/settings-submenu.js.map +1 -1
  355. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  356. package/dist/modes/interactive/components/skill-invocation-message.js +11 -4
  357. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  358. package/dist/modes/interactive/components/status-indicator.d.ts +3 -1
  359. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
  360. package/dist/modes/interactive/components/status-indicator.js +10 -3
  361. package/dist/modes/interactive/components/status-indicator.js.map +1 -1
  362. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  363. package/dist/modes/interactive/components/thinking-selector.js +14 -9
  364. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  365. package/dist/modes/interactive/components/tool-execution.d.ts +28 -16
  366. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  367. package/dist/modes/interactive/components/tool-execution.js +73 -80
  368. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  369. package/dist/modes/interactive/components/tool-panel.d.ts.map +1 -1
  370. package/dist/modes/interactive/components/tool-panel.js +7 -2
  371. package/dist/modes/interactive/components/tool-panel.js.map +1 -1
  372. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  373. package/dist/modes/interactive/components/tree-selector.js +18 -5
  374. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  375. package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -1
  376. package/dist/modes/interactive/components/trust-selector.js +12 -12
  377. package/dist/modes/interactive/components/trust-selector.js.map +1 -1
  378. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  379. package/dist/modes/interactive/components/user-message-selector.js +2 -2
  380. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  381. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  382. package/dist/modes/interactive/components/user-message.js +6 -3
  383. package/dist/modes/interactive/components/user-message.js.map +1 -1
  384. package/dist/modes/interactive/interactive-mode.d.ts +50 -31
  385. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  386. package/dist/modes/interactive/interactive-mode.js +494 -229
  387. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  388. package/dist/modes/interactive/theme/dark.json +2 -1
  389. package/dist/modes/interactive/theme/light.json +2 -1
  390. package/dist/modes/interactive/theme/theme-controller.d.ts +1 -0
  391. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  392. package/dist/modes/interactive/theme/theme-controller.js +5 -0
  393. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  394. package/dist/modes/interactive/theme/theme-json.d.ts +84 -0
  395. package/dist/modes/interactive/theme/theme-json.d.ts.map +1 -0
  396. package/dist/modes/interactive/theme/theme-json.js +130 -0
  397. package/dist/modes/interactive/theme/theme-json.js.map +1 -0
  398. package/dist/modes/interactive/theme/theme-schema.json +6 -2
  399. package/dist/modes/interactive/theme/theme.d.ts +14 -5
  400. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  401. package/dist/modes/interactive/theme/theme.js +18 -119
  402. package/dist/modes/interactive/theme/theme.js.map +1 -1
  403. package/dist/modes/interactive/tui-renderer.d.ts +21 -0
  404. package/dist/modes/interactive/tui-renderer.d.ts.map +1 -0
  405. package/dist/modes/interactive/tui-renderer.js +66 -0
  406. package/dist/modes/interactive/tui-renderer.js.map +1 -0
  407. package/dist/modes/print-mode.d.ts.map +1 -1
  408. package/dist/modes/print-mode.js +49 -23
  409. package/dist/modes/print-mode.js.map +1 -1
  410. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  411. package/dist/modes/rpc/rpc-mode.js +2 -2
  412. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  413. package/dist/testing/replay/recorded-provider.d.ts +2 -2
  414. package/dist/testing/replay/recorded-provider.d.ts.map +1 -1
  415. package/dist/testing/replay/recorded-provider.js +2 -5
  416. package/dist/testing/replay/recorded-provider.js.map +1 -1
  417. package/dist/testing/replay/runner.d.ts.map +1 -1
  418. package/dist/testing/replay/runner.js +0 -1
  419. package/dist/testing/replay/runner.js.map +1 -1
  420. package/dist/utils/clipboard-command.d.ts +7 -0
  421. package/dist/utils/clipboard-command.d.ts.map +1 -0
  422. package/dist/utils/clipboard-command.js +45 -0
  423. package/dist/utils/clipboard-command.js.map +1 -0
  424. package/dist/utils/clipboard-image.d.ts.map +1 -1
  425. package/dist/utils/clipboard-image.js +53 -81
  426. package/dist/utils/clipboard-image.js.map +1 -1
  427. package/dist/utils/clipboard.d.ts.map +1 -1
  428. package/dist/utils/clipboard.js +111 -121
  429. package/dist/utils/clipboard.js.map +1 -1
  430. package/dist/utils/exif-orientation.d.ts.map +1 -1
  431. package/dist/utils/exif-orientation.js +2 -3
  432. package/dist/utils/exif-orientation.js.map +1 -1
  433. package/dist/utils/mime.d.ts.map +1 -1
  434. package/dist/utils/mime.js +1 -1
  435. package/dist/utils/mime.js.map +1 -1
  436. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  437. package/dist/utils/syntax-highlight.js +21 -21
  438. package/dist/utils/syntax-highlight.js.map +1 -1
  439. package/dist/utils/tool-result-images.d.ts +3 -1
  440. package/dist/utils/tool-result-images.d.ts.map +1 -1
  441. package/dist/utils/tool-result-images.js +4 -1
  442. package/dist/utils/tool-result-images.js.map +1 -1
  443. package/dist/utils/tools-manager.d.ts.map +1 -1
  444. package/dist/utils/tools-manager.js +11 -2
  445. package/dist/utils/tools-manager.js.map +1 -1
  446. package/dist/utils/wsl.d.ts +3 -0
  447. package/dist/utils/wsl.d.ts.map +1 -0
  448. package/dist/utils/wsl.js +15 -0
  449. package/dist/utils/wsl.js.map +1 -0
  450. package/dist/utils/zip.d.ts +7 -0
  451. package/dist/utils/zip.d.ts.map +1 -0
  452. package/dist/utils/zip.js +60 -0
  453. package/dist/utils/zip.js.map +1 -0
  454. package/docs/cli-integration.md +107 -0
  455. package/docs/cli.md +269 -0
  456. package/docs/compaction.md +73 -24
  457. package/docs/configuration.md +45 -0
  458. package/docs/containerization.md +22 -21
  459. package/docs/custom-provider.md +21 -12
  460. package/docs/development.md +19 -0
  461. package/docs/docs.json +139 -95
  462. package/docs/extensions.md +243 -371
  463. package/docs/how-pi-works.md +49 -0
  464. package/docs/images/interactive-mode.png +0 -0
  465. package/docs/index.md +3 -3
  466. package/docs/json.md +43 -3
  467. package/docs/keybindings.md +57 -54
  468. package/docs/llama-cpp.md +2 -2
  469. package/docs/message-types.md +261 -0
  470. package/docs/models.md +103 -49
  471. package/docs/packages.md +49 -47
  472. package/docs/prompt-templates.md +29 -56
  473. package/docs/providers.md +91 -139
  474. package/docs/quickstart.md +42 -14
  475. package/docs/rpc-commands.md +854 -0
  476. package/docs/rpc-extension-ui.md +200 -0
  477. package/docs/rpc.md +121 -223
  478. package/docs/sdk.md +99 -124
  479. package/docs/security.md +7 -7
  480. package/docs/session-format.md +85 -82
  481. package/docs/sessions.md +41 -57
  482. package/docs/settings.md +95 -88
  483. package/docs/shell-aliases.md +68 -3
  484. package/docs/skills.md +62 -49
  485. package/docs/slash-commands.md +60 -0
  486. package/docs/terminal-setup.md +86 -55
  487. package/docs/termux.md +65 -75
  488. package/docs/themes.md +64 -86
  489. package/docs/tmux.md +29 -7
  490. package/docs/tui.md +67 -122
  491. package/docs/usage.md +31 -42
  492. package/docs/windows.md +41 -13
  493. package/examples/README.md +16 -2
  494. package/examples/extensions/README.md +0 -1
  495. package/examples/extensions/custom-provider-anthropic/index.ts +18 -12
  496. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  497. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  498. package/examples/extensions/custom-provider-gitlab-duo/index.ts +2 -2
  499. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  500. package/examples/extensions/dynamic-resources/dynamic.json +2 -0
  501. package/examples/extensions/gondolin/package-lock.json +2 -2
  502. package/examples/extensions/gondolin/package.json +1 -1
  503. package/examples/extensions/prompt-customizer.ts +19 -67
  504. package/examples/extensions/sandbox/package-lock.json +2 -2
  505. package/examples/extensions/sandbox/package.json +1 -1
  506. package/examples/extensions/with-deps/package-lock.json +2 -2
  507. package/examples/extensions/with-deps/package.json +1 -1
  508. package/examples/plugins/pi-example-plugin/README.md +38 -0
  509. package/examples/plugins/pi-example-plugin/package.json +10 -0
  510. package/examples/plugins/pi-example-plugin/src/contract.ts +13 -0
  511. package/examples/plugins/pi-example-plugin/src/session.ts +24 -0
  512. package/examples/plugins/pi-example-plugin/src/tui.ts +31 -0
  513. package/examples/rpc-client.ts +35 -0
  514. package/examples/rpc-extension-ui.ts +25 -5
  515. package/examples/sdk/README.md +1 -1
  516. package/npm-shrinkwrap.json +861 -513
  517. package/package.json +27 -18
  518. package/dist/bun/register-bedrock.d.ts +0 -2
  519. package/dist/bun/register-bedrock.d.ts.map +0 -1
  520. package/dist/bun/register-bedrock.js +0 -4
  521. package/dist/bun/register-bedrock.js.map +0 -1
  522. package/dist/cli/experimental/auth.d.ts +0 -16
  523. package/dist/cli/experimental/auth.d.ts.map +0 -1
  524. package/dist/cli/experimental/auth.js +0 -13
  525. package/dist/cli/experimental/auth.js.map +0 -1
  526. package/dist/cli/experimental/cli.d.ts +0 -6
  527. package/dist/cli/experimental/cli.d.ts.map +0 -1
  528. package/dist/cli/experimental/cli.js +0 -5
  529. package/dist/cli/experimental/cli.js.map +0 -1
  530. package/dist/cli/experimental/command-options.d.ts +0 -17
  531. package/dist/cli/experimental/command-options.d.ts.map +0 -1
  532. package/dist/cli/experimental/command-options.js +0 -35
  533. package/dist/cli/experimental/command-options.js.map +0 -1
  534. package/dist/cli/experimental/command.d.ts +0 -63
  535. package/dist/cli/experimental/command.d.ts.map +0 -1
  536. package/dist/cli/experimental/command.js +0 -130
  537. package/dist/cli/experimental/command.js.map +0 -1
  538. package/dist/cli/experimental/commands/client.d.ts +0 -13
  539. package/dist/cli/experimental/commands/client.d.ts.map +0 -1
  540. package/dist/cli/experimental/commands/client.js +0 -25
  541. package/dist/cli/experimental/commands/client.js.map +0 -1
  542. package/dist/cli/experimental/commands/pi.d.ts +0 -15
  543. package/dist/cli/experimental/commands/pi.d.ts.map +0 -1
  544. package/dist/cli/experimental/commands/pi.js +0 -28
  545. package/dist/cli/experimental/commands/pi.js.map +0 -1
  546. package/dist/cli/experimental/commands/server.d.ts +0 -13
  547. package/dist/cli/experimental/commands/server.d.ts.map +0 -1
  548. package/dist/cli/experimental/commands/server.js +0 -25
  549. package/dist/cli/experimental/commands/server.js.map +0 -1
  550. package/dist/cli/experimental/transport-address.d.ts +0 -10
  551. package/dist/cli/experimental/transport-address.d.ts.map +0 -1
  552. package/dist/cli/experimental/transport-address.js +0 -38
  553. package/dist/cli/experimental/transport-address.js.map +0 -1
  554. package/dist/client/index.d.ts +0 -3
  555. package/dist/client/index.d.ts.map +0 -1
  556. package/dist/client/index.js +0 -3
  557. package/dist/client/index.js.map +0 -1
  558. package/dist/client/remote-session.d.ts +0 -53
  559. package/dist/client/remote-session.d.ts.map +0 -1
  560. package/dist/client/remote-session.js +0 -340
  561. package/dist/client/remote-session.js.map +0 -1
  562. package/dist/client/transcript.d.ts +0 -12
  563. package/dist/client/transcript.d.ts.map +0 -1
  564. package/dist/client/transcript.js +0 -98
  565. package/dist/client/transcript.js.map +0 -1
  566. package/dist/modes/interactive/components/message-spine.d.ts +0 -14
  567. package/dist/modes/interactive/components/message-spine.d.ts.map +0 -1
  568. package/dist/modes/interactive/components/message-spine.js +0 -19
  569. package/dist/modes/interactive/components/message-spine.js.map +0 -1
  570. package/dist/utils/clipboard-native.d.ts +0 -11
  571. package/dist/utils/clipboard-native.d.ts.map +0 -1
  572. package/dist/utils/clipboard-native.js +0 -20
  573. package/dist/utils/clipboard-native.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"delegate.js","sourceRoot":"","sources":["../../../src/core/tools/delegate.ts"],"names":[],"mappings":"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","sourcesContent":["import { Text } from \"@earendil-works/pi-tui\";\nimport type { AgentToolResult } from \"apex-code-agent-core\";\nimport { minimatch } from \"minimatch\";\nimport { type Static, Type } from \"typebox\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport type { DelegationRuntimeOptions } from \"../delegation/runtime.ts\";\nimport { retrieveDelegationResult, runDelegation } from \"../delegation/runtime.ts\";\nimport { type ApexToolDefinition, type EvidenceRecord, toolUnion } from \"./contract.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nconst workspaceSchema = Type.Object({\n\tisolation: Type.Union([Type.Literal(\"shared-read\"), Type.Literal(\"worktree\")], {\n\t\tdescription:\n\t\t\t'Child workspace isolation: \"shared-read\" runs in the parent checkout; \"worktree\" gives the child its own git worktree.',\n\t}),\n\townedPaths: Type.Optional(\n\t\tType.Array(Type.String(), {\n\t\t\tdescription:\n\t\t\t\t\"Workspace-relative paths the child owns for writes. Advisory claims; overlapping claims are refused.\",\n\t\t}),\n\t),\n});\n\nconst delegateSchemaProperties = {\n\tagentType: Type.String({\n\t\tdescription: \"The subagent type. Required both to launch a task and to retrieve a background result.\",\n\t}),\n\ttask: Type.String({ description: \"The task to delegate. Supply it to launch a delegation.\" }),\n\tworkspace: Type.Optional(\n\t\tType.Object(\n\t\t\t{\n\t\t\t\tisolation: workspaceSchema.properties.isolation,\n\t\t\t\townedPaths: workspaceSchema.properties.ownedPaths,\n\t\t\t},\n\t\t\t{ description: \"The child's requested workspace authority. Defaults to shared-read with no owned paths.\" },\n\t\t),\n\t),\n\tbackground: Type.Optional(\n\t\tType.Boolean({ description: \"Return a handle immediately instead of waiting for the child.\" }),\n\t),\n\thandle: Type.String({\n\t\tdescription: \"A background delegation handle returned by an earlier call. Supply it to retrieve the result.\",\n\t}),\n};\n\nconst delegateSchema = toolUnion(\n\t[\n\t\tType.Object({\n\t\t\tagentType: Type.String(),\n\t\t\ttask: Type.String(),\n\t\t\tworkspace: Type.Optional(workspaceSchema),\n\t\t\tbackground: Type.Optional(Type.Boolean()),\n\t\t}),\n\t\tType.Object({ agentType: Type.String(), handle: Type.String() }),\n\t],\n\tdelegateSchemaProperties,\n);\n\nexport type DelegateInput = Static<typeof delegateSchema>;\n\nexport interface DelegateDetails {\n\tagentType: string;\n\ttask: string;\n\toutput: string;\n\thandle?: string;\n}\n\nfunction formatDelegateCall(input: DelegateInput, theme: Theme): string {\n\tif (\"handle\" in input) {\n\t\treturn `${theme.fg(\"toolTitle\", theme.bold(\"delegate\"))} ${theme.fg(\"accent\", input.agentType)} · retrieve`;\n\t}\n\tconst task = input.task.replace(/\\s+/g, \" \").trim();\n\treturn `${theme.fg(\"toolTitle\", theme.bold(\"delegate\"))} ${theme.fg(\"accent\", input.agentType)} · ${theme.fg(\"toolOutput\", task)}`;\n}\n\nfunction formatDelegateResult(details: DelegateDetails, expanded: boolean, theme: Theme): string {\n\tif (expanded) return theme.fg(\"toolOutput\", details.output);\n\tconst lineCount = details.output ? details.output.split(\"\\n\").length : 0;\n\treturn `${theme.fg(\"accent\", details.agentType)} · ${lineCount} ${lineCount === 1 ? \"line\" : \"lines\"}`;\n}\n\n/**\n * The delegation entry point (task 4.6's contract, task 5.2's execution). Runs a\n * real child through the injected `DelegationRuntimeOptions` -- capability ceiling,\n * derived permission store, and child-session construction all live behind that\n * injection (ADR 0008), matching the `todo_write`/`tool_schema` convention of\n * injecting collaborators rather than reaching for global state. Recursion\n * depth, artifact isolation, and real agent discovery are wired:\n * `../delegation/runtime.ts` bounds depth and roots per-child artifact\n * directories, and `../delegation/agents.ts` supplies production markdown\n * discovery through the injected resolver.\n */\nexport function createDelegateToolDefinition(\n\truntime: DelegationRuntimeOptions,\n): ApexToolDefinition<typeof delegateSchema, DelegateDetails> {\n\treturn {\n\t\tname: \"delegate\",\n\t\tlabel: \"delegate\",\n\t\tdescription: \"Delegate a task to a subagent.\",\n\t\tparameters: delegateSchema,\n\t\tcontract: {\n\t\t\tcapabilities: new Set([\"delegate\"]),\n\t\t\tpermission: {\n\t\t\t\tdefaultBehavior: \"ask\",\n\t\t\t\tmatches: (ruleContent, params) => minimatch(params.agentType, ruleContent),\n\t\t\t\tdescribe: (ruleContent) => `Delegate to agent types matching \"${ruleContent}\"`,\n\t\t\t\truleForCall: (params) => params.agentType,\n\t\t\t},\n\t\t\tcontext: { resultRecoverable: false, deferSchema: true },\n\t\t\tevidence: {\n\t\t\t\temits: new Set([\"workflow\"]),\n\t\t\t\t// capture runs in afterToolCall with the completed result, so a launch\n\t\t\t\t// can carry its handle even though the params could not know it: the\n\t\t\t\t// handle is the child's session id, which names the child's session\n\t\t\t\t// file and artifact dir under the parent's delegations/. This reuses\n\t\t\t\t// the existing WorkflowEvidenceRecord.handle field -- no contract or\n\t\t\t\t// sink shape change (the per-child session linkage is the evidence\n\t\t\t\t// model; see docs/plans/2026-09-09-run-and-child-session-architecture.md).\n\t\t\t\tcapture: (params, result): EvidenceRecord[] =>\n\t\t\t\t\t\"task\" in params\n\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tkind: \"workflow\",\n\t\t\t\t\t\t\t\t\tagentType: params.agentType,\n\t\t\t\t\t\t\t\t\ttask: params.task,\n\t\t\t\t\t\t\t\t\thandle: result.details.handle,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t: [{ kind: \"workflow\", agentType: params.agentType, handle: params.handle }],\n\t\t\t},\n\t\t},\n\t\tasync execute(_toolCallId, input: DelegateInput): Promise<AgentToolResult<DelegateDetails>> {\n\t\t\tconst workspace =\n\t\t\t\t\"task\" in input && input.workspace\n\t\t\t\t\t? { isolation: input.workspace.isolation, ownedPaths: input.workspace.ownedPaths ?? [] }\n\t\t\t\t\t: undefined;\n\t\t\tconst result =\n\t\t\t\t\"task\" in input\n\t\t\t\t\t? await runDelegation(runtime, input.agentType, input.task, { background: input.background, workspace })\n\t\t\t\t\t: await retrieveDelegationResult(runtime, input.handle, input.agentType);\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: result.output }],\n\t\t\t\tdetails: {\n\t\t\t\t\tagentType: result.agentType,\n\t\t\t\t\ttask: result.task,\n\t\t\t\t\toutput: result.output,\n\t\t\t\t\thandle: result.handleId,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\trenderCall(input, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatDelegateCall(input, theme));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatDelegateResult(result.details, options.expanded, theme));\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createDelegateTool(runtime: DelegationRuntimeOptions) {\n\treturn wrapToolDefinition(createDelegateToolDefinition(runtime));\n}\n"]}
1
+ {"version":3,"file":"delegate.js","sourceRoot":"","sources":["../../../src/core/tools/delegate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,wDAAwD,CAAC;AAG3F,OAAO,EAAE,wBAAwB,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACnF,OAAO,EAAgD,SAAS,EAAE,MAAM,eAAe,CAAC;AACxF,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAElE,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC;IACnC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,EAAE;QAC9E,WAAW,EACV,wHAAwH;KACzH,CAAC;IACF,UAAU,EAAE,IAAI,CAAC,QAAQ,CACxB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE;QACzB,WAAW,EACV,sGAAsG;KACvG,CAAC,CACF;CACD,CAAC,CAAC;AAEH,MAAM,wBAAwB,GAAG;IAChC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC;QACtB,WAAW,EAAE,wFAAwF;KACrG,CAAC;IACF,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,yDAAyD,EAAE,CAAC;IAC7F,SAAS,EAAE,IAAI,CAAC,QAAQ,CACvB,IAAI,CAAC,MAAM,CACV;QACC,SAAS,EAAE,eAAe,CAAC,UAAU,CAAC,SAAS;QAC/C,UAAU,EAAE,eAAe,CAAC,UAAU,CAAC,UAAU;KACjD,EACD,EAAE,WAAW,EAAE,yFAAyF,EAAE,CAC1G,CACD;IACD,UAAU,EAAE,IAAI,CAAC,QAAQ,CACxB,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,+DAA+D,EAAE,CAAC,CAC9F;IACD,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;QACnB,WAAW,EAAE,+FAA+F;KAC5G,CAAC;CACF,CAAC;AAEF,MAAM,cAAc,GAAG,SAAS,CAC/B;IACC,IAAI,CAAC,MAAM,CAAC;QACX,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE;QACxB,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE;QACnB,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC;QACzC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;KACzC,CAAC;IACF,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;CAChE,EACD,wBAAwB,CACxB,CAAC;AAWF,SAAS,kBAAkB,CAAC,KAAoB,EAAE,KAAY,EAAU;IACvE,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC;QACvB,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,cAAa,CAAC;IAC7G,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACpD,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,OAAM,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,IAAI,CAAC,EAAE,CAAC;AAAA,CACnI;AAED,SAAS,oBAAoB,CAAC,OAAwB,EAAE,QAAiB,EAAE,KAAY,EAAU;IAChG,IAAI,QAAQ;QAAE,OAAO,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5D,OAAO,iBAAiB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AAAA,CACxF;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,4BAA4B,CAC3C,OAAiC,EAC4B;IAC7D,OAAO;QACN,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,UAAU;QACjB,WAAW,EAAE,gCAAgC;QAC7C,UAAU,EAAE,cAAc;QAC1B,QAAQ,EAAE;YACT,YAAY,EAAE,IAAI,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;YACnC,UAAU,EAAE;gBACX,eAAe,EAAE,KAAK;gBACtB,OAAO,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC;gBAC1E,QAAQ,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,qCAAqC,WAAW,GAAG;gBAC9E,WAAW,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS;aACzC;YACD,OAAO,EAAE,EAAE,iBAAiB,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE;YACxD,QAAQ,EAAE;gBACT,KAAK,EAAE,IAAI,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;gBAC5B,uEAAuE;gBACvE,qEAAqE;gBACrE,oEAAoE;gBACpE,qEAAqE;gBACrE,qEAAqE;gBACrE,mEAAmE;gBACnE,2EAA2E;gBAC3E,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAoB,EAAE,CAC7C,MAAM,IAAI,MAAM;oBACf,CAAC,CAAC;wBACA;4BACC,IAAI,EAAE,UAAU;4BAChB,SAAS,EAAE,MAAM,CAAC,SAAS;4BAC3B,IAAI,EAAE,MAAM,CAAC,IAAI;4BACjB,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM;yBAC7B;qBACD;oBACF,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;aAC9E;SACD;QACD,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,KAAoB,EAA6C;YAC3F,MAAM,SAAS,GACd,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,SAAS;gBACjC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC,UAAU,IAAI,EAAE,EAAE;gBACxF,CAAC,CAAC,SAAS,CAAC;YACd,MAAM,MAAM,GACX,MAAM,IAAI,KAAK;gBACd,CAAC,CAAC,MAAM,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,SAAS,EAAE,CAAC;gBACxG,CAAC,CAAC,MAAM,wBAAwB,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;YAC3E,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;gBAChD,OAAO,EAAE;oBACR,SAAS,EAAE,MAAM,CAAC,SAAS;oBAC3B,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,MAAM,EAAE,MAAM,CAAC,QAAQ;iBACvB;aACD,CAAC;QAAA,CACF;QACD,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE;YACjC,MAAM,IAAI,GAAI,OAAO,CAAC,aAAkC,IAAI,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC/E,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;YAC/C,OAAO,IAAI,CAAC;QAAA,CACZ;QACD,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;YAC7C,MAAM,IAAI,GAAI,OAAO,CAAC,aAAkC,IAAI,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC/E,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;YAC5E,OAAO,IAAI,CAAC;QAAA,CACZ;KACD,CAAC;AAAA,CACF;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAiC,EAAE;IACrE,OAAO,kBAAkB,CAAC,4BAA4B,CAAC,OAAO,CAAC,CAAC,CAAC;AAAA,CACjE","sourcesContent":["import { Text } from \"@earendil-works/pi-tui\";\nimport type { AgentToolResult } from \"apex-code-agent-core\";\nimport { minimatch } from \"minimatch\";\nimport { type Static, Type } from \"typebox\";\nimport { formatHiddenLines } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport type { DelegationRuntimeOptions } from \"../delegation/runtime.ts\";\nimport { retrieveDelegationResult, runDelegation } from \"../delegation/runtime.ts\";\nimport { type ApexToolDefinition, type EvidenceRecord, toolUnion } from \"./contract.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nconst workspaceSchema = Type.Object({\n\tisolation: Type.Union([Type.Literal(\"shared-read\"), Type.Literal(\"worktree\")], {\n\t\tdescription:\n\t\t\t'Child workspace isolation: \"shared-read\" runs in the parent checkout; \"worktree\" gives the child its own git worktree.',\n\t}),\n\townedPaths: Type.Optional(\n\t\tType.Array(Type.String(), {\n\t\t\tdescription:\n\t\t\t\t\"Workspace-relative paths the child owns for writes. Advisory claims; overlapping claims are refused.\",\n\t\t}),\n\t),\n});\n\nconst delegateSchemaProperties = {\n\tagentType: Type.String({\n\t\tdescription: \"The subagent type. Required both to launch a task and to retrieve a background result.\",\n\t}),\n\ttask: Type.String({ description: \"The task to delegate. Supply it to launch a delegation.\" }),\n\tworkspace: Type.Optional(\n\t\tType.Object(\n\t\t\t{\n\t\t\t\tisolation: workspaceSchema.properties.isolation,\n\t\t\t\townedPaths: workspaceSchema.properties.ownedPaths,\n\t\t\t},\n\t\t\t{ description: \"The child's requested workspace authority. Defaults to shared-read with no owned paths.\" },\n\t\t),\n\t),\n\tbackground: Type.Optional(\n\t\tType.Boolean({ description: \"Return a handle immediately instead of waiting for the child.\" }),\n\t),\n\thandle: Type.String({\n\t\tdescription: \"A background delegation handle returned by an earlier call. Supply it to retrieve the result.\",\n\t}),\n};\n\nconst delegateSchema = toolUnion(\n\t[\n\t\tType.Object({\n\t\t\tagentType: Type.String(),\n\t\t\ttask: Type.String(),\n\t\t\tworkspace: Type.Optional(workspaceSchema),\n\t\t\tbackground: Type.Optional(Type.Boolean()),\n\t\t}),\n\t\tType.Object({ agentType: Type.String(), handle: Type.String() }),\n\t],\n\tdelegateSchemaProperties,\n);\n\nexport type DelegateInput = Static<typeof delegateSchema>;\n\nexport interface DelegateDetails {\n\tagentType: string;\n\ttask: string;\n\toutput: string;\n\thandle?: string;\n}\n\nfunction formatDelegateCall(input: DelegateInput, theme: Theme): string {\n\tif (\"handle\" in input) {\n\t\treturn `${theme.fg(\"toolTitle\", theme.bold(\"delegate\"))} ${theme.fg(\"accent\", input.agentType)} · retrieve`;\n\t}\n\tconst task = input.task.replace(/\\s+/g, \" \").trim();\n\treturn `${theme.fg(\"toolTitle\", theme.bold(\"delegate\"))} ${theme.fg(\"accent\", input.agentType)} · ${theme.fg(\"toolOutput\", task)}`;\n}\n\nfunction formatDelegateResult(details: DelegateDetails, expanded: boolean, theme: Theme): string {\n\tif (expanded) return theme.fg(\"toolOutput\", details.output);\n\treturn formatHiddenLines(details.output ? details.output.split(\"\\n\").length : 0, \"all\");\n}\n\n/**\n * The delegation entry point (task 4.6's contract, task 5.2's execution). Runs a\n * real child through the injected `DelegationRuntimeOptions` -- capability ceiling,\n * derived permission store, and child-session construction all live behind that\n * injection (ADR 0008), matching the `todo_write`/`tool_schema` convention of\n * injecting collaborators rather than reaching for global state. Recursion\n * depth, artifact isolation, and real agent discovery are wired:\n * `../delegation/runtime.ts` bounds depth and roots per-child artifact\n * directories, and `../delegation/agents.ts` supplies production markdown\n * discovery through the injected resolver.\n */\nexport function createDelegateToolDefinition(\n\truntime: DelegationRuntimeOptions,\n): ApexToolDefinition<typeof delegateSchema, DelegateDetails> {\n\treturn {\n\t\tname: \"delegate\",\n\t\tlabel: \"delegate\",\n\t\tdescription: \"Delegate a task to a subagent.\",\n\t\tparameters: delegateSchema,\n\t\tcontract: {\n\t\t\tcapabilities: new Set([\"delegate\"]),\n\t\t\tpermission: {\n\t\t\t\tdefaultBehavior: \"ask\",\n\t\t\t\tmatches: (ruleContent, params) => minimatch(params.agentType, ruleContent),\n\t\t\t\tdescribe: (ruleContent) => `Delegate to agent types matching \"${ruleContent}\"`,\n\t\t\t\truleForCall: (params) => params.agentType,\n\t\t\t},\n\t\t\tcontext: { resultRecoverable: false, deferSchema: true },\n\t\t\tevidence: {\n\t\t\t\temits: new Set([\"workflow\"]),\n\t\t\t\t// capture runs in afterToolCall with the completed result, so a launch\n\t\t\t\t// can carry its handle even though the params could not know it: the\n\t\t\t\t// handle is the child's session id, which names the child's session\n\t\t\t\t// file and artifact dir under the parent's delegations/. This reuses\n\t\t\t\t// the existing WorkflowEvidenceRecord.handle field -- no contract or\n\t\t\t\t// sink shape change (the per-child session linkage is the evidence\n\t\t\t\t// model; see docs/plans/2026-09-09-run-and-child-session-architecture.md).\n\t\t\t\tcapture: (params, result): EvidenceRecord[] =>\n\t\t\t\t\t\"task\" in params\n\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tkind: \"workflow\",\n\t\t\t\t\t\t\t\t\tagentType: params.agentType,\n\t\t\t\t\t\t\t\t\ttask: params.task,\n\t\t\t\t\t\t\t\t\thandle: result.details.handle,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t: [{ kind: \"workflow\", agentType: params.agentType, handle: params.handle }],\n\t\t\t},\n\t\t},\n\t\tasync execute(_toolCallId, input: DelegateInput): Promise<AgentToolResult<DelegateDetails>> {\n\t\t\tconst workspace =\n\t\t\t\t\"task\" in input && input.workspace\n\t\t\t\t\t? { isolation: input.workspace.isolation, ownedPaths: input.workspace.ownedPaths ?? [] }\n\t\t\t\t\t: undefined;\n\t\t\tconst result =\n\t\t\t\t\"task\" in input\n\t\t\t\t\t? await runDelegation(runtime, input.agentType, input.task, { background: input.background, workspace })\n\t\t\t\t\t: await retrieveDelegationResult(runtime, input.handle, input.agentType);\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: result.output }],\n\t\t\t\tdetails: {\n\t\t\t\t\tagentType: result.agentType,\n\t\t\t\t\ttask: result.task,\n\t\t\t\t\toutput: result.output,\n\t\t\t\t\thandle: result.handleId,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\trenderCall(input, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatDelegateCall(input, theme));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatDelegateResult(result.details, options.expanded, theme));\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createDelegateTool(runtime: DelegationRuntimeOptions) {\n\treturn wrapToolDefinition(createDelegateToolDefinition(runtime));\n}\n"]}
@@ -1,14 +1,9 @@
1
- import { Box } from "@earendil-works/pi-tui";
2
1
  import type { AgentTool } from "apex-code-agent-core";
3
2
  import { type Static, Type } from "typebox";
4
3
  import { type PreparedPathOperation } from "../permissions/operations.ts";
5
4
  import type { ApexToolDefinition } from "./contract.ts";
6
5
  import type { DiagnosticsOperations, DiagnosticsOutcome } from "./diagnostics.ts";
7
- import { type EditDiffError, type EditDiffResult } from "./edit-diff.ts";
8
- type EditPreview = EditDiffResult | EditDiffError;
9
- type EditRenderState = {
10
- callComponent?: EditCallRenderComponent;
11
- };
6
+ import { type EditRenderState } from "./renderers/edit.ts";
12
7
  declare const editSchema: Type.TObject<{
13
8
  path: Type.TString;
14
9
  edits: Type.TArray<Type.TObject<{
@@ -61,12 +56,6 @@ export interface EditToolOptions {
61
56
  */
62
57
  diagnosticsOperations?: DiagnosticsOperations;
63
58
  }
64
- type EditCallRenderComponent = Box & {
65
- preview?: EditPreview;
66
- previewArgsKey?: string;
67
- previewPending?: boolean;
68
- settledError?: boolean;
69
- };
70
59
  export declare function createEditToolDefinition(cwd: string, options?: EditToolOptions): ApexToolDefinition<typeof editSchema, EditToolDetails | undefined, EditRenderState>;
71
60
  export declare function createEditTool(cwd: string, options?: EditToolOptions): AgentTool<typeof editSchema>;
72
61
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../../src/core/tools/edit.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAA2B,MAAM,wBAAwB,CAAC;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAK5C,OAAO,EAA4B,KAAK,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAEpG,OAAO,KAAK,EAAE,kBAAkB,EAAkB,MAAM,eAAe,CAAC;AACxE,OAAO,KAAK,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAElF,OAAO,EAMN,KAAK,aAAa,EAClB,KAAK,cAAc,EAKnB,MAAM,gBAAgB,CAAC;AAOxB,KAAK,WAAW,GAAG,cAAc,GAAG,aAAa,CAAC;AAElD,KAAK,eAAe,GAAG;IACtB,aAAa,CAAC,EAAE,uBAAuB,CAAC;CACxC,CAAC;AAaF,QAAA,MAAM,UAAU;;;;;;EASf,CAAC;AAEF,eAAO,MAAM,gCAAgC;;;CAQnC,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAqBtD,MAAM,WAAW,eAAe;IAC/B,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uFAAuF;IACvF,WAAW,CAAC,EAAE,kBAAkB,CAAC;CACjC;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,qCAAqC;IACrC,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,8BAA8B;IAC9B,SAAS,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,4DAA4D;IAC5D,MAAM,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,qBAAqB,KAAK,MAAM,CAAC;IAChE,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,qBAAqB,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAChF;AAUD,MAAM,WAAW,eAAe;IAC/B,oEAAoE;IACpE,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;CAC9C;AA2FD,KAAK,uBAAuB,GAAG,GAAG,GAAG;IACpC,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAoLF,wBAAgB,wBAAwB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,eAAe,GACvB,kBAAkB,CAAC,OAAO,UAAU,EAAE,eAAe,GAAG,SAAS,EAAE,eAAe,CAAC,CAqLrF;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAEnG","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { Box, Container, Spacer, Text } from \"@earendil-works/pi-tui\";\nimport type { AgentTool } from \"apex-code-agent-core\";\nimport { constants } from \"fs\";\nimport { access as fsAccess, readFile as fsReadFile } from \"fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport { renderDiff } from \"../../modes/interactive/components/diff.ts\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { splitBom } from \"../../utils/text.ts\";\nimport { getExperimentalToolSampling } from \"../experimental.ts\";\nimport { getPreparedPathOperation, type PreparedPathOperation } from \"../permissions/operations.ts\";\nimport type { PermissionPreview } from \"../permissions/responder.ts\";\nimport type { ApexToolDefinition, EvidenceRecord } from \"./contract.ts\";\nimport type { DiagnosticsOperations, DiagnosticsOutcome } from \"./diagnostics.ts\";\nimport { diagnosticEvidenceForPath, formatDiagnosticsOutcome } from \"./diagnostics.ts\";\nimport {\n\tapplyEditsToNormalizedContent,\n\tcomputeEditsDiff,\n\tcomputeEditsDiffFromContent,\n\tdetectLineEnding,\n\ttype Edit,\n\ttype EditDiffError,\n\ttype EditDiffResult,\n\tgenerateDiffString,\n\tgenerateUnifiedPatch,\n\tnormalizeToLF,\n\trestoreLineEndings,\n} from \"./edit-diff.ts\";\nimport { withFileMutationQueue } from \"./file-mutation-queue.ts\";\nimport { createPathPermissionSpec } from \"./path-permission.ts\";\nimport { readPreparedPath, resolveToCwd, writePathAtomically, writePreparedPath } from \"./path-utils.ts\";\nimport { renderToolPath, str } from \"./render-utils.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\ntype EditPreview = EditDiffResult | EditDiffError;\n\ntype EditRenderState = {\n\tcallComponent?: EditCallRenderComponent;\n};\n\nconst replaceEditSchema = Type.Object(\n\t{\n\t\toldText: Type.String({\n\t\t\tdescription:\n\t\t\t\t\"Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call.\",\n\t\t}),\n\t\tnewText: Type.String({ description: \"Replacement text for this targeted edit.\" }),\n\t},\n\t{},\n);\n\nconst editSchema = Type.Object(\n\t{\n\t\tpath: Type.String({ description: \"Path to the file to edit (relative or absolute)\" }),\n\t\tedits: Type.Array(replaceEditSchema, {\n\t\t\tdescription:\n\t\t\t\t\"One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead.\",\n\t\t}),\n\t},\n\t{},\n);\n\nexport const editToolSystemPromptContribution = {\n\tsnippet: \"Make precise file edits with exact text replacement, including multiple disjoint edits in one call\",\n\tguidelines: [\n\t\t\"Use edit for precise changes (edits[].oldText must match exactly)\",\n\t\t\"When changing multiple separate locations in one file, use one edit call with multiple entries in edits[] instead of multiple edit calls\",\n\t\t\"Each edits[].oldText is matched against the original file, not after earlier edits are applied. Do not emit overlapping or nested edits. Merge nearby changes into one edit.\",\n\t\t\"Keep edits[].oldText as small as possible while still being unique in the file. Do not pad with large unchanged regions.\",\n\t],\n} as const;\n\nexport type EditToolInput = Static<typeof editSchema>;\ntype LegacyEditToolInput = EditToolInput & {\n\toldText?: unknown;\n\tnewText?: unknown;\n};\n\nfunction sha256(value: string): string {\n\treturn createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\ntype SingleEditInput = { oldText: string; newText: string };\n\nfunction isSingleEditInput(value: unknown): value is SingleEditInput {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\treturn false;\n\t}\n\n\tconst edit = value as Record<string, unknown>;\n\treturn typeof edit.oldText === \"string\" && typeof edit.newText === \"string\";\n}\n\nexport interface EditToolDetails {\n\t/** Display-oriented diff of the changes made */\n\tdiff: string;\n\t/** Standard unified patch of the changes made */\n\tpatch: string;\n\t/** Line number of the first change in the new file (for editor navigation) */\n\tfirstChangedLine?: number;\n\t/** Present only when `EditToolOptions.diagnosticsOperations` is configured (LSP.4). */\n\tdiagnostics?: DiagnosticsOutcome;\n}\n\n/**\n * Pluggable operations for the edit tool.\n * Override these to delegate file editing to remote systems (for example SSH).\n */\nexport interface EditOperations {\n\t/** Read file contents as a Buffer */\n\treadFile: (absolutePath: string) => Promise<Buffer>;\n\t/** Write content to a file */\n\twriteFile: (absolutePath: string, content: string) => Promise<void>;\n\t/** Check if file is readable and writable (throw if not) */\n\taccess: (absolutePath: string) => Promise<void>;\n\t/**\n\t * Execute a gate-prepared edit no-follow against the authorized target.\n\t * Required for gated calls: when a prepared operation exists, pathname reads\n\t * and writes are never used, so an unset implementation fails closed.\n\t */\n\treadPreparedFile?: (operation: PreparedPathOperation) => Buffer;\n\twritePreparedFile?: (operation: PreparedPathOperation, content: Buffer) => void;\n}\n\nconst defaultEditOperations: EditOperations = {\n\treadFile: (path) => fsReadFile(path),\n\twriteFile: async (path, content) => writePathAtomically(path, content),\n\taccess: (path) => fsAccess(path, constants.R_OK | constants.W_OK),\n\treadPreparedFile: (operation) => readPreparedPath(operation),\n\twritePreparedFile: (operation, content) => writePreparedPath(operation, content),\n};\n\nexport interface EditToolOptions {\n\t/** Custom operations for file editing. Default: local filesystem */\n\toperations?: EditOperations;\n\t/**\n\t * Optional post-mutation diagnostics (LSP.4). Absent by default -- byte-identical\n\t * existing behavior. When present, called inside `withFileMutationQueue` after the\n\t * write succeeds and before the queue releases, matching `TestOperations`/\n\t * `GrepOperations`' injection pattern (`test.ts:28`, `grep.ts:58`).\n\t */\n\tdiagnosticsOperations?: DiagnosticsOperations;\n}\n\n/** A preview is a courtesy, so it never costs more than a screen or two of reading. */\nconst PREVIEW_MAX_BYTES = 512 * 1024;\nconst PREVIEW_MAX_LINES = 40;\n\n/**\n * Describe the edit for the person deciding whether to allow it.\n *\n * Reads through the operation `prepareCall` stored rather than resolving the\n * pathname again, so a target swapped after authorization fails here exactly as\n * it fails the write. `readPreparedPath` throws in that case and the gate turns\n * the throw into a stated reason, which is the outcome a reader needs: better a\n * prompt that admits it cannot show the change than a diff of the wrong file.\n */\nfunction previewEdit(params: EditToolInput): PermissionPreview {\n\tconst prepared = getPreparedPathOperation(params);\n\tif (!prepared) return { kind: \"unavailable\", reason: \"No authorized target was prepared for this call\" };\n\tif (prepared.kind === \"path-new\") {\n\t\treturn { kind: \"summary\", lines: [`Create ${params.path}`] };\n\t}\n\n\tconst buffer = readPreparedPath(prepared, PREVIEW_MAX_BYTES + 1);\n\tif (buffer.byteLength > PREVIEW_MAX_BYTES) {\n\t\treturn { kind: \"unavailable\", reason: `File is larger than ${PREVIEW_MAX_BYTES / 1024}KB, so no diff is shown` };\n\t}\n\tif (buffer.includes(0)) {\n\t\treturn { kind: \"unavailable\", reason: \"File is binary, so there is no diff to show\" };\n\t}\n\n\tconst result = computeEditsDiffFromContent(params.path, buffer.toString(\"utf-8\"), params.edits as Edit[]);\n\tif (\"error\" in result) return { kind: \"unavailable\", reason: result.error };\n\n\tconst lines = result.diff.split(\"\\n\");\n\tconst shown = lines.slice(0, PREVIEW_MAX_LINES);\n\treturn { kind: \"diff\", path: params.path, lines: shown, omittedLines: lines.length - shown.length };\n}\n\nfunction prepareEditArguments(input: unknown): EditToolInput {\n\tif (!input || typeof input !== \"object\") {\n\t\treturn input as EditToolInput;\n\t}\n\n\tconst args = input as Record<string, unknown>;\n\n\t// Some models (Opus 4.6, GLM-5.1) send edits as a JSON string instead of an array.\n\t// Others send a single edit object instead of a one-element edits array.\n\tif (typeof args.edits === \"string\") {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(args.edits);\n\t\t\tif (Array.isArray(parsed)) {\n\t\t\t\targs.edits = parsed;\n\t\t\t} else if (isSingleEditInput(parsed)) {\n\t\t\t\targs.edits = [parsed];\n\t\t\t}\n\t\t} catch {}\n\t} else if (isSingleEditInput(args.edits)) {\n\t\targs.edits = [args.edits];\n\t}\n\n\tconst legacy = args as LegacyEditToolInput;\n\tif (typeof legacy.oldText !== \"string\" || typeof legacy.newText !== \"string\") {\n\t\treturn args as EditToolInput;\n\t}\n\n\tconst edits = Array.isArray(legacy.edits) ? [...legacy.edits] : [];\n\tedits.push({ oldText: legacy.oldText, newText: legacy.newText });\n\tconst { oldText: _oldText, newText: _newText, ...rest } = legacy;\n\treturn { ...rest, edits } as EditToolInput;\n}\n\nfunction validateEditInput(input: EditToolInput): { path: string; edits: Edit[] } {\n\tif (!Array.isArray(input.edits) || input.edits.length === 0) {\n\t\tthrow new Error(\"Edit tool input is invalid. edits must contain at least one replacement.\");\n\t}\n\treturn { path: input.path, edits: input.edits };\n}\n\ntype RenderableEditArgs = {\n\tpath?: string;\n\tfile_path?: string;\n\tedits?: Edit[];\n\toldText?: string;\n\tnewText?: string;\n};\n\ntype EditToolResultLike = {\n\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\tdetails?: EditToolDetails;\n};\n\ntype EditCallRenderComponent = Box & {\n\tpreview?: EditPreview;\n\tpreviewArgsKey?: string;\n\tpreviewPending?: boolean;\n\tsettledError?: boolean;\n};\n\nfunction createEditCallRenderComponent(): EditCallRenderComponent {\n\treturn Object.assign(new Box(1, 1, (text: string) => text), {\n\t\tpreview: undefined as EditPreview | undefined,\n\t\tpreviewArgsKey: undefined as string | undefined,\n\t\tpreviewPending: false,\n\t\tsettledError: false,\n\t});\n}\n\nfunction getEditCallRenderComponent(state: EditRenderState, lastComponent: unknown): EditCallRenderComponent {\n\tif (lastComponent instanceof Box) {\n\t\tconst component = lastComponent as EditCallRenderComponent;\n\t\tstate.callComponent = component;\n\t\treturn component;\n\t}\n\tif (state.callComponent) {\n\t\treturn state.callComponent;\n\t}\n\tconst component = createEditCallRenderComponent();\n\tstate.callComponent = component;\n\treturn component;\n}\n\nfunction getRenderablePreviewInput(args: RenderableEditArgs | undefined): { path: string; edits: Edit[] } | null {\n\tif (!args) {\n\t\treturn null;\n\t}\n\n\tconst path = typeof args.path === \"string\" ? args.path : typeof args.file_path === \"string\" ? args.file_path : null;\n\tif (!path) {\n\t\treturn null;\n\t}\n\n\tif (\n\t\tArray.isArray(args.edits) &&\n\t\targs.edits.length > 0 &&\n\t\targs.edits.every((edit) => typeof edit?.oldText === \"string\" && typeof edit?.newText === \"string\")\n\t) {\n\t\treturn { path, edits: args.edits };\n\t}\n\n\tif (typeof args.oldText === \"string\" && typeof args.newText === \"string\") {\n\t\treturn { path, edits: [{ oldText: args.oldText, newText: args.newText }] };\n\t}\n\n\treturn null;\n}\n\n/**\n * Added and removed line counts read off a unified diff.\n *\n * `+++`/`---` file headers open with the same characters as content lines, so\n * they are skipped explicitly rather than by counting the first two lines,\n * which a diff without headers would not have.\n */\nfunction countChangedLines(diff: string): { added: number; removed: number } {\n\tlet added = 0;\n\tlet removed = 0;\n\tfor (const line of diff.split(\"\\n\")) {\n\t\tif (line.startsWith(\"+++\") || line.startsWith(\"---\")) continue;\n\t\tif (line.startsWith(\"+\")) added++;\n\t\telse if (line.startsWith(\"-\")) removed++;\n\t}\n\treturn { added, removed };\n}\n\n/** The one line a collapsed diff leaves behind, so the edit is still legible as an edit. */\nfunction formatChangeSummary(diff: string, theme: Theme): string {\n\tconst { added, removed } = countChangedLines(diff);\n\tconst parts: string[] = [];\n\tif (added > 0) parts.push(theme.fg(\"toolDiffAdded\", `+${added}`));\n\tif (removed > 0) parts.push(theme.fg(\"toolDiffRemoved\", `-${removed}`));\n\tif (parts.length === 0) return theme.fg(\"dim\", \"no line changes\");\n\treturn parts.join(theme.fg(\"dim\", \" \"));\n}\n\nfunction formatEditCall(args: RenderableEditArgs | undefined, theme: Theme, cwd: string): string {\n\tconst pathDisplay = renderToolPath(str(args?.file_path ?? args?.path), theme, cwd);\n\treturn `${theme.fg(\"toolTitle\", theme.bold(\"edit\"))} ${pathDisplay}`;\n}\n\nfunction formatEditResult(\n\targs: RenderableEditArgs | undefined,\n\tpreview: EditPreview | undefined,\n\tresult: EditToolResultLike,\n\ttheme: Theme,\n\tisError: boolean,\n\tdiffsExpanded: boolean,\n): string | undefined {\n\tconst rawPath = str(args?.file_path ?? args?.path);\n\tconst previewDiff = preview && !(\"error\" in preview) ? preview.diff : undefined;\n\tconst previewError = preview && \"error\" in preview ? preview.error : undefined;\n\tif (isError) {\n\t\tconst errorText = result.content\n\t\t\t.filter((c) => c.type === \"text\")\n\t\t\t.map((c) => c.text || \"\")\n\t\t\t.join(\"\\n\");\n\t\tif (!errorText || errorText === previewError) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn theme.fg(\"error\", errorText);\n\t}\n\n\tconst resultDiff = result.details?.diff;\n\tif (resultDiff && resultDiff !== previewDiff) {\n\t\treturn diffsExpanded\n\t\t\t? renderDiff(resultDiff, { filePath: rawPath ?? undefined })\n\t\t\t: formatChangeSummary(resultDiff, theme);\n\t}\n\n\treturn undefined;\n}\n\nfunction getEditHeaderBg(\n\tpreview: EditPreview | undefined,\n\tsettledError: boolean | undefined,\n\ttheme: Theme,\n): (text: string) => string {\n\tif (preview) {\n\t\tif (\"error\" in preview) {\n\t\t\treturn (text: string) => theme.bg(\"toolErrorBg\", text);\n\t\t}\n\t\treturn (text: string) => theme.bg(\"toolSuccessBg\", text);\n\t}\n\tif (settledError) {\n\t\treturn (text: string) => theme.bg(\"toolErrorBg\", text);\n\t}\n\treturn (text: string) => theme.bg(\"toolPendingBg\", text);\n}\n\nfunction buildEditCallComponent(\n\tcomponent: EditCallRenderComponent,\n\targs: RenderableEditArgs | undefined,\n\ttheme: Theme,\n\tcwd: string,\n\tdiffsExpanded: boolean,\n): EditCallRenderComponent {\n\tcomponent.setBgFn(getEditHeaderBg(component.preview, component.settledError, theme));\n\tcomponent.clear();\n\tcomponent.addChild(new Text(formatEditCall(args, theme, cwd), 0, 0));\n\n\tif (!component.preview) {\n\t\treturn component;\n\t}\n\n\t// An error always shows, whatever the detail level. A collapsed diff still\n\t// leaves its counts behind, so the row never becomes a bare filename.\n\tconst body =\n\t\t\"error\" in component.preview\n\t\t\t? theme.fg(\"error\", component.preview.error)\n\t\t\t: diffsExpanded\n\t\t\t\t? renderDiff(component.preview.diff)\n\t\t\t\t: formatChangeSummary(component.preview.diff, theme);\n\tcomponent.addChild(new Spacer(1));\n\tcomponent.addChild(new Text(body, 0, 0));\n\treturn component;\n}\n\nfunction setEditPreview(\n\tcomponent: EditCallRenderComponent,\n\tpreview: EditPreview,\n\targsKey: string | undefined,\n): boolean {\n\tconst current = component.preview;\n\tconst changed =\n\t\tcurrent === undefined ||\n\t\t(\"error\" in current && \"error\" in preview\n\t\t\t? current.error !== preview.error\n\t\t\t: \"error\" in current !== \"error\" in preview) ||\n\t\t(!(\"error\" in current) &&\n\t\t\t!(\"error\" in preview) &&\n\t\t\t(current.diff !== preview.diff || current.firstChangedLine !== preview.firstChangedLine));\n\tcomponent.preview = preview;\n\tcomponent.previewArgsKey = argsKey;\n\tcomponent.previewPending = false;\n\treturn changed;\n}\n\nexport function createEditToolDefinition(\n\tcwd: string,\n\toptions?: EditToolOptions,\n): ApexToolDefinition<typeof editSchema, EditToolDetails | undefined, EditRenderState> {\n\tconst ops = options?.operations ?? defaultEditOperations;\n\tconst diagnosticsOperations = options?.diagnosticsOperations;\n\treturn {\n\t\tname: \"edit\",\n\t\tlabel: \"edit\",\n\t\tdescription:\n\t\t\t\"Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.\",\n\t\tpromptSnippet: editToolSystemPromptContribution.snippet,\n\t\tpromptGuidelines: [...editToolSystemPromptContribution.guidelines],\n\t\tparameters: editSchema,\n\t\tcontract: {\n\t\t\tcapabilities: new Set([\"fs.read\", \"fs.write\"]),\n\t\t\tpermission: createPathPermissionSpec({\n\t\t\t\tcwd,\n\t\t\t\tdefaultBehavior: \"ask\",\n\t\t\t\tverb: \"Edit\",\n\t\t\t\tgetPath: (params) => params.path,\n\t\t\t\tpreviewCall: (params) => previewEdit(params as EditToolInput),\n\t\t\t}),\n\t\t\tcontext: { resultRecoverable: true, deferSchema: false },\n\t\t\tevidence: {\n\t\t\t\temits: new Set(diagnosticsOperations ? [\"diff\", \"diagnostic\"] : [\"diff\"]),\n\t\t\t\tcapture: (params, result) => {\n\t\t\t\t\tconst patch = result.details?.patch;\n\t\t\t\t\tconst records: EvidenceRecord[] = patch\n\t\t\t\t\t\t? [{ kind: \"diff\", path: params.path, patchHash: sha256(patch) }]\n\t\t\t\t\t\t: [{ kind: \"diff\", path: params.path }];\n\t\t\t\t\tconst diagnostics = result.details?.diagnostics;\n\t\t\t\t\tif (diagnostics) records.push(diagnosticEvidenceForPath(params.path, diagnostics));\n\t\t\t\t\treturn records;\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tconstrainedSampling: getExperimentalToolSampling(),\n\t\trenderShell: \"self\",\n\t\tprepareArguments: prepareEditArguments,\n\t\tasync execute(_toolCallId, input: EditToolInput, signal?: AbortSignal, _onUpdate?, _ctx?) {\n\t\t\tconst { path, edits } = validateEditInput(input);\n\t\t\tconst prepared = getPreparedPathOperation(input);\n\t\t\tconst absolutePath = prepared?.path.value ?? resolveToCwd(path, cwd);\n\t\t\tif (prepared && (!ops.readPreparedFile || !ops.writePreparedFile)) {\n\t\t\t\tthrow new Error(\"No safe prepared edit operation is available for this gated edit\");\n\t\t\t}\n\n\t\t\treturn withFileMutationQueue(absolutePath, async () => {\n\t\t\t\t// Do not reject from an abort event listener here: that would release the\n\t\t\t\t// mutation queue while an in-flight filesystem operation may still finish.\n\t\t\t\t// Checking signal.aborted after each await observes the same aborts while\n\t\t\t\t// keeping the queue locked until the current operation has settled.\n\t\t\t\tconst throwIfAborted = (): void => {\n\t\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\t\t};\n\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Check if file exists (skipped for a gated call: the prepared operation\n\t\t\t\t// already proves existence, and the no-follow read enforces the identity).\n\t\t\t\ttry {\n\t\t\t\t\tif (!prepared) await ops.access(absolutePath);\n\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\tthrowIfAborted();\n\t\t\t\t\tconst errorMessage =\n\t\t\t\t\t\terror instanceof Error && \"code\" in error ? `Error code: ${error.code}` : String(error);\n\t\t\t\t\tthrow new Error(`Could not edit file: ${path}. ${errorMessage}.`);\n\t\t\t\t}\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Read the file.\n\t\t\t\tconst buffer = prepared ? ops.readPreparedFile!(prepared) : await ops.readFile(absolutePath);\n\t\t\t\tconst rawContent = buffer.toString(\"utf-8\");\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Strip BOM before matching. The model will not include an invisible BOM in oldText.\n\t\t\t\tconst { bom, text: content } = splitBom(rawContent);\n\t\t\t\tconst originalEnding = detectLineEnding(content);\n\t\t\t\tconst normalizedContent = normalizeToLF(content);\n\t\t\t\tconst { baseContent, newContent } = applyEditsToNormalizedContent(normalizedContent, edits, path);\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\tconst finalContent = bom + restoreLineEndings(newContent, originalEnding);\n\t\t\t\tif (prepared) ops.writePreparedFile!(prepared, Buffer.from(finalContent, \"utf-8\"));\n\t\t\t\telse await ops.writeFile(absolutePath, finalContent);\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\tconst diffResult = generateDiffString(baseContent, newContent);\n\t\t\t\tconst patch = generateUnifiedPatch(path, baseContent, newContent);\n\t\t\t\tconst successText = `Successfully replaced ${edits.length} block(s) in ${path}.`;\n\n\t\t\t\tif (diagnosticsOperations) {\n\t\t\t\t\tconst diagnostics = await diagnosticsOperations.afterMutation(absolutePath, signal);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `${successText}\\n\\n${formatDiagnosticsOutcome(diagnostics)}` }],\n\t\t\t\t\t\tdetails: { diff: diffResult.diff, patch, firstChangedLine: diffResult.firstChangedLine, diagnostics },\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: successText }],\n\t\t\t\t\tdetails: { diff: diffResult.diff, patch, firstChangedLine: diffResult.firstChangedLine },\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t\trenderCall(args, theme, context) {\n\t\t\tconst component = getEditCallRenderComponent(context.state, context.lastComponent);\n\t\t\tconst previewInput = getRenderablePreviewInput(args as RenderableEditArgs | undefined);\n\t\t\tconst argsKey = previewInput\n\t\t\t\t? JSON.stringify({ path: previewInput.path, edits: previewInput.edits })\n\t\t\t\t: undefined;\n\n\t\t\tif (component.previewArgsKey !== argsKey) {\n\t\t\t\tcomponent.preview = undefined;\n\t\t\t\tcomponent.previewArgsKey = argsKey;\n\t\t\t\tcomponent.previewPending = false;\n\t\t\t\tcomponent.settledError = false;\n\t\t\t}\n\n\t\t\tif (context.argsComplete && previewInput && !component.preview && !component.previewPending) {\n\t\t\t\tcomponent.previewPending = true;\n\t\t\t\tconst requestKey = argsKey;\n\t\t\t\tvoid computeEditsDiff(previewInput.path, previewInput.edits, context.cwd).then((preview) => {\n\t\t\t\t\tif (component.previewArgsKey === requestKey) {\n\t\t\t\t\t\tsetEditPreview(component, preview, requestKey);\n\t\t\t\t\t\tcontext.invalidate();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn buildEditCallComponent(component, args, theme, context.cwd, context.editDiffsExpanded);\n\t\t},\n\t\trenderResult(result, _options, theme, context) {\n\t\t\tconst callComponent = context.state.callComponent;\n\t\t\tconst previewInput = getRenderablePreviewInput(context.args as RenderableEditArgs | undefined);\n\t\t\tconst argsKey = previewInput\n\t\t\t\t? JSON.stringify({ path: previewInput.path, edits: previewInput.edits })\n\t\t\t\t: undefined;\n\t\t\tconst typedResult = result as EditToolResultLike;\n\t\t\tconst resultDiff = !context.isError ? typedResult.details?.diff : undefined;\n\t\t\tlet changed = false;\n\t\t\tif (callComponent) {\n\t\t\t\tif (typeof resultDiff === \"string\") {\n\t\t\t\t\tchanged =\n\t\t\t\t\t\tsetEditPreview(\n\t\t\t\t\t\t\tcallComponent,\n\t\t\t\t\t\t\t{ diff: resultDiff, firstChangedLine: typedResult.details?.firstChangedLine },\n\t\t\t\t\t\t\targsKey,\n\t\t\t\t\t\t) || changed;\n\t\t\t\t}\n\t\t\t\tif (callComponent.settledError !== context.isError) {\n\t\t\t\t\tcallComponent.settledError = context.isError;\n\t\t\t\t\tchanged = true;\n\t\t\t\t}\n\t\t\t\tif (changed) {\n\t\t\t\t\tbuildEditCallComponent(\n\t\t\t\t\t\tcallComponent,\n\t\t\t\t\t\tcontext.args as RenderableEditArgs | undefined,\n\t\t\t\t\t\ttheme,\n\t\t\t\t\t\tcontext.cwd,\n\t\t\t\t\t\tcontext.editDiffsExpanded,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst output = formatEditResult(\n\t\t\t\tcontext.args,\n\t\t\t\tcallComponent?.preview,\n\t\t\t\ttypedResult,\n\t\t\t\ttheme,\n\t\t\t\tcontext.isError,\n\t\t\t\tcontext.editDiffsExpanded,\n\t\t\t);\n\t\t\tconst component = (context.lastComponent as Container | undefined) ?? new Container();\n\t\t\tcomponent.clear();\n\t\t\tif (!output) {\n\t\t\t\treturn component;\n\t\t\t}\n\t\t\tcomponent.addChild(new Spacer(1));\n\t\t\tcomponent.addChild(new Text(output, 1, 0));\n\t\t\treturn component;\n\t\t},\n\t};\n}\n\nexport function createEditTool(cwd: string, options?: EditToolOptions): AgentTool<typeof editSchema> {\n\treturn wrapToolDefinition(createEditToolDefinition(cwd, options));\n}\n"]}
1
+ {"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../../src/core/tools/edit.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAI5C,OAAO,EAA4B,KAAK,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAEpG,OAAO,KAAK,EAAE,kBAAkB,EAAkB,MAAM,eAAe,CAAC;AACxE,OAAO,KAAK,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAelF,OAAO,EAAE,KAAK,eAAe,EAAiB,MAAM,qBAAqB,CAAC;AAc1E,QAAA,MAAM,UAAU;;;;;;EASf,CAAC;AAEF,eAAO,MAAM,gCAAgC;;;CAQnC,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAqBtD,MAAM,WAAW,eAAe;IAC/B,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uFAAuF;IACvF,WAAW,CAAC,EAAE,kBAAkB,CAAC;CACjC;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,qCAAqC;IACrC,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,8BAA8B;IAC9B,SAAS,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,4DAA4D;IAC5D,MAAM,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,qBAAqB,KAAK,MAAM,CAAC;IAChE,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,qBAAqB,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAChF;AAUD,MAAM,WAAW,eAAe;IAC/B,oEAAoE;IACpE,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;CAC9C;AA8ED,wBAAgB,wBAAwB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,eAAe,GACvB,kBAAkB,CAAC,OAAO,UAAU,EAAE,eAAe,GAAG,SAAS,EAAE,eAAe,CAAC,CAyGrF;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAEnG","sourcesContent":["import { createHash } from \"node:crypto\";\nimport type { AgentTool } from \"apex-code-agent-core\";\nimport { constants } from \"fs\";\nimport { access as fsAccess, readFile as fsReadFile } from \"fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport { splitBom } from \"../../utils/text.ts\";\nimport { getExperimentalToolSampling } from \"../experimental.ts\";\nimport type { ExtensionContext } from \"../extensions/types.ts\";\nimport { getPreparedPathOperation, type PreparedPathOperation } from \"../permissions/operations.ts\";\nimport type { PermissionPreview } from \"../permissions/responder.ts\";\nimport type { ApexToolDefinition, EvidenceRecord } from \"./contract.ts\";\nimport type { DiagnosticsOperations, DiagnosticsOutcome } from \"./diagnostics.ts\";\nimport { diagnosticEvidenceForPath, formatDiagnosticsOutcome } from \"./diagnostics.ts\";\nimport {\n\tapplyEditsToNormalizedContent,\n\tcomputeEditsDiffFromContent,\n\tdetectLineEnding,\n\ttype Edit,\n\tgenerateDiffString,\n\tgenerateUnifiedPatch,\n\tnormalizeToLF,\n\trestoreLineEndings,\n} from \"./edit-diff.ts\";\nimport { withFileMutationQueue } from \"./file-mutation-queue.ts\";\nimport { createPathPermissionSpec } from \"./path-permission.ts\";\nimport { readPreparedPath, resolveToCwd, writePathAtomically, writePreparedPath } from \"./path-utils.ts\";\nimport { type EditRenderState, editRenderers } from \"./renderers/edit.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nconst replaceEditSchema = Type.Object(\n\t{\n\t\toldText: Type.String({\n\t\t\tdescription:\n\t\t\t\t\"Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call.\",\n\t\t}),\n\t\tnewText: Type.String({ description: \"Replacement text for this targeted edit.\" }),\n\t},\n\t{},\n);\n\nconst editSchema = Type.Object(\n\t{\n\t\tpath: Type.String({ description: \"Path to the file to edit (relative or absolute)\" }),\n\t\tedits: Type.Array(replaceEditSchema, {\n\t\t\tdescription:\n\t\t\t\t\"One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead.\",\n\t\t}),\n\t},\n\t{},\n);\n\nexport const editToolSystemPromptContribution = {\n\tsnippet: \"Make precise file edits with exact text replacement, including multiple disjoint edits in one call\",\n\tguidelines: [\n\t\t\"Use edit for precise changes (edits[].oldText must match exactly)\",\n\t\t\"When changing multiple separate locations in one file, use one edit call with multiple entries in edits[] instead of multiple edit calls\",\n\t\t\"Each edits[].oldText is matched against the original file, not after earlier edits are applied. Do not emit overlapping or nested edits. Merge nearby changes into one edit.\",\n\t\t\"Keep edits[].oldText as small as possible while still being unique in the file. Do not pad with large unchanged regions.\",\n\t],\n} as const;\n\nexport type EditToolInput = Static<typeof editSchema>;\ntype LegacyEditToolInput = EditToolInput & {\n\toldText?: unknown;\n\tnewText?: unknown;\n};\n\nfunction sha256(value: string): string {\n\treturn createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\ntype SingleEditInput = { oldText: string; newText: string };\n\nfunction isSingleEditInput(value: unknown): value is SingleEditInput {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\treturn false;\n\t}\n\n\tconst edit = value as Record<string, unknown>;\n\treturn typeof edit.oldText === \"string\" && typeof edit.newText === \"string\";\n}\n\nexport interface EditToolDetails {\n\t/** Display-oriented diff of the changes made */\n\tdiff: string;\n\t/** Standard unified patch of the changes made */\n\tpatch: string;\n\t/** Line number of the first change in the new file (for editor navigation) */\n\tfirstChangedLine?: number;\n\t/** Present only when `EditToolOptions.diagnosticsOperations` is configured (LSP.4). */\n\tdiagnostics?: DiagnosticsOutcome;\n}\n\n/**\n * Pluggable operations for the edit tool.\n * Override these to delegate file editing to remote systems (for example SSH).\n */\nexport interface EditOperations {\n\t/** Read file contents as a Buffer */\n\treadFile: (absolutePath: string) => Promise<Buffer>;\n\t/** Write content to a file */\n\twriteFile: (absolutePath: string, content: string) => Promise<void>;\n\t/** Check if file is readable and writable (throw if not) */\n\taccess: (absolutePath: string) => Promise<void>;\n\t/**\n\t * Execute a gate-prepared edit no-follow against the authorized target.\n\t * Required for gated calls: when a prepared operation exists, pathname reads\n\t * and writes are never used, so an unset implementation fails closed.\n\t */\n\treadPreparedFile?: (operation: PreparedPathOperation) => Buffer;\n\twritePreparedFile?: (operation: PreparedPathOperation, content: Buffer) => void;\n}\n\nconst defaultEditOperations: EditOperations = {\n\treadFile: (path) => fsReadFile(path),\n\twriteFile: async (path, content) => writePathAtomically(path, content),\n\taccess: (path) => fsAccess(path, constants.R_OK | constants.W_OK),\n\treadPreparedFile: (operation) => readPreparedPath(operation),\n\twritePreparedFile: (operation, content) => writePreparedPath(operation, content),\n};\n\nexport interface EditToolOptions {\n\t/** Custom operations for file editing. Default: local filesystem */\n\toperations?: EditOperations;\n\t/**\n\t * Optional post-mutation diagnostics (LSP.4). Absent by default -- byte-identical\n\t * existing behavior. When present, called inside `withFileMutationQueue` after the\n\t * write succeeds and before the queue releases, matching `TestOperations`/\n\t * `GrepOperations`' injection pattern (`test.ts:28`, `grep.ts:58`).\n\t */\n\tdiagnosticsOperations?: DiagnosticsOperations;\n}\n\n/** A preview is a courtesy, so it never costs more than a screen or two of reading. */\nconst PREVIEW_MAX_BYTES = 512 * 1024;\nconst PREVIEW_MAX_LINES = 40;\n\n/**\n * Describe the edit for the person deciding whether to allow it.\n *\n * Reads through the operation `prepareCall` stored rather than resolving the\n * pathname again, so a target swapped after authorization fails here exactly as\n * it fails the write. `readPreparedPath` throws in that case and the gate turns\n * the throw into a stated reason, which is the outcome a reader needs: better a\n * prompt that admits it cannot show the change than a diff of the wrong file.\n */\nfunction previewEdit(params: EditToolInput): PermissionPreview {\n\tconst prepared = getPreparedPathOperation(params);\n\tif (!prepared) return { kind: \"unavailable\", reason: \"No authorized target was prepared for this call\" };\n\tif (prepared.kind === \"path-new\") {\n\t\treturn { kind: \"summary\", lines: [`Create ${params.path}`] };\n\t}\n\n\tconst buffer = readPreparedPath(prepared, PREVIEW_MAX_BYTES + 1);\n\tif (buffer.byteLength > PREVIEW_MAX_BYTES) {\n\t\treturn { kind: \"unavailable\", reason: `File is larger than ${PREVIEW_MAX_BYTES / 1024}KB, so no diff is shown` };\n\t}\n\tif (buffer.includes(0)) {\n\t\treturn { kind: \"unavailable\", reason: \"File is binary, so there is no diff to show\" };\n\t}\n\n\tconst result = computeEditsDiffFromContent(params.path, buffer.toString(\"utf-8\"), params.edits as Edit[]);\n\tif (\"error\" in result) return { kind: \"unavailable\", reason: result.error };\n\n\tconst lines = result.diff.split(\"\\n\");\n\tconst shown = lines.slice(0, PREVIEW_MAX_LINES);\n\treturn { kind: \"diff\", path: params.path, lines: shown, omittedLines: lines.length - shown.length };\n}\n\nfunction prepareEditArguments(input: unknown): EditToolInput {\n\tif (!input || typeof input !== \"object\") {\n\t\treturn input as EditToolInput;\n\t}\n\n\tconst args = input as Record<string, unknown>;\n\n\t// Some models (Opus 4.6, GLM-5.1) send edits as a JSON string instead of an array.\n\t// Others send a single edit object instead of a one-element edits array.\n\tif (typeof args.edits === \"string\") {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(args.edits);\n\t\t\tif (Array.isArray(parsed)) {\n\t\t\t\targs.edits = parsed;\n\t\t\t} else if (isSingleEditInput(parsed)) {\n\t\t\t\targs.edits = [parsed];\n\t\t\t}\n\t\t} catch {}\n\t} else if (isSingleEditInput(args.edits)) {\n\t\targs.edits = [args.edits];\n\t}\n\n\tconst legacy = args as LegacyEditToolInput;\n\tif (typeof legacy.oldText !== \"string\" || typeof legacy.newText !== \"string\") {\n\t\treturn args as EditToolInput;\n\t}\n\n\tconst edits = Array.isArray(legacy.edits) ? [...legacy.edits] : [];\n\tedits.push({ oldText: legacy.oldText, newText: legacy.newText });\n\tconst { oldText: _oldText, newText: _newText, ...rest } = legacy;\n\treturn { ...rest, edits } as EditToolInput;\n}\n\nfunction validateEditInput(input: EditToolInput): { path: string; edits: Edit[] } {\n\tif (!Array.isArray(input.edits) || input.edits.length === 0) {\n\t\tthrow new Error(\"Edit tool input is invalid. edits must contain at least one replacement.\");\n\t}\n\treturn { path: input.path, edits: input.edits };\n}\n\nexport function createEditToolDefinition(\n\tcwd: string,\n\toptions?: EditToolOptions,\n): ApexToolDefinition<typeof editSchema, EditToolDetails | undefined, EditRenderState> {\n\tconst ops = options?.operations ?? defaultEditOperations;\n\tconst diagnosticsOperations = options?.diagnosticsOperations;\n\treturn {\n\t\tname: \"edit\",\n\t\tlabel: \"edit\",\n\t\tdescription:\n\t\t\t\"Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.\",\n\t\tpromptSnippet: editToolSystemPromptContribution.snippet,\n\t\tpromptGuidelines: [...editToolSystemPromptContribution.guidelines],\n\t\tparameters: editSchema,\n\t\tcontract: {\n\t\t\tcapabilities: new Set([\"fs.read\", \"fs.write\"]),\n\t\t\tpermission: createPathPermissionSpec({\n\t\t\t\tcwd,\n\t\t\t\tdefaultBehavior: \"ask\",\n\t\t\t\tverb: \"Edit\",\n\t\t\t\tgetPath: (params) => params.path,\n\t\t\t\tpreviewCall: (params) => previewEdit(params as EditToolInput),\n\t\t\t}),\n\t\t\tcontext: { resultRecoverable: true, deferSchema: false },\n\t\t\tevidence: {\n\t\t\t\temits: new Set(diagnosticsOperations ? [\"diff\", \"diagnostic\"] : [\"diff\"]),\n\t\t\t\tcapture: (params, result) => {\n\t\t\t\t\tconst patch = result.details?.patch;\n\t\t\t\t\tconst records: EvidenceRecord[] = patch\n\t\t\t\t\t\t? [{ kind: \"diff\", path: params.path, patchHash: sha256(patch) }]\n\t\t\t\t\t\t: [{ kind: \"diff\", path: params.path }];\n\t\t\t\t\tconst diagnostics = result.details?.diagnostics;\n\t\t\t\t\tif (diagnostics) records.push(diagnosticEvidenceForPath(params.path, diagnostics));\n\t\t\t\t\treturn records;\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tconstrainedSampling: getExperimentalToolSampling() ?? { type: \"json_schema\", strict: \"prefer\" },\n\t\trenderShell: \"self\",\n\t\tprepareArguments: prepareEditArguments,\n\t\tasync execute(_toolCallId, input: EditToolInput, signal?: AbortSignal, _onUpdate?, ctx?: ExtensionContext) {\n\t\t\tconst { path, edits } = validateEditInput(input);\n\t\t\tconst prepared = getPreparedPathOperation(input);\n\t\t\tconst absolutePath = prepared?.path.value ?? resolveToCwd(path, ctx?.cwd || cwd);\n\t\t\tif (prepared && (!ops.readPreparedFile || !ops.writePreparedFile)) {\n\t\t\t\tthrow new Error(\"No safe prepared edit operation is available for this gated edit\");\n\t\t\t}\n\n\t\t\treturn withFileMutationQueue(absolutePath, async () => {\n\t\t\t\t// Do not reject from an abort event listener here: that would release the\n\t\t\t\t// mutation queue while an in-flight filesystem operation may still finish.\n\t\t\t\t// Checking signal.aborted after each await observes the same aborts while\n\t\t\t\t// keeping the queue locked until the current operation has settled.\n\t\t\t\tconst throwIfAborted = (): void => {\n\t\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\t\t};\n\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Check if file exists (skipped for a gated call: the prepared operation\n\t\t\t\t// already proves existence, and the no-follow read enforces the identity).\n\t\t\t\ttry {\n\t\t\t\t\tif (!prepared) await ops.access(absolutePath);\n\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\tthrowIfAborted();\n\t\t\t\t\tconst errorMessage =\n\t\t\t\t\t\terror instanceof Error && \"code\" in error ? `Error code: ${error.code}` : String(error);\n\t\t\t\t\tthrow new Error(`Could not edit file: ${path}. ${errorMessage}.`);\n\t\t\t\t}\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Read the file.\n\t\t\t\tconst buffer = prepared ? ops.readPreparedFile!(prepared) : await ops.readFile(absolutePath);\n\t\t\t\tconst rawContent = buffer.toString(\"utf-8\");\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Strip BOM before matching. The model will not include an invisible BOM in oldText.\n\t\t\t\tconst { bom, text: content } = splitBom(rawContent);\n\t\t\t\tconst originalEnding = detectLineEnding(content);\n\t\t\t\tconst normalizedContent = normalizeToLF(content);\n\t\t\t\tconst { baseContent, newContent } = applyEditsToNormalizedContent(normalizedContent, edits, path);\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\tconst finalContent = bom + restoreLineEndings(newContent, originalEnding);\n\t\t\t\tif (prepared) ops.writePreparedFile!(prepared, Buffer.from(finalContent, \"utf-8\"));\n\t\t\t\telse await ops.writeFile(absolutePath, finalContent);\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\tconst diffResult = generateDiffString(baseContent, newContent);\n\t\t\t\tconst patch = generateUnifiedPatch(path, baseContent, newContent);\n\t\t\t\tconst successText = `Successfully replaced ${edits.length} block(s) in ${path}.`;\n\n\t\t\t\tif (diagnosticsOperations) {\n\t\t\t\t\tconst diagnostics = await diagnosticsOperations.afterMutation(absolutePath, signal);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `${successText}\\n\\n${formatDiagnosticsOutcome(diagnostics)}` }],\n\t\t\t\t\t\tdetails: { diff: diffResult.diff, patch, firstChangedLine: diffResult.firstChangedLine, diagnostics },\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: successText }],\n\t\t\t\t\tdetails: { diff: diffResult.diff, patch, firstChangedLine: diffResult.firstChangedLine },\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t\t...editRenderers,\n\t};\n}\n\nexport function createEditTool(cwd: string, options?: EditToolOptions): AgentTool<typeof editSchema> {\n\treturn wrapToolDefinition(createEditToolDefinition(cwd, options));\n}\n"]}
@@ -1,18 +1,16 @@
1
1
  import { createHash } from "node:crypto";
2
- import { Box, Container, Spacer, Text } from "@earendil-works/pi-tui";
3
2
  import { constants } from "fs";
4
3
  import { access as fsAccess, readFile as fsReadFile } from "fs/promises";
5
4
  import { Type } from "typebox";
6
- import { renderDiff } from "../../modes/interactive/components/diff.js";
7
5
  import { splitBom } from "../../utils/text.js";
8
6
  import { getExperimentalToolSampling } from "../experimental.js";
9
7
  import { getPreparedPathOperation } from "../permissions/operations.js";
10
8
  import { diagnosticEvidenceForPath, formatDiagnosticsOutcome } from "./diagnostics.js";
11
- import { applyEditsToNormalizedContent, computeEditsDiff, computeEditsDiffFromContent, detectLineEnding, generateDiffString, generateUnifiedPatch, normalizeToLF, restoreLineEndings, } from "./edit-diff.js";
9
+ import { applyEditsToNormalizedContent, computeEditsDiffFromContent, detectLineEnding, generateDiffString, generateUnifiedPatch, normalizeToLF, restoreLineEndings, } from "./edit-diff.js";
12
10
  import { withFileMutationQueue } from "./file-mutation-queue.js";
13
11
  import { createPathPermissionSpec } from "./path-permission.js";
14
12
  import { readPreparedPath, resolveToCwd, writePathAtomically, writePreparedPath } from "./path-utils.js";
15
- import { renderToolPath, str } from "./render-utils.js";
13
+ import { editRenderers } from "./renderers/edit.js";
16
14
  import { wrapToolDefinition } from "./tool-definition-wrapper.js";
17
15
  const replaceEditSchema = Type.Object({
18
16
  oldText: Type.String({
@@ -122,147 +120,6 @@ function validateEditInput(input) {
122
120
  }
123
121
  return { path: input.path, edits: input.edits };
124
122
  }
125
- function createEditCallRenderComponent() {
126
- return Object.assign(new Box(1, 1, (text) => text), {
127
- preview: undefined,
128
- previewArgsKey: undefined,
129
- previewPending: false,
130
- settledError: false,
131
- });
132
- }
133
- function getEditCallRenderComponent(state, lastComponent) {
134
- if (lastComponent instanceof Box) {
135
- const component = lastComponent;
136
- state.callComponent = component;
137
- return component;
138
- }
139
- if (state.callComponent) {
140
- return state.callComponent;
141
- }
142
- const component = createEditCallRenderComponent();
143
- state.callComponent = component;
144
- return component;
145
- }
146
- function getRenderablePreviewInput(args) {
147
- if (!args) {
148
- return null;
149
- }
150
- const path = typeof args.path === "string" ? args.path : typeof args.file_path === "string" ? args.file_path : null;
151
- if (!path) {
152
- return null;
153
- }
154
- if (Array.isArray(args.edits) &&
155
- args.edits.length > 0 &&
156
- args.edits.every((edit) => typeof edit?.oldText === "string" && typeof edit?.newText === "string")) {
157
- return { path, edits: args.edits };
158
- }
159
- if (typeof args.oldText === "string" && typeof args.newText === "string") {
160
- return { path, edits: [{ oldText: args.oldText, newText: args.newText }] };
161
- }
162
- return null;
163
- }
164
- /**
165
- * Added and removed line counts read off a unified diff.
166
- *
167
- * `+++`/`---` file headers open with the same characters as content lines, so
168
- * they are skipped explicitly rather than by counting the first two lines,
169
- * which a diff without headers would not have.
170
- */
171
- function countChangedLines(diff) {
172
- let added = 0;
173
- let removed = 0;
174
- for (const line of diff.split("\n")) {
175
- if (line.startsWith("+++") || line.startsWith("---"))
176
- continue;
177
- if (line.startsWith("+"))
178
- added++;
179
- else if (line.startsWith("-"))
180
- removed++;
181
- }
182
- return { added, removed };
183
- }
184
- /** The one line a collapsed diff leaves behind, so the edit is still legible as an edit. */
185
- function formatChangeSummary(diff, theme) {
186
- const { added, removed } = countChangedLines(diff);
187
- const parts = [];
188
- if (added > 0)
189
- parts.push(theme.fg("toolDiffAdded", `+${added}`));
190
- if (removed > 0)
191
- parts.push(theme.fg("toolDiffRemoved", `-${removed}`));
192
- if (parts.length === 0)
193
- return theme.fg("dim", "no line changes");
194
- return parts.join(theme.fg("dim", " "));
195
- }
196
- function formatEditCall(args, theme, cwd) {
197
- const pathDisplay = renderToolPath(str(args?.file_path ?? args?.path), theme, cwd);
198
- return `${theme.fg("toolTitle", theme.bold("edit"))} ${pathDisplay}`;
199
- }
200
- function formatEditResult(args, preview, result, theme, isError, diffsExpanded) {
201
- const rawPath = str(args?.file_path ?? args?.path);
202
- const previewDiff = preview && !("error" in preview) ? preview.diff : undefined;
203
- const previewError = preview && "error" in preview ? preview.error : undefined;
204
- if (isError) {
205
- const errorText = result.content
206
- .filter((c) => c.type === "text")
207
- .map((c) => c.text || "")
208
- .join("\n");
209
- if (!errorText || errorText === previewError) {
210
- return undefined;
211
- }
212
- return theme.fg("error", errorText);
213
- }
214
- const resultDiff = result.details?.diff;
215
- if (resultDiff && resultDiff !== previewDiff) {
216
- return diffsExpanded
217
- ? renderDiff(resultDiff, { filePath: rawPath ?? undefined })
218
- : formatChangeSummary(resultDiff, theme);
219
- }
220
- return undefined;
221
- }
222
- function getEditHeaderBg(preview, settledError, theme) {
223
- if (preview) {
224
- if ("error" in preview) {
225
- return (text) => theme.bg("toolErrorBg", text);
226
- }
227
- return (text) => theme.bg("toolSuccessBg", text);
228
- }
229
- if (settledError) {
230
- return (text) => theme.bg("toolErrorBg", text);
231
- }
232
- return (text) => theme.bg("toolPendingBg", text);
233
- }
234
- function buildEditCallComponent(component, args, theme, cwd, diffsExpanded) {
235
- component.setBgFn(getEditHeaderBg(component.preview, component.settledError, theme));
236
- component.clear();
237
- component.addChild(new Text(formatEditCall(args, theme, cwd), 0, 0));
238
- if (!component.preview) {
239
- return component;
240
- }
241
- // An error always shows, whatever the detail level. A collapsed diff still
242
- // leaves its counts behind, so the row never becomes a bare filename.
243
- const body = "error" in component.preview
244
- ? theme.fg("error", component.preview.error)
245
- : diffsExpanded
246
- ? renderDiff(component.preview.diff)
247
- : formatChangeSummary(component.preview.diff, theme);
248
- component.addChild(new Spacer(1));
249
- component.addChild(new Text(body, 0, 0));
250
- return component;
251
- }
252
- function setEditPreview(component, preview, argsKey) {
253
- const current = component.preview;
254
- const changed = current === undefined ||
255
- ("error" in current && "error" in preview
256
- ? current.error !== preview.error
257
- : "error" in current !== "error" in preview) ||
258
- (!("error" in current) &&
259
- !("error" in preview) &&
260
- (current.diff !== preview.diff || current.firstChangedLine !== preview.firstChangedLine));
261
- component.preview = preview;
262
- component.previewArgsKey = argsKey;
263
- component.previewPending = false;
264
- return changed;
265
- }
266
123
  export function createEditToolDefinition(cwd, options) {
267
124
  const ops = options?.operations ?? defaultEditOperations;
268
125
  const diagnosticsOperations = options?.diagnosticsOperations;
@@ -297,13 +154,13 @@ export function createEditToolDefinition(cwd, options) {
297
154
  },
298
155
  },
299
156
  },
300
- constrainedSampling: getExperimentalToolSampling(),
157
+ constrainedSampling: getExperimentalToolSampling() ?? { type: "json_schema", strict: "prefer" },
301
158
  renderShell: "self",
302
159
  prepareArguments: prepareEditArguments,
303
- async execute(_toolCallId, input, signal, _onUpdate, _ctx) {
160
+ async execute(_toolCallId, input, signal, _onUpdate, ctx) {
304
161
  const { path, edits } = validateEditInput(input);
305
162
  const prepared = getPreparedPathOperation(input);
306
- const absolutePath = prepared?.path.value ?? resolveToCwd(path, cwd);
163
+ const absolutePath = prepared?.path.value ?? resolveToCwd(path, ctx?.cwd || cwd);
307
164
  if (prepared && (!ops.readPreparedFile || !ops.writePreparedFile)) {
308
165
  throw new Error("No safe prepared edit operation is available for this gated edit");
309
166
  }
@@ -361,62 +218,7 @@ export function createEditToolDefinition(cwd, options) {
361
218
  };
362
219
  });
363
220
  },
364
- renderCall(args, theme, context) {
365
- const component = getEditCallRenderComponent(context.state, context.lastComponent);
366
- const previewInput = getRenderablePreviewInput(args);
367
- const argsKey = previewInput
368
- ? JSON.stringify({ path: previewInput.path, edits: previewInput.edits })
369
- : undefined;
370
- if (component.previewArgsKey !== argsKey) {
371
- component.preview = undefined;
372
- component.previewArgsKey = argsKey;
373
- component.previewPending = false;
374
- component.settledError = false;
375
- }
376
- if (context.argsComplete && previewInput && !component.preview && !component.previewPending) {
377
- component.previewPending = true;
378
- const requestKey = argsKey;
379
- void computeEditsDiff(previewInput.path, previewInput.edits, context.cwd).then((preview) => {
380
- if (component.previewArgsKey === requestKey) {
381
- setEditPreview(component, preview, requestKey);
382
- context.invalidate();
383
- }
384
- });
385
- }
386
- return buildEditCallComponent(component, args, theme, context.cwd, context.editDiffsExpanded);
387
- },
388
- renderResult(result, _options, theme, context) {
389
- const callComponent = context.state.callComponent;
390
- const previewInput = getRenderablePreviewInput(context.args);
391
- const argsKey = previewInput
392
- ? JSON.stringify({ path: previewInput.path, edits: previewInput.edits })
393
- : undefined;
394
- const typedResult = result;
395
- const resultDiff = !context.isError ? typedResult.details?.diff : undefined;
396
- let changed = false;
397
- if (callComponent) {
398
- if (typeof resultDiff === "string") {
399
- changed =
400
- setEditPreview(callComponent, { diff: resultDiff, firstChangedLine: typedResult.details?.firstChangedLine }, argsKey) || changed;
401
- }
402
- if (callComponent.settledError !== context.isError) {
403
- callComponent.settledError = context.isError;
404
- changed = true;
405
- }
406
- if (changed) {
407
- buildEditCallComponent(callComponent, context.args, theme, context.cwd, context.editDiffsExpanded);
408
- }
409
- }
410
- const output = formatEditResult(context.args, callComponent?.preview, typedResult, theme, context.isError, context.editDiffsExpanded);
411
- const component = context.lastComponent ?? new Container();
412
- component.clear();
413
- if (!output) {
414
- return component;
415
- }
416
- component.addChild(new Spacer(1));
417
- component.addChild(new Text(output, 1, 0));
418
- return component;
419
- },
221
+ ...editRenderers,
420
222
  };
421
223
  }
422
224
  export function createEditTool(cwd, options) {
@@ -1 +1 @@
1
- {"version":3,"file":"edit.js","sourceRoot":"","sources":["../../../src/core/tools/edit.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { Box, Container, Spacer, Text } from \"@earendil-works/pi-tui\";\nimport type { AgentTool } from \"apex-code-agent-core\";\nimport { constants } from \"fs\";\nimport { access as fsAccess, readFile as fsReadFile } from \"fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport { renderDiff } from \"../../modes/interactive/components/diff.ts\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { splitBom } from \"../../utils/text.ts\";\nimport { getExperimentalToolSampling } from \"../experimental.ts\";\nimport { getPreparedPathOperation, type PreparedPathOperation } from \"../permissions/operations.ts\";\nimport type { PermissionPreview } from \"../permissions/responder.ts\";\nimport type { ApexToolDefinition, EvidenceRecord } from \"./contract.ts\";\nimport type { DiagnosticsOperations, DiagnosticsOutcome } from \"./diagnostics.ts\";\nimport { diagnosticEvidenceForPath, formatDiagnosticsOutcome } from \"./diagnostics.ts\";\nimport {\n\tapplyEditsToNormalizedContent,\n\tcomputeEditsDiff,\n\tcomputeEditsDiffFromContent,\n\tdetectLineEnding,\n\ttype Edit,\n\ttype EditDiffError,\n\ttype EditDiffResult,\n\tgenerateDiffString,\n\tgenerateUnifiedPatch,\n\tnormalizeToLF,\n\trestoreLineEndings,\n} from \"./edit-diff.ts\";\nimport { withFileMutationQueue } from \"./file-mutation-queue.ts\";\nimport { createPathPermissionSpec } from \"./path-permission.ts\";\nimport { readPreparedPath, resolveToCwd, writePathAtomically, writePreparedPath } from \"./path-utils.ts\";\nimport { renderToolPath, str } from \"./render-utils.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\ntype EditPreview = EditDiffResult | EditDiffError;\n\ntype EditRenderState = {\n\tcallComponent?: EditCallRenderComponent;\n};\n\nconst replaceEditSchema = Type.Object(\n\t{\n\t\toldText: Type.String({\n\t\t\tdescription:\n\t\t\t\t\"Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call.\",\n\t\t}),\n\t\tnewText: Type.String({ description: \"Replacement text for this targeted edit.\" }),\n\t},\n\t{},\n);\n\nconst editSchema = Type.Object(\n\t{\n\t\tpath: Type.String({ description: \"Path to the file to edit (relative or absolute)\" }),\n\t\tedits: Type.Array(replaceEditSchema, {\n\t\t\tdescription:\n\t\t\t\t\"One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead.\",\n\t\t}),\n\t},\n\t{},\n);\n\nexport const editToolSystemPromptContribution = {\n\tsnippet: \"Make precise file edits with exact text replacement, including multiple disjoint edits in one call\",\n\tguidelines: [\n\t\t\"Use edit for precise changes (edits[].oldText must match exactly)\",\n\t\t\"When changing multiple separate locations in one file, use one edit call with multiple entries in edits[] instead of multiple edit calls\",\n\t\t\"Each edits[].oldText is matched against the original file, not after earlier edits are applied. Do not emit overlapping or nested edits. Merge nearby changes into one edit.\",\n\t\t\"Keep edits[].oldText as small as possible while still being unique in the file. Do not pad with large unchanged regions.\",\n\t],\n} as const;\n\nexport type EditToolInput = Static<typeof editSchema>;\ntype LegacyEditToolInput = EditToolInput & {\n\toldText?: unknown;\n\tnewText?: unknown;\n};\n\nfunction sha256(value: string): string {\n\treturn createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\ntype SingleEditInput = { oldText: string; newText: string };\n\nfunction isSingleEditInput(value: unknown): value is SingleEditInput {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\treturn false;\n\t}\n\n\tconst edit = value as Record<string, unknown>;\n\treturn typeof edit.oldText === \"string\" && typeof edit.newText === \"string\";\n}\n\nexport interface EditToolDetails {\n\t/** Display-oriented diff of the changes made */\n\tdiff: string;\n\t/** Standard unified patch of the changes made */\n\tpatch: string;\n\t/** Line number of the first change in the new file (for editor navigation) */\n\tfirstChangedLine?: number;\n\t/** Present only when `EditToolOptions.diagnosticsOperations` is configured (LSP.4). */\n\tdiagnostics?: DiagnosticsOutcome;\n}\n\n/**\n * Pluggable operations for the edit tool.\n * Override these to delegate file editing to remote systems (for example SSH).\n */\nexport interface EditOperations {\n\t/** Read file contents as a Buffer */\n\treadFile: (absolutePath: string) => Promise<Buffer>;\n\t/** Write content to a file */\n\twriteFile: (absolutePath: string, content: string) => Promise<void>;\n\t/** Check if file is readable and writable (throw if not) */\n\taccess: (absolutePath: string) => Promise<void>;\n\t/**\n\t * Execute a gate-prepared edit no-follow against the authorized target.\n\t * Required for gated calls: when a prepared operation exists, pathname reads\n\t * and writes are never used, so an unset implementation fails closed.\n\t */\n\treadPreparedFile?: (operation: PreparedPathOperation) => Buffer;\n\twritePreparedFile?: (operation: PreparedPathOperation, content: Buffer) => void;\n}\n\nconst defaultEditOperations: EditOperations = {\n\treadFile: (path) => fsReadFile(path),\n\twriteFile: async (path, content) => writePathAtomically(path, content),\n\taccess: (path) => fsAccess(path, constants.R_OK | constants.W_OK),\n\treadPreparedFile: (operation) => readPreparedPath(operation),\n\twritePreparedFile: (operation, content) => writePreparedPath(operation, content),\n};\n\nexport interface EditToolOptions {\n\t/** Custom operations for file editing. Default: local filesystem */\n\toperations?: EditOperations;\n\t/**\n\t * Optional post-mutation diagnostics (LSP.4). Absent by default -- byte-identical\n\t * existing behavior. When present, called inside `withFileMutationQueue` after the\n\t * write succeeds and before the queue releases, matching `TestOperations`/\n\t * `GrepOperations`' injection pattern (`test.ts:28`, `grep.ts:58`).\n\t */\n\tdiagnosticsOperations?: DiagnosticsOperations;\n}\n\n/** A preview is a courtesy, so it never costs more than a screen or two of reading. */\nconst PREVIEW_MAX_BYTES = 512 * 1024;\nconst PREVIEW_MAX_LINES = 40;\n\n/**\n * Describe the edit for the person deciding whether to allow it.\n *\n * Reads through the operation `prepareCall` stored rather than resolving the\n * pathname again, so a target swapped after authorization fails here exactly as\n * it fails the write. `readPreparedPath` throws in that case and the gate turns\n * the throw into a stated reason, which is the outcome a reader needs: better a\n * prompt that admits it cannot show the change than a diff of the wrong file.\n */\nfunction previewEdit(params: EditToolInput): PermissionPreview {\n\tconst prepared = getPreparedPathOperation(params);\n\tif (!prepared) return { kind: \"unavailable\", reason: \"No authorized target was prepared for this call\" };\n\tif (prepared.kind === \"path-new\") {\n\t\treturn { kind: \"summary\", lines: [`Create ${params.path}`] };\n\t}\n\n\tconst buffer = readPreparedPath(prepared, PREVIEW_MAX_BYTES + 1);\n\tif (buffer.byteLength > PREVIEW_MAX_BYTES) {\n\t\treturn { kind: \"unavailable\", reason: `File is larger than ${PREVIEW_MAX_BYTES / 1024}KB, so no diff is shown` };\n\t}\n\tif (buffer.includes(0)) {\n\t\treturn { kind: \"unavailable\", reason: \"File is binary, so there is no diff to show\" };\n\t}\n\n\tconst result = computeEditsDiffFromContent(params.path, buffer.toString(\"utf-8\"), params.edits as Edit[]);\n\tif (\"error\" in result) return { kind: \"unavailable\", reason: result.error };\n\n\tconst lines = result.diff.split(\"\\n\");\n\tconst shown = lines.slice(0, PREVIEW_MAX_LINES);\n\treturn { kind: \"diff\", path: params.path, lines: shown, omittedLines: lines.length - shown.length };\n}\n\nfunction prepareEditArguments(input: unknown): EditToolInput {\n\tif (!input || typeof input !== \"object\") {\n\t\treturn input as EditToolInput;\n\t}\n\n\tconst args = input as Record<string, unknown>;\n\n\t// Some models (Opus 4.6, GLM-5.1) send edits as a JSON string instead of an array.\n\t// Others send a single edit object instead of a one-element edits array.\n\tif (typeof args.edits === \"string\") {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(args.edits);\n\t\t\tif (Array.isArray(parsed)) {\n\t\t\t\targs.edits = parsed;\n\t\t\t} else if (isSingleEditInput(parsed)) {\n\t\t\t\targs.edits = [parsed];\n\t\t\t}\n\t\t} catch {}\n\t} else if (isSingleEditInput(args.edits)) {\n\t\targs.edits = [args.edits];\n\t}\n\n\tconst legacy = args as LegacyEditToolInput;\n\tif (typeof legacy.oldText !== \"string\" || typeof legacy.newText !== \"string\") {\n\t\treturn args as EditToolInput;\n\t}\n\n\tconst edits = Array.isArray(legacy.edits) ? [...legacy.edits] : [];\n\tedits.push({ oldText: legacy.oldText, newText: legacy.newText });\n\tconst { oldText: _oldText, newText: _newText, ...rest } = legacy;\n\treturn { ...rest, edits } as EditToolInput;\n}\n\nfunction validateEditInput(input: EditToolInput): { path: string; edits: Edit[] } {\n\tif (!Array.isArray(input.edits) || input.edits.length === 0) {\n\t\tthrow new Error(\"Edit tool input is invalid. edits must contain at least one replacement.\");\n\t}\n\treturn { path: input.path, edits: input.edits };\n}\n\ntype RenderableEditArgs = {\n\tpath?: string;\n\tfile_path?: string;\n\tedits?: Edit[];\n\toldText?: string;\n\tnewText?: string;\n};\n\ntype EditToolResultLike = {\n\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\tdetails?: EditToolDetails;\n};\n\ntype EditCallRenderComponent = Box & {\n\tpreview?: EditPreview;\n\tpreviewArgsKey?: string;\n\tpreviewPending?: boolean;\n\tsettledError?: boolean;\n};\n\nfunction createEditCallRenderComponent(): EditCallRenderComponent {\n\treturn Object.assign(new Box(1, 1, (text: string) => text), {\n\t\tpreview: undefined as EditPreview | undefined,\n\t\tpreviewArgsKey: undefined as string | undefined,\n\t\tpreviewPending: false,\n\t\tsettledError: false,\n\t});\n}\n\nfunction getEditCallRenderComponent(state: EditRenderState, lastComponent: unknown): EditCallRenderComponent {\n\tif (lastComponent instanceof Box) {\n\t\tconst component = lastComponent as EditCallRenderComponent;\n\t\tstate.callComponent = component;\n\t\treturn component;\n\t}\n\tif (state.callComponent) {\n\t\treturn state.callComponent;\n\t}\n\tconst component = createEditCallRenderComponent();\n\tstate.callComponent = component;\n\treturn component;\n}\n\nfunction getRenderablePreviewInput(args: RenderableEditArgs | undefined): { path: string; edits: Edit[] } | null {\n\tif (!args) {\n\t\treturn null;\n\t}\n\n\tconst path = typeof args.path === \"string\" ? args.path : typeof args.file_path === \"string\" ? args.file_path : null;\n\tif (!path) {\n\t\treturn null;\n\t}\n\n\tif (\n\t\tArray.isArray(args.edits) &&\n\t\targs.edits.length > 0 &&\n\t\targs.edits.every((edit) => typeof edit?.oldText === \"string\" && typeof edit?.newText === \"string\")\n\t) {\n\t\treturn { path, edits: args.edits };\n\t}\n\n\tif (typeof args.oldText === \"string\" && typeof args.newText === \"string\") {\n\t\treturn { path, edits: [{ oldText: args.oldText, newText: args.newText }] };\n\t}\n\n\treturn null;\n}\n\n/**\n * Added and removed line counts read off a unified diff.\n *\n * `+++`/`---` file headers open with the same characters as content lines, so\n * they are skipped explicitly rather than by counting the first two lines,\n * which a diff without headers would not have.\n */\nfunction countChangedLines(diff: string): { added: number; removed: number } {\n\tlet added = 0;\n\tlet removed = 0;\n\tfor (const line of diff.split(\"\\n\")) {\n\t\tif (line.startsWith(\"+++\") || line.startsWith(\"---\")) continue;\n\t\tif (line.startsWith(\"+\")) added++;\n\t\telse if (line.startsWith(\"-\")) removed++;\n\t}\n\treturn { added, removed };\n}\n\n/** The one line a collapsed diff leaves behind, so the edit is still legible as an edit. */\nfunction formatChangeSummary(diff: string, theme: Theme): string {\n\tconst { added, removed } = countChangedLines(diff);\n\tconst parts: string[] = [];\n\tif (added > 0) parts.push(theme.fg(\"toolDiffAdded\", `+${added}`));\n\tif (removed > 0) parts.push(theme.fg(\"toolDiffRemoved\", `-${removed}`));\n\tif (parts.length === 0) return theme.fg(\"dim\", \"no line changes\");\n\treturn parts.join(theme.fg(\"dim\", \" \"));\n}\n\nfunction formatEditCall(args: RenderableEditArgs | undefined, theme: Theme, cwd: string): string {\n\tconst pathDisplay = renderToolPath(str(args?.file_path ?? args?.path), theme, cwd);\n\treturn `${theme.fg(\"toolTitle\", theme.bold(\"edit\"))} ${pathDisplay}`;\n}\n\nfunction formatEditResult(\n\targs: RenderableEditArgs | undefined,\n\tpreview: EditPreview | undefined,\n\tresult: EditToolResultLike,\n\ttheme: Theme,\n\tisError: boolean,\n\tdiffsExpanded: boolean,\n): string | undefined {\n\tconst rawPath = str(args?.file_path ?? args?.path);\n\tconst previewDiff = preview && !(\"error\" in preview) ? preview.diff : undefined;\n\tconst previewError = preview && \"error\" in preview ? preview.error : undefined;\n\tif (isError) {\n\t\tconst errorText = result.content\n\t\t\t.filter((c) => c.type === \"text\")\n\t\t\t.map((c) => c.text || \"\")\n\t\t\t.join(\"\\n\");\n\t\tif (!errorText || errorText === previewError) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn theme.fg(\"error\", errorText);\n\t}\n\n\tconst resultDiff = result.details?.diff;\n\tif (resultDiff && resultDiff !== previewDiff) {\n\t\treturn diffsExpanded\n\t\t\t? renderDiff(resultDiff, { filePath: rawPath ?? undefined })\n\t\t\t: formatChangeSummary(resultDiff, theme);\n\t}\n\n\treturn undefined;\n}\n\nfunction getEditHeaderBg(\n\tpreview: EditPreview | undefined,\n\tsettledError: boolean | undefined,\n\ttheme: Theme,\n): (text: string) => string {\n\tif (preview) {\n\t\tif (\"error\" in preview) {\n\t\t\treturn (text: string) => theme.bg(\"toolErrorBg\", text);\n\t\t}\n\t\treturn (text: string) => theme.bg(\"toolSuccessBg\", text);\n\t}\n\tif (settledError) {\n\t\treturn (text: string) => theme.bg(\"toolErrorBg\", text);\n\t}\n\treturn (text: string) => theme.bg(\"toolPendingBg\", text);\n}\n\nfunction buildEditCallComponent(\n\tcomponent: EditCallRenderComponent,\n\targs: RenderableEditArgs | undefined,\n\ttheme: Theme,\n\tcwd: string,\n\tdiffsExpanded: boolean,\n): EditCallRenderComponent {\n\tcomponent.setBgFn(getEditHeaderBg(component.preview, component.settledError, theme));\n\tcomponent.clear();\n\tcomponent.addChild(new Text(formatEditCall(args, theme, cwd), 0, 0));\n\n\tif (!component.preview) {\n\t\treturn component;\n\t}\n\n\t// An error always shows, whatever the detail level. A collapsed diff still\n\t// leaves its counts behind, so the row never becomes a bare filename.\n\tconst body =\n\t\t\"error\" in component.preview\n\t\t\t? theme.fg(\"error\", component.preview.error)\n\t\t\t: diffsExpanded\n\t\t\t\t? renderDiff(component.preview.diff)\n\t\t\t\t: formatChangeSummary(component.preview.diff, theme);\n\tcomponent.addChild(new Spacer(1));\n\tcomponent.addChild(new Text(body, 0, 0));\n\treturn component;\n}\n\nfunction setEditPreview(\n\tcomponent: EditCallRenderComponent,\n\tpreview: EditPreview,\n\targsKey: string | undefined,\n): boolean {\n\tconst current = component.preview;\n\tconst changed =\n\t\tcurrent === undefined ||\n\t\t(\"error\" in current && \"error\" in preview\n\t\t\t? current.error !== preview.error\n\t\t\t: \"error\" in current !== \"error\" in preview) ||\n\t\t(!(\"error\" in current) &&\n\t\t\t!(\"error\" in preview) &&\n\t\t\t(current.diff !== preview.diff || current.firstChangedLine !== preview.firstChangedLine));\n\tcomponent.preview = preview;\n\tcomponent.previewArgsKey = argsKey;\n\tcomponent.previewPending = false;\n\treturn changed;\n}\n\nexport function createEditToolDefinition(\n\tcwd: string,\n\toptions?: EditToolOptions,\n): ApexToolDefinition<typeof editSchema, EditToolDetails | undefined, EditRenderState> {\n\tconst ops = options?.operations ?? defaultEditOperations;\n\tconst diagnosticsOperations = options?.diagnosticsOperations;\n\treturn {\n\t\tname: \"edit\",\n\t\tlabel: \"edit\",\n\t\tdescription:\n\t\t\t\"Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.\",\n\t\tpromptSnippet: editToolSystemPromptContribution.snippet,\n\t\tpromptGuidelines: [...editToolSystemPromptContribution.guidelines],\n\t\tparameters: editSchema,\n\t\tcontract: {\n\t\t\tcapabilities: new Set([\"fs.read\", \"fs.write\"]),\n\t\t\tpermission: createPathPermissionSpec({\n\t\t\t\tcwd,\n\t\t\t\tdefaultBehavior: \"ask\",\n\t\t\t\tverb: \"Edit\",\n\t\t\t\tgetPath: (params) => params.path,\n\t\t\t\tpreviewCall: (params) => previewEdit(params as EditToolInput),\n\t\t\t}),\n\t\t\tcontext: { resultRecoverable: true, deferSchema: false },\n\t\t\tevidence: {\n\t\t\t\temits: new Set(diagnosticsOperations ? [\"diff\", \"diagnostic\"] : [\"diff\"]),\n\t\t\t\tcapture: (params, result) => {\n\t\t\t\t\tconst patch = result.details?.patch;\n\t\t\t\t\tconst records: EvidenceRecord[] = patch\n\t\t\t\t\t\t? [{ kind: \"diff\", path: params.path, patchHash: sha256(patch) }]\n\t\t\t\t\t\t: [{ kind: \"diff\", path: params.path }];\n\t\t\t\t\tconst diagnostics = result.details?.diagnostics;\n\t\t\t\t\tif (diagnostics) records.push(diagnosticEvidenceForPath(params.path, diagnostics));\n\t\t\t\t\treturn records;\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tconstrainedSampling: getExperimentalToolSampling(),\n\t\trenderShell: \"self\",\n\t\tprepareArguments: prepareEditArguments,\n\t\tasync execute(_toolCallId, input: EditToolInput, signal?: AbortSignal, _onUpdate?, _ctx?) {\n\t\t\tconst { path, edits } = validateEditInput(input);\n\t\t\tconst prepared = getPreparedPathOperation(input);\n\t\t\tconst absolutePath = prepared?.path.value ?? resolveToCwd(path, cwd);\n\t\t\tif (prepared && (!ops.readPreparedFile || !ops.writePreparedFile)) {\n\t\t\t\tthrow new Error(\"No safe prepared edit operation is available for this gated edit\");\n\t\t\t}\n\n\t\t\treturn withFileMutationQueue(absolutePath, async () => {\n\t\t\t\t// Do not reject from an abort event listener here: that would release the\n\t\t\t\t// mutation queue while an in-flight filesystem operation may still finish.\n\t\t\t\t// Checking signal.aborted after each await observes the same aborts while\n\t\t\t\t// keeping the queue locked until the current operation has settled.\n\t\t\t\tconst throwIfAborted = (): void => {\n\t\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\t\t};\n\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Check if file exists (skipped for a gated call: the prepared operation\n\t\t\t\t// already proves existence, and the no-follow read enforces the identity).\n\t\t\t\ttry {\n\t\t\t\t\tif (!prepared) await ops.access(absolutePath);\n\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\tthrowIfAborted();\n\t\t\t\t\tconst errorMessage =\n\t\t\t\t\t\terror instanceof Error && \"code\" in error ? `Error code: ${error.code}` : String(error);\n\t\t\t\t\tthrow new Error(`Could not edit file: ${path}. ${errorMessage}.`);\n\t\t\t\t}\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Read the file.\n\t\t\t\tconst buffer = prepared ? ops.readPreparedFile!(prepared) : await ops.readFile(absolutePath);\n\t\t\t\tconst rawContent = buffer.toString(\"utf-8\");\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Strip BOM before matching. The model will not include an invisible BOM in oldText.\n\t\t\t\tconst { bom, text: content } = splitBom(rawContent);\n\t\t\t\tconst originalEnding = detectLineEnding(content);\n\t\t\t\tconst normalizedContent = normalizeToLF(content);\n\t\t\t\tconst { baseContent, newContent } = applyEditsToNormalizedContent(normalizedContent, edits, path);\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\tconst finalContent = bom + restoreLineEndings(newContent, originalEnding);\n\t\t\t\tif (prepared) ops.writePreparedFile!(prepared, Buffer.from(finalContent, \"utf-8\"));\n\t\t\t\telse await ops.writeFile(absolutePath, finalContent);\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\tconst diffResult = generateDiffString(baseContent, newContent);\n\t\t\t\tconst patch = generateUnifiedPatch(path, baseContent, newContent);\n\t\t\t\tconst successText = `Successfully replaced ${edits.length} block(s) in ${path}.`;\n\n\t\t\t\tif (diagnosticsOperations) {\n\t\t\t\t\tconst diagnostics = await diagnosticsOperations.afterMutation(absolutePath, signal);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `${successText}\\n\\n${formatDiagnosticsOutcome(diagnostics)}` }],\n\t\t\t\t\t\tdetails: { diff: diffResult.diff, patch, firstChangedLine: diffResult.firstChangedLine, diagnostics },\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: successText }],\n\t\t\t\t\tdetails: { diff: diffResult.diff, patch, firstChangedLine: diffResult.firstChangedLine },\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t\trenderCall(args, theme, context) {\n\t\t\tconst component = getEditCallRenderComponent(context.state, context.lastComponent);\n\t\t\tconst previewInput = getRenderablePreviewInput(args as RenderableEditArgs | undefined);\n\t\t\tconst argsKey = previewInput\n\t\t\t\t? JSON.stringify({ path: previewInput.path, edits: previewInput.edits })\n\t\t\t\t: undefined;\n\n\t\t\tif (component.previewArgsKey !== argsKey) {\n\t\t\t\tcomponent.preview = undefined;\n\t\t\t\tcomponent.previewArgsKey = argsKey;\n\t\t\t\tcomponent.previewPending = false;\n\t\t\t\tcomponent.settledError = false;\n\t\t\t}\n\n\t\t\tif (context.argsComplete && previewInput && !component.preview && !component.previewPending) {\n\t\t\t\tcomponent.previewPending = true;\n\t\t\t\tconst requestKey = argsKey;\n\t\t\t\tvoid computeEditsDiff(previewInput.path, previewInput.edits, context.cwd).then((preview) => {\n\t\t\t\t\tif (component.previewArgsKey === requestKey) {\n\t\t\t\t\t\tsetEditPreview(component, preview, requestKey);\n\t\t\t\t\t\tcontext.invalidate();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn buildEditCallComponent(component, args, theme, context.cwd, context.editDiffsExpanded);\n\t\t},\n\t\trenderResult(result, _options, theme, context) {\n\t\t\tconst callComponent = context.state.callComponent;\n\t\t\tconst previewInput = getRenderablePreviewInput(context.args as RenderableEditArgs | undefined);\n\t\t\tconst argsKey = previewInput\n\t\t\t\t? JSON.stringify({ path: previewInput.path, edits: previewInput.edits })\n\t\t\t\t: undefined;\n\t\t\tconst typedResult = result as EditToolResultLike;\n\t\t\tconst resultDiff = !context.isError ? typedResult.details?.diff : undefined;\n\t\t\tlet changed = false;\n\t\t\tif (callComponent) {\n\t\t\t\tif (typeof resultDiff === \"string\") {\n\t\t\t\t\tchanged =\n\t\t\t\t\t\tsetEditPreview(\n\t\t\t\t\t\t\tcallComponent,\n\t\t\t\t\t\t\t{ diff: resultDiff, firstChangedLine: typedResult.details?.firstChangedLine },\n\t\t\t\t\t\t\targsKey,\n\t\t\t\t\t\t) || changed;\n\t\t\t\t}\n\t\t\t\tif (callComponent.settledError !== context.isError) {\n\t\t\t\t\tcallComponent.settledError = context.isError;\n\t\t\t\t\tchanged = true;\n\t\t\t\t}\n\t\t\t\tif (changed) {\n\t\t\t\t\tbuildEditCallComponent(\n\t\t\t\t\t\tcallComponent,\n\t\t\t\t\t\tcontext.args as RenderableEditArgs | undefined,\n\t\t\t\t\t\ttheme,\n\t\t\t\t\t\tcontext.cwd,\n\t\t\t\t\t\tcontext.editDiffsExpanded,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst output = formatEditResult(\n\t\t\t\tcontext.args,\n\t\t\t\tcallComponent?.preview,\n\t\t\t\ttypedResult,\n\t\t\t\ttheme,\n\t\t\t\tcontext.isError,\n\t\t\t\tcontext.editDiffsExpanded,\n\t\t\t);\n\t\t\tconst component = (context.lastComponent as Container | undefined) ?? new Container();\n\t\t\tcomponent.clear();\n\t\t\tif (!output) {\n\t\t\t\treturn component;\n\t\t\t}\n\t\t\tcomponent.addChild(new Spacer(1));\n\t\t\tcomponent.addChild(new Text(output, 1, 0));\n\t\t\treturn component;\n\t\t},\n\t};\n}\n\nexport function createEditTool(cwd: string, options?: EditToolOptions): AgentTool<typeof editSchema> {\n\treturn wrapToolDefinition(createEditToolDefinition(cwd, options));\n}\n"]}
1
+ {"version":3,"file":"edit.js","sourceRoot":"","sources":["../../../src/core/tools/edit.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport type { AgentTool } from \"apex-code-agent-core\";\nimport { constants } from \"fs\";\nimport { access as fsAccess, readFile as fsReadFile } from \"fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport { splitBom } from \"../../utils/text.ts\";\nimport { getExperimentalToolSampling } from \"../experimental.ts\";\nimport type { ExtensionContext } from \"../extensions/types.ts\";\nimport { getPreparedPathOperation, type PreparedPathOperation } from \"../permissions/operations.ts\";\nimport type { PermissionPreview } from \"../permissions/responder.ts\";\nimport type { ApexToolDefinition, EvidenceRecord } from \"./contract.ts\";\nimport type { DiagnosticsOperations, DiagnosticsOutcome } from \"./diagnostics.ts\";\nimport { diagnosticEvidenceForPath, formatDiagnosticsOutcome } from \"./diagnostics.ts\";\nimport {\n\tapplyEditsToNormalizedContent,\n\tcomputeEditsDiffFromContent,\n\tdetectLineEnding,\n\ttype Edit,\n\tgenerateDiffString,\n\tgenerateUnifiedPatch,\n\tnormalizeToLF,\n\trestoreLineEndings,\n} from \"./edit-diff.ts\";\nimport { withFileMutationQueue } from \"./file-mutation-queue.ts\";\nimport { createPathPermissionSpec } from \"./path-permission.ts\";\nimport { readPreparedPath, resolveToCwd, writePathAtomically, writePreparedPath } from \"./path-utils.ts\";\nimport { type EditRenderState, editRenderers } from \"./renderers/edit.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nconst replaceEditSchema = Type.Object(\n\t{\n\t\toldText: Type.String({\n\t\t\tdescription:\n\t\t\t\t\"Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call.\",\n\t\t}),\n\t\tnewText: Type.String({ description: \"Replacement text for this targeted edit.\" }),\n\t},\n\t{},\n);\n\nconst editSchema = Type.Object(\n\t{\n\t\tpath: Type.String({ description: \"Path to the file to edit (relative or absolute)\" }),\n\t\tedits: Type.Array(replaceEditSchema, {\n\t\t\tdescription:\n\t\t\t\t\"One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead.\",\n\t\t}),\n\t},\n\t{},\n);\n\nexport const editToolSystemPromptContribution = {\n\tsnippet: \"Make precise file edits with exact text replacement, including multiple disjoint edits in one call\",\n\tguidelines: [\n\t\t\"Use edit for precise changes (edits[].oldText must match exactly)\",\n\t\t\"When changing multiple separate locations in one file, use one edit call with multiple entries in edits[] instead of multiple edit calls\",\n\t\t\"Each edits[].oldText is matched against the original file, not after earlier edits are applied. Do not emit overlapping or nested edits. Merge nearby changes into one edit.\",\n\t\t\"Keep edits[].oldText as small as possible while still being unique in the file. Do not pad with large unchanged regions.\",\n\t],\n} as const;\n\nexport type EditToolInput = Static<typeof editSchema>;\ntype LegacyEditToolInput = EditToolInput & {\n\toldText?: unknown;\n\tnewText?: unknown;\n};\n\nfunction sha256(value: string): string {\n\treturn createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\ntype SingleEditInput = { oldText: string; newText: string };\n\nfunction isSingleEditInput(value: unknown): value is SingleEditInput {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\treturn false;\n\t}\n\n\tconst edit = value as Record<string, unknown>;\n\treturn typeof edit.oldText === \"string\" && typeof edit.newText === \"string\";\n}\n\nexport interface EditToolDetails {\n\t/** Display-oriented diff of the changes made */\n\tdiff: string;\n\t/** Standard unified patch of the changes made */\n\tpatch: string;\n\t/** Line number of the first change in the new file (for editor navigation) */\n\tfirstChangedLine?: number;\n\t/** Present only when `EditToolOptions.diagnosticsOperations` is configured (LSP.4). */\n\tdiagnostics?: DiagnosticsOutcome;\n}\n\n/**\n * Pluggable operations for the edit tool.\n * Override these to delegate file editing to remote systems (for example SSH).\n */\nexport interface EditOperations {\n\t/** Read file contents as a Buffer */\n\treadFile: (absolutePath: string) => Promise<Buffer>;\n\t/** Write content to a file */\n\twriteFile: (absolutePath: string, content: string) => Promise<void>;\n\t/** Check if file is readable and writable (throw if not) */\n\taccess: (absolutePath: string) => Promise<void>;\n\t/**\n\t * Execute a gate-prepared edit no-follow against the authorized target.\n\t * Required for gated calls: when a prepared operation exists, pathname reads\n\t * and writes are never used, so an unset implementation fails closed.\n\t */\n\treadPreparedFile?: (operation: PreparedPathOperation) => Buffer;\n\twritePreparedFile?: (operation: PreparedPathOperation, content: Buffer) => void;\n}\n\nconst defaultEditOperations: EditOperations = {\n\treadFile: (path) => fsReadFile(path),\n\twriteFile: async (path, content) => writePathAtomically(path, content),\n\taccess: (path) => fsAccess(path, constants.R_OK | constants.W_OK),\n\treadPreparedFile: (operation) => readPreparedPath(operation),\n\twritePreparedFile: (operation, content) => writePreparedPath(operation, content),\n};\n\nexport interface EditToolOptions {\n\t/** Custom operations for file editing. Default: local filesystem */\n\toperations?: EditOperations;\n\t/**\n\t * Optional post-mutation diagnostics (LSP.4). Absent by default -- byte-identical\n\t * existing behavior. When present, called inside `withFileMutationQueue` after the\n\t * write succeeds and before the queue releases, matching `TestOperations`/\n\t * `GrepOperations`' injection pattern (`test.ts:28`, `grep.ts:58`).\n\t */\n\tdiagnosticsOperations?: DiagnosticsOperations;\n}\n\n/** A preview is a courtesy, so it never costs more than a screen or two of reading. */\nconst PREVIEW_MAX_BYTES = 512 * 1024;\nconst PREVIEW_MAX_LINES = 40;\n\n/**\n * Describe the edit for the person deciding whether to allow it.\n *\n * Reads through the operation `prepareCall` stored rather than resolving the\n * pathname again, so a target swapped after authorization fails here exactly as\n * it fails the write. `readPreparedPath` throws in that case and the gate turns\n * the throw into a stated reason, which is the outcome a reader needs: better a\n * prompt that admits it cannot show the change than a diff of the wrong file.\n */\nfunction previewEdit(params: EditToolInput): PermissionPreview {\n\tconst prepared = getPreparedPathOperation(params);\n\tif (!prepared) return { kind: \"unavailable\", reason: \"No authorized target was prepared for this call\" };\n\tif (prepared.kind === \"path-new\") {\n\t\treturn { kind: \"summary\", lines: [`Create ${params.path}`] };\n\t}\n\n\tconst buffer = readPreparedPath(prepared, PREVIEW_MAX_BYTES + 1);\n\tif (buffer.byteLength > PREVIEW_MAX_BYTES) {\n\t\treturn { kind: \"unavailable\", reason: `File is larger than ${PREVIEW_MAX_BYTES / 1024}KB, so no diff is shown` };\n\t}\n\tif (buffer.includes(0)) {\n\t\treturn { kind: \"unavailable\", reason: \"File is binary, so there is no diff to show\" };\n\t}\n\n\tconst result = computeEditsDiffFromContent(params.path, buffer.toString(\"utf-8\"), params.edits as Edit[]);\n\tif (\"error\" in result) return { kind: \"unavailable\", reason: result.error };\n\n\tconst lines = result.diff.split(\"\\n\");\n\tconst shown = lines.slice(0, PREVIEW_MAX_LINES);\n\treturn { kind: \"diff\", path: params.path, lines: shown, omittedLines: lines.length - shown.length };\n}\n\nfunction prepareEditArguments(input: unknown): EditToolInput {\n\tif (!input || typeof input !== \"object\") {\n\t\treturn input as EditToolInput;\n\t}\n\n\tconst args = input as Record<string, unknown>;\n\n\t// Some models (Opus 4.6, GLM-5.1) send edits as a JSON string instead of an array.\n\t// Others send a single edit object instead of a one-element edits array.\n\tif (typeof args.edits === \"string\") {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(args.edits);\n\t\t\tif (Array.isArray(parsed)) {\n\t\t\t\targs.edits = parsed;\n\t\t\t} else if (isSingleEditInput(parsed)) {\n\t\t\t\targs.edits = [parsed];\n\t\t\t}\n\t\t} catch {}\n\t} else if (isSingleEditInput(args.edits)) {\n\t\targs.edits = [args.edits];\n\t}\n\n\tconst legacy = args as LegacyEditToolInput;\n\tif (typeof legacy.oldText !== \"string\" || typeof legacy.newText !== \"string\") {\n\t\treturn args as EditToolInput;\n\t}\n\n\tconst edits = Array.isArray(legacy.edits) ? [...legacy.edits] : [];\n\tedits.push({ oldText: legacy.oldText, newText: legacy.newText });\n\tconst { oldText: _oldText, newText: _newText, ...rest } = legacy;\n\treturn { ...rest, edits } as EditToolInput;\n}\n\nfunction validateEditInput(input: EditToolInput): { path: string; edits: Edit[] } {\n\tif (!Array.isArray(input.edits) || input.edits.length === 0) {\n\t\tthrow new Error(\"Edit tool input is invalid. edits must contain at least one replacement.\");\n\t}\n\treturn { path: input.path, edits: input.edits };\n}\n\nexport function createEditToolDefinition(\n\tcwd: string,\n\toptions?: EditToolOptions,\n): ApexToolDefinition<typeof editSchema, EditToolDetails | undefined, EditRenderState> {\n\tconst ops = options?.operations ?? defaultEditOperations;\n\tconst diagnosticsOperations = options?.diagnosticsOperations;\n\treturn {\n\t\tname: \"edit\",\n\t\tlabel: \"edit\",\n\t\tdescription:\n\t\t\t\"Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.\",\n\t\tpromptSnippet: editToolSystemPromptContribution.snippet,\n\t\tpromptGuidelines: [...editToolSystemPromptContribution.guidelines],\n\t\tparameters: editSchema,\n\t\tcontract: {\n\t\t\tcapabilities: new Set([\"fs.read\", \"fs.write\"]),\n\t\t\tpermission: createPathPermissionSpec({\n\t\t\t\tcwd,\n\t\t\t\tdefaultBehavior: \"ask\",\n\t\t\t\tverb: \"Edit\",\n\t\t\t\tgetPath: (params) => params.path,\n\t\t\t\tpreviewCall: (params) => previewEdit(params as EditToolInput),\n\t\t\t}),\n\t\t\tcontext: { resultRecoverable: true, deferSchema: false },\n\t\t\tevidence: {\n\t\t\t\temits: new Set(diagnosticsOperations ? [\"diff\", \"diagnostic\"] : [\"diff\"]),\n\t\t\t\tcapture: (params, result) => {\n\t\t\t\t\tconst patch = result.details?.patch;\n\t\t\t\t\tconst records: EvidenceRecord[] = patch\n\t\t\t\t\t\t? [{ kind: \"diff\", path: params.path, patchHash: sha256(patch) }]\n\t\t\t\t\t\t: [{ kind: \"diff\", path: params.path }];\n\t\t\t\t\tconst diagnostics = result.details?.diagnostics;\n\t\t\t\t\tif (diagnostics) records.push(diagnosticEvidenceForPath(params.path, diagnostics));\n\t\t\t\t\treturn records;\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tconstrainedSampling: getExperimentalToolSampling() ?? { type: \"json_schema\", strict: \"prefer\" },\n\t\trenderShell: \"self\",\n\t\tprepareArguments: prepareEditArguments,\n\t\tasync execute(_toolCallId, input: EditToolInput, signal?: AbortSignal, _onUpdate?, ctx?: ExtensionContext) {\n\t\t\tconst { path, edits } = validateEditInput(input);\n\t\t\tconst prepared = getPreparedPathOperation(input);\n\t\t\tconst absolutePath = prepared?.path.value ?? resolveToCwd(path, ctx?.cwd || cwd);\n\t\t\tif (prepared && (!ops.readPreparedFile || !ops.writePreparedFile)) {\n\t\t\t\tthrow new Error(\"No safe prepared edit operation is available for this gated edit\");\n\t\t\t}\n\n\t\t\treturn withFileMutationQueue(absolutePath, async () => {\n\t\t\t\t// Do not reject from an abort event listener here: that would release the\n\t\t\t\t// mutation queue while an in-flight filesystem operation may still finish.\n\t\t\t\t// Checking signal.aborted after each await observes the same aborts while\n\t\t\t\t// keeping the queue locked until the current operation has settled.\n\t\t\t\tconst throwIfAborted = (): void => {\n\t\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\t\t};\n\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Check if file exists (skipped for a gated call: the prepared operation\n\t\t\t\t// already proves existence, and the no-follow read enforces the identity).\n\t\t\t\ttry {\n\t\t\t\t\tif (!prepared) await ops.access(absolutePath);\n\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\tthrowIfAborted();\n\t\t\t\t\tconst errorMessage =\n\t\t\t\t\t\terror instanceof Error && \"code\" in error ? `Error code: ${error.code}` : String(error);\n\t\t\t\t\tthrow new Error(`Could not edit file: ${path}. ${errorMessage}.`);\n\t\t\t\t}\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Read the file.\n\t\t\t\tconst buffer = prepared ? ops.readPreparedFile!(prepared) : await ops.readFile(absolutePath);\n\t\t\t\tconst rawContent = buffer.toString(\"utf-8\");\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Strip BOM before matching. The model will not include an invisible BOM in oldText.\n\t\t\t\tconst { bom, text: content } = splitBom(rawContent);\n\t\t\t\tconst originalEnding = detectLineEnding(content);\n\t\t\t\tconst normalizedContent = normalizeToLF(content);\n\t\t\t\tconst { baseContent, newContent } = applyEditsToNormalizedContent(normalizedContent, edits, path);\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\tconst finalContent = bom + restoreLineEndings(newContent, originalEnding);\n\t\t\t\tif (prepared) ops.writePreparedFile!(prepared, Buffer.from(finalContent, \"utf-8\"));\n\t\t\t\telse await ops.writeFile(absolutePath, finalContent);\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\tconst diffResult = generateDiffString(baseContent, newContent);\n\t\t\t\tconst patch = generateUnifiedPatch(path, baseContent, newContent);\n\t\t\t\tconst successText = `Successfully replaced ${edits.length} block(s) in ${path}.`;\n\n\t\t\t\tif (diagnosticsOperations) {\n\t\t\t\t\tconst diagnostics = await diagnosticsOperations.afterMutation(absolutePath, signal);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `${successText}\\n\\n${formatDiagnosticsOutcome(diagnostics)}` }],\n\t\t\t\t\t\tdetails: { diff: diffResult.diff, patch, firstChangedLine: diffResult.firstChangedLine, diagnostics },\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: successText }],\n\t\t\t\t\tdetails: { diff: diffResult.diff, patch, firstChangedLine: diffResult.firstChangedLine },\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t\t...editRenderers,\n\t};\n}\n\nexport function createEditTool(cwd: string, options?: EditToolOptions): AgentTool<typeof editSchema> {\n\treturn wrapToolDefinition(createEditToolDefinition(cwd, options));\n}\n"]}