zidane 7.2.4 → 8.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (376) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +34 -6
  3. package/dist/{acp-D-tVyUjw.js → acp-DQDhi2dj.js} +230 -77
  4. package/dist/acp-DQDhi2dj.js.map +1 -0
  5. package/dist/acp-cli.d.ts +1 -1
  6. package/dist/acp-cli.js +9 -66
  7. package/dist/acp-cli.js.map +1 -1
  8. package/dist/acp.d.ts +10 -590
  9. package/dist/acp.d.ts.map +1 -1
  10. package/dist/acp.js +3 -3
  11. package/dist/{agent-D0zZnGbt.js → agent-DSLNmBp0.js} +14401 -13214
  12. package/dist/agent-DSLNmBp0.js.map +1 -0
  13. package/dist/agent.d.ts +1 -1
  14. package/dist/agent.js +3 -2
  15. package/dist/aliasing-lVFbm81n.js +217 -0
  16. package/dist/aliasing-lVFbm81n.js.map +1 -0
  17. package/dist/{anthropic-C2aole0G.js → anthropic-CD00LhUP.js} +1442 -1264
  18. package/dist/anthropic-CD00LhUP.js.map +1 -0
  19. package/dist/artifacts-CV2hUKnL.js.map +1 -1
  20. package/dist/{atomic-write-B7zr1ddF.js → atomic-write-Ijgf2Mhc.js} +13 -3
  21. package/dist/atomic-write-Ijgf2Mhc.js.map +1 -0
  22. package/dist/call-tool-dHlbGOIY.js +70 -0
  23. package/dist/call-tool-dHlbGOIY.js.map +1 -0
  24. package/dist/chat/pure.d.ts +372 -6
  25. package/dist/chat/pure.d.ts.map +1 -1
  26. package/dist/chat/pure.js +35 -244
  27. package/dist/chat/pure.js.map +1 -1
  28. package/dist/{approvals-DKaJZYlm.js → chat-JPJJ8uu5.js} +15879 -14631
  29. package/dist/chat-JPJJ8uu5.js.map +1 -0
  30. package/dist/chat.d.ts +4 -6
  31. package/dist/chat.js +23 -12
  32. package/dist/cli-shared-C-YCaglL.js +159 -0
  33. package/dist/cli-shared-C-YCaglL.js.map +1 -0
  34. package/dist/client-core-BQSyDALT.d.ts +2115 -0
  35. package/dist/client-core-BQSyDALT.d.ts.map +1 -0
  36. package/dist/codemode-worker.d.ts +1 -0
  37. package/dist/codemode-worker.js +155 -0
  38. package/dist/codemode-worker.js.map +1 -0
  39. package/dist/codemode.d.ts +352 -0
  40. package/dist/codemode.d.ts.map +1 -0
  41. package/dist/codemode.js +5 -0
  42. package/dist/connection-Dr-Js4yZ.d.ts +28 -0
  43. package/dist/connection-Dr-Js4yZ.d.ts.map +1 -0
  44. package/dist/connection-loop-gdh22LTI.js +112 -0
  45. package/dist/connection-loop-gdh22LTI.js.map +1 -0
  46. package/dist/context-segments-BHKlagL6.js +1016 -0
  47. package/dist/context-segments-BHKlagL6.js.map +1 -0
  48. package/dist/{context-transport-T_6AYIvy.js → context-transport-DSMTUsK1.js} +3 -3
  49. package/dist/{context-transport-T_6AYIvy.js.map → context-transport-DSMTUsK1.js.map} +1 -1
  50. package/dist/contexts/daytona.d.ts +19 -8
  51. package/dist/contexts/daytona.d.ts.map +1 -1
  52. package/dist/contexts/daytona.js +1 -440
  53. package/dist/contexts/docker.d.ts +36 -7
  54. package/dist/contexts/docker.d.ts.map +1 -1
  55. package/dist/contexts/docker.js +1 -456
  56. package/dist/contexts/e2b.d.ts +68 -13
  57. package/dist/contexts/e2b.d.ts.map +1 -1
  58. package/dist/contexts/e2b.js +1 -382
  59. package/dist/contexts/sandbox.d.ts +1 -1
  60. package/dist/contexts/sandbox.js +5 -0
  61. package/dist/contexts/sandbox.js.map +1 -1
  62. package/dist/{contexts-CRE9pw07.js → contexts-d7UolYot.js} +1059 -524
  63. package/dist/contexts-d7UolYot.js.map +1 -0
  64. package/dist/contexts.d.ts +3 -3
  65. package/dist/contexts.js +1 -1
  66. package/dist/cred-keys-GpBg71cP.js +105 -0
  67. package/dist/cred-keys-GpBg71cP.js.map +1 -0
  68. package/dist/{auth-BG2rVKSt.js → credentials-JttEuRON.js} +55 -206
  69. package/dist/credentials-JttEuRON.js.map +1 -0
  70. package/dist/{cursor-iojRXHF9.js → cursor-CdjaQTBW.js} +3 -3
  71. package/dist/{cursor-iojRXHF9.js.map → cursor-CdjaQTBW.js.map} +1 -1
  72. package/dist/daemon-cli.d.ts +1 -1
  73. package/dist/daemon-cli.js +3 -2
  74. package/dist/daemon-cli.js.map +1 -1
  75. package/dist/daytona-DG3omipZ.js +513 -0
  76. package/dist/daytona-DG3omipZ.js.map +1 -0
  77. package/dist/defaults-Cx3zvDOV.js +23 -0
  78. package/dist/defaults-Cx3zvDOV.js.map +1 -0
  79. package/dist/dispatcher-BMlu2BmZ.js +4941 -0
  80. package/dist/dispatcher-BMlu2BmZ.js.map +1 -0
  81. package/dist/docker-BZhMMJUp.js +727 -0
  82. package/dist/docker-BZhMMJUp.js.map +1 -0
  83. package/dist/e2b-CEVOdRib.js +480 -0
  84. package/dist/e2b-CEVOdRib.js.map +1 -0
  85. package/dist/edit-utils-EGosADZq.js +234 -0
  86. package/dist/edit-utils-EGosADZq.js.map +1 -0
  87. package/dist/environment-8wsKE2Ln.js +214 -0
  88. package/dist/environment-8wsKE2Ln.js.map +1 -0
  89. package/dist/eval-BNcvle_J.js +1595 -0
  90. package/dist/eval-BNcvle_J.js.map +1 -0
  91. package/dist/eval.d.ts +2 -2
  92. package/dist/eval.js +1 -1489
  93. package/dist/executor-Cx5-8yqi.js +621 -0
  94. package/dist/executor-Cx5-8yqi.js.map +1 -0
  95. package/dist/extension-authoring-DyGGmq9V.js +385 -0
  96. package/dist/extension-authoring-DyGGmq9V.js.map +1 -0
  97. package/dist/extensions.d.ts +2 -2
  98. package/dist/extensions.js +3 -3
  99. package/dist/{fetch-url-DX75gpL0.js → fetch-url-Ct2TjDWt.js} +4 -4
  100. package/dist/{fetch-url-DX75gpL0.js.map → fetch-url-Ct2TjDWt.js.map} +1 -1
  101. package/dist/{format-BF745pLL.js → format-C2NQEVUH.js} +39 -2
  102. package/dist/format-C2NQEVUH.js.map +1 -0
  103. package/dist/format-bytes-C7tfc3Zm.js +55 -0
  104. package/dist/format-bytes-C7tfc3Zm.js.map +1 -0
  105. package/dist/headless-C_rNUuYC.js +960 -0
  106. package/dist/headless-C_rNUuYC.js.map +1 -0
  107. package/dist/headless.d.ts +1 -1
  108. package/dist/headless.js +1 -413
  109. package/dist/{history-search-C4bk1Wz_.js → history-search-CcYzF8-0.js} +7 -3
  110. package/dist/history-search-CcYzF8-0.js.map +1 -0
  111. package/dist/history-search-worker.d.ts +1 -1
  112. package/dist/history-search-worker.js +1 -1
  113. package/dist/host-D7NrI03V.js +378 -0
  114. package/dist/host-D7NrI03V.js.map +1 -0
  115. package/dist/host-signals-BcP5QKUD.js +118 -0
  116. package/dist/host-signals-BcP5QKUD.js.map +1 -0
  117. package/dist/identity-CwfO8K-t.js +26 -0
  118. package/dist/identity-CwfO8K-t.js.map +1 -0
  119. package/dist/{index-BgN1T3lk.d.ts → index-BGe1fQT7.d.ts} +10987 -9320
  120. package/dist/index-BGe1fQT7.d.ts.map +1 -0
  121. package/dist/index-BVQsIKGn.d.ts +448 -0
  122. package/dist/index-BVQsIKGn.d.ts.map +1 -0
  123. package/dist/{index-C6NEd5y_.d.ts → index-CHABJd-L.d.ts} +3386 -502
  124. package/dist/index-CHABJd-L.d.ts.map +1 -0
  125. package/dist/{index-C37_ppWv.d.ts → index-D6a7qXpg.d.ts} +2 -3
  126. package/dist/index-D6a7qXpg.d.ts.map +1 -0
  127. package/dist/index.d.ts +6 -6
  128. package/dist/index.js +27 -23
  129. package/dist/{completion-core-BRo86R_L.js → inline-ghost-BVRQeGoL.js} +50 -2
  130. package/dist/inline-ghost-BVRQeGoL.js.map +1 -0
  131. package/dist/ipc/remote.d.ts +313 -0
  132. package/dist/ipc/remote.d.ts.map +1 -0
  133. package/dist/ipc/remote.js +4 -0
  134. package/dist/ipc.d.ts +6 -964
  135. package/dist/ipc.js +403 -4
  136. package/dist/ipc.js.map +1 -0
  137. package/dist/{isolation-Kfoof0MM.d.ts → isolation-D9L650W5.d.ts} +100 -15
  138. package/dist/isolation-D9L650W5.d.ts.map +1 -0
  139. package/dist/json-rpc--HXQti1E.js +350 -0
  140. package/dist/json-rpc--HXQti1E.js.map +1 -0
  141. package/dist/links-j8rED1sR.js +603 -0
  142. package/dist/links-j8rED1sR.js.map +1 -0
  143. package/dist/local-terminal-D8QThwo_.js +252 -0
  144. package/dist/local-terminal-D8QThwo_.js.map +1 -0
  145. package/dist/{logger--C1VQjwJ.js → logger-Gtqlayx8.js} +199 -173
  146. package/dist/logger-Gtqlayx8.js.map +1 -0
  147. package/dist/logs-view-CWG8aUAG.js.map +1 -1
  148. package/dist/{mcp-CgNd-f3F.js → mcp-_wecH9Qe.js} +608 -562
  149. package/dist/mcp-_wecH9Qe.js.map +1 -0
  150. package/dist/mcp.d.ts +2 -2
  151. package/dist/mcp.js +2 -2
  152. package/dist/media-sniff-UKijEaiQ.js.map +1 -1
  153. package/dist/{messages-2jcOA_5R.js → messages-BqiwcD2Q.js} +1017 -1014
  154. package/dist/messages-BqiwcD2Q.js.map +1 -0
  155. package/dist/{oauth-DxHO17JE.js → oauth-Px_pBB9W.js} +5 -5
  156. package/dist/{oauth-DxHO17JE.js.map → oauth-Px_pBB9W.js.map} +1 -1
  157. package/dist/{openai-compat-Dy56weK8.js → openai-compat-CFrpH7uq.js} +432 -589
  158. package/dist/openai-compat-CFrpH7uq.js.map +1 -0
  159. package/dist/orchestration-BCGmB8Ps.js +511 -0
  160. package/dist/orchestration-BCGmB8Ps.js.map +1 -0
  161. package/dist/output/stream-json.d.ts +1 -2
  162. package/dist/output/stream-json.d.ts.map +1 -1
  163. package/dist/output/stream-json.js +1 -1
  164. package/dist/output/terminal.d.ts +1 -2
  165. package/dist/output/terminal.d.ts.map +1 -1
  166. package/dist/output/terminal.js +13 -7
  167. package/dist/output/terminal.js.map +1 -1
  168. package/dist/{plugins-gbI7SBA6.js → plugins-DS7mahzZ.js} +20 -101
  169. package/dist/plugins-DS7mahzZ.js.map +1 -0
  170. package/dist/plugins.d.ts +1 -1
  171. package/dist/plugins.js +1 -2
  172. package/dist/prelude-Cxo4t74B.js +517 -0
  173. package/dist/prelude-Cxo4t74B.js.map +1 -0
  174. package/dist/presets.d.ts +1 -1
  175. package/dist/presets.js +1 -2
  176. package/dist/project-root-B8zADr4o.js +167 -0
  177. package/dist/project-root-B8zADr4o.js.map +1 -0
  178. package/dist/project-user-paths-BSgtrRxl.js +58 -0
  179. package/dist/project-user-paths-BSgtrRxl.js.map +1 -0
  180. package/dist/{prompts-Pqc3JdW_.d.ts → prompts-DYcvqShf.d.ts} +14 -11
  181. package/dist/prompts-DYcvqShf.d.ts.map +1 -0
  182. package/dist/protocol-DnhqqSmE.js +13 -0
  183. package/dist/protocol-DnhqqSmE.js.map +1 -0
  184. package/dist/providers/anthropic.d.ts +2 -2
  185. package/dist/providers/anthropic.js +1 -2
  186. package/dist/providers/arcee.d.ts +1 -1
  187. package/dist/providers/arcee.js +1 -1
  188. package/dist/providers/baseten.d.ts +1 -1
  189. package/dist/providers/baseten.js +1 -1
  190. package/dist/providers/cerebras.d.ts +1 -1
  191. package/dist/providers/cerebras.js +3 -2
  192. package/dist/providers/cerebras.js.map +1 -1
  193. package/dist/providers/local.d.ts +1 -1
  194. package/dist/providers/local.js +1 -1
  195. package/dist/providers/openai-compat.d.ts +1 -1
  196. package/dist/providers/openai-compat.js +1 -2
  197. package/dist/providers/openai.d.ts +1 -1
  198. package/dist/providers/openai.js +15 -12
  199. package/dist/providers/openai.js.map +1 -1
  200. package/dist/providers/openrouter.d.ts +1 -1
  201. package/dist/providers/openrouter.js +3 -2
  202. package/dist/providers/openrouter.js.map +1 -1
  203. package/dist/providers/xai.d.ts +1 -1
  204. package/dist/providers/xai.js +3 -3
  205. package/dist/{providers-BVhnFyiY.js → providers-XUR7F4Hi.js} +4 -4
  206. package/dist/{providers-BVhnFyiY.js.map → providers-XUR7F4Hi.js.map} +1 -1
  207. package/dist/providers.d.ts +1 -1
  208. package/dist/providers.js +4 -4
  209. package/dist/registry-D6ShBWJU.js +5234 -0
  210. package/dist/registry-D6ShBWJU.js.map +1 -0
  211. package/dist/remote-hosts-BtA_9ZGp.js +97 -0
  212. package/dist/remote-hosts-BtA_9ZGp.js.map +1 -0
  213. package/dist/restate.d.ts +2 -3
  214. package/dist/restate.d.ts.map +1 -1
  215. package/dist/restate.js +631 -572
  216. package/dist/restate.js.map +1 -1
  217. package/dist/run-summary-CklLiZ4y.js +288 -0
  218. package/dist/run-summary-CklLiZ4y.js.map +1 -0
  219. package/dist/{sandbox-BH0WQkXn.d.ts → sandbox-C5dR5DwQ.d.ts} +6 -3
  220. package/dist/sandbox-C5dR5DwQ.d.ts.map +1 -0
  221. package/dist/session/sqlite.d.ts +1 -2
  222. package/dist/session/sqlite.d.ts.map +1 -1
  223. package/dist/session/sqlite.js +1 -616
  224. package/dist/session-factory-BUGY5P40.js +1576 -0
  225. package/dist/session-factory-BUGY5P40.js.map +1 -0
  226. package/dist/{session-BqRP1hS7.js → session-xh9JXu6i.js} +94 -52
  227. package/dist/session-xh9JXu6i.js.map +1 -0
  228. package/dist/session.d.ts +1 -1
  229. package/dist/session.js +2 -2
  230. package/dist/settings-keys-Ckf29NeM.js +677 -0
  231. package/dist/settings-keys-Ckf29NeM.js.map +1 -0
  232. package/dist/shell-path-Dqaoow2J.js +412 -0
  233. package/dist/shell-path-Dqaoow2J.js.map +1 -0
  234. package/dist/{skills-BC3dodWp.js → skills-DKqZJm4X.js} +430 -470
  235. package/dist/skills-DKqZJm4X.js.map +1 -0
  236. package/dist/skills.d.ts +2 -2
  237. package/dist/skills.js +1 -2
  238. package/dist/source-mPExaUm8.js +381 -0
  239. package/dist/source-mPExaUm8.js.map +1 -0
  240. package/dist/sqlite-DV1DQzN2.js +698 -0
  241. package/dist/sqlite-DV1DQzN2.js.map +1 -0
  242. package/dist/{src-CkNQKFKr.js → src-BRMYRJib.js} +903 -1121
  243. package/dist/src-BRMYRJib.js.map +1 -0
  244. package/dist/{stdio-DPpBDPx5.js → stdio-C6YyoW3I.js} +4 -4
  245. package/dist/{stdio-DPpBDPx5.js.map → stdio-C6YyoW3I.js.map} +1 -1
  246. package/dist/{stdio-loader-Bbx19dMZ.js → stdio-loader-C830Vg-Z.js} +4 -4
  247. package/dist/{stdio-loader-Bbx19dMZ.js.map → stdio-loader-C830Vg-Z.js.map} +1 -1
  248. package/dist/system-prompt-MNVHatSD.d.ts.map +1 -1
  249. package/dist/timeout-DEaqslLO.d.ts.map +1 -1
  250. package/dist/todo-edits-Dn251YUP.js +1790 -0
  251. package/dist/todo-edits-Dn251YUP.js.map +1 -0
  252. package/dist/{turn-operations-DrbJlpq9.js → tool-formatters-IQFDrdrs.js} +1456 -2120
  253. package/dist/tool-formatters-IQFDrdrs.js.map +1 -0
  254. package/dist/tool-state-Dku6YqAB.js +989 -0
  255. package/dist/tool-state-Dku6YqAB.js.map +1 -0
  256. package/dist/tools/fetch-url.d.ts +1 -2
  257. package/dist/tools/fetch-url.d.ts.map +1 -1
  258. package/dist/tools/fetch-url.js +1 -2
  259. package/dist/tools/prompts.d.ts +1 -1
  260. package/dist/tools/prompts.js +7 -7
  261. package/dist/tools/prompts.js.map +1 -1
  262. package/dist/tools/web-search.d.ts +1 -2
  263. package/dist/tools/web-search.d.ts.map +1 -1
  264. package/dist/tools/web-search.js +2 -2
  265. package/dist/tools/web-search.js.map +1 -1
  266. package/dist/tools-_DnT3AGM.js +578 -0
  267. package/dist/tools-_DnT3AGM.js.map +1 -0
  268. package/dist/tools.d.ts +3 -3
  269. package/dist/tools.js +4 -2
  270. package/dist/tui.d.ts +534 -517
  271. package/dist/tui.d.ts.map +1 -1
  272. package/dist/tui.js +34933 -27242
  273. package/dist/tui.js.map +1 -1
  274. package/dist/turn-operations-B8sokwi5.js +333 -0
  275. package/dist/turn-operations-B8sokwi5.js.map +1 -0
  276. package/dist/turn-operations-DQX5ZZni.d.ts +3089 -0
  277. package/dist/turn-operations-DQX5ZZni.d.ts.map +1 -0
  278. package/dist/types-C7ZFOztE.d.ts +132 -0
  279. package/dist/types-C7ZFOztE.d.ts.map +1 -0
  280. package/dist/types-CH5XpIHw.js +114 -0
  281. package/dist/types-CH5XpIHw.js.map +1 -0
  282. package/dist/{types-CWgENVLY.js → types-Cu0ZGDu9.js} +10 -6
  283. package/dist/types-Cu0ZGDu9.js.map +1 -0
  284. package/dist/types-IqegbJEE.d.ts +624 -0
  285. package/dist/types-IqegbJEE.d.ts.map +1 -0
  286. package/dist/types.d.ts +4 -4
  287. package/dist/types.js +1 -1
  288. package/dist/url-D8HCl65b.js +1259 -0
  289. package/dist/url-D8HCl65b.js.map +1 -0
  290. package/dist/wasm-BVT-j5cl.js +33 -0
  291. package/dist/wasm-BVT-j5cl.js.map +1 -0
  292. package/dist/workspace-exec-stream-SV2R9d5S.js +355 -0
  293. package/dist/workspace-exec-stream-SV2R9d5S.js.map +1 -0
  294. package/dist/ws-CIHMvlSh.js +952 -0
  295. package/dist/ws-CIHMvlSh.js.map +1 -0
  296. package/dist/ws-client-N7NxzvQp.js +230 -0
  297. package/dist/ws-client-N7NxzvQp.js.map +1 -0
  298. package/dist/{xai-CazjStOK.js → xai-CvJTeLrI.js} +165 -5
  299. package/dist/xai-CvJTeLrI.js.map +1 -0
  300. package/dist/xdg-zweed0-t.js +117 -0
  301. package/dist/xdg-zweed0-t.js.map +1 -0
  302. package/docs/ACP.md +52 -0
  303. package/docs/ARCHITECTURE.md +103 -6
  304. package/docs/ARTIFACTS.md +8 -4
  305. package/docs/CHAT.md +165 -14
  306. package/docs/EXECUTION_CONTEXT.md +8 -0
  307. package/docs/EXTENSIONS.md +123 -2
  308. package/docs/HEADLESS.md +2 -0
  309. package/docs/IPC.md +775 -64
  310. package/docs/MACHINES.md +456 -0
  311. package/docs/PANELS.md +3 -0
  312. package/docs/README.md +4 -0
  313. package/docs/RESTATE.md +3 -2
  314. package/docs/RUN_IN_BACKGROUND.md +10 -2
  315. package/docs/SERVER.md +1085 -0
  316. package/docs/SKILL.md +6 -1
  317. package/docs/TERMINAL.md +75 -0
  318. package/docs/TUI.md +65 -14
  319. package/package.json +58 -26
  320. package/scripts/eval.ts +4 -0
  321. package/dist/acp-D-tVyUjw.js.map +0 -1
  322. package/dist/agent-D0zZnGbt.js.map +0 -1
  323. package/dist/anthropic-C2aole0G.js.map +0 -1
  324. package/dist/approvals-DKaJZYlm.js.map +0 -1
  325. package/dist/atomic-write-B7zr1ddF.js.map +0 -1
  326. package/dist/auth-BG2rVKSt.js.map +0 -1
  327. package/dist/completion-core-BRo86R_L.js.map +0 -1
  328. package/dist/contexts/daytona.js.map +0 -1
  329. package/dist/contexts/docker.js.map +0 -1
  330. package/dist/contexts/e2b.js.map +0 -1
  331. package/dist/contexts-CRE9pw07.js.map +0 -1
  332. package/dist/eval.js.map +0 -1
  333. package/dist/format-BF745pLL.js.map +0 -1
  334. package/dist/glob-DluQFSw1.js +0 -270
  335. package/dist/glob-DluQFSw1.js.map +0 -1
  336. package/dist/headless.js.map +0 -1
  337. package/dist/history-search-C4bk1Wz_.js.map +0 -1
  338. package/dist/index-BgN1T3lk.d.ts.map +0 -1
  339. package/dist/index-C37_ppWv.d.ts.map +0 -1
  340. package/dist/index-C6NEd5y_.d.ts.map +0 -1
  341. package/dist/ipc-zVSyo6K1.js +0 -331
  342. package/dist/ipc-zVSyo6K1.js.map +0 -1
  343. package/dist/ipc.d.ts.map +0 -1
  344. package/dist/isolation-Kfoof0MM.d.ts.map +0 -1
  345. package/dist/json-rpc-rSWMUh9b.js +0 -192
  346. package/dist/json-rpc-rSWMUh9b.js.map +0 -1
  347. package/dist/logger--C1VQjwJ.js.map +0 -1
  348. package/dist/mcp-CgNd-f3F.js.map +0 -1
  349. package/dist/messages-2jcOA_5R.js.map +0 -1
  350. package/dist/openai-compat-Dy56weK8.js.map +0 -1
  351. package/dist/output-cap-C9zukcCj.js +0 -100
  352. package/dist/output-cap-C9zukcCj.js.map +0 -1
  353. package/dist/panels-B6gRk4bf.js +0 -789
  354. package/dist/panels-B6gRk4bf.js.map +0 -1
  355. package/dist/plugins-gbI7SBA6.js.map +0 -1
  356. package/dist/prompts-Pqc3JdW_.d.ts.map +0 -1
  357. package/dist/run-summary-BU_NgwUT.js +0 -269
  358. package/dist/run-summary-BU_NgwUT.js.map +0 -1
  359. package/dist/sandbox-BH0WQkXn.d.ts.map +0 -1
  360. package/dist/session/sqlite.js.map +0 -1
  361. package/dist/session-BqRP1hS7.js.map +0 -1
  362. package/dist/shell-path-h5czzllR.js +0 -1549
  363. package/dist/shell-path-h5czzllR.js.map +0 -1
  364. package/dist/skills-BC3dodWp.js.map +0 -1
  365. package/dist/src-CkNQKFKr.js.map +0 -1
  366. package/dist/todo-edits-UOwgxGKu.js +0 -528
  367. package/dist/todo-edits-UOwgxGKu.js.map +0 -1
  368. package/dist/tool-formatters-DoRLnfuD.d.ts +0 -759
  369. package/dist/tool-formatters-DoRLnfuD.d.ts.map +0 -1
  370. package/dist/transcript-anchors-BeudMbXx.d.ts +0 -1762
  371. package/dist/transcript-anchors-BeudMbXx.d.ts.map +0 -1
  372. package/dist/turn-operations-C8bMBDl_.d.ts +0 -1258
  373. package/dist/turn-operations-C8bMBDl_.d.ts.map +0 -1
  374. package/dist/turn-operations-DrbJlpq9.js.map +0 -1
  375. package/dist/types-CWgENVLY.js.map +0 -1
  376. package/dist/xai-CazjStOK.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-keys-Ckf29NeM.js","names":["(pkg as { version?: string }).version"],"sources":["../src/ipc/daemon/lifecycle.ts","../package.json","../src/version.ts","../src/ipc/protocol.ts","../src/ipc/transports/client-core.ts","../src/chat/sync/hash.ts","../src/chat/sync/settings-keys.ts"],"sourcesContent":["/**\n * Daemon lifecycle: socket-path resolution, liveness probing, stale-socket\n * cleanup, and spawn-on-demand.\n *\n * The socket lives in a dedicated daemon subdir of the resolved state dir\n * (`~/.zidane/daemon/daemon.sock` by default, honoring the same\n * `ZIDANE_STORAGE_DIR` / `ZIDANE_PREFIX` env knobs every other surface\n * uses), overridable via `ZIDANE_DAEMON_SOCKET` for parallel installs and\n * tests.\n */\nimport { spawn } from 'node:child_process'\nimport { existsSync, readdirSync, statSync } from 'node:fs'\nimport { connect } from 'node:net'\nimport { basename, dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { resolveStorageDirs } from '../../chat/xdg'\n\n/**\n * Build fingerprint for the handshake — the mtime of this module's file\n * at import time. Client and daemon load the same file from disk, so a\n * daemon spawned before a rebuild (or a source edit in dev) reports a\n * different id than a freshly-started client, and the client drains +\n * respawns it. This closes the \"same protocol version, different code\"\n * gap that a hand-bumped version constant can't: during development the\n * daemon process is frozen at spawn while the tree keeps moving.\n *\n * Compiled binaries (`/$bunfs/…` virtual paths) can't be stat'ed and\n * report `'unknown'`; the check is skipped when EITHER side is unknown,\n * so released builds rely on `IPC_PROTOCOL_VERSION` alone — correct,\n * since their code only changes when the version does.\n */\nexport const IPC_BUILD_ID: string = (() => {\n try {\n const selfPath = fileURLToPath(import.meta.url)\n /*\n * Dev (running from source): fingerprint the WHOLE ipc surface, not\n * just this file — a change to server.ts / engine.ts / runtime code\n * with no edit to lifecycle.ts must still retire an old daemon. Walk\n * `src/ipc/**` and take the newest mtime. When the tree isn't present\n * (bundled dist, compiled binary) the walk throws and we fall back to\n * this module's own file mtime; in a bundle every ipc source collapses\n * into one chunk, so that single mtime already moves on any ipc change.\n */\n /*\n * Root validation is load-bearing: from a built bundle this module\n * lives flat in `dist/`, so the two-levels-up guess would be the\n * PACKAGE root — walking it would synchronously stat the whole repo\n * (node_modules, .git) at import time and fingerprint unrelated\n * churn. Only walk when the candidate directory demonstrably IS the\n * ipc source tree; a bundle falls back to this chunk's own mtime,\n * which already moves on every rebuild.\n */\n const ipcRoot = dirname(dirname(selfPath))\n if (!existsSync(join(ipcRoot, 'protocol.ts')))\n return String(Math.floor(statSync(selfPath).mtimeMs))\n\n /*\n * Dev scope: walk the whole `src/` tree, not just `src/ipc` — daemon\n * behavior also lives in agent.ts, loop.ts, and chat/** (store,\n * replay, discovery), and an edit there must retire a running dev\n * daemon just as surely as an ipc edit (the spawn-marker incident\n * lived in chat/store.ts). A few hundred stats — milliseconds.\n */\n const srcRoot = dirname(ipcRoot)\n let newest = 0\n const walk = (dir: string): void => {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const full = join(dir, entry.name)\n if (entry.isDirectory())\n walk(full)\n else\n newest = Math.max(newest, statSync(full).mtimeMs)\n }\n }\n try {\n walk(srcRoot)\n }\n catch {\n newest = statSync(selfPath).mtimeMs\n }\n return String(Math.floor(newest))\n }\n catch {\n return 'unknown'\n }\n})()\n\n/**\n * Socket file name. Dev builds (`ZIDANE_DEV=1`, set by every `dev` script\n * in the repo) get their OWN socket so a checkout's TUI, GUI and `zidane\n * daemon` pair up among themselves and never attach to — or get refused by\n * — the installed daemon. Without this, a protocol bump in the working\n * tree turned the dev GUI's dot red against the stable daemon, and a dev\n * daemon could drain the one the installed TUI relies on.\n */\nexport function daemonSocketName(env: NodeJS.ProcessEnv = process.env): 'daemon.sock' | 'dev.sock' {\n return env.ZIDANE_DEV && env.ZIDANE_DEV !== '0' ? 'dev.sock' : 'daemon.sock'\n}\n\nexport function defaultSocketPath(): string {\n const explicit = process.env.ZIDANE_DAEMON_SOCKET\n if (explicit)\n return explicit\n /*\n * The socket is transient runtime state, so it lands under the resolved\n * state dir — XDG-aware on XDG installs, `<storageDir>/<prefix>` in\n * legacy mode. Uses the same resolver every other surface reads through,\n * honoring `ZIDANE_STORAGE_DIR` / `ZIDANE_PREFIX`.\n *\n * DEDICATED `daemon/` subdir (protocol v6): the state dir is shared with\n * `state.json` / logs, so the daemon can't chmod it 0700 without\n * affecting unrelated files. The server hardens this subdir instead;\n * client and server must agree on this path.\n */\n const dirs = resolveStorageDirs({\n ...(process.env.ZIDANE_PREFIX !== undefined ? { prefix: process.env.ZIDANE_PREFIX } : {}),\n })\n return join(dirs.stateDir, 'daemon', daemonSocketName())\n}\n\n/**\n * Pre-v6 socket location for the given (v6) socket path, or null when the\n * path isn't the default `<stateDir>/daemon/daemon.sock` layout (explicit\n * `ZIDANE_DAEMON_SOCKET` users never had a migration to run). A daemon\n * still serving the old path would be ORPHANED by the move — new clients\n * never probe it, and a service-style `--idle-exit 0` daemon would hold\n * agents and run-guard markers against the same sessions.db forever —\n * so daemon startup probes this path and drains any survivor.\n */\nexport function legacySocketPath(socketPath: string): string | null {\n const dir = dirname(socketPath)\n if (basename(socketPath) !== 'daemon.sock' || basename(dir) !== 'daemon')\n return null\n return join(dirname(dir), 'daemon.sock')\n}\n\n/**\n * Spawn command that re-enters the CURRENT zidane program as `… daemon`.\n *\n * Three launch shapes:\n * - compiled Bun binary — `Bun.main` is the virtual `/$bunfs/…` entry the\n * binary self-inserts as argv[1], so the spawn must NOT repeat it\n * (verified: repeating it makes the child parse the junk path as its\n * subcommand and boot the full TUI instead of the daemon).\n * - dev (`bun run cli.ts`) — the script path must ride along.\n * - Node hosts (no `Bun` global) — fall back to the published bin.\n */\nexport function selfDaemonSpawnCommand(): string[] {\n const bunMain = (globalThis as { Bun?: { main?: string } }).Bun?.main\n // Compiled binary: the virtual entry parses its own `daemon` subcommand.\n if (bunMain?.startsWith('/$bunfs'))\n return [process.execPath, 'daemon']\n // Dev-from-source: only re-execute `Bun.main` when it's actually a\n // zidane CLI entry (`cli.ts`/`cli.js`). For any other embedder (library\n // consumer, script) re-running their entry with a `daemon` argv would\n // launch an arbitrary program — fall back to the published bin instead.\n if (bunMain && /(?:^|[/\\\\])cli\\.[cm]?[jt]s$/.test(bunMain))\n return [process.execPath, bunMain, 'daemon']\n return ['zidane-daemon']\n}\n\n/**\n * True when something accepts connections on `socketPath`. Distinguishes a\n * live daemon from a stale socket file left by a crashed one.\n */\nexport function probeSocket(socketPath: string, timeoutMs = 1000): Promise<boolean> {\n return new Promise((resolve) => {\n /*\n * Skip the connect entirely unless the path is an actual socket file.\n * A stale REGULAR file (crashed daemon) or a missing path both mean\n * \"nothing listening\" — and connecting to them can surface a noisy\n * async ENOENT/ENOTSOCK that some runtimes treat as uncaught.\n */\n try {\n if (!existsSync(socketPath) || !statSync(socketPath).isSocket()) {\n resolve(false)\n return\n }\n }\n catch {\n resolve(false)\n return\n }\n\n let socket: ReturnType<typeof connect>\n try {\n socket = connect(socketPath)\n }\n catch {\n resolve(false)\n return\n }\n const done = (alive: boolean): void => {\n socket.destroy()\n resolve(alive)\n }\n socket.once('connect', () => done(true))\n socket.once('error', () => done(false))\n socket.setTimeout(timeoutMs, () => done(false))\n })\n}\n\nexport interface EnsureDaemonOptions {\n socketPath?: string\n /**\n * Command used to spawn the daemon when nothing is listening. Defaults to\n * `['zidane-daemon']` (the published bin). The child is detached and\n * unref'd — it outlives the spawning client by design.\n */\n spawnCommand?: string[]\n /** Total time to wait for the daemon to accept connections. */\n timeoutMs?: number\n}\n\n/**\n * Make sure a daemon is listening, spawning one if needed. Resolves with\n * the socket path once a connection succeeds; rejects when the daemon\n * failed to come up within `timeoutMs`.\n */\nconst pendingStarts = new Map<string, Promise<string>>()\n\nexport function ensureDaemonRunning(options: EnsureDaemonOptions = {}): Promise<string> {\n const socketPath = options.socketPath ?? defaultSocketPath()\n const pending = pendingStarts.get(socketPath)\n if (pending)\n return pending\n const start = startDaemon({ ...options, socketPath }).finally(() => pendingStarts.delete(socketPath))\n pendingStarts.set(socketPath, start)\n return start\n}\n\nasync function startDaemon(options: EnsureDaemonOptions & { socketPath: string }): Promise<string> {\n const socketPath = options.socketPath\n if (await probeSocket(socketPath))\n return socketPath\n\n const [cmd, ...args] = options.spawnCommand ?? ['zidane-daemon']\n const child = spawn(cmd!, args, {\n detached: true,\n stdio: 'ignore',\n env: { ...process.env, ZIDANE_DAEMON_SOCKET: socketPath },\n })\n /*\n * A missing binary (e.g. `zidane-daemon` not on PATH) emits an async\n * `error` event; without a listener Node rethrows it as an uncaught\n * exception and crashes the caller. Capture it and surface a clean\n * rejection through the poll loop below.\n */\n let spawnError: Error | undefined\n child.once('error', (err: Error) => {\n spawnError = err\n })\n child.unref()\n\n const deadline = Date.now() + (options.timeoutMs ?? 8000)\n for (;;) {\n if (spawnError !== undefined)\n throw new Error(`Failed to spawn zidane daemon (${cmd}): ${spawnError.message}`)\n if (await probeSocket(socketPath))\n return socketPath\n if (Date.now() > deadline)\n throw new Error(`zidane daemon did not come up on ${socketPath} within ${options.timeoutMs ?? 8000}ms.`)\n await new Promise(r => setTimeout(r, 150))\n }\n}\n","","/**\n * The version of the zidane code this process is running — `package.json`\n * inlined at build time (Bun `--compile`, tsdown for `dist/`, and Vite for\n * the GUI main all fold JSON imports into the bundle, so this never reads\n * the filesystem at runtime and cannot report a NEIGHBOUR package's version\n * the way a `require('../package.json')` from a bundled chunk can).\n *\n * Used by the daemon handshake: a client running newer code than the daemon\n * retires it, so an upgrade can never leave windows silently executing on a\n * process started from the previous release.\n */\nimport pkg from '../package.json' with { type: 'json' }\n\nexport const ZIDANE_VERSION: string = (pkg as { version?: string }).version ?? '0.0.0'\n\n/**\n * Compare two dotted versions (`7.0.19`, `7.1.0-beta.1`): negative when `a`\n * is older, positive when newer, 0 when equal. Pre-release tags are ignored\n * — same release train, same code as far as the daemon fence is concerned.\n * Unparseable input compares equal (never fences on garbage).\n */\nexport function compareVersions(a: string, b: string): number {\n const pa = parse(a)\n const pb = parse(b)\n if (!pa || !pb)\n return 0\n for (let i = 0; i < 3; i++) {\n const d = (pa[i] ?? 0) - (pb[i] ?? 0)\n if (d !== 0)\n return d\n }\n return 0\n}\n\nfunction parse(v: string): number[] | null {\n const m = /^v?(\\d+)\\.(\\d+)\\.(\\d+)/.exec(v.trim())\n return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null\n}\n","/**\n * zidane/ipc wire protocol — the transport-agnostic contract between a chat\n * host (the process that owns live `Agent` instances) and its clients (GUI\n * renderer, TUI window, `zidane attach`, …).\n *\n * The host-domain shapes (the `HostSignal` push union and everything it\n * carries) live in `src/chat/host/signals.ts` — the host must not depend on\n * `src/ipc/**`. This module re-exports them unchanged and adds the\n * transport-only contract: the typed JSON-RPC method map, session rows, and\n * the daemon handshake.\n *\n * Everything in this file is JSON-serializable: it must survive Electron's\n * structured clone AND a JSON-RPC socket hop unchanged. Canonical agent\n * types (`StreamEvent`, `InteractionRequest`, …) are re-used where they are\n * already wire-safe; host-only shapes (live `resolve` callbacks, `Map`s)\n * never appear here.\n *\n * Versioning: bump `IPC_PROTOCOL_VERSION` on any breaking change to the\n * signal union or the method map. The daemon handshake refuses mismatched\n * peers so a stale daemon never talks to an upgraded client (see\n * `daemon/lifecycle.ts`).\n */\nimport type { BrowserResponse } from '../chat/browser/protocol'\nimport type { CommandOutputBlock } from '../chat/commands'\nimport type { EnvironmentActionResult, EnvironmentActionSummary, EnvironmentRequest, EnvironmentTeardownResult, EnvironmentVerifyResult } from '../chat/environment'\nimport type { EnvironmentDescriptor, EnvironmentSettingsChange } from '../chat/environment-settings'\nimport type { CompactionReport } from '../chat/host/compaction'\nimport type { ContextSegmentsReport, WorkspaceListFilesOptions } from '../chat/host/engine'\nimport type { SessionLaunchOverrides } from '../chat/host/launch-overrides'\nimport type {\n CreateWorkerParams as OrchestrationCreateWorkerParams,\n WorkerRow as OrchestrationWorkerRow,\n WorkerSummary as OrchestrationWorkerSummary,\n} from '../chat/host/orchestration'\nimport type {\n CommandArgSuggestionSummary,\n CommandSummary,\n HostSettings,\n HostSignal,\n PendingInteraction,\n PromptAttachment,\n QueuedItem,\n RunningWorkItem,\n SendOptions,\n SessionPresence,\n TodosSnapshot,\n WireApprovalRequest,\n} from '../chat/host/signals'\nimport type {\n ApprovalDecision,\n ContextBreakdown,\n InteractionResponse,\n ProviderKey,\n SearchTurnResult,\n SessionEnvironmentSummary,\n SessionHeader,\n SessionHistoryMatch,\n SessionMeta,\n StreamEvent,\n SystemMdFile,\n TodoItem,\n} from '../chat/index'\nimport type { MachineInfo, MachineLinksStatus, MachineRegisterParams } from '../chat/machine-protocol'\nimport type { SyncCategory, SyncClaimResult, SyncPayload, SyncPushResult, SyncStatus } from '../chat/sync/types'\nimport type { TerminalAttachResult, TerminalInfo, TerminalOpenInput, TerminalSessionState } from '../chat/terminal/protocol'\nimport type { ExecResult, ListFilesEntry } from '../contexts/types'\nimport type { SessionArtifact } from '../session/artifacts'\nimport type { SessionData } from '../session/index'\nimport type { JsonValue, McpServerConfig, SessionTurn, ThinkingLevel } from '../types'\nimport { isMethodNotFound } from '../chat/hosts/connection'\n\nexport type {\n ApprovalOriginator,\n CommandArgSuggestionSummary,\n CommandSummary,\n HostSettings,\n HostSignal,\n PendingInteraction,\n PromptAttachment,\n QueuedItem,\n RunningWorkItem,\n SendOptions,\n SerializedPreview,\n SessionPresence,\n TodosSnapshot,\n WireApprovalRequest,\n} from '../chat/host/signals'\n\n/** The machine protocol (`docs/MACHINES.md`), versioned on its own (`MACHINE_PROTOCOL_VERSION`). */\nexport {\n isValidMachineName,\n MACHINE_HOST_METHODS,\n MACHINE_IDEMPOTENT_METHODS,\n MACHINE_PROTOCOL_VERSION,\n MachineErrorCode,\n machineKind,\n parseMachineKind,\n} from '../chat/machine-protocol'\nexport type {\n MachineCapabilities,\n MachineHandleRef,\n MachineInfo,\n MachineMethodName,\n MachineMethods,\n MachineNotifications,\n MachineParams,\n MachineRegisterParams,\n MachineRegisterResult,\n MachineResult,\n MachineRoot,\n MachineStatusChange,\n} from '../chat/machine-protocol'\n\n/**\n * v6 (changes since v5):\n * - `event` signals carry an optional `echo` flag marking host-generated\n * SEND/STEER echoes of the user's own message.\n * - `chat.pushQueued` result gained the `'queued'` delivered variant.\n * - `sessions.setModel` now honors `fallbacks`: it persists the canonical\n * `metadata.modelChain` and CLEARS a previously persisted chain when\n * omitted/empty. It also accepts `effort` / `modelOptions` and resets\n * both when omitted (a pick is atomic — no stale per-model knobs).\n * - additive: `extension.emit` notification + `extension:signal` fan-out\n * (the permission-gated per-extension cross-window bus, `ctx.bus`).\n * Older daemons ignore the unknown notification; older clients drop the\n * unknown signal kind — no version bump needed.\n * - additive: `extension.emit` / `extension:signal` carry an optional\n * `nonce` (the emitter's per-process random id) so receivers dedupe on\n * `(extensionId, nonce, seq)` instead of the collision-prone\n * `(extensionId, seq)`. Older peers omit it and fall back to the\n * seq-only key — no version bump needed.\n * - `SessionRow.modelFallbacks` is now populated from the session's\n * persisted `metadata.modelChain`.\n * - Default socket path moved from `<stateDir>/daemon.sock` to the\n * dedicated `<stateDir>/daemon/daemon.sock` (dir chmod'd 0700) so the\n * daemon can harden its socket dir without touching shared state files.\n * - ADDITIVE (no version bump — older daemons answer \"method not\n * found\", clients degrade to local compute): `suggest.resolve` RPC\n * resolves inline ghost-text autocomplete daemon-side, and the\n * `suggest:changed` signal fans the result out to every OTHER peer\n * on the session so mirroring windows paint the same ghost without\n * recomputing.\n * - ADDITIVE (no version bump — optional field, older daemons simply\n * omit it and clients fall back to the single `suggestion`):\n * `suggest.resolve` results and `suggest:changed` signals carry the\n * resolver's full ordered `candidates` list so daemon mode keeps\n * ↑/↓ candidate rotation instead of degrading to one suggestion.\n * - ADDITIVE (no version bump — `optional()` swallows \"method not\n * found\" on an older daemon, which then simply keeps its stale\n * registries as before): `runtime.reload` RPC drops the daemon's\n * cached extension registries and retires live agents after a window\n * reloaded its extensions.\n * - ADDITIVE (no version bump): `terminal.registerViewer` /\n * `terminal.unregisterViewer`. The desktop app registers as a client that\n * can show terminals; agents only get terminal tools while one is\n * attached. An older daemon answers \"method not found\" (and keeps giving\n * every agent the tools, as before); an older desktop app on a newer\n * daemon never registers, so its agents run without terminal tools.\n * - ADDITIVE (no version bump): `queue.attachments` returns a queued\n * entry's attachments with their bytes, and `queue.update` accepts\n * `attachments` to replace them. An older daemon answers \"method not\n * found\" / ignores the field: the entry's attachments stay as queued.\n * - ADDITIVE (no version bump): `chat.steer` / `chat.followUp` resolve to\n * whether the message reached a live run. Older daemons resolve `null`,\n * which clients treat as delivered (the pre-existing behavior).\n * - ADDITIVE (no version bump): `sessions.fork`, `sessions.deleteTurn`,\n * `sessions.editTurnText`, `sessions.setFolder`, `sessions.appendTurns`.\n * History and folder edits run in the host instead of being written to\n * the store by the client (then `sessions.touch` + `chat.rebuildAgent`).\n * Older clients keep the old path, which still works on a shared disk.\n * A newer client only meets an older daemon while it retires (the\n * release fence drains it otherwise), and then gets \"method not found\".\n * - ADDITIVE (no version bump): `sessions.listMeta`, `sessions.getMeta`,\n * `sessions.get`, `sessions.setExtensionState` serve a client the\n * session data it used to read and write in its own store, so a window\n * on another machine sees the host's sessions. `sessions.create` accepts `id`, `effort`, `modelOptions` and\n * `pinnedSkills`; `todos.set` accepts `persistIdle`. An older host answers\n * \"method not found\" / ignores the fields: a window falls back to the\n * store it shares with a local daemon, and refuses a remote host.\n */\nexport const IPC_PROTOCOL_VERSION = 13\n\n/**\n * JSON-RPC error codes specific to the zidane daemon. Lives here (not in\n * `daemon/server.ts`) so clients can import the codes without pulling the\n * server's module graph.\n */\nexport const IpcErrorCode = {\n VersionMismatch: -32010,\n NotHandshaken: -32011,\n /** A network transport's per-connection request budget is spent; retry later. */\n RateLimited: -32012,\n /**\n * The reply would exceed the transport's message size: nothing was sent\n * but this error (the connection stays). Ask for less (a transcript: a\n * smaller page, see {@link loadAllEvents}).\n */\n ResponseTooLarge: -32013,\n /**\n * The handler threw: the host refused or failed the call (`message` says\n * why). Hosts before it answered -32000, which ACP uses for\n * `AuthenticationRequired`; clients treat both as a plain remote error.\n */\n HandlerFailed: -32014,\n} as const\n\n/**\n * Client heartbeat request (`{}` → `{}`), outside the method table: every\n * host answers it, before the handshake too. A host predating it answers\n * \"method not found\", which still proves it alive.\n */\nexport const PING_METHOD = '$/ping'\n\n/**\n * Session-scoped signals fanned out to every peer carry their number in\n * their session as this extra field on the `ipc.signal` params (clients\n * predating it ignore it; `IpcClient` strips it and hands it to listeners as\n * {@link SignalMeta}). Per session, from 1, gap-free within one host process.\n */\nexport const SIGNAL_SEQ_FIELD = '$seq'\n\n/** What a signal listener gets beside the signal: its number in its session, when it has one. */\nexport interface SignalMeta {\n seq: number\n}\n\nexport interface SequencedSignal {\n seq: number\n signal: HostSignal\n}\n\nexport type SessionResumeResult\n = | { ok: true, signals: SequencedSignal[] }\n /** `epoch`: another host process numbered them. `gap`: the log no longer covers the position. */\n | { ok: false, reason: 'epoch' | 'gap' }\n\n/* -------------------------------------------------------------------------\n * Request/response methods (client → host)\n * ---------------------------------------------------------------------- */\n\n/**\n * Typed method map for the daemon transport. Keys are JSON-RPC method\n * names; each entry pins params/result so both the daemon dispatch table\n * and the client proxy are checked against the same contract.\n *\n * Scope: the chat core every client needs. Host-UI-specific surfaces\n * (folder pickers, themes, keybindings) intentionally stay client-local.\n */\nexport interface IpcMethods {\n /** `wake` is host-internal (see `SendOptions.wake`) — not accepted over the wire. */\n 'chat.send': { params: Omit<SendOptions, 'wake'>, result: { runId: string } }\n 'chat.interrupt': { params: { sessionId: string }, result: void }\n /** `true` when the message reached a live run; `false` when nothing was running (it was not delivered). */\n 'chat.steer': { params: { sessionId: string, message: string }, result: boolean }\n 'chat.followUp': { params: { sessionId: string, message: string }, result: boolean }\n 'chat.pushQueued': {\n params: { sessionId: string, message: string, activatedSkills?: string[], keepDraft?: boolean }\n result: { delivered: 'steer' | 'send' | 'command' | 'queued' }\n }\n 'chat.isRunning': { params: { sessionId: string }, result: boolean }\n /**\n * Retire the session's live agent so the next run rebuilds against\n * fresh config/credentials (MCP login, extension reload). Run-end\n * deferred when a run is in flight; HITL/queue state survives.\n */\n 'chat.rebuildAgent': { params: { sessionId: string }, result: void }\n /**\n * `zidane run --system / --mcp` for a host-backed window: launch overrides\n * for the session's agent (`ChatHost.setLaunchOverrides`), owned by the\n * calling client and dropped when it disconnects. A call with neither field clears them.\n */\n 'sessions.setLaunchOverrides': { params: { sessionId: string } & SessionLaunchOverrides, result: void }\n /**\n * Drop the daemon's cached runtime configs (extension registries, per\n * cwd) and retire every live agent so the next command or run rebuilds\n * against what is on disk now. Sent by a window after it reloaded its\n * own extensions (install, update, remove, `/reload`): extension `/`\n * commands execute daemon-side, so without this the daemon keeps\n * running the code it loaded at boot. Busy sessions rebuild at run end.\n */\n 'runtime.reload': { params: Record<string, never>, result: void }\n 'chat.listWork': { params: { sessionId: string }, result: RunningWorkItem[] }\n 'chat.cancelWork': { params: { sessionId: string, id: string | 'all', reason?: string }, result: boolean }\n\n 'sessions.list': { params: { projectRoot?: string | null, archive?: 'active' | 'archived' | 'all' }, result: SessionRow[] }\n /**\n * The session list as a window renders it (`SessionMeta`: title, turn /\n * message / run counts, project, cwd, environment, artifact count, the\n * orchestration main flag), newest first. `projectRoot`: omitted = every\n * project, `null` = untagged sessions.\n */\n 'sessions.listMeta': { params: { projectRoot?: string | null }, result: SessionMeta[] }\n /** One `SessionMeta` by id (rows a filtered list can't return, e.g. the main); `null` when unknown. */\n 'sessions.getMeta': { params: { sessionId: string }, result: SessionMeta | null }\n /**\n * The whole session document as the host holds it: the live copy when an\n * agent is live (turns persisted mid-run, todos kept in memory), else the\n * stored one, a stale `running` marker demoted. `null` when unknown.\n */\n 'sessions.get': { params: { sessionId: string, turns?: boolean }, result: SessionDocumentHead | null }\n /**\n * A slice of a session's turns, `[from, from + limit)` (default from 0,\n * {@link SESSION_TURNS_PAGE} turns, at most {@link SESSION_TURNS_MAX_PAGE}),\n * from the same copy `sessions.get` reads, and how many turns it has: a\n * client reads a long session's document a page at a time\n * ({@link loadSessionDocument}) instead of in one reply. With\n * `sessions.get` `turns: false` (the document without its turns), what an\n * export needs. Pages and that head come from one snapshot of the\n * document per content version (read once, not per page), and name it\n * (`version`): a client that sees it change mid-load starts over rather\n * than mix two versions ({@link loadSessionDocument}). `null` when\n * unknown. Additive: an older host answers \"method not found\", ignores\n * `turns: false`, and names no version.\n */\n 'sessions.getTurns': { params: { sessionId: string, from?: number, limit?: number }, result: { turns: SessionTurn[], total: number, version?: string } | null }\n /**\n * The full text of one tool result (`callId`; `turnId`, when known, the\n * turn that holds it): what a clipped tool row shows on expand, without\n * the session crossing the wire. `null` when no such result. Additive.\n */\n 'sessions.getToolResult': { params: { sessionId: string, callId: string, turnId?: string }, result: string | null }\n /**\n * One session's header: its list row plus metadata, profile and status,\n * without turns or runs (the live copy when an agent holds it). What a\n * window re-reads on `sessions:changed`. Additive. `usage: true` adds the\n * footer's numbers, computed host-side from the turns and runs\n * (`contextTokens`, `costUsd`): a client needs no document for its context\n * gauge or cost pill. Older hosts ignore it.\n */\n 'sessions.getHeader': { params: { sessionId: string, usage?: boolean }, result: SessionHeader | null }\n /**\n * One key of an extension's per-session state (`metadata.extensions`, the\n * bag `ctx.session` and renderer `useSessionState` share), written by the\n * host into its copy of the session. `value` omitted deletes the key.\n */\n 'sessions.setExtensionState': { params: { sessionId: string, extension: string, key: string, value?: JsonValue }, result: void }\n 'sessions.create': { params: CreateSessionParams, result: SessionRow }\n /** Resolves with what happened to the session's environment (a provider may keep it). */\n 'sessions.delete': { params: { sessionId: string }, result: { environment?: EnvironmentTeardownResult } }\n /** Provision a failed (or restart-stranded) environment again. */\n 'sessions.retryEnvironment': { params: { sessionId: string }, result: void }\n /** The per-session commands the session's environment offers right now (push, open PR, …). */\n 'sessions.environmentActions': { params: { sessionId: string }, result: EnvironmentActionSummary[] }\n /** Run one of them in the session's environment (resumed when suspended). */\n 'sessions.runEnvironmentAction': { params: { sessionId: string, actionId: string }, result: EnvironmentActionResult }\n /**\n * The session's workspace (`ChatHost.workspace*`): its execution context,\n * rooted inside the environment when the files live there, else at the\n * session's cwd. Paths and exec `cwd` resolve against the root as the\n * execution context resolves them; containment is the context's own.\n * `cwd` / `env` on exec and the list / size methods are additive: an\n * older daemon ignores the former and answers \"method not found\" to the\n * latter (active clients are build-fenced, so this is a transient case).\n */\n 'sessions.workspaceExec': { params: { sessionId: string, command: string, cwd?: string, env?: Record<string, string>, timeoutSeconds?: number }, result: ExecResult }\n /**\n * The same command, streamed (`!` on a remote host): the reply names the\n * exec, its output follows as `workspace:exec:data` signals and ends with\n * one `workspace:exec:exit`, all to this connection only (signals may\n * precede the reply). Bounded per connection (concurrent commands, chunk\n * size, total output: past it the process is stopped and the exit says\n * `truncated`). A dropped connection kills what it started. Additive: an\n * older host answers \"method not found\" and clients use `workspaceExec`.\n */\n 'sessions.workspaceExecStream': { params: { sessionId: string, command: string, cwd?: string }, result: { execId: string } }\n /** Kill a streamed command's process group (this connection's only; `cancelled: false` otherwise or when it already ended). */\n 'sessions.workspaceExecCancel': { params: { execId: string }, result: { cancelled: boolean } }\n 'sessions.workspaceReadFile': { params: { sessionId: string, path: string }, result: string }\n 'sessions.workspaceWriteFile': { params: { sessionId: string, path: string, content: string }, result: void }\n 'sessions.workspaceListFiles': { params: { sessionId: string, path: string, options?: WorkspaceListFilesOptions }, result: ListFilesEntry[] }\n 'sessions.workspaceFileSize': { params: { sessionId: string, path: string }, result: number | null }\n /**\n * Every environment kind the host can create, described for a new session\n * in `cwd` (availability, default, branch suggestion, options — secrets\n * only as \"configured\"). What pickers and the Environments settings render.\n * `kind`: a machine kind (`local@laptop`) says `cwd` is that machine's\n * folder, checked against its roots instead of this host's\n * (`docs/MACHINES.md` § Folders); the same on `commands.*`, `catalog.*`\n * and `models.list`. Additive.\n */\n 'environments.list': { params: { cwd?: string, kind?: string }, result: EnvironmentDescriptor[] }\n /**\n * Apply one Environments-settings edit (enable, default, options,\n * secrets), validated against the kind's schema. Settings changes fan out\n * as `settings:changed`; secrets are stored host-side and never returned.\n */\n 'environments.update': { params: EnvironmentSettingsChange, result: void }\n /** \"Test connection\" for a kind with its current options. */\n 'environments.verify': { params: { kind: string }, result: EnvironmentVerifyResult }\n 'sessions.setTitle': { params: { sessionId: string, title: string }, result: void }\n /**\n * Title the session ON the host: its providers and credentials (a server\n * session's transcript never goes to the window's provider), the same\n * generator (`generateSessionTitle`), written as `sessions.setTitle` does.\n * `providerKey` / `model`: the window's pick, used when the host has that\n * provider; otherwise the session's own provider and model. The Main\n * session is refused (it keeps its name). Additive: an older host answers\n * \"method not found\".\n */\n 'sessions.generateTitle': { params: { sessionId: string, providerKey?: string, model?: string }, result: { title: string } }\n 'sessions.setArchived': { params: { sessionId: string, archived: boolean }, result: void }\n 'sessions.setAgentId': { params: { sessionId: string, agentId: string }, result: void }\n 'sessions.setEffort': { params: { sessionId: string, effort: ThinkingLevel }, result: void }\n /**\n * The one model-swap contract (`ChatHost.setSessionModel`). A pick is a\n * whole: `fallbacks` (ordered, primary excluded) REPLACES the persisted\n * `metadata.modelChain` (omitted/empty clears it); `effort` and\n * `modelOptions` are reset to the supplied values (omitted clears them —\n * per-model knobs never leak onto the new model). The live agent is\n * retired so the next run rebuilds on the new pick (run-end deferred\n * while a run is in flight).\n */\n 'sessions.setModel': {\n params: {\n sessionId: string\n providerKey: ProviderKey\n modelId: string\n fallbacks?: ModelFallbackRef[]\n effort?: ThinkingLevel\n modelOptions?: Record<string, boolean>\n }\n result: void\n }\n 'sessions.setModelOptions': { params: { sessionId: string, options: Record<string, boolean> }, result: void }\n /**\n * The session's transcript as canonical events. Without `before` / `limit`:\n * every turn, as a plain array (the shape every client predating paging\n * reads). With either: one page, `{ events, cursor? }`, the last `limit`\n * turns (default {@link LOAD_EVENTS_PAGE_TURNS}, at most\n * {@link LOAD_EVENTS_MAX_PAGE_TURNS}) before turn position `before`\n * (default: the end), its start moved back to an exchange boundary when one\n * is near so a tool call is never cut from its result. `cursor`: the\n * `before` of the previous page, absent at the first turn. Typed here as\n * the unpaged call every client makes; a paged call goes through\n * {@link loadEventsPage}. Paging is additive: an older host ignores the\n * fields and answers the whole array.\n */\n 'sessions.loadEvents': { params: { sessionId: string }, result: StreamEvent[] }\n /**\n * Reattach without a reload: the session's signals numbered after\n * `afterSeq` (see {@link SIGNAL_SEQ_FIELD}), in order, as long as this host\n * process (`epoch`, from `HelloResult.signalEpoch`) still holds them all.\n * Otherwise refused, and the client reloads with `sessions.loadEvents`.\n * Additive: an older host answers \"method not found\", same fallback.\n */\n 'sessions.resume': { params: { sessionId: string, epoch: string, afterSeq: number }, result: SessionResumeResult }\n 'sessions.getTurn': { params: { sessionId: string, turnId: string }, result: SessionTurn | null }\n 'sessions.contextBreakdown': { params: { sessionId: string }, result: ContextBreakdown | null }\n /**\n * Artifacts one session recorded (PRs, branches, commits, files,\n * extension kinds — see `session/artifacts.ts`), newest first. Empty on\n * stores without artifact support. Additive; pre-artifact daemons\n * reject the method and clients treat that as empty.\n */\n 'sessions.artifacts': { params: { sessionId: string, kind?: string, limit?: number }, result: SessionArtifact[] }\n /**\n * Artifacts across sessions, filtered by project root (`null` = untagged\n * sessions, omitted = every project) and/or kind/uri (reverse lookup).\n */\n 'artifacts.list': { params: { projectRoot?: string | null, kind?: string, uri?: string, since?: number, limit?: number }, result: SessionArtifact[] }\n /** Remove one artifact. `false` when the store has no artifact support. Fans out `artifact:changed`. */\n 'artifacts.delete': { params: { sessionId: string, artifactId: string }, result: boolean }\n /**\n * Upsert an artifact — the lazy `resolve()` write-back (refreshed\n * `label` / `meta`). Same merge semantics as `SessionStore.upsertArtifact`;\n * `null` when the session is unknown or the store lacks support.\n */\n 'artifacts.upsert': { params: { artifact: SessionArtifact }, result: SessionArtifact | null }\n /**\n * Transcript search over ONE session, daemon-side. The daemon owns the\n * authoritative turns (live wrapper when an agent is active — fresh\n * mid-run, which a window's load-time snapshot is not) and an LRU index\n * cache shared by every window, so repeat queries pay match cost only.\n * Results come back in TURN ORDER (search is a transcript filter).\n */\n 'history.searchSession': {\n params: { sessionId: string, query: string, limit?: number }\n result: SearchTurnResult[]\n }\n /**\n * Cross-session content search, daemon-side. One RPC replaces a\n * window's per-session index/build/search round-trips — indexes are\n * built once in the daemon and shared by every window.\n */\n 'history.searchAll': {\n params: { query: string, sessionIds: string[], excerptLimit?: number }\n result: Record<string, SessionHistoryMatch>\n }\n /**\n * A window appended transcript content OUT-OF-BAND (local `/` command\n * output, `!` shell turns — written straight to the shared store, not\n * through a host run). The daemon fans out `sessions:changed` so every\n * window (issuer included) re-converges on the canonical replay NOW\n * instead of at the next run end. Sent as a notification.\n */\n 'sessions.touch': { params: { sessionId: string }, result: void }\n /** Fork at `turnId` into a new session (`ChatHost.forkSession`); announced as a `sessions:changed` create. */\n 'sessions.fork': { params: { sessionId: string, turnId: string, title?: string }, result: { id: string } }\n /** History edits (`ChatHost.deleteTurn` / `editTurnText`): refused while the session runs. */\n 'sessions.deleteTurn': { params: { sessionId: string, turnId: string }, result: void }\n 'sessions.editTurnText': { params: { sessionId: string, turnId: string, text: string }, result: void }\n /** Bind to a folder, or back to a plain chat with `cwd: ''` (`ChatHost.setSessionFolder`). */\n 'sessions.setFolder': { params: { sessionId: string, cwd: string }, result: void }\n /** Turns written outside a run, e.g. `!` shell output (`ChatHost.appendTurns`). */\n 'sessions.appendTurns': { params: { sessionId: string, turns: SessionTurn[] }, result: void }\n /**\n * `ctx.appendNote` outside a run: a display-only note, rendered live and\n * persisted (`ChatHost.appendNote`). False for an unknown session or no blocks.\n */\n 'sessions.appendNote': { params: { sessionId: string, blocks: CommandOutputBlock[] }, result: boolean }\n /** Compact now (`ChatHost.compactSessionNow`): what was done, `null` when nothing was. Older daemons resolve `null`. */\n 'sessions.compact': { params: { sessionId: string }, result: CompactionReport | null }\n\n 'todos.get': { params: { sessionId: string }, result: TodosSnapshot | null }\n /**\n * Apply a user todo edit (add / edit / remove / cycle / clear) to the\n * session the MODEL reads.\n *\n * Required because todos live in `session.metadata` and `todowrite` reads\n * them off the daemon agent's in-memory `Session`. A window writing its own\n * `Session` instance persisted an edit that the daemon never observed, so the\n * model's next `todowrite` silently overwrote it.\n *\n * Sends the whole list rather than a delta: the mutators in\n * `chat/todo-edits.ts` are already whole-list transforms, and a delta would\n * need conflict rules against a list the model rewrites concurrently.\n *\n * `null` = no live agent (or no run owns a todo slot), and the caller should\n * apply its own store-level write — race-free, since nothing is appending.\n */\n /**\n * `persistIdle`: with no live agent, the host applies the edit to the stored\n * session itself (the run the list belongs to must exist) instead of\n * answering `null`. Older hosts ignore it.\n */\n 'todos.set': { params: { sessionId: string, items: readonly TodoItem[], persistIdle?: boolean }, result: TodosSnapshot | null }\n\n /*\n * Orchestration — a pinned \"main\" session that drives other sessions\n * (\"workers\"). Feature-gated by `Settings.orchestration`; every method below\n * resolves to `null` / rejects when it is off — the main SURVIVES the toggle\n * as a persisted session, so the gate has to live on the verbs, not just on\n * discovery.\n *\n * `mainId` is load-bearing, not decorative: the host refuses any verb whose\n * `mainId` is not itself a main session. Targets are NOT limited to the\n * workers that main created — the main observes and drives the whole store —\n * but it may never target itself or another main (the depth cap).\n */\n /** The main session id, creating it (directory-less) when the setting is on and none exists. */\n 'orchestration.main': { params: Record<string, never>, result: string | null }\n 'orchestration.createWorker': { params: { mainId: string } & OrchestrationCreateWorkerParams, result: string }\n 'orchestration.list': { params: { mainId: string, limit?: number }, result: OrchestrationWorkerRow[] }\n 'orchestration.read': { params: { mainId: string, sessionId: string }, result: OrchestrationWorkerSummary | null }\n /** `wake` (default true): whether that run finishing wakes the main. */\n 'orchestration.send': { params: { mainId: string, sessionId: string, prompt: string, wake?: boolean }, result: void }\n 'orchestration.steer': { params: { mainId: string, sessionId: string, message: string }, result: void }\n 'orchestration.cancel': { params: { mainId: string, sessionId: string }, result: void }\n 'orchestration.transcript': { params: { mainId: string, sessionId: string, limit?: number }, result: string }\n\n /** Extension-contributed `/` commands discovered for `cwd`. */\n 'commands.list': { params: { cwd: string, kind?: string }, result: CommandSummary[] }\n /** Argument suggestions for `/name <prefix>` — best-effort, empty on failure. */\n 'commands.completeArgs': { params: { cwd: string, name: string, argsPrefix: string, kind?: string }, result: CommandArgSuggestionSummary[] }\n\n 'interactions.list': { params: { sessionId?: string }, result: PendingInteraction[] }\n 'interactions.respond': { params: { requestId: string, response: InteractionResponse }, result: { ok: boolean } }\n 'interactions.cancel': { params: { requestId: string, reason?: string }, result: { ok: boolean } }\n 'interactions.rehydrate': { params: { sessionId: string }, result: PendingInteraction[] }\n /**\n * Dev browser: a window offers to host the pages the agent's `browser_*`\n * tools drive (the GUI's main process). Released when the connection\n * drops. It then answers each `browser:request` signal addressed to it.\n */\n 'browser.registerHost': { params: { hostId: string }, result: { ok: boolean } }\n 'browser.unregisterHost': { params: { hostId: string }, result: { ok: boolean } }\n 'browser.respond': { params: { requestId: string, response: BrowserResponse }, result: { ok: boolean } }\n /**\n * Terminals, run by the host in the session's environment. `clientId`\n * names one view (a window's drawer or panel); views attached through a\n * connection are detached when it drops. Output arrives as\n * `terminal:output` signals; `ack` what was written to keep it flowing.\n */\n 'terminal.state': { params: { sessionId: string }, result: TerminalSessionState }\n 'terminal.open': { params: TerminalOpenInput, result: TerminalInfo }\n 'terminal.attach': { params: { terminalId: string, clientId: string }, result: TerminalAttachResult }\n 'terminal.detach': { params: { terminalId: string, clientId: string }, result: void }\n /** `clientId` + `response`: bytes the view's emulator generated (DSR/DA replies), dropped unless that view owns the size. */\n 'terminal.write': { params: { terminalId: string, data: string, clientId?: string, response?: boolean }, result: void }\n 'terminal.resize': { params: { terminalId: string, clientId: string, cols: number, rows: number, claim?: boolean }, result: void }\n 'terminal.ack': { params: { terminalId: string, clientId: string, offset: number }, result: void }\n 'terminal.restart': { params: { terminalId: string }, result: TerminalInfo }\n 'terminal.close': { params: { terminalId: string }, result: void }\n 'terminal.setHidden': { params: { terminalId: string, hidden: boolean }, result: void }\n /**\n * This connection can show terminals (the desktop app). While at least one\n * viewer is attached, agents get the terminal tools; the registration is\n * dropped with the connection.\n */\n 'terminal.registerViewer': { params: { viewerId: string }, result: { ok: boolean } }\n 'terminal.unregisterViewer': { params: { viewerId: string }, result: { ok: boolean } }\n\n 'approvals.resolve': { params: { requestId: string, decision: ApprovalDecision }, result: void }\n 'approvals.denyAll': { params: { sessionId?: string }, result: void }\n 'approvals.listPending': { params: Record<string, never>, result: WireApprovalRequest[] }\n\n /**\n * Type-ahead queue, host-owned so every window sees and can manipulate\n * the same list. `queue.add` queues when a run is in flight and sends\n * immediately otherwise; the host auto-drains the queue FIFO at run end.\n */\n 'queue.list': { params: { sessionId: string }, result: QueuedItem[] }\n\n /**\n * Which `SYSTEM.md` override composes this session's prompt, for windows\n * attaching to an already-warm agent.\n *\n * The `system-md` signal fires once per agent BUILD and the daemon caches\n * agents, so the normal multi-window case (daemon already running, open a\n * second terminal or the GUI) would otherwise never learn that the built-in\n * safety and git doctrine has been replaced. `null` = no live agent yet, in\n * which case the next build broadcasts it.\n */\n 'sessions.systemMd': {\n params: { sessionId: string }\n result: { file: SystemMdFile | null, shadowed: readonly SystemMdFile[] } | null\n }\n /**\n * Every chunk of the session's system prompt with provenance — the\n * Instructions tab. Built from the live agent's assembly, so it reflects\n * MCP instructions, extension fragments and the resolved `SYSTEM.md`.\n */\n 'sessions.contextSegments': { params: { sessionId: string }, result: ContextSegmentsReport | null }\n /** Seed a user-scope `SYSTEM.md` from the session's doctrine; throws when an override could not apply. */\n 'sessions.createSystemOverride': { params: { sessionId: string }, result: { path: string, created: boolean } }\n 'queue.add': {\n /**\n * `asCommand`: see `SendOptions.asCommand` — the host refuses when it cannot resolve it.\n * `keepDraft`: see `SendOptions.keepDraft` — a prompt from outside the composer.\n */\n params: { sessionId: string, text: string, activatedSkills?: string[], attachments?: PromptAttachment[], asCommand?: string, keepDraft?: boolean }\n result: { delivered: 'queued' | 'sent' | 'steer' }\n }\n 'queue.remove': { params: { sessionId: string, id: string }, result: boolean }\n /**\n * Edit a queued entry in place; order is kept. `attachments` replaces the\n * entry's list when given. `false` when already sent / dropped.\n */\n 'queue.update': { params: { sessionId: string, id: string, text: string, attachments?: PromptAttachment[] }, result: boolean }\n /** A queued entry's attachments with their bytes; `null` when already sent / dropped. */\n 'queue.attachments': { params: { sessionId: string, id: string }, result: PromptAttachment[] | null }\n /** Steer a queued entry into the live run now (falls back to send when idle). */\n 'queue.pushNow': { params: { sessionId: string, id: string }, result: { delivered: 'steer' | 'send' | 'queued' | 'missing' } }\n\n /** Current shared draft for a session — backfill on window attach. */\n 'drafts.get': { params: { sessionId: string }, result: { text: string, shell?: boolean, attachments?: PromptAttachment[], search?: { active: boolean, query: string } } }\n /**\n * Replace the session's shared draft. Fans out `draft:changed` to every\n * OTHER peer. Ephemeral daemon state — drafts don't survive a daemon\n * restart and are cleared when any window submits the prompt.\n */\n /**\n * `shell` carries the prompt's shell mode OUT OF BAND — never encoded\n * into the text, so a literal leading `!` in a normal draft can't flip\n * other windows into shell-execution semantics.\n */\n 'drafts.set': { params: { sessionId: string, text: string, shell?: boolean }, result: void }\n /** Replace the shared draft's composing attachments (notification). */\n 'drafts.setAttachments': { params: { sessionId: string, attachments: PromptAttachment[] }, result: void }\n /** Replace the shared transcript-search state (notification, per keystroke). */\n 'search.set': { params: { sessionId: string, active: boolean, query: string }, result: void }\n /**\n * Extension bus emit from a wire client whose extensions run CLIENT-side\n * (TUI daemon mode — the extension has no host to broadcast through).\n * Sent as a notification. The daemon validates the extension id against\n * the session cwd's registry (boot registry when no `sessionId`) and the\n * `'ipc'` permission, re-validates the 64 KiB payload cap, delivers to\n * its own subscribers, and fans out `extension:signal` to every OTHER\n * peer (origin excluded — the emitter already delivered locally).\n */\n 'extension.emit': { params: { extensionId: string, sessionId?: string, payload: JsonValue, seq: number, nonce?: string }, result: void }\n /**\n * Resolve inline ghost-text autocomplete daemon-side (the typing\n * window's request IS the single computation): canonical resolver\n * against the session cwd's extension registry. Latest-wins per\n * session — a `seq` older than the newest seen returns\n * `{ suggestion: null }` without computing, and a newer request\n * aborts an in-flight compute. The result additionally fans out as\n * `suggest:changed` to every OTHER peer.\n */\n 'suggest.resolve': { params: { sessionId: string, text: string, caret: number, seq: number }, result: { suggestion: string | null, seq: number, candidates?: string[] } }\n\n 'settings.get': { params: Record<string, never>, result: HostSettings }\n 'settings.set': { params: { patch: Partial<HostSettings> }, result: HostSettings }\n\n /** Current presence snapshot — backfill for a freshly opened session list. */\n 'presence.list': { params: Record<string, never>, result: SessionPresence[] }\n /**\n * Tag the calling peer as watching a session (one per connection; the\n * TUI opens one connection per activated session). Sent as a\n * notification right after the handshake. Detach is implicit — the\n * daemon recomputes presence when the socket drops.\n */\n 'presence.watch': { params: { sessionId: string }, result: void }\n\n /**\n * Where this host lets a session's folder be: a server's workspace roots\n * (`confined`: `sessions.create` / `setFolder` refuse anything outside),\n * or the user's home on a local host (unconfined). Additive.\n */\n 'fs.roots': { params: Record<string, never>, result: FsRoots }\n /**\n * The folders in `path` (default: the first root), for a folder picker on\n * the host's machine. Only inside the roots (real paths: `..` and\n * symlinks out are refused), no dotfiles. Additive.\n */\n 'fs.listDirs': { params: { path?: string }, result: FsDirListing }\n\n /**\n * The host's provider credentials, as the host's agents use them (its\n * data dir's `credentials.json` and environment): per provider, whether\n * something is configured, its stored API key / OAuth accounts (labels,\n * which is active) and an env var it reads. Never a secret. Additive.\n */\n 'auth.status': { params: Record<string, never>, result: { providers: HostProviderAuth[] } }\n /**\n * Store an API key for one of the host's providers as its active\n * credential, apply it to the host's environment, and rebuild agents\n * (idle now, busy ones at run end). Returns the provider's new status.\n * OAuth sign-in goes through `auth.oauth.*`. Additive.\n */\n 'auth.setApiKey': { params: { provider: string, key: string }, result: HostProviderAuth }\n /**\n * Remove one stored credential (`account`: its key from `auth.status`) or,\n * without one, every stored credential of the provider; then as\n * `auth.setApiKey`. A key the host only has from its own environment is\n * left alone. Additive.\n */\n 'auth.remove': { params: { provider: string, account?: string }, result: { removed: boolean, provider: HostProviderAuth } }\n /**\n * OAuth sign-in with the browser on the CLIENT and the tokens on the host:\n * the host starts a provider's login (`provider`) or an MCP server's\n * (`mcpServer`, found in `cwd`'s catalog, as `catalog.mcps`), keeping the\n * PKCE verifier and `state`, and answers with the authorization URL.\n * `mode: 'loopback'`: the client listens at `redirectUri` (a provider's\n * fixed port; for an MCP server the loopback URI the client passed) and\n * forwards the code; `'browser'`: the client opens `url` (pasting a code if\n * the page shows one); `'device'`: shows `userCode`. The flow belongs to\n * this connection, is single-use and expires (`expiresAt`). Additive.\n */\n 'auth.oauth.begin': { params: { provider?: string, mcpServer?: string, cwd?: string, kind?: string, redirectUri?: string }, result: HostOAuthBegin }\n /**\n * Deliver the code (`code` + `state` from the loopback, or `input`: what\n * the user pasted) once, then wait for the host's token exchange; without\n * either, just wait (device and polling flows). A wrong `state` or another\n * connection's flow is refused. Tokens stay on the host: the result says\n * what changed, never a secret.\n */\n 'auth.oauth.complete': { params: { flowId: string, code?: string, state?: string, input?: string }, result: HostOAuthComplete }\n /**\n * Answer the step a flow is waiting on (`HostOAuthBegin.step` before its\n * URL, `HostOAuthComplete.step` after): a select's option id (none:\n * cancel), a prompt's text. Answers with where the flow is now: its URL, or\n * the next step. Then `complete` as before. Additive.\n */\n 'auth.oauth.respond': { params: { flowId: string, stepId: string, value?: string }, result: HostOAuthBegin }\n /** Abandon a flow of this connection. */\n 'auth.oauth.cancel': { params: { flowId: string }, result: { cancelled: boolean } }\n\n /**\n * What the host discovered for the settings tabs, each entry with whether\n * the host's settings enable it (an unset allowlist enables everything).\n * `cwd` adds the project scope of that folder (inside the workspace roots\n * on a server); without it, the user scope (the host user's home). The\n * enabled lists are written with `settings.set`. Installing, removing and\n * MCP sign-in stay on the host's machine. Additive.\n */\n 'catalog.skills': { params: { cwd?: string, kind?: string }, result: { skills: HostCatalogSkill[] } }\n /** MCP servers: `env` and `headers` values, URL credentials and query values are redacted. */\n 'catalog.mcps': { params: { cwd?: string, kind?: string }, result: { servers: HostCatalogMcp[], errors: HostCatalogError[] } }\n 'catalog.extensions': { params: { cwd?: string, kind?: string }, result: { extensions: HostCatalogExtension[] } }\n 'catalog.plugins': { params: { cwd?: string, kind?: string }, result: { plugins: HostCatalogPlugin[] } }\n /**\n * Install a skill or an extension on the host, in its user's scope only\n * (`scope` may only be `'user'`): a GitHub (`owner/repo[#ref][:dir]`, a\n * GitHub URL, a skills.sh URL) or npm spec; paths are refused. `skills` /\n * `all` pick from a multi-skill source (the `multiple-candidates` error\n * lists them), `extension` from a multi-extension one. Runs the host's\n * package managers and fetches code there: a zidane-server's\n * `allowRemoteInstalls` gates it, every attempt is audited. Bounded in\n * time; the progress lines come back with the result. Every window gets\n * `catalog:changed`. Additive (`remoteInstalls` on `ipc.hello`).\n */\n 'catalog.install': { params: { kind: HostInstallKind, spec: string, scope?: 'user', skills?: string[], all?: boolean, extension?: string, overwrite?: boolean }, result: { installed: string[], message: string, progress: string[] } }\n /** Remove a user-scope skill or extension of the host by name (its directory). As `catalog.install`. */\n 'catalog.remove': { params: { kind: HostInstallKind, name: string }, result: { removed: string, message: string } }\n /** Update a user-scope extension installed from a source. As `catalog.install`. */\n 'catalog.update': { params: { kind: HostInstallKind, name: string }, result: { updated: string, upToDate: boolean, message: string } }\n /**\n * Add or replace an MCP server in the host user's `mcps.json`. Its `env` /\n * `headers` values are stored there and never come back (`catalog.mcps`\n * redacts them, the reply names the server only). As `catalog.install`.\n */\n 'mcp.upsert': { params: { config: McpServerConfig }, result: { name: string, created: boolean } }\n /** Remove an MCP server from the host user's `mcps.json`; `removed: false` when it has none. As `catalog.install`. */\n 'mcp.remove': { params: { name: string }, result: { removed: boolean } }\n /**\n * The host's credentialed providers (what its agents can run) and their\n * models, for a model picker of a session on that host. `cwd` adds the\n * providers its extensions contribute there. Additive.\n */\n 'models.list': { params: { cwd?: string, kind?: string }, result: { providers: HostModelProvider[] } }\n\n /**\n * The machines this host knows (`docs/MACHINES.md`), online or not, and\n * forgetting one (it disconnects; its `local@` / `worktree@` kinds stop\n * resolving). Additive.\n */\n 'machines.list': { params: Record<string, never>, result: MachineInfo[] }\n 'machines.forget': { params: { machineId: string }, result: { forgotten: boolean } }\n /**\n * Folders of a machine, for a client's folder picker: the host proxies a\n * listing to the machine (`fs.list`, confined to its roots there): the\n * folders in `path` (absent: its first root), and every root. Additive.\n */\n 'machines.listDirs': { params: { machineId: string, path?: string }, result: { path: string, dirs: string[], roots: string[] } }\n /**\n * A local host's machine links (`docs/MACHINES.md` § Client UI), behind\n * remote hosts: share this computer with a saved server (the machine agent\n * runs in this host's process, with the machine token `token` or the one\n * already stored for that server), stop sharing, use a saved server as a\n * machine (reverse direction), and read their state. Refused while remote\n * hosts are off. Additive.\n */\n 'machines.share.start': { params: { hostId: string, name: string, roots: string[], token?: string }, result: MachineLinksStatus }\n 'machines.share.stop': { params: { hostId: string }, result: MachineLinksStatus }\n 'machines.useServer': { params: { hostId: string, enabled: boolean }, result: MachineLinksStatus }\n 'machines.links.status': { params: Record<string, never>, result: MachineLinksStatus }\n /**\n * Reverse direction (`docs/MACHINES.md` § Reverse direction): a client asks\n * this server to lend itself as a machine over this very connection\n * (`allowAsMachine` on, else refused). `hostId` names the asking host, so\n * a reconnect finds its tasks and terminals again. Then `machine.call`\n * carries each host→machine request (`MachineMethods`), answered by the\n * server's confined executor; machine notifications come back as\n * `machine:notification` signals on this connection only.\n */\n 'machine.attach': { params: { hostId: string }, result: MachineRegisterParams }\n 'machine.call': { params: { method: string, params?: JsonValue }, result: JsonValue }\n 'machine.detach': { params: Record<string, never>, result: { detached: boolean } }\n /**\n * Mint a `machine`-scoped token on this server (a zidane-server only), so\n * a window can share its computer in one step. Any client may: in the\n * single-user model a client token is already an admin's. Audited.\n */\n 'tokens.createMachineToken': { params: { name: string }, result: { id: string, name: string, token: string } }\n\n /*\n * Settings sync, a client's computer → this server (`docs/SERVER.md`\n * § Settings sync). A zidane-server only; other hosts refuse. One source\n * device per server: `sync.claim` makes the caller it (or says who is,\n * unless `takeover`), `sync.push` applies one category's snapshot through\n * the host's own setters, skipping fields edited here since (overrides),\n * `sync.reset` drops an override, `sync.release` stops the source. Every\n * call is audited with its token. Additive.\n */\n 'sync.status': { params: Record<string, never>, result: SyncStatus }\n 'sync.claim': { params: { deviceId: string, deviceName: string, takeover?: boolean, categories?: SyncCategory[], keys?: string[] }, result: SyncClaimResult }\n 'sync.push': { params: { deviceId: string, category: SyncCategory, payload: SyncPayload }, result: SyncPushResult }\n 'sync.reset': { params: { field: string }, result: { reset: boolean } }\n 'sync.release': { params: { deviceId: string }, result: { released: boolean } }\n\n 'daemon.info': { params: Record<string, never>, result: HelloResult }\n /**\n * Graceful drain: deny pending approvals, abort live runs, close the\n * socket. Used by clients that detect a protocol-version mismatch and\n * need the stale daemon gone before respawning.\n *\n * `whenIdle` (version-skew retirement): a daemon with active work does\n * NOT abort it. It answers `{ deferred: true }` and exits once idle.\n * Explicit stops (`zidane daemon stop`) omit it and drain immediately.\n * Daemons predating the flag ignore it and drain immediately.\n */\n 'daemon.shutdown': { params: { whenIdle?: boolean }, result: { deferred?: boolean } | void }\n}\n\n/** The host's identity from a hello (or `daemon.info`) reply; `null` from a host that predates it. */\nexport function hostRefOf(hello: HelloResult): HostRef | null {\n if (typeof hello.hostId !== 'string' || !hello.hostKind)\n return null\n return { id: hello.hostId, kind: hello.hostKind, name: hello.hostName ?? hello.hostId }\n}\n\nexport type IpcMethodName = keyof IpcMethods\nexport type IpcParams<M extends IpcMethodName> = IpcMethods[M]['params']\nexport type IpcResult<M extends IpcMethodName> = IpcMethods[M]['result']\n\n/** Turns per `sessions.loadEvents` page when only `before` is given. */\nexport const LOAD_EVENTS_PAGE_TURNS = 200\n/** Largest `limit` a host honors. */\nexport const LOAD_EVENTS_MAX_PAGE_TURNS = 1000\n\nexport interface LoadEventsPaging {\n /** Turn position (exclusive) the page ends at: a previous page's `cursor`. */\n before?: number\n /** Turns in the page. */\n limit?: number\n}\n\nexport interface SessionEventsPage {\n events: StreamEvent[]\n /** Pass as `before` for the page before this one; absent once the first turn is in. */\n cursor?: number\n /**\n * The events are this page's slice of the whole replay, so pages\n * concatenate to exactly one whole `loadEvents`. Absent from an older\n * host, whose pages replay on their own ({@link loadAllEvents} restores\n * the exchange separator at their joins).\n */\n exact?: true\n /**\n * With `exact`: how many events of the whole replay come before this\n * page. Lets a client open on the tail of a long transcript and still\n * say how much it left out ({@link loadEventsTail}). Absent from an\n * older host.\n */\n start?: number\n}\n\n/**\n * One page of `sessions.loadEvents` (see its paging). An older host answers\n * the whole transcript: it comes back as one page with no cursor.\n */\nexport async function loadEventsPage(\n request: (method: 'sessions.loadEvents', params: { sessionId: string }) => Promise<StreamEvent[]>,\n params: { sessionId: string } & LoadEventsPaging,\n): Promise<SessionEventsPage> {\n const result = await request('sessions.loadEvents', params) as StreamEvent[] | SessionEventsPage\n return Array.isArray(result) ? { events: result } : result\n}\n\nfunction isResponseTooLarge(err: unknown): boolean {\n return typeof err === 'object' && err !== null && (err as { code?: unknown }).code === IpcErrorCode.ResponseTooLarge\n}\n\n/**\n * A session's whole transcript, loaded a page at a time from the end so no\n * single reply carries it all (a long session with images can outgrow a\n * transport's message size). A page refused as too large is asked again at\n * half the turns, down to one; a single turn that still doesn't fit fails\n * the load. An older host answers the whole transcript to the first call.\n */\nexport async function loadAllEvents(\n request: (method: 'sessions.loadEvents', params: { sessionId: string }) => Promise<StreamEvent[]>,\n sessionId: string,\n options: { pageTurns?: number } = {},\n): Promise<StreamEvent[]> {\n return (await loadEventsFromEnd(request, sessionId, options.pageTurns ?? LOAD_EVENTS_PAGE_TURNS)).events\n}\n\n/**\n * The end of a session's transcript: pages from the end until `enough`\n * holds for what was loaded (or the first turn is in), and how many events\n * of the whole replay come before it (`earlier`). Only exact pages can stop\n * early, since only they say where they start: an older host's transcript\n * loads whole, with `earlier` 0.\n */\nexport async function loadEventsTail(\n request: (method: 'sessions.loadEvents', params: { sessionId: string }) => Promise<StreamEvent[]>,\n sessionId: string,\n enough: (events: readonly StreamEvent[]) => boolean,\n options: { pageTurns?: number } = {},\n): Promise<{ events: StreamEvent[], earlier: number }> {\n return loadEventsFromEnd(request, sessionId, options.pageTurns ?? LOAD_EVENTS_PAGE_TURNS, enough)\n}\n\nasync function loadEventsFromEnd(\n request: (method: 'sessions.loadEvents', params: { sessionId: string }) => Promise<StreamEvent[]>,\n sessionId: string,\n pageTurns: number,\n enough?: (events: readonly StreamEvent[]) => boolean,\n): Promise<{ events: StreamEvent[], earlier: number }> {\n let limit = pageTurns\n const pages: StreamEvent[][] = []\n let newerExact = false\n let allExact = true\n let before: number | undefined\n for (;;) {\n let page: SessionEventsPage\n try {\n page = await loadEventsPage(request, { sessionId, limit, ...(before !== undefined ? { before } : {}) })\n }\n catch (err) {\n if (isResponseTooLarge(err) && limit > 1) {\n limit = Math.max(1, Math.floor(limit / 2))\n continue\n }\n throw err\n }\n /*\n * An exact page is a slice of the whole replay: nothing to restore. An\n * older host's pages replay on their own, so the exchange separator a\n * whole replay puts before a prompt that follows an exchange is missing\n * where the newer page starts (its pages start at a prompt when they\n * can): put it back.\n */\n const newer = pages[0]\n if (newer && !newerExact && newer[0]?.kind === 'user-prompt' && page.events.length > 0)\n newer.unshift({ kind: 'separator', text: '' })\n newerExact = page.exact === true\n allExact &&= newerExact && page.start !== undefined\n pages.unshift(page.events)\n // Done at the first turn; a cursor that doesn't move back would loop.\n if (page.cursor === undefined || page.cursor <= 0 || (before !== undefined && page.cursor >= before))\n break\n if (enough && allExact) {\n const events = pages.flat()\n if (enough(events))\n return { events, earlier: page.start! }\n }\n before = page.cursor\n }\n return { events: pages.flat(), earlier: 0 }\n}\n\n/** Turns per `sessions.getTurns` page by default. */\nexport const SESSION_TURNS_PAGE = 200\n/** Largest `limit` a host honors for `sessions.getTurns`. */\nexport const SESSION_TURNS_MAX_PAGE = 1000\n\ntype SessionDocumentRequest = <M extends 'sessions.get' | 'sessions.getTurns'>(method: M, params: IpcParams<M>) => Promise<IpcResult<M>>\n\n/**\n * What `sessions.get` answers: the document; with `turns: false`, the\n * version of the snapshot it was cut from, the one `sessions.getTurns`\n * pages carry.\n */\nexport type SessionDocumentHead = SessionData & { version?: string }\n\n/** How many times a paged read starts over because the session changed under it, before it asks for the whole document in one reply. */\nconst SESSION_DOCUMENT_RESTARTS = 3\n\n/**\n * A session's whole document, read a page of turns at a time so no reply\n * carries it all (`sessions.getTurns` pages, then the `sessions.get`\n * `turns: false` head; a page refused as too large is asked again at half\n * the turns). Every page and the head name the snapshot they come from: a\n * version change mid-read (a turn appended, a compaction) starts the read\n * over, so the result is one version, never pages of two. After\n * {@link SESSION_DOCUMENT_RESTARTS} restarts (a session busier than the\n * read), the whole document comes in one reply. A host that predates\n * `sessions.getTurns` sends it that way too; one that names no version is\n * read as before. `null` when the host doesn't know the session.\n */\nexport async function loadSessionDocument(\n request: SessionDocumentRequest,\n sessionId: string,\n options: { pageTurns?: number } = {},\n): Promise<SessionData | null> {\n const paging = { limit: options.pageTurns ?? SESSION_TURNS_PAGE }\n for (let attempt = 0; attempt <= SESSION_DOCUMENT_RESTARTS; attempt++) {\n const read = await readSessionDocumentOnce(request, sessionId, paging)\n if (read !== 'changed')\n return read\n }\n return withoutVersion(await request('sessions.get', { sessionId }))\n}\n\nfunction withoutVersion(head: SessionDocumentHead | null): SessionData | null {\n if (!head)\n return null\n const { version: _version, ...data } = head\n return data\n}\n\n/** One paged read; `'changed'`: the version moved between two of its replies. */\nasync function readSessionDocumentOnce(request: SessionDocumentRequest, sessionId: string, paging: { limit: number }): Promise<SessionData | null | 'changed'> {\n const turns: SessionTurn[] = []\n let total = Infinity\n let version: { of?: string } | null = null\n while (turns.length < total) {\n let page: IpcResult<'sessions.getTurns'>\n try {\n page = await request('sessions.getTurns', { sessionId, from: turns.length, limit: paging.limit })\n }\n catch (err) {\n if (turns.length === 0 && isMethodNotFound(err))\n return withoutVersion(await request('sessions.get', { sessionId }))\n if (isResponseTooLarge(err) && paging.limit > 1) {\n paging.limit = Math.max(1, Math.floor(paging.limit / 2))\n continue\n }\n throw err\n }\n if (!page)\n return null\n if (version === null)\n version = { ...(page.version !== undefined ? { of: page.version } : {}) }\n else if (page.version !== version.of)\n return 'changed'\n total = page.total\n // A session that shrank meanwhile on a host that names no version ends the read where it is.\n if (page.turns.length === 0)\n break\n turns.push(...page.turns)\n }\n const head = await request('sessions.get', { sessionId, turns: false })\n if (!head)\n return null\n if (version !== null && head.version !== version.of)\n return 'changed'\n return { ...withoutVersion(head)!, turns }\n}\n\n/** A catalog entry's on/off state as the host's settings decide it. */\ninterface HostCatalogToggle {\n name: string\n /** The host's settings enable it (always `false` for an entry that cannot load). */\n enabled: boolean\n /**\n * Its own allowlist governs it (`enabledSkills`, …). `false`: contributed\n * by a plugin or extension (their toggle governs it), or broken.\n */\n toggleable: boolean\n}\n\nexport interface HostCatalogSkill extends HostCatalogToggle {\n description: string\n source?: 'project' | 'user' | 'inline' | 'builtin'\n /** `SKILL.md` on the host's machine. */\n location?: string\n /** `disk`: a scan path; else the plugin or extension that contributes it (`contributedBy`). */\n origin: 'disk' | 'plugin' | 'extension'\n contributedBy?: string\n}\n\n/** Every secret-bearing value of a catalog entry is replaced by this. */\nexport const REDACTED = '<redacted>'\n\nexport interface HostCatalogMcp extends HostCatalogToggle {\n transport: 'stdio' | 'sse' | 'streamable-http'\n source: 'project' | 'user'\n /** The config file on the host's machine. */\n path: string\n command?: string\n args?: string[]\n /** Credentials and query values redacted. */\n url?: string\n cwd?: string\n scope?: 'host' | 'context'\n auth?: 'oauth'\n /** Names only: every value is {@link REDACTED}. */\n env?: Record<string, string>\n headers?: Record<string, string>\n}\n\n/** A config file that failed to parse (or an informational skip). */\nexport interface HostCatalogError {\n path: string\n source: 'project' | 'user'\n message: string\n informational?: boolean\n}\n\nexport interface HostCatalogExtension extends HostCatalogToggle {\n source: 'user' | 'project' | 'inline' | 'builtin'\n version?: string\n description?: string\n dir?: string\n /** Why it did not load. */\n error?: string\n /** What it contributes: `tools`, `skills`, `mcps`, `commands`, … */\n capabilities?: string[]\n}\n\nexport interface HostCatalogPlugin extends HostCatalogToggle {\n origin: { kind: 'disk', scope: 'project' | 'user', dir: string } | { kind: 'extension', extensionName: string, dir: string }\n /** `false`: the manifest was rejected (`error` says why). */\n ok: boolean\n version?: string\n description?: string\n skills: string[]\n mcpServers: string[]\n error?: string\n}\n\n/** One provider a host can run, with its models (`models.list`). */\nexport interface HostModelProvider {\n key: string\n label: string\n models: HostModelInfo[]\n}\n\n/** `ModelInfo` as it crosses the wire. */\nexport interface HostModelInfo {\n id: string\n name?: string\n contextWindow: number\n maxTokens?: number\n reasoning?: boolean\n input?: ('text' | 'image')[]\n cost?: { input: number, output: number, cacheRead?: number, cacheWrite?: number }\n provider?: string\n options?: { id: string, label: string, description?: string, costMultiplier?: { input?: number, output?: number, cacheRead?: number, cacheWrite?: number } }[]\n}\n\n/** One credential source of a host's provider (`auth.status`); no secret. */\nexport interface HostAuthMethod {\n source: 'apikey' | 'oauth' | 'env'\n /** A stored credential the provider resolves (`env` never is). */\n active: boolean\n /** Credentials-file key of a stored credential: the `account` of `auth.remove`. */\n key?: string\n /** OAuth account name. */\n label?: string\n /** Display detail: `credentials.json`, an OAuth account and its expiry, an env var name. */\n detail: string\n}\n\n/** `auth.oauth.begin`: what the client shows and where the code comes back. */\n/**\n * A question the provider's sign-in asks before (or after) its URL: a choice\n * between flows, or a free text. The client shows it and answers with\n * `auth.oauth.respond`; the host never picks for the user.\n */\nexport type HostOAuthStep\n = | { id: string, kind: 'select', message: string, options: Array<{ id: string, label: string }> }\n | { id: string, kind: 'prompt', message: string, placeholder?: string, allowEmpty?: boolean }\n\nexport interface HostOAuthBegin {\n /** Random, single-use, bound to the connection that began it. */\n flowId: string\n /** The authorization URL (a device flow: its verification URL); `''` while a `step` comes first. */\n url: string\n /** `step`: answer {@link step} (`auth.oauth.respond`) before the URL exists. */\n mode: 'loopback' | 'browser' | 'device' | 'step'\n step?: HostOAuthStep\n /** `loopback`: where the browser is sent back, on the client's machine. */\n redirectUri?: string\n /** `device`: the code to enter at `url`. */\n userCode?: string\n instructions?: string\n /** Epoch ms: the host forgets the flow after it. */\n expiresAt: number\n}\n\n/** `auth.oauth.complete`: the outcome, never a token. */\nexport interface HostOAuthComplete {\n /** A provider sign-in: its new status. */\n provider?: HostProviderAuth\n /** An MCP server sign-in: its name. */\n mcpServer?: string\n /** Not finished: the sign-in asks this. Answer it (`auth.oauth.respond`), then `complete` again. */\n step?: HostOAuthStep\n}\n\nexport interface HostProviderAuth {\n key: string\n label: string\n /** Some credential source is present. */\n configured: boolean\n /** The provider signs in with OAuth (on the host's machine only). */\n oauth: boolean\n /** The env var it reads, when it declares one. */\n envKey?: string\n methods: HostAuthMethod[]\n}\n\nexport interface FsRoots {\n /** Real paths, the default first. */\n roots: string[]\n /** Session folders must be inside `roots` (a server). */\n confined: boolean\n}\n\nexport interface FsDirEntry {\n name: string\n /** Real path (a symlink resolved). */\n path: string\n /** Holds a `.git`. */\n isGitRepo: boolean\n}\n\nexport interface FsDirListing {\n roots: string[]\n /** The listed folder, as a real path. */\n path: string\n /** The folder above, or `null` at a root. */\n parent: string | null\n /** Sorted by name. */\n entries: FsDirEntry[]\n /** More folders than the listing returns. */\n truncated?: boolean\n}\n\n/** One row in a cross-window session list. */\n/** One ordered model-fallback target (primary excluded). */\nexport interface ModelFallbackRef {\n providerKey: ProviderKey\n modelId: string\n}\n\nexport interface SessionRow {\n id: string\n title: string\n projectRoot: string | null\n cwd: string\n agentId?: string\n status: 'idle' | 'running' | 'completed' | 'error'\n createdAt: number\n updatedAt: number\n archived: boolean\n /** Orchestration main session — see `SessionMeta.isMain`. Additive. */\n isMain?: boolean\n providerKey?: ProviderKey\n modelId?: string\n effort?: ThinkingLevel\n modelOptions?: Record<string, boolean>\n /** Validated (head-matched) fallback chain tail, for pickers/badges. */\n modelFallbacks?: ModelFallbackRef[]\n /** Non-local environment summary (kind, state, branch, error). */\n environment?: SessionEnvironmentSummary\n /** The host serving this row (`HelloResult.hostId`). Additive: absent from older hosts. */\n hostId?: string\n}\n\nexport interface CreateSessionParams {\n /** Tool-execution directory — `projectRoot` is derived from it host-side. */\n cwd: string\n title?: string\n agentId?: string\n providerKey?: ProviderKey\n modelId?: string\n /** Seed an ordered fallback chain alongside the model pick. */\n fallbacks?: ModelFallbackRef[]\n /** The model pick's reasoning effort and options, stamped with it. */\n effort?: ThinkingLevel\n modelOptions?: Record<string, boolean>\n /** Skills pinned from the first turn (an authoring session's docs skill). */\n pinnedSkills?: string[]\n /** Mark as an extension-authoring session (auto-activates the docs skill). */\n extensionEdit?: boolean\n /** Mark as a skill-authoring session for the named skill (dir = `cwd`). */\n skillEdit?: { name: string }\n /** Where the session's work happens. Omitted → local. */\n environment?: EnvironmentRequest\n}\n\n/* -------------------------------------------------------------------------\n * Daemon handshake\n * ---------------------------------------------------------------------- */\n\nexport interface HelloParams {\n protocolVersion: number\n /** Client's zidane version — surfaced in daemon diagnostics. */\n appVersion: string\n pid: number\n /**\n * Build fingerprint (module mtime; `'unknown'` in compiled binaries).\n * When BOTH sides report a real id and they differ, the daemon rejects\n * the handshake like a protocol-version mismatch — the client drains it\n * and respawns. Closes same-version code drift during development.\n */\n buildId?: string\n /**\n * Version of the zidane code the client runs (`ZIDANE_VERSION`, inlined at\n * build). Unlike `buildId` this survives compiled binaries, so it closes\n * the gap released builds had: same protocol version, older code. A\n * client STRICTLY NEWER than the daemon is rejected like a build mismatch\n * and the stale daemon is drained; an older client is accepted and\n * degrades via `optional()`.\n */\n codeVersion?: string\n}\n\n/**\n * What a host process is: a window's own (`in-process`), the local shared\n * daemon (`daemon`), or a remote `zidane-server` (`server`).\n */\nexport type HostKind = 'in-process' | 'daemon' | 'server'\n\n/** Which host a client is talking to, as clients keep it (from `hostRefOf`). */\nexport interface HostRef {\n /** Stable across restarts: persisted in the host's data dir. */\n id: string\n kind: HostKind\n /** Display name: the machine's hostname by default. */\n name: string\n}\n\nexport interface HelloResult {\n protocolVersion: number\n appVersion: string\n pid: number\n startedAt: number\n buildId?: string\n codeVersion?: string\n /**\n * Host identity (additive). `hostId` is a UUID persisted once in the host's\n * data dir, so it survives restarts; the in-process host and the local\n * daemon share the data dir, and so the id: they are the same computer.\n */\n hostId?: string\n hostKind?: HostKind\n hostName?: string\n /**\n * The daemon is older than a client that attached while it had active\n * work: it accepted the handshake instead of draining (which would abort\n * those runs) and exits once idle. Clients attach normally; their\n * reconnect path lands on a fresh daemon after the exit.\n */\n retiring?: boolean\n /**\n * Names this host process's signal numbering ({@link SIGNAL_SEQ_FIELD}):\n * a position from another epoch cannot be resumed. Additive.\n */\n signalEpoch?: string\n /**\n * This server lends itself as a machine to the hosts of its clients\n * (`machine.attach`, `allowAsMachine` on). Absent: it doesn't. Additive.\n */\n machineServe?: boolean\n /**\n * This server takes installs and removals from its clients (`catalog.install`\n * / `remove` / `update`, `mcp.upsert` / `remove`; `allowRemoteInstalls` on).\n * Absent: it doesn't (or predates them). Additive.\n */\n remoteInstalls?: boolean\n /** This server takes settings sync from a client's computer (`sync.*`). Absent: it doesn't. Additive. */\n sync?: boolean\n}\n\n/** `catalog.install` / `remove` / `update`: what is installed from a client, in the host user's scope. */\nexport type HostInstallKind = 'skill' | 'extension'\n\n/** Which catalog a `catalog:changed` signal says to re-read. */\nexport type HostCatalogName = 'skills' | 'mcps' | 'extensions' | 'plugins'\n","/**\n * The client side every wire transport shares (the unix socket in\n * `../client.ts`, the WebSocket in `./ws-client.ts`): the `ipc.hello`\n * handshake with its version fences, typed requests with deadlines,\n * notifications, and signal fan-out. A transport supplies a connected\n * JSON-RPC {@link ClientChannel}; this turns it into an {@link IpcClient}.\n */\nimport type { AcpPeer, JsonRpcMessage } from '../../acp/types'\nimport type { HelloResult, HostSignal, IpcMethodName, IpcParams, IpcResult, SignalMeta } from '../protocol'\nimport { JsonRpcConnectionClosedError, JsonRpcRemoteError } from '../../acp/json-rpc'\nimport { compareVersions, ZIDANE_VERSION } from '../../version'\nimport { IPC_BUILD_ID } from '../daemon/lifecycle'\nimport { IPC_PROTOCOL_VERSION, IpcErrorCode, PING_METHOD, SIGNAL_SEQ_FIELD } from '../protocol'\n\nexport interface IpcClient {\n hello: HelloResult\n request: <M extends IpcMethodName>(method: M, params: IpcParams<M>) => Promise<IpcResult<M>>\n /**\n * Fire-and-forget notification — same method table as `request`, but no\n * id, no response, no pending-promise bookkeeping. The hot path for\n * high-frequency writes (per-keystroke draft sync). Daemons that don't\n * know the method ignore it silently.\n */\n notify: <M extends IpcMethodName>(method: M, params: IpcParams<M>) => void\n /** Host signals, with their number in their session when they have one (`SignalMeta`). */\n onSignal: (cb: SignalListener) => () => void\n close: () => void\n}\n\nexport type SignalListener = (signal: HostSignal, meta?: SignalMeta) => void\n\nexport class IpcVersionMismatchError extends Error {\n constructor(message: string, readonly daemon?: HelloResult) {\n super(message)\n this.name = 'IpcVersionMismatchError'\n }\n}\n\n/** A connected JSON-RPC link to a host, as a transport hands it over. */\nexport interface ClientChannel {\n rpc: Pick<AcpPeer, 'sendRequest' | 'sendNotification'>\n /** The caller's `close()`: quiet (no `onClose`), fails what is in flight. Idempotent. */\n close: () => void\n /** Drop a wedged connection: like the host going away, so the transport's `onClose` fires. */\n abort: () => void\n /** Where the host is, for error messages (a socket path, a URL). */\n where: string\n}\n\nexport interface ClientCoreOptions {\n appVersion?: string\n /**\n * When the host refuses the handshake on a version / build mismatch:\n * `always` asks it to drain so a matching one can be spawned (session\n * controllers on the local daemon); `stale-only` only when the host is\n * provably older (passive local clients); `never` leaves it running (a\n * remote server's lifetime is not the client's to end).\n */\n drain: 'always' | 'stale-only' | 'never'\n /**\n * Send this build's fingerprint, so a host from an older build of the same\n * protocol refuses us. Off sends the `'unknown'` sentinel: clients that\n * can't act on a build mismatch (no drain, no respawn) opt out of that fence.\n */\n buildFence: boolean\n /**\n * Ping the host (`$/ping`) this often once attached; two pings in a row\n * left unanswered at the next tick abort the connection (the transport's\n * `onClose` fires, its owner reconnects). Off when absent or `0`: a\n * local socket learns of a dead host from the kernel.\n */\n heartbeatMs?: number\n}\n\n/** Missed heartbeats after which the host is considered gone. */\nexport const HEARTBEAT_MISSES = 2\n\n/** Starts the client heartbeat on `channel`; returns its stop. Stops itself once the channel closes. */\nfunction startHeartbeat(channel: ClientChannel, intervalMs: number): () => void {\n let awaiting = false\n let missed = 0\n const timer = setInterval(() => {\n if (awaiting && ++missed >= HEARTBEAT_MISSES) {\n clearInterval(timer)\n channel.abort()\n return\n }\n awaiting = true\n channel.rpc.sendRequest(PING_METHOD, {}).then(\n () => {\n awaiting = false\n missed = 0\n },\n (err: unknown) => {\n if (err instanceof JsonRpcConnectionClosedError) {\n clearInterval(timer)\n return\n }\n // Any answer, an error included (a host predating `$/ping`), proves it alive.\n awaiting = false\n missed = 0\n },\n )\n }, intervalMs)\n timer.unref?.()\n return () => clearInterval(timer)\n}\n\n/** The signal listeners of one client, and the JSON-RPC notification handler that feeds them. */\nexport function createSignalListeners() {\n const listeners = new Set<SignalListener>()\n return {\n listeners,\n onNotification(message: JsonRpcMessage & { method: string }): void {\n if (message.method !== 'ipc.signal')\n return\n const params = (message as { params?: HostSignal & { [SIGNAL_SEQ_FIELD]?: unknown } }).params\n if (!params)\n return\n const { [SIGNAL_SEQ_FIELD]: seq, ...signal } = params\n const meta = typeof seq === 'number' ? { seq } : undefined\n for (const cb of listeners)\n cb(signal as HostSignal, meta)\n },\n }\n}\n\nfunction hostRelease(hello: HelloResult): string | undefined {\n for (const value of [hello.codeVersion, hello.appVersion]) {\n if (typeof value !== 'string')\n continue\n const match = /^(?:zidane-gui\\/)?(v?\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?)$/.exec(value.trim())\n if (match)\n return match[1]\n }\n return undefined\n}\n\nconst HELLO_TIMEOUT_MS = 5000\nconst LONG_REQUEST_TIMEOUT_MS = 10 * 60 * 1000\n/** RPCs that legitimately run long — full compaction, index-backed cross-session search. */\nconst LONG_REQUEST_METHODS = new Set<string>(['sessions.compact', 'history.searchAll', 'history.searchSession'])\n\n/**\n * A refused handshake. Asks the host to drain when `drain` allows it, closes\n * the channel, and returns the error to throw.\n */\nasync function refusedHello(channel: ClientChannel, err: JsonRpcRemoteError, drain: ClientCoreOptions['drain']): Promise<IpcVersionMismatchError> {\n /*\n * Ask the stale daemon to drain so the caller can respawn a matching\n * one. AWAIT the reply (bounded) before tearing the connection down —\n * closing discards unflushed writes, so a fire-and-forget\n * `daemon.shutdown` could be dropped, leaving the stale daemon alive\n * and defeating `connectOrSpawnDaemon`'s retry.\n */\n const daemon = (err.data as { daemon?: HelloResult } | undefined)?.daemon\n // A network server's lifetime is never a client's to end, whatever `drain` says.\n if (daemon?.hostKind === 'server') {\n channel.close()\n return new IpcVersionMismatchError(serverMismatchMessage(daemon, channel.where) ?? err.message, daemon)\n }\n /*\n * Passive clients (`stale-only`) never retire a daemon on a protocol /\n * build mismatch — it may be NEWER than them. A daemon that is provably\n * OLDER — an older release, or the same release speaking an older\n * protocol (a dev build from before a protocol bump) — is the case where\n * draining is always safe: nothing newer can be running on it, and\n * whoever attaches next spawns a current one. Without this a passive\n * client (the GUI) would sit in-process forever behind a stale daemon\n * nobody restarts: every retry is refused.\n */\n const daemonIsOlderRelease\n = typeof daemon?.codeVersion === 'string' && compareVersions(daemon.codeVersion, ZIDANE_VERSION) < 0\n const release = daemon && hostRelease(daemon)\n const daemonIsNewerRelease = release !== undefined && compareVersions(release, ZIDANE_VERSION) > 0\n const daemonSpeaksOlderProtocol = typeof daemon?.protocolVersion === 'number' && daemon.protocolVersion < IPC_PROTOCOL_VERSION\n const daemonIsStale = daemonIsOlderRelease || daemonSpeaksOlderProtocol\n if (drain !== 'never' && !daemonIsNewerRelease && (drain === 'always' || daemonIsStale)) {\n // `whenIdle`: a daemon with live runs defers its exit instead of\n // aborting them (older daemons ignore the flag and drain now).\n await Promise.race([\n channel.rpc.sendRequest('daemon.shutdown', { whenIdle: true }).catch(() => undefined),\n new Promise(resolve => setTimeout(resolve, 1500)),\n ])\n }\n channel.close()\n return new IpcVersionMismatchError(err.message, daemon)\n}\n\n/** A server's protocol refusal, from this client's side: both versions and which side to upgrade. */\nfunction serverMismatchMessage(server: HelloResult, where: string): string | null {\n if (typeof server.protocolVersion !== 'number' || server.protocolVersion === IPC_PROTOCOL_VERSION)\n return null\n const upgrade = server.protocolVersion < IPC_PROTOCOL_VERSION ? 'server' : 'client'\n return `Protocol version mismatch with ${where}: the server speaks v${server.protocolVersion}, this client v${IPC_PROTOCOL_VERSION}. Upgrade the ${upgrade}.`\n}\n\nasync function handshake(channel: ClientChannel, options: ClientCoreOptions): Promise<HelloResult> {\n /*\n * Bound the handshake: a wedged daemon (accepting connections but never\n * reading — e.g. SIGSTOP'd) would otherwise hang this promise forever.\n * On timeout the channel is closed and the connect rejects.\n * `Promise.race` keeps the losing request promise handled, so the\n * connection-closed rejection that follows `close()` can't surface as an\n * unhandled rejection.\n */\n let helloTimer: ReturnType<typeof setTimeout> | undefined\n try {\n return (await Promise.race([\n channel.rpc.sendRequest('ipc.hello', {\n protocolVersion: IPC_PROTOCOL_VERSION,\n appVersion: options.appVersion ?? 'dev',\n pid: process.pid,\n // Build fingerprint: a daemon started from an OLDER build of this\n // same protocol version rejects us, gets drained, and respawns —\n // dev daemons can no longer run stale code silently. Clients that\n // cannot act on a build mismatch send the 'unknown' sentinel\n // instead (see `buildFence`): fencing them would just lock them\n // out until someone else retires the host. They stay fenced by\n // protocol version and degrade via `optional()` like any client of\n // an older daemon.\n buildId: options.buildFence ? IPC_BUILD_ID : 'unknown',\n // Always sent, passive clients included: a stale-RELEASE daemon is\n // safe for anyone to retire (see `refusedHello`).\n codeVersion: ZIDANE_VERSION,\n }),\n new Promise<never>((_, reject) => {\n helloTimer = setTimeout(\n () => reject(new Error(`Daemon handshake timed out after ${HELLO_TIMEOUT_MS}ms on ${channel.where}.`)),\n HELLO_TIMEOUT_MS,\n )\n }),\n ])) as HelloResult\n }\n catch (err) {\n if (err instanceof JsonRpcRemoteError && err.code === IpcErrorCode.VersionMismatch)\n throw await refusedHello(channel, err, options.drain)\n channel.close()\n throw err\n }\n finally {\n clearTimeout(helloTimer)\n }\n}\n\n/** Handshake over `channel`, then the typed client around it. On failure the channel is closed. */\nexport async function openIpcClient(\n channel: ClientChannel,\n listeners: Set<SignalListener>,\n options: ClientCoreOptions,\n): Promise<IpcClient> {\n const hello = await handshake(channel, options)\n\n const release = hostRelease(hello)\n // A `retiring` daemon is fence-aware and already exits once idle; staying\n // attached until then keeps its live runs reachable from this window. A\n // network server is never retired for a client: an older one is attached\n // to, and this client degrades (`optional()`) like an older client does.\n if (!hello.retiring && hello.hostKind !== 'server' && release !== undefined && compareVersions(release, ZIDANE_VERSION) < 0) {\n // Pre-fence daemons accept hello without checking codeVersion. Disconnect\n // only: shutting down a successfully attached daemon can abort active runs.\n channel.close()\n throw new IpcVersionMismatchError(\n `Daemon release ${release} is older than client ${ZIDANE_VERSION}. Restart the daemon when active runs have finished.`,\n hello,\n )\n }\n\n // Env override is a test seam (process-level e2e exercises the real\n // deadline without waiting 30 s); undocumented, not a user setting.\n const requestTimeoutMs = Number(process.env.ZIDANE_IPC_REQUEST_TIMEOUT_MS) || 30_000\n\n const stopHeartbeat = options.heartbeatMs ? startHeartbeat(channel, options.heartbeatMs) : () => undefined\n\n return {\n hello,\n notify: (method, params) => {\n try {\n channel.rpc.sendNotification(method, params)\n }\n catch {\n // fire-and-forget by contract — a dying connection surfaces via onClose\n }\n },\n request: async (method, params) => {\n /*\n * Per-request deadline: close rejection covers a DEAD host, but a\n * wedged one (alive, not reading — the same class the server-side\n * backpressure bound handles for peers) would hang callers forever.\n * On timeout the connection is aborted (NOT `close()` — the `onClose`\n * path must fire so reconnect logic takes over) and every pending\n * request rejects via the close sweep. Known long-running RPCs get a\n * generous budget; tearing the connection down mid-`sessions.compact`\n * would abort real work, so those bounds are deliberately loose.\n */\n // A machine call lasts as long as its command (`docs/MACHINES.md`); a dead host is the heartbeat's to catch.\n if (method === 'machine.call')\n return channel.rpc.sendRequest(method, params) as Promise<IpcResult<typeof method>>\n const timeoutMs = LONG_REQUEST_METHODS.has(method) ? LONG_REQUEST_TIMEOUT_MS : requestTimeoutMs\n let timer: ReturnType<typeof setTimeout> | undefined\n try {\n return (await Promise.race([\n channel.rpc.sendRequest(method, params),\n new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n reject(new Error(`Daemon request ${method} timed out after ${timeoutMs}ms, closing the connection.`))\n channel.abort()\n }, timeoutMs)\n timer.unref?.()\n }),\n ])) as IpcResult<typeof method>\n }\n finally {\n clearTimeout(timer)\n }\n },\n onSignal: (cb) => {\n listeners.add(cb)\n return () => listeners.delete(cb)\n },\n close: () => {\n stopHeartbeat()\n channel.close()\n },\n }\n}\n","/** Stable hashes of sync values: equal values (whatever their key order) hash the same, on both sides. */\nimport { createHash } from 'node:crypto'\n\nexport const isRecord = (value: unknown): value is Record<string, unknown> => typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/** JSON with sorted keys (undefined members dropped). */\nexport function stableStringify(value: unknown): string {\n if (Array.isArray(value))\n return `[${value.map(stableStringify).join(',')}]`\n if (isRecord(value))\n return `{${Object.keys(value).sort().filter(k => value[k] !== undefined).map(k => `${JSON.stringify(k)}:${stableStringify(value[k])}`).join(',')}}`\n return JSON.stringify(value) ?? 'undefined'\n}\n\nexport function hashValue(value: unknown): string {\n return createHash('sha256').update(stableStringify(value)).digest('hex')\n}\n","/** Which settings the `settings` sync category carries (`./types`). */\nimport type { Settings } from '../types'\nimport { HOST_ENABLED_LISTS, isWindowOnlySetting } from '../host-scoped-settings'\n\n/**\n * Host-scoped settings that still don't sync: they describe this computer\n * (its environments, its daemon, remote hosts on it) or would turn off what\n * the server has that this computer doesn't (the enabled allowlists, its OS\n * sandbox). Every `sandbox*` key, present and future, is the server's own:\n * a client turning it off there would be a sandbox escape.\n */\nconst NOT_SYNCED_SETTINGS: ReadonlySet<string> = new Set<string>(['environments', 'useDaemon', 'remoteHosts', ...HOST_ENABLED_LISTS])\n\n/** A setting the `settings` category carries: host-scoped (never window-only) and not machine-specific. */\nexport function isSyncableSetting(key: keyof Settings | string): boolean {\n return !isWindowOnlySetting(key) && !NOT_SYNCED_SETTINGS.has(key) && !key.startsWith('sandbox')\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,MAAa,sBAA8B;CACzC,IAAI;EACF,MAAM,WAAW,cAAc,YAAY,GAAG;EAmB9C,MAAM,UAAU,QAAQ,QAAQ,QAAQ,CAAC;EACzC,IAAI,CAAC,WAAW,KAAK,SAAS,aAAa,CAAC,GAC1C,OAAO,OAAO,KAAK,MAAM,SAAS,QAAQ,CAAC,CAAC,OAAO,CAAC;EAStD,MAAM,UAAU,QAAQ,OAAO;EAC/B,IAAI,SAAS;EACb,MAAM,QAAQ,QAAsB;GAClC,KAAK,MAAM,SAAS,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;IAC7D,MAAM,OAAO,KAAK,KAAK,MAAM,IAAI;IACjC,IAAI,MAAM,YAAY,GACpB,KAAK,IAAI;SAET,SAAS,KAAK,IAAI,QAAQ,SAAS,IAAI,CAAC,CAAC,OAAO;GACpD;EACF;EACA,IAAI;GACF,KAAK,OAAO;EACd,QACM;GACJ,SAAS,SAAS,QAAQ,CAAC,CAAC;EAC9B;EACA,OAAO,OAAO,KAAK,MAAM,MAAM,CAAC;CAClC,QACM;EACJ,OAAO;CACT;AACF,EAAA,CAAG;;;;;;;;;AAUH,SAAgB,iBAAiB,MAAyB,QAAQ,KAAiC;CACjG,OAAO,IAAI,cAAc,IAAI,eAAe,MAAM,aAAa;AACjE;AAEA,SAAgB,oBAA4B;CAC1C,MAAM,WAAW,QAAQ,IAAI;CAC7B,IAAI,UACF,OAAO;CAYT,MAAM,OAAO,mBAAmB,EAC9B,GAAI,QAAQ,IAAI,kBAAkB,KAAA,IAAY,EAAE,QAAQ,QAAQ,IAAI,cAAc,IAAI,CAAC,EACzF,CAAC;CACD,OAAO,KAAK,KAAK,UAAU,UAAU,iBAAiB,CAAC;AACzD;;;;;;;;;;AAWA,SAAgB,iBAAiB,YAAmC;CAClE,MAAM,MAAM,QAAQ,UAAU;CAC9B,IAAI,SAAS,UAAU,MAAM,iBAAiB,SAAS,GAAG,MAAM,UAC9D,OAAO;CACT,OAAO,KAAK,QAAQ,GAAG,GAAG,aAAa;AACzC;;;;;;;;;;;;AAaA,SAAgB,yBAAmC;CACjD,MAAM,UAAW,WAA2C,KAAK;CAEjE,IAAI,SAAS,WAAW,SAAS,GAC/B,OAAO,CAAC,QAAQ,UAAU,QAAQ;CAKpC,IAAI,WAAW,8BAA8B,KAAK,OAAO,GACvD,OAAO;EAAC,QAAQ;EAAU;EAAS;CAAQ;CAC7C,OAAO,CAAC,eAAe;AACzB;;;;;AAMA,SAAgB,YAAY,YAAoB,YAAY,KAAwB;CAClF,OAAO,IAAI,SAAS,YAAY;EAO9B,IAAI;GACF,IAAI,CAAC,WAAW,UAAU,KAAK,CAAC,SAAS,UAAU,CAAC,CAAC,SAAS,GAAG;IAC/D,QAAQ,KAAK;IACb;GACF;EACF,QACM;GACJ,QAAQ,KAAK;GACb;EACF;EAEA,IAAI;EACJ,IAAI;GACF,SAAS,QAAQ,UAAU;EAC7B,QACM;GACJ,QAAQ,KAAK;GACb;EACF;EACA,MAAM,QAAQ,UAAyB;GACrC,OAAO,QAAQ;GACf,QAAQ,KAAK;EACf;EACA,OAAO,KAAK,iBAAiB,KAAK,IAAI,CAAC;EACvC,OAAO,KAAK,eAAe,KAAK,KAAK,CAAC;EACtC,OAAO,WAAW,iBAAiB,KAAK,KAAK,CAAC;CAChD,CAAC;AACH;;;;;;AAmBA,MAAM,gCAAgB,IAAI,IAA6B;AAEvD,SAAgB,oBAAoB,UAA+B,CAAC,GAAoB;CACtF,MAAM,aAAa,QAAQ,cAAc,kBAAkB;CAC3D,MAAM,UAAU,cAAc,IAAI,UAAU;CAC5C,IAAI,SACF,OAAO;CACT,MAAM,QAAQ,YAAY;EAAE,GAAG;EAAS;CAAW,CAAC,CAAC,CAAC,cAAc,cAAc,OAAO,UAAU,CAAC;CACpG,cAAc,IAAI,YAAY,KAAK;CACnC,OAAO;AACT;AAEA,eAAe,YAAY,SAAwE;CACjG,MAAM,aAAa,QAAQ;CAC3B,IAAI,MAAM,YAAY,UAAU,GAC9B,OAAO;CAET,MAAM,CAAC,KAAK,GAAG,QAAQ,QAAQ,gBAAgB,CAAC,eAAe;CAC/D,MAAM,QAAQ,MAAM,KAAM,MAAM;EAC9B,UAAU;EACV,OAAO;EACP,KAAK;GAAE,GAAG,QAAQ;GAAK,sBAAsB;EAAW;CAC1D,CAAC;CAOD,IAAI;CACJ,MAAM,KAAK,UAAU,QAAe;EAClC,aAAa;CACf,CAAC;CACD,MAAM,MAAM;CAEZ,MAAM,WAAW,KAAK,IAAI,KAAK,QAAQ,aAAa;CACpD,SAAS;EACP,IAAI,eAAe,KAAA,GACjB,MAAM,IAAI,MAAM,kCAAkC,IAAI,KAAK,WAAW,SAAS;EACjF,IAAI,MAAM,YAAY,UAAU,GAC9B,OAAO;EACT,IAAI,KAAK,IAAI,IAAI,UACf,MAAM,IAAI,MAAM,oCAAoC,WAAW,UAAU,QAAQ,aAAa,IAAK,IAAI;EACzG,MAAM,IAAI,SAAQ,MAAK,WAAW,GAAG,GAAG,CAAC;CAC3C;AACF;;;;;;;;;;;;;;AE3PA,MAAa,iBAAyBA;;;;;;;AAQtC,SAAgB,gBAAgB,GAAW,GAAmB;CAC5D,MAAM,KAAK,MAAM,CAAC;CAClB,MAAM,KAAK,MAAM,CAAC;CAClB,IAAI,CAAC,MAAM,CAAC,IACV,OAAO;CACT,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;EAC1B,MAAM,KAAK,GAAG,MAAM,MAAM,GAAG,MAAM;EACnC,IAAI,MAAM,GACR,OAAO;CACX;CACA,OAAO;AACT;AAEA,SAAS,MAAM,GAA4B;CACzC,MAAM,IAAI,yBAAyB,KAAK,EAAE,KAAK,CAAC;CAChD,OAAO,IAAI;EAAC,OAAO,EAAE,EAAE;EAAG,OAAO,EAAE,EAAE;EAAG,OAAO,EAAE,EAAE;CAAC,IAAI;AAC1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC+IA,MAAa,uBAAuB;;;;;;AAOpC,MAAa,eAAe;CAC1B,iBAAiB;CACjB,eAAe;;CAEf,aAAa;;;;;;CAMb,kBAAkB;;;;;;CAMlB,eAAe;AACjB;;;;;;AAOA,MAAa,cAAc;;;;;;;AAQ3B,MAAa,mBAAmB;;AA4pBhC,SAAgB,UAAU,OAAoC;CAC5D,IAAI,OAAO,MAAM,WAAW,YAAY,CAAC,MAAM,UAC7C,OAAO;CACT,OAAO;EAAE,IAAI,MAAM;EAAQ,MAAM,MAAM;EAAU,MAAM,MAAM,YAAY,MAAM;CAAO;AACxF;;AAOA,MAAa,yBAAyB;;AAEtC,MAAa,6BAA6B;;;;;AAiC1C,eAAsB,eACpB,SACA,QAC4B;CAC5B,MAAM,SAAS,MAAM,QAAQ,uBAAuB,MAAM;CAC1D,OAAO,MAAM,QAAQ,MAAM,IAAI,EAAE,QAAQ,OAAO,IAAI;AACtD;AAEA,SAAS,mBAAmB,KAAuB;CACjD,OAAO,OAAO,QAAQ,YAAY,QAAQ,QAAS,IAA2B,SAAS,aAAa;AACtG;;;;;;;;AASA,eAAsB,cACpB,SACA,WACA,UAAkC,CAAC,GACX;CACxB,QAAQ,MAAM,kBAAkB,SAAS,WAAW,QAAQ,aAAA,GAAmC,EAAA,CAAG;AACpG;;;;;;;;AASA,eAAsB,eACpB,SACA,WACA,QACA,UAAkC,CAAC,GACkB;CACrD,OAAO,kBAAkB,SAAS,WAAW,QAAQ,aAAA,KAAqC,MAAM;AAClG;AAEA,eAAe,kBACb,SACA,WACA,WACA,QACqD;CACrD,IAAI,QAAQ;CACZ,MAAM,QAAyB,CAAC;CAChC,IAAI,aAAa;CACjB,IAAI,WAAW;CACf,IAAI;CACJ,SAAS;EACP,IAAI;EACJ,IAAI;GACF,OAAO,MAAM,eAAe,SAAS;IAAE;IAAW;IAAO,GAAI,WAAW,KAAA,IAAY,EAAE,OAAO,IAAI,CAAC;GAAG,CAAC;EACxG,SACO,KAAK;GACV,IAAI,mBAAmB,GAAG,KAAK,QAAQ,GAAG;IACxC,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,CAAC,CAAC;IACzC;GACF;GACA,MAAM;EACR;EAQA,MAAM,QAAQ,MAAM;EACpB,IAAI,SAAS,CAAC,cAAc,MAAM,EAAE,EAAE,SAAS,iBAAiB,KAAK,OAAO,SAAS,GACnF,MAAM,QAAQ;GAAE,MAAM;GAAa,MAAM;EAAG,CAAC;EAC/C,aAAa,KAAK,UAAU;EAC5B,aAAa,cAAc,KAAK,UAAU,KAAA;EAC1C,MAAM,QAAQ,KAAK,MAAM;EAEzB,IAAI,KAAK,WAAW,KAAA,KAAa,KAAK,UAAU,KAAM,WAAW,KAAA,KAAa,KAAK,UAAU,QAC3F;EACF,IAAI,UAAU,UAAU;GACtB,MAAM,SAAS,MAAM,KAAK;GAC1B,IAAI,OAAO,MAAM,GACf,OAAO;IAAE;IAAQ,SAAS,KAAK;GAAO;EAC1C;EACA,SAAS,KAAK;CAChB;CACA,OAAO;EAAE,QAAQ,MAAM,KAAK;EAAG,SAAS;CAAE;AAC5C;;AAGA,MAAa,qBAAqB;;AAElC,MAAa,yBAAyB;;AAYtC,MAAM,4BAA4B;;;;;;;;;;;;;AAclC,eAAsB,oBACpB,SACA,WACA,UAAkC,CAAC,GACN;CAC7B,MAAM,SAAS,EAAE,OAAO,QAAQ,aAAA,IAAgC;CAChE,KAAK,IAAI,UAAU,GAAG,WAAW,2BAA2B,WAAW;EACrE,MAAM,OAAO,MAAM,wBAAwB,SAAS,WAAW,MAAM;EACrE,IAAI,SAAS,WACX,OAAO;CACX;CACA,OAAO,eAAe,MAAM,QAAQ,gBAAgB,EAAE,UAAU,CAAC,CAAC;AACpE;AAEA,SAAS,eAAe,MAAsD;CAC5E,IAAI,CAAC,MACH,OAAO;CACT,MAAM,EAAE,SAAS,UAAU,GAAG,SAAS;CACvC,OAAO;AACT;;AAGA,eAAe,wBAAwB,SAAiC,WAAmB,QAAoE;CAC7J,MAAM,QAAuB,CAAC;CAC9B,IAAI,QAAQ;CACZ,IAAI,UAAkC;CACtC,OAAO,MAAM,SAAS,OAAO;EAC3B,IAAI;EACJ,IAAI;GACF,OAAO,MAAM,QAAQ,qBAAqB;IAAE;IAAW,MAAM,MAAM;IAAQ,OAAO,OAAO;GAAM,CAAC;EAClG,SACO,KAAK;GACV,IAAI,MAAM,WAAW,KAAK,iBAAiB,GAAG,GAC5C,OAAO,eAAe,MAAM,QAAQ,gBAAgB,EAAE,UAAU,CAAC,CAAC;GACpE,IAAI,mBAAmB,GAAG,KAAK,OAAO,QAAQ,GAAG;IAC/C,OAAO,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAM,OAAO,QAAQ,CAAC,CAAC;IACvD;GACF;GACA,MAAM;EACR;EACA,IAAI,CAAC,MACH,OAAO;EACT,IAAI,YAAY,MACd,UAAU,EAAE,GAAI,KAAK,YAAY,KAAA,IAAY,EAAE,IAAI,KAAK,QAAQ,IAAI,CAAC,EAAG;OACrE,IAAI,KAAK,YAAY,QAAQ,IAChC,OAAO;EACT,QAAQ,KAAK;EAEb,IAAI,KAAK,MAAM,WAAW,GACxB;EACF,MAAM,KAAK,GAAG,KAAK,KAAK;CAC1B;CACA,MAAM,OAAO,MAAM,QAAQ,gBAAgB;EAAE;EAAW,OAAO;CAAM,CAAC;CACtE,IAAI,CAAC,MACH,OAAO;CACT,IAAI,YAAY,QAAQ,KAAK,YAAY,QAAQ,IAC/C,OAAO;CACT,OAAO;EAAE,GAAG,eAAe,IAAI;EAAI;CAAM;AAC3C;;AAyBA,MAAa,WAAW;;;ACllCxB,IAAa,0BAAb,cAA6C,MAAM;CACX;CAAtC,YAAY,SAAiB,QAA+B;EAC1D,MAAM,OAAO;EADuB,KAAA,SAAA;EAEpC,KAAK,OAAO;CACd;AACF;;AA0CA,SAAS,eAAe,SAAwB,YAAgC;CAC9E,IAAI,WAAW;CACf,IAAI,SAAS;CACb,MAAM,QAAQ,kBAAkB;EAC9B,IAAI,YAAY,EAAE,UAAA,GAA4B;GAC5C,cAAc,KAAK;GACnB,QAAQ,MAAM;GACd;EACF;EACA,WAAW;EACX,QAAQ,IAAI,YAAY,aAAa,CAAC,CAAC,CAAC,CAAC,WACjC;GACJ,WAAW;GACX,SAAS;EACX,IACC,QAAiB;GAChB,IAAI,eAAe,8BAA8B;IAC/C,cAAc,KAAK;IACnB;GACF;GAEA,WAAW;GACX,SAAS;EACX,CACF;CACF,GAAG,UAAU;CACb,MAAM,QAAQ;CACd,aAAa,cAAc,KAAK;AAClC;;AAGA,SAAgB,wBAAwB;CACtC,MAAM,4BAAY,IAAI,IAAoB;CAC1C,OAAO;EACL;EACA,eAAe,SAAoD;GACjE,IAAI,QAAQ,WAAW,cACrB;GACF,MAAM,SAAU,QAAuE;GACvF,IAAI,CAAC,QACH;GACF,MAAM,GAAG,mBAAmB,KAAK,GAAG,WAAW;GAC/C,MAAM,OAAO,OAAO,QAAQ,WAAW,EAAE,IAAI,IAAI,KAAA;GACjD,KAAK,MAAM,MAAM,WACf,GAAG,QAAsB,IAAI;EACjC;CACF;AACF;AAEA,SAAS,YAAY,OAAwC;CAC3D,KAAK,MAAM,SAAS,CAAC,MAAM,aAAa,MAAM,UAAU,GAAG;EACzD,IAAI,OAAO,UAAU,UACnB;EACF,MAAM,QAAQ,sHAAsH,KAAK,MAAM,KAAK,CAAC;EACrJ,IAAI,OACF,OAAO,MAAM;CACjB;AAEF;AAEA,MAAM,mBAAmB;AACzB,MAAM,0BAA0B;;AAEhC,MAAM,uCAAuB,IAAI,IAAY;CAAC;CAAoB;CAAqB;AAAuB,CAAC;;;;;AAM/G,eAAe,aAAa,SAAwB,KAAyB,OAAqE;CAQhJ,MAAM,SAAU,IAAI,MAA+C;CAEnE,IAAI,QAAQ,aAAa,UAAU;EACjC,QAAQ,MAAM;EACd,OAAO,IAAI,wBAAwB,sBAAsB,QAAQ,QAAQ,KAAK,KAAK,IAAI,SAAS,MAAM;CACxG;CAWA,MAAM,uBACF,OAAO,QAAQ,gBAAgB,YAAY,gBAAgB,OAAO,aAAa,cAAc,IAAI;CACrG,MAAM,UAAU,UAAU,YAAY,MAAM;CAC5C,MAAM,uBAAuB,YAAY,KAAA,KAAa,gBAAgB,SAAS,cAAc,IAAI;CACjG,MAAM,4BAA4B,OAAO,QAAQ,oBAAoB,YAAY,OAAO,kBAAA;CAExF,IAAI,UAAU,WAAW,CAAC,yBAAyB,UAAU,YADvC,wBAAwB,4BAI5C,MAAM,QAAQ,KAAK,CACjB,QAAQ,IAAI,YAAY,mBAAmB,EAAE,UAAU,KAAK,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS,GACpF,IAAI,SAAQ,YAAW,WAAW,SAAS,IAAI,CAAC,CAClD,CAAC;CAEH,QAAQ,MAAM;CACd,OAAO,IAAI,wBAAwB,IAAI,SAAS,MAAM;AACxD;;AAGA,SAAS,sBAAsB,QAAqB,OAA8B;CAChF,IAAI,OAAO,OAAO,oBAAoB,YAAY,OAAO,oBAAA,IACvD,OAAO;CACT,MAAM,UAAU,OAAO,kBAAA,KAAyC,WAAW;CAC3E,OAAO,kCAAkC,MAAM,uBAAuB,OAAO,gBAAgB,iCAAsD,QAAQ;AAC7J;AAEA,eAAe,UAAU,SAAwB,SAAkD;CASjG,IAAI;CACJ,IAAI;EACF,OAAQ,MAAM,QAAQ,KAAK,CACzB,QAAQ,IAAI,YAAY,aAAa;GACnC,iBAAA;GACA,YAAY,QAAQ,cAAc;GAClC,KAAK,QAAQ;GASb,SAAS,QAAQ,aAAa,eAAe;GAG7C,aAAa;EACf,CAAC,GACD,IAAI,SAAgB,GAAG,WAAW;GAChC,aAAa,iBACL,uBAAO,IAAI,MAAM,oCAAoC,iBAAiB,QAAQ,QAAQ,MAAM,EAAE,CAAC,GACrG,gBACF;EACF,CAAC,CACH,CAAC;CACH,SACO,KAAK;EACV,IAAI,eAAe,sBAAsB,IAAI,SAAS,aAAa,iBACjE,MAAM,MAAM,aAAa,SAAS,KAAK,QAAQ,KAAK;EACtD,QAAQ,MAAM;EACd,MAAM;CACR,UACQ;EACN,aAAa,UAAU;CACzB;AACF;;AAGA,eAAsB,cACpB,SACA,WACA,SACoB;CACpB,MAAM,QAAQ,MAAM,UAAU,SAAS,OAAO;CAE9C,MAAM,UAAU,YAAY,KAAK;CAKjC,IAAI,CAAC,MAAM,YAAY,MAAM,aAAa,YAAY,YAAY,KAAA,KAAa,gBAAgB,SAAS,cAAc,IAAI,GAAG;EAG3H,QAAQ,MAAM;EACd,MAAM,IAAI,wBACR,kBAAkB,QAAQ,wBAAwB,eAAe,uDACjE,KACF;CACF;CAIA,MAAM,mBAAmB,OAAO,QAAQ,IAAI,6BAA6B,KAAK;CAE9E,MAAM,gBAAgB,QAAQ,cAAc,eAAe,SAAS,QAAQ,WAAW,UAAU,KAAA;CAEjG,OAAO;EACL;EACA,SAAS,QAAQ,WAAW;GAC1B,IAAI;IACF,QAAQ,IAAI,iBAAiB,QAAQ,MAAM;GAC7C,QACM,CAEN;EACF;EACA,SAAS,OAAO,QAAQ,WAAW;GAYjC,IAAI,WAAW,gBACb,OAAO,QAAQ,IAAI,YAAY,QAAQ,MAAM;GAC/C,MAAM,YAAY,qBAAqB,IAAI,MAAM,IAAI,0BAA0B;GAC/E,IAAI;GACJ,IAAI;IACF,OAAQ,MAAM,QAAQ,KAAK,CACzB,QAAQ,IAAI,YAAY,QAAQ,MAAM,GACtC,IAAI,SAAgB,GAAG,WAAW;KAChC,QAAQ,iBAAiB;MACvB,uBAAO,IAAI,MAAM,kBAAkB,OAAO,mBAAmB,UAAU,4BAA4B,CAAC;MACpG,QAAQ,MAAM;KAChB,GAAG,SAAS;KACZ,MAAM,QAAQ;IAChB,CAAC,CACH,CAAC;GACH,UACQ;IACN,aAAa,KAAK;GACpB;EACF;EACA,WAAW,OAAO;GAChB,UAAU,IAAI,EAAE;GAChB,aAAa,UAAU,OAAO,EAAE;EAClC;EACA,aAAa;GACX,cAAc;GACd,QAAQ,MAAM;EAChB;CACF;AACF;;;;AClUA,MAAa,YAAY,UAAqD,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;;AAGjJ,SAAgB,gBAAgB,OAAwB;CACtD,IAAI,MAAM,QAAQ,KAAK,GACrB,OAAO,IAAI,MAAM,IAAI,eAAe,CAAC,CAAC,KAAK,GAAG,EAAE;CAClD,IAAI,SAAS,KAAK,GAChB,OAAO,IAAI,OAAO,KAAK,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,QAAO,MAAK,MAAM,OAAO,KAAA,CAAS,CAAC,CAAC,KAAI,MAAK,GAAG,KAAK,UAAU,CAAC,EAAE,GAAG,gBAAgB,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE;CACnJ,OAAO,KAAK,UAAU,KAAK,KAAK;AAClC;AAEA,SAAgB,UAAU,OAAwB;CAChD,OAAO,WAAW,QAAQ,CAAC,CAAC,OAAO,gBAAgB,KAAK,CAAC,CAAC,CAAC,OAAO,KAAK;AACzE;;;;;;;;;;ACLA,MAAM,sCAA2C,IAAI,IAAY;CAAC;CAAgB;CAAa;CAAe,GAAG;AAAkB,CAAC;;AAGpI,SAAgB,kBAAkB,KAAuC;CACvE,OAAO,CAAC,oBAAoB,GAAG,KAAK,CAAC,oBAAoB,IAAI,GAAG,KAAK,CAAC,IAAI,WAAW,SAAS;AAChG"}