zidane 7.2.4 → 8.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (376) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +34 -6
  3. package/dist/{acp-D-tVyUjw.js → acp-DQDhi2dj.js} +230 -77
  4. package/dist/acp-DQDhi2dj.js.map +1 -0
  5. package/dist/acp-cli.d.ts +1 -1
  6. package/dist/acp-cli.js +9 -66
  7. package/dist/acp-cli.js.map +1 -1
  8. package/dist/acp.d.ts +10 -590
  9. package/dist/acp.d.ts.map +1 -1
  10. package/dist/acp.js +3 -3
  11. package/dist/{agent-D0zZnGbt.js → agent-DSLNmBp0.js} +14401 -13214
  12. package/dist/agent-DSLNmBp0.js.map +1 -0
  13. package/dist/agent.d.ts +1 -1
  14. package/dist/agent.js +3 -2
  15. package/dist/aliasing-lVFbm81n.js +217 -0
  16. package/dist/aliasing-lVFbm81n.js.map +1 -0
  17. package/dist/{anthropic-C2aole0G.js → anthropic-CD00LhUP.js} +1442 -1264
  18. package/dist/anthropic-CD00LhUP.js.map +1 -0
  19. package/dist/artifacts-CV2hUKnL.js.map +1 -1
  20. package/dist/{atomic-write-B7zr1ddF.js → atomic-write-Ijgf2Mhc.js} +13 -3
  21. package/dist/atomic-write-Ijgf2Mhc.js.map +1 -0
  22. package/dist/call-tool-dHlbGOIY.js +70 -0
  23. package/dist/call-tool-dHlbGOIY.js.map +1 -0
  24. package/dist/chat/pure.d.ts +372 -6
  25. package/dist/chat/pure.d.ts.map +1 -1
  26. package/dist/chat/pure.js +35 -244
  27. package/dist/chat/pure.js.map +1 -1
  28. package/dist/{approvals-DKaJZYlm.js → chat-JPJJ8uu5.js} +15879 -14631
  29. package/dist/chat-JPJJ8uu5.js.map +1 -0
  30. package/dist/chat.d.ts +4 -6
  31. package/dist/chat.js +23 -12
  32. package/dist/cli-shared-C-YCaglL.js +159 -0
  33. package/dist/cli-shared-C-YCaglL.js.map +1 -0
  34. package/dist/client-core-BQSyDALT.d.ts +2115 -0
  35. package/dist/client-core-BQSyDALT.d.ts.map +1 -0
  36. package/dist/codemode-worker.d.ts +1 -0
  37. package/dist/codemode-worker.js +155 -0
  38. package/dist/codemode-worker.js.map +1 -0
  39. package/dist/codemode.d.ts +352 -0
  40. package/dist/codemode.d.ts.map +1 -0
  41. package/dist/codemode.js +5 -0
  42. package/dist/connection-Dr-Js4yZ.d.ts +28 -0
  43. package/dist/connection-Dr-Js4yZ.d.ts.map +1 -0
  44. package/dist/connection-loop-gdh22LTI.js +112 -0
  45. package/dist/connection-loop-gdh22LTI.js.map +1 -0
  46. package/dist/context-segments-BHKlagL6.js +1016 -0
  47. package/dist/context-segments-BHKlagL6.js.map +1 -0
  48. package/dist/{context-transport-T_6AYIvy.js → context-transport-DSMTUsK1.js} +3 -3
  49. package/dist/{context-transport-T_6AYIvy.js.map → context-transport-DSMTUsK1.js.map} +1 -1
  50. package/dist/contexts/daytona.d.ts +19 -8
  51. package/dist/contexts/daytona.d.ts.map +1 -1
  52. package/dist/contexts/daytona.js +1 -440
  53. package/dist/contexts/docker.d.ts +36 -7
  54. package/dist/contexts/docker.d.ts.map +1 -1
  55. package/dist/contexts/docker.js +1 -456
  56. package/dist/contexts/e2b.d.ts +68 -13
  57. package/dist/contexts/e2b.d.ts.map +1 -1
  58. package/dist/contexts/e2b.js +1 -382
  59. package/dist/contexts/sandbox.d.ts +1 -1
  60. package/dist/contexts/sandbox.js +5 -0
  61. package/dist/contexts/sandbox.js.map +1 -1
  62. package/dist/{contexts-CRE9pw07.js → contexts-d7UolYot.js} +1059 -524
  63. package/dist/contexts-d7UolYot.js.map +1 -0
  64. package/dist/contexts.d.ts +3 -3
  65. package/dist/contexts.js +1 -1
  66. package/dist/cred-keys-GpBg71cP.js +105 -0
  67. package/dist/cred-keys-GpBg71cP.js.map +1 -0
  68. package/dist/{auth-BG2rVKSt.js → credentials-JttEuRON.js} +55 -206
  69. package/dist/credentials-JttEuRON.js.map +1 -0
  70. package/dist/{cursor-iojRXHF9.js → cursor-CdjaQTBW.js} +3 -3
  71. package/dist/{cursor-iojRXHF9.js.map → cursor-CdjaQTBW.js.map} +1 -1
  72. package/dist/daemon-cli.d.ts +1 -1
  73. package/dist/daemon-cli.js +3 -2
  74. package/dist/daemon-cli.js.map +1 -1
  75. package/dist/daytona-DG3omipZ.js +513 -0
  76. package/dist/daytona-DG3omipZ.js.map +1 -0
  77. package/dist/defaults-Cx3zvDOV.js +23 -0
  78. package/dist/defaults-Cx3zvDOV.js.map +1 -0
  79. package/dist/dispatcher-BMlu2BmZ.js +4941 -0
  80. package/dist/dispatcher-BMlu2BmZ.js.map +1 -0
  81. package/dist/docker-BZhMMJUp.js +727 -0
  82. package/dist/docker-BZhMMJUp.js.map +1 -0
  83. package/dist/e2b-CEVOdRib.js +480 -0
  84. package/dist/e2b-CEVOdRib.js.map +1 -0
  85. package/dist/edit-utils-EGosADZq.js +234 -0
  86. package/dist/edit-utils-EGosADZq.js.map +1 -0
  87. package/dist/environment-8wsKE2Ln.js +214 -0
  88. package/dist/environment-8wsKE2Ln.js.map +1 -0
  89. package/dist/eval-BNcvle_J.js +1595 -0
  90. package/dist/eval-BNcvle_J.js.map +1 -0
  91. package/dist/eval.d.ts +2 -2
  92. package/dist/eval.js +1 -1489
  93. package/dist/executor-Cx5-8yqi.js +621 -0
  94. package/dist/executor-Cx5-8yqi.js.map +1 -0
  95. package/dist/extension-authoring-DyGGmq9V.js +385 -0
  96. package/dist/extension-authoring-DyGGmq9V.js.map +1 -0
  97. package/dist/extensions.d.ts +2 -2
  98. package/dist/extensions.js +3 -3
  99. package/dist/{fetch-url-DX75gpL0.js → fetch-url-Ct2TjDWt.js} +4 -4
  100. package/dist/{fetch-url-DX75gpL0.js.map → fetch-url-Ct2TjDWt.js.map} +1 -1
  101. package/dist/{format-BF745pLL.js → format-C2NQEVUH.js} +39 -2
  102. package/dist/format-C2NQEVUH.js.map +1 -0
  103. package/dist/format-bytes-C7tfc3Zm.js +55 -0
  104. package/dist/format-bytes-C7tfc3Zm.js.map +1 -0
  105. package/dist/headless-C_rNUuYC.js +960 -0
  106. package/dist/headless-C_rNUuYC.js.map +1 -0
  107. package/dist/headless.d.ts +1 -1
  108. package/dist/headless.js +1 -413
  109. package/dist/{history-search-C4bk1Wz_.js → history-search-CcYzF8-0.js} +7 -3
  110. package/dist/history-search-CcYzF8-0.js.map +1 -0
  111. package/dist/history-search-worker.d.ts +1 -1
  112. package/dist/history-search-worker.js +1 -1
  113. package/dist/host-D7NrI03V.js +378 -0
  114. package/dist/host-D7NrI03V.js.map +1 -0
  115. package/dist/host-signals-BcP5QKUD.js +118 -0
  116. package/dist/host-signals-BcP5QKUD.js.map +1 -0
  117. package/dist/identity-CwfO8K-t.js +26 -0
  118. package/dist/identity-CwfO8K-t.js.map +1 -0
  119. package/dist/{index-BgN1T3lk.d.ts → index-BGe1fQT7.d.ts} +10987 -9320
  120. package/dist/index-BGe1fQT7.d.ts.map +1 -0
  121. package/dist/index-BVQsIKGn.d.ts +448 -0
  122. package/dist/index-BVQsIKGn.d.ts.map +1 -0
  123. package/dist/{index-C6NEd5y_.d.ts → index-CHABJd-L.d.ts} +3386 -502
  124. package/dist/index-CHABJd-L.d.ts.map +1 -0
  125. package/dist/{index-C37_ppWv.d.ts → index-D6a7qXpg.d.ts} +2 -3
  126. package/dist/index-D6a7qXpg.d.ts.map +1 -0
  127. package/dist/index.d.ts +6 -6
  128. package/dist/index.js +27 -23
  129. package/dist/{completion-core-BRo86R_L.js → inline-ghost-BVRQeGoL.js} +50 -2
  130. package/dist/inline-ghost-BVRQeGoL.js.map +1 -0
  131. package/dist/ipc/remote.d.ts +313 -0
  132. package/dist/ipc/remote.d.ts.map +1 -0
  133. package/dist/ipc/remote.js +4 -0
  134. package/dist/ipc.d.ts +6 -964
  135. package/dist/ipc.js +403 -4
  136. package/dist/ipc.js.map +1 -0
  137. package/dist/{isolation-Kfoof0MM.d.ts → isolation-D9L650W5.d.ts} +100 -15
  138. package/dist/isolation-D9L650W5.d.ts.map +1 -0
  139. package/dist/json-rpc--HXQti1E.js +350 -0
  140. package/dist/json-rpc--HXQti1E.js.map +1 -0
  141. package/dist/links-j8rED1sR.js +603 -0
  142. package/dist/links-j8rED1sR.js.map +1 -0
  143. package/dist/local-terminal-D8QThwo_.js +252 -0
  144. package/dist/local-terminal-D8QThwo_.js.map +1 -0
  145. package/dist/{logger--C1VQjwJ.js → logger-Gtqlayx8.js} +199 -173
  146. package/dist/logger-Gtqlayx8.js.map +1 -0
  147. package/dist/logs-view-CWG8aUAG.js.map +1 -1
  148. package/dist/{mcp-CgNd-f3F.js → mcp-_wecH9Qe.js} +608 -562
  149. package/dist/mcp-_wecH9Qe.js.map +1 -0
  150. package/dist/mcp.d.ts +2 -2
  151. package/dist/mcp.js +2 -2
  152. package/dist/media-sniff-UKijEaiQ.js.map +1 -1
  153. package/dist/{messages-2jcOA_5R.js → messages-BqiwcD2Q.js} +1017 -1014
  154. package/dist/messages-BqiwcD2Q.js.map +1 -0
  155. package/dist/{oauth-DxHO17JE.js → oauth-Px_pBB9W.js} +5 -5
  156. package/dist/{oauth-DxHO17JE.js.map → oauth-Px_pBB9W.js.map} +1 -1
  157. package/dist/{openai-compat-Dy56weK8.js → openai-compat-CFrpH7uq.js} +432 -589
  158. package/dist/openai-compat-CFrpH7uq.js.map +1 -0
  159. package/dist/orchestration-BCGmB8Ps.js +511 -0
  160. package/dist/orchestration-BCGmB8Ps.js.map +1 -0
  161. package/dist/output/stream-json.d.ts +1 -2
  162. package/dist/output/stream-json.d.ts.map +1 -1
  163. package/dist/output/stream-json.js +1 -1
  164. package/dist/output/terminal.d.ts +1 -2
  165. package/dist/output/terminal.d.ts.map +1 -1
  166. package/dist/output/terminal.js +13 -7
  167. package/dist/output/terminal.js.map +1 -1
  168. package/dist/{plugins-gbI7SBA6.js → plugins-DS7mahzZ.js} +20 -101
  169. package/dist/plugins-DS7mahzZ.js.map +1 -0
  170. package/dist/plugins.d.ts +1 -1
  171. package/dist/plugins.js +1 -2
  172. package/dist/prelude-Cxo4t74B.js +517 -0
  173. package/dist/prelude-Cxo4t74B.js.map +1 -0
  174. package/dist/presets.d.ts +1 -1
  175. package/dist/presets.js +1 -2
  176. package/dist/project-root-B8zADr4o.js +167 -0
  177. package/dist/project-root-B8zADr4o.js.map +1 -0
  178. package/dist/project-user-paths-BSgtrRxl.js +58 -0
  179. package/dist/project-user-paths-BSgtrRxl.js.map +1 -0
  180. package/dist/{prompts-Pqc3JdW_.d.ts → prompts-DYcvqShf.d.ts} +14 -11
  181. package/dist/prompts-DYcvqShf.d.ts.map +1 -0
  182. package/dist/protocol-DnhqqSmE.js +13 -0
  183. package/dist/protocol-DnhqqSmE.js.map +1 -0
  184. package/dist/providers/anthropic.d.ts +2 -2
  185. package/dist/providers/anthropic.js +1 -2
  186. package/dist/providers/arcee.d.ts +1 -1
  187. package/dist/providers/arcee.js +1 -1
  188. package/dist/providers/baseten.d.ts +1 -1
  189. package/dist/providers/baseten.js +1 -1
  190. package/dist/providers/cerebras.d.ts +1 -1
  191. package/dist/providers/cerebras.js +3 -2
  192. package/dist/providers/cerebras.js.map +1 -1
  193. package/dist/providers/local.d.ts +1 -1
  194. package/dist/providers/local.js +1 -1
  195. package/dist/providers/openai-compat.d.ts +1 -1
  196. package/dist/providers/openai-compat.js +1 -2
  197. package/dist/providers/openai.d.ts +1 -1
  198. package/dist/providers/openai.js +15 -12
  199. package/dist/providers/openai.js.map +1 -1
  200. package/dist/providers/openrouter.d.ts +1 -1
  201. package/dist/providers/openrouter.js +3 -2
  202. package/dist/providers/openrouter.js.map +1 -1
  203. package/dist/providers/xai.d.ts +1 -1
  204. package/dist/providers/xai.js +3 -3
  205. package/dist/{providers-BVhnFyiY.js → providers-XUR7F4Hi.js} +4 -4
  206. package/dist/{providers-BVhnFyiY.js.map → providers-XUR7F4Hi.js.map} +1 -1
  207. package/dist/providers.d.ts +1 -1
  208. package/dist/providers.js +4 -4
  209. package/dist/registry-D6ShBWJU.js +5234 -0
  210. package/dist/registry-D6ShBWJU.js.map +1 -0
  211. package/dist/remote-hosts-BtA_9ZGp.js +97 -0
  212. package/dist/remote-hosts-BtA_9ZGp.js.map +1 -0
  213. package/dist/restate.d.ts +2 -3
  214. package/dist/restate.d.ts.map +1 -1
  215. package/dist/restate.js +631 -572
  216. package/dist/restate.js.map +1 -1
  217. package/dist/run-summary-CklLiZ4y.js +288 -0
  218. package/dist/run-summary-CklLiZ4y.js.map +1 -0
  219. package/dist/{sandbox-BH0WQkXn.d.ts → sandbox-C5dR5DwQ.d.ts} +6 -3
  220. package/dist/sandbox-C5dR5DwQ.d.ts.map +1 -0
  221. package/dist/session/sqlite.d.ts +1 -2
  222. package/dist/session/sqlite.d.ts.map +1 -1
  223. package/dist/session/sqlite.js +1 -616
  224. package/dist/session-factory-BUGY5P40.js +1576 -0
  225. package/dist/session-factory-BUGY5P40.js.map +1 -0
  226. package/dist/{session-BqRP1hS7.js → session-xh9JXu6i.js} +94 -52
  227. package/dist/session-xh9JXu6i.js.map +1 -0
  228. package/dist/session.d.ts +1 -1
  229. package/dist/session.js +2 -2
  230. package/dist/settings-keys-Ckf29NeM.js +677 -0
  231. package/dist/settings-keys-Ckf29NeM.js.map +1 -0
  232. package/dist/shell-path-Dqaoow2J.js +412 -0
  233. package/dist/shell-path-Dqaoow2J.js.map +1 -0
  234. package/dist/{skills-BC3dodWp.js → skills-DKqZJm4X.js} +430 -470
  235. package/dist/skills-DKqZJm4X.js.map +1 -0
  236. package/dist/skills.d.ts +2 -2
  237. package/dist/skills.js +1 -2
  238. package/dist/source-mPExaUm8.js +381 -0
  239. package/dist/source-mPExaUm8.js.map +1 -0
  240. package/dist/sqlite-DV1DQzN2.js +698 -0
  241. package/dist/sqlite-DV1DQzN2.js.map +1 -0
  242. package/dist/{src-CkNQKFKr.js → src-BRMYRJib.js} +903 -1121
  243. package/dist/src-BRMYRJib.js.map +1 -0
  244. package/dist/{stdio-DPpBDPx5.js → stdio-C6YyoW3I.js} +4 -4
  245. package/dist/{stdio-DPpBDPx5.js.map → stdio-C6YyoW3I.js.map} +1 -1
  246. package/dist/{stdio-loader-Bbx19dMZ.js → stdio-loader-C830Vg-Z.js} +4 -4
  247. package/dist/{stdio-loader-Bbx19dMZ.js.map → stdio-loader-C830Vg-Z.js.map} +1 -1
  248. package/dist/system-prompt-MNVHatSD.d.ts.map +1 -1
  249. package/dist/timeout-DEaqslLO.d.ts.map +1 -1
  250. package/dist/todo-edits-Dn251YUP.js +1790 -0
  251. package/dist/todo-edits-Dn251YUP.js.map +1 -0
  252. package/dist/{turn-operations-DrbJlpq9.js → tool-formatters-IQFDrdrs.js} +1456 -2120
  253. package/dist/tool-formatters-IQFDrdrs.js.map +1 -0
  254. package/dist/tool-state-Dku6YqAB.js +989 -0
  255. package/dist/tool-state-Dku6YqAB.js.map +1 -0
  256. package/dist/tools/fetch-url.d.ts +1 -2
  257. package/dist/tools/fetch-url.d.ts.map +1 -1
  258. package/dist/tools/fetch-url.js +1 -2
  259. package/dist/tools/prompts.d.ts +1 -1
  260. package/dist/tools/prompts.js +7 -7
  261. package/dist/tools/prompts.js.map +1 -1
  262. package/dist/tools/web-search.d.ts +1 -2
  263. package/dist/tools/web-search.d.ts.map +1 -1
  264. package/dist/tools/web-search.js +2 -2
  265. package/dist/tools/web-search.js.map +1 -1
  266. package/dist/tools-_DnT3AGM.js +578 -0
  267. package/dist/tools-_DnT3AGM.js.map +1 -0
  268. package/dist/tools.d.ts +3 -3
  269. package/dist/tools.js +4 -2
  270. package/dist/tui.d.ts +534 -517
  271. package/dist/tui.d.ts.map +1 -1
  272. package/dist/tui.js +34933 -27242
  273. package/dist/tui.js.map +1 -1
  274. package/dist/turn-operations-B8sokwi5.js +333 -0
  275. package/dist/turn-operations-B8sokwi5.js.map +1 -0
  276. package/dist/turn-operations-DQX5ZZni.d.ts +3089 -0
  277. package/dist/turn-operations-DQX5ZZni.d.ts.map +1 -0
  278. package/dist/types-C7ZFOztE.d.ts +132 -0
  279. package/dist/types-C7ZFOztE.d.ts.map +1 -0
  280. package/dist/types-CH5XpIHw.js +114 -0
  281. package/dist/types-CH5XpIHw.js.map +1 -0
  282. package/dist/{types-CWgENVLY.js → types-Cu0ZGDu9.js} +10 -6
  283. package/dist/types-Cu0ZGDu9.js.map +1 -0
  284. package/dist/types-IqegbJEE.d.ts +624 -0
  285. package/dist/types-IqegbJEE.d.ts.map +1 -0
  286. package/dist/types.d.ts +4 -4
  287. package/dist/types.js +1 -1
  288. package/dist/url-D8HCl65b.js +1259 -0
  289. package/dist/url-D8HCl65b.js.map +1 -0
  290. package/dist/wasm-BVT-j5cl.js +33 -0
  291. package/dist/wasm-BVT-j5cl.js.map +1 -0
  292. package/dist/workspace-exec-stream-SV2R9d5S.js +355 -0
  293. package/dist/workspace-exec-stream-SV2R9d5S.js.map +1 -0
  294. package/dist/ws-CIHMvlSh.js +952 -0
  295. package/dist/ws-CIHMvlSh.js.map +1 -0
  296. package/dist/ws-client-N7NxzvQp.js +230 -0
  297. package/dist/ws-client-N7NxzvQp.js.map +1 -0
  298. package/dist/{xai-CazjStOK.js → xai-CvJTeLrI.js} +165 -5
  299. package/dist/xai-CvJTeLrI.js.map +1 -0
  300. package/dist/xdg-zweed0-t.js +117 -0
  301. package/dist/xdg-zweed0-t.js.map +1 -0
  302. package/docs/ACP.md +52 -0
  303. package/docs/ARCHITECTURE.md +103 -6
  304. package/docs/ARTIFACTS.md +8 -4
  305. package/docs/CHAT.md +165 -14
  306. package/docs/EXECUTION_CONTEXT.md +8 -0
  307. package/docs/EXTENSIONS.md +123 -2
  308. package/docs/HEADLESS.md +2 -0
  309. package/docs/IPC.md +775 -64
  310. package/docs/MACHINES.md +456 -0
  311. package/docs/PANELS.md +3 -0
  312. package/docs/README.md +4 -0
  313. package/docs/RESTATE.md +3 -2
  314. package/docs/RUN_IN_BACKGROUND.md +10 -2
  315. package/docs/SERVER.md +1085 -0
  316. package/docs/SKILL.md +6 -1
  317. package/docs/TERMINAL.md +75 -0
  318. package/docs/TUI.md +65 -14
  319. package/package.json +58 -26
  320. package/scripts/eval.ts +4 -0
  321. package/dist/acp-D-tVyUjw.js.map +0 -1
  322. package/dist/agent-D0zZnGbt.js.map +0 -1
  323. package/dist/anthropic-C2aole0G.js.map +0 -1
  324. package/dist/approvals-DKaJZYlm.js.map +0 -1
  325. package/dist/atomic-write-B7zr1ddF.js.map +0 -1
  326. package/dist/auth-BG2rVKSt.js.map +0 -1
  327. package/dist/completion-core-BRo86R_L.js.map +0 -1
  328. package/dist/contexts/daytona.js.map +0 -1
  329. package/dist/contexts/docker.js.map +0 -1
  330. package/dist/contexts/e2b.js.map +0 -1
  331. package/dist/contexts-CRE9pw07.js.map +0 -1
  332. package/dist/eval.js.map +0 -1
  333. package/dist/format-BF745pLL.js.map +0 -1
  334. package/dist/glob-DluQFSw1.js +0 -270
  335. package/dist/glob-DluQFSw1.js.map +0 -1
  336. package/dist/headless.js.map +0 -1
  337. package/dist/history-search-C4bk1Wz_.js.map +0 -1
  338. package/dist/index-BgN1T3lk.d.ts.map +0 -1
  339. package/dist/index-C37_ppWv.d.ts.map +0 -1
  340. package/dist/index-C6NEd5y_.d.ts.map +0 -1
  341. package/dist/ipc-zVSyo6K1.js +0 -331
  342. package/dist/ipc-zVSyo6K1.js.map +0 -1
  343. package/dist/ipc.d.ts.map +0 -1
  344. package/dist/isolation-Kfoof0MM.d.ts.map +0 -1
  345. package/dist/json-rpc-rSWMUh9b.js +0 -192
  346. package/dist/json-rpc-rSWMUh9b.js.map +0 -1
  347. package/dist/logger--C1VQjwJ.js.map +0 -1
  348. package/dist/mcp-CgNd-f3F.js.map +0 -1
  349. package/dist/messages-2jcOA_5R.js.map +0 -1
  350. package/dist/openai-compat-Dy56weK8.js.map +0 -1
  351. package/dist/output-cap-C9zukcCj.js +0 -100
  352. package/dist/output-cap-C9zukcCj.js.map +0 -1
  353. package/dist/panels-B6gRk4bf.js +0 -789
  354. package/dist/panels-B6gRk4bf.js.map +0 -1
  355. package/dist/plugins-gbI7SBA6.js.map +0 -1
  356. package/dist/prompts-Pqc3JdW_.d.ts.map +0 -1
  357. package/dist/run-summary-BU_NgwUT.js +0 -269
  358. package/dist/run-summary-BU_NgwUT.js.map +0 -1
  359. package/dist/sandbox-BH0WQkXn.d.ts.map +0 -1
  360. package/dist/session/sqlite.js.map +0 -1
  361. package/dist/session-BqRP1hS7.js.map +0 -1
  362. package/dist/shell-path-h5czzllR.js +0 -1549
  363. package/dist/shell-path-h5czzllR.js.map +0 -1
  364. package/dist/skills-BC3dodWp.js.map +0 -1
  365. package/dist/src-CkNQKFKr.js.map +0 -1
  366. package/dist/todo-edits-UOwgxGKu.js +0 -528
  367. package/dist/todo-edits-UOwgxGKu.js.map +0 -1
  368. package/dist/tool-formatters-DoRLnfuD.d.ts +0 -759
  369. package/dist/tool-formatters-DoRLnfuD.d.ts.map +0 -1
  370. package/dist/transcript-anchors-BeudMbXx.d.ts +0 -1762
  371. package/dist/transcript-anchors-BeudMbXx.d.ts.map +0 -1
  372. package/dist/turn-operations-C8bMBDl_.d.ts +0 -1258
  373. package/dist/turn-operations-C8bMBDl_.d.ts.map +0 -1
  374. package/dist/turn-operations-DrbJlpq9.js.map +0 -1
  375. package/dist/types-CWgENVLY.js.map +0 -1
  376. package/dist/xai-CazjStOK.js.map +0 -1
@@ -0,0 +1,1259 @@
1
+ import { i as styleReplacementForVia, n as resolveOldString } from "./edit-utils-EGosADZq.js";
2
+ //#region src/chat/browser/url.ts
3
+ /**
4
+ * What the dev browser will load. It is a browser for the app you are
5
+ * building, not the web at large: http(s) only, bare local addresses
6
+ * default to http, anything that looks like a host gets https. Shared by the
7
+ * GUI address bar and the agent's `browser_open` / `browser_navigate`.
8
+ */
9
+ const LOCAL_HOST = /^(?:localhost|127(?:\.\d{1,3}){3}|0\.0\.0\.0|\[::1\]|[\w-]+\.localhost)(?::\d+)?(?:[/?#]|$)/i;
10
+ const HOST_LIKE = /^(?:[\w-]+\.)+[a-z]{2,}(?::\d+)?(?:[/?#]|$)/i;
11
+ const PORT_ONLY = /^:?(\d{2,5})([/?#].*)?$/;
12
+ /** Normalize address-bar input to a loadable URL, or `null` when it is not one. */
13
+ function normalizeBrowserUrl(input) {
14
+ const text = input.trim();
15
+ if (!text) return null;
16
+ const port = PORT_ONLY.exec(text);
17
+ if (port) return canonical(`http://localhost:${port[1]}${port[2] ?? ""}`);
18
+ if (/^[a-z][a-z\d+.-]*:\/\//i.test(text)) return isAllowedBrowserUrl(text) ? canonical(text) : null;
19
+ if (/\s/.test(text)) return null;
20
+ if (LOCAL_HOST.test(text)) return canonical(`http://${text}`);
21
+ if (HOST_LIKE.test(text)) return canonical(`https://${text}`);
22
+ return null;
23
+ }
24
+ /** Only http(s) pages (and the blank page) ever load in the dev browser. */
25
+ function isAllowedBrowserUrl(url) {
26
+ if (url === "about:blank") return true;
27
+ try {
28
+ const { protocol } = new URL(url);
29
+ return protocol === "http:" || protocol === "https:";
30
+ } catch {
31
+ return false;
32
+ }
33
+ }
34
+ /** A loopback address: the dev servers the browser exists for. */
35
+ function isLocalBrowserUrl(url) {
36
+ try {
37
+ const host = new URL(url).hostname;
38
+ return host === "localhost" || host.endsWith(".localhost") || host === "0.0.0.0" || host === "[::1]" || /^127(?:\.\d{1,3}){3}$/.test(host);
39
+ } catch {
40
+ return false;
41
+ }
42
+ }
43
+ function canonical(url) {
44
+ try {
45
+ return new URL(url).toString();
46
+ } catch {
47
+ return null;
48
+ }
49
+ }
50
+ //#endregion
51
+ //#region src/chat/command-notes.ts
52
+ /** The persisted invocation header block: `` `❯ /commit args` ``. */
53
+ function commandHeaderBlock(invocation) {
54
+ return `\`❯ ${invocation}\``;
55
+ }
56
+ /** `/name args` from a persisted header block, or null when the text is not one. */
57
+ function parseCommandHeader(text) {
58
+ const match = /^`❯ (\/[\s\S]+)`$/.exec(text.trim());
59
+ return match ? match[1] : null;
60
+ }
61
+ const PREFIX_SEPARATOR = /^\s*(?:[:·—-]\s*)?/;
62
+ /**
63
+ * The receipt text for one note. Older displays repeat the command
64
+ * (`/commit: 83dfea7`, `/review — 3 reviewers, fixes applied`); the prompt
65
+ * bubble above already names it, so the prefix goes, and a leftover ` — `
66
+ * reads as ` · `. A note without a display shows its first line.
67
+ */
68
+ function commandNoteText(display, text, invocation) {
69
+ let line = (display ?? text.split("\n").find((l) => l.trim()) ?? "").trim();
70
+ const prefix = [invocation, invocation?.split(/\s/, 1)[0]].filter((p) => Boolean(p)).find((p) => line.startsWith(p)) ?? /^\/[\w.:-]+/.exec(line)?.[0];
71
+ if (prefix) {
72
+ const rest = line.slice(prefix.length).replace(PREFIX_SEPARATOR, "");
73
+ if (rest) line = /^[0-9a-f]{7,40}$/.test(rest) ? `committed ${rest}` : rest;
74
+ }
75
+ line = line.replace(/\s+—\s+/g, " · ");
76
+ return line.length > 160 ? `${line.slice(0, 159)}…` : line;
77
+ }
78
+ /**
79
+ * The `display` a context note persists with: the command's marker, its
80
+ * first line when it gave none, or `''` for a model-only note
81
+ * (`display: false`), which shows nothing.
82
+ */
83
+ function noteDisplay(display, text) {
84
+ return display === false ? "" : display ?? commandNoteText(void 0, text);
85
+ }
86
+ /** A command step label: the display as given, minus any leftover ` — `. */
87
+ function commandStepLabel(display) {
88
+ return display.replace(/\s+—\s+/g, " · ");
89
+ }
90
+ const merged = /* @__PURE__ */ new WeakMap();
91
+ function isTopPrompt(event) {
92
+ return event.kind === "user-prompt" && !event.childId && (event.depth ?? 0) === 0;
93
+ }
94
+ /**
95
+ * One receipt line per exchange: every `command-note` in an exchange moves
96
+ * to its end and joins into a single event (`committed 83dfea7 · pushed to
97
+ * origin/main`). Returns `events` itself when there is nothing to merge;
98
+ * the merged event keeps its identity while its notes do not change, so
99
+ * memoised rows stay put.
100
+ */
101
+ function gatherCommandNotes(events) {
102
+ if (!events.some((e) => e.kind === "command-note")) return events;
103
+ const out = [];
104
+ let notes = [];
105
+ const flush = () => {
106
+ if (notes.length === 0) return;
107
+ const first = notes[0];
108
+ const key = notes.map((n) => n.text).join("\0");
109
+ let event = first;
110
+ if (notes.length > 1) {
111
+ const cached = merged.get(first);
112
+ event = cached?.key === key ? cached.event : {
113
+ ...first,
114
+ text: notes.map((n) => n.text).join(" · ")
115
+ };
116
+ merged.set(first, {
117
+ key,
118
+ event
119
+ });
120
+ }
121
+ let at = out.length;
122
+ while (at > 0 && out[at - 1].kind === "separator") at--;
123
+ out.splice(at, 0, event);
124
+ notes = [];
125
+ };
126
+ for (const event of events) {
127
+ if (isTopPrompt(event)) flush();
128
+ if (event.kind === "command-note" && !event.childId) {
129
+ notes.push(event);
130
+ continue;
131
+ }
132
+ out.push(event);
133
+ }
134
+ flush();
135
+ return out.length === events.length && out.every((e, i) => e === events[i]) ? events : out;
136
+ }
137
+ //#endregion
138
+ //#region src/chat/edit-approval.ts
139
+ /**
140
+ * Convert a per-hunk approval mask into an `EditOutcome[]`. `true` →
141
+ * `applied`; `false` → `denied` with the supplied reason.
142
+ *
143
+ * Length is `Math.max(mask.length, fallbackLength)` so callers passing a
144
+ * shorter mask still get a fully-populated array — missing entries
145
+ * default to applied, matching the "no decision => keep" convention.
146
+ */
147
+ function maskToOutcomeKinds(mask, fallbackLength, deniedReason = "denied by user") {
148
+ const len = Math.max(mask.length, fallbackLength);
149
+ const out = [];
150
+ for (let i = 0; i < len; i++) {
151
+ const keep = i < mask.length ? mask[i] : true;
152
+ out.push(keep ? { kind: "applied" } : {
153
+ kind: "denied",
154
+ reason: deniedReason
155
+ });
156
+ }
157
+ return out;
158
+ }
159
+ function resolveApprovalForPayload(decision, payload) {
160
+ const total = payload.hunks.length;
161
+ if (decision === "deny") {
162
+ const outcomes = Array.from({ length: total }, () => ({
163
+ kind: "denied",
164
+ reason: "denied by user"
165
+ }));
166
+ return {
167
+ outcomes,
168
+ shouldBlock: true,
169
+ syntheticEvent: {
170
+ ...payload,
171
+ outcomes
172
+ }
173
+ };
174
+ }
175
+ if (typeof decision === "object" && decision.kind === "partial") {
176
+ const outcomes = maskToOutcomeKinds(decision.mask, total);
177
+ return {
178
+ outcomes,
179
+ shouldBlock: !outcomes.some((o) => o.kind === "applied"),
180
+ syntheticEvent: {
181
+ ...payload,
182
+ outcomes
183
+ }
184
+ };
185
+ }
186
+ return {
187
+ outcomes: Array.from({ length: total }, () => ({ kind: "applied" })),
188
+ shouldBlock: false,
189
+ syntheticEvent: null
190
+ };
191
+ }
192
+ /** Sentinel tags used by {@link buildEditOutcomesAnnotation} / parser. */
193
+ const ANNOTATION_OPEN = "<edit-outcomes>";
194
+ const ANNOTATION_CLOSE = "</edit-outcomes>";
195
+ const OUTCOME_KIND_RE = /^applied|denied|skipped|failed$/;
196
+ const OUTCOME_LINE_RE = /^#(\d+) (applied|denied|skipped|failed)(?:: ?(.*))?$/;
197
+ /**
198
+ * Render an `EditOutcome[]` as the wire-format annotation block. Returns
199
+ * the body to APPEND to a tool result; callers join with a leading
200
+ * `\n\n` separator. Idempotent on missing reasons — bare `applied` lines
201
+ * stay terse.
202
+ */
203
+ function buildEditOutcomesAnnotation(outcomes) {
204
+ const lines = [ANNOTATION_OPEN];
205
+ for (let i = 0; i < outcomes.length; i++) {
206
+ const o = outcomes[i];
207
+ if (!OUTCOME_KIND_RE.test(o.kind)) continue;
208
+ const reason = o.reason ? `: ${o.reason}` : "";
209
+ lines.push(`#${i + 1} ${o.kind}${reason}`);
210
+ }
211
+ lines.push(ANNOTATION_CLOSE);
212
+ return lines.join("\n");
213
+ }
214
+ /**
215
+ * Parse an `<edit-outcomes>…</edit-outcomes>` annotation block out of a
216
+ * tool result body. Returns the outcomes keyed by 1-based hunk index, or
217
+ * `null` when the block is missing / malformed.
218
+ *
219
+ * Anchored on the explicit tag pair so the parser doesn't false-positive
220
+ * on natural prose that happens to contain `#1 applied`.
221
+ */
222
+ function parseEditOutcomesFromResult(result) {
223
+ const text = typeof result === "string" ? result : result.filter((b) => b.type === "text").map((b) => b.text).join("\n");
224
+ if (!text) return null;
225
+ const openIdx = text.indexOf(`\n${ANNOTATION_OPEN}\n`);
226
+ const startIdx = openIdx >= 0 ? openIdx + 1 : text.startsWith(`${ANNOTATION_OPEN}\n`) ? 0 : -1;
227
+ if (startIdx < 0) return null;
228
+ const closeNeedle = `\n${ANNOTATION_CLOSE}`;
229
+ const closeIdx = text.indexOf(closeNeedle, startIdx);
230
+ if (closeIdx < 0) return null;
231
+ const body = text.slice(startIdx + 15 + 1, closeIdx);
232
+ const found = [];
233
+ for (const line of body.split("\n")) {
234
+ if (line.length === 0) continue;
235
+ const m = OUTCOME_LINE_RE.exec(line);
236
+ if (!m) return null;
237
+ const idx = Number.parseInt(m[1], 10);
238
+ if (!Number.isFinite(idx) || idx < 1) return null;
239
+ const kind = m[2];
240
+ const reason = m[3]?.trim();
241
+ found.push({
242
+ idx,
243
+ outcome: {
244
+ kind,
245
+ ...reason ? { reason } : {}
246
+ }
247
+ });
248
+ }
249
+ if (found.length === 0) return null;
250
+ const maxIdx = Math.max(...found.map((f) => f.idx));
251
+ const outcomes = Array.from({ length: maxIdx }, () => ({ kind: "applied" }));
252
+ for (const { idx, outcome } of found) outcomes[idx - 1] = outcome;
253
+ return outcomes;
254
+ }
255
+ /**
256
+ * Strip the first `<edit-outcomes>…</edit-outcomes>` block out of a tool
257
+ * result body, returning the surrounding text. Used by the
258
+ * `tool:transform` hook to peel a body-emitted annotation before
259
+ * re-appending the merged (approval ∪ body) version — otherwise the
260
+ * result would carry two annotation blocks and
261
+ * {@link parseEditOutcomesFromResult} would only see the first.
262
+ *
263
+ * Anchored on the same `\n<edit-outcomes>\n` / start-of-string newline
264
+ * shape the parser uses, so prose that incidentally mentions
265
+ * `<edit-outcomes>` (e.g. a model summarizing its own format) isn't
266
+ * mistakenly stripped. Trims a single leading `\n\n` separator when
267
+ * present so successive strips don't leave dangling blank lines.
268
+ * Idempotent on inputs that don't contain a properly-anchored block.
269
+ */
270
+ function stripEditOutcomesAnnotation(text) {
271
+ const newlineNeedle = `\n${ANNOTATION_OPEN}\n`;
272
+ const newlineIdx = text.indexOf(newlineNeedle);
273
+ let openIdx;
274
+ if (newlineIdx >= 0) openIdx = newlineIdx + 1;
275
+ else if (text.startsWith(`${ANNOTATION_OPEN}\n`)) openIdx = 0;
276
+ else return text;
277
+ const closeIdx = text.indexOf(ANNOTATION_CLOSE, openIdx);
278
+ if (closeIdx < 0) return text;
279
+ const blockEnd = closeIdx + 16;
280
+ const sepStart = openIdx >= 2 && text.slice(openIdx - 2, openIdx) === "\n\n" ? openIdx - 2 : openIdx;
281
+ return text.slice(0, sepStart) + text.slice(blockEnd);
282
+ }
283
+ /**
284
+ * Merge body-side outcomes (keyed against the approved subset the tool
285
+ * actually ran on, in subset-position order) into approval-side outcomes
286
+ * (1:1 with the model's ORIGINAL `edits` list, with `denied` entries for
287
+ * every hunk the user dropped).
288
+ *
289
+ * Algorithm: walk the approval array; every `applied` placeholder
290
+ * corresponds to one approved hunk that the body ran. Consume body's
291
+ * outcomes in order against those placeholders. Non-`applied` approval
292
+ * entries (`denied`, `skipped`) stay untouched — they describe gate-
293
+ * level decisions the body never saw.
294
+ *
295
+ * Pure. Returns a fresh array; never mutates either input.
296
+ *
297
+ * Edge cases:
298
+ * - `body` is empty / shorter than the approved count → remaining
299
+ * approval `applied` placeholders stay as `applied` (the body ran
300
+ * happily; absence of a body entry means nothing failed).
301
+ * - `body` longer than approved count → trailing body entries are
302
+ * ignored. Shouldn't happen in practice (body sees the rebound
303
+ * subset), but the guard keeps the merge total-pure.
304
+ */
305
+ function mergeApprovalAndBodyOutcomes(approval, body) {
306
+ if (!body || body.length === 0) return approval.slice();
307
+ const out = [];
308
+ let bi = 0;
309
+ for (const entry of approval) if (entry.kind === "applied" && bi < body.length) {
310
+ out.push(body[bi]);
311
+ bi++;
312
+ } else out.push(entry);
313
+ return out;
314
+ }
315
+ /**
316
+ * Rewrite a `multi_edit` body header so the totals reflect the model's
317
+ * ORIGINAL edit list (the merged outcomes count) instead of the subset
318
+ * the body actually saw after gate rebinding. Without this, a partially
319
+ * approved call surfaces a misleading `applied 2 of 2 edits` (subset
320
+ * counts) on the wire even when the original was `applied 2 of 3`.
321
+ *
322
+ * Three body-side shapes are handled (matching `multi_edit`'s emit):
323
+ * 1. `Edited <path>: applied N edits (R replacements).`
324
+ * 2. `Edited <path>: applied N of M edits (R replacements).`
325
+ * 3. `multi_edit error: no edits applied to <path> (M attempted).`
326
+ *
327
+ * The replacements count is preserved verbatim — it's a body-side stat
328
+ * the chat layer can't recompute. When the first line doesn't look like
329
+ * any of the three shapes (e.g. an unrelated error preamble bubbled up),
330
+ * the text is returned unchanged.
331
+ */
332
+ function rewriteMultiEditHeader(text, merged, path) {
333
+ const newlineIdx = text.indexOf("\n");
334
+ const firstLine = newlineIdx < 0 ? text : text.slice(0, newlineIdx);
335
+ const rest = newlineIdx < 0 ? "" : text.slice(newlineIdx);
336
+ const successMatch = firstLine.match(/^Edited .+: applied \d+(?: of \d+)? edits? \((\d+) replacement/);
337
+ const isFailedShape = firstLine.startsWith("multi_edit error: no edits applied to ") && firstLine.endsWith(" attempted).");
338
+ if (!successMatch && !isFailedShape) return text;
339
+ const replacements = successMatch ? Number.parseInt(successMatch[1], 10) || 0 : 0;
340
+ const applied = summarizeOutcomes(merged).applied;
341
+ const total = merged.length;
342
+ let newHeader;
343
+ if (applied === total) newHeader = `Edited ${path}: applied ${total} edit${total === 1 ? "" : "s"} (${replacements} replacement${replacements === 1 ? "" : "s"}).`;
344
+ else if (applied > 0) newHeader = `Edited ${path}: applied ${applied} of ${total} edits (${replacements} replacement${replacements === 1 ? "" : "s"}).`;
345
+ else newHeader = `multi_edit error: no edits applied to ${path} (${total} attempted).`;
346
+ return newHeader + rest;
347
+ }
348
+ /**
349
+ * Aggregate counts for the transcript's summary badge (`3 applied · 1
350
+ * denied · 1 skipped`). Exported so renderers don't reimplement the
351
+ * tally. Pure / O(n).
352
+ */
353
+ function summarizeOutcomes(outcomes) {
354
+ const counts = {
355
+ applied: 0,
356
+ denied: 0,
357
+ skipped: 0,
358
+ failed: 0,
359
+ pending: 0
360
+ };
361
+ if (!outcomes) return {
362
+ ...counts,
363
+ total: 0
364
+ };
365
+ for (const o of outcomes) counts[o.kind] += 1;
366
+ return {
367
+ ...counts,
368
+ total: outcomes.length
369
+ };
370
+ }
371
+ //#endregion
372
+ //#region src/chat/edit-diff.ts
373
+ function extractEditPayload(name, input, priorContent) {
374
+ const path = input.path;
375
+ if (typeof path !== "string" || path === "") return void 0;
376
+ if (name === "edit") {
377
+ const oldString = input.old_string;
378
+ const newString = input.new_string;
379
+ if (typeof oldString !== "string" || typeof newString !== "string") return void 0;
380
+ return {
381
+ tool: "edit",
382
+ path,
383
+ hunks: [{
384
+ oldString,
385
+ newString,
386
+ ...input.replace_all === true ? { replaceAll: true } : {}
387
+ }],
388
+ ...priorContent !== void 0 ? { priorContent } : {}
389
+ };
390
+ }
391
+ if (name === "multi_edit") {
392
+ const steps = input.edits;
393
+ if (!Array.isArray(steps) || steps.length === 0) return void 0;
394
+ const hunks = [];
395
+ for (const raw of steps) {
396
+ if (typeof raw?.old_string !== "string" || typeof raw?.new_string !== "string") return void 0;
397
+ hunks.push({
398
+ oldString: raw.old_string,
399
+ newString: raw.new_string,
400
+ ...raw.replace_all === true ? { replaceAll: true } : {}
401
+ });
402
+ }
403
+ return {
404
+ tool: "multi_edit",
405
+ path,
406
+ hunks,
407
+ ...priorContent !== void 0 ? { priorContent } : {}
408
+ };
409
+ }
410
+ if (name === "write_file") {
411
+ const content = input.content;
412
+ if (typeof content !== "string") return void 0;
413
+ return {
414
+ tool: "write_file",
415
+ path,
416
+ hunks: [{
417
+ oldString: priorContent ?? "",
418
+ newString: content
419
+ }],
420
+ ...priorContent !== void 0 ? { priorContent } : {}
421
+ };
422
+ }
423
+ }
424
+ /**
425
+ * LCS table cell budget shared by the line- and token-level diffs. 4M
426
+ * cells ≈ low tens of MB of `number[]` rows — imperceptible — while
427
+ * anything needing more (multi-thousand-line change cores) wouldn't
428
+ * produce a human-readable minimal diff anyway.
429
+ */
430
+ const LCS_CELL_BUDGET = 4e6;
431
+ function computeLineDiff(oldString, newString) {
432
+ const oldLines = splitLines(oldString);
433
+ const newLines = splitLines(newString);
434
+ let lo = 0;
435
+ while (lo < oldLines.length && lo < newLines.length && oldLines[lo] === newLines[lo]) lo++;
436
+ let oldHi = oldLines.length;
437
+ let newHi = newLines.length;
438
+ while (oldHi > lo && newHi > lo && oldLines[oldHi - 1] === newLines[newHi - 1]) {
439
+ oldHi--;
440
+ newHi--;
441
+ }
442
+ const out = [];
443
+ for (let k = 0; k < lo; k++) out.push({
444
+ op: "context",
445
+ text: oldLines[k]
446
+ });
447
+ const n = oldHi - lo;
448
+ const m = newHi - lo;
449
+ if ((n + 1) * (m + 1) > LCS_CELL_BUDGET) {
450
+ for (let k = lo; k < oldHi; k++) out.push({
451
+ op: "remove",
452
+ text: oldLines[k]
453
+ });
454
+ for (let k = lo; k < newHi; k++) out.push({
455
+ op: "add",
456
+ text: newLines[k]
457
+ });
458
+ } else if (n > 0 || m > 0) appendLcsDiff(out, oldLines, newLines, lo, oldHi, newHi);
459
+ for (let k = oldHi; k < oldLines.length; k++) out.push({
460
+ op: "context",
461
+ text: oldLines[k]
462
+ });
463
+ return out;
464
+ }
465
+ /**
466
+ * The classic LCS table + reverse walk over `old[lo..oldHi) ×
467
+ * new[lo..newHi)`, appending ops to `out` in forward order. Diagonals at
468
+ * equal lines → context; otherwise step into the higher of (up, left)
469
+ * and emit remove/add respectively. Ties break so adjacent remove/add
470
+ * pairs stay grouped (the intra-line highlighter pairs them up).
471
+ */
472
+ function appendLcsDiff(out, oldLines, newLines, lo, oldHi, newHi) {
473
+ const n = oldHi - lo;
474
+ const m = newHi - lo;
475
+ const lcs = Array.from({ length: n + 1 }, () => Array.from({ length: m + 1 }).fill(0));
476
+ for (let i = 0; i < n; i++) for (let j = 0; j < m; j++) lcs[i + 1][j + 1] = oldLines[lo + i] === newLines[lo + j] ? lcs[i][j] + 1 : Math.max(lcs[i][j + 1], lcs[i + 1][j]);
477
+ const core = [];
478
+ let i = n;
479
+ let j = m;
480
+ while (i > 0 || j > 0) {
481
+ if (i > 0 && j > 0 && oldLines[lo + i - 1] === newLines[lo + j - 1]) {
482
+ core.push({
483
+ op: "context",
484
+ text: oldLines[lo + i - 1]
485
+ });
486
+ i--;
487
+ j--;
488
+ continue;
489
+ }
490
+ if (j > 0 && (i === 0 || lcs[i][j - 1] >= lcs[i - 1][j])) {
491
+ core.push({
492
+ op: "add",
493
+ text: newLines[lo + j - 1]
494
+ });
495
+ j--;
496
+ continue;
497
+ }
498
+ core.push({
499
+ op: "remove",
500
+ text: oldLines[lo + i - 1]
501
+ });
502
+ i--;
503
+ }
504
+ core.reverse();
505
+ out.push(...core);
506
+ }
507
+ /**
508
+ * Split a string into lines preserving empty lines but dropping the
509
+ * implicit trailing `""` produced by a final `\n`. Exported only for
510
+ * its tests — callers should use `computeLineDiff`.
511
+ */
512
+ function splitLines(s) {
513
+ if (s === "") return [];
514
+ const parts = s.split("\n");
515
+ if (parts[parts.length - 1] === "") parts.pop();
516
+ return parts;
517
+ }
518
+ function computeInlineDiff(oldLine, newLine) {
519
+ const oldTokens = tokenize(oldLine);
520
+ const newTokens = tokenize(newLine);
521
+ const n = oldTokens.length;
522
+ const m = newTokens.length;
523
+ if ((n + 1) * (m + 1) > LCS_CELL_BUDGET) return {
524
+ oldSegments: oldLine === "" ? [] : [{
525
+ text: oldLine,
526
+ changed: true
527
+ }],
528
+ newSegments: newLine === "" ? [] : [{
529
+ text: newLine,
530
+ changed: true
531
+ }]
532
+ };
533
+ const lcs = Array.from({ length: n + 1 }, () => Array.from({ length: m + 1 }).fill(0));
534
+ for (let i = 0; i < n; i++) for (let j = 0; j < m; j++) lcs[i + 1][j + 1] = oldTokens[i] === newTokens[j] ? lcs[i][j] + 1 : Math.max(lcs[i][j + 1], lcs[i + 1][j]);
535
+ const oldSegments = [];
536
+ const newSegments = [];
537
+ let i = n;
538
+ let j = m;
539
+ while (i > 0 || j > 0) {
540
+ if (i > 0 && j > 0 && oldTokens[i - 1] === newTokens[j - 1]) {
541
+ pushSegment(oldSegments, {
542
+ text: oldTokens[i - 1],
543
+ changed: false
544
+ });
545
+ pushSegment(newSegments, {
546
+ text: newTokens[j - 1],
547
+ changed: false
548
+ });
549
+ i--;
550
+ j--;
551
+ continue;
552
+ }
553
+ if (j > 0 && (i === 0 || lcs[i][j - 1] >= lcs[i - 1][j])) {
554
+ pushSegment(newSegments, {
555
+ text: newTokens[j - 1],
556
+ changed: true
557
+ });
558
+ j--;
559
+ continue;
560
+ }
561
+ pushSegment(oldSegments, {
562
+ text: oldTokens[i - 1],
563
+ changed: true
564
+ });
565
+ i--;
566
+ }
567
+ oldSegments.reverse();
568
+ newSegments.reverse();
569
+ return {
570
+ oldSegments,
571
+ newSegments
572
+ };
573
+ }
574
+ /**
575
+ * Coalesce adjacent same-state segments so the renderer emits one
576
+ * `<span>` per run instead of one per token — keeps the React tree
577
+ * shallow on dense lines without changing the visual output.
578
+ *
579
+ * Walking direction is reverse (we push during the reverse walk, then
580
+ * the caller reverses the array), so we coalesce against the *tail*.
581
+ */
582
+ function pushSegment(buf, seg) {
583
+ const tail = buf[buf.length - 1];
584
+ if (tail && tail.changed === seg.changed) tail.text = seg.text + tail.text;
585
+ else buf.push(seg);
586
+ }
587
+ /**
588
+ * Tokenize on word / non-word boundaries. Each run of `\w+` is one
589
+ * token; each run of `\W+` (whitespace, punctuation) is another. This
590
+ * gives the right granularity for renames (`oldName` → `newName`) and
591
+ * for symbol swaps (`+ → -`) without exploding into per-char segments.
592
+ *
593
+ * Exported only for its tests.
594
+ */
595
+ function tokenize(s) {
596
+ if (s === "") return [];
597
+ const out = [];
598
+ for (const match of s.matchAll(/\w+|\W+/g)) out.push(match[0]);
599
+ return out;
600
+ }
601
+ /**
602
+ * Apply the payload's hunks against `priorContent` and return the
603
+ * resulting file body. Mirrors the agent's tool-side semantics:
604
+ * - `replaceAll === true` → `String.replaceAll`
605
+ * - otherwise → first-occurrence `String.replace`
606
+ *
607
+ * Hunks are applied in order — a `multi_edit` later hunk operates on
608
+ * the output of the earlier ones, just like the actual tool.
609
+ */
610
+ function applyEditPayload(payload, priorContent) {
611
+ let out = priorContent;
612
+ for (const hunk of payload.hunks) out = hunk.replaceAll ? out.replaceAll(hunk.oldString, hunk.newString) : out.replace(hunk.oldString, hunk.newString);
613
+ return out;
614
+ }
615
+ /**
616
+ * Like `buildUnifiedDiff` but operating against the full file content
617
+ * so the diff carries *real* file line numbers and configurable
618
+ * surrounding context.
619
+ *
620
+ * Strategy:
621
+ * 1. Apply the payload to `priorContent` → `newContent`.
622
+ * 2. Run `computeLineDiff` over the whole file.
623
+ * 3. Group non-context ops into hunks, padding each with up to
624
+ * `contextLines` of context above and below. Adjacent hunks
625
+ * whose context regions touch are merged so we don't emit two
626
+ * `@@` headers separated by zero context lines.
627
+ *
628
+ * The output line numbers in the `@@` header are 1-based and reflect
629
+ * the change's position in the actual file — what the user expects
630
+ * when reading a diff alongside their editor.
631
+ *
632
+ * For `write_file` creating a new file (priorContent === ''), this
633
+ * falls back to the same `--- /dev/null` convention as
634
+ * `buildUnifiedDiff`.
635
+ */
636
+ function buildContextualDiff(payload, priorContent, contextLines = 3) {
637
+ const newContent = applyEditPayload(payload, priorContent);
638
+ const isNewFile = priorContent === "";
639
+ const ops = computeLineDiff(priorContent, newContent);
640
+ const oldLineFor = [];
641
+ const newLineFor = [];
642
+ let ol = 1;
643
+ let nl = 1;
644
+ for (const op of ops) {
645
+ oldLineFor.push(ol);
646
+ newLineFor.push(nl);
647
+ if (op.op !== "add") ol++;
648
+ if (op.op !== "remove") nl++;
649
+ }
650
+ const hunks = [];
651
+ for (let i = 0; i < ops.length; i++) {
652
+ if (ops[i].op === "context") continue;
653
+ const start = Math.max(0, i - contextLines);
654
+ const end = Math.min(ops.length - 1, i + contextLines);
655
+ const last = hunks[hunks.length - 1];
656
+ if (last && start <= last[1] + 1) last[1] = Math.max(last[1], end);
657
+ else hunks.push([start, end]);
658
+ }
659
+ if (hunks.length === 0) return "";
660
+ const parts = [];
661
+ parts.push(isNewFile ? "--- /dev/null" : `--- a/${payload.path}`);
662
+ parts.push(`+++ b/${payload.path}`);
663
+ for (const [start, end] of hunks) {
664
+ const slice = ops.slice(start, end + 1);
665
+ const oldCount = slice.filter((l) => l.op !== "add").length;
666
+ const newCount = slice.filter((l) => l.op !== "remove").length;
667
+ const oldStart = oldCount === 0 ? Math.max(0, oldLineFor[start] - 1) : oldLineFor[start];
668
+ const newStart = newCount === 0 ? Math.max(0, newLineFor[start] - 1) : newLineFor[start];
669
+ parts.push(`@@ -${oldStart},${oldCount} +${newStart},${newCount} @@`);
670
+ for (const line of slice) {
671
+ const prefix = line.op === "add" ? "+" : line.op === "remove" ? "-" : " ";
672
+ parts.push(`${prefix}${line.text}`);
673
+ }
674
+ }
675
+ return `${parts.join("\n")}\n`;
676
+ }
677
+ /**
678
+ * Build a per-hunk digest used by the compact diff view.
679
+ *
680
+ * Strategy:
681
+ * - When `priorContent` is present and the payload describes a real
682
+ * file transformation, compute the contextual diff once, then walk
683
+ * the LCS ops splitting at runs of `add` / `remove` to anchor each
684
+ * summary entry to the **real** file line. This guarantees the
685
+ * summary's `L<n>` matches what the user sees in their editor.
686
+ * - Otherwise, fall back to per-hunk LCS over the (oldString,
687
+ * newString) snippet pair. Line numbers are absent because the
688
+ * snippet has no file position.
689
+ */
690
+ function summarizeEditPayload(payload) {
691
+ const prior = payload.priorContent;
692
+ if (prior !== void 0) return summarizeOpsByHunk(computeLineDiff(prior, applyEditPayload(payload, prior)));
693
+ const hunks = [];
694
+ let totalAdded = 0;
695
+ let totalRemoved = 0;
696
+ for (const hunk of payload.hunks) {
697
+ const ops = computeLineDiff(hunk.oldString, hunk.newString);
698
+ let added = 0;
699
+ let removed = 0;
700
+ let firstOld;
701
+ let firstNew;
702
+ for (const op of ops) if (op.op === "add") {
703
+ added++;
704
+ if (firstNew === void 0) firstNew = op.text;
705
+ } else if (op.op === "remove") {
706
+ removed++;
707
+ if (firstOld === void 0) firstOld = op.text;
708
+ }
709
+ totalAdded += added;
710
+ totalRemoved += removed;
711
+ hunks.push({
712
+ added,
713
+ removed,
714
+ ...firstOld !== void 0 ? { firstOld } : {},
715
+ ...firstNew !== void 0 ? { firstNew } : {}
716
+ });
717
+ }
718
+ return {
719
+ totalAdded,
720
+ totalRemoved,
721
+ hunks
722
+ };
723
+ }
724
+ /**
725
+ * Walk an LCS op stream and emit one summary entry per *run* of
726
+ * non-context ops, with the new-file line number where each run
727
+ * starts. Adjacent add/remove ops collapse into the same entry —
728
+ * matches git's hunk grouping at zero context.
729
+ */
730
+ function summarizeOpsByHunk(ops) {
731
+ const hunks = [];
732
+ let totalAdded = 0;
733
+ let totalRemoved = 0;
734
+ let nl = 1;
735
+ let i = 0;
736
+ while (i < ops.length) {
737
+ if (ops[i].op === "context") {
738
+ nl++;
739
+ i++;
740
+ continue;
741
+ }
742
+ const runStartLine = nl;
743
+ let added = 0;
744
+ let removed = 0;
745
+ let firstOld;
746
+ let firstNew;
747
+ while (i < ops.length && ops[i].op !== "context") {
748
+ const cur = ops[i];
749
+ if (cur.op === "add") {
750
+ added++;
751
+ if (firstNew === void 0) firstNew = cur.text;
752
+ nl++;
753
+ } else {
754
+ removed++;
755
+ if (firstOld === void 0) firstOld = cur.text;
756
+ }
757
+ i++;
758
+ }
759
+ totalAdded += added;
760
+ totalRemoved += removed;
761
+ hunks.push({
762
+ line: runStartLine,
763
+ added,
764
+ removed,
765
+ ...firstOld !== void 0 ? { firstOld } : {},
766
+ ...firstNew !== void 0 ? { firstNew } : {}
767
+ });
768
+ }
769
+ return {
770
+ totalAdded,
771
+ totalRemoved,
772
+ hunks
773
+ };
774
+ }
775
+ function previewEditPayload(payload, priorContent, contextLines = 3) {
776
+ const resolution = [];
777
+ const resolvedHunks = [];
778
+ const perHunkDiff = [];
779
+ let running = priorContent;
780
+ for (const hunk of payload.hunks) {
781
+ if (hunk.oldString === "" || hunk.oldString === running) {
782
+ resolution.push({
783
+ resolved: true,
784
+ via: "exact",
785
+ occurrences: 1
786
+ });
787
+ resolvedHunks.push(hunk);
788
+ perHunkDiff.push(buildContextualDiff({
789
+ ...payload,
790
+ hunks: [hunk]
791
+ }, running, contextLines));
792
+ running = hunk.newString;
793
+ continue;
794
+ }
795
+ const match = resolveOldString(running, hunk.oldString);
796
+ if (!match) {
797
+ resolution.push({ resolved: false });
798
+ resolvedHunks.push(hunk);
799
+ perHunkDiff.push("");
800
+ continue;
801
+ }
802
+ const ambiguous = match.occurrences > 1 && !hunk.replaceAll;
803
+ const styledNew = styleReplacementForVia(hunk.newString, match.via, match.actual);
804
+ const resolvedHunk = {
805
+ oldString: match.actual,
806
+ newString: styledNew,
807
+ ...hunk.replaceAll ? { replaceAll: true } : {}
808
+ };
809
+ resolution.push({
810
+ resolved: !ambiguous,
811
+ via: match.via,
812
+ occurrences: match.occurrences,
813
+ ...ambiguous ? { ambiguous: true } : {}
814
+ });
815
+ resolvedHunks.push(resolvedHunk);
816
+ perHunkDiff.push(ambiguous ? "" : buildContextualDiff({
817
+ ...payload,
818
+ hunks: [resolvedHunk]
819
+ }, running, contextLines));
820
+ if (!ambiguous) running = hunk.replaceAll ? running.replaceAll(match.actual, styledNew) : running.replace(match.actual, styledNew);
821
+ }
822
+ const resolvedPayload = {
823
+ ...payload,
824
+ hunks: resolvedHunks
825
+ };
826
+ const applicableHunks = resolvedHunks.filter((_, i) => resolution[i].resolved);
827
+ return {
828
+ diffText: applicableHunks.length === 0 ? "" : buildContextualDiff({
829
+ ...payload,
830
+ hunks: applicableHunks
831
+ }, priorContent, contextLines),
832
+ resolution,
833
+ perHunkDiff,
834
+ resolvedPayload
835
+ };
836
+ }
837
+ /** Default size budget (UTF-16 code units) for transcript diff rows. */
838
+ const DIFF_RENDER_MAX_BYTES = 524288;
839
+ /** Marker appended to a line hard-truncated mid-content by the size cap. */
840
+ const CLIP_LINE_MARKER = " …⟨line clipped⟩";
841
+ /**
842
+ * Truncate `line` so it fits `budget` code units including the marker,
843
+ * without splitting a UTF-16 surrogate pair. Returns the line unchanged
844
+ * when it already fits.
845
+ */
846
+ function clipLine(line, budget) {
847
+ if (line.length <= budget) return line;
848
+ let end = Math.max(0, budget - 16);
849
+ const code = line.charCodeAt(end - 1);
850
+ if (end > 0 && code >= 55296 && code <= 56319) end--;
851
+ return line.slice(0, end) + CLIP_LINE_MARKER;
852
+ }
853
+ function clipDiffForRender(diff, maxLines = 600, maxBytes = DIFF_RENDER_MAX_BYTES) {
854
+ const lines = diff.split("\n");
855
+ const totalLines = lines.length > 0 && lines[lines.length - 1] === "" ? lines.length - 1 : lines.length;
856
+ if (totalLines <= maxLines && diff.length <= maxBytes) return {
857
+ text: diff,
858
+ hiddenLines: 0,
859
+ totalLines
860
+ };
861
+ const kept = [];
862
+ let used = 0;
863
+ for (let i = 0; i < totalLines; i++) {
864
+ if (kept.length >= maxLines) break;
865
+ const line = lines[i];
866
+ const cost = line.length + 1;
867
+ if (used + cost > maxBytes) {
868
+ if (kept.length === 0) kept.push(clipLine(line, maxBytes));
869
+ break;
870
+ }
871
+ kept.push(line);
872
+ used += cost;
873
+ }
874
+ return {
875
+ text: kept.join("\n"),
876
+ hiddenLines: totalLines - kept.length,
877
+ totalLines
878
+ };
879
+ }
880
+ function buildUnifiedDiff(payload) {
881
+ const parts = [];
882
+ const isNewFile = payload.tool === "write_file" && payload.hunks[0]?.oldString === "";
883
+ parts.push(isNewFile ? `--- /dev/null` : `--- a/${payload.path}`);
884
+ parts.push(`+++ b/${payload.path}`);
885
+ for (const hunk of payload.hunks) {
886
+ const lines = computeLineDiff(hunk.oldString, hunk.newString);
887
+ const oldCount = lines.filter((l) => l.op !== "add").length;
888
+ const newCount = lines.filter((l) => l.op !== "remove").length;
889
+ const oldStart = oldCount === 0 ? 0 : 1;
890
+ const newStart = newCount === 0 ? 0 : 1;
891
+ parts.push(`@@ -${oldStart},${oldCount} +${newStart},${newCount} @@`);
892
+ for (const line of lines) {
893
+ const prefix = line.op === "add" ? "+" : line.op === "remove" ? "-" : " ";
894
+ parts.push(`${prefix}${line.text}`);
895
+ }
896
+ }
897
+ return `${parts.join("\n")}\n`;
898
+ }
899
+ const FILETYPE_BY_EXT = {
900
+ ts: "typescript",
901
+ mts: "typescript",
902
+ cts: "typescript",
903
+ tsx: "typescriptreact",
904
+ js: "javascript",
905
+ mjs: "javascript",
906
+ cjs: "javascript",
907
+ jsx: "javascriptreact",
908
+ py: "python",
909
+ pyi: "python",
910
+ rs: "rust",
911
+ go: "go",
912
+ json: "json",
913
+ jsonc: "json",
914
+ sh: "bash",
915
+ bash: "bash",
916
+ zsh: "bash",
917
+ yaml: "yaml",
918
+ yml: "yaml",
919
+ html: "html",
920
+ htm: "html",
921
+ css: "css",
922
+ md: "markdown",
923
+ markdown: "markdown",
924
+ zig: "zig",
925
+ lua: "lua",
926
+ toml: "toml",
927
+ sql: "sql"
928
+ };
929
+ function filetypeFromPath(path) {
930
+ const cleaned = path.split(/[?#]/, 1)[0];
931
+ const lastDot = cleaned.lastIndexOf(".");
932
+ if (lastDot === -1 || lastDot === cleaned.length - 1) return void 0;
933
+ const ext = cleaned.slice(lastDot + 1).toLowerCase();
934
+ return FILETYPE_BY_EXT[ext];
935
+ }
936
+ //#endregion
937
+ //#region src/chat/prompt-segments.ts
938
+ /**
939
+ * Split a prompt buffer into word-sized atomic segments suitable for a
940
+ * flex-row + flex-wrap renderer (TUI) or a `display: inline` flow with
941
+ * inline-block chips (GUI). Each chip becomes one segment (atomic —
942
+ * never broken across rows); each plain run is split into "word +
943
+ * trailing space" units so wraps land at clean word boundaries.
944
+ *
945
+ * Robust to:
946
+ * - Overlapping refs — sorted by start; later refs that overlap are
947
+ * dropped via the first-wins rule.
948
+ * - Out-of-bounds refs — dropped entirely when `end > text.length` or
949
+ * `start >= text.length`. Partial clipping would silently truncate
950
+ * a chip's label; the caller is in a better position to surface the
951
+ * mismatch (typically a stale `refs` array referencing a previous text).
952
+ * - Whitespace-only plain runs — emitted as their own plain segment
953
+ * so chip-adjacent-to-chip cases keep the original spacing.
954
+ *
955
+ * Word splitter rationale: `\S+\s*` keeps trailing whitespace attached
956
+ * to its preceding word so wrap boundaries land between words (cleanly).
957
+ * A leading-whitespace-only segment is captured by `\s+` so we don't
958
+ * drop it entirely when the plain run starts with a space.
959
+ */
960
+ function splitPromptSegments(text, refs) {
961
+ const sorted = [...refs].filter((r) => r.end > r.start && r.start < text.length && r.end <= text.length).sort((a, b) => a.start - b.start);
962
+ const out = [];
963
+ let cursor = 0;
964
+ for (const ref of sorted) {
965
+ if (ref.start < cursor) continue;
966
+ if (ref.start > cursor) {
967
+ const matches = text.slice(cursor, ref.start).match(/\S+\s*|\s+/g) ?? [];
968
+ for (const m of matches) out.push({
969
+ kind: "plain",
970
+ text: m
971
+ });
972
+ }
973
+ out.push({
974
+ kind: "chip",
975
+ text: text.slice(ref.start, ref.end),
976
+ providerId: ref.providerId
977
+ });
978
+ cursor = ref.end;
979
+ }
980
+ if (cursor < text.length) {
981
+ const matches = text.slice(cursor).match(/\S+\s*|\s+/g) ?? [];
982
+ for (const m of matches) out.push({
983
+ kind: "plain",
984
+ text: m
985
+ });
986
+ }
987
+ return out;
988
+ }
989
+ /**
990
+ * File-mention refs recovered from a prompt's text: `@<path>` at the start
991
+ * or after whitespace, where the path looks like one (has a `/` or a `.`),
992
+ * trailing punctuation excluded (the files completion's own rule).
993
+ *
994
+ * Refs are known only to the client that sent the prompt, which typed the
995
+ * mention through a completion. The persisted turn and the send echo other
996
+ * windows receive carry the text alone, so without this a prompt's chips
997
+ * existed in the sender's live transcript only: gone after a reload, never
998
+ * shown in another window or the TUI. Replay and the echo fill refs from
999
+ * this when the event has none, so every client paints the same prompt.
1000
+ * Skills and chats mentions are not inferred: their tokens (`/name`,
1001
+ * `#token`) are ordinary text too often to guess without the catalogs.
1002
+ */
1003
+ function inferPromptRefs(text) {
1004
+ const refs = [];
1005
+ for (const m of text.matchAll(/(^|\s)@(\S+)/g)) {
1006
+ const path = m[2].replace(/[.,;:)\]}!?'"]+$/, "");
1007
+ if (!/[/.]/.test(path) || path.includes("@")) continue;
1008
+ const start = m.index + m[1].length;
1009
+ refs.push({
1010
+ start,
1011
+ end: start + 1 + path.length,
1012
+ providerId: "files"
1013
+ });
1014
+ }
1015
+ return refs;
1016
+ }
1017
+ /**
1018
+ * The segments cut into the lines the user typed. A flex-wrap row cannot
1019
+ * break on a newline inside one of its items, so each line renders as its
1020
+ * own row; an empty array is a blank line.
1021
+ */
1022
+ function promptSegmentLines(segments) {
1023
+ const lines = [[]];
1024
+ for (const segment of segments) {
1025
+ if (segment.kind !== "plain") {
1026
+ lines[lines.length - 1].push(segment);
1027
+ continue;
1028
+ }
1029
+ segment.text.split("\n").forEach((part, i) => {
1030
+ if (i > 0) lines.push([]);
1031
+ if (part) lines[lines.length - 1].push({
1032
+ kind: "plain",
1033
+ text: part
1034
+ });
1035
+ });
1036
+ }
1037
+ return lines;
1038
+ }
1039
+ //#endregion
1040
+ //#region src/chat/settings-defaults.ts
1041
+ const DEFAULT_SETTINGS = {
1042
+ showThinking: true,
1043
+ toolCallDisplay: "formatted",
1044
+ showToolResults: true,
1045
+ groupToolCalls: false,
1046
+ showFullShellOutput: false,
1047
+ showRunReceipt: true,
1048
+ showCacheNotices: true,
1049
+ safeMode: true,
1050
+ useDaemon: false,
1051
+ remoteHosts: false,
1052
+ orchestration: false,
1053
+ loadProjectExtensions: false,
1054
+ importForeignConfigs: false,
1055
+ importRulerConfigs: true,
1056
+ hideSubagentOutput: true,
1057
+ subagentModels: true,
1058
+ queueMessages: true,
1059
+ theme: "default",
1060
+ showAllProjects: false,
1061
+ resumeLastSession: true,
1062
+ persistToolResults: true,
1063
+ stableToolList: false,
1064
+ codemode: false,
1065
+ sandbox: false,
1066
+ sandboxNetwork: "allow",
1067
+ sandboxAllowWrite: "",
1068
+ autoCompact: true,
1069
+ autoCompactThreshold: .8,
1070
+ resumeOnMaxTokens: false,
1071
+ maxOutputTokens: 0,
1072
+ maxTurns: 0,
1073
+ retryMaxAttempts: 0,
1074
+ maxCostUsd: 0,
1075
+ maxTotalTokens: 0,
1076
+ maxWallMinutes: 0,
1077
+ thinkingBinding: "drop_block",
1078
+ showEditDiffs: true,
1079
+ editDiffDisplay: "full",
1080
+ transcriptDensity: "full",
1081
+ showCompactionSummary: false,
1082
+ compactionModel: "",
1083
+ targetFps: 60,
1084
+ mouseInteractions: true,
1085
+ interactionMode: "ask",
1086
+ smoothStreaming: true,
1087
+ fileLogging: false,
1088
+ showTodoIndicator: true,
1089
+ showUsageIndicator: true,
1090
+ showThrobber: false,
1091
+ artifacts: true,
1092
+ browser: true,
1093
+ browserAgent: true,
1094
+ browserAutoShow: true,
1095
+ terminal: true,
1096
+ terminalAgent: true,
1097
+ terminalAgentTasks: true,
1098
+ closeTerminalOnCleanExit: true,
1099
+ confirmGitSync: true,
1100
+ sidebarRunDetails: true,
1101
+ openIn: "editor",
1102
+ checkForUpdates: true,
1103
+ subscriptionUsage: true,
1104
+ uiMode: "full",
1105
+ userInstructionsScope: "both",
1106
+ ctrlCBehavior: "quit",
1107
+ terminalTitle: "off",
1108
+ sessionIcon: "",
1109
+ attentionIcon: "",
1110
+ activeIcon: "",
1111
+ attachmentsEnabled: true,
1112
+ externalEditor: true,
1113
+ inlineAutocomplete: false
1114
+ };
1115
+ //#endregion
1116
+ //#region src/chat/hosts/types.ts
1117
+ /** A refused `add` / `rename`; `code` says why. */
1118
+ var HostRegistryError = class extends Error {
1119
+ code;
1120
+ constructor(code, message) {
1121
+ super(message);
1122
+ this.code = code;
1123
+ this.name = "HostRegistryError";
1124
+ }
1125
+ };
1126
+ //#endregion
1127
+ //#region src/chat/secret-shapes.ts
1128
+ /**
1129
+ * What a credential looks like, as pure predicates: secret-looking names
1130
+ * (`--api-key`, `DB_PASS`, `"apiKey"`), known token shapes (`sk-…`,
1131
+ * `ghp_…`, `zds_…`) and high-entropy values. Shared by everything that must
1132
+ * keep a token out of what it shows or saves: the host's MCP catalog
1133
+ * redaction (`src/ipc/daemon/redact.ts`) and the remote host URL check
1134
+ * (`./hosts/url.ts`). Node-free.
1135
+ *
1136
+ * Over-matching an ordinary word is a cosmetic loss; under-matching leaks a
1137
+ * credential, so the rules lean wide, but stay off file paths, package names
1138
+ * and plain words (`passthrough`, `bypass`, `keymap`).
1139
+ */
1140
+ /**
1141
+ * A secret-looking name: a flag (`--auth-token`), a variable (`DB_PASS`), a
1142
+ * JSON key (`apiKey`) or a connection-string key (`Password`). `pass` and
1143
+ * `key` count only as a whole word or a `-` / `_` segment at the end.
1144
+ */
1145
+ const SECRET_NAME = /token|secret|passw(?:or)?d|passphrase|pwd|api[-_]?key|access[-_]?key|private[-_]?key|auth|credential|bearer|cookie|(?:^|[-_])(?:pass|key)$/i;
1146
+ /** Token prefixes issued by common services, with enough body to be a credential. */
1147
+ const KNOWN_TOKEN = /(?<![\w-])(?:sk-[\w-]{16,}|sk_(?:live|test)_\w{16,}|gh[pousr]_\w{20,}|github_pat_\w{20,}|xox[abposr]-[\w-]{10,}|(?:AKIA|ASIA)[0-9A-Z]{16}|glpat-[\w-]{20,}|zds_[\w-]{20,}|AIza[\w-]{30,})/g;
1148
+ function isSecretName(name) {
1149
+ return SECRET_NAME.test(name);
1150
+ }
1151
+ /** A known token shape somewhere in `value`. */
1152
+ function containsKnownToken(value) {
1153
+ KNOWN_TOKEN.lastIndex = 0;
1154
+ return KNOWN_TOKEN.test(value);
1155
+ }
1156
+ function entropy(value) {
1157
+ const counts = /* @__PURE__ */ new Map();
1158
+ for (const char of value) counts.set(char, (counts.get(char) ?? 0) + 1);
1159
+ let bits = 0;
1160
+ for (const count of counts.values()) {
1161
+ const p = count / value.length;
1162
+ bits -= p * Math.log2(p);
1163
+ }
1164
+ return bits;
1165
+ }
1166
+ /**
1167
+ * A whole value that looks like a credential: a known token shape, a long
1168
+ * hex / UUID-like id, or a long random mix of cases and digits. Words joined
1169
+ * by dashes (`server-2024-edition`) and paths stay readable.
1170
+ */
1171
+ function looksLikeSecret(value) {
1172
+ KNOWN_TOKEN.lastIndex = 0;
1173
+ const known = KNOWN_TOKEN.exec(value);
1174
+ if (known && known[0] === value) return true;
1175
+ if (value.length < 20 || !/^[\w\-+=.~]+$/.test(value) || !/\d/.test(value) || !/[a-z]/i.test(value)) return false;
1176
+ const digits = value.replace(/\D/g, "").length;
1177
+ if (/^[\da-f-]+$/i.test(value)) return digits / value.length >= .25;
1178
+ return /[a-z]/.test(value) && /[A-Z]/.test(value) && entropy(value) >= 4;
1179
+ }
1180
+ function safeDecode(segment) {
1181
+ try {
1182
+ return decodeURIComponent(segment);
1183
+ } catch {
1184
+ return segment;
1185
+ }
1186
+ }
1187
+ /** A URL path segment that carries a credential (as is, or percent-decoded). */
1188
+ function isSecretPathSegment(segment) {
1189
+ const decoded = safeDecode(segment);
1190
+ return looksLikeSecret(segment) || looksLikeSecret(decoded) || containsKnownToken(decoded);
1191
+ }
1192
+ //#endregion
1193
+ //#region src/chat/hosts/url.ts
1194
+ /**
1195
+ * Host URLs a client accepts: `wss://`, or `ws://` to this machine only (a
1196
+ * token must not cross the network in the clear), with no credentials in
1197
+ * them: no `user:pass@`, no query string, no fragment, no token-looking
1198
+ * path segment (`wss://h/zds_…`, a long random id: the shapes the MCP
1199
+ * catalog redacts, `../secret-shapes`). Tokens go in the token field, and a
1200
+ * URL ends up in hosts.json, error messages and the GUI's renderer.
1201
+ * Messages show {@link displayHostUrl}, never the input. Node-free.
1202
+ */
1203
+ var RemoteHostError = class extends Error {
1204
+ constructor(message) {
1205
+ super(message);
1206
+ this.name = "RemoteHostError";
1207
+ }
1208
+ };
1209
+ /**
1210
+ * A loopback host: `localhost`, `127.x.x.x` or `::1` (bracketed, as in a URL,
1211
+ * or bare, as an interface to bind). The one check for both ends: a client
1212
+ * allowing `ws://`, a server refusing to listen in the clear.
1213
+ */
1214
+ function isLoopbackHost(host) {
1215
+ const bare = host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host;
1216
+ return bare === "localhost" || bare === "::1" || /^127\.\d+\.\d+\.\d+$/.test(bare);
1217
+ }
1218
+ /** Shown in place of a path segment that looks like a credential. */
1219
+ const REDACTED_SEGMENT = "<redacted>";
1220
+ /** Scheme, host, port and path of a URL (token-looking path segments redacted): what is safe to show or log. */
1221
+ function displayHostUrl(raw) {
1222
+ try {
1223
+ const url = new URL(raw.trim());
1224
+ const path = url.pathname.split("/").map((segment) => isSecretPathSegment(segment) ? REDACTED_SEGMENT : segment).join("/");
1225
+ return `${url.protocol}//${url.host}${path.replace(/\/$/, "")}`;
1226
+ } catch {
1227
+ return "<invalid URL>";
1228
+ }
1229
+ }
1230
+ /** `raw` carries something {@link parseRemoteHostUrl} refuses as a credential (userinfo, query, fragment, a token-looking path segment). */
1231
+ function urlCarriesSecrets(raw) {
1232
+ if (/[@?#]/.test(raw)) return true;
1233
+ try {
1234
+ return new URL(raw.trim()).pathname.split("/").some(isSecretPathSegment);
1235
+ } catch {
1236
+ return false;
1237
+ }
1238
+ }
1239
+ /** Validate and normalize a host URL (no trailing slash); throws {@link RemoteHostError}. */
1240
+ function parseRemoteHostUrl(raw) {
1241
+ let url;
1242
+ try {
1243
+ url = new URL(raw.trim());
1244
+ } catch {
1245
+ throw new RemoteHostError("Invalid host URL: expected wss://host[:port].");
1246
+ }
1247
+ const shown = displayHostUrl(raw);
1248
+ if (url.username !== "" || url.password !== "") throw new RemoteHostError(`Host URLs can't carry a user or password (${shown}): put the token in the token field (or --token-file), not in the URL.`);
1249
+ if (url.search !== "" || raw.includes("?")) throw new RemoteHostError(`Host URLs can't carry a query string (${shown}): remove it; a token goes in the token field (or --token-file).`);
1250
+ if (url.hash !== "" || raw.includes("#")) throw new RemoteHostError(`Host URLs can't carry a fragment (${shown}): remove it.`);
1251
+ if (url.pathname.split("/").some(isSecretPathSegment)) throw new RemoteHostError(`Host URLs can't carry a token in their path (${url.protocol}//${url.host}): remove it; a token goes in the token field (or --token-file).`);
1252
+ if (url.protocol === "wss:" || url.protocol === "ws:" && isLoopbackHost(url.hostname)) return url.href.replace(/\/$/, "");
1253
+ if (url.protocol === "ws:") throw new RemoteHostError(`Refusing ws://${url.host}: the token would travel unencrypted. Use wss:// (ws:// is only for 127.0.0.1 / localhost).`);
1254
+ throw new RemoteHostError(`Invalid host URL ${shown}: expected wss://host[:port].`);
1255
+ }
1256
+ //#endregion
1257
+ export { resolveApprovalForPayload as A, isAllowedBrowserUrl as B, splitLines as C, maskToOutcomeKinds as D, buildEditOutcomesAnnotation as E, commandNoteText as F, normalizeBrowserUrl as H, commandStepLabel as I, gatherCommandNotes as L, stripEditOutcomesAnnotation as M, summarizeOutcomes as N, mergeApprovalAndBodyOutcomes as O, commandHeaderBlock as P, noteDisplay as R, previewEditPayload as S, tokenize as T, isLocalBrowserUrl as V, clipDiffForRender as _, KNOWN_TOKEN as a, extractEditPayload as b, looksLikeSecret as c, inferPromptRefs as d, promptSegmentLines as f, buildUnifiedDiff as g, buildContextualDiff as h, urlCarriesSecrets as i, rewriteMultiEditHeader as j, parseEditOutcomesFromResult as k, HostRegistryError as l, applyEditPayload as m, displayHostUrl as n, isSecretName as o, splitPromptSegments as p, parseRemoteHostUrl as r, isSecretPathSegment as s, RemoteHostError as t, DEFAULT_SETTINGS as u, computeInlineDiff as v, summarizeEditPayload as w, filetypeFromPath as x, computeLineDiff as y, parseCommandHeader as z };
1258
+
1259
+ //# sourceMappingURL=url-D8HCl65b.js.map