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,952 @@
1
+ import { t as projectUserPaths } from "./project-user-paths-BSgtrRxl.js";
2
+ import { i as writeJsonFileAtomic, t as OWNER_ONLY } from "./atomic-write-Ijgf2Mhc.js";
3
+ import { n as displayHostUrl, u as DEFAULT_SETTINGS } from "./url-D8HCl65b.js";
4
+ import { B as parseMcpsFile, Ot as readProjects, P as userSystemMdPath, i as probeUnsavedHost, rt as loadState, t as createHostRegistry } from "./registry-D6ShBWJU.js";
5
+ import { a as readProviderCredential } from "./credentials-JttEuRON.js";
6
+ import { f as HostIdentityError, i as SYNC_MODES, n as SYNC_CATEGORIES, s as fieldCategory } from "./types-CH5XpIHw.js";
7
+ import { g as hostRefOf, i as IpcVersionMismatchError, n as hashValue, r as isRecord, t as isSyncableSetting } from "./settings-keys-Ckf29NeM.js";
8
+ import { t as keepHostConnected } from "./connection-loop-gdh22LTI.js";
9
+ import { n as connectWsClient, t as HostAuthError } from "./ws-client-N7NxzvQp.js";
10
+ import { existsSync, lstatSync, readFileSync, readdirSync, statSync, watch } from "node:fs";
11
+ import { basename, dirname, join, relative, sep } from "node:path";
12
+ import { hostname } from "node:os";
13
+ import { randomUUID } from "node:crypto";
14
+ //#region src/chat/sync/collect.ts
15
+ const MAX_FILE_BYTES = 1048576;
16
+ const MAX_SKILL_BYTES = 4194304;
17
+ const MAX_SKILL_FILES = 200;
18
+ const MAX_DEPTH = 8;
19
+ /** Not part of a skill: version control and installed dependencies. */
20
+ const SKIPPED_DIRS = /* @__PURE__ */ new Set([".git", "node_modules"]);
21
+ function userPaths(sources, subPath) {
22
+ return projectUserPaths({
23
+ subPath,
24
+ cwd: sources.home,
25
+ home: sources.home,
26
+ prefix: sources.prefix
27
+ }).filter((p) => p.source === "user").map((p) => p.path);
28
+ }
29
+ /** Every file and folder a category reads: what the watchers watch. */
30
+ function syncWatchTargets(sources) {
31
+ return [
32
+ {
33
+ category: "settings",
34
+ path: sources.statePath,
35
+ recursive: false
36
+ },
37
+ {
38
+ category: "safelists",
39
+ path: join(sources.dataDir, "projects.json"),
40
+ recursive: false
41
+ },
42
+ {
43
+ category: "files",
44
+ path: userSystemMdPath({
45
+ home: sources.home,
46
+ prefix: sources.prefix
47
+ }),
48
+ recursive: false
49
+ },
50
+ ...userPaths(sources, "skills").map((path) => ({
51
+ category: "files",
52
+ path,
53
+ recursive: true
54
+ })),
55
+ ...userPaths(sources, "mcps.json").map((path) => ({
56
+ category: "mcps",
57
+ path,
58
+ recursive: false
59
+ })),
60
+ ...userPaths(sources, "extensions").map((path) => ({
61
+ category: "extensions",
62
+ path,
63
+ recursive: true
64
+ })),
65
+ {
66
+ category: "keys",
67
+ path: join(sources.dataDir, "credentials.json"),
68
+ recursive: false
69
+ }
70
+ ];
71
+ }
72
+ function settingsPayload(sources) {
73
+ const stored = loadState(sources.statePath).settings ?? {};
74
+ const merged = {
75
+ ...DEFAULT_SETTINGS,
76
+ ...stored
77
+ };
78
+ return { values: Object.fromEntries(Object.entries(merged).filter(([key]) => key in DEFAULT_SETTINGS && isSyncableSetting(key))) };
79
+ }
80
+ function safelistsPayload(sources) {
81
+ const projects = readProjects(sources.dataDir);
82
+ return { projects: Object.fromEntries(Object.entries(projects).flatMap(([path, entry]) => Array.isArray(entry?.safelist) ? [[path, [...entry.safelist]]] : [])) };
83
+ }
84
+ /** A skill folder's files, or null when it is over the bounds (or not a plain folder). */
85
+ function skillFiles(dir) {
86
+ const files = [];
87
+ let total = 0;
88
+ const walk = (at, depth) => {
89
+ if (depth > MAX_DEPTH) return false;
90
+ for (const name of readdirSync(at).sort()) {
91
+ const path = join(at, name);
92
+ const stat = lstatSync(path);
93
+ if (stat.isDirectory()) {
94
+ if (SKIPPED_DIRS.has(name)) continue;
95
+ if (!walk(path, depth + 1)) return false;
96
+ } else if (stat.isFile()) {
97
+ if (stat.size > MAX_FILE_BYTES || files.length >= MAX_SKILL_FILES) return false;
98
+ total += stat.size;
99
+ if (total > MAX_SKILL_BYTES) return false;
100
+ files.push({
101
+ path: relative(dir, path).split(sep).join("/"),
102
+ data: readFileSync(path).toString("base64")
103
+ });
104
+ }
105
+ }
106
+ return true;
107
+ };
108
+ try {
109
+ return walk(dir, 1) && files.length > 0 ? files : null;
110
+ } catch {
111
+ return null;
112
+ }
113
+ }
114
+ /** The user-scope skills: name → folder, the first root of a name winning (as discovery does). */
115
+ function userSkillDirs(sources) {
116
+ const found = /* @__PURE__ */ new Map();
117
+ for (const root of userPaths(sources, "skills")) {
118
+ let names;
119
+ try {
120
+ names = readdirSync(root).sort();
121
+ } catch {
122
+ continue;
123
+ }
124
+ for (const name of names) {
125
+ const dir = join(root, name);
126
+ if (!found.has(name) && !name.startsWith(".") && existsSync(join(dir, "SKILL.md")) && lstatSync(dir).isDirectory()) found.set(name, dir);
127
+ }
128
+ }
129
+ return found;
130
+ }
131
+ function filesPayload(sources) {
132
+ const mdPath = userSystemMdPath({
133
+ home: sources.home,
134
+ prefix: sources.prefix
135
+ });
136
+ const systemMd = existsSync(mdPath) ? readFileSync(mdPath, "utf8") : null;
137
+ const skills = [];
138
+ for (const [name, dir] of userSkillDirs(sources)) {
139
+ const files = skillFiles(dir);
140
+ if (files) skills.push({
141
+ name,
142
+ files
143
+ });
144
+ }
145
+ return {
146
+ systemMd,
147
+ skills
148
+ };
149
+ }
150
+ function mcpsPayload(sources) {
151
+ const servers = /* @__PURE__ */ new Map();
152
+ for (const path of userPaths(sources, "mcps.json")) {
153
+ if (!existsSync(path)) continue;
154
+ try {
155
+ for (const server of parseMcpsFile(readFileSync(path, "utf8"))) if (!servers.has(server.name)) servers.set(server.name, server);
156
+ } catch {}
157
+ }
158
+ return { servers: [...servers.values()] };
159
+ }
160
+ /** User-scope extensions: those with a source (syncable) and the local ones (not). */
161
+ function userExtensions(sources) {
162
+ const syncable = [];
163
+ const local = [];
164
+ const seen = /* @__PURE__ */ new Set();
165
+ for (const root of userPaths(sources, "extensions")) {
166
+ let names;
167
+ try {
168
+ names = readdirSync(root).sort();
169
+ } catch {
170
+ continue;
171
+ }
172
+ for (const name of names) {
173
+ const dir = join(root, name);
174
+ if (name.startsWith(".") || seen.has(name) || !lstatSync(dir).isDirectory()) continue;
175
+ seen.add(name);
176
+ let provenance = null;
177
+ try {
178
+ provenance = JSON.parse(readFileSync(join(dir, ".install.json"), "utf8"));
179
+ } catch {}
180
+ if (provenance && typeof provenance.spec === "string" && provenance.spec.trim() !== "") syncable.push({
181
+ name,
182
+ spec: provenance.spec,
183
+ ...typeof provenance.extension === "string" ? { extension: provenance.extension } : {}
184
+ });
185
+ else local.push(name);
186
+ }
187
+ }
188
+ return {
189
+ syncable,
190
+ local
191
+ };
192
+ }
193
+ /** Providers with an API key stored here: what the keys category can offer. */
194
+ function storedApiKeyProviders(sources) {
195
+ return Object.values(sources.providers()).flatMap((descriptor) => {
196
+ const credential = readProviderCredential(sources.dataDir, descriptor);
197
+ return credential?.kind === "apikey" && credential.value ? [{
198
+ key: descriptor.key,
199
+ label: descriptor.label
200
+ }] : [];
201
+ });
202
+ }
203
+ function keysPayload(sources, optedIn) {
204
+ const providers = sources.providers();
205
+ return { keys: optedIn.flatMap((provider) => {
206
+ const descriptor = providers[provider];
207
+ const credential = descriptor ? readProviderCredential(sources.dataDir, descriptor) : void 0;
208
+ return credential?.kind === "apikey" && credential.value ? [{
209
+ provider,
210
+ key: credential.value
211
+ }] : [];
212
+ }) };
213
+ }
214
+ function collectSyncPayload(category, sources, optedInKeys = []) {
215
+ switch (category) {
216
+ case "settings": return settingsPayload(sources);
217
+ case "safelists": return safelistsPayload(sources);
218
+ case "files": return filesPayload(sources);
219
+ case "mcps": return mcpsPayload(sources);
220
+ case "extensions": return { extensions: userExtensions(sources).syncable };
221
+ case "keys": return keysPayload(sources, optedInKeys);
222
+ }
223
+ }
224
+ //#endregion
225
+ //#region src/chat/sync/local.ts
226
+ const DEFAULT_SERVER_SYNC = {
227
+ mode: "off",
228
+ categories: ["settings"],
229
+ keys: [],
230
+ pending: [],
231
+ sent: {},
232
+ results: {}
233
+ };
234
+ function hostsSyncPath(dataDir) {
235
+ return join(dataDir, "hosts-sync.json");
236
+ }
237
+ function deviceIdentityPath(dataDir) {
238
+ return join(dataDir, "device.json");
239
+ }
240
+ function readJson(path) {
241
+ if (!existsSync(path)) return void 0;
242
+ try {
243
+ return JSON.parse(readFileSync(path, "utf8"));
244
+ } catch {
245
+ return;
246
+ }
247
+ }
248
+ /** This computer's device id and name, made on first use. */
249
+ function readDeviceIdentity(dataDir, name) {
250
+ const raw = readJson(deviceIdentityPath(dataDir));
251
+ if (isRecord(raw) && typeof raw.id === "string" && raw.id !== "") return {
252
+ id: raw.id,
253
+ name: name ?? (typeof raw.name === "string" && raw.name ? raw.name : hostname())
254
+ };
255
+ const identity = {
256
+ id: randomUUID(),
257
+ name: name ?? hostname()
258
+ };
259
+ writeJsonFileAtomic(deviceIdentityPath(dataDir), identity, OWNER_ONLY);
260
+ return identity;
261
+ }
262
+ function categoriesOf(value) {
263
+ return Array.isArray(value) ? SYNC_CATEGORIES.filter((c) => value.includes(c)) : [];
264
+ }
265
+ function serverConfigOf(raw) {
266
+ if (!isRecord(raw)) return { ...DEFAULT_SERVER_SYNC };
267
+ return {
268
+ mode: SYNC_MODES.includes(raw.mode) ? raw.mode : "off",
269
+ categories: categoriesOf(raw.categories),
270
+ keys: Array.isArray(raw.keys) ? raw.keys.filter((k) => typeof k === "string") : [],
271
+ pending: categoriesOf(raw.pending),
272
+ sent: isRecord(raw.sent) ? Object.fromEntries(Object.entries(raw.sent).filter(([c, h]) => SYNC_CATEGORIES.includes(c) && typeof h === "string")) : {},
273
+ ...typeof raw.lastSyncAt === "number" ? { lastSyncAt: raw.lastSyncAt } : {},
274
+ ...typeof raw.lastError === "string" ? { lastError: raw.lastError } : {},
275
+ results: isRecord(raw.results) ? raw.results : {}
276
+ };
277
+ }
278
+ function readSyncConfigs(dataDir) {
279
+ const raw = readJson(hostsSyncPath(dataDir));
280
+ if (!isRecord(raw) || !isRecord(raw.servers)) return {};
281
+ return Object.fromEntries(Object.entries(raw.servers).map(([key, value]) => [key, serverConfigOf(value)]));
282
+ }
283
+ function writeSyncConfigs(dataDir, servers) {
284
+ const file = {
285
+ version: 1,
286
+ servers
287
+ };
288
+ writeJsonFileAtomic(hostsSyncPath(dataDir), file, OWNER_ONLY);
289
+ }
290
+ //#endregion
291
+ //#region src/chat/sync/pusher.ts
292
+ const errorText = (err) => err instanceof Error ? err.message : String(err);
293
+ function createSyncPusher({ sources, device, emit }) {
294
+ const configs = readSyncConfigs(sources.dataDir);
295
+ const clients = /* @__PURE__ */ new Map();
296
+ const statuses = /* @__PURE__ */ new Map();
297
+ const conflicts = /* @__PURE__ */ new Map();
298
+ const flushing = /* @__PURE__ */ new Map();
299
+ const again = /* @__PURE__ */ new Set();
300
+ let stopped = false;
301
+ const configOf = (key) => configs[key] ?? {
302
+ ...DEFAULT_SERVER_SYNC,
303
+ categories: [...DEFAULT_SERVER_SYNC.categories]
304
+ };
305
+ const save = (key, config) => {
306
+ configs[key] = config;
307
+ writeSyncConfigs(sources.dataDir, configs);
308
+ emit();
309
+ };
310
+ const fail = (key, err) => save(key, {
311
+ ...configOf(key),
312
+ lastError: errorText(err)
313
+ });
314
+ /** Categories whose snapshot here differs from what was last pushed to the server. */
315
+ const changedCategories = (config, only) => config.categories.filter((category) => {
316
+ if (only && category !== only) return false;
317
+ try {
318
+ return hashValue(collectSyncPayload(category, sources, config.keys)) !== config.sent[category];
319
+ } catch {
320
+ return true;
321
+ }
322
+ });
323
+ const queue = (key, categories) => {
324
+ const config = configOf(key);
325
+ const pending = SYNC_CATEGORIES.filter((c) => config.pending.includes(c) || categories.includes(c));
326
+ if (pending.length !== config.pending.length) save(key, {
327
+ ...config,
328
+ pending
329
+ });
330
+ };
331
+ async function claim(key, client, takeover) {
332
+ const config = configOf(key);
333
+ const result = await client.request("sync.claim", {
334
+ deviceId: device.id,
335
+ deviceName: device.name,
336
+ categories: config.categories,
337
+ keys: config.keys,
338
+ ...takeover ? { takeover: true } : {}
339
+ });
340
+ statuses.set(key, result.status);
341
+ if (result.claimed) conflicts.delete(key);
342
+ else conflicts.set(key, result.status.source?.deviceName ?? "another device");
343
+ return result.claimed;
344
+ }
345
+ async function flushOnce(key, takeover) {
346
+ const client = clients.get(key);
347
+ let config = configOf(key);
348
+ if (!client || !client.hello.sync || config.mode === "off" || config.pending.length === 0 && !takeover || stopped) return;
349
+ try {
350
+ if (!await claim(key, client, takeover)) return;
351
+ for (const category of [...configOf(key).pending]) {
352
+ config = configOf(key);
353
+ if (!config.categories.includes(category)) {
354
+ save(key, {
355
+ ...config,
356
+ pending: config.pending.filter((c) => c !== category)
357
+ });
358
+ continue;
359
+ }
360
+ const payload = collectSyncPayload(category, sources, config.keys);
361
+ const result = await client.request("sync.push", {
362
+ deviceId: device.id,
363
+ category,
364
+ payload
365
+ });
366
+ config = configOf(key);
367
+ const { lastError: _dropped, ...rest } = config;
368
+ save(key, {
369
+ ...rest,
370
+ pending: config.pending.filter((c) => c !== category),
371
+ sent: {
372
+ ...config.sent,
373
+ [category]: hashValue(payload)
374
+ },
375
+ results: {
376
+ ...config.results,
377
+ [category]: result
378
+ },
379
+ lastSyncAt: Date.now()
380
+ });
381
+ }
382
+ statuses.set(key, await client.request("sync.status", {}));
383
+ } catch (err) {
384
+ fail(key, err);
385
+ }
386
+ }
387
+ /** Push the queue if the server is connected and this device is its source; `takeover` claims it first. */
388
+ function flush(key, takeover = false) {
389
+ const running = flushing.get(key);
390
+ if (running && !takeover) {
391
+ again.add(key);
392
+ return running;
393
+ }
394
+ const run = (async () => {
395
+ if (running) await running;
396
+ await flushOnce(key, takeover);
397
+ while (again.delete(key)) await flushOnce(key, false);
398
+ })().finally(() => {
399
+ if (flushing.get(key) === run) flushing.delete(key);
400
+ emit();
401
+ });
402
+ flushing.set(key, run);
403
+ emit();
404
+ return run;
405
+ }
406
+ /** Read the server's record: who syncs there now. */
407
+ async function refresh(key) {
408
+ const client = clients.get(key);
409
+ if (!client?.hello.sync) return;
410
+ try {
411
+ const status = await client.request("sync.status", {});
412
+ statuses.set(key, status);
413
+ if (!status.source || status.source.deviceId === device.id) conflicts.delete(key);
414
+ else if (configOf(key).mode !== "off") conflicts.set(key, status.source.deviceName);
415
+ } catch {}
416
+ emit();
417
+ }
418
+ /** This device stops being the server's source (the server keeps what it has). */
419
+ async function release(key) {
420
+ const client = clients.get(key);
421
+ conflicts.delete(key);
422
+ if (!client?.hello.sync) return;
423
+ await client.request("sync.release", { deviceId: device.id }).catch(() => void 0);
424
+ const status = await client.request("sync.status", {}).catch(() => null);
425
+ if (status) statuses.set(key, status);
426
+ }
427
+ function forget(key) {
428
+ clients.delete(key);
429
+ statuses.delete(key);
430
+ conflicts.delete(key);
431
+ if (configs[key]) {
432
+ delete configs[key];
433
+ writeSyncConfigs(sources.dataDir, configs);
434
+ }
435
+ }
436
+ return {
437
+ configs,
438
+ clients,
439
+ statuses,
440
+ conflicts,
441
+ flushing,
442
+ configOf,
443
+ save,
444
+ fail,
445
+ changedCategories,
446
+ queue,
447
+ claim,
448
+ flush,
449
+ refresh,
450
+ release,
451
+ forget,
452
+ stop: () => {
453
+ stopped = true;
454
+ clients.clear();
455
+ }
456
+ };
457
+ }
458
+ //#endregion
459
+ //#region src/chat/sync/watchers.ts
460
+ function createSyncWatchers({ sources, debounceMs, check }) {
461
+ let watchers = [];
462
+ let timer = null;
463
+ let closed = false;
464
+ const dirty = /* @__PURE__ */ new Set();
465
+ const closeAll = () => {
466
+ for (const w of watchers) w.close();
467
+ watchers = [];
468
+ };
469
+ const schedule = (category) => {
470
+ if (closed) return;
471
+ dirty.add(category ?? "all");
472
+ if (timer) return;
473
+ timer = setTimeout(() => {
474
+ timer = null;
475
+ const which = [...dirty];
476
+ dirty.clear();
477
+ check(which);
478
+ }, debounceMs);
479
+ };
480
+ return {
481
+ schedule,
482
+ refresh(active) {
483
+ closeAll();
484
+ if (closed || !active) return;
485
+ for (const target of syncWatchTargets(sources)) {
486
+ const isDir = existsSync(target.path) && statSync(target.path).isDirectory();
487
+ const at = isDir ? target.path : dirname(target.path);
488
+ if (!existsSync(at)) continue;
489
+ const name = basename(target.path);
490
+ try {
491
+ watchers.push(watch(at, {
492
+ recursive: isDir && target.recursive,
493
+ persistent: false
494
+ }, (_event, changed) => {
495
+ if (isDir || changed === null || String(changed) === name) schedule(target.category);
496
+ }));
497
+ } catch {}
498
+ }
499
+ },
500
+ count: () => watchers.length,
501
+ close() {
502
+ closed = true;
503
+ if (timer) clearTimeout(timer);
504
+ timer = null;
505
+ closeAll();
506
+ }
507
+ };
508
+ }
509
+ //#endregion
510
+ //#region src/chat/sync/engine.ts
511
+ /**
512
+ * Engines CREATED in this process so far: monotonic (never decremented when
513
+ * one stops), not a live count. The containment tests compare it before and
514
+ * after a mount to prove an engine did, or did not, start.
515
+ */
516
+ let engines = 0;
517
+ function createSyncEngine(options) {
518
+ engines++;
519
+ const sources = {
520
+ dataDir: options.dataDir,
521
+ statePath: options.statePath,
522
+ home: options.home,
523
+ prefix: options.prefix,
524
+ providers: options.providers
525
+ };
526
+ const device = readDeviceIdentity(options.dataDir, options.deviceName);
527
+ const listeners = /* @__PURE__ */ new Set();
528
+ const emit = () => {
529
+ for (const listener of [...listeners]) try {
530
+ listener();
531
+ } catch {}
532
+ };
533
+ const pusher = createSyncPusher({
534
+ sources,
535
+ device,
536
+ emit
537
+ });
538
+ const { configOf, save, queue, flush, clients, statuses, conflicts } = pusher;
539
+ const keeping = () => Object.entries(pusher.configs).filter(([, c]) => c.mode === "keep").map(([key]) => key);
540
+ const watchers = createSyncWatchers({
541
+ sources,
542
+ debounceMs: options.debounceMs ?? 500,
543
+ check: (which) => {
544
+ for (const key of keeping()) {
545
+ const config = configOf(key);
546
+ const changed = which.includes("all") ? pusher.changedCategories(config) : which.flatMap((c) => pusher.changedCategories(config, c));
547
+ if (changed.length > 0) {
548
+ queue(key, changed);
549
+ flush(key);
550
+ }
551
+ }
552
+ refreshWatchers();
553
+ }
554
+ });
555
+ function refreshWatchers() {
556
+ watchers.refresh(options.watch !== false && keeping().length > 0);
557
+ emit();
558
+ }
559
+ /** A config patch applied: what it turns on gets pushed (all of it when a mode starts). */
560
+ async function apply(key, before, next, patch) {
561
+ if (next.mode === "off") {
562
+ const turnedOff = before.mode !== "off";
563
+ save(key, turnedOff ? {
564
+ ...next,
565
+ pending: [],
566
+ sent: {}
567
+ } : next);
568
+ if (turnedOff) {
569
+ refreshWatchers();
570
+ await pusher.release(key);
571
+ emit();
572
+ }
573
+ return;
574
+ }
575
+ const fresh = before.mode === "off" || patch.mode === "once";
576
+ const added = next.categories.filter((c) => !before.categories.includes(c));
577
+ const keysChanged = patch.keys !== void 0 && hashValue(before.keys) !== hashValue(next.keys);
578
+ const toPush = fresh ? next.categories : [...added, ...keysChanged && next.categories.includes("keys") ? ["keys"] : []];
579
+ next.pending = SYNC_CATEGORIES.filter((c) => next.categories.includes(c) && (next.pending.includes(c) || toPush.includes(c)));
580
+ if (fresh) next.sent = {};
581
+ save(key, next);
582
+ refreshWatchers();
583
+ const client = clients.get(key);
584
+ if (client?.hello.sync && next.pending.length === 0 && (added.length > 0 || keysChanged)) {
585
+ await pusher.claim(key, client, false).catch((err) => pusher.fail(key, err));
586
+ emit();
587
+ }
588
+ await flush(key);
589
+ }
590
+ const engine = {
591
+ device,
592
+ view: (key) => ({
593
+ config: configOf(key),
594
+ connected: clients.has(key),
595
+ supported: clients.get(key)?.hello.sync === true,
596
+ status: statuses.get(key) ?? null,
597
+ conflict: conflicts.get(key) ?? null,
598
+ busy: pusher.flushing.has(key)
599
+ }),
600
+ configure(key, patch) {
601
+ const before = configOf(key);
602
+ return apply(key, before, {
603
+ ...before,
604
+ ...patch.mode ? { mode: patch.mode } : {},
605
+ ...patch.categories ? { categories: SYNC_CATEGORIES.filter((c) => patch.categories.includes(c)) } : {},
606
+ ...patch.keys ? { keys: [...new Set(patch.keys)] } : {}
607
+ }, patch);
608
+ },
609
+ async pushAll(key) {
610
+ const config = configOf(key);
611
+ if (config.mode === "off") return;
612
+ save(key, {
613
+ ...config,
614
+ pending: [...config.categories],
615
+ sent: {}
616
+ });
617
+ await flush(key);
618
+ },
619
+ async takeOver(key) {
620
+ const config = configOf(key);
621
+ if (config.mode === "off") return;
622
+ save(key, {
623
+ ...config,
624
+ pending: [...config.categories],
625
+ sent: {}
626
+ });
627
+ await flush(key, true);
628
+ },
629
+ async reset(key, field) {
630
+ const client = clients.get(key);
631
+ if (!client) throw new Error("The server is not connected.");
632
+ await client.request("sync.reset", { field });
633
+ await pusher.refresh(key);
634
+ const category = fieldCategory(field);
635
+ const config = configOf(key);
636
+ if (category && config.categories.includes(category) && config.mode !== "off") {
637
+ save(key, {
638
+ ...config,
639
+ sent: {
640
+ ...config.sent,
641
+ [category]: ""
642
+ }
643
+ });
644
+ queue(key, [category]);
645
+ await flush(key);
646
+ }
647
+ },
648
+ refresh: (key) => pusher.refresh(key),
649
+ connected(key, client) {
650
+ clients.set(key, client);
651
+ emit();
652
+ if (!client.hello.sync) return;
653
+ const config = configOf(key);
654
+ if (config.mode === "keep") {
655
+ const changed = pusher.changedCategories(config);
656
+ if (changed.length > 0) queue(key, changed);
657
+ }
658
+ pusher.refresh(key).then(() => flush(key));
659
+ },
660
+ disconnected(key) {
661
+ clients.delete(key);
662
+ emit();
663
+ },
664
+ serverChanged: (key) => {
665
+ const before = statuses.get(key);
666
+ pusher.refresh(key).then(() => {
667
+ const after = statuses.get(key);
668
+ const config = configOf(key);
669
+ if (!before || !after || after.source?.deviceId !== device.id || config.mode === "off") return;
670
+ const back = Object.keys(before.overrides).filter((field) => !after.overrides[field]).map(fieldCategory).filter((c) => c !== void 0 && config.categories.includes(c));
671
+ if (back.length === 0) return;
672
+ save(key, {
673
+ ...config,
674
+ sent: Object.fromEntries(Object.entries(config.sent).filter(([c]) => !back.includes(c)))
675
+ });
676
+ queue(key, back);
677
+ flush(key);
678
+ });
679
+ },
680
+ removed(key) {
681
+ if (configOf(key).mode !== "off") pusher.release(key);
682
+ pusher.forget(key);
683
+ refreshWatchers();
684
+ },
685
+ notifyLocalChange(category) {
686
+ if (keeping().length > 0) watchers.schedule(category);
687
+ },
688
+ localInfo: () => syncLocalInfo(sources),
689
+ watching: () => watchers.count() > 0,
690
+ subscribe(listener) {
691
+ listeners.add(listener);
692
+ return () => listeners.delete(listener);
693
+ },
694
+ stop() {
695
+ watchers.close();
696
+ pusher.stop();
697
+ listeners.clear();
698
+ }
699
+ };
700
+ refreshWatchers();
701
+ return engine;
702
+ }
703
+ function syncLocalInfo(sources) {
704
+ const read = (fn, fallback) => {
705
+ try {
706
+ return fn();
707
+ } catch {
708
+ return fallback;
709
+ }
710
+ };
711
+ return {
712
+ keyProviders: read(() => storedApiKeyProviders(sources), []),
713
+ localExtensions: read(() => userExtensions(sources).local, []),
714
+ stdioMcps: read(() => collectSyncPayload("mcps", sources).servers.filter((s) => typeof s.command === "string" && s.command !== "").map((s) => String(s.name)), [])
715
+ };
716
+ }
717
+ //#endregion
718
+ //#region src/ipc/hosts/probe.ts
719
+ /** Bound on one probe: the upgrade, the handshake and `daemon.info`. */
720
+ const HOST_PROBE_TIMEOUT_MS = 1e4;
721
+ const TLS_FAILURE = /certificate|self[- ]signed|\btls\b|\bssl\b|UNABLE_TO_VERIFY|CERT_|ERR_TLS/i;
722
+ function classify(err) {
723
+ if (err instanceof HostAuthError) return err.status === 401 ? {
724
+ error: "auth",
725
+ message: "The host refused the token (401). Create a new one on the server: zidane server token create --name <device>."
726
+ } : {
727
+ error: "auth",
728
+ message: err.message
729
+ };
730
+ if (err instanceof IpcVersionMismatchError) return {
731
+ error: "protocol",
732
+ message: err.message
733
+ };
734
+ const message = err instanceof Error ? err.message : String(err);
735
+ if (TLS_FAILURE.test(message)) return {
736
+ error: "tls",
737
+ message: `TLS failed: ${message}`
738
+ };
739
+ return {
740
+ error: "unreachable",
741
+ message
742
+ };
743
+ }
744
+ /**
745
+ * A failed WebSocket says nothing about why. For `wss://`, ask the same
746
+ * address over HTTPS: a certificate or handshake failure there is a TLS
747
+ * problem, anything else stays "unreachable".
748
+ */
749
+ async function tlsFailure(url, signal) {
750
+ if (!url.startsWith("wss:")) return null;
751
+ try {
752
+ (await fetch(`https:${url.slice(4)}`, {
753
+ redirect: "manual",
754
+ signal: AbortSignal.any([signal, AbortSignal.timeout(5e3)])
755
+ })).body?.cancel().catch(() => {});
756
+ return null;
757
+ } catch (err) {
758
+ const e = err;
759
+ const detail = `${typeof e.code === "string" ? e.code : ""} ${typeof e.message === "string" ? e.message : ""}`;
760
+ return TLS_FAILURE.test(detail) ? `TLS failed: ${String(e.message ?? e.code)}` : null;
761
+ }
762
+ }
763
+ /** Connect, read the host's identity and `daemon.info`, disconnect. Never throws. */
764
+ async function probeWsHost(target) {
765
+ const started = performance.now();
766
+ const signal = AbortSignal.timeout(target.timeoutMs ?? 1e4);
767
+ let client;
768
+ try {
769
+ client = await connectWsClient({
770
+ url: target.url,
771
+ token: target.token,
772
+ heartbeatMs: 0,
773
+ signal
774
+ });
775
+ const hostRef = hostRefOf(client.hello);
776
+ if (!hostRef) return {
777
+ ok: false,
778
+ error: "protocol",
779
+ message: `${displayHostUrl(target.url)} runs a zidane too old to say which host it is. Upgrade the server.`
780
+ };
781
+ const info = await client.request("daemon.info", {});
782
+ const serverVersion = info.codeVersion ?? info.appVersion;
783
+ return {
784
+ ok: true,
785
+ hostRef,
786
+ ...serverVersion ? { serverVersion } : {},
787
+ latencyMs: Math.round(performance.now() - started)
788
+ };
789
+ } catch (err) {
790
+ if (signal.aborted && !(err instanceof HostAuthError)) return {
791
+ ok: false,
792
+ error: "unreachable",
793
+ message: `No answer from ${displayHostUrl(target.url)} within ${target.timeoutMs ?? 1e4} ms.`
794
+ };
795
+ const classified = classify(err);
796
+ if (classified.error === "unreachable") {
797
+ const tls = await tlsFailure(target.url, signal).catch(() => null);
798
+ if (tls) return {
799
+ ok: false,
800
+ error: "tls",
801
+ message: tls
802
+ };
803
+ }
804
+ return {
805
+ ok: false,
806
+ ...classified
807
+ };
808
+ } finally {
809
+ client?.close();
810
+ }
811
+ }
812
+ /** The registry in `dataDir`, connecting over WebSocket. */
813
+ function createWsHostRegistry(options) {
814
+ return createHostRegistry({
815
+ dataDir: options.dataDir,
816
+ probe: probeWsHost
817
+ });
818
+ }
819
+ //#endregion
820
+ //#region src/ipc/hosts/saved-hosts.ts
821
+ /** No token is saved for this server (removed by hand, or another window removed it). */
822
+ var MissingHostTokenError = class extends Error {
823
+ constructor() {
824
+ super("No token saved for this server: add it again.");
825
+ this.name = "MissingHostTokenError";
826
+ }
827
+ };
828
+ function startSavedHosts(options) {
829
+ const { registry, directory, skip = () => false } = options;
830
+ const classify = (err) => err instanceof MissingHostTokenError ? "auth" : err instanceof HostIdentityError ? "identity" : options.classify?.(err) ?? "retry";
831
+ /** The saved server, or nobody: a connection from another host is closed before anyone sees it. */
832
+ const dial = async (entry, token, attempt) => {
833
+ const client = await options.connect(entry, token, attempt);
834
+ const ref = hostRefOf(client.hello);
835
+ if (ref?.id === entry.id) return client;
836
+ client.close();
837
+ throw new HostIdentityError(displayHostUrl(entry.url), ref?.name);
838
+ };
839
+ const loops = /* @__PURE__ */ new Map();
840
+ const disconnect = (key) => {
841
+ loops.get(key)?.stop();
842
+ loops.delete(key);
843
+ };
844
+ /** (Re)connect `entry` with the token saved now, its directory entry kept or created in place. */
845
+ const connect = (entry) => {
846
+ const key = entry.id;
847
+ disconnect(key);
848
+ directory.upsert(entry, registry.token(key));
849
+ loops.set(key, keepHostConnected({
850
+ connect: (attempt) => {
851
+ const token = registry.token(key);
852
+ return token ? dial(entry, token, attempt) : Promise.reject(new MissingHostTokenError());
853
+ },
854
+ update: (patch) => directory.update(key, patch),
855
+ classify,
856
+ ...options.onSignal ? { onSignal: (signal) => options.onSignal(key, signal) } : {},
857
+ ...options.onConnected ? { onConnected: (client) => options.onConnected(key, client) } : {},
858
+ ...options.onDisconnected ? { onDisconnected: () => options.onDisconnected(key) } : {},
859
+ ...options.minDelayMs !== void 0 ? { minDelayMs: options.minDelayMs } : {},
860
+ ...options.maxDelayMs !== void 0 ? { maxDelayMs: options.maxDelayMs } : {}
861
+ }));
862
+ };
863
+ /** Bring the directory in line with the saved hosts. */
864
+ const sync = () => {
865
+ const entries = registry.list().filter((entry) => !skip(entry));
866
+ const saved = new Set(entries.map((entry) => entry.id));
867
+ const known = new Map(directory.saved().map((host) => [host.key, host.url]));
868
+ for (const key of known.keys()) if (!saved.has(key)) {
869
+ disconnect(key);
870
+ directory.remove(key);
871
+ }
872
+ for (const entry of entries) if (known.get(entry.id) !== entry.url) connect(entry);
873
+ else directory.update(entry.id, {
874
+ name: entry.name,
875
+ ...entry.serverVersion ? { serverVersion: entry.serverVersion } : {}
876
+ });
877
+ };
878
+ sync();
879
+ return {
880
+ list: () => registry.list(),
881
+ add: async (input) => {
882
+ const entry = await registry.add(input);
883
+ if (!skip(entry)) connect(entry);
884
+ sync();
885
+ return entry;
886
+ },
887
+ remove: (id) => {
888
+ const removed = registry.remove(id);
889
+ sync();
890
+ return removed;
891
+ },
892
+ rename: (id, name) => {
893
+ const entry = registry.rename(id, name);
894
+ sync();
895
+ return entry;
896
+ },
897
+ test: async (target) => {
898
+ if (typeof target === "object" && !("id" in target)) {
899
+ if (!options.probeUnsaved) throw new Error("Testing an unsaved host is not available here.");
900
+ return options.probeUnsaved(target);
901
+ }
902
+ const id = typeof target === "string" ? target : target.id;
903
+ const result = await registry.test(id);
904
+ if (result.ok) {
905
+ directory.update(id, {
906
+ serverName: result.hostRef.name,
907
+ ...result.serverVersion ? { serverVersion: result.serverVersion } : {}
908
+ });
909
+ loops.get(id)?.retry();
910
+ }
911
+ return result;
912
+ },
913
+ retry: (id) => loops.get(id)?.retry(),
914
+ stop: () => {
915
+ for (const key of [...loops.keys()]) {
916
+ disconnect(key);
917
+ directory.remove(key);
918
+ }
919
+ }
920
+ };
921
+ }
922
+ //#endregion
923
+ //#region src/ipc/hosts/ws.ts
924
+ /** A refused token stays refused until the user changes something: no retry loop. */
925
+ function classifyWsFailure(err) {
926
+ return err instanceof HostAuthError ? "auth" : err instanceof HostIdentityError ? "identity" : "retry";
927
+ }
928
+ /** The add form's "test": the registry's own checks and probe over WebSocket, saving nothing. */
929
+ function probeUnsavedWsHost(target) {
930
+ return probeUnsavedHost(probeWsHost, target);
931
+ }
932
+ function startWsSavedHosts(options) {
933
+ const { dataDir, appVersion, connect, registry, ...rest } = options;
934
+ return startSavedHosts({
935
+ ...rest,
936
+ registry: registry ?? createWsHostRegistry({ dataDir }),
937
+ classify: classifyWsFailure,
938
+ probeUnsaved: probeUnsavedWsHost,
939
+ connect: connect ?? ((entry, token, attempt) => connectWsClient({
940
+ url: entry.url,
941
+ token,
942
+ expectHostId: entry.id,
943
+ ...appVersion ? { appVersion } : {},
944
+ signal: attempt.signal,
945
+ onClose: attempt.onClose
946
+ }))
947
+ });
948
+ }
949
+ //#endregion
950
+ export { startSavedHosts as a, probeWsHost as c, MissingHostTokenError as i, createSyncEngine as l, probeUnsavedWsHost as n, HOST_PROBE_TIMEOUT_MS as o, startWsSavedHosts as r, createWsHostRegistry as s, classifyWsFailure as t };
951
+
952
+ //# sourceMappingURL=ws-CIHMvlSh.js.map