zidane 7.2.5 → 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 -27243
  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-BKVIIOqH.js +0 -331
  342. package/dist/ipc-BKVIIOqH.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-DfdXrGg9.js +0 -1549
  363. package/dist/shell-path-DfdXrGg9.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 @@
1
+ {"version":3,"file":"ws-CIHMvlSh.js","names":[],"sources":["../src/chat/sync/collect.ts","../src/chat/sync/local.ts","../src/chat/sync/pusher.ts","../src/chat/sync/watchers.ts","../src/chat/sync/engine.ts","../src/ipc/hosts/probe.ts","../src/ipc/hosts/saved-hosts.ts","../src/ipc/hosts/ws.ts"],"sourcesContent":["/**\n * This computer's state for each sync category, read from disk as a\n * `sync.push` payload (`./types` `SyncPayloads`): what the user set here,\n * never what a server session put in a window.\n *\n * - settings: `state.json`'s settings over the defaults, syncable keys only;\n * - safelists: `projects.json`;\n * - files: the user-scope `SYSTEM.md`, and the user-scope skills\n * (`~/.agents/skills`, `~/.<prefix>/skills`; the first of a name wins),\n * bounded like the server bounds them (a skill over them is left out);\n * - mcps: the user-scope `mcps.json` files (the first of a name wins);\n * - extensions: user-scope extensions installed from a source (their\n * `.install.json`); the others are listed as not syncable;\n * - keys: the stored API keys of the providers opted in.\n */\nimport type { ProviderDescriptor } from '../providers'\nimport type { SyncCategory, SyncFile, SyncPayloads } from './types'\nimport { existsSync, lstatSync, readdirSync, readFileSync } from 'node:fs'\nimport { join, relative, sep } from 'node:path'\nimport { readProviderCredential } from '../credentials'\nimport { parseMcpsFile } from '../mcps-discovery'\nimport { projectUserPaths } from '../project-user-paths'\nimport { readProjects } from '../safe-mode'\nimport { DEFAULT_SETTINGS } from '../settings-context'\nimport { loadState } from '../store'\nimport { userSystemMdPath } from '../system-md'\nimport { isSyncableSetting } from './settings-keys'\n\nexport interface SyncSources {\n /** The user dir (`projects.json`, `credentials.json`). */\n dataDir: string\n /** This computer's `state.json`. */\n statePath: string\n home: string\n prefix: string\n providers: () => Readonly<Record<string, ProviderDescriptor>>\n}\n\nconst MAX_FILE_BYTES = 1024 * 1024\nconst MAX_SKILL_BYTES = 4 * 1024 * 1024\nconst MAX_SKILL_FILES = 200\nconst MAX_DEPTH = 8\n/** Not part of a skill: version control and installed dependencies. */\nconst SKIPPED_DIRS = new Set(['.git', 'node_modules'])\n\nfunction userPaths(sources: SyncSources, subPath: string): string[] {\n return projectUserPaths({ subPath, cwd: sources.home, home: sources.home, prefix: sources.prefix }).filter(p => p.source === 'user').map(p => p.path)\n}\n\n/** Every file and folder a category reads: what the watchers watch. */\nexport function syncWatchTargets(sources: SyncSources): { category: SyncCategory, path: string, recursive: boolean }[] {\n return [\n { category: 'settings', path: sources.statePath, recursive: false },\n { category: 'safelists', path: join(sources.dataDir, 'projects.json'), recursive: false },\n { category: 'files', path: userSystemMdPath({ home: sources.home, prefix: sources.prefix }), recursive: false },\n ...userPaths(sources, 'skills').map(path => ({ category: 'files' as const, path, recursive: true })),\n ...userPaths(sources, 'mcps.json').map(path => ({ category: 'mcps' as const, path, recursive: false })),\n ...userPaths(sources, 'extensions').map(path => ({ category: 'extensions' as const, path, recursive: true })),\n { category: 'keys', path: join(sources.dataDir, 'credentials.json'), recursive: false },\n ]\n}\n\nfunction settingsPayload(sources: SyncSources): SyncPayloads['settings'] {\n const stored = (loadState(sources.statePath).settings ?? {}) as Record<string, unknown>\n const merged = { ...DEFAULT_SETTINGS, ...stored } as Record<string, unknown>\n return { values: Object.fromEntries(Object.entries(merged).filter(([key]) => key in DEFAULT_SETTINGS && isSyncableSetting(key))) }\n}\n\nfunction safelistsPayload(sources: SyncSources): SyncPayloads['safelists'] {\n const projects = readProjects(sources.dataDir)\n return { projects: Object.fromEntries(Object.entries(projects).flatMap(([path, entry]) => (Array.isArray(entry?.safelist) ? [[path, [...entry.safelist]]] : []))) }\n}\n\n/** A skill folder's files, or null when it is over the bounds (or not a plain folder). */\nfunction skillFiles(dir: string): SyncFile[] | null {\n const files: SyncFile[] = []\n let total = 0\n const walk = (at: string, depth: number): boolean => {\n if (depth > MAX_DEPTH)\n return false\n for (const name of readdirSync(at).sort()) {\n const path = join(at, name)\n const stat = lstatSync(path)\n if (stat.isDirectory()) {\n if (SKIPPED_DIRS.has(name))\n continue\n if (!walk(path, depth + 1))\n return false\n }\n else if (stat.isFile()) {\n if (stat.size > MAX_FILE_BYTES || files.length >= MAX_SKILL_FILES)\n return false\n total += stat.size\n if (total > MAX_SKILL_BYTES)\n return false\n files.push({ path: relative(dir, path).split(sep).join('/'), data: readFileSync(path).toString('base64') })\n }\n // Links and anything else: not copied.\n }\n return true\n }\n try {\n return walk(dir, 1) && files.length > 0 ? files : null\n }\n catch {\n return null\n }\n}\n\n/** The user-scope skills: name → folder, the first root of a name winning (as discovery does). */\nexport function userSkillDirs(sources: SyncSources): Map<string, string> {\n const found = new Map<string, string>()\n for (const root of userPaths(sources, 'skills')) {\n let names: string[]\n try {\n names = readdirSync(root).sort()\n }\n catch {\n continue\n }\n for (const name of names) {\n const dir = join(root, name)\n if (!found.has(name) && !name.startsWith('.') && existsSync(join(dir, 'SKILL.md')) && lstatSync(dir).isDirectory())\n found.set(name, dir)\n }\n }\n return found\n}\n\nfunction filesPayload(sources: SyncSources): SyncPayloads['files'] {\n const mdPath = userSystemMdPath({ home: sources.home, prefix: sources.prefix })\n const systemMd = existsSync(mdPath) ? readFileSync(mdPath, 'utf8') : null\n const skills: SyncPayloads['files']['skills'] = []\n for (const [name, dir] of userSkillDirs(sources)) {\n const files = skillFiles(dir)\n if (files)\n skills.push({ name, files })\n }\n return { systemMd, skills }\n}\n\nfunction mcpsPayload(sources: SyncSources): SyncPayloads['mcps'] {\n const servers = new Map<string, Record<string, unknown>>()\n for (const path of userPaths(sources, 'mcps.json')) {\n if (!existsSync(path))\n continue\n try {\n for (const server of parseMcpsFile(readFileSync(path, 'utf8'))) {\n if (!servers.has(server.name))\n servers.set(server.name, server as unknown as Record<string, unknown>)\n }\n }\n catch {\n // A file discovery can't read either: nothing to sync from it.\n }\n }\n return { servers: [...servers.values()] }\n}\n\n/** User-scope extensions: those with a source (syncable) and the local ones (not). */\nexport function userExtensions(sources: SyncSources): { syncable: SyncPayloads['extensions']['extensions'], local: string[] } {\n const syncable: SyncPayloads['extensions']['extensions'] = []\n const local: string[] = []\n const seen = new Set<string>()\n for (const root of userPaths(sources, 'extensions')) {\n let names: string[]\n try {\n names = readdirSync(root).sort()\n }\n catch {\n continue\n }\n for (const name of names) {\n const dir = join(root, name)\n if (name.startsWith('.') || seen.has(name) || !lstatSync(dir).isDirectory())\n continue\n seen.add(name)\n // `.install.json` (`src/extensions/install.ts`): the spec an install replays.\n let provenance: { spec?: unknown, extension?: unknown } | null = null\n try {\n provenance = JSON.parse(readFileSync(join(dir, '.install.json'), 'utf8'))\n }\n catch {}\n if (provenance && typeof provenance.spec === 'string' && provenance.spec.trim() !== '')\n syncable.push({ name, spec: provenance.spec, ...(typeof provenance.extension === 'string' ? { extension: provenance.extension } : {}) })\n else\n local.push(name)\n }\n }\n return { syncable, local }\n}\n\n/** Providers with an API key stored here: what the keys category can offer. */\nexport function storedApiKeyProviders(sources: SyncSources): { key: string, label: string }[] {\n return Object.values(sources.providers()).flatMap((descriptor) => {\n const credential = readProviderCredential(sources.dataDir, descriptor)\n return credential?.kind === 'apikey' && credential.value ? [{ key: descriptor.key, label: descriptor.label }] : []\n })\n}\n\nfunction keysPayload(sources: SyncSources, optedIn: readonly string[]): SyncPayloads['keys'] {\n const providers = sources.providers()\n return {\n keys: optedIn.flatMap((provider) => {\n const descriptor = providers[provider]\n const credential = descriptor ? readProviderCredential(sources.dataDir, descriptor) : undefined\n return credential?.kind === 'apikey' && credential.value ? [{ provider, key: credential.value }] : []\n }),\n }\n}\n\nexport function collectSyncPayload(category: SyncCategory, sources: SyncSources, optedInKeys: readonly string[] = []): SyncPayloads[SyncCategory] {\n switch (category) {\n case 'settings': return settingsPayload(sources)\n case 'safelists': return safelistsPayload(sources)\n case 'files': return filesPayload(sources)\n case 'mcps': return mcpsPayload(sources)\n case 'extensions': return { extensions: userExtensions(sources).syncable }\n case 'keys': return keysPayload(sources, optedInKeys)\n }\n}\n","/**\n * This computer's side of settings sync, on disk:\n *\n * - `<dataDir>/device.json` (0600): the device id servers know this computer\n * by (random, made once) and its name (the host name).\n * - `<dataDir>/hosts-sync.json` (0600), next to `hosts.json`: per saved\n * server (by host id), the mode, the categories, the API keys opted in,\n * the categories still to push (the offline queue: one entry per category,\n * the newest value wins, so at most six) and the outcome of the last push.\n */\nimport type { SyncCategory, SyncMode, SyncPushResult } from './types'\nimport { randomUUID } from 'node:crypto'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { hostname } from 'node:os'\nimport { join } from 'node:path'\nimport { OWNER_ONLY, writeJsonFileAtomic } from '../../atomic-write'\nimport { isRecord } from './hash'\nimport { SYNC_CATEGORIES, SYNC_MODES } from './types'\n\nexport interface DeviceIdentity {\n id: string\n name: string\n}\n\nexport interface ServerSyncConfig {\n mode: SyncMode\n categories: SyncCategory[]\n /** Providers whose stored API key goes to this server. */\n keys: string[]\n /** Categories changed here and not pushed yet (offline queue). */\n pending: SyncCategory[]\n /** Per category, a hash of what was last pushed (a restart finds what changed meanwhile). */\n sent: Partial<Record<SyncCategory, string>>\n lastSyncAt?: number\n lastError?: string\n /** What the last push of each category did there. */\n results: Partial<Record<SyncCategory, SyncPushResult>>\n}\n\ninterface SyncConfigFile {\n version: 1\n servers: Record<string, ServerSyncConfig>\n}\n\nexport const DEFAULT_SERVER_SYNC: Readonly<ServerSyncConfig> = { mode: 'off', categories: ['settings'], keys: [], pending: [], sent: {}, results: {} }\n\nexport function hostsSyncPath(dataDir: string): string {\n return join(dataDir, 'hosts-sync.json')\n}\n\nexport function deviceIdentityPath(dataDir: string): string {\n return join(dataDir, 'device.json')\n}\n\nfunction readJson(path: string): unknown {\n if (!existsSync(path))\n return undefined\n try {\n return JSON.parse(readFileSync(path, 'utf8'))\n }\n catch {\n return undefined\n }\n}\n\n/** This computer's device id and name, made on first use. */\nexport function readDeviceIdentity(dataDir: string, name?: string): DeviceIdentity {\n const raw = readJson(deviceIdentityPath(dataDir))\n if (isRecord(raw) && typeof raw.id === 'string' && raw.id !== '')\n return { id: raw.id, name: name ?? (typeof raw.name === 'string' && raw.name ? raw.name : hostname()) }\n const identity = { id: randomUUID(), name: name ?? hostname() }\n writeJsonFileAtomic(deviceIdentityPath(dataDir), identity, OWNER_ONLY)\n return identity\n}\n\nfunction categoriesOf(value: unknown): SyncCategory[] {\n return Array.isArray(value) ? SYNC_CATEGORIES.filter(c => value.includes(c)) : []\n}\n\nfunction serverConfigOf(raw: unknown): ServerSyncConfig {\n if (!isRecord(raw))\n return { ...DEFAULT_SERVER_SYNC }\n return {\n mode: SYNC_MODES.includes(raw.mode as SyncMode) ? raw.mode as SyncMode : 'off',\n categories: categoriesOf(raw.categories),\n keys: Array.isArray(raw.keys) ? raw.keys.filter((k): k is string => typeof k === 'string') : [],\n pending: categoriesOf(raw.pending),\n sent: isRecord(raw.sent) ? Object.fromEntries(Object.entries(raw.sent).filter(([c, h]) => SYNC_CATEGORIES.includes(c as SyncCategory) && typeof h === 'string')) : {},\n ...(typeof raw.lastSyncAt === 'number' ? { lastSyncAt: raw.lastSyncAt } : {}),\n ...(typeof raw.lastError === 'string' ? { lastError: raw.lastError } : {}),\n results: isRecord(raw.results) ? raw.results as ServerSyncConfig['results'] : {},\n }\n}\n\nexport function readSyncConfigs(dataDir: string): Record<string, ServerSyncConfig> {\n const raw = readJson(hostsSyncPath(dataDir))\n if (!isRecord(raw) || !isRecord(raw.servers))\n return {}\n return Object.fromEntries(Object.entries(raw.servers).map(([key, value]) => [key, serverConfigOf(value)]))\n}\n\nexport function writeSyncConfigs(dataDir: string, servers: Record<string, ServerSyncConfig>): void {\n const file: SyncConfigFile = { version: 1, servers }\n writeJsonFileAtomic(hostsSyncPath(dataDir), file, OWNER_ONLY)\n}\n","/**\n * The push side of settings sync (`./engine`): per server, its config (read\n * from and saved to `hosts-sync.json`), its connection, what it said last\n * (`sync.status`, a conflicting source), and the queue flush: claim, then\n * push each pending category's snapshot, one flush at a time per server.\n */\nimport type { SyncSources } from './collect'\nimport type { SyncClient } from './engine'\nimport type { DeviceIdentity, ServerSyncConfig } from './local'\nimport type { SyncCategory, SyncStatus } from './types'\nimport { collectSyncPayload } from './collect'\nimport { hashValue } from './hash'\nimport { DEFAULT_SERVER_SYNC, readSyncConfigs, writeSyncConfigs } from './local'\nimport { SYNC_CATEGORIES } from './types'\n\nconst errorText = (err: unknown): string => (err instanceof Error ? err.message : String(err))\n\nexport function createSyncPusher({ sources, device, emit }: { sources: SyncSources, device: DeviceIdentity, emit: () => void }) {\n const configs = readSyncConfigs(sources.dataDir)\n const clients = new Map<string, SyncClient>()\n const statuses = new Map<string, SyncStatus>()\n const conflicts = new Map<string, string>()\n const flushing = new Map<string, Promise<void>>()\n const again = new Set<string>()\n let stopped = false\n\n const configOf = (key: string): ServerSyncConfig => configs[key] ?? { ...DEFAULT_SERVER_SYNC, categories: [...DEFAULT_SERVER_SYNC.categories] }\n const save = (key: string, config: ServerSyncConfig): void => {\n configs[key] = config\n writeSyncConfigs(sources.dataDir, configs)\n emit()\n }\n const fail = (key: string, err: unknown): void => save(key, { ...configOf(key), lastError: errorText(err) })\n\n /** Categories whose snapshot here differs from what was last pushed to the server. */\n const changedCategories = (config: ServerSyncConfig, only?: SyncCategory): SyncCategory[] =>\n config.categories.filter((category) => {\n if (only && category !== only)\n return false\n try {\n return hashValue(collectSyncPayload(category, sources, config.keys)) !== config.sent[category]\n }\n catch {\n return true\n }\n })\n\n const queue = (key: string, categories: readonly SyncCategory[]): void => {\n const config = configOf(key)\n const pending = SYNC_CATEGORIES.filter(c => config.pending.includes(c) || categories.includes(c))\n if (pending.length !== config.pending.length)\n save(key, { ...config, pending })\n }\n\n async function claim(key: string, client: SyncClient, takeover: boolean): Promise<boolean> {\n const config = configOf(key)\n const result = await client.request('sync.claim', { deviceId: device.id, deviceName: device.name, categories: config.categories, keys: config.keys, ...(takeover ? { takeover: true } : {}) })\n statuses.set(key, result.status)\n if (result.claimed)\n conflicts.delete(key)\n else\n conflicts.set(key, result.status.source?.deviceName ?? 'another device')\n return result.claimed\n }\n\n async function flushOnce(key: string, takeover: boolean): Promise<void> {\n const client = clients.get(key)\n let config = configOf(key)\n if (!client || !client.hello.sync || config.mode === 'off' || (config.pending.length === 0 && !takeover) || stopped)\n return\n try {\n if (!(await claim(key, client, takeover)))\n return\n for (const category of [...configOf(key).pending]) {\n config = configOf(key)\n if (!config.categories.includes(category)) {\n save(key, { ...config, pending: config.pending.filter(c => c !== category) })\n continue\n }\n const payload = collectSyncPayload(category, sources, config.keys)\n const result = await client.request('sync.push', { deviceId: device.id, category, payload })\n config = configOf(key)\n const { lastError: _dropped, ...rest } = config\n save(key, {\n ...rest,\n pending: config.pending.filter(c => c !== category),\n sent: { ...config.sent, [category]: hashValue(payload) },\n results: { ...config.results, [category]: result },\n lastSyncAt: Date.now(),\n })\n }\n statuses.set(key, await client.request('sync.status', {}))\n }\n catch (err) {\n fail(key, err)\n }\n }\n\n /** Push the queue if the server is connected and this device is its source; `takeover` claims it first. */\n function flush(key: string, takeover = false): Promise<void> {\n const running = flushing.get(key)\n if (running && !takeover) {\n again.add(key)\n return running\n }\n const run = (async () => {\n if (running)\n await running\n await flushOnce(key, takeover)\n // A change while pushing: once more (`flushOnce` stops on its own once stopped).\n while (again.delete(key))\n await flushOnce(key, false)\n })().finally(() => {\n if (flushing.get(key) === run)\n flushing.delete(key)\n emit()\n })\n flushing.set(key, run)\n emit()\n return run\n }\n\n /** Read the server's record: who syncs there now. */\n async function refresh(key: string): Promise<void> {\n const client = clients.get(key)\n if (!client?.hello.sync)\n return\n try {\n const status = await client.request('sync.status', {})\n statuses.set(key, status)\n if (!status.source || status.source.deviceId === device.id)\n conflicts.delete(key)\n else if (configOf(key).mode !== 'off')\n conflicts.set(key, status.source.deviceName)\n }\n catch {}\n emit()\n }\n\n /** This device stops being the server's source (the server keeps what it has). */\n async function release(key: string): Promise<void> {\n const client = clients.get(key)\n conflicts.delete(key)\n if (!client?.hello.sync)\n return\n await client.request('sync.release', { deviceId: device.id }).catch(() => undefined)\n const status = await client.request('sync.status', {}).catch(() => null)\n if (status)\n statuses.set(key, status)\n }\n\n function forget(key: string): void {\n clients.delete(key)\n statuses.delete(key)\n conflicts.delete(key)\n if (configs[key]) {\n delete configs[key]\n writeSyncConfigs(sources.dataDir, configs)\n }\n }\n\n return {\n configs,\n clients,\n statuses,\n conflicts,\n flushing,\n configOf,\n save,\n fail,\n changedCategories,\n queue,\n claim,\n flush,\n refresh,\n release,\n forget,\n stop: () => {\n stopped = true\n clients.clear()\n },\n }\n}\n","/**\n * File watchers for settings sync (`./engine`): on each file and folder a\n * category reads (`syncWatchTargets`), or the folder it would appear in.\n * Events are debounced into one check of the categories they touched; the\n * watchers are rebuilt after each check (a folder created since, such as the\n * first skill, is then watched too).\n */\nimport type { SyncSources } from './collect'\nimport type { SyncCategory } from './types'\nimport { existsSync, statSync, watch } from 'node:fs'\nimport { basename, dirname } from 'node:path'\nimport { syncWatchTargets } from './collect'\n\nexport interface SyncWatchers {\n /** Start (or restart) the watchers when `active`, else close them. */\n refresh: (active: boolean) => void\n /** Report a change (a watcher, or the app's own settings stream). */\n schedule: (category?: SyncCategory) => void\n count: () => number\n close: () => void\n}\n\nexport function createSyncWatchers({ sources, debounceMs, check }: {\n sources: SyncSources\n debounceMs: number\n /** After the debounce: the categories that changed (`all`: unknown which), then the watchers are refreshed by the caller. */\n check: (which: readonly (SyncCategory | 'all')[]) => void\n}): SyncWatchers {\n let watchers: { close: () => void }[] = []\n let timer: ReturnType<typeof setTimeout> | null = null\n let closed = false\n const dirty = new Set<SyncCategory | 'all'>()\n\n const closeAll = (): void => {\n for (const w of watchers)\n w.close()\n watchers = []\n }\n\n const schedule = (category?: SyncCategory): void => {\n if (closed)\n return\n dirty.add(category ?? 'all')\n if (timer)\n return\n timer = setTimeout(() => {\n timer = null\n const which = [...dirty]\n dirty.clear()\n check(which)\n }, debounceMs)\n }\n\n return {\n schedule,\n refresh(active) {\n closeAll()\n if (closed || !active)\n return\n for (const target of syncWatchTargets(sources)) {\n const isDir = existsSync(target.path) && statSync(target.path).isDirectory()\n const at = isDir ? target.path : dirname(target.path)\n if (!existsSync(at))\n continue\n const name = basename(target.path)\n try {\n // A file's folder: only that file's events.\n watchers.push(watch(at, { recursive: isDir && target.recursive, persistent: false }, (_event, changed) => {\n if (isDir || changed === null || String(changed) === name)\n schedule(target.category)\n }))\n }\n catch {\n // A folder that can't be watched: the app's own reports still find its changes.\n }\n }\n },\n count: () => watchers.length,\n close() {\n closed = true\n if (timer)\n clearTimeout(timer)\n timer = null\n closeAll()\n },\n }\n}\n","/**\n * Settings sync, the client side shared by the TUI and the GUI main process:\n * for each saved server, push this computer's categories to it\n * (`sync.claim`, `sync.push`), now (Import once) or as they change (Keep in\n * sync). Loaded by each app behind its `remoteHosts` gate only, with the\n * saved hosts; nothing here dials: the app hands over each server's\n * connection (`connected` / `disconnected`).\n *\n * Change detection: file watchers on what each category reads\n * (`syncWatchTargets`), only while some server keeps in sync, plus the\n * app's own reports (`notifyLocalChange`: its settings stream). Either one\n * schedules a check (debounced): a category whose snapshot hashes\n * differently from what was last pushed is queued (`pending`, persisted in\n * `hosts-sync.json`), and the queue flushes when the server is connected.\n * Offline, it waits; the newest value wins, there being one source.\n */\nimport type { ProviderDescriptor } from '../providers'\nimport type { DeviceIdentity, ServerSyncConfig } from './local'\nimport type { SyncCategory, SyncClaimResult, SyncPayload, SyncPayloads, SyncPushResult, SyncStatus } from './types'\nimport { collectSyncPayload, storedApiKeyProviders, userExtensions } from './collect'\nimport { hashValue } from './hash'\nimport { readDeviceIdentity } from './local'\nimport { createSyncPusher } from './pusher'\nimport { fieldCategory, SYNC_CATEGORIES } from './types'\nimport { createSyncWatchers } from './watchers'\n\n/** The part of a host connection sync uses (an `IpcClient` is one). */\nexport interface SyncClient {\n request: ((method: 'sync.status', params: Record<string, never>) => Promise<SyncStatus>)\n & ((method: 'sync.claim', params: { deviceId: string, deviceName: string, takeover?: boolean, categories?: SyncCategory[], keys?: string[] }) => Promise<SyncClaimResult>)\n & ((method: 'sync.push', params: { deviceId: string, category: SyncCategory, payload: SyncPayload }) => Promise<SyncPushResult>)\n & ((method: 'sync.reset', params: { field: string }) => Promise<{ reset: boolean }>)\n & ((method: 'sync.release', params: { deviceId: string }) => Promise<{ released: boolean }>)\n hello: { sync?: boolean }\n}\n\nexport interface SyncEngineOptions {\n dataDir: string\n statePath: string\n home: string\n prefix: string\n providers: () => Readonly<Record<string, ProviderDescriptor>>\n /** Default: this computer's host name. */\n deviceName?: string\n /** Wait after a change before checking (a save is often several writes). Default 500 ms. */\n debounceMs?: number\n /** File watchers (default on); off, only `notifyLocalChange` finds changes. */\n watch?: boolean\n}\n\n/** What a UI shows for one server. */\nexport interface SyncView {\n config: ServerSyncConfig\n connected: boolean\n /** The server takes sync (`ipc.hello.sync`); false for an older server. */\n supported: boolean\n /** The server's record, when read. */\n status: SyncStatus | null\n /** Another device syncs to this server: its name. */\n conflict: string | null\n busy: boolean\n}\n\nexport interface SyncEngine {\n device: DeviceIdentity\n view: (key: string) => SyncView\n /** Change the mode, categories or opted-in keys; pushes what that calls for. */\n configure: (key: string, patch: Partial<Pick<ServerSyncConfig, 'mode' | 'categories' | 'keys'>>) => Promise<void>\n /** Push every selected category now (whatever the mode, but off). */\n pushAll: (key: string) => Promise<void>\n /** Become the source of a server another device syncs to, then push. */\n takeOver: (key: string) => Promise<void>\n /** Drop an override on the server (the next push writes the field again). */\n reset: (key: string, field: string) => Promise<void>\n /** Read the server's record again. */\n refresh: (key: string) => Promise<void>\n connected: (key: string, client: SyncClient) => void\n disconnected: (key: string) => void\n /** A server's `sync:changed` signal. */\n serverChanged: (key: string) => void\n /** The server was removed here: forget its sync config (the server keeps what it has). */\n removed: (key: string) => void\n /** This computer changed something (the app's settings stream): check, push if it differs. */\n notifyLocalChange: (category?: SyncCategory) => void\n /** What this computer has that the UIs mention: API keys to opt in, extensions that can't sync, stdio MCP servers. */\n localInfo: () => SyncLocalInfo\n /** File watchers are running (some server keeps in sync). */\n watching: () => boolean\n subscribe: (listener: () => void) => () => void\n stop: () => void\n}\n\nexport interface SyncLocalInfo {\n keyProviders: { key: string, label: string }[]\n localExtensions: string[]\n stdioMcps: string[]\n}\n\n/**\n * Engines CREATED in this process so far: monotonic (never decremented when\n * one stops), not a live count. The containment tests compare it before and\n * after a mount to prove an engine did, or did not, start.\n */\nlet engines = 0\nexport function syncEngineCount(): number {\n return engines\n}\n\nexport function createSyncEngine(options: SyncEngineOptions): SyncEngine {\n engines++\n const sources = { dataDir: options.dataDir, statePath: options.statePath, home: options.home, prefix: options.prefix, providers: options.providers }\n const device = readDeviceIdentity(options.dataDir, options.deviceName)\n const listeners = new Set<() => void>()\n const emit = (): void => {\n for (const listener of [...listeners]) {\n try {\n listener()\n }\n catch {}\n }\n }\n const pusher = createSyncPusher({ sources, device, emit })\n const { configOf, save, queue, flush, clients, statuses, conflicts } = pusher\n const keeping = (): string[] => Object.entries(pusher.configs).filter(([, c]) => c.mode === 'keep').map(([key]) => key)\n\n const watchers = createSyncWatchers({\n sources,\n debounceMs: options.debounceMs ?? 500,\n // Each server that keeps in sync: queue what changed, push it.\n check: (which) => {\n for (const key of keeping()) {\n const config = configOf(key)\n const changed = which.includes('all') ? pusher.changedCategories(config) : which.flatMap(c => pusher.changedCategories(config, c as SyncCategory))\n if (changed.length > 0) {\n queue(key, changed)\n void flush(key)\n }\n }\n refreshWatchers()\n },\n })\n function refreshWatchers(): void {\n watchers.refresh(options.watch !== false && keeping().length > 0)\n emit()\n }\n\n /** A config patch applied: what it turns on gets pushed (all of it when a mode starts). */\n async function apply(key: string, before: ServerSyncConfig, next: ServerSyncConfig, patch: Partial<ServerSyncConfig>): Promise<void> {\n if (next.mode === 'off') {\n const turnedOff = before.mode !== 'off'\n save(key, turnedOff ? { ...next, pending: [], sent: {} } : next)\n if (turnedOff) {\n refreshWatchers()\n // The server keeps what it has; it stops naming this device as its source.\n await pusher.release(key)\n emit()\n }\n return\n }\n const fresh = before.mode === 'off' || patch.mode === 'once'\n const added = next.categories.filter(c => !before.categories.includes(c))\n const keysChanged = patch.keys !== undefined && hashValue(before.keys) !== hashValue(next.keys)\n const toPush = fresh ? next.categories : [...added, ...(keysChanged && next.categories.includes('keys') ? ['keys' as const] : [])]\n next.pending = SYNC_CATEGORIES.filter(c => next.categories.includes(c) && (next.pending.includes(c) || toPush.includes(c)))\n if (fresh)\n next.sent = {}\n save(key, next)\n refreshWatchers()\n // New categories or keys with nothing queued: claim again, the server checks pushes against them.\n const client = clients.get(key)\n if (client?.hello.sync && next.pending.length === 0 && (added.length > 0 || keysChanged)) {\n await pusher.claim(key, client, false).catch(err => pusher.fail(key, err))\n emit()\n }\n await flush(key)\n }\n\n const engine: SyncEngine = {\n device,\n\n view: key => ({\n config: configOf(key),\n connected: clients.has(key),\n supported: clients.get(key)?.hello.sync === true,\n status: statuses.get(key) ?? null,\n conflict: conflicts.get(key) ?? null,\n busy: pusher.flushing.has(key),\n }),\n\n configure(key, patch) {\n const before = configOf(key)\n const next: ServerSyncConfig = {\n ...before,\n ...(patch.mode ? { mode: patch.mode } : {}),\n ...(patch.categories ? { categories: SYNC_CATEGORIES.filter(c => patch.categories!.includes(c)) } : {}),\n ...(patch.keys ? { keys: [...new Set(patch.keys)] } : {}),\n }\n return apply(key, before, next, patch)\n },\n\n async pushAll(key) {\n const config = configOf(key)\n if (config.mode === 'off')\n return\n save(key, { ...config, pending: [...config.categories], sent: {} })\n await flush(key)\n },\n\n async takeOver(key) {\n const config = configOf(key)\n if (config.mode === 'off')\n return\n save(key, { ...config, pending: [...config.categories], sent: {} })\n await flush(key, true)\n },\n\n async reset(key, field) {\n const client = clients.get(key)\n if (!client)\n throw new Error('The server is not connected.')\n await client.request('sync.reset', { field })\n await pusher.refresh(key)\n // That field is sync's again: send its category.\n const category = fieldCategory(field)\n const config = configOf(key)\n if (category && config.categories.includes(category) && config.mode !== 'off') {\n save(key, { ...config, sent: { ...config.sent, [category]: '' } })\n queue(key, [category])\n await flush(key)\n }\n },\n\n refresh: key => pusher.refresh(key),\n\n connected(key, client) {\n clients.set(key, client)\n emit()\n if (!client.hello.sync)\n return\n const config = configOf(key)\n // Keep in sync: what changed here while away (or while this app was closed) joins the queue.\n if (config.mode === 'keep') {\n const changed = pusher.changedCategories(config)\n if (changed.length > 0)\n queue(key, changed)\n }\n void pusher.refresh(key).then(() => flush(key))\n },\n\n disconnected(key) {\n clients.delete(key)\n emit()\n },\n\n serverChanged: (key) => {\n const before = statuses.get(key)\n void pusher.refresh(key).then(() => {\n // An override reset there (from any window): its category is sync's again, push it.\n const after = statuses.get(key)\n const config = configOf(key)\n if (!before || !after || after.source?.deviceId !== device.id || config.mode === 'off')\n return\n const back = Object.keys(before.overrides).filter(field => !after.overrides[field]).map(fieldCategory).filter((c): c is SyncCategory => c !== undefined && config.categories.includes(c))\n if (back.length === 0)\n return\n save(key, { ...config, sent: Object.fromEntries(Object.entries(config.sent).filter(([c]) => !back.includes(c as SyncCategory))) })\n queue(key, back)\n void flush(key)\n })\n },\n\n removed(key) {\n if (configOf(key).mode !== 'off')\n void pusher.release(key)\n pusher.forget(key)\n refreshWatchers()\n },\n\n notifyLocalChange(category) {\n if (keeping().length > 0)\n watchers.schedule(category)\n },\n\n localInfo: () => syncLocalInfo(sources),\n\n watching: () => watchers.count() > 0,\n\n subscribe(listener) {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n\n stop() {\n watchers.close()\n pusher.stop()\n listeners.clear()\n },\n }\n\n refreshWatchers()\n return engine\n}\n\nfunction syncLocalInfo(sources: Parameters<typeof storedApiKeyProviders>[0]): SyncLocalInfo {\n const read = <T>(fn: () => T, fallback: T): T => {\n try {\n return fn()\n }\n catch {\n return fallback\n }\n }\n return {\n keyProviders: read(() => storedApiKeyProviders(sources), []),\n localExtensions: read(() => userExtensions(sources).local, []),\n stdioMcps: read(() => (collectSyncPayload('mcps', sources) as SyncPayloads['mcps']).servers.filter(s => typeof s.command === 'string' && s.command !== '').map(s => String(s.name)), []),\n }\n}\n","/**\n * The host registry's connection (`src/chat/hosts`): a WebSocket probe that\n * says who answers at a URL with a token, and the registry wired to it.\n */\nimport type { HostErrorCode, HostProbeResult, HostRegistry } from '../../chat/hosts'\nimport { createHostRegistry, displayHostUrl } from '../../chat/hosts'\nimport { hostRefOf } from '../protocol'\nimport { IpcVersionMismatchError } from '../transports/client-core'\nimport { connectWsClient, HostAuthError } from '../transports/ws-client'\n\n/** Bound on one probe: the upgrade, the handshake and `daemon.info`. */\nexport const HOST_PROBE_TIMEOUT_MS = 10_000\n\nconst TLS_FAILURE = /certificate|self[- ]signed|\\btls\\b|\\bssl\\b|UNABLE_TO_VERIFY|CERT_|ERR_TLS/i\n\nfunction classify(err: unknown): { error: HostErrorCode, message: string } {\n if (err instanceof HostAuthError) {\n return err.status === 401\n ? { error: 'auth', message: 'The host refused the token (401). Create a new one on the server: zidane server token create --name <device>.' }\n : { error: 'auth', message: err.message }\n }\n if (err instanceof IpcVersionMismatchError)\n return { error: 'protocol', message: err.message }\n const message = err instanceof Error ? err.message : String(err)\n if (TLS_FAILURE.test(message))\n return { error: 'tls', message: `TLS failed: ${message}` }\n return { error: 'unreachable', message }\n}\n\n/**\n * A failed WebSocket says nothing about why. For `wss://`, ask the same\n * address over HTTPS: a certificate or handshake failure there is a TLS\n * problem, anything else stays \"unreachable\".\n */\nasync function tlsFailure(url: string, signal: AbortSignal): Promise<string | null> {\n if (!url.startsWith('wss:'))\n return null\n try {\n // No token, and no redirect followed: only the TLS handshake with this origin matters.\n const response = await fetch(`https:${url.slice('wss:'.length)}`, { redirect: 'manual', signal: AbortSignal.any([signal, AbortSignal.timeout(5000)]) })\n void response.body?.cancel().catch(() => {})\n return null\n }\n catch (err) {\n const e = err as { code?: unknown, message?: unknown }\n const detail = `${typeof e.code === 'string' ? e.code : ''} ${typeof e.message === 'string' ? e.message : ''}`\n return TLS_FAILURE.test(detail) ? `TLS failed: ${String(e.message ?? e.code)}` : null\n }\n}\n\n/** Connect, read the host's identity and `daemon.info`, disconnect. Never throws. */\nexport async function probeWsHost(target: { url: string, token: string, timeoutMs?: number }): Promise<HostProbeResult> {\n const started = performance.now()\n const signal = AbortSignal.timeout(target.timeoutMs ?? HOST_PROBE_TIMEOUT_MS)\n let client: Awaited<ReturnType<typeof connectWsClient>> | undefined\n try {\n client = await connectWsClient({ url: target.url, token: target.token, heartbeatMs: 0, signal })\n const hostRef = hostRefOf(client.hello)\n if (!hostRef)\n return { ok: false, error: 'protocol', message: `${displayHostUrl(target.url)} runs a zidane too old to say which host it is. Upgrade the server.` }\n const info = await client.request('daemon.info', {})\n const serverVersion = info.codeVersion ?? info.appVersion\n return { ok: true, hostRef, ...(serverVersion ? { serverVersion } : {}), latencyMs: Math.round(performance.now() - started) }\n }\n catch (err) {\n if (signal.aborted && !(err instanceof HostAuthError))\n return { ok: false, error: 'unreachable', message: `No answer from ${displayHostUrl(target.url)} within ${target.timeoutMs ?? HOST_PROBE_TIMEOUT_MS} ms.` }\n const classified = classify(err)\n if (classified.error === 'unreachable') {\n const tls = await tlsFailure(target.url, signal).catch(() => null)\n if (tls)\n return { ok: false, error: 'tls', message: tls }\n }\n return { ok: false, ...classified }\n }\n finally {\n client?.close()\n }\n}\n\n/** The registry in `dataDir`, connecting over WebSocket. */\nexport function createWsHostRegistry(options: { dataDir: string }): HostRegistry {\n return createHostRegistry({ dataDir: options.dataDir, probe: probeWsHost })\n}\n","/**\n * A client's saved servers, kept in its host directory: one directory entry\n * and one app-lifetime connection (`connection-loop`) per server in the\n * registry, in step with it. Shared by the TUI and the GUI main process,\n * which each supply their directory (`SavedHostsDirectory`) and how to dial.\n *\n * Saving a server that is already saved (same host id: a new token, a new\n * URL) reconfigures its entry IN PLACE and reconnects: the entry is never\n * removed, so the sessions routed to it stay routed. Only a server leaving\n * the registry (removed here or by another window) or `stop()` removes an\n * entry, and the directory decides what that means for an open session.\n *\n * Every connection is checked against the saved entry's id (the server's\n * `hostId` when it was added): another host answering at the URL is closed\n * at once, reported as `identity` and not retried, so nothing it says is\n * recorded under the saved id. Dialers may check first (`expectHostId`).\n *\n * No WebSocket import: the WebSocket wiring is `./ws.ts`.\n */\nimport type { HostEntry, HostProbeResult, HostRegistry, HostTestResult } from '../../chat/hosts'\nimport type { HostSignal } from '../protocol'\nimport type { IpcClient } from '../transports/client-core'\nimport type { HostConnectionLoop, HostConnectionPatch, HostFailureKind } from './connection-loop'\nimport { displayHostUrl, HostIdentityError } from '../../chat/hosts'\nimport { hostRefOf } from '../protocol'\nimport { keepHostConnected } from './connection-loop'\n\n/** The client's host directory, as the saved servers see it. Keys are host ids. */\nexport interface SavedHostsDirectory {\n /** The saved servers it holds now, with their URL (a `--host` server excluded). */\n saved: () => { key: string, url: string }[]\n /** Add the entry, or reconfigure the one under its key in place (status `connecting`). */\n upsert: (entry: HostEntry, token: string | undefined) => void\n update: (key: string, patch: HostConnectionPatch & { name?: string, serverVersion?: string }) => void\n /** The server left the registry, or the saved servers stopped. */\n remove: (key: string) => void\n}\n\n/** No token is saved for this server (removed by hand, or another window removed it). */\nexport class MissingHostTokenError extends Error {\n constructor() {\n super('No token saved for this server: add it again.')\n this.name = 'MissingHostTokenError'\n }\n}\n\nexport interface SavedHostsOptions {\n registry: HostRegistry\n directory: SavedHostsDirectory\n /** One connect attempt to a saved server, with its token read fresh. */\n connect: (entry: HostEntry, token: string, options: { signal: AbortSignal, onClose: () => void }) => Promise<IpcClient>\n /** `auth`: refused for good. A missing token is always `auth`, another host answering always `identity`. */\n classify?: (err: unknown) => HostFailureKind\n /** The add form's test of an unsaved URL + token (`probeUnsavedHost`). */\n probeUnsaved?: (target: { url: string, token: string }) => Promise<HostProbeResult>\n /** Saved entries the directory already reaches another way (the TUI's `--host` server). */\n skip?: (entry: HostEntry) => boolean\n onSignal?: (key: string, signal: HostSignal) => void\n onConnected?: (key: string, client: IpcClient) => void\n onDisconnected?: (key: string) => void\n minDelayMs?: number\n maxDelayMs?: number\n}\n\nexport interface SavedHostsController {\n /** The saved hosts, read fresh (other windows share the file). */\n list: () => HostEntry[]\n /** Verify, save, connect (in place when already saved). Throws a `HostRegistryError`. */\n add: (input: { url: string, token: string, name?: string }) => Promise<HostEntry>\n remove: (id: string) => boolean\n rename: (id: string, name: string) => HostEntry\n /** A saved server (by id), or an unsaved URL + token (the add form's test). */\n test: (target: string | { id: string } | { url: string, token: string }) => Promise<HostTestResult>\n /** Reconnect now (after an outage or a token fix). */\n retry: (id: string) => void\n stop: () => void\n}\n\nexport function startSavedHosts(options: SavedHostsOptions): SavedHostsController {\n const { registry, directory, skip = () => false } = options\n const classify = (err: unknown): HostFailureKind => err instanceof MissingHostTokenError ? 'auth' : err instanceof HostIdentityError ? 'identity' : (options.classify?.(err) ?? 'retry')\n\n /** The saved server, or nobody: a connection from another host is closed before anyone sees it. */\n const dial = async (entry: HostEntry, token: string, attempt: { signal: AbortSignal, onClose: () => void }): Promise<IpcClient> => {\n const client = await options.connect(entry, token, attempt)\n const ref = hostRefOf(client.hello)\n if (ref?.id === entry.id)\n return client\n client.close()\n throw new HostIdentityError(displayHostUrl(entry.url), ref?.name)\n }\n const loops = new Map<string, HostConnectionLoop>()\n\n const disconnect = (key: string): void => {\n loops.get(key)?.stop()\n loops.delete(key)\n }\n\n /** (Re)connect `entry` with the token saved now, its directory entry kept or created in place. */\n const connect = (entry: HostEntry): void => {\n const key = entry.id\n disconnect(key)\n directory.upsert(entry, registry.token(key))\n loops.set(key, keepHostConnected({\n connect: (attempt) => {\n const token = registry.token(key)\n return token ? dial(entry, token, attempt) : Promise.reject(new MissingHostTokenError())\n },\n update: patch => directory.update(key, patch),\n classify,\n ...(options.onSignal ? { onSignal: (signal: HostSignal) => options.onSignal!(key, signal) } : {}),\n ...(options.onConnected ? { onConnected: (client: IpcClient) => options.onConnected!(key, client) } : {}),\n ...(options.onDisconnected ? { onDisconnected: () => options.onDisconnected!(key) } : {}),\n ...(options.minDelayMs !== undefined ? { minDelayMs: options.minDelayMs } : {}),\n ...(options.maxDelayMs !== undefined ? { maxDelayMs: options.maxDelayMs } : {}),\n }))\n }\n\n /** Bring the directory in line with the saved hosts. */\n const sync = (): void => {\n const entries = registry.list().filter(entry => !skip(entry))\n const saved = new Set(entries.map(entry => entry.id))\n const known = new Map(directory.saved().map(host => [host.key, host.url]))\n for (const key of known.keys()) {\n if (!saved.has(key)) {\n disconnect(key)\n directory.remove(key)\n }\n }\n for (const entry of entries) {\n if (known.get(entry.id) !== entry.url)\n connect(entry)\n else\n directory.update(entry.id, { name: entry.name, ...(entry.serverVersion ? { serverVersion: entry.serverVersion } : {}) })\n }\n }\n\n sync()\n return {\n list: () => registry.list(),\n add: async (input) => {\n const entry = await registry.add(input)\n // Saved again (a new token or URL): reconnect with them, the entry kept.\n if (!skip(entry))\n connect(entry)\n sync()\n return entry\n },\n remove: (id) => {\n const removed = registry.remove(id)\n sync()\n return removed\n },\n rename: (id, name) => {\n const entry = registry.rename(id, name)\n sync()\n return entry\n },\n test: async (target) => {\n if (typeof target === 'object' && !('id' in target)) {\n if (!options.probeUnsaved)\n throw new Error('Testing an unsaved host is not available here.')\n return options.probeUnsaved(target)\n }\n const id = typeof target === 'string' ? target : target.id\n const result = await registry.test(id)\n if (result.ok) {\n directory.update(id, { serverName: result.hostRef.name, ...(result.serverVersion ? { serverVersion: result.serverVersion } : {}) })\n loops.get(id)?.retry()\n }\n return result\n },\n retry: id => loops.get(id)?.retry(),\n stop: () => {\n for (const key of [...loops.keys()]) {\n disconnect(key)\n directory.remove(key)\n }\n },\n }\n}\n","/**\n * Saved servers over WebSocket: the registry in `dataDir`, the add form's\n * unsaved test, the refusal classification and (by default) the dial, wired\n * for `startSavedHosts`. Loaded behind each client's remote-hosts gate.\n */\nimport type { HostProbeResult } from '../../chat/hosts'\nimport type { HostFailureKind } from './connection-loop'\nimport type { SavedHostsController, SavedHostsOptions } from './saved-hosts'\nimport { HostIdentityError, probeUnsavedHost } from '../../chat/hosts'\nimport { connectWsClient, HostAuthError } from '../transports/ws-client'\nimport { createWsHostRegistry, probeWsHost } from './probe'\nimport { startSavedHosts } from './saved-hosts'\n\n/** A refused token stays refused until the user changes something: no retry loop. */\nexport function classifyWsFailure(err: unknown): HostFailureKind {\n return err instanceof HostAuthError ? 'auth' : err instanceof HostIdentityError ? 'identity' : 'retry'\n}\n\n/** The add form's \"test\": the registry's own checks and probe over WebSocket, saving nothing. */\nexport function probeUnsavedWsHost(target: { url: string, token: string }): Promise<HostProbeResult> {\n return probeUnsavedHost(probeWsHost, target)\n}\n\nexport type WsSavedHostsOptions = Omit<SavedHostsOptions, 'registry' | 'connect' | 'classify' | 'probeUnsaved'> & {\n dataDir: string\n /** Client version in the server's diagnostics (default dial only). */\n appVersion?: string\n /** Dial another way (the TUI goes through its directory entry's transport). Default: `connectWsClient`. */\n connect?: SavedHostsOptions['connect']\n registry?: SavedHostsOptions['registry']\n}\n\nexport function startWsSavedHosts(options: WsSavedHostsOptions): SavedHostsController {\n const { dataDir, appVersion, connect, registry, ...rest } = options\n return startSavedHosts({\n ...rest,\n registry: registry ?? createWsHostRegistry({ dataDir }),\n classify: classifyWsFailure,\n probeUnsaved: probeUnsavedWsHost,\n connect: connect ?? ((entry, token, attempt) => connectWsClient({\n url: entry.url,\n token,\n expectHostId: entry.id,\n ...(appVersion ? { appVersion } : {}),\n signal: attempt.signal,\n onClose: attempt.onClose,\n })),\n })\n}\n"],"mappings":"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"}
@@ -0,0 +1,230 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-BhDjJH2R.js";
2
+ import { a as errorResponse, i as createJsonRpcEndpoint, o as successResponse } from "./json-rpc--HXQti1E.js";
3
+ import { n as displayHostUrl } from "./url-D8HCl65b.js";
4
+ import { f as HostIdentityError, h as METHOD_NOT_FOUND } from "./types-CH5XpIHw.js";
5
+ import { a as createSignalListeners, g as hostRefOf, o as openIpcClient } from "./settings-keys-Ckf29NeM.js";
6
+ //#region src/ipc/transports/ws-auth.ts
7
+ /**
8
+ * How a WebSocket client's token reaches the server, shared by both ends.
9
+ *
10
+ * Preferred: `Authorization: Bearer <token>` (Bun's WebSocket can set it).
11
+ * Fallback for clients that can't set handshake headers (Node's and the
12
+ * browser's WebSocket): a `zidane.bearer.<token>` entry in
13
+ * `Sec-WebSocket-Protocol`, offered next to `zidane`, the subprotocol the
14
+ * server selects. A token sent this way must be a valid subprotocol token
15
+ * (base64url is).
16
+ */
17
+ /** The subprotocol clients offer and the server selects. */
18
+ const WS_SUBPROTOCOL = "zidane";
19
+ /** Prefix of the subprotocol entry carrying the bearer token. */
20
+ const WS_BEARER_PREFIX = "zidane.bearer.";
21
+ /**
22
+ * Why a server refused an upgrade with a 403, as a machine-readable code in
23
+ * {@link WS_REFUSAL_HEADER}. Clients show a fixed text per code (never the
24
+ * response body, which a proxy may fill with anything, the request's own
25
+ * headers included) and ignore codes they don't know.
26
+ */
27
+ const WS_REFUSAL_HEADER = "X-Zidane-Refusal";
28
+ const WS_REFUSAL_REASONS = [
29
+ "origin",
30
+ "insecure-transport",
31
+ "untrusted-proxy",
32
+ "scope"
33
+ ];
34
+ function isWsRefusalReason(value) {
35
+ return typeof value === "string" && WS_REFUSAL_REASONS.includes(value);
36
+ }
37
+ //#endregion
38
+ //#region src/ipc/transports/ws-client.ts
39
+ var ws_client_exports = /* @__PURE__ */ __exportAll({
40
+ HostAuthError: () => HostAuthError,
41
+ HostRedirectError: () => HostRedirectError,
42
+ WS_HEARTBEAT_MS: () => WS_HEARTBEAT_MS,
43
+ connectWsClient: () => connectWsClient
44
+ });
45
+ /** Heartbeat interval on both ends of a WebSocket by default. */
46
+ const WS_HEARTBEAT_MS = 2e4;
47
+ /** How long an upgrade may take by default. */
48
+ const WS_OPEN_TIMEOUT_MS = 15e3;
49
+ const FORBIDDEN = {
50
+ "origin": "this client's origin is not allowed by the server (allowedOrigins)",
51
+ "insecure-transport": "the server only accepts connections through its HTTPS proxy",
52
+ "untrusted-proxy": "the server only accepts connections from its trusted proxies",
53
+ "scope": "this token's scope cannot open a client connection"
54
+ };
55
+ /**
56
+ * The server refused this client's credential: 401 (no valid token) or 403
57
+ * (not allowed here). `reason` only when the server sent a code clients know.
58
+ */
59
+ var HostAuthError = class extends Error {
60
+ status;
61
+ reason;
62
+ url;
63
+ constructor(url, status, reason) {
64
+ const shown = displayHostUrl(url);
65
+ super(`WebSocket connection to ${shown} failed: ${status === 401 ? "token refused (401): check --token / ZIDANE_HOST_TOKEN, or create a new one with `zidane server token create`" : `forbidden (403): ${reason ? FORBIDDEN[reason] : "refused by the server or a proxy in front of it (origin, token scope or proxy rules)"}`}.`);
66
+ this.status = status;
67
+ this.reason = reason;
68
+ this.name = "HostAuthError";
69
+ this.url = shown;
70
+ }
71
+ };
72
+ /** The URL answered with a redirect: not followed (the token would go along). */
73
+ var HostRedirectError = class extends Error {
74
+ constructor(url, status) {
75
+ super(`WebSocket connection to ${displayHostUrl(url)} failed: the server redirects (${status}); not following it with the token. Check the URL (scheme, host, path) or the proxy in front of the server.`);
76
+ this.name = "HostRedirectError";
77
+ }
78
+ };
79
+ /** Bun's WebSocket takes handshake headers; the WHATWG one (Node, browsers) does not. */
80
+ const canSendHeaders = () => typeof globalThis.Bun !== "undefined";
81
+ function createSocket(options) {
82
+ const protocols = [WS_SUBPROTOCOL];
83
+ const carrier = options.tokenCarrier ?? (canSendHeaders() ? "header" : "subprotocol");
84
+ if (options.token && carrier === "subprotocol") protocols.push(`${WS_BEARER_PREFIX}${options.token}`);
85
+ if (options.token && carrier === "header") return new WebSocket(options.url, {
86
+ headers: { Authorization: `Bearer ${options.token}` },
87
+ protocols
88
+ });
89
+ return new WebSocket(options.url, protocols);
90
+ }
91
+ /** The upgrade took longer than `openTimeoutMs`: nothing answered, so there is no refusal to ask about. */
92
+ var WsOpenTimeoutError = class extends Error {
93
+ constructor(url, timeoutMs) {
94
+ super(`WebSocket connection to ${displayHostUrl(url)} timed out after ${timeoutMs} ms.`);
95
+ this.name = "WsOpenTimeoutError";
96
+ }
97
+ };
98
+ function abortError(signal) {
99
+ return signal.reason instanceof Error ? signal.reason : new DOMException("The connect was aborted.", "AbortError");
100
+ }
101
+ /** Resolves on `open`; rejects on failure, timeout or abort (closing the socket). */
102
+ function opened(ws, url, timeoutMs, signal) {
103
+ return new Promise((resolve, reject) => {
104
+ const done = new AbortController();
105
+ let timer;
106
+ const settle = (err) => {
107
+ if (done.signal.aborted) return;
108
+ done.abort();
109
+ clearTimeout(timer);
110
+ if (!err) return resolve();
111
+ ws.close();
112
+ reject(err);
113
+ };
114
+ const fail = (detail) => () => settle(/* @__PURE__ */ new Error(`WebSocket connection to ${displayHostUrl(url)} failed${detail}.`));
115
+ ws.addEventListener("open", () => settle(), { signal: done.signal });
116
+ ws.addEventListener("error", fail(""), { signal: done.signal });
117
+ ws.addEventListener("close", (event) => fail(` (close ${event.code}${event.reason ? `: ${event.reason}` : ""})`)(), { signal: done.signal });
118
+ signal?.addEventListener("abort", () => settle(abortError(signal)), { signal: done.signal });
119
+ timer = setTimeout(() => settle(new WsOpenTimeoutError(url, timeoutMs)), timeoutMs);
120
+ });
121
+ }
122
+ /** Why an upgrade failed, asked over plain HTTP: a {@link HostAuthError} for 401 / 403, a {@link HostRedirectError} for 3xx, else `null`. */
123
+ async function refusal(options) {
124
+ try {
125
+ const url = new URL(options.url);
126
+ url.protocol = url.protocol === "wss:" ? "https:" : "http:";
127
+ const timeout = AbortSignal.timeout(5e3);
128
+ const response = await fetch(url, {
129
+ headers: options.token ? { Authorization: `Bearer ${options.token}` } : {},
130
+ redirect: "manual",
131
+ signal: options.signal ? AbortSignal.any([options.signal, timeout]) : timeout
132
+ });
133
+ response.body?.cancel().catch(() => {});
134
+ if (response.type === "opaqueredirect" || response.status >= 300 && response.status < 400) return new HostRedirectError(options.url, response.status);
135
+ if (response.status !== 401 && response.status !== 403) return null;
136
+ const reason = response.headers.get(WS_REFUSAL_HEADER);
137
+ return new HostAuthError(options.url, response.status, response.status === 403 && isWsRefusalReason(reason) ? reason : void 0);
138
+ } catch {
139
+ return null;
140
+ }
141
+ }
142
+ /** Close a connection whose host is not the one expected, and say so. */
143
+ function checkIdentity(client, options) {
144
+ if (options.expectHostId === void 0) return client;
145
+ const ref = hostRefOf(client.hello);
146
+ if (ref?.id === options.expectHostId) return client;
147
+ client.close();
148
+ throw new HostIdentityError(displayHostUrl(options.url), ref?.name);
149
+ }
150
+ async function connectWsClient(options) {
151
+ const { signal } = options;
152
+ signal?.throwIfAborted();
153
+ const ws = createSocket(options);
154
+ ws.binaryType = "arraybuffer";
155
+ try {
156
+ await opened(ws, options.url, options.openTimeoutMs ?? WS_OPEN_TIMEOUT_MS, signal);
157
+ } catch (err) {
158
+ if (signal?.aborted || err instanceof WsOpenTimeoutError) throw err;
159
+ throw await refusal(options) ?? err;
160
+ }
161
+ const signals = createSignalListeners();
162
+ let closed = false;
163
+ const rpc = createJsonRpcEndpoint({
164
+ send: (json) => {
165
+ try {
166
+ ws.send(json);
167
+ } catch {}
168
+ },
169
+ onRequest: async (message) => {
170
+ const serve = options.serve;
171
+ if (!serve) return errorResponse(message.id, METHOD_NOT_FOUND, "Clients do not accept requests.");
172
+ try {
173
+ return successResponse(message.id, await serve.request(message.method, message.params) ?? null);
174
+ } catch (err) {
175
+ const code = err.code;
176
+ return errorResponse(message.id, typeof code === "number" ? code : -32e3, err instanceof Error ? err.message : String(err));
177
+ }
178
+ },
179
+ onNotification: (message) => {
180
+ if (message.method === "ipc.signal" || !options.serve?.notification) return signals.onNotification(message);
181
+ options.serve.notification(message.method, message.params);
182
+ }
183
+ });
184
+ const decoder = new TextDecoder();
185
+ ws.addEventListener("message", (event) => {
186
+ if (closed) return;
187
+ rpc.receive(typeof event.data === "string" ? event.data : decoder.decode(event.data));
188
+ });
189
+ /** The host went away (or the connection was given up): fail what is pending, tell the owner. */
190
+ const lost = () => {
191
+ if (closed) return;
192
+ closed = true;
193
+ rpc.close();
194
+ options.onClose?.();
195
+ };
196
+ ws.addEventListener("close", lost);
197
+ ws.addEventListener("error", () => {});
198
+ const close = () => {
199
+ if (closed) return;
200
+ closed = true;
201
+ rpc.close();
202
+ ws.close(1e3);
203
+ };
204
+ const onAbort = () => close();
205
+ signal?.addEventListener("abort", onAbort, { once: true });
206
+ try {
207
+ return checkIdentity(await openIpcClient({
208
+ rpc,
209
+ close,
210
+ abort: () => {
211
+ lost();
212
+ ws.close(1e3);
213
+ },
214
+ where: displayHostUrl(options.url)
215
+ }, signals.listeners, {
216
+ ...options.appVersion ? { appVersion: options.appVersion } : {},
217
+ drain: "never",
218
+ buildFence: false,
219
+ heartbeatMs: options.heartbeatMs ?? 2e4
220
+ }), options);
221
+ } catch (err) {
222
+ throw signal?.aborted ? abortError(signal) : err;
223
+ } finally {
224
+ signal?.removeEventListener("abort", onAbort);
225
+ }
226
+ }
227
+ //#endregion
228
+ export { connectWsClient as n, ws_client_exports as r, HostAuthError as t };
229
+
230
+ //# sourceMappingURL=ws-client-N7NxzvQp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws-client-N7NxzvQp.js","names":["BunWebSocket"],"sources":["../src/ipc/transports/ws-auth.ts","../src/ipc/transports/ws-client.ts"],"sourcesContent":["/**\n * How a WebSocket client's token reaches the server, shared by both ends.\n *\n * Preferred: `Authorization: Bearer <token>` (Bun's WebSocket can set it).\n * Fallback for clients that can't set handshake headers (Node's and the\n * browser's WebSocket): a `zidane.bearer.<token>` entry in\n * `Sec-WebSocket-Protocol`, offered next to `zidane`, the subprotocol the\n * server selects. A token sent this way must be a valid subprotocol token\n * (base64url is).\n */\n\n/** The subprotocol clients offer and the server selects. */\nexport const WS_SUBPROTOCOL = 'zidane'\n/** Prefix of the subprotocol entry carrying the bearer token. */\nexport const WS_BEARER_PREFIX = 'zidane.bearer.'\n\nexport type WsTokenCarrier = 'header' | 'subprotocol'\n\n/**\n * What an accepted connection is: a `client` (a window: the whole method\n * table, signals) or a `machine` lending its execution (`docs/MACHINES.md`:\n * only `ipc.hello`, `$/ping`, `machine.register`, never a peer). Default `client`.\n */\nexport type WsConnectionScope = 'client' | 'machine'\n\n/**\n * A server's answer to an upgrade's token. Accepted: `principal` names what\n * authenticated (a token id), so connections can be dropped by it later.\n * Refused: the HTTP status, sent before any JSON-RPC (401 no valid\n * credential, 403 a credential not allowed here).\n */\nexport type WsAuthVerdict\n = | { ok: true, principal?: string, scope?: WsConnectionScope }\n | { ok: false, status: 401 | 403, reason?: WsRefusalReason }\n\n/**\n * Why a server refused an upgrade with a 403, as a machine-readable code in\n * {@link WS_REFUSAL_HEADER}. Clients show a fixed text per code (never the\n * response body, which a proxy may fill with anything, the request's own\n * headers included) and ignore codes they don't know.\n */\nexport const WS_REFUSAL_HEADER = 'X-Zidane-Refusal'\nconst WS_REFUSAL_REASONS = ['origin', 'insecure-transport', 'untrusted-proxy', 'scope'] as const\nexport type WsRefusalReason = typeof WS_REFUSAL_REASONS[number]\n\nexport function isWsRefusalReason(value: unknown): value is WsRefusalReason {\n return typeof value === 'string' && (WS_REFUSAL_REASONS as readonly string[]).includes(value)\n}\n\n/** Subprotocols offered in `Sec-WebSocket-Protocol`. */\nexport function offeredSubprotocols(request: Request): string[] {\n return (request.headers.get('sec-websocket-protocol') ?? '').split(',').map(p => p.trim()).filter(Boolean)\n}\n\n/** The client's token: `Authorization: Bearer`, else the subprotocol entry. */\nexport function requestToken(request: Request): string | undefined {\n const auth = request.headers.get('authorization')\n const bearer = auth && /^Bearer\\s+(\\S+)$/i.exec(auth.trim())\n if (bearer)\n return bearer[1]\n const entry = offeredSubprotocols(request).find(p => p.startsWith(WS_BEARER_PREFIX))\n return entry ? entry.slice(WS_BEARER_PREFIX.length) : undefined\n}\n","/**\n * `IpcClient` over a WebSocket (a remote `zidane-server`, `./ws-server`):\n * one JSON-RPC message per text frame, the same handshake, deadlines and\n * signal delivery as the unix-socket client (`./client-core`).\n *\n * Uses the runtime's global `WebSocket` (Bun; Node >= 22), so it is safe in\n * the Node-imported `zidane/ipc` barrel. Unlike a local daemon client it\n * never asks the host to drain on a version mismatch (a remote server's\n * lifetime is not a client's to end) and opts out of the dev build fence.\n *\n * Opening is bounded (`openTimeoutMs`) and abortable (`signal`, up to the\n * end of the handshake). A refused upgrade is opaque to a WebSocket (no\n * status, just \"expected 101\", close 1002), so on failure the client asks\n * the same URL over plain HTTP, with the same token, why: a 401 or 403\n * becomes a {@link HostAuthError} with a fixed message (the response body\n * is never read: a proxy may echo the request's headers, the token\n * included, and the message reaches a GUI renderer). That request never\n * follows a redirect: a 3xx is reported as a misconfigured URL, and the\n * token goes nowhere but the URL's own origin.\n *\n * Messages name the URL by scheme, host and path only (`displayHostUrl`).\n */\nimport type { IpcClient } from './client-core'\nimport type { WsRefusalReason, WsTokenCarrier } from './ws-auth'\nimport { createJsonRpcEndpoint, errorResponse, successResponse } from '../../acp/json-rpc'\nimport { HostIdentityError, METHOD_NOT_FOUND } from '../../chat/hosts/connection'\nimport { displayHostUrl } from '../../chat/hosts/url'\nimport { hostRefOf } from '../protocol'\nimport { createSignalListeners, openIpcClient } from './client-core'\nimport { isWsRefusalReason, WS_BEARER_PREFIX, WS_REFUSAL_HEADER, WS_SUBPROTOCOL } from './ws-auth'\n\nexport interface WsClientOptions {\n /** `ws://` or `wss://` URL of the server. */\n url: string\n /** Bearer token for the server, see `./ws-auth`. */\n token?: string\n /**\n * How the token travels. Default: the `Authorization` header where the\n * runtime's WebSocket can set one (Bun), else the subprotocol fallback.\n */\n tokenCarrier?: WsTokenCarrier\n /** Client zidane version, surfaced in the host's diagnostics. */\n appVersion?: string\n /** The connection dropped (server exit, network error, a missed deadline or heartbeat). Not called for `close()`. */\n onClose?: () => void\n /** `$/ping` interval (`./client-core`). Default {@link WS_HEARTBEAT_MS}; `0` disables. */\n heartbeatMs?: number\n /** Bound on the upgrade (not the handshake, which has its own). Default {@link WS_OPEN_TIMEOUT_MS}. */\n openTimeoutMs?: number\n /** Abandon the connect (upgrade and handshake): it rejects with the signal's reason. */\n signal?: AbortSignal\n /**\n * The host id a saved host answered with when it was added: a hello with\n * any other id closes the connection and rejects with a\n * {@link HostIdentityError} (nothing is read from that host).\n */\n expectHostId?: string\n /**\n * Answer the host's requests and notifications on this connection: a\n * machine serving its host (`docs/MACHINES.md`). A throw becomes a\n * JSON-RPC error (its `code` when it carries one). Default: a client\n * refuses requests and reads only `ipc.signal`.\n */\n serve?: {\n request: (method: string, params: unknown) => Promise<unknown>\n notification?: (method: string, params: unknown) => void\n }\n}\n\n/** Heartbeat interval on both ends of a WebSocket by default. */\nexport const WS_HEARTBEAT_MS = 20_000\n/** How long an upgrade may take by default. */\nconst WS_OPEN_TIMEOUT_MS = 15_000\n\nconst FORBIDDEN: Record<WsRefusalReason, string> = {\n 'origin': 'this client\\'s origin is not allowed by the server (allowedOrigins)',\n 'insecure-transport': 'the server only accepts connections through its HTTPS proxy',\n 'untrusted-proxy': 'the server only accepts connections from its trusted proxies',\n 'scope': 'this token\\'s scope cannot open a client connection',\n}\n\n/**\n * The server refused this client's credential: 401 (no valid token) or 403\n * (not allowed here). `reason` only when the server sent a code clients know.\n */\nexport class HostAuthError extends Error {\n readonly url: string\n constructor(url: string, readonly status: 401 | 403, readonly reason?: WsRefusalReason) {\n const shown = displayHostUrl(url)\n super(`WebSocket connection to ${shown} failed: ${status === 401\n ? 'token refused (401): check --token / ZIDANE_HOST_TOKEN, or create a new one with `zidane server token create`'\n : `forbidden (403): ${reason ? FORBIDDEN[reason] : 'refused by the server or a proxy in front of it (origin, token scope or proxy rules)'}`}.`)\n this.name = 'HostAuthError'\n this.url = shown\n }\n}\n\n/** The URL answered with a redirect: not followed (the token would go along). */\nexport class HostRedirectError extends Error {\n constructor(url: string, status: number) {\n super(`WebSocket connection to ${displayHostUrl(url)} failed: the server redirects (${status}); not following it with the token. Check the URL (scheme, host, path) or the proxy in front of the server.`)\n this.name = 'HostRedirectError'\n }\n}\n\n/** Bun's WebSocket takes handshake headers; the WHATWG one (Node, browsers) does not. */\nconst canSendHeaders = (): boolean => typeof (globalThis as { Bun?: unknown }).Bun !== 'undefined'\n\nfunction createSocket(options: WsClientOptions): WebSocket {\n const protocols = [WS_SUBPROTOCOL]\n const carrier = options.tokenCarrier ?? (canSendHeaders() ? 'header' : 'subprotocol')\n if (options.token && carrier === 'subprotocol')\n protocols.push(`${WS_BEARER_PREFIX}${options.token}`)\n if (options.token && carrier === 'header') {\n // Bun's constructor extension: `{ headers, protocols }` in place of the protocol list.\n const BunWebSocket = WebSocket as unknown as new (url: string, init: { headers: Record<string, string>, protocols: string[] }) => WebSocket\n return new BunWebSocket(options.url, { headers: { Authorization: `Bearer ${options.token}` }, protocols })\n }\n return new WebSocket(options.url, protocols)\n}\n\n/** The upgrade took longer than `openTimeoutMs`: nothing answered, so there is no refusal to ask about. */\nclass WsOpenTimeoutError extends Error {\n constructor(url: string, timeoutMs: number) {\n super(`WebSocket connection to ${displayHostUrl(url)} timed out after ${timeoutMs} ms.`)\n this.name = 'WsOpenTimeoutError'\n }\n}\n\nfunction abortError(signal: AbortSignal): Error {\n return signal.reason instanceof Error ? signal.reason : new DOMException('The connect was aborted.', 'AbortError')\n}\n\n/** Resolves on `open`; rejects on failure, timeout or abort (closing the socket). */\nfunction opened(ws: WebSocket, url: string, timeoutMs: number, signal: AbortSignal | undefined): Promise<void> {\n return new Promise((resolve, reject) => {\n const done = new AbortController()\n let timer: ReturnType<typeof setTimeout> | undefined\n const settle = (err?: Error): void => {\n if (done.signal.aborted)\n return\n done.abort()\n clearTimeout(timer)\n if (!err)\n return resolve()\n ws.close()\n reject(err)\n }\n const fail = (detail: string) => () => settle(new Error(`WebSocket connection to ${displayHostUrl(url)} failed${detail}.`))\n ws.addEventListener('open', () => settle(), { signal: done.signal })\n ws.addEventListener('error', fail(''), { signal: done.signal })\n ws.addEventListener('close', event => fail(` (close ${event.code}${event.reason ? `: ${event.reason}` : ''})`)(), { signal: done.signal })\n signal?.addEventListener('abort', () => settle(abortError(signal)), { signal: done.signal })\n timer = setTimeout(() => settle(new WsOpenTimeoutError(url, timeoutMs)), timeoutMs)\n })\n}\n\n/** Why an upgrade failed, asked over plain HTTP: a {@link HostAuthError} for 401 / 403, a {@link HostRedirectError} for 3xx, else `null`. */\nasync function refusal(options: WsClientOptions): Promise<Error | null> {\n try {\n const url = new URL(options.url)\n url.protocol = url.protocol === 'wss:' ? 'https:' : 'http:'\n const timeout = AbortSignal.timeout(5000)\n const response = await fetch(url, {\n headers: options.token ? { Authorization: `Bearer ${options.token}` } : {},\n redirect: 'manual',\n signal: options.signal ? AbortSignal.any([options.signal, timeout]) : timeout,\n })\n void response.body?.cancel().catch(() => {})\n if (response.type === 'opaqueredirect' || (response.status >= 300 && response.status < 400))\n return new HostRedirectError(options.url, response.status)\n if (response.status !== 401 && response.status !== 403)\n return null\n const reason = response.headers.get(WS_REFUSAL_HEADER)\n return new HostAuthError(options.url, response.status, response.status === 403 && isWsRefusalReason(reason) ? reason : undefined)\n }\n catch {\n return null\n }\n}\n\n/** Close a connection whose host is not the one expected, and say so. */\nfunction checkIdentity(client: IpcClient, options: WsClientOptions): IpcClient {\n if (options.expectHostId === undefined)\n return client\n const ref = hostRefOf(client.hello)\n if (ref?.id === options.expectHostId)\n return client\n client.close()\n throw new HostIdentityError(displayHostUrl(options.url), ref?.name)\n}\n\nexport async function connectWsClient(options: WsClientOptions): Promise<IpcClient> {\n const { signal } = options\n signal?.throwIfAborted()\n const ws = createSocket(options)\n ws.binaryType = 'arraybuffer'\n try {\n await opened(ws, options.url, options.openTimeoutMs ?? WS_OPEN_TIMEOUT_MS, signal)\n }\n catch (err) {\n if (signal?.aborted || err instanceof WsOpenTimeoutError)\n throw err\n throw (await refusal(options)) ?? err\n }\n\n const signals = createSignalListeners()\n let closed = false\n\n const rpc = createJsonRpcEndpoint({\n send: (json) => {\n try {\n ws.send(json)\n }\n catch {\n // A closing socket: the close handler fails what is pending.\n }\n },\n // The host never sends requests to clients, only notifications; a machine serves them.\n onRequest: async (message) => {\n const serve = options.serve\n if (!serve)\n return errorResponse(message.id, METHOD_NOT_FOUND, 'Clients do not accept requests.')\n try {\n return successResponse(message.id, (await serve.request(message.method, message.params)) ?? null)\n }\n catch (err) {\n const code = (err as { code?: unknown }).code\n return errorResponse(message.id, typeof code === 'number' ? code : -32000, err instanceof Error ? err.message : String(err))\n }\n },\n onNotification: (message) => {\n if (message.method === 'ipc.signal' || !options.serve?.notification)\n return signals.onNotification(message)\n options.serve.notification(message.method, (message as { params?: unknown }).params)\n },\n })\n\n const decoder = new TextDecoder()\n ws.addEventListener('message', (event: MessageEvent) => {\n if (closed)\n return\n rpc.receive(typeof event.data === 'string' ? event.data : decoder.decode(event.data as ArrayBuffer))\n })\n\n /** The host went away (or the connection was given up): fail what is pending, tell the owner. */\n const lost = (): void => {\n if (closed)\n return\n closed = true\n rpc.close()\n options.onClose?.()\n }\n ws.addEventListener('close', lost)\n ws.addEventListener('error', () => {\n // 'close' follows.\n })\n\n const close = (): void => {\n if (closed)\n return\n closed = true\n rpc.close()\n ws.close(1000)\n }\n\n // Aborted mid-handshake: the close fails the pending hello, and the connect rejects with the signal's reason.\n const onAbort = (): void => close()\n signal?.addEventListener('abort', onAbort, { once: true })\n try {\n return checkIdentity(await openIpcClient(\n {\n rpc,\n close,\n abort: () => {\n lost()\n ws.close(1000)\n },\n where: displayHostUrl(options.url),\n },\n signals.listeners,\n {\n ...(options.appVersion ? { appVersion: options.appVersion } : {}),\n drain: 'never',\n buildFence: false,\n heartbeatMs: options.heartbeatMs ?? WS_HEARTBEAT_MS,\n },\n ), options)\n }\n catch (err) {\n throw signal?.aborted ? abortError(signal) : err\n }\n finally {\n signal?.removeEventListener('abort', onAbort)\n }\n}\n"],"mappings":"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"}