zidane 7.2.5 → 8.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (376) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +34 -6
  3. package/dist/{acp-D-tVyUjw.js → acp-DQDhi2dj.js} +230 -77
  4. package/dist/acp-DQDhi2dj.js.map +1 -0
  5. package/dist/acp-cli.d.ts +1 -1
  6. package/dist/acp-cli.js +9 -66
  7. package/dist/acp-cli.js.map +1 -1
  8. package/dist/acp.d.ts +10 -590
  9. package/dist/acp.d.ts.map +1 -1
  10. package/dist/acp.js +3 -3
  11. package/dist/{agent-D0zZnGbt.js → agent-DSLNmBp0.js} +14401 -13214
  12. package/dist/agent-DSLNmBp0.js.map +1 -0
  13. package/dist/agent.d.ts +1 -1
  14. package/dist/agent.js +3 -2
  15. package/dist/aliasing-lVFbm81n.js +217 -0
  16. package/dist/aliasing-lVFbm81n.js.map +1 -0
  17. package/dist/{anthropic-C2aole0G.js → anthropic-CD00LhUP.js} +1442 -1264
  18. package/dist/anthropic-CD00LhUP.js.map +1 -0
  19. package/dist/artifacts-CV2hUKnL.js.map +1 -1
  20. package/dist/{atomic-write-B7zr1ddF.js → atomic-write-Ijgf2Mhc.js} +13 -3
  21. package/dist/atomic-write-Ijgf2Mhc.js.map +1 -0
  22. package/dist/call-tool-dHlbGOIY.js +70 -0
  23. package/dist/call-tool-dHlbGOIY.js.map +1 -0
  24. package/dist/chat/pure.d.ts +372 -6
  25. package/dist/chat/pure.d.ts.map +1 -1
  26. package/dist/chat/pure.js +35 -244
  27. package/dist/chat/pure.js.map +1 -1
  28. package/dist/{approvals-DKaJZYlm.js → chat-JPJJ8uu5.js} +15879 -14631
  29. package/dist/chat-JPJJ8uu5.js.map +1 -0
  30. package/dist/chat.d.ts +4 -6
  31. package/dist/chat.js +23 -12
  32. package/dist/cli-shared-C-YCaglL.js +159 -0
  33. package/dist/cli-shared-C-YCaglL.js.map +1 -0
  34. package/dist/client-core-BQSyDALT.d.ts +2115 -0
  35. package/dist/client-core-BQSyDALT.d.ts.map +1 -0
  36. package/dist/codemode-worker.d.ts +1 -0
  37. package/dist/codemode-worker.js +155 -0
  38. package/dist/codemode-worker.js.map +1 -0
  39. package/dist/codemode.d.ts +352 -0
  40. package/dist/codemode.d.ts.map +1 -0
  41. package/dist/codemode.js +5 -0
  42. package/dist/connection-Dr-Js4yZ.d.ts +28 -0
  43. package/dist/connection-Dr-Js4yZ.d.ts.map +1 -0
  44. package/dist/connection-loop-gdh22LTI.js +112 -0
  45. package/dist/connection-loop-gdh22LTI.js.map +1 -0
  46. package/dist/context-segments-BHKlagL6.js +1016 -0
  47. package/dist/context-segments-BHKlagL6.js.map +1 -0
  48. package/dist/{context-transport-T_6AYIvy.js → context-transport-DSMTUsK1.js} +3 -3
  49. package/dist/{context-transport-T_6AYIvy.js.map → context-transport-DSMTUsK1.js.map} +1 -1
  50. package/dist/contexts/daytona.d.ts +19 -8
  51. package/dist/contexts/daytona.d.ts.map +1 -1
  52. package/dist/contexts/daytona.js +1 -440
  53. package/dist/contexts/docker.d.ts +36 -7
  54. package/dist/contexts/docker.d.ts.map +1 -1
  55. package/dist/contexts/docker.js +1 -456
  56. package/dist/contexts/e2b.d.ts +68 -13
  57. package/dist/contexts/e2b.d.ts.map +1 -1
  58. package/dist/contexts/e2b.js +1 -382
  59. package/dist/contexts/sandbox.d.ts +1 -1
  60. package/dist/contexts/sandbox.js +5 -0
  61. package/dist/contexts/sandbox.js.map +1 -1
  62. package/dist/{contexts-CRE9pw07.js → contexts-d7UolYot.js} +1059 -524
  63. package/dist/contexts-d7UolYot.js.map +1 -0
  64. package/dist/contexts.d.ts +3 -3
  65. package/dist/contexts.js +1 -1
  66. package/dist/cred-keys-GpBg71cP.js +105 -0
  67. package/dist/cred-keys-GpBg71cP.js.map +1 -0
  68. package/dist/{auth-BG2rVKSt.js → credentials-JttEuRON.js} +55 -206
  69. package/dist/credentials-JttEuRON.js.map +1 -0
  70. package/dist/{cursor-iojRXHF9.js → cursor-CdjaQTBW.js} +3 -3
  71. package/dist/{cursor-iojRXHF9.js.map → cursor-CdjaQTBW.js.map} +1 -1
  72. package/dist/daemon-cli.d.ts +1 -1
  73. package/dist/daemon-cli.js +3 -2
  74. package/dist/daemon-cli.js.map +1 -1
  75. package/dist/daytona-DG3omipZ.js +513 -0
  76. package/dist/daytona-DG3omipZ.js.map +1 -0
  77. package/dist/defaults-Cx3zvDOV.js +23 -0
  78. package/dist/defaults-Cx3zvDOV.js.map +1 -0
  79. package/dist/dispatcher-BMlu2BmZ.js +4941 -0
  80. package/dist/dispatcher-BMlu2BmZ.js.map +1 -0
  81. package/dist/docker-BZhMMJUp.js +727 -0
  82. package/dist/docker-BZhMMJUp.js.map +1 -0
  83. package/dist/e2b-CEVOdRib.js +480 -0
  84. package/dist/e2b-CEVOdRib.js.map +1 -0
  85. package/dist/edit-utils-EGosADZq.js +234 -0
  86. package/dist/edit-utils-EGosADZq.js.map +1 -0
  87. package/dist/environment-8wsKE2Ln.js +214 -0
  88. package/dist/environment-8wsKE2Ln.js.map +1 -0
  89. package/dist/eval-BNcvle_J.js +1595 -0
  90. package/dist/eval-BNcvle_J.js.map +1 -0
  91. package/dist/eval.d.ts +2 -2
  92. package/dist/eval.js +1 -1489
  93. package/dist/executor-Cx5-8yqi.js +621 -0
  94. package/dist/executor-Cx5-8yqi.js.map +1 -0
  95. package/dist/extension-authoring-DyGGmq9V.js +385 -0
  96. package/dist/extension-authoring-DyGGmq9V.js.map +1 -0
  97. package/dist/extensions.d.ts +2 -2
  98. package/dist/extensions.js +3 -3
  99. package/dist/{fetch-url-DX75gpL0.js → fetch-url-Ct2TjDWt.js} +4 -4
  100. package/dist/{fetch-url-DX75gpL0.js.map → fetch-url-Ct2TjDWt.js.map} +1 -1
  101. package/dist/{format-BF745pLL.js → format-C2NQEVUH.js} +39 -2
  102. package/dist/format-C2NQEVUH.js.map +1 -0
  103. package/dist/format-bytes-C7tfc3Zm.js +55 -0
  104. package/dist/format-bytes-C7tfc3Zm.js.map +1 -0
  105. package/dist/headless-C_rNUuYC.js +960 -0
  106. package/dist/headless-C_rNUuYC.js.map +1 -0
  107. package/dist/headless.d.ts +1 -1
  108. package/dist/headless.js +1 -413
  109. package/dist/{history-search-C4bk1Wz_.js → history-search-CcYzF8-0.js} +7 -3
  110. package/dist/history-search-CcYzF8-0.js.map +1 -0
  111. package/dist/history-search-worker.d.ts +1 -1
  112. package/dist/history-search-worker.js +1 -1
  113. package/dist/host-D7NrI03V.js +378 -0
  114. package/dist/host-D7NrI03V.js.map +1 -0
  115. package/dist/host-signals-BcP5QKUD.js +118 -0
  116. package/dist/host-signals-BcP5QKUD.js.map +1 -0
  117. package/dist/identity-CwfO8K-t.js +26 -0
  118. package/dist/identity-CwfO8K-t.js.map +1 -0
  119. package/dist/{index-BgN1T3lk.d.ts → index-BGe1fQT7.d.ts} +10987 -9320
  120. package/dist/index-BGe1fQT7.d.ts.map +1 -0
  121. package/dist/index-BVQsIKGn.d.ts +448 -0
  122. package/dist/index-BVQsIKGn.d.ts.map +1 -0
  123. package/dist/{index-C6NEd5y_.d.ts → index-CHABJd-L.d.ts} +3386 -502
  124. package/dist/index-CHABJd-L.d.ts.map +1 -0
  125. package/dist/{index-C37_ppWv.d.ts → index-D6a7qXpg.d.ts} +2 -3
  126. package/dist/index-D6a7qXpg.d.ts.map +1 -0
  127. package/dist/index.d.ts +6 -6
  128. package/dist/index.js +27 -23
  129. package/dist/{completion-core-BRo86R_L.js → inline-ghost-BVRQeGoL.js} +50 -2
  130. package/dist/inline-ghost-BVRQeGoL.js.map +1 -0
  131. package/dist/ipc/remote.d.ts +313 -0
  132. package/dist/ipc/remote.d.ts.map +1 -0
  133. package/dist/ipc/remote.js +4 -0
  134. package/dist/ipc.d.ts +6 -964
  135. package/dist/ipc.js +403 -4
  136. package/dist/ipc.js.map +1 -0
  137. package/dist/{isolation-Kfoof0MM.d.ts → isolation-D9L650W5.d.ts} +100 -15
  138. package/dist/isolation-D9L650W5.d.ts.map +1 -0
  139. package/dist/json-rpc--HXQti1E.js +350 -0
  140. package/dist/json-rpc--HXQti1E.js.map +1 -0
  141. package/dist/links-j8rED1sR.js +603 -0
  142. package/dist/links-j8rED1sR.js.map +1 -0
  143. package/dist/local-terminal-D8QThwo_.js +252 -0
  144. package/dist/local-terminal-D8QThwo_.js.map +1 -0
  145. package/dist/{logger--C1VQjwJ.js → logger-Gtqlayx8.js} +199 -173
  146. package/dist/logger-Gtqlayx8.js.map +1 -0
  147. package/dist/logs-view-CWG8aUAG.js.map +1 -1
  148. package/dist/{mcp-CgNd-f3F.js → mcp-_wecH9Qe.js} +608 -562
  149. package/dist/mcp-_wecH9Qe.js.map +1 -0
  150. package/dist/mcp.d.ts +2 -2
  151. package/dist/mcp.js +2 -2
  152. package/dist/media-sniff-UKijEaiQ.js.map +1 -1
  153. package/dist/{messages-2jcOA_5R.js → messages-BqiwcD2Q.js} +1017 -1014
  154. package/dist/messages-BqiwcD2Q.js.map +1 -0
  155. package/dist/{oauth-DxHO17JE.js → oauth-Px_pBB9W.js} +5 -5
  156. package/dist/{oauth-DxHO17JE.js.map → oauth-Px_pBB9W.js.map} +1 -1
  157. package/dist/{openai-compat-Dy56weK8.js → openai-compat-CFrpH7uq.js} +432 -589
  158. package/dist/openai-compat-CFrpH7uq.js.map +1 -0
  159. package/dist/orchestration-BCGmB8Ps.js +511 -0
  160. package/dist/orchestration-BCGmB8Ps.js.map +1 -0
  161. package/dist/output/stream-json.d.ts +1 -2
  162. package/dist/output/stream-json.d.ts.map +1 -1
  163. package/dist/output/stream-json.js +1 -1
  164. package/dist/output/terminal.d.ts +1 -2
  165. package/dist/output/terminal.d.ts.map +1 -1
  166. package/dist/output/terminal.js +13 -7
  167. package/dist/output/terminal.js.map +1 -1
  168. package/dist/{plugins-gbI7SBA6.js → plugins-DS7mahzZ.js} +20 -101
  169. package/dist/plugins-DS7mahzZ.js.map +1 -0
  170. package/dist/plugins.d.ts +1 -1
  171. package/dist/plugins.js +1 -2
  172. package/dist/prelude-Cxo4t74B.js +517 -0
  173. package/dist/prelude-Cxo4t74B.js.map +1 -0
  174. package/dist/presets.d.ts +1 -1
  175. package/dist/presets.js +1 -2
  176. package/dist/project-root-B8zADr4o.js +167 -0
  177. package/dist/project-root-B8zADr4o.js.map +1 -0
  178. package/dist/project-user-paths-BSgtrRxl.js +58 -0
  179. package/dist/project-user-paths-BSgtrRxl.js.map +1 -0
  180. package/dist/{prompts-Pqc3JdW_.d.ts → prompts-DYcvqShf.d.ts} +14 -11
  181. package/dist/prompts-DYcvqShf.d.ts.map +1 -0
  182. package/dist/protocol-DnhqqSmE.js +13 -0
  183. package/dist/protocol-DnhqqSmE.js.map +1 -0
  184. package/dist/providers/anthropic.d.ts +2 -2
  185. package/dist/providers/anthropic.js +1 -2
  186. package/dist/providers/arcee.d.ts +1 -1
  187. package/dist/providers/arcee.js +1 -1
  188. package/dist/providers/baseten.d.ts +1 -1
  189. package/dist/providers/baseten.js +1 -1
  190. package/dist/providers/cerebras.d.ts +1 -1
  191. package/dist/providers/cerebras.js +3 -2
  192. package/dist/providers/cerebras.js.map +1 -1
  193. package/dist/providers/local.d.ts +1 -1
  194. package/dist/providers/local.js +1 -1
  195. package/dist/providers/openai-compat.d.ts +1 -1
  196. package/dist/providers/openai-compat.js +1 -2
  197. package/dist/providers/openai.d.ts +1 -1
  198. package/dist/providers/openai.js +15 -12
  199. package/dist/providers/openai.js.map +1 -1
  200. package/dist/providers/openrouter.d.ts +1 -1
  201. package/dist/providers/openrouter.js +3 -2
  202. package/dist/providers/openrouter.js.map +1 -1
  203. package/dist/providers/xai.d.ts +1 -1
  204. package/dist/providers/xai.js +3 -3
  205. package/dist/{providers-BVhnFyiY.js → providers-XUR7F4Hi.js} +4 -4
  206. package/dist/{providers-BVhnFyiY.js.map → providers-XUR7F4Hi.js.map} +1 -1
  207. package/dist/providers.d.ts +1 -1
  208. package/dist/providers.js +4 -4
  209. package/dist/registry-D6ShBWJU.js +5234 -0
  210. package/dist/registry-D6ShBWJU.js.map +1 -0
  211. package/dist/remote-hosts-BtA_9ZGp.js +97 -0
  212. package/dist/remote-hosts-BtA_9ZGp.js.map +1 -0
  213. package/dist/restate.d.ts +2 -3
  214. package/dist/restate.d.ts.map +1 -1
  215. package/dist/restate.js +631 -572
  216. package/dist/restate.js.map +1 -1
  217. package/dist/run-summary-CklLiZ4y.js +288 -0
  218. package/dist/run-summary-CklLiZ4y.js.map +1 -0
  219. package/dist/{sandbox-BH0WQkXn.d.ts → sandbox-C5dR5DwQ.d.ts} +6 -3
  220. package/dist/sandbox-C5dR5DwQ.d.ts.map +1 -0
  221. package/dist/session/sqlite.d.ts +1 -2
  222. package/dist/session/sqlite.d.ts.map +1 -1
  223. package/dist/session/sqlite.js +1 -616
  224. package/dist/session-factory-BUGY5P40.js +1576 -0
  225. package/dist/session-factory-BUGY5P40.js.map +1 -0
  226. package/dist/{session-BqRP1hS7.js → session-xh9JXu6i.js} +94 -52
  227. package/dist/session-xh9JXu6i.js.map +1 -0
  228. package/dist/session.d.ts +1 -1
  229. package/dist/session.js +2 -2
  230. package/dist/settings-keys-Ckf29NeM.js +677 -0
  231. package/dist/settings-keys-Ckf29NeM.js.map +1 -0
  232. package/dist/shell-path-Dqaoow2J.js +412 -0
  233. package/dist/shell-path-Dqaoow2J.js.map +1 -0
  234. package/dist/{skills-BC3dodWp.js → skills-DKqZJm4X.js} +430 -470
  235. package/dist/skills-DKqZJm4X.js.map +1 -0
  236. package/dist/skills.d.ts +2 -2
  237. package/dist/skills.js +1 -2
  238. package/dist/source-mPExaUm8.js +381 -0
  239. package/dist/source-mPExaUm8.js.map +1 -0
  240. package/dist/sqlite-DV1DQzN2.js +698 -0
  241. package/dist/sqlite-DV1DQzN2.js.map +1 -0
  242. package/dist/{src-CkNQKFKr.js → src-BRMYRJib.js} +903 -1121
  243. package/dist/src-BRMYRJib.js.map +1 -0
  244. package/dist/{stdio-DPpBDPx5.js → stdio-C6YyoW3I.js} +4 -4
  245. package/dist/{stdio-DPpBDPx5.js.map → stdio-C6YyoW3I.js.map} +1 -1
  246. package/dist/{stdio-loader-Bbx19dMZ.js → stdio-loader-C830Vg-Z.js} +4 -4
  247. package/dist/{stdio-loader-Bbx19dMZ.js.map → stdio-loader-C830Vg-Z.js.map} +1 -1
  248. package/dist/system-prompt-MNVHatSD.d.ts.map +1 -1
  249. package/dist/timeout-DEaqslLO.d.ts.map +1 -1
  250. package/dist/todo-edits-Dn251YUP.js +1790 -0
  251. package/dist/todo-edits-Dn251YUP.js.map +1 -0
  252. package/dist/{turn-operations-DrbJlpq9.js → tool-formatters-IQFDrdrs.js} +1456 -2120
  253. package/dist/tool-formatters-IQFDrdrs.js.map +1 -0
  254. package/dist/tool-state-Dku6YqAB.js +989 -0
  255. package/dist/tool-state-Dku6YqAB.js.map +1 -0
  256. package/dist/tools/fetch-url.d.ts +1 -2
  257. package/dist/tools/fetch-url.d.ts.map +1 -1
  258. package/dist/tools/fetch-url.js +1 -2
  259. package/dist/tools/prompts.d.ts +1 -1
  260. package/dist/tools/prompts.js +7 -7
  261. package/dist/tools/prompts.js.map +1 -1
  262. package/dist/tools/web-search.d.ts +1 -2
  263. package/dist/tools/web-search.d.ts.map +1 -1
  264. package/dist/tools/web-search.js +2 -2
  265. package/dist/tools/web-search.js.map +1 -1
  266. package/dist/tools-_DnT3AGM.js +578 -0
  267. package/dist/tools-_DnT3AGM.js.map +1 -0
  268. package/dist/tools.d.ts +3 -3
  269. package/dist/tools.js +4 -2
  270. package/dist/tui.d.ts +534 -517
  271. package/dist/tui.d.ts.map +1 -1
  272. package/dist/tui.js +34933 -27243
  273. package/dist/tui.js.map +1 -1
  274. package/dist/turn-operations-B8sokwi5.js +333 -0
  275. package/dist/turn-operations-B8sokwi5.js.map +1 -0
  276. package/dist/turn-operations-DQX5ZZni.d.ts +3089 -0
  277. package/dist/turn-operations-DQX5ZZni.d.ts.map +1 -0
  278. package/dist/types-C7ZFOztE.d.ts +132 -0
  279. package/dist/types-C7ZFOztE.d.ts.map +1 -0
  280. package/dist/types-CH5XpIHw.js +114 -0
  281. package/dist/types-CH5XpIHw.js.map +1 -0
  282. package/dist/{types-CWgENVLY.js → types-Cu0ZGDu9.js} +10 -6
  283. package/dist/types-Cu0ZGDu9.js.map +1 -0
  284. package/dist/types-IqegbJEE.d.ts +624 -0
  285. package/dist/types-IqegbJEE.d.ts.map +1 -0
  286. package/dist/types.d.ts +4 -4
  287. package/dist/types.js +1 -1
  288. package/dist/url-D8HCl65b.js +1259 -0
  289. package/dist/url-D8HCl65b.js.map +1 -0
  290. package/dist/wasm-BVT-j5cl.js +33 -0
  291. package/dist/wasm-BVT-j5cl.js.map +1 -0
  292. package/dist/workspace-exec-stream-SV2R9d5S.js +355 -0
  293. package/dist/workspace-exec-stream-SV2R9d5S.js.map +1 -0
  294. package/dist/ws-CIHMvlSh.js +952 -0
  295. package/dist/ws-CIHMvlSh.js.map +1 -0
  296. package/dist/ws-client-N7NxzvQp.js +230 -0
  297. package/dist/ws-client-N7NxzvQp.js.map +1 -0
  298. package/dist/{xai-CazjStOK.js → xai-CvJTeLrI.js} +165 -5
  299. package/dist/xai-CvJTeLrI.js.map +1 -0
  300. package/dist/xdg-zweed0-t.js +117 -0
  301. package/dist/xdg-zweed0-t.js.map +1 -0
  302. package/docs/ACP.md +52 -0
  303. package/docs/ARCHITECTURE.md +103 -6
  304. package/docs/ARTIFACTS.md +8 -4
  305. package/docs/CHAT.md +165 -14
  306. package/docs/EXECUTION_CONTEXT.md +8 -0
  307. package/docs/EXTENSIONS.md +123 -2
  308. package/docs/HEADLESS.md +2 -0
  309. package/docs/IPC.md +775 -64
  310. package/docs/MACHINES.md +456 -0
  311. package/docs/PANELS.md +3 -0
  312. package/docs/README.md +4 -0
  313. package/docs/RESTATE.md +3 -2
  314. package/docs/RUN_IN_BACKGROUND.md +10 -2
  315. package/docs/SERVER.md +1085 -0
  316. package/docs/SKILL.md +6 -1
  317. package/docs/TERMINAL.md +75 -0
  318. package/docs/TUI.md +65 -14
  319. package/package.json +58 -26
  320. package/scripts/eval.ts +4 -0
  321. package/dist/acp-D-tVyUjw.js.map +0 -1
  322. package/dist/agent-D0zZnGbt.js.map +0 -1
  323. package/dist/anthropic-C2aole0G.js.map +0 -1
  324. package/dist/approvals-DKaJZYlm.js.map +0 -1
  325. package/dist/atomic-write-B7zr1ddF.js.map +0 -1
  326. package/dist/auth-BG2rVKSt.js.map +0 -1
  327. package/dist/completion-core-BRo86R_L.js.map +0 -1
  328. package/dist/contexts/daytona.js.map +0 -1
  329. package/dist/contexts/docker.js.map +0 -1
  330. package/dist/contexts/e2b.js.map +0 -1
  331. package/dist/contexts-CRE9pw07.js.map +0 -1
  332. package/dist/eval.js.map +0 -1
  333. package/dist/format-BF745pLL.js.map +0 -1
  334. package/dist/glob-DluQFSw1.js +0 -270
  335. package/dist/glob-DluQFSw1.js.map +0 -1
  336. package/dist/headless.js.map +0 -1
  337. package/dist/history-search-C4bk1Wz_.js.map +0 -1
  338. package/dist/index-BgN1T3lk.d.ts.map +0 -1
  339. package/dist/index-C37_ppWv.d.ts.map +0 -1
  340. package/dist/index-C6NEd5y_.d.ts.map +0 -1
  341. package/dist/ipc-BKVIIOqH.js +0 -331
  342. package/dist/ipc-BKVIIOqH.js.map +0 -1
  343. package/dist/ipc.d.ts.map +0 -1
  344. package/dist/isolation-Kfoof0MM.d.ts.map +0 -1
  345. package/dist/json-rpc-rSWMUh9b.js +0 -192
  346. package/dist/json-rpc-rSWMUh9b.js.map +0 -1
  347. package/dist/logger--C1VQjwJ.js.map +0 -1
  348. package/dist/mcp-CgNd-f3F.js.map +0 -1
  349. package/dist/messages-2jcOA_5R.js.map +0 -1
  350. package/dist/openai-compat-Dy56weK8.js.map +0 -1
  351. package/dist/output-cap-C9zukcCj.js +0 -100
  352. package/dist/output-cap-C9zukcCj.js.map +0 -1
  353. package/dist/panels-B6gRk4bf.js +0 -789
  354. package/dist/panels-B6gRk4bf.js.map +0 -1
  355. package/dist/plugins-gbI7SBA6.js.map +0 -1
  356. package/dist/prompts-Pqc3JdW_.d.ts.map +0 -1
  357. package/dist/run-summary-BU_NgwUT.js +0 -269
  358. package/dist/run-summary-BU_NgwUT.js.map +0 -1
  359. package/dist/sandbox-BH0WQkXn.d.ts.map +0 -1
  360. package/dist/session/sqlite.js.map +0 -1
  361. package/dist/session-BqRP1hS7.js.map +0 -1
  362. package/dist/shell-path-DfdXrGg9.js +0 -1549
  363. package/dist/shell-path-DfdXrGg9.js.map +0 -1
  364. package/dist/skills-BC3dodWp.js.map +0 -1
  365. package/dist/src-CkNQKFKr.js.map +0 -1
  366. package/dist/todo-edits-UOwgxGKu.js +0 -528
  367. package/dist/todo-edits-UOwgxGKu.js.map +0 -1
  368. package/dist/tool-formatters-DoRLnfuD.d.ts +0 -759
  369. package/dist/tool-formatters-DoRLnfuD.d.ts.map +0 -1
  370. package/dist/transcript-anchors-BeudMbXx.d.ts +0 -1762
  371. package/dist/transcript-anchors-BeudMbXx.d.ts.map +0 -1
  372. package/dist/turn-operations-C8bMBDl_.d.ts +0 -1258
  373. package/dist/turn-operations-C8bMBDl_.d.ts.map +0 -1
  374. package/dist/turn-operations-DrbJlpq9.js.map +0 -1
  375. package/dist/types-CWgENVLY.js.map +0 -1
  376. package/dist/xai-CazjStOK.js.map +0 -1
@@ -1,1549 +0,0 @@
1
- import { Fn as serializedPayloadBytes, Pn as createExtensionBus, ct as discoverAndBuildExtensionRegistry, st as createExtensionHud, vt as createExtensionHostRuntimeBridge } from "./agent-D0zZnGbt.js";
2
- import { S as resolveInlineSuggestion, b as createPathAutocompleteProvider } from "./src-CkNQKFKr.js";
3
- import { l as normalizeArtifactInput } from "./artifacts-CV2hUKnL.js";
4
- import { t as writeFileAtomic } from "./atomic-write-B7zr1ddF.js";
5
- import { p as resolveStorageDirs } from "./plugins-gbI7SBA6.js";
6
- import { a as successResponse, i as errorResponse, n as JsonRpcRemoteError, r as createJsonRpcConnection } from "./json-rpc-rSWMUh9b.js";
7
- import { Vt as isMainSession } from "./turn-operations-DrbJlpq9.js";
8
- import { c as searchSessionHistoryIndexAsync, n as buildSessionSearchIndexAsync, u as searchSessionIndexAsync } from "./history-search-C4bk1Wz_.js";
9
- import { Bn as resolveConfig, Di as deriveSessionTitle, Ft as toTodosSnapshot, Jt as createFileMcpCredentialStore, Kt as sessionModelFallbacks, Oi as eventsFromTurns, Pt as createChatHost, fn as DEFAULT_SETTINGS, gn as SETTINGS_TOGGLES, yn as enforceSettingsInvariants } from "./approvals-DKaJZYlm.js";
10
- import { h as BUILTIN_PROVIDERS, n as applyApiKeyEnv, r as credentialsPath } from "./auth-BG2rVKSt.js";
11
- import { basename, delimiter, dirname, join } from "node:path";
12
- import { chmodSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync, unlinkSync } from "node:fs";
13
- import { userInfo } from "node:os";
14
- import { spawn, spawnSync } from "node:child_process";
15
- import { fileURLToPath } from "node:url";
16
- import { connect, createServer } from "node:net";
17
- import process$1 from "node:process";
18
- //#endregion
19
- //#region src/version.ts
20
- /**
21
- * The version of the zidane code this process is running — `package.json`
22
- * inlined at build time (Bun `--compile`, tsdown for `dist/`, and Vite for
23
- * the GUI main all fold JSON imports into the bundle, so this never reads
24
- * the filesystem at runtime and cannot report a NEIGHBOUR package's version
25
- * the way a `require('../package.json')` from a bundled chunk can).
26
- *
27
- * Used by the daemon handshake: a client running newer code than the daemon
28
- * retires it, so an upgrade can never leave windows silently executing on a
29
- * process started from the previous release.
30
- */
31
- const ZIDANE_VERSION = "7.2.5";
32
- /**
33
- * Compare two dotted versions (`7.0.19`, `7.1.0-beta.1`): negative when `a`
34
- * is older, positive when newer, 0 when equal. Pre-release tags are ignored
35
- * — same release train, same code as far as the daemon fence is concerned.
36
- * Unparseable input compares equal (never fences on garbage).
37
- */
38
- function compareVersions(a, b) {
39
- const pa = parse(a);
40
- const pb = parse(b);
41
- if (!pa || !pb) return 0;
42
- for (let i = 0; i < 3; i++) {
43
- const d = (pa[i] ?? 0) - (pb[i] ?? 0);
44
- if (d !== 0) return d;
45
- }
46
- return 0;
47
- }
48
- function parse(v) {
49
- const m = /^v?(\d+)\.(\d+)\.(\d+)/.exec(v.trim());
50
- return m ? [
51
- Number(m[1]),
52
- Number(m[2]),
53
- Number(m[3])
54
- ] : null;
55
- }
56
- //#endregion
57
- //#region src/ipc/daemon/lifecycle.ts
58
- /**
59
- * Daemon lifecycle: socket-path resolution, liveness probing, stale-socket
60
- * cleanup, and spawn-on-demand.
61
- *
62
- * The socket lives in a dedicated daemon subdir of the resolved state dir
63
- * (`~/.zidane/daemon/daemon.sock` by default, honoring the same
64
- * `ZIDANE_STORAGE_DIR` / `ZIDANE_PREFIX` env knobs every other surface
65
- * uses), overridable via `ZIDANE_DAEMON_SOCKET` for parallel installs and
66
- * tests.
67
- */
68
- /**
69
- * Build fingerprint for the handshake — the mtime of this module's file
70
- * at import time. Client and daemon load the same file from disk, so a
71
- * daemon spawned before a rebuild (or a source edit in dev) reports a
72
- * different id than a freshly-started client, and the client drains +
73
- * respawns it. This closes the "same protocol version, different code"
74
- * gap that a hand-bumped version constant can't: during development the
75
- * daemon process is frozen at spawn while the tree keeps moving.
76
- *
77
- * Compiled binaries (`/$bunfs/…` virtual paths) can't be stat'ed and
78
- * report `'unknown'`; the check is skipped when EITHER side is unknown,
79
- * so released builds rely on `IPC_PROTOCOL_VERSION` alone — correct,
80
- * since their code only changes when the version does.
81
- */
82
- const IPC_BUILD_ID = (() => {
83
- try {
84
- const selfPath = fileURLToPath(import.meta.url);
85
- const ipcRoot = dirname(dirname(selfPath));
86
- if (!existsSync(join(ipcRoot, "protocol.ts"))) return String(Math.floor(statSync(selfPath).mtimeMs));
87
- const srcRoot = dirname(ipcRoot);
88
- let newest = 0;
89
- const walk = (dir) => {
90
- for (const entry of readdirSync(dir, { withFileTypes: true })) {
91
- const full = join(dir, entry.name);
92
- if (entry.isDirectory()) walk(full);
93
- else newest = Math.max(newest, statSync(full).mtimeMs);
94
- }
95
- };
96
- try {
97
- walk(srcRoot);
98
- } catch {
99
- newest = statSync(selfPath).mtimeMs;
100
- }
101
- return String(Math.floor(newest));
102
- } catch {
103
- return "unknown";
104
- }
105
- })();
106
- /**
107
- * Socket file name. Dev builds (`ZIDANE_DEV=1`, set by every `dev` script
108
- * in the repo) get their OWN socket so a checkout's TUI, GUI and `zidane
109
- * daemon` pair up among themselves and never attach to — or get refused by
110
- * — the installed daemon. Without this, a protocol bump in the working
111
- * tree turned the dev GUI's dot red against the stable daemon, and a dev
112
- * daemon could drain the one the installed TUI relies on.
113
- */
114
- function daemonSocketName(env = process.env) {
115
- return env.ZIDANE_DEV && env.ZIDANE_DEV !== "0" ? "dev.sock" : "daemon.sock";
116
- }
117
- function defaultSocketPath() {
118
- const explicit = process.env.ZIDANE_DAEMON_SOCKET;
119
- if (explicit) return explicit;
120
- return join(resolveStorageDirs({ ...process.env.ZIDANE_PREFIX !== void 0 ? { prefix: process.env.ZIDANE_PREFIX } : {} }).stateDir, "daemon", daemonSocketName());
121
- }
122
- /**
123
- * Pre-v6 socket location for the given (v6) socket path, or null when the
124
- * path isn't the default `<stateDir>/daemon/daemon.sock` layout (explicit
125
- * `ZIDANE_DAEMON_SOCKET` users never had a migration to run). A daemon
126
- * still serving the old path would be ORPHANED by the move — new clients
127
- * never probe it, and a service-style `--idle-exit 0` daemon would hold
128
- * agents and run-guard markers against the same sessions.db forever —
129
- * so daemon startup probes this path and drains any survivor.
130
- */
131
- function legacySocketPath(socketPath) {
132
- const dir = dirname(socketPath);
133
- if (basename(socketPath) !== "daemon.sock" || basename(dir) !== "daemon") return null;
134
- return join(dirname(dir), "daemon.sock");
135
- }
136
- /**
137
- * Spawn command that re-enters the CURRENT zidane program as `… daemon`.
138
- *
139
- * Three launch shapes:
140
- * - compiled Bun binary — `Bun.main` is the virtual `/$bunfs/…` entry the
141
- * binary self-inserts as argv[1], so the spawn must NOT repeat it
142
- * (verified: repeating it makes the child parse the junk path as its
143
- * subcommand and boot the full TUI instead of the daemon).
144
- * - dev (`bun run cli.ts`) — the script path must ride along.
145
- * - Node hosts (no `Bun` global) — fall back to the published bin.
146
- */
147
- function selfDaemonSpawnCommand() {
148
- const bunMain = globalThis.Bun?.main;
149
- if (bunMain?.startsWith("/$bunfs")) return [process.execPath, "daemon"];
150
- if (bunMain && /(?:^|[/\\])cli\.[cm]?[jt]s$/.test(bunMain)) return [
151
- process.execPath,
152
- bunMain,
153
- "daemon"
154
- ];
155
- return ["zidane-daemon"];
156
- }
157
- /**
158
- * True when something accepts connections on `socketPath`. Distinguishes a
159
- * live daemon from a stale socket file left by a crashed one.
160
- */
161
- function probeSocket(socketPath, timeoutMs = 1e3) {
162
- return new Promise((resolve) => {
163
- try {
164
- if (!existsSync(socketPath) || !statSync(socketPath).isSocket()) {
165
- resolve(false);
166
- return;
167
- }
168
- } catch {
169
- resolve(false);
170
- return;
171
- }
172
- let socket;
173
- try {
174
- socket = connect(socketPath);
175
- } catch {
176
- resolve(false);
177
- return;
178
- }
179
- const done = (alive) => {
180
- socket.destroy();
181
- resolve(alive);
182
- };
183
- socket.once("connect", () => done(true));
184
- socket.once("error", () => done(false));
185
- socket.setTimeout(timeoutMs, () => done(false));
186
- });
187
- }
188
- /**
189
- * Make sure a daemon is listening, spawning one if needed. Resolves with
190
- * the socket path once a connection succeeds; rejects when the daemon
191
- * failed to come up within `timeoutMs`.
192
- */
193
- const pendingStarts = /* @__PURE__ */ new Map();
194
- function ensureDaemonRunning(options = {}) {
195
- const socketPath = options.socketPath ?? defaultSocketPath();
196
- const pending = pendingStarts.get(socketPath);
197
- if (pending) return pending;
198
- const start = startDaemon({
199
- ...options,
200
- socketPath
201
- }).finally(() => pendingStarts.delete(socketPath));
202
- pendingStarts.set(socketPath, start);
203
- return start;
204
- }
205
- async function startDaemon(options) {
206
- const socketPath = options.socketPath;
207
- if (await probeSocket(socketPath)) return socketPath;
208
- const [cmd, ...args] = options.spawnCommand ?? ["zidane-daemon"];
209
- const child = spawn(cmd, args, {
210
- detached: true,
211
- stdio: "ignore",
212
- env: {
213
- ...process.env,
214
- ZIDANE_DAEMON_SOCKET: socketPath
215
- }
216
- });
217
- let spawnError;
218
- child.once("error", (err) => {
219
- spawnError = err;
220
- });
221
- child.unref();
222
- const deadline = Date.now() + (options.timeoutMs ?? 8e3);
223
- for (;;) {
224
- if (spawnError !== void 0) throw new Error(`Failed to spawn zidane daemon (${cmd}): ${spawnError.message}`);
225
- if (await probeSocket(socketPath)) return socketPath;
226
- if (Date.now() > deadline) throw new Error(`zidane daemon did not come up on ${socketPath} within ${options.timeoutMs ?? 8e3}ms.`);
227
- await new Promise((r) => setTimeout(r, 150));
228
- }
229
- }
230
- //#endregion
231
- //#region src/ipc/protocol.ts
232
- /**
233
- * v6 (changes since v5):
234
- * - `event` signals carry an optional `echo` flag marking host-generated
235
- * SEND/STEER echoes of the user's own message.
236
- * - `chat.pushQueued` result gained the `'queued'` delivered variant.
237
- * - `sessions.setModel` now honors `fallbacks`: it persists the canonical
238
- * `metadata.modelChain` and CLEARS a previously persisted chain when
239
- * omitted/empty. It also accepts `effort` / `modelOptions` and resets
240
- * both when omitted (a pick is atomic — no stale per-model knobs).
241
- * - additive: `extension.emit` notification + `extension:signal` fan-out
242
- * (the permission-gated per-extension cross-window bus, `ctx.bus`).
243
- * Older daemons ignore the unknown notification; older clients drop the
244
- * unknown signal kind — no version bump needed.
245
- * - additive: `extension.emit` / `extension:signal` carry an optional
246
- * `nonce` (the emitter's per-process random id) so receivers dedupe on
247
- * `(extensionId, nonce, seq)` instead of the collision-prone
248
- * `(extensionId, seq)`. Older peers omit it and fall back to the
249
- * seq-only key — no version bump needed.
250
- * - `SessionRow.modelFallbacks` is now populated from the session's
251
- * persisted `metadata.modelChain`.
252
- * - Default socket path moved from `<stateDir>/daemon.sock` to the
253
- * dedicated `<stateDir>/daemon/daemon.sock` (dir chmod'd 0700) so the
254
- * daemon can harden its socket dir without touching shared state files.
255
- * - ADDITIVE (no version bump — older daemons answer "method not
256
- * found", clients degrade to local compute): `suggest.resolve` RPC
257
- * resolves inline ghost-text autocomplete daemon-side, and the
258
- * `suggest:changed` signal fans the result out to every OTHER peer
259
- * on the session so mirroring windows paint the same ghost without
260
- * recomputing.
261
- * - ADDITIVE (no version bump — optional field, older daemons simply
262
- * omit it and clients fall back to the single `suggestion`):
263
- * `suggest.resolve` results and `suggest:changed` signals carry the
264
- * resolver's full ordered `candidates` list so daemon mode keeps
265
- * ↑/↓ candidate rotation instead of degrading to one suggestion.
266
- * - ADDITIVE (no version bump — `optional()` swallows "method not
267
- * found" on an older daemon, which then simply keeps its stale
268
- * registries as before): `runtime.reload` RPC drops the daemon's
269
- * cached extension registries and retires live agents after a window
270
- * reloaded its extensions.
271
- */
272
- const IPC_PROTOCOL_VERSION = 9;
273
- /**
274
- * JSON-RPC error codes specific to the zidane daemon. Lives here (not in
275
- * `daemon/server.ts`) so clients can import the codes without pulling the
276
- * server's module graph.
277
- */
278
- const IpcErrorCode = {
279
- VersionMismatch: -32010,
280
- NotHandshaken: -32011
281
- };
282
- //#endregion
283
- //#region src/ipc/client.ts
284
- function daemonRelease(hello) {
285
- for (const value of [hello.codeVersion, hello.appVersion]) {
286
- if (typeof value !== "string") continue;
287
- 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());
288
- if (match) return match[1];
289
- }
290
- }
291
- var IpcVersionMismatchError = class extends Error {
292
- daemon;
293
- constructor(message, daemon) {
294
- super(message);
295
- this.daemon = daemon;
296
- this.name = "IpcVersionMismatchError";
297
- }
298
- };
299
- async function connectIpcClient(options) {
300
- const socket = await new Promise((resolvePromise, reject) => {
301
- const s = connect(options.socketPath);
302
- s.once("connect", () => {
303
- s.off("error", reject);
304
- resolvePromise(s);
305
- });
306
- s.once("error", reject);
307
- });
308
- const listeners = /* @__PURE__ */ new Set();
309
- let closed = false;
310
- const connection = createJsonRpcConnection({
311
- input: socket,
312
- output: socket,
313
- onRequest: (message) => errorResponse(message.id, -32601, "Clients do not accept requests."),
314
- onNotification: (message) => {
315
- if (message.method !== "ipc.signal") return;
316
- const signal = message.params;
317
- if (!signal) return;
318
- for (const cb of listeners) cb(signal);
319
- }
320
- });
321
- connection.start();
322
- const close = () => {
323
- if (closed) return;
324
- closed = true;
325
- connection.close();
326
- socket.destroy();
327
- };
328
- socket.on("close", () => {
329
- if (closed) return;
330
- closed = true;
331
- connection.close();
332
- options.onClose?.();
333
- });
334
- socket.on("error", () => {});
335
- const HELLO_TIMEOUT_MS = 5e3;
336
- const REQUEST_TIMEOUT_MS = 3e4;
337
- const LONG_REQUEST_TIMEOUT_MS = 600 * 1e3;
338
- /** RPCs that legitimately run long — full compaction, index-backed cross-session search. */
339
- const LONG_REQUEST_METHODS = /* @__PURE__ */ new Set([
340
- "sessions.compact",
341
- "history.searchAll",
342
- "history.searchSession"
343
- ]);
344
- let helloTimer;
345
- let hello;
346
- try {
347
- hello = await Promise.race([connection.sendRequest("ipc.hello", {
348
- protocolVersion: 9,
349
- appVersion: options.appVersion ?? "dev",
350
- pid: process.pid,
351
- buildId: options.drainOnMismatch === false ? "unknown" : IPC_BUILD_ID,
352
- codeVersion: ZIDANE_VERSION
353
- }), new Promise((_, reject) => {
354
- helloTimer = setTimeout(() => reject(/* @__PURE__ */ new Error(`Daemon handshake timed out after ${HELLO_TIMEOUT_MS}ms on ${options.socketPath}.`)), HELLO_TIMEOUT_MS);
355
- })]);
356
- } catch (err) {
357
- if (err instanceof JsonRpcRemoteError && err.code === IpcErrorCode.VersionMismatch) {
358
- const daemon = err.data?.daemon;
359
- const daemonIsOlderRelease = typeof daemon?.codeVersion === "string" && compareVersions(daemon.codeVersion, ZIDANE_VERSION) < 0;
360
- const release = daemon && daemonRelease(daemon);
361
- if (!(release !== void 0 && compareVersions(release, ZIDANE_VERSION) > 0) && (options.drainOnMismatch !== false || daemonIsOlderRelease)) await Promise.race([connection.sendRequest("daemon.shutdown", {}).catch(() => void 0), new Promise((resolve) => setTimeout(resolve, 1500))]);
362
- close();
363
- throw new IpcVersionMismatchError(err.message, daemon);
364
- }
365
- close();
366
- throw err;
367
- } finally {
368
- clearTimeout(helloTimer);
369
- }
370
- const release = daemonRelease(hello);
371
- if (release !== void 0 && compareVersions(release, ZIDANE_VERSION) < 0) {
372
- close();
373
- throw new IpcVersionMismatchError(`Daemon release ${release} is older than client ${ZIDANE_VERSION}. Restart the daemon when active runs have finished.`, hello);
374
- }
375
- return {
376
- hello,
377
- notify: (method, params) => {
378
- try {
379
- connection.sendNotification(method, params);
380
- } catch {}
381
- },
382
- request: async (method, params) => {
383
- const timeoutMs = LONG_REQUEST_METHODS.has(method) ? LONG_REQUEST_TIMEOUT_MS : REQUEST_TIMEOUT_MS;
384
- let timer;
385
- try {
386
- return await Promise.race([connection.sendRequest(method, params), new Promise((_, reject) => {
387
- timer = setTimeout(() => {
388
- reject(/* @__PURE__ */ new Error(`Daemon request ${method} timed out after ${timeoutMs}ms — tearing the connection down.`));
389
- socket.destroy();
390
- }, timeoutMs);
391
- timer.unref?.();
392
- })]);
393
- } finally {
394
- clearTimeout(timer);
395
- }
396
- },
397
- onSignal: (cb) => {
398
- listeners.add(cb);
399
- return () => listeners.delete(cb);
400
- },
401
- close
402
- };
403
- }
404
- /**
405
- * One-call convenience for windows: make sure a daemon is up (spawning if
406
- * needed), connect, and — when the running daemon speaks an older protocol
407
- * — drain it and spawn a fresh one before retrying once.
408
- */
409
- async function connectOrSpawnDaemon(options = {}) {
410
- const socketPath = await ensureDaemonRunning(options);
411
- try {
412
- return await connectIpcClient({
413
- ...options,
414
- socketPath
415
- });
416
- } catch (err) {
417
- if (!(err instanceof IpcVersionMismatchError)) throw err;
418
- const drainDeadline = Date.now() + 2e3;
419
- while (await probeSocket(socketPath)) {
420
- if (Date.now() > drainDeadline) break;
421
- await new Promise((r) => setTimeout(r, 100));
422
- }
423
- const retryPath = await ensureDaemonRunning(options);
424
- return connectIpcClient({
425
- ...options,
426
- socketPath: retryPath
427
- });
428
- }
429
- }
430
- //#endregion
431
- //#region src/ipc/daemon/environment.ts
432
- /**
433
- * File-backed pending-approvals persistence (`pending-approvals.json` next
434
- * to `state.json`). Small, rewritten atomically enough for its purpose —
435
- * the queue holds at most a handful of rows.
436
- */
437
- function createFileApprovalsStore(path) {
438
- function read() {
439
- if (!existsSync(path)) return [];
440
- try {
441
- const parsed = JSON.parse(readFileSync(path, "utf8"));
442
- return Array.isArray(parsed) ? parsed : [];
443
- } catch {
444
- return [];
445
- }
446
- }
447
- function write(rows) {
448
- if (rows.length === 0) {
449
- try {
450
- unlinkSync(path);
451
- } catch {}
452
- return;
453
- }
454
- mkdirSync(dirname(path), { recursive: true });
455
- writeFileAtomic(path, JSON.stringify(rows, null, 2));
456
- }
457
- return {
458
- insert(request) {
459
- const rows = read().filter((r) => r.id !== request.id);
460
- rows.push(request);
461
- write(rows);
462
- },
463
- delete(id) {
464
- write(read().filter((r) => r.id !== id));
465
- },
466
- clear() {
467
- write([]);
468
- },
469
- list() {
470
- return read();
471
- }
472
- };
473
- }
474
- async function createDaemonEnvironment(options) {
475
- const { createTuiStore } = await import("./session/sqlite.js");
476
- const config = resolveConfig({
477
- ...options.cwd !== void 0 ? { cwd: options.cwd } : {},
478
- store: (resolved) => createTuiStore(resolved.db)
479
- });
480
- const store = config.store;
481
- if (config.paths.projectDir) process.stderr.write(`[zidane-daemon] warning: project-DB mode is active — this daemon is bound to ${config.paths.db}. Windows opened in other projects will share this project's sessions. Run a per-project daemon (ZIDANE_DAEMON_SOCKET) to isolate them.\n`);
482
- const readSettings = () => ({
483
- ...DEFAULT_SETTINGS,
484
- ...config.initialSettings,
485
- ...config.stateStore.load().settings ?? {}
486
- });
487
- /**
488
- * Fields the invariant forced (only ever `false`), so the stored file records
489
- * them too — otherwise a later read of `state.settings` would resurrect the
490
- * value the invariant just rejected.
491
- */
492
- const pickInvariantFields = (merged, patch) => {
493
- const out = {};
494
- for (const row of SETTINGS_TOGGLES) if (row.requires && merged[row.key] === false && patch[row.key] !== false) out[row.key] = false;
495
- return out;
496
- };
497
- const writeSettings = (patch) => {
498
- const state = config.stateStore.load();
499
- const merged = enforceSettingsInvariants({
500
- ...DEFAULT_SETTINGS,
501
- ...config.initialSettings,
502
- ...state.settings ?? {},
503
- ...patch
504
- });
505
- const next = {
506
- ...state.settings ?? {},
507
- ...patch,
508
- ...pickInvariantFields(merged, patch)
509
- };
510
- config.stateStore.save({
511
- ...state,
512
- settings: next
513
- });
514
- return merged;
515
- };
516
- const hud = createExtensionHud();
517
- hud.subscribe(() => {
518
- const state = hud.getState();
519
- options.broadcast({
520
- kind: "hud:state",
521
- statuses: Object.fromEntries(Object.entries(state.statuses).map(([name, s]) => [name, {
522
- text: s.text,
523
- loader: s.loader
524
- }])),
525
- banners: Object.fromEntries(Object.entries(state.banners).map(([name, lines]) => [name, [...lines]]))
526
- });
527
- });
528
- hud.onNotify((n) => {
529
- options.broadcast({
530
- kind: "hud:notify",
531
- extension: n.extension,
532
- text: n.text,
533
- tone: n.tone
534
- });
535
- });
536
- const extensionBus = createExtensionBus();
537
- extensionBus.onEmit((envelope) => {
538
- options.broadcast({
539
- kind: "extension:signal",
540
- ...envelope
541
- });
542
- });
543
- const RUNTIME_CACHE_MAX = 16;
544
- const runtimeCache = /* @__PURE__ */ new Map();
545
- const hostRuntime = createExtensionHostRuntimeBridge();
546
- /**
547
- * Best-effort release of an evicted entry's extension registry
548
- * (teardown hooks, HUD writers — `registry.dispose()` is idempotent).
549
- * Fire-and-forget: eviction must never block or throw on a broken
550
- * extension teardown, and a rejected resolve has nothing to release.
551
- */
552
- const disposeRuntime = (promise) => {
553
- promise.then((config) => config.extensions.dispose()).catch(() => void 0);
554
- };
555
- const runtimeConfig = (cwd) => {
556
- const settings = readSettings();
557
- const key = [
558
- cwd,
559
- JSON.stringify(settings.enabledExtensions ?? null),
560
- String(settings.loadProjectExtensions === true)
561
- ].join("\0");
562
- const existing = runtimeCache.get(key);
563
- if (existing) {
564
- runtimeCache.delete(key);
565
- runtimeCache.set(key, existing);
566
- return existing;
567
- }
568
- const promise = (async () => {
569
- return resolveConfig({
570
- cwd,
571
- extensionRegistry: await discoverAndBuildExtensionRegistry({
572
- cwd,
573
- hud,
574
- bus: extensionBus,
575
- hostRuntime,
576
- prefix: config.prefix,
577
- ...settings.enabledExtensions !== void 0 ? { enabledAllowlist: [...settings.enabledExtensions] } : {},
578
- trustProjectExtensions: settings.loadProjectExtensions === true,
579
- readSettings
580
- }),
581
- store: () => store
582
- });
583
- })();
584
- runtimeCache.set(key, promise);
585
- while (runtimeCache.size > RUNTIME_CACHE_MAX) {
586
- const oldest = runtimeCache.keys().next().value;
587
- if (oldest === void 0) break;
588
- const evicted = runtimeCache.get(oldest);
589
- runtimeCache.delete(oldest);
590
- if (evicted) disposeRuntime(evicted);
591
- }
592
- promise.catch(() => {
593
- if (runtimeCache.get(key) === promise) runtimeCache.delete(key);
594
- });
595
- return promise;
596
- };
597
- const userDataDir = () => config.paths.userDir;
598
- const applyAuthEnv = () => {
599
- const dir = userDataDir();
600
- process.env.ZIDANE_CREDENTIALS_PATH = credentialsPath(dir);
601
- applyApiKeyEnv(dir, BUILTIN_PROVIDERS);
602
- };
603
- return {
604
- multiProcess: true,
605
- broadcast: options.broadcast,
606
- store,
607
- readSettings,
608
- writeSettings,
609
- runtimeConfig,
610
- hostRuntime,
611
- userDataDir,
612
- applyAuthEnv,
613
- mcpCredentialStore: () => createFileMcpCredentialStore(userDataDir()),
614
- approvalsPersistence: createFileApprovalsStore(join(dirname(config.paths.state), "pending-approvals.json")),
615
- ...options.debugStream !== void 0 ? { debugStream: options.debugStream } : {},
616
- invalidateRuntime: () => {
617
- for (const entry of runtimeCache.values()) disposeRuntime(entry);
618
- runtimeCache.clear();
619
- },
620
- config,
621
- extensionBus
622
- };
623
- }
624
- //#endregion
625
- //#region src/ipc/daemon/server.ts
626
- /**
627
- * Per-peer write backpressure bound. A wedged peer (e.g. a SIGSTOP'd
628
- * terminal) stops reading its socket, so fan-out writes pile up in
629
- * `socket.writableLength` without bound and can OOM the daemon. A peer
630
- * buffering more than this is destroyed — the protocol supports re-attach
631
- * + backfill, so killing a wedged peer is safe and self-healing.
632
- */
633
- const PEER_WRITE_HIGH_WATERMARK = 8 * 1024 * 1024;
634
- async function startIpcDaemon(options) {
635
- const { socketPath } = options;
636
- const log = options.onLog ?? (() => void 0);
637
- const startedAt = Date.now();
638
- const appVersion = options.appVersion ?? "dev";
639
- const peers = /* @__PURE__ */ new Set();
640
- /** Sessions with a run in flight, tracked from the run signals themselves. */
641
- const runningSessions = /* @__PURE__ */ new Set();
642
- const broadcast = (signal) => {
643
- broadcastExcept(null, signal);
644
- switch (signal.kind) {
645
- case "run:start":
646
- runningSessions.add(signal.sessionId);
647
- broadcastPresence();
648
- break;
649
- case "run:end":
650
- runningSessions.delete(signal.sessionId);
651
- broadcastPresence();
652
- break;
653
- case "approval:request":
654
- case "approval:resolved":
655
- case "interaction:request":
656
- case "interaction:resolved":
657
- broadcastPresence();
658
- break;
659
- default: break;
660
- }
661
- };
662
- /**
663
- * Fan out to every handshaken peer except `origin`. Draft signals use
664
- * this so a window's own keystrokes never bounce back and fight its
665
- * cursor — echo-safety by construction, no client-side dedupe.
666
- */
667
- function broadcastExcept(origin, signal) {
668
- for (const peer of peers) {
669
- if (!peer.ready || peer === origin) continue;
670
- if (peer.socket.writableLength > PEER_WRITE_HIGH_WATERMARK) {
671
- console.warn(`[ipc-daemon] peer buffered ${peer.socket.writableLength} bytes (> ${PEER_WRITE_HIGH_WATERMARK}) — destroying wedged connection`);
672
- peer.socket.destroy();
673
- continue;
674
- }
675
- try {
676
- peer.connection.sendNotification("ipc.signal", signal);
677
- } catch {}
678
- }
679
- }
680
- /**
681
- * Shared per-session prompt drafts. Ephemeral by design — in-memory
682
- * only, cleared when any window submits, gone on daemon restart.
683
- */
684
- const drafts = /* @__PURE__ */ new Map();
685
- /**
686
- * Bound a peer-supplied attachment list: shape-guarded entries only,
687
- * 24 MiB of base64 per list. Shared by `queue.add` and
688
- * `drafts.setAttachments`.
689
- */
690
- function boundAttachments(list) {
691
- let budget = 24 * 1024 * 1024;
692
- const out = [];
693
- for (const entry of list) {
694
- const a = entry;
695
- if (typeof a?.mediaType !== "string" || typeof a?.data !== "string") continue;
696
- budget -= a.data.length;
697
- if (budget < 0) break;
698
- out.push({
699
- mediaType: a.mediaType,
700
- data: a.data,
701
- ...typeof a.name === "string" ? { name: a.name.slice(0, 256) } : {}
702
- });
703
- }
704
- return out;
705
- }
706
- /** Total base64 bytes currently pinned by ALL draft attachments. */
707
- function draftAttachmentBytes() {
708
- let total = 0;
709
- for (const entry of drafts.values()) for (const attachment of entry.attachments ?? []) total += attachment.data.length;
710
- return total;
711
- }
712
- /** Consume the draft after a submit — every window except the sender clears. */
713
- function clearDraft(sessionId, origin) {
714
- const entry = drafts.get(sessionId);
715
- if (!entry) return;
716
- drafts.delete(sessionId);
717
- if (entry.text) broadcastExcept(origin, {
718
- kind: "draft:changed",
719
- sessionId,
720
- text: ""
721
- });
722
- if (entry.attachments?.length) broadcastExcept(origin, {
723
- kind: "draft:attachments",
724
- sessionId,
725
- attachments: []
726
- });
727
- }
728
- /**
729
- * Shared inline-autocomplete state — per-session latest-wins
730
- * coalescing for `suggest.resolve`. `seq` is the newest sequence seen
731
- * (stale requests return without computing); `controller` aborts an
732
- * in-flight compute when a newer request supersedes it (the GUI's
733
- * controller-map pattern, daemon-side). Bounded like `drafts`: keys
734
- * only evict on session delete, so cap the map at 256 sessions.
735
- */
736
- const suggests = /* @__PURE__ */ new Map();
737
- /** Drop empty draft entries so the map only holds live composing state. */
738
- function compactDraft(sessionId, entry) {
739
- if (!entry.text && !entry.shell && !entry.attachments?.length && !entry.search?.active) drafts.delete(sessionId);
740
- else drafts.set(sessionId, entry);
741
- }
742
- const env = await (options.createEnvironment ? options.createEnvironment(broadcast) : createDaemonEnvironment({ broadcast }));
743
- const host = createChatHost(env);
744
- /**
745
- * Live presence: which sessions have attached windows, and their
746
- * run / awaiting-input state. Union of watched, live-agent, and
747
- * pending-HITL sessions — small by construction.
748
- */
749
- function computePresence() {
750
- const windowCounts = /* @__PURE__ */ new Map();
751
- for (const peer of peers) if (peer.ready && peer.watching) windowCounts.set(peer.watching, (windowCounts.get(peer.watching) ?? 0) + 1);
752
- const attention = /* @__PURE__ */ new Set();
753
- for (const request of host.approvals.listPending()) attention.add(request.sessionId);
754
- for (const pending of host.interactions.list()) attention.add(pending.sessionId);
755
- const live = new Map(host.listLiveSessions().map((entry) => [entry.sessionId, entry.running]));
756
- return [.../* @__PURE__ */ new Set([
757
- ...windowCounts.keys(),
758
- ...attention,
759
- ...live.keys(),
760
- ...runningSessions
761
- ])].map((sessionId) => ({
762
- sessionId,
763
- windows: windowCounts.get(sessionId) ?? 0,
764
- running: runningSessions.has(sessionId) || live.get(sessionId) === true,
765
- attention: attention.has(sessionId)
766
- }));
767
- }
768
- function broadcastPresence() {
769
- broadcastExcept(null, {
770
- kind: "presence:changed",
771
- sessions: computePresence()
772
- });
773
- }
774
- const SEARCH_INDEX_CACHE_MAX = 64;
775
- /** Latest `history.searchAll` generation per peer — see the handler. */
776
- const searchGenerations = /* @__PURE__ */ new WeakMap();
777
- const searchIndexCache = /* @__PURE__ */ new Map();
778
- async function sessionSearchIndex(sessionId) {
779
- const liveTurns = host.getLiveTurns(sessionId);
780
- let turns;
781
- let key;
782
- if (liveTurns) {
783
- turns = [...liveTurns];
784
- key = `live:${turns.length}:${turns.at(-1)?.id ?? ""}`;
785
- } else {
786
- const data = await env.store.load(sessionId);
787
- if (!data) return null;
788
- turns = data.turns;
789
- key = `store:${data.updatedAt}:${data.turns.length}`;
790
- }
791
- const cached = searchIndexCache.get(sessionId);
792
- if (cached?.key === key) {
793
- searchIndexCache.delete(sessionId);
794
- searchIndexCache.set(sessionId, cached);
795
- return cached.index;
796
- }
797
- const index = await buildSessionSearchIndexAsync(turns);
798
- searchIndexCache.set(sessionId, {
799
- key,
800
- index
801
- });
802
- while (searchIndexCache.size > SEARCH_INDEX_CACHE_MAX) {
803
- const oldest = searchIndexCache.keys().next().value;
804
- if (oldest === void 0) break;
805
- searchIndexCache.delete(oldest);
806
- }
807
- return index;
808
- }
809
- host.approvals.rehydrate();
810
- const store = env.store;
811
- /** Wire-supplied limit → sane positive integer capped at 1000, else `undefined` (no limit). */
812
- function boundedLimit(raw) {
813
- return Number.isInteger(raw) && raw > 0 ? Math.min(raw, 1e3) : void 0;
814
- }
815
- function toRow(data) {
816
- const meta = data.metadata ?? {};
817
- const title = deriveSessionTitle(data.turns, meta);
818
- return {
819
- id: data.id,
820
- title,
821
- ...isMainSession(meta) ? { isMain: true } : {},
822
- projectRoot: data.projectRoot ?? null,
823
- cwd: typeof meta.cwd === "string" ? meta.cwd : data.projectRoot ?? "",
824
- ...typeof data.agentId === "string" ? { agentId: data.agentId } : {},
825
- status: host.isSessionRunning(data.id) ? "running" : data.status === "running" && Date.now() - data.updatedAt >= 3e5 ? "idle" : data.status,
826
- createdAt: data.createdAt,
827
- updatedAt: data.updatedAt,
828
- archived: meta.archived === true,
829
- ...typeof meta.providerKey === "string" ? { providerKey: meta.providerKey } : {},
830
- ...typeof meta.modelId === "string" ? { modelId: meta.modelId } : {},
831
- ...typeof meta.effort === "string" ? { effort: meta.effort } : {},
832
- ...meta.modelOptions && typeof meta.modelOptions === "object" ? { modelOptions: meta.modelOptions } : {},
833
- ...(() => {
834
- const fallbacks = sessionModelFallbacks(meta);
835
- return fallbacks ? { modelFallbacks: fallbacks } : {};
836
- })()
837
- };
838
- }
839
- async function loadOrThrow(sessionId) {
840
- const data = await store.load(sessionId);
841
- if (!data) throw new Error(`Session "${sessionId}" not found.`);
842
- return data;
843
- }
844
- /**
845
- * Apply a metadata-only patch. Prefers the host's live-session path (safe
846
- * mid-run — routes through the in-memory `Session` whose turns are the
847
- * source of truth); only falls back to a store-level full-document
848
- * `save()` when the session is idle, where no run is appending turns so
849
- * `load → mutate → save` can't drop concurrently-persisted turns.
850
- *
851
- * `bumpUpdatedAt: false` skips the recency bump so a rename doesn't yank
852
- * the row to the top of recency-sorted lists (mirrors the GUI).
853
- */
854
- async function patchSessionMeta(sessionId, patch, opts = {}) {
855
- await host.patchSessionMeta(sessionId, patch, opts);
856
- broadcast({
857
- kind: "sessions:changed",
858
- op: "update",
859
- sessionId
860
- });
861
- }
862
- async function patchSession(sessionId, mutate) {
863
- const data = await loadOrThrow(sessionId);
864
- mutate(data);
865
- data.updatedAt = Date.now();
866
- await store.save(data);
867
- broadcast({
868
- kind: "sessions:changed",
869
- op: "update",
870
- sessionId
871
- });
872
- }
873
- async function createSessionRow(params) {
874
- const id = await host.createSession(params);
875
- const data = await loadOrThrow(id);
876
- broadcast({
877
- kind: "sessions:changed",
878
- op: "create",
879
- sessionId: id
880
- });
881
- return toRow(data);
882
- }
883
- const methods = {
884
- "chat.send": async (p, peer) => {
885
- const { wake: _stripped, ...params } = p;
886
- const result = await host.sendPrompt(params);
887
- clearDraft(p.sessionId, peer);
888
- return result;
889
- },
890
- "chat.interrupt": (p) => host.interrupt(p.sessionId),
891
- "chat.steer": (p) => host.steer(p.sessionId, p.message),
892
- "chat.followUp": (p) => host.followUp(p.sessionId, p.message),
893
- "chat.pushQueued": async (p, peer) => {
894
- const result = await host.pushQueued(p.sessionId, p.message, p.activatedSkills);
895
- clearDraft(p.sessionId, peer);
896
- return result;
897
- },
898
- "commands.list": (p) => host.listCommands(p.cwd),
899
- "commands.completeArgs": (p) => host.completeCommandArgs(p.cwd, p.name, p.argsPrefix),
900
- "queue.list": (p) => host.queueList(p.sessionId),
901
- "sessions.systemMd": (p) => host.sessionSystemMd(p.sessionId),
902
- "queue.add": async (p, peer) => {
903
- const text = typeof p.text === "string" ? p.text.slice(0, 64 * 1024) : "";
904
- const activatedSkills = Array.isArray(p.activatedSkills) ? p.activatedSkills.filter((name) => typeof name === "string") : void 0;
905
- const attachments = Array.isArray(p.attachments) ? boundAttachments(p.attachments) : void 0;
906
- const asCommand = typeof p.asCommand === "string" ? p.asCommand.slice(0, 128) : void 0;
907
- const result = await host.queueAdd(p.sessionId, text, activatedSkills, attachments, asCommand);
908
- clearDraft(p.sessionId, peer);
909
- return result;
910
- },
911
- "sessions.contextSegments": (p) => host.getContextSegments(p.sessionId),
912
- "sessions.createSystemOverride": (p) => host.createSystemOverride(p.sessionId),
913
- "queue.remove": (p) => host.queueRemove(p.sessionId, p.id),
914
- "queue.update": (p) => host.queueUpdate(p.sessionId, p.id, typeof p.text === "string" ? p.text.slice(0, 64 * 1024) : ""),
915
- "queue.pushNow": (p) => host.queuePushNow(p.sessionId, p.id),
916
- "drafts.get": (p) => {
917
- const entry = drafts.get(p.sessionId);
918
- return {
919
- text: entry?.text ?? "",
920
- ...entry?.shell ? { shell: true } : {},
921
- ...entry?.attachments?.length ? { attachments: entry.attachments } : {},
922
- ...entry?.search?.active ? { search: entry.search } : {}
923
- };
924
- },
925
- "drafts.set": (p, peer) => {
926
- const text = typeof p.text === "string" ? p.text.slice(0, 64 * 1024) : "";
927
- const truncated = typeof p.text === "string" && p.text.length > text.length;
928
- if (!drafts.has(p.sessionId) && drafts.size >= 256) return;
929
- const entry = drafts.get(p.sessionId) ?? {};
930
- entry.text = text.length > 0 ? text : void 0;
931
- entry.shell = p.shell === true ? true : void 0;
932
- compactDraft(p.sessionId, entry);
933
- broadcastExcept(truncated ? null : peer, {
934
- kind: "draft:changed",
935
- sessionId: p.sessionId,
936
- text,
937
- ...p.shell === true ? { shell: true } : {}
938
- });
939
- },
940
- "search.set": (p, peer) => {
941
- const active = p.active === true;
942
- const query = typeof p.query === "string" ? p.query.slice(0, 4 * 1024) : "";
943
- if (!drafts.has(p.sessionId) && drafts.size >= 256) return;
944
- const entry = drafts.get(p.sessionId) ?? {};
945
- entry.search = active || query.length > 0 ? {
946
- active,
947
- query
948
- } : void 0;
949
- compactDraft(p.sessionId, entry);
950
- broadcastExcept(peer, {
951
- kind: "search:changed",
952
- sessionId: p.sessionId,
953
- active,
954
- query
955
- });
956
- },
957
- "extension.emit": async (p, peer) => {
958
- const extensionId = typeof p.extensionId === "string" ? p.extensionId : "";
959
- if (extensionId.length === 0 || extensionId.length > 256) return;
960
- if (typeof p.seq !== "number" || !Number.isFinite(p.seq)) return;
961
- const sessionId = typeof p.sessionId === "string" ? p.sessionId : void 0;
962
- const bytes = serializedPayloadBytes(p.payload);
963
- if (bytes === null || bytes > 65536) return;
964
- let registry = env.config.extensions;
965
- if (sessionId !== void 0) try {
966
- const data = await loadOrThrow(sessionId);
967
- const meta = data.metadata ?? {};
968
- const cwd = typeof meta.cwd === "string" ? meta.cwd : data.projectRoot ?? "";
969
- registry = (await env.runtimeConfig(cwd)).extensions;
970
- } catch {
971
- return;
972
- }
973
- if (!registry.loaded.some((ext) => !ext.error && ext.name === extensionId && ext.definition?.permissions?.includes("ipc") === true)) return;
974
- const nonce = typeof p.nonce === "string" ? p.nonce : void 0;
975
- const envelope = {
976
- extensionId,
977
- ...sessionId !== void 0 ? { sessionId } : {},
978
- payload: p.payload,
979
- seq: p.seq,
980
- ...nonce !== void 0 ? { nonce } : {}
981
- };
982
- env.extensionBus?.deliver(envelope);
983
- broadcastExcept(peer, {
984
- kind: "extension:signal",
985
- ...envelope
986
- });
987
- },
988
- "suggest.resolve": async (p, peer) => {
989
- const sessionId = String(p.sessionId);
990
- const seq = typeof p.seq === "number" ? p.seq : 0;
991
- const text = typeof p.text === "string" ? p.text.slice(0, 64 * 1024) : "";
992
- const caret = typeof p.caret === "number" ? Math.max(0, Math.min(Math.floor(p.caret), text.length)) : text.length;
993
- const prev = suggests.get(sessionId);
994
- if (prev && seq < prev.seq) return {
995
- suggestion: null,
996
- seq
997
- };
998
- if (!prev && suggests.size >= 256) return {
999
- suggestion: null,
1000
- seq
1001
- };
1002
- prev?.controller?.abort();
1003
- const controller = new AbortController();
1004
- const entry = {
1005
- seq,
1006
- controller
1007
- };
1008
- suggests.set(sessionId, entry);
1009
- try {
1010
- const data = await loadOrThrow(sessionId);
1011
- const meta = data.metadata ?? {};
1012
- const cwd = typeof meta.cwd === "string" ? meta.cwd : data.projectRoot ?? "";
1013
- const config = await env.runtimeConfig(cwd);
1014
- const result = await resolveInlineSuggestion([createPathAutocompleteProvider({ cwd: () => cwd }), ...config.extensions.inlineAutocompleteProviders], {
1015
- text,
1016
- cursor: caret,
1017
- cwd,
1018
- signal: controller.signal
1019
- });
1020
- if (controller.signal.aborted || suggests.get(sessionId) !== entry) return {
1021
- suggestion: null,
1022
- seq
1023
- };
1024
- const candidates = result ? [...result.suffixes] : [];
1025
- const suggestion = candidates[0] ?? null;
1026
- broadcastExcept(peer, {
1027
- kind: "suggest:changed",
1028
- sessionId,
1029
- seq,
1030
- basis: text,
1031
- caret,
1032
- suggestion,
1033
- ...candidates.length > 0 ? { candidates } : {}
1034
- });
1035
- return {
1036
- suggestion,
1037
- seq,
1038
- ...candidates.length > 0 ? { candidates } : {}
1039
- };
1040
- } finally {
1041
- if (suggests.get(sessionId) === entry) entry.controller = null;
1042
- }
1043
- },
1044
- "drafts.setAttachments": (p, peer) => {
1045
- const bounded = Array.isArray(p.attachments) ? boundAttachments(p.attachments) : [];
1046
- if (!drafts.has(p.sessionId) && drafts.size >= 256) return;
1047
- const currentBytes = (drafts.get(p.sessionId)?.attachments ?? []).reduce((sum, a) => sum + a.data.length, 0);
1048
- const incomingBytes = bounded.reduce((sum, a) => sum + a.data.length, 0);
1049
- if (draftAttachmentBytes() - currentBytes + incomingBytes > 96 * 1024 * 1024) return;
1050
- const entry = drafts.get(p.sessionId) ?? {};
1051
- entry.attachments = bounded.length > 0 ? bounded : void 0;
1052
- compactDraft(p.sessionId, entry);
1053
- broadcastExcept(peer, {
1054
- kind: "draft:attachments",
1055
- sessionId: p.sessionId,
1056
- attachments: bounded
1057
- });
1058
- },
1059
- "chat.isRunning": (p) => host.isSessionRunning(p.sessionId),
1060
- "chat.rebuildAgent": (p) => host.disposeAgentForRebuild(p.sessionId),
1061
- "runtime.reload": () => {
1062
- env.invalidateRuntime();
1063
- host.rebuildAllAgents();
1064
- },
1065
- "chat.listWork": (p) => host.listRunningWork(p.sessionId),
1066
- "chat.cancelWork": (p) => host.cancelRunningWork(p.sessionId, p.id, p.reason),
1067
- "sessions.list": async (p) => {
1068
- const filter = p?.projectRoot !== void 0 ? { projectRoot: p.projectRoot } : void 0;
1069
- const applyArchive = (rows) => {
1070
- const filtered = rows.filter((row) => {
1071
- if (p?.archive === "active") return !row.archived;
1072
- if (p?.archive === "archived") return row.archived;
1073
- return true;
1074
- });
1075
- filtered.sort((a, b) => b.updatedAt - a.updatedAt);
1076
- return filtered;
1077
- };
1078
- if (store.listMeta) return applyArchive((await store.listMeta(filter)).map((meta) => {
1079
- const md = meta.metadata;
1080
- const title = deriveSessionTitle(meta.firstUserTurn ? [meta.firstUserTurn] : [], md);
1081
- return {
1082
- id: meta.id,
1083
- title,
1084
- projectRoot: meta.projectRoot ?? null,
1085
- cwd: typeof md.cwd === "string" ? md.cwd : meta.projectRoot ?? "",
1086
- ...meta.agentId ? { agentId: meta.agentId } : {},
1087
- status: host.isSessionRunning(meta.id) ? "running" : meta.status === "running" && Date.now() - meta.updatedAt >= 3e5 ? "idle" : meta.status ?? "idle",
1088
- createdAt: meta.createdAt ?? 0,
1089
- updatedAt: meta.updatedAt,
1090
- archived: md.archived === true,
1091
- ...typeof md.providerKey === "string" ? { providerKey: md.providerKey } : {},
1092
- ...typeof md.modelId === "string" ? { modelId: md.modelId } : {},
1093
- ...typeof md.effort === "string" ? { effort: md.effort } : {},
1094
- ...md.modelOptions && typeof md.modelOptions === "object" ? { modelOptions: md.modelOptions } : {},
1095
- ...(() => {
1096
- const fallbacks = sessionModelFallbacks(md);
1097
- return fallbacks ? { modelFallbacks: fallbacks } : {};
1098
- })()
1099
- };
1100
- }));
1101
- const ids = await store.list(filter);
1102
- const rows = [];
1103
- for (const id of ids) {
1104
- const data = await store.load(id);
1105
- if (!data) continue;
1106
- rows.push(toRow(data));
1107
- }
1108
- return applyArchive(rows);
1109
- },
1110
- "sessions.create": (p) => createSessionRow(p),
1111
- "sessions.delete": async (p) => {
1112
- drafts.delete(p.sessionId);
1113
- suggests.get(p.sessionId)?.controller?.abort();
1114
- suggests.delete(p.sessionId);
1115
- host.disposeSession(p.sessionId);
1116
- await store.delete(p.sessionId);
1117
- broadcast({
1118
- kind: "sessions:changed",
1119
- op: "delete",
1120
- sessionId: p.sessionId
1121
- });
1122
- },
1123
- "sessions.setTitle": (p) => patchSessionMeta(p.sessionId, { title: p.title }, { bumpUpdatedAt: false }),
1124
- "sessions.setArchived": (p) => patchSessionMeta(p.sessionId, { archived: p.archived }),
1125
- "sessions.setAgentId": async (p) => {
1126
- if (await host.setLiveSessionAgentId(p.sessionId, p.agentId)) broadcast({
1127
- kind: "sessions:changed",
1128
- op: "update",
1129
- sessionId: p.sessionId
1130
- });
1131
- else await patchSession(p.sessionId, (d) => {
1132
- d.agentId = p.agentId;
1133
- });
1134
- host.disposeAgentForRebuild(p.sessionId);
1135
- },
1136
- "sessions.setEffort": (p) => patchSessionMeta(p.sessionId, { effort: p.effort }),
1137
- "sessions.setModel": async (p) => {
1138
- await host.setSessionModel(p.sessionId, {
1139
- providerKey: p.providerKey,
1140
- modelId: p.modelId,
1141
- ...p.fallbacks ? { fallbacks: p.fallbacks } : {},
1142
- ...p.effort ? { effort: p.effort } : {},
1143
- ...p.modelOptions ? { modelOptions: p.modelOptions } : {}
1144
- });
1145
- broadcast({
1146
- kind: "sessions:changed",
1147
- op: "update",
1148
- sessionId: p.sessionId
1149
- });
1150
- },
1151
- "sessions.setModelOptions": (p) => patchSessionMeta(p.sessionId, { modelOptions: p.options }),
1152
- "sessions.loadEvents": async (p) => {
1153
- const data = await loadOrThrow(p.sessionId);
1154
- return eventsFromTurns(data.turns, data.runs);
1155
- },
1156
- "sessions.getTurn": async (p) => {
1157
- return (await store.load(p.sessionId))?.turns.find((t) => t.id === p.turnId) ?? null;
1158
- },
1159
- "sessions.contextBreakdown": (p) => host.getContextBreakdown(p.sessionId),
1160
- "sessions.artifacts": async (p) => {
1161
- if (!store.listArtifacts) return [];
1162
- return store.listArtifacts({
1163
- sessionId: p.sessionId,
1164
- ...typeof p.kind === "string" ? { kind: p.kind } : {},
1165
- ...boundedLimit(p.limit) !== void 0 ? { limit: boundedLimit(p.limit) } : {}
1166
- });
1167
- },
1168
- "artifacts.list": async (p) => {
1169
- if (!store.listArtifacts) return [];
1170
- return store.listArtifacts({
1171
- ...p.projectRoot === null || typeof p.projectRoot === "string" ? { projectRoot: p.projectRoot } : {},
1172
- ...typeof p.kind === "string" ? { kind: p.kind } : {},
1173
- ...typeof p.uri === "string" ? { uri: p.uri } : {},
1174
- ...typeof p.since === "number" && Number.isFinite(p.since) ? { since: p.since } : {},
1175
- ...boundedLimit(p.limit) !== void 0 ? { limit: boundedLimit(p.limit) } : {}
1176
- });
1177
- },
1178
- "artifacts.delete": async (p) => {
1179
- if (!store.deleteArtifact) return false;
1180
- await store.deleteArtifact(p.sessionId, p.artifactId);
1181
- broadcast({
1182
- kind: "artifact:changed",
1183
- sessionId: p.sessionId,
1184
- op: "delete",
1185
- artifactId: p.artifactId
1186
- });
1187
- return true;
1188
- },
1189
- "artifacts.upsert": async (p) => {
1190
- if (!store.upsertArtifact) return null;
1191
- const normalized = normalizeArtifactInput(p.artifact);
1192
- if (!normalized || typeof p.artifact?.sessionId !== "string" || typeof p.artifact?.id !== "string") return null;
1193
- const now = Date.now();
1194
- const stored = await store.upsertArtifact({
1195
- ...normalized,
1196
- id: p.artifact.id,
1197
- sessionId: p.artifact.sessionId,
1198
- ...typeof p.artifact.runId === "string" ? { runId: p.artifact.runId } : {},
1199
- ...typeof p.artifact.turnId === "string" ? { turnId: p.artifact.turnId } : {},
1200
- createdAt: typeof p.artifact.createdAt === "number" ? p.artifact.createdAt : now,
1201
- updatedAt: now
1202
- });
1203
- if (stored) broadcast({
1204
- kind: "artifact:changed",
1205
- sessionId: stored.sessionId,
1206
- op: "upsert",
1207
- artifactId: stored.id,
1208
- artifact: stored
1209
- });
1210
- return stored;
1211
- },
1212
- "history.searchSession": async (p) => {
1213
- const index = await sessionSearchIndex(p.sessionId);
1214
- if (!index) return [];
1215
- const limit = Number.isInteger(p.limit) && p.limit > 0 ? Math.min(p.limit, index.turns.length) : index.turns.length;
1216
- const matches = await searchSessionIndexAsync(index, p.query, { limit });
1217
- const order = new Map(index.turns.map((entry, i) => [entry.turn.id, i]));
1218
- matches.sort((a, b) => (order.get(a.turn.id) ?? 0) - (order.get(b.turn.id) ?? 0));
1219
- return matches;
1220
- },
1221
- "history.searchAll": async (p, peer) => {
1222
- const generation = (searchGenerations.get(peer) ?? 0) + 1;
1223
- searchGenerations.set(peer, generation);
1224
- const results = {};
1225
- const ids = Array.isArray(p.sessionIds) ? p.sessionIds.slice(0, 500) : [];
1226
- for (const sessionId of ids) {
1227
- if (searchGenerations.get(peer) !== generation) break;
1228
- try {
1229
- const index = await sessionSearchIndex(sessionId);
1230
- if (!index) continue;
1231
- const match = await searchSessionHistoryIndexAsync(index, p.query, p.excerptLimit ?? 3);
1232
- if (match) results[sessionId] = match;
1233
- } catch {}
1234
- }
1235
- return results;
1236
- },
1237
- "sessions.touch": (p) => {
1238
- broadcast({
1239
- kind: "sessions:changed",
1240
- op: "update",
1241
- sessionId: p.sessionId
1242
- });
1243
- },
1244
- "sessions.compact": (p) => host.compactSessionNow(p.sessionId),
1245
- "todos.get": (p) => {
1246
- const state = host.getTodosSnapshot(p.sessionId);
1247
- return state ? toTodosSnapshot(state) : null;
1248
- },
1249
- "todos.set": async (p) => {
1250
- const state = await host.setTodos(p.sessionId, p.items);
1251
- return state ? toTodosSnapshot(state) : null;
1252
- },
1253
- "orchestration.main": () => host.orchestration.ensureMain(),
1254
- "orchestration.createWorker": ({ mainId, ...params }) => host.orchestration.createWorker(mainId, params),
1255
- "orchestration.list": (p) => host.orchestration.list(p.mainId, p.limit),
1256
- "orchestration.read": async (p) => await host.orchestration.canOrchestrate(p.mainId, p.sessionId) ? host.orchestration.read(p.sessionId) : null,
1257
- "orchestration.send": (p) => host.orchestration.send(p.mainId, p.sessionId, p.prompt, p.wake),
1258
- "orchestration.steer": (p) => host.orchestration.steer(p.mainId, p.sessionId, p.message),
1259
- "orchestration.cancel": (p) => host.orchestration.cancel(p.mainId, p.sessionId),
1260
- "orchestration.transcript": (p) => host.orchestration.transcript(p.mainId, p.sessionId, p.limit),
1261
- "interactions.list": (p) => host.interactions.list(p?.sessionId),
1262
- "interactions.respond": (p) => host.interactions.respond(p.requestId, p.response),
1263
- "interactions.cancel": (p) => host.interactions.cancel(p.requestId, p.reason),
1264
- "interactions.rehydrate": (p) => host.interactions.rehydrate(p.sessionId),
1265
- "approvals.resolve": (p) => host.approvals.resolve(p.requestId, p.decision),
1266
- "approvals.denyAll": (p) => host.approvals.denyAll(p?.sessionId),
1267
- "approvals.listPending": () => host.approvals.listPending(),
1268
- "settings.get": () => env.readSettings(),
1269
- "settings.set": (p) => {
1270
- const before = env.readSettings();
1271
- const next = env.writeSettings(p.patch);
1272
- const changed = (key) => JSON.stringify(before[key]) !== JSON.stringify(next[key]);
1273
- if (changed("enabledExtensions") || changed("loadProjectExtensions")) {
1274
- env.invalidateRuntime();
1275
- host.shutdown();
1276
- } else if (changed("enabledMcps") || changed("disabledMcpTools") || changed("enabledSkills") || changed("enabledPlugins") || changed("importForeignConfigs") || changed("importRulerConfigs")) host.shutdown();
1277
- if (changed("interactionMode") && next.interactionMode === "skip") host.interactions.resolveAutomatically();
1278
- broadcast({
1279
- kind: "settings:changed",
1280
- settings: next
1281
- });
1282
- return next;
1283
- },
1284
- "presence.list": () => computePresence(),
1285
- "presence.watch": (p, peer) => {
1286
- peer.watching = p.sessionId;
1287
- broadcastPresence();
1288
- store.load(p.sessionId).then((data) => {
1289
- if (!data) return;
1290
- const meta = data.metadata ?? {};
1291
- const cwd = typeof meta.cwd === "string" ? meta.cwd : data.projectRoot ?? "";
1292
- return env.runtimeConfig(cwd);
1293
- }).catch(() => void 0);
1294
- },
1295
- "daemon.info": () => ({
1296
- protocolVersion: 9,
1297
- appVersion,
1298
- pid: process.pid,
1299
- startedAt
1300
- }),
1301
- "daemon.shutdown": async () => {
1302
- setImmediate(() => {
1303
- close().then(() => options.onIdle?.());
1304
- });
1305
- }
1306
- };
1307
- let idleTimer;
1308
- function armIdleTimer() {
1309
- if (!options.idleShutdownMs || !options.onIdle) return;
1310
- clearTimeout(idleTimer);
1311
- idleTimer = setTimeout(() => {
1312
- if (peers.size > 0) return;
1313
- if (host.hasActiveWork()) {
1314
- armIdleTimer();
1315
- return;
1316
- }
1317
- options.onIdle?.();
1318
- }, options.idleShutdownMs);
1319
- }
1320
- function handleConnection(socket) {
1321
- const peer = {
1322
- socket,
1323
- connection: void 0,
1324
- ready: false,
1325
- watching: null
1326
- };
1327
- const connection = createJsonRpcConnection({
1328
- input: socket,
1329
- output: socket,
1330
- onRequest: async (message) => {
1331
- if (message.method === "ipc.hello") {
1332
- const params = message.params ?? {};
1333
- const clientBuild = Number(params.buildId);
1334
- const daemonBuild = Number(IPC_BUILD_ID);
1335
- const staleBuild = params.buildId !== void 0 && params.buildId !== "unknown" && IPC_BUILD_ID !== "unknown" && Number.isFinite(clientBuild) && Number.isFinite(daemonBuild) && clientBuild > daemonBuild;
1336
- const staleRelease = typeof params.codeVersion === "string" && compareVersions(params.codeVersion, ZIDANE_VERSION) > 0;
1337
- if (params.protocolVersion !== 9 || staleBuild || staleRelease) return errorResponse(message.id, IpcErrorCode.VersionMismatch, staleRelease ? `Stale daemon: it runs zidane ${ZIDANE_VERSION} but the client runs ${params.codeVersion}. Draining for respawn.` : staleBuild ? `Build mismatch: the daemon was started from an older build (daemon ${IPC_BUILD_ID}, client ${params.buildId}). Draining for respawn.` : `Protocol version mismatch: daemon speaks v9, client sent v${params.protocolVersion ?? "?"}.`, { daemon: {
1338
- protocolVersion: 9,
1339
- appVersion,
1340
- pid: process.pid,
1341
- startedAt,
1342
- buildId: IPC_BUILD_ID,
1343
- codeVersion: ZIDANE_VERSION
1344
- } });
1345
- peer.ready = true;
1346
- const result = {
1347
- protocolVersion: 9,
1348
- appVersion,
1349
- pid: process.pid,
1350
- startedAt,
1351
- buildId: IPC_BUILD_ID,
1352
- codeVersion: ZIDANE_VERSION
1353
- };
1354
- return successResponse(message.id, result);
1355
- }
1356
- if (!peer.ready && message.method !== "daemon.shutdown" && message.method !== "daemon.info") return errorResponse(message.id, IpcErrorCode.NotHandshaken, "Handshake required: send ipc.hello first.");
1357
- const handler = methods[message.method];
1358
- if (!handler) return errorResponse(message.id, -32601, `Unknown method "${message.method}".`);
1359
- try {
1360
- const result = await handler(message.params, peer);
1361
- return successResponse(message.id, result ?? null);
1362
- } catch (err) {
1363
- return errorResponse(message.id, -32e3, err instanceof Error ? err.message : String(err));
1364
- }
1365
- },
1366
- onNotification: async (message) => {
1367
- if (!peer.ready) return;
1368
- const handler = methods[message.method];
1369
- if (!handler) return;
1370
- try {
1371
- await handler(message.params, peer);
1372
- } catch {}
1373
- },
1374
- onError: (err) => log(`[ipc-daemon] peer error: ${err.message}`)
1375
- });
1376
- peer.connection = connection;
1377
- peers.add(peer);
1378
- connection.start();
1379
- log(`[ipc-daemon] peer connected (${peers.size} total)`);
1380
- const drop = () => {
1381
- if (!peers.delete(peer)) return;
1382
- connection.close();
1383
- log(`[ipc-daemon] peer disconnected (${peers.size} left)`);
1384
- if (peer.watching) broadcastPresence();
1385
- if (peers.size === 0) armIdleTimer();
1386
- };
1387
- socket.on("close", drop);
1388
- socket.on("error", drop);
1389
- }
1390
- if (existsSync(socketPath)) {
1391
- if (await probeSocket(socketPath)) throw new Error(`A zidane daemon is already listening on ${socketPath}.`);
1392
- if (await probeSocket(socketPath)) throw new Error(`A zidane daemon is already listening on ${socketPath}.`);
1393
- unlinkSync(socketPath);
1394
- }
1395
- const socketDir = dirname(socketPath);
1396
- const dedicatedSocketDir = basename(socketDir) === "daemon" || !existsSync(socketDir);
1397
- mkdirSync(socketDir, {
1398
- recursive: true,
1399
- mode: 448
1400
- });
1401
- if (dedicatedSocketDir) try {
1402
- chmodSync(socketDir, 448);
1403
- } catch {}
1404
- const server = createServer(handleConnection);
1405
- await new Promise((resolvePromise, reject) => {
1406
- server.once("error", reject);
1407
- server.listen(socketPath, () => {
1408
- server.off("error", reject);
1409
- resolvePromise();
1410
- });
1411
- });
1412
- try {
1413
- chmodSync(socketPath, 384);
1414
- } catch {}
1415
- log(`[ipc-daemon] listening on ${socketPath}`);
1416
- let ownsSocketFile = true;
1417
- armIdleTimer();
1418
- const legacyPath = legacySocketPath(socketPath);
1419
- if (legacyPath) (async () => {
1420
- if (!await probeSocket(legacyPath)) return;
1421
- log(`[ipc-daemon] draining legacy daemon on ${legacyPath}`);
1422
- try {
1423
- const survivor = await connectIpcClient({
1424
- socketPath: legacyPath,
1425
- appVersion: `${appVersion}/legacy-drain`,
1426
- drainOnMismatch: true
1427
- });
1428
- await survivor.request("daemon.shutdown", {}).catch(() => void 0);
1429
- survivor.close();
1430
- } catch {}
1431
- })();
1432
- async function doClose() {
1433
- clearTimeout(idleTimer);
1434
- await host.drain();
1435
- for (const peer of peers) {
1436
- peer.connection.close();
1437
- peer.socket.destroy();
1438
- }
1439
- peers.clear();
1440
- await new Promise((resolvePromise) => {
1441
- server.close(() => resolvePromise());
1442
- });
1443
- if (ownsSocketFile) {
1444
- ownsSocketFile = false;
1445
- try {
1446
- unlinkSync(socketPath);
1447
- } catch {}
1448
- }
1449
- }
1450
- let closePromise = null;
1451
- function close() {
1452
- closePromise ??= doClose();
1453
- return closePromise;
1454
- }
1455
- return {
1456
- socketPath,
1457
- host,
1458
- peerCount: () => peers.size,
1459
- close
1460
- };
1461
- }
1462
- //#endregion
1463
- //#region src/ipc/daemon/shell-path.ts
1464
- /**
1465
- * Login-shell PATH for processes not started from a terminal.
1466
- *
1467
- * A Dock/Finder-launched GUI, or a daemon it spawns, inherits launchd's PATH
1468
- * (`/usr/bin:/bin:/usr/sbin:/sbin`), so `node` / `bun` / `yarn` are invisible
1469
- * to agent shell commands. Ask the user's login shell for its PATH and merge
1470
- * it into `process.env.PATH`.
1471
- *
1472
- * Merge, don't replace: a terminal launch may have prepended entries the rc
1473
- * files know nothing about (`nvm use`, direnv, `PATH=... zidane`), and those
1474
- * must survive. Idempotent, so every surface (GUI, daemon) can call it and a
1475
- * daemon spawned by an already-fixed GUI ends up with the same PATH.
1476
- */
1477
- const DELIMITER = "_ZIDANE_SHELL_ENV_";
1478
- /** A slow rc file costs startup time; a prompting one must never hang the process. */
1479
- const DEFAULT_TIMEOUT_MS = 3e3;
1480
- function defaultShell(env) {
1481
- try {
1482
- const { shell } = userInfo();
1483
- if (shell) return shell;
1484
- } catch {}
1485
- return env.SHELL || (process$1.platform === "darwin" ? "/bin/zsh" : "/bin/sh");
1486
- }
1487
- function parsePath(stdout) {
1488
- const body = stdout.split(DELIMITER)[1];
1489
- if (body === void 0) return void 0;
1490
- const clean = body.replace(/\u001B\[[0-9;]*[A-Z]/gi, "");
1491
- for (const line of clean.split("\n")) if (line.startsWith("PATH=")) return line.slice(5) || void 0;
1492
- }
1493
- /**
1494
- * PATH as seen by an interactive login shell, or `undefined` when no shell
1495
- * answers in time. Tries the user's shell first, then POSIX fallbacks for
1496
- * non-POSIX defaults (nushell, xonsh) whose `-ilc` differs. An explicit
1497
- * `shell` is tried alone.
1498
- */
1499
- function shellPath(options = {}) {
1500
- if (process$1.platform === "win32") return void 0;
1501
- const env = options.env ?? process$1.env;
1502
- const timeout = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
1503
- const shells = options.shell ? [options.shell] : [.../* @__PURE__ */ new Set([
1504
- defaultShell(env),
1505
- "/bin/zsh",
1506
- "/bin/bash"
1507
- ])];
1508
- for (const shell of shells) {
1509
- const result = spawnSync(shell, ["-ilc", `echo -n "${DELIMITER}"; command env; echo -n "${DELIMITER}"; exit`], {
1510
- encoding: "utf8",
1511
- timeout,
1512
- stdio: [
1513
- "ignore",
1514
- "pipe",
1515
- "ignore"
1516
- ],
1517
- env: {
1518
- ...env,
1519
- DISABLE_AUTO_UPDATE: "true",
1520
- ZSH_TMUX_AUTOSTARTED: "true",
1521
- ZSH_TMUX_AUTOSTART: "false"
1522
- }
1523
- });
1524
- if (result.error || result.status !== 0) continue;
1525
- const path = parsePath(result.stdout);
1526
- if (path) return path;
1527
- }
1528
- }
1529
- /**
1530
- * Entries of `current` the shell doesn't know about (ad-hoc prepends from the
1531
- * launching terminal) stay in front; then the shell's PATH in its own order.
1532
- * From the Dock every launchd entry is already in the shell PATH, so the
1533
- * result is exactly the shell PATH, with the shell's precedence intact.
1534
- */
1535
- function mergePath(current, shell) {
1536
- const split = (path) => (path ?? "").split(delimiter).filter(Boolean);
1537
- const fromShell = split(shell);
1538
- const known = new Set(fromShell);
1539
- return [.../* @__PURE__ */ new Set([...split(current).filter((entry) => !known.has(entry)), ...fromShell])].join(delimiter);
1540
- }
1541
- /** Merge the login shell's PATH into `process.env.PATH`. No-op on Windows or when no shell answers. */
1542
- function fixPath() {
1543
- const extra = shellPath();
1544
- if (extra) process$1.env.PATH = mergePath(process$1.env.PATH, extra);
1545
- }
1546
- //#endregion
1547
- export { selfDaemonSpawnCommand as _, createDaemonEnvironment as a, connectIpcClient as c, IpcErrorCode as d, IPC_BUILD_ID as f, probeSocket as g, ensureDaemonRunning as h, startIpcDaemon as i, connectOrSpawnDaemon as l, defaultSocketPath as m, mergePath as n, createFileApprovalsStore as o, daemonSocketName as p, shellPath as r, IpcVersionMismatchError as s, fixPath as t, IPC_PROTOCOL_VERSION as u };
1548
-
1549
- //# sourceMappingURL=shell-path-DfdXrGg9.js.map