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.
- package/LICENSE +21 -0
- package/README.md +34 -6
- package/dist/{acp-D-tVyUjw.js → acp-DQDhi2dj.js} +230 -77
- package/dist/acp-DQDhi2dj.js.map +1 -0
- package/dist/acp-cli.d.ts +1 -1
- package/dist/acp-cli.js +9 -66
- package/dist/acp-cli.js.map +1 -1
- package/dist/acp.d.ts +10 -590
- package/dist/acp.d.ts.map +1 -1
- package/dist/acp.js +3 -3
- package/dist/{agent-D0zZnGbt.js → agent-DSLNmBp0.js} +14401 -13214
- package/dist/agent-DSLNmBp0.js.map +1 -0
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +3 -2
- package/dist/aliasing-lVFbm81n.js +217 -0
- package/dist/aliasing-lVFbm81n.js.map +1 -0
- package/dist/{anthropic-C2aole0G.js → anthropic-CD00LhUP.js} +1442 -1264
- package/dist/anthropic-CD00LhUP.js.map +1 -0
- package/dist/artifacts-CV2hUKnL.js.map +1 -1
- package/dist/{atomic-write-B7zr1ddF.js → atomic-write-Ijgf2Mhc.js} +13 -3
- package/dist/atomic-write-Ijgf2Mhc.js.map +1 -0
- package/dist/call-tool-dHlbGOIY.js +70 -0
- package/dist/call-tool-dHlbGOIY.js.map +1 -0
- package/dist/chat/pure.d.ts +372 -6
- package/dist/chat/pure.d.ts.map +1 -1
- package/dist/chat/pure.js +35 -244
- package/dist/chat/pure.js.map +1 -1
- package/dist/{approvals-DKaJZYlm.js → chat-JPJJ8uu5.js} +15879 -14631
- package/dist/chat-JPJJ8uu5.js.map +1 -0
- package/dist/chat.d.ts +4 -6
- package/dist/chat.js +23 -12
- package/dist/cli-shared-C-YCaglL.js +159 -0
- package/dist/cli-shared-C-YCaglL.js.map +1 -0
- package/dist/client-core-BQSyDALT.d.ts +2115 -0
- package/dist/client-core-BQSyDALT.d.ts.map +1 -0
- package/dist/codemode-worker.d.ts +1 -0
- package/dist/codemode-worker.js +155 -0
- package/dist/codemode-worker.js.map +1 -0
- package/dist/codemode.d.ts +352 -0
- package/dist/codemode.d.ts.map +1 -0
- package/dist/codemode.js +5 -0
- package/dist/connection-Dr-Js4yZ.d.ts +28 -0
- package/dist/connection-Dr-Js4yZ.d.ts.map +1 -0
- package/dist/connection-loop-gdh22LTI.js +112 -0
- package/dist/connection-loop-gdh22LTI.js.map +1 -0
- package/dist/context-segments-BHKlagL6.js +1016 -0
- package/dist/context-segments-BHKlagL6.js.map +1 -0
- package/dist/{context-transport-T_6AYIvy.js → context-transport-DSMTUsK1.js} +3 -3
- package/dist/{context-transport-T_6AYIvy.js.map → context-transport-DSMTUsK1.js.map} +1 -1
- package/dist/contexts/daytona.d.ts +19 -8
- package/dist/contexts/daytona.d.ts.map +1 -1
- package/dist/contexts/daytona.js +1 -440
- package/dist/contexts/docker.d.ts +36 -7
- package/dist/contexts/docker.d.ts.map +1 -1
- package/dist/contexts/docker.js +1 -456
- package/dist/contexts/e2b.d.ts +68 -13
- package/dist/contexts/e2b.d.ts.map +1 -1
- package/dist/contexts/e2b.js +1 -382
- package/dist/contexts/sandbox.d.ts +1 -1
- package/dist/contexts/sandbox.js +5 -0
- package/dist/contexts/sandbox.js.map +1 -1
- package/dist/{contexts-CRE9pw07.js → contexts-d7UolYot.js} +1059 -524
- package/dist/contexts-d7UolYot.js.map +1 -0
- package/dist/contexts.d.ts +3 -3
- package/dist/contexts.js +1 -1
- package/dist/cred-keys-GpBg71cP.js +105 -0
- package/dist/cred-keys-GpBg71cP.js.map +1 -0
- package/dist/{auth-BG2rVKSt.js → credentials-JttEuRON.js} +55 -206
- package/dist/credentials-JttEuRON.js.map +1 -0
- package/dist/{cursor-iojRXHF9.js → cursor-CdjaQTBW.js} +3 -3
- package/dist/{cursor-iojRXHF9.js.map → cursor-CdjaQTBW.js.map} +1 -1
- package/dist/daemon-cli.d.ts +1 -1
- package/dist/daemon-cli.js +3 -2
- package/dist/daemon-cli.js.map +1 -1
- package/dist/daytona-DG3omipZ.js +513 -0
- package/dist/daytona-DG3omipZ.js.map +1 -0
- package/dist/defaults-Cx3zvDOV.js +23 -0
- package/dist/defaults-Cx3zvDOV.js.map +1 -0
- package/dist/dispatcher-BMlu2BmZ.js +4941 -0
- package/dist/dispatcher-BMlu2BmZ.js.map +1 -0
- package/dist/docker-BZhMMJUp.js +727 -0
- package/dist/docker-BZhMMJUp.js.map +1 -0
- package/dist/e2b-CEVOdRib.js +480 -0
- package/dist/e2b-CEVOdRib.js.map +1 -0
- package/dist/edit-utils-EGosADZq.js +234 -0
- package/dist/edit-utils-EGosADZq.js.map +1 -0
- package/dist/environment-8wsKE2Ln.js +214 -0
- package/dist/environment-8wsKE2Ln.js.map +1 -0
- package/dist/eval-BNcvle_J.js +1595 -0
- package/dist/eval-BNcvle_J.js.map +1 -0
- package/dist/eval.d.ts +2 -2
- package/dist/eval.js +1 -1489
- package/dist/executor-Cx5-8yqi.js +621 -0
- package/dist/executor-Cx5-8yqi.js.map +1 -0
- package/dist/extension-authoring-DyGGmq9V.js +385 -0
- package/dist/extension-authoring-DyGGmq9V.js.map +1 -0
- package/dist/extensions.d.ts +2 -2
- package/dist/extensions.js +3 -3
- package/dist/{fetch-url-DX75gpL0.js → fetch-url-Ct2TjDWt.js} +4 -4
- package/dist/{fetch-url-DX75gpL0.js.map → fetch-url-Ct2TjDWt.js.map} +1 -1
- package/dist/{format-BF745pLL.js → format-C2NQEVUH.js} +39 -2
- package/dist/format-C2NQEVUH.js.map +1 -0
- package/dist/format-bytes-C7tfc3Zm.js +55 -0
- package/dist/format-bytes-C7tfc3Zm.js.map +1 -0
- package/dist/headless-C_rNUuYC.js +960 -0
- package/dist/headless-C_rNUuYC.js.map +1 -0
- package/dist/headless.d.ts +1 -1
- package/dist/headless.js +1 -413
- package/dist/{history-search-C4bk1Wz_.js → history-search-CcYzF8-0.js} +7 -3
- package/dist/history-search-CcYzF8-0.js.map +1 -0
- package/dist/history-search-worker.d.ts +1 -1
- package/dist/history-search-worker.js +1 -1
- package/dist/host-D7NrI03V.js +378 -0
- package/dist/host-D7NrI03V.js.map +1 -0
- package/dist/host-signals-BcP5QKUD.js +118 -0
- package/dist/host-signals-BcP5QKUD.js.map +1 -0
- package/dist/identity-CwfO8K-t.js +26 -0
- package/dist/identity-CwfO8K-t.js.map +1 -0
- package/dist/{index-BgN1T3lk.d.ts → index-BGe1fQT7.d.ts} +10987 -9320
- package/dist/index-BGe1fQT7.d.ts.map +1 -0
- package/dist/index-BVQsIKGn.d.ts +448 -0
- package/dist/index-BVQsIKGn.d.ts.map +1 -0
- package/dist/{index-C6NEd5y_.d.ts → index-CHABJd-L.d.ts} +3386 -502
- package/dist/index-CHABJd-L.d.ts.map +1 -0
- package/dist/{index-C37_ppWv.d.ts → index-D6a7qXpg.d.ts} +2 -3
- package/dist/index-D6a7qXpg.d.ts.map +1 -0
- package/dist/index.d.ts +6 -6
- package/dist/index.js +27 -23
- package/dist/{completion-core-BRo86R_L.js → inline-ghost-BVRQeGoL.js} +50 -2
- package/dist/inline-ghost-BVRQeGoL.js.map +1 -0
- package/dist/ipc/remote.d.ts +313 -0
- package/dist/ipc/remote.d.ts.map +1 -0
- package/dist/ipc/remote.js +4 -0
- package/dist/ipc.d.ts +6 -964
- package/dist/ipc.js +403 -4
- package/dist/ipc.js.map +1 -0
- package/dist/{isolation-Kfoof0MM.d.ts → isolation-D9L650W5.d.ts} +100 -15
- package/dist/isolation-D9L650W5.d.ts.map +1 -0
- package/dist/json-rpc--HXQti1E.js +350 -0
- package/dist/json-rpc--HXQti1E.js.map +1 -0
- package/dist/links-j8rED1sR.js +603 -0
- package/dist/links-j8rED1sR.js.map +1 -0
- package/dist/local-terminal-D8QThwo_.js +252 -0
- package/dist/local-terminal-D8QThwo_.js.map +1 -0
- package/dist/{logger--C1VQjwJ.js → logger-Gtqlayx8.js} +199 -173
- package/dist/logger-Gtqlayx8.js.map +1 -0
- package/dist/logs-view-CWG8aUAG.js.map +1 -1
- package/dist/{mcp-CgNd-f3F.js → mcp-_wecH9Qe.js} +608 -562
- package/dist/mcp-_wecH9Qe.js.map +1 -0
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +2 -2
- package/dist/media-sniff-UKijEaiQ.js.map +1 -1
- package/dist/{messages-2jcOA_5R.js → messages-BqiwcD2Q.js} +1017 -1014
- package/dist/messages-BqiwcD2Q.js.map +1 -0
- package/dist/{oauth-DxHO17JE.js → oauth-Px_pBB9W.js} +5 -5
- package/dist/{oauth-DxHO17JE.js.map → oauth-Px_pBB9W.js.map} +1 -1
- package/dist/{openai-compat-Dy56weK8.js → openai-compat-CFrpH7uq.js} +432 -589
- package/dist/openai-compat-CFrpH7uq.js.map +1 -0
- package/dist/orchestration-BCGmB8Ps.js +511 -0
- package/dist/orchestration-BCGmB8Ps.js.map +1 -0
- package/dist/output/stream-json.d.ts +1 -2
- package/dist/output/stream-json.d.ts.map +1 -1
- package/dist/output/stream-json.js +1 -1
- package/dist/output/terminal.d.ts +1 -2
- package/dist/output/terminal.d.ts.map +1 -1
- package/dist/output/terminal.js +13 -7
- package/dist/output/terminal.js.map +1 -1
- package/dist/{plugins-gbI7SBA6.js → plugins-DS7mahzZ.js} +20 -101
- package/dist/plugins-DS7mahzZ.js.map +1 -0
- package/dist/plugins.d.ts +1 -1
- package/dist/plugins.js +1 -2
- package/dist/prelude-Cxo4t74B.js +517 -0
- package/dist/prelude-Cxo4t74B.js.map +1 -0
- package/dist/presets.d.ts +1 -1
- package/dist/presets.js +1 -2
- package/dist/project-root-B8zADr4o.js +167 -0
- package/dist/project-root-B8zADr4o.js.map +1 -0
- package/dist/project-user-paths-BSgtrRxl.js +58 -0
- package/dist/project-user-paths-BSgtrRxl.js.map +1 -0
- package/dist/{prompts-Pqc3JdW_.d.ts → prompts-DYcvqShf.d.ts} +14 -11
- package/dist/prompts-DYcvqShf.d.ts.map +1 -0
- package/dist/protocol-DnhqqSmE.js +13 -0
- package/dist/protocol-DnhqqSmE.js.map +1 -0
- package/dist/providers/anthropic.d.ts +2 -2
- package/dist/providers/anthropic.js +1 -2
- package/dist/providers/arcee.d.ts +1 -1
- package/dist/providers/arcee.js +1 -1
- package/dist/providers/baseten.d.ts +1 -1
- package/dist/providers/baseten.js +1 -1
- package/dist/providers/cerebras.d.ts +1 -1
- package/dist/providers/cerebras.js +3 -2
- package/dist/providers/cerebras.js.map +1 -1
- package/dist/providers/local.d.ts +1 -1
- package/dist/providers/local.js +1 -1
- package/dist/providers/openai-compat.d.ts +1 -1
- package/dist/providers/openai-compat.js +1 -2
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openai.js +15 -12
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/openrouter.d.ts +1 -1
- package/dist/providers/openrouter.js +3 -2
- package/dist/providers/openrouter.js.map +1 -1
- package/dist/providers/xai.d.ts +1 -1
- package/dist/providers/xai.js +3 -3
- package/dist/{providers-BVhnFyiY.js → providers-XUR7F4Hi.js} +4 -4
- package/dist/{providers-BVhnFyiY.js.map → providers-XUR7F4Hi.js.map} +1 -1
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +4 -4
- package/dist/registry-D6ShBWJU.js +5234 -0
- package/dist/registry-D6ShBWJU.js.map +1 -0
- package/dist/remote-hosts-BtA_9ZGp.js +97 -0
- package/dist/remote-hosts-BtA_9ZGp.js.map +1 -0
- package/dist/restate.d.ts +2 -3
- package/dist/restate.d.ts.map +1 -1
- package/dist/restate.js +631 -572
- package/dist/restate.js.map +1 -1
- package/dist/run-summary-CklLiZ4y.js +288 -0
- package/dist/run-summary-CklLiZ4y.js.map +1 -0
- package/dist/{sandbox-BH0WQkXn.d.ts → sandbox-C5dR5DwQ.d.ts} +6 -3
- package/dist/sandbox-C5dR5DwQ.d.ts.map +1 -0
- package/dist/session/sqlite.d.ts +1 -2
- package/dist/session/sqlite.d.ts.map +1 -1
- package/dist/session/sqlite.js +1 -616
- package/dist/session-factory-BUGY5P40.js +1576 -0
- package/dist/session-factory-BUGY5P40.js.map +1 -0
- package/dist/{session-BqRP1hS7.js → session-xh9JXu6i.js} +94 -52
- package/dist/session-xh9JXu6i.js.map +1 -0
- package/dist/session.d.ts +1 -1
- package/dist/session.js +2 -2
- package/dist/settings-keys-Ckf29NeM.js +677 -0
- package/dist/settings-keys-Ckf29NeM.js.map +1 -0
- package/dist/shell-path-Dqaoow2J.js +412 -0
- package/dist/shell-path-Dqaoow2J.js.map +1 -0
- package/dist/{skills-BC3dodWp.js → skills-DKqZJm4X.js} +430 -470
- package/dist/skills-DKqZJm4X.js.map +1 -0
- package/dist/skills.d.ts +2 -2
- package/dist/skills.js +1 -2
- package/dist/source-mPExaUm8.js +381 -0
- package/dist/source-mPExaUm8.js.map +1 -0
- package/dist/sqlite-DV1DQzN2.js +698 -0
- package/dist/sqlite-DV1DQzN2.js.map +1 -0
- package/dist/{src-CkNQKFKr.js → src-BRMYRJib.js} +903 -1121
- package/dist/src-BRMYRJib.js.map +1 -0
- package/dist/{stdio-DPpBDPx5.js → stdio-C6YyoW3I.js} +4 -4
- package/dist/{stdio-DPpBDPx5.js.map → stdio-C6YyoW3I.js.map} +1 -1
- package/dist/{stdio-loader-Bbx19dMZ.js → stdio-loader-C830Vg-Z.js} +4 -4
- package/dist/{stdio-loader-Bbx19dMZ.js.map → stdio-loader-C830Vg-Z.js.map} +1 -1
- package/dist/system-prompt-MNVHatSD.d.ts.map +1 -1
- package/dist/timeout-DEaqslLO.d.ts.map +1 -1
- package/dist/todo-edits-Dn251YUP.js +1790 -0
- package/dist/todo-edits-Dn251YUP.js.map +1 -0
- package/dist/{turn-operations-DrbJlpq9.js → tool-formatters-IQFDrdrs.js} +1456 -2120
- package/dist/tool-formatters-IQFDrdrs.js.map +1 -0
- package/dist/tool-state-Dku6YqAB.js +989 -0
- package/dist/tool-state-Dku6YqAB.js.map +1 -0
- package/dist/tools/fetch-url.d.ts +1 -2
- package/dist/tools/fetch-url.d.ts.map +1 -1
- package/dist/tools/fetch-url.js +1 -2
- package/dist/tools/prompts.d.ts +1 -1
- package/dist/tools/prompts.js +7 -7
- package/dist/tools/prompts.js.map +1 -1
- package/dist/tools/web-search.d.ts +1 -2
- package/dist/tools/web-search.d.ts.map +1 -1
- package/dist/tools/web-search.js +2 -2
- package/dist/tools/web-search.js.map +1 -1
- package/dist/tools-_DnT3AGM.js +578 -0
- package/dist/tools-_DnT3AGM.js.map +1 -0
- package/dist/tools.d.ts +3 -3
- package/dist/tools.js +4 -2
- package/dist/tui.d.ts +534 -517
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +34933 -27243
- package/dist/tui.js.map +1 -1
- package/dist/turn-operations-B8sokwi5.js +333 -0
- package/dist/turn-operations-B8sokwi5.js.map +1 -0
- package/dist/turn-operations-DQX5ZZni.d.ts +3089 -0
- package/dist/turn-operations-DQX5ZZni.d.ts.map +1 -0
- package/dist/types-C7ZFOztE.d.ts +132 -0
- package/dist/types-C7ZFOztE.d.ts.map +1 -0
- package/dist/types-CH5XpIHw.js +114 -0
- package/dist/types-CH5XpIHw.js.map +1 -0
- package/dist/{types-CWgENVLY.js → types-Cu0ZGDu9.js} +10 -6
- package/dist/types-Cu0ZGDu9.js.map +1 -0
- package/dist/types-IqegbJEE.d.ts +624 -0
- package/dist/types-IqegbJEE.d.ts.map +1 -0
- package/dist/types.d.ts +4 -4
- package/dist/types.js +1 -1
- package/dist/url-D8HCl65b.js +1259 -0
- package/dist/url-D8HCl65b.js.map +1 -0
- package/dist/wasm-BVT-j5cl.js +33 -0
- package/dist/wasm-BVT-j5cl.js.map +1 -0
- package/dist/workspace-exec-stream-SV2R9d5S.js +355 -0
- package/dist/workspace-exec-stream-SV2R9d5S.js.map +1 -0
- package/dist/ws-CIHMvlSh.js +952 -0
- package/dist/ws-CIHMvlSh.js.map +1 -0
- package/dist/ws-client-N7NxzvQp.js +230 -0
- package/dist/ws-client-N7NxzvQp.js.map +1 -0
- package/dist/{xai-CazjStOK.js → xai-CvJTeLrI.js} +165 -5
- package/dist/xai-CvJTeLrI.js.map +1 -0
- package/dist/xdg-zweed0-t.js +117 -0
- package/dist/xdg-zweed0-t.js.map +1 -0
- package/docs/ACP.md +52 -0
- package/docs/ARCHITECTURE.md +103 -6
- package/docs/ARTIFACTS.md +8 -4
- package/docs/CHAT.md +165 -14
- package/docs/EXECUTION_CONTEXT.md +8 -0
- package/docs/EXTENSIONS.md +123 -2
- package/docs/HEADLESS.md +2 -0
- package/docs/IPC.md +775 -64
- package/docs/MACHINES.md +456 -0
- package/docs/PANELS.md +3 -0
- package/docs/README.md +4 -0
- package/docs/RESTATE.md +3 -2
- package/docs/RUN_IN_BACKGROUND.md +10 -2
- package/docs/SERVER.md +1085 -0
- package/docs/SKILL.md +6 -1
- package/docs/TERMINAL.md +75 -0
- package/docs/TUI.md +65 -14
- package/package.json +58 -26
- package/scripts/eval.ts +4 -0
- package/dist/acp-D-tVyUjw.js.map +0 -1
- package/dist/agent-D0zZnGbt.js.map +0 -1
- package/dist/anthropic-C2aole0G.js.map +0 -1
- package/dist/approvals-DKaJZYlm.js.map +0 -1
- package/dist/atomic-write-B7zr1ddF.js.map +0 -1
- package/dist/auth-BG2rVKSt.js.map +0 -1
- package/dist/completion-core-BRo86R_L.js.map +0 -1
- package/dist/contexts/daytona.js.map +0 -1
- package/dist/contexts/docker.js.map +0 -1
- package/dist/contexts/e2b.js.map +0 -1
- package/dist/contexts-CRE9pw07.js.map +0 -1
- package/dist/eval.js.map +0 -1
- package/dist/format-BF745pLL.js.map +0 -1
- package/dist/glob-DluQFSw1.js +0 -270
- package/dist/glob-DluQFSw1.js.map +0 -1
- package/dist/headless.js.map +0 -1
- package/dist/history-search-C4bk1Wz_.js.map +0 -1
- package/dist/index-BgN1T3lk.d.ts.map +0 -1
- package/dist/index-C37_ppWv.d.ts.map +0 -1
- package/dist/index-C6NEd5y_.d.ts.map +0 -1
- package/dist/ipc-BKVIIOqH.js +0 -331
- package/dist/ipc-BKVIIOqH.js.map +0 -1
- package/dist/ipc.d.ts.map +0 -1
- package/dist/isolation-Kfoof0MM.d.ts.map +0 -1
- package/dist/json-rpc-rSWMUh9b.js +0 -192
- package/dist/json-rpc-rSWMUh9b.js.map +0 -1
- package/dist/logger--C1VQjwJ.js.map +0 -1
- package/dist/mcp-CgNd-f3F.js.map +0 -1
- package/dist/messages-2jcOA_5R.js.map +0 -1
- package/dist/openai-compat-Dy56weK8.js.map +0 -1
- package/dist/output-cap-C9zukcCj.js +0 -100
- package/dist/output-cap-C9zukcCj.js.map +0 -1
- package/dist/panels-B6gRk4bf.js +0 -789
- package/dist/panels-B6gRk4bf.js.map +0 -1
- package/dist/plugins-gbI7SBA6.js.map +0 -1
- package/dist/prompts-Pqc3JdW_.d.ts.map +0 -1
- package/dist/run-summary-BU_NgwUT.js +0 -269
- package/dist/run-summary-BU_NgwUT.js.map +0 -1
- package/dist/sandbox-BH0WQkXn.d.ts.map +0 -1
- package/dist/session/sqlite.js.map +0 -1
- package/dist/session-BqRP1hS7.js.map +0 -1
- package/dist/shell-path-DfdXrGg9.js +0 -1549
- package/dist/shell-path-DfdXrGg9.js.map +0 -1
- package/dist/skills-BC3dodWp.js.map +0 -1
- package/dist/src-CkNQKFKr.js.map +0 -1
- package/dist/todo-edits-UOwgxGKu.js +0 -528
- package/dist/todo-edits-UOwgxGKu.js.map +0 -1
- package/dist/tool-formatters-DoRLnfuD.d.ts +0 -759
- package/dist/tool-formatters-DoRLnfuD.d.ts.map +0 -1
- package/dist/transcript-anchors-BeudMbXx.d.ts +0 -1762
- package/dist/transcript-anchors-BeudMbXx.d.ts.map +0 -1
- package/dist/turn-operations-C8bMBDl_.d.ts +0 -1258
- package/dist/turn-operations-C8bMBDl_.d.ts.map +0 -1
- package/dist/turn-operations-DrbJlpq9.js.map +0 -1
- package/dist/types-CWgENVLY.js.map +0 -1
- package/dist/xai-CazjStOK.js.map +0 -1
|
@@ -0,0 +1,677 @@
|
|
|
1
|
+
import { t as resolveStorageDirs } from "./xdg-zweed0-t.js";
|
|
2
|
+
import { n as JsonRpcRemoteError, t as JsonRpcConnectionClosedError } from "./json-rpc--HXQti1E.js";
|
|
3
|
+
import { a as HOST_ENABLED_LISTS, s as isWindowOnlySetting } from "./registry-D6ShBWJU.js";
|
|
4
|
+
import { g as isMethodNotFound } from "./types-CH5XpIHw.js";
|
|
5
|
+
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
6
|
+
import { basename, dirname, join } from "node:path";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { createHash } from "node:crypto";
|
|
9
|
+
import { spawn } from "node:child_process";
|
|
10
|
+
import { connect } from "node:net";
|
|
11
|
+
//#region src/ipc/daemon/lifecycle.ts
|
|
12
|
+
/**
|
|
13
|
+
* Daemon lifecycle: socket-path resolution, liveness probing, stale-socket
|
|
14
|
+
* cleanup, and spawn-on-demand.
|
|
15
|
+
*
|
|
16
|
+
* The socket lives in a dedicated daemon subdir of the resolved state dir
|
|
17
|
+
* (`~/.zidane/daemon/daemon.sock` by default, honoring the same
|
|
18
|
+
* `ZIDANE_STORAGE_DIR` / `ZIDANE_PREFIX` env knobs every other surface
|
|
19
|
+
* uses), overridable via `ZIDANE_DAEMON_SOCKET` for parallel installs and
|
|
20
|
+
* tests.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Build fingerprint for the handshake — the mtime of this module's file
|
|
24
|
+
* at import time. Client and daemon load the same file from disk, so a
|
|
25
|
+
* daemon spawned before a rebuild (or a source edit in dev) reports a
|
|
26
|
+
* different id than a freshly-started client, and the client drains +
|
|
27
|
+
* respawns it. This closes the "same protocol version, different code"
|
|
28
|
+
* gap that a hand-bumped version constant can't: during development the
|
|
29
|
+
* daemon process is frozen at spawn while the tree keeps moving.
|
|
30
|
+
*
|
|
31
|
+
* Compiled binaries (`/$bunfs/…` virtual paths) can't be stat'ed and
|
|
32
|
+
* report `'unknown'`; the check is skipped when EITHER side is unknown,
|
|
33
|
+
* so released builds rely on `IPC_PROTOCOL_VERSION` alone — correct,
|
|
34
|
+
* since their code only changes when the version does.
|
|
35
|
+
*/
|
|
36
|
+
const IPC_BUILD_ID = (() => {
|
|
37
|
+
try {
|
|
38
|
+
const selfPath = fileURLToPath(import.meta.url);
|
|
39
|
+
const ipcRoot = dirname(dirname(selfPath));
|
|
40
|
+
if (!existsSync(join(ipcRoot, "protocol.ts"))) return String(Math.floor(statSync(selfPath).mtimeMs));
|
|
41
|
+
const srcRoot = dirname(ipcRoot);
|
|
42
|
+
let newest = 0;
|
|
43
|
+
const walk = (dir) => {
|
|
44
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
45
|
+
const full = join(dir, entry.name);
|
|
46
|
+
if (entry.isDirectory()) walk(full);
|
|
47
|
+
else newest = Math.max(newest, statSync(full).mtimeMs);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
try {
|
|
51
|
+
walk(srcRoot);
|
|
52
|
+
} catch {
|
|
53
|
+
newest = statSync(selfPath).mtimeMs;
|
|
54
|
+
}
|
|
55
|
+
return String(Math.floor(newest));
|
|
56
|
+
} catch {
|
|
57
|
+
return "unknown";
|
|
58
|
+
}
|
|
59
|
+
})();
|
|
60
|
+
/**
|
|
61
|
+
* Socket file name. Dev builds (`ZIDANE_DEV=1`, set by every `dev` script
|
|
62
|
+
* in the repo) get their OWN socket so a checkout's TUI, GUI and `zidane
|
|
63
|
+
* daemon` pair up among themselves and never attach to — or get refused by
|
|
64
|
+
* — the installed daemon. Without this, a protocol bump in the working
|
|
65
|
+
* tree turned the dev GUI's dot red against the stable daemon, and a dev
|
|
66
|
+
* daemon could drain the one the installed TUI relies on.
|
|
67
|
+
*/
|
|
68
|
+
function daemonSocketName(env = process.env) {
|
|
69
|
+
return env.ZIDANE_DEV && env.ZIDANE_DEV !== "0" ? "dev.sock" : "daemon.sock";
|
|
70
|
+
}
|
|
71
|
+
function defaultSocketPath() {
|
|
72
|
+
const explicit = process.env.ZIDANE_DAEMON_SOCKET;
|
|
73
|
+
if (explicit) return explicit;
|
|
74
|
+
const dirs = resolveStorageDirs({ ...process.env.ZIDANE_PREFIX !== void 0 ? { prefix: process.env.ZIDANE_PREFIX } : {} });
|
|
75
|
+
return join(dirs.stateDir, "daemon", daemonSocketName());
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Pre-v6 socket location for the given (v6) socket path, or null when the
|
|
79
|
+
* path isn't the default `<stateDir>/daemon/daemon.sock` layout (explicit
|
|
80
|
+
* `ZIDANE_DAEMON_SOCKET` users never had a migration to run). A daemon
|
|
81
|
+
* still serving the old path would be ORPHANED by the move — new clients
|
|
82
|
+
* never probe it, and a service-style `--idle-exit 0` daemon would hold
|
|
83
|
+
* agents and run-guard markers against the same sessions.db forever —
|
|
84
|
+
* so daemon startup probes this path and drains any survivor.
|
|
85
|
+
*/
|
|
86
|
+
function legacySocketPath(socketPath) {
|
|
87
|
+
const dir = dirname(socketPath);
|
|
88
|
+
if (basename(socketPath) !== "daemon.sock" || basename(dir) !== "daemon") return null;
|
|
89
|
+
return join(dirname(dir), "daemon.sock");
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Spawn command that re-enters the CURRENT zidane program as `… daemon`.
|
|
93
|
+
*
|
|
94
|
+
* Three launch shapes:
|
|
95
|
+
* - compiled Bun binary — `Bun.main` is the virtual `/$bunfs/…` entry the
|
|
96
|
+
* binary self-inserts as argv[1], so the spawn must NOT repeat it
|
|
97
|
+
* (verified: repeating it makes the child parse the junk path as its
|
|
98
|
+
* subcommand and boot the full TUI instead of the daemon).
|
|
99
|
+
* - dev (`bun run cli.ts`) — the script path must ride along.
|
|
100
|
+
* - Node hosts (no `Bun` global) — fall back to the published bin.
|
|
101
|
+
*/
|
|
102
|
+
function selfDaemonSpawnCommand() {
|
|
103
|
+
const bunMain = globalThis.Bun?.main;
|
|
104
|
+
if (bunMain?.startsWith("/$bunfs")) return [process.execPath, "daemon"];
|
|
105
|
+
if (bunMain && /(?:^|[/\\])cli\.[cm]?[jt]s$/.test(bunMain)) return [
|
|
106
|
+
process.execPath,
|
|
107
|
+
bunMain,
|
|
108
|
+
"daemon"
|
|
109
|
+
];
|
|
110
|
+
return ["zidane-daemon"];
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* True when something accepts connections on `socketPath`. Distinguishes a
|
|
114
|
+
* live daemon from a stale socket file left by a crashed one.
|
|
115
|
+
*/
|
|
116
|
+
function probeSocket(socketPath, timeoutMs = 1e3) {
|
|
117
|
+
return new Promise((resolve) => {
|
|
118
|
+
try {
|
|
119
|
+
if (!existsSync(socketPath) || !statSync(socketPath).isSocket()) {
|
|
120
|
+
resolve(false);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
} catch {
|
|
124
|
+
resolve(false);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
let socket;
|
|
128
|
+
try {
|
|
129
|
+
socket = connect(socketPath);
|
|
130
|
+
} catch {
|
|
131
|
+
resolve(false);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const done = (alive) => {
|
|
135
|
+
socket.destroy();
|
|
136
|
+
resolve(alive);
|
|
137
|
+
};
|
|
138
|
+
socket.once("connect", () => done(true));
|
|
139
|
+
socket.once("error", () => done(false));
|
|
140
|
+
socket.setTimeout(timeoutMs, () => done(false));
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Make sure a daemon is listening, spawning one if needed. Resolves with
|
|
145
|
+
* the socket path once a connection succeeds; rejects when the daemon
|
|
146
|
+
* failed to come up within `timeoutMs`.
|
|
147
|
+
*/
|
|
148
|
+
const pendingStarts = /* @__PURE__ */ new Map();
|
|
149
|
+
function ensureDaemonRunning(options = {}) {
|
|
150
|
+
const socketPath = options.socketPath ?? defaultSocketPath();
|
|
151
|
+
const pending = pendingStarts.get(socketPath);
|
|
152
|
+
if (pending) return pending;
|
|
153
|
+
const start = startDaemon({
|
|
154
|
+
...options,
|
|
155
|
+
socketPath
|
|
156
|
+
}).finally(() => pendingStarts.delete(socketPath));
|
|
157
|
+
pendingStarts.set(socketPath, start);
|
|
158
|
+
return start;
|
|
159
|
+
}
|
|
160
|
+
async function startDaemon(options) {
|
|
161
|
+
const socketPath = options.socketPath;
|
|
162
|
+
if (await probeSocket(socketPath)) return socketPath;
|
|
163
|
+
const [cmd, ...args] = options.spawnCommand ?? ["zidane-daemon"];
|
|
164
|
+
const child = spawn(cmd, args, {
|
|
165
|
+
detached: true,
|
|
166
|
+
stdio: "ignore",
|
|
167
|
+
env: {
|
|
168
|
+
...process.env,
|
|
169
|
+
ZIDANE_DAEMON_SOCKET: socketPath
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
let spawnError;
|
|
173
|
+
child.once("error", (err) => {
|
|
174
|
+
spawnError = err;
|
|
175
|
+
});
|
|
176
|
+
child.unref();
|
|
177
|
+
const deadline = Date.now() + (options.timeoutMs ?? 8e3);
|
|
178
|
+
for (;;) {
|
|
179
|
+
if (spawnError !== void 0) throw new Error(`Failed to spawn zidane daemon (${cmd}): ${spawnError.message}`);
|
|
180
|
+
if (await probeSocket(socketPath)) return socketPath;
|
|
181
|
+
if (Date.now() > deadline) throw new Error(`zidane daemon did not come up on ${socketPath} within ${options.timeoutMs ?? 8e3}ms.`);
|
|
182
|
+
await new Promise((r) => setTimeout(r, 150));
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
//#endregion
|
|
186
|
+
//#region src/version.ts
|
|
187
|
+
/**
|
|
188
|
+
* The version of the zidane code this process is running — `package.json`
|
|
189
|
+
* inlined at build time (Bun `--compile`, tsdown for `dist/`, and Vite for
|
|
190
|
+
* the GUI main all fold JSON imports into the bundle, so this never reads
|
|
191
|
+
* the filesystem at runtime and cannot report a NEIGHBOUR package's version
|
|
192
|
+
* the way a `require('../package.json')` from a bundled chunk can).
|
|
193
|
+
*
|
|
194
|
+
* Used by the daemon handshake: a client running newer code than the daemon
|
|
195
|
+
* retires it, so an upgrade can never leave windows silently executing on a
|
|
196
|
+
* process started from the previous release.
|
|
197
|
+
*/
|
|
198
|
+
const ZIDANE_VERSION = "8.0.4";
|
|
199
|
+
/**
|
|
200
|
+
* Compare two dotted versions (`7.0.19`, `7.1.0-beta.1`): negative when `a`
|
|
201
|
+
* is older, positive when newer, 0 when equal. Pre-release tags are ignored
|
|
202
|
+
* — same release train, same code as far as the daemon fence is concerned.
|
|
203
|
+
* Unparseable input compares equal (never fences on garbage).
|
|
204
|
+
*/
|
|
205
|
+
function compareVersions(a, b) {
|
|
206
|
+
const pa = parse(a);
|
|
207
|
+
const pb = parse(b);
|
|
208
|
+
if (!pa || !pb) return 0;
|
|
209
|
+
for (let i = 0; i < 3; i++) {
|
|
210
|
+
const d = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
211
|
+
if (d !== 0) return d;
|
|
212
|
+
}
|
|
213
|
+
return 0;
|
|
214
|
+
}
|
|
215
|
+
function parse(v) {
|
|
216
|
+
const m = /^v?(\d+)\.(\d+)\.(\d+)/.exec(v.trim());
|
|
217
|
+
return m ? [
|
|
218
|
+
Number(m[1]),
|
|
219
|
+
Number(m[2]),
|
|
220
|
+
Number(m[3])
|
|
221
|
+
] : null;
|
|
222
|
+
}
|
|
223
|
+
//#endregion
|
|
224
|
+
//#region src/ipc/protocol.ts
|
|
225
|
+
/**
|
|
226
|
+
* v6 (changes since v5):
|
|
227
|
+
* - `event` signals carry an optional `echo` flag marking host-generated
|
|
228
|
+
* SEND/STEER echoes of the user's own message.
|
|
229
|
+
* - `chat.pushQueued` result gained the `'queued'` delivered variant.
|
|
230
|
+
* - `sessions.setModel` now honors `fallbacks`: it persists the canonical
|
|
231
|
+
* `metadata.modelChain` and CLEARS a previously persisted chain when
|
|
232
|
+
* omitted/empty. It also accepts `effort` / `modelOptions` and resets
|
|
233
|
+
* both when omitted (a pick is atomic — no stale per-model knobs).
|
|
234
|
+
* - additive: `extension.emit` notification + `extension:signal` fan-out
|
|
235
|
+
* (the permission-gated per-extension cross-window bus, `ctx.bus`).
|
|
236
|
+
* Older daemons ignore the unknown notification; older clients drop the
|
|
237
|
+
* unknown signal kind — no version bump needed.
|
|
238
|
+
* - additive: `extension.emit` / `extension:signal` carry an optional
|
|
239
|
+
* `nonce` (the emitter's per-process random id) so receivers dedupe on
|
|
240
|
+
* `(extensionId, nonce, seq)` instead of the collision-prone
|
|
241
|
+
* `(extensionId, seq)`. Older peers omit it and fall back to the
|
|
242
|
+
* seq-only key — no version bump needed.
|
|
243
|
+
* - `SessionRow.modelFallbacks` is now populated from the session's
|
|
244
|
+
* persisted `metadata.modelChain`.
|
|
245
|
+
* - Default socket path moved from `<stateDir>/daemon.sock` to the
|
|
246
|
+
* dedicated `<stateDir>/daemon/daemon.sock` (dir chmod'd 0700) so the
|
|
247
|
+
* daemon can harden its socket dir without touching shared state files.
|
|
248
|
+
* - ADDITIVE (no version bump — older daemons answer "method not
|
|
249
|
+
* found", clients degrade to local compute): `suggest.resolve` RPC
|
|
250
|
+
* resolves inline ghost-text autocomplete daemon-side, and the
|
|
251
|
+
* `suggest:changed` signal fans the result out to every OTHER peer
|
|
252
|
+
* on the session so mirroring windows paint the same ghost without
|
|
253
|
+
* recomputing.
|
|
254
|
+
* - ADDITIVE (no version bump — optional field, older daemons simply
|
|
255
|
+
* omit it and clients fall back to the single `suggestion`):
|
|
256
|
+
* `suggest.resolve` results and `suggest:changed` signals carry the
|
|
257
|
+
* resolver's full ordered `candidates` list so daemon mode keeps
|
|
258
|
+
* ↑/↓ candidate rotation instead of degrading to one suggestion.
|
|
259
|
+
* - ADDITIVE (no version bump — `optional()` swallows "method not
|
|
260
|
+
* found" on an older daemon, which then simply keeps its stale
|
|
261
|
+
* registries as before): `runtime.reload` RPC drops the daemon's
|
|
262
|
+
* cached extension registries and retires live agents after a window
|
|
263
|
+
* reloaded its extensions.
|
|
264
|
+
* - ADDITIVE (no version bump): `terminal.registerViewer` /
|
|
265
|
+
* `terminal.unregisterViewer`. The desktop app registers as a client that
|
|
266
|
+
* can show terminals; agents only get terminal tools while one is
|
|
267
|
+
* attached. An older daemon answers "method not found" (and keeps giving
|
|
268
|
+
* every agent the tools, as before); an older desktop app on a newer
|
|
269
|
+
* daemon never registers, so its agents run without terminal tools.
|
|
270
|
+
* - ADDITIVE (no version bump): `queue.attachments` returns a queued
|
|
271
|
+
* entry's attachments with their bytes, and `queue.update` accepts
|
|
272
|
+
* `attachments` to replace them. An older daemon answers "method not
|
|
273
|
+
* found" / ignores the field: the entry's attachments stay as queued.
|
|
274
|
+
* - ADDITIVE (no version bump): `chat.steer` / `chat.followUp` resolve to
|
|
275
|
+
* whether the message reached a live run. Older daemons resolve `null`,
|
|
276
|
+
* which clients treat as delivered (the pre-existing behavior).
|
|
277
|
+
* - ADDITIVE (no version bump): `sessions.fork`, `sessions.deleteTurn`,
|
|
278
|
+
* `sessions.editTurnText`, `sessions.setFolder`, `sessions.appendTurns`.
|
|
279
|
+
* History and folder edits run in the host instead of being written to
|
|
280
|
+
* the store by the client (then `sessions.touch` + `chat.rebuildAgent`).
|
|
281
|
+
* Older clients keep the old path, which still works on a shared disk.
|
|
282
|
+
* A newer client only meets an older daemon while it retires (the
|
|
283
|
+
* release fence drains it otherwise), and then gets "method not found".
|
|
284
|
+
* - ADDITIVE (no version bump): `sessions.listMeta`, `sessions.getMeta`,
|
|
285
|
+
* `sessions.get`, `sessions.setExtensionState` serve a client the
|
|
286
|
+
* session data it used to read and write in its own store, so a window
|
|
287
|
+
* on another machine sees the host's sessions. `sessions.create` accepts `id`, `effort`, `modelOptions` and
|
|
288
|
+
* `pinnedSkills`; `todos.set` accepts `persistIdle`. An older host answers
|
|
289
|
+
* "method not found" / ignores the fields: a window falls back to the
|
|
290
|
+
* store it shares with a local daemon, and refuses a remote host.
|
|
291
|
+
*/
|
|
292
|
+
const IPC_PROTOCOL_VERSION = 13;
|
|
293
|
+
/**
|
|
294
|
+
* JSON-RPC error codes specific to the zidane daemon. Lives here (not in
|
|
295
|
+
* `daemon/server.ts`) so clients can import the codes without pulling the
|
|
296
|
+
* server's module graph.
|
|
297
|
+
*/
|
|
298
|
+
const IpcErrorCode = {
|
|
299
|
+
VersionMismatch: -32010,
|
|
300
|
+
NotHandshaken: -32011,
|
|
301
|
+
/** A network transport's per-connection request budget is spent; retry later. */
|
|
302
|
+
RateLimited: -32012,
|
|
303
|
+
/**
|
|
304
|
+
* The reply would exceed the transport's message size: nothing was sent
|
|
305
|
+
* but this error (the connection stays). Ask for less (a transcript: a
|
|
306
|
+
* smaller page, see {@link loadAllEvents}).
|
|
307
|
+
*/
|
|
308
|
+
ResponseTooLarge: -32013,
|
|
309
|
+
/**
|
|
310
|
+
* The handler threw: the host refused or failed the call (`message` says
|
|
311
|
+
* why). Hosts before it answered -32000, which ACP uses for
|
|
312
|
+
* `AuthenticationRequired`; clients treat both as a plain remote error.
|
|
313
|
+
*/
|
|
314
|
+
HandlerFailed: -32014
|
|
315
|
+
};
|
|
316
|
+
/**
|
|
317
|
+
* Client heartbeat request (`{}` → `{}`), outside the method table: every
|
|
318
|
+
* host answers it, before the handshake too. A host predating it answers
|
|
319
|
+
* "method not found", which still proves it alive.
|
|
320
|
+
*/
|
|
321
|
+
const PING_METHOD = "$/ping";
|
|
322
|
+
/**
|
|
323
|
+
* Session-scoped signals fanned out to every peer carry their number in
|
|
324
|
+
* their session as this extra field on the `ipc.signal` params (clients
|
|
325
|
+
* predating it ignore it; `IpcClient` strips it and hands it to listeners as
|
|
326
|
+
* {@link SignalMeta}). Per session, from 1, gap-free within one host process.
|
|
327
|
+
*/
|
|
328
|
+
const SIGNAL_SEQ_FIELD = "$seq";
|
|
329
|
+
/** The host's identity from a hello (or `daemon.info`) reply; `null` from a host that predates it. */
|
|
330
|
+
function hostRefOf(hello) {
|
|
331
|
+
if (typeof hello.hostId !== "string" || !hello.hostKind) return null;
|
|
332
|
+
return {
|
|
333
|
+
id: hello.hostId,
|
|
334
|
+
kind: hello.hostKind,
|
|
335
|
+
name: hello.hostName ?? hello.hostId
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
/** Turns per `sessions.loadEvents` page when only `before` is given. */
|
|
339
|
+
const LOAD_EVENTS_PAGE_TURNS = 200;
|
|
340
|
+
/** Largest `limit` a host honors. */
|
|
341
|
+
const LOAD_EVENTS_MAX_PAGE_TURNS = 1e3;
|
|
342
|
+
/**
|
|
343
|
+
* One page of `sessions.loadEvents` (see its paging). An older host answers
|
|
344
|
+
* the whole transcript: it comes back as one page with no cursor.
|
|
345
|
+
*/
|
|
346
|
+
async function loadEventsPage(request, params) {
|
|
347
|
+
const result = await request("sessions.loadEvents", params);
|
|
348
|
+
return Array.isArray(result) ? { events: result } : result;
|
|
349
|
+
}
|
|
350
|
+
function isResponseTooLarge(err) {
|
|
351
|
+
return typeof err === "object" && err !== null && err.code === IpcErrorCode.ResponseTooLarge;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* A session's whole transcript, loaded a page at a time from the end so no
|
|
355
|
+
* single reply carries it all (a long session with images can outgrow a
|
|
356
|
+
* transport's message size). A page refused as too large is asked again at
|
|
357
|
+
* half the turns, down to one; a single turn that still doesn't fit fails
|
|
358
|
+
* the load. An older host answers the whole transcript to the first call.
|
|
359
|
+
*/
|
|
360
|
+
async function loadAllEvents(request, sessionId, options = {}) {
|
|
361
|
+
return (await loadEventsFromEnd(request, sessionId, options.pageTurns ?? 200)).events;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* The end of a session's transcript: pages from the end until `enough`
|
|
365
|
+
* holds for what was loaded (or the first turn is in), and how many events
|
|
366
|
+
* of the whole replay come before it (`earlier`). Only exact pages can stop
|
|
367
|
+
* early, since only they say where they start: an older host's transcript
|
|
368
|
+
* loads whole, with `earlier` 0.
|
|
369
|
+
*/
|
|
370
|
+
async function loadEventsTail(request, sessionId, enough, options = {}) {
|
|
371
|
+
return loadEventsFromEnd(request, sessionId, options.pageTurns ?? 200, enough);
|
|
372
|
+
}
|
|
373
|
+
async function loadEventsFromEnd(request, sessionId, pageTurns, enough) {
|
|
374
|
+
let limit = pageTurns;
|
|
375
|
+
const pages = [];
|
|
376
|
+
let newerExact = false;
|
|
377
|
+
let allExact = true;
|
|
378
|
+
let before;
|
|
379
|
+
for (;;) {
|
|
380
|
+
let page;
|
|
381
|
+
try {
|
|
382
|
+
page = await loadEventsPage(request, {
|
|
383
|
+
sessionId,
|
|
384
|
+
limit,
|
|
385
|
+
...before !== void 0 ? { before } : {}
|
|
386
|
+
});
|
|
387
|
+
} catch (err) {
|
|
388
|
+
if (isResponseTooLarge(err) && limit > 1) {
|
|
389
|
+
limit = Math.max(1, Math.floor(limit / 2));
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
throw err;
|
|
393
|
+
}
|
|
394
|
+
const newer = pages[0];
|
|
395
|
+
if (newer && !newerExact && newer[0]?.kind === "user-prompt" && page.events.length > 0) newer.unshift({
|
|
396
|
+
kind: "separator",
|
|
397
|
+
text: ""
|
|
398
|
+
});
|
|
399
|
+
newerExact = page.exact === true;
|
|
400
|
+
allExact &&= newerExact && page.start !== void 0;
|
|
401
|
+
pages.unshift(page.events);
|
|
402
|
+
if (page.cursor === void 0 || page.cursor <= 0 || before !== void 0 && page.cursor >= before) break;
|
|
403
|
+
if (enough && allExact) {
|
|
404
|
+
const events = pages.flat();
|
|
405
|
+
if (enough(events)) return {
|
|
406
|
+
events,
|
|
407
|
+
earlier: page.start
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
before = page.cursor;
|
|
411
|
+
}
|
|
412
|
+
return {
|
|
413
|
+
events: pages.flat(),
|
|
414
|
+
earlier: 0
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
/** Turns per `sessions.getTurns` page by default. */
|
|
418
|
+
const SESSION_TURNS_PAGE = 200;
|
|
419
|
+
/** Largest `limit` a host honors for `sessions.getTurns`. */
|
|
420
|
+
const SESSION_TURNS_MAX_PAGE = 1e3;
|
|
421
|
+
/** How many times a paged read starts over because the session changed under it, before it asks for the whole document in one reply. */
|
|
422
|
+
const SESSION_DOCUMENT_RESTARTS = 3;
|
|
423
|
+
/**
|
|
424
|
+
* A session's whole document, read a page of turns at a time so no reply
|
|
425
|
+
* carries it all (`sessions.getTurns` pages, then the `sessions.get`
|
|
426
|
+
* `turns: false` head; a page refused as too large is asked again at half
|
|
427
|
+
* the turns). Every page and the head name the snapshot they come from: a
|
|
428
|
+
* version change mid-read (a turn appended, a compaction) starts the read
|
|
429
|
+
* over, so the result is one version, never pages of two. After
|
|
430
|
+
* {@link SESSION_DOCUMENT_RESTARTS} restarts (a session busier than the
|
|
431
|
+
* read), the whole document comes in one reply. A host that predates
|
|
432
|
+
* `sessions.getTurns` sends it that way too; one that names no version is
|
|
433
|
+
* read as before. `null` when the host doesn't know the session.
|
|
434
|
+
*/
|
|
435
|
+
async function loadSessionDocument(request, sessionId, options = {}) {
|
|
436
|
+
const paging = { limit: options.pageTurns ?? 200 };
|
|
437
|
+
for (let attempt = 0; attempt <= SESSION_DOCUMENT_RESTARTS; attempt++) {
|
|
438
|
+
const read = await readSessionDocumentOnce(request, sessionId, paging);
|
|
439
|
+
if (read !== "changed") return read;
|
|
440
|
+
}
|
|
441
|
+
return withoutVersion(await request("sessions.get", { sessionId }));
|
|
442
|
+
}
|
|
443
|
+
function withoutVersion(head) {
|
|
444
|
+
if (!head) return null;
|
|
445
|
+
const { version: _version, ...data } = head;
|
|
446
|
+
return data;
|
|
447
|
+
}
|
|
448
|
+
/** One paged read; `'changed'`: the version moved between two of its replies. */
|
|
449
|
+
async function readSessionDocumentOnce(request, sessionId, paging) {
|
|
450
|
+
const turns = [];
|
|
451
|
+
let total = Infinity;
|
|
452
|
+
let version = null;
|
|
453
|
+
while (turns.length < total) {
|
|
454
|
+
let page;
|
|
455
|
+
try {
|
|
456
|
+
page = await request("sessions.getTurns", {
|
|
457
|
+
sessionId,
|
|
458
|
+
from: turns.length,
|
|
459
|
+
limit: paging.limit
|
|
460
|
+
});
|
|
461
|
+
} catch (err) {
|
|
462
|
+
if (turns.length === 0 && isMethodNotFound(err)) return withoutVersion(await request("sessions.get", { sessionId }));
|
|
463
|
+
if (isResponseTooLarge(err) && paging.limit > 1) {
|
|
464
|
+
paging.limit = Math.max(1, Math.floor(paging.limit / 2));
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
throw err;
|
|
468
|
+
}
|
|
469
|
+
if (!page) return null;
|
|
470
|
+
if (version === null) version = { ...page.version !== void 0 ? { of: page.version } : {} };
|
|
471
|
+
else if (page.version !== version.of) return "changed";
|
|
472
|
+
total = page.total;
|
|
473
|
+
if (page.turns.length === 0) break;
|
|
474
|
+
turns.push(...page.turns);
|
|
475
|
+
}
|
|
476
|
+
const head = await request("sessions.get", {
|
|
477
|
+
sessionId,
|
|
478
|
+
turns: false
|
|
479
|
+
});
|
|
480
|
+
if (!head) return null;
|
|
481
|
+
if (version !== null && head.version !== version.of) return "changed";
|
|
482
|
+
return {
|
|
483
|
+
...withoutVersion(head),
|
|
484
|
+
turns
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
/** Every secret-bearing value of a catalog entry is replaced by this. */
|
|
488
|
+
const REDACTED = "<redacted>";
|
|
489
|
+
//#endregion
|
|
490
|
+
//#region src/ipc/transports/client-core.ts
|
|
491
|
+
var IpcVersionMismatchError = class extends Error {
|
|
492
|
+
daemon;
|
|
493
|
+
constructor(message, daemon) {
|
|
494
|
+
super(message);
|
|
495
|
+
this.daemon = daemon;
|
|
496
|
+
this.name = "IpcVersionMismatchError";
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
/** Starts the client heartbeat on `channel`; returns its stop. Stops itself once the channel closes. */
|
|
500
|
+
function startHeartbeat(channel, intervalMs) {
|
|
501
|
+
let awaiting = false;
|
|
502
|
+
let missed = 0;
|
|
503
|
+
const timer = setInterval(() => {
|
|
504
|
+
if (awaiting && ++missed >= 2) {
|
|
505
|
+
clearInterval(timer);
|
|
506
|
+
channel.abort();
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
awaiting = true;
|
|
510
|
+
channel.rpc.sendRequest(PING_METHOD, {}).then(() => {
|
|
511
|
+
awaiting = false;
|
|
512
|
+
missed = 0;
|
|
513
|
+
}, (err) => {
|
|
514
|
+
if (err instanceof JsonRpcConnectionClosedError) {
|
|
515
|
+
clearInterval(timer);
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
awaiting = false;
|
|
519
|
+
missed = 0;
|
|
520
|
+
});
|
|
521
|
+
}, intervalMs);
|
|
522
|
+
timer.unref?.();
|
|
523
|
+
return () => clearInterval(timer);
|
|
524
|
+
}
|
|
525
|
+
/** The signal listeners of one client, and the JSON-RPC notification handler that feeds them. */
|
|
526
|
+
function createSignalListeners() {
|
|
527
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
528
|
+
return {
|
|
529
|
+
listeners,
|
|
530
|
+
onNotification(message) {
|
|
531
|
+
if (message.method !== "ipc.signal") return;
|
|
532
|
+
const params = message.params;
|
|
533
|
+
if (!params) return;
|
|
534
|
+
const { [SIGNAL_SEQ_FIELD]: seq, ...signal } = params;
|
|
535
|
+
const meta = typeof seq === "number" ? { seq } : void 0;
|
|
536
|
+
for (const cb of listeners) cb(signal, meta);
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
function hostRelease(hello) {
|
|
541
|
+
for (const value of [hello.codeVersion, hello.appVersion]) {
|
|
542
|
+
if (typeof value !== "string") continue;
|
|
543
|
+
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());
|
|
544
|
+
if (match) return match[1];
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
const HELLO_TIMEOUT_MS = 5e3;
|
|
548
|
+
const LONG_REQUEST_TIMEOUT_MS = 6e5;
|
|
549
|
+
/** RPCs that legitimately run long — full compaction, index-backed cross-session search. */
|
|
550
|
+
const LONG_REQUEST_METHODS = /* @__PURE__ */ new Set([
|
|
551
|
+
"sessions.compact",
|
|
552
|
+
"history.searchAll",
|
|
553
|
+
"history.searchSession"
|
|
554
|
+
]);
|
|
555
|
+
/**
|
|
556
|
+
* A refused handshake. Asks the host to drain when `drain` allows it, closes
|
|
557
|
+
* the channel, and returns the error to throw.
|
|
558
|
+
*/
|
|
559
|
+
async function refusedHello(channel, err, drain) {
|
|
560
|
+
const daemon = err.data?.daemon;
|
|
561
|
+
if (daemon?.hostKind === "server") {
|
|
562
|
+
channel.close();
|
|
563
|
+
return new IpcVersionMismatchError(serverMismatchMessage(daemon, channel.where) ?? err.message, daemon);
|
|
564
|
+
}
|
|
565
|
+
const daemonIsOlderRelease = typeof daemon?.codeVersion === "string" && compareVersions(daemon.codeVersion, ZIDANE_VERSION) < 0;
|
|
566
|
+
const release = daemon && hostRelease(daemon);
|
|
567
|
+
const daemonIsNewerRelease = release !== void 0 && compareVersions(release, ZIDANE_VERSION) > 0;
|
|
568
|
+
const daemonSpeaksOlderProtocol = typeof daemon?.protocolVersion === "number" && daemon.protocolVersion < 13;
|
|
569
|
+
if (drain !== "never" && !daemonIsNewerRelease && (drain === "always" || daemonIsOlderRelease || daemonSpeaksOlderProtocol)) await Promise.race([channel.rpc.sendRequest("daemon.shutdown", { whenIdle: true }).catch(() => void 0), new Promise((resolve) => setTimeout(resolve, 1500))]);
|
|
570
|
+
channel.close();
|
|
571
|
+
return new IpcVersionMismatchError(err.message, daemon);
|
|
572
|
+
}
|
|
573
|
+
/** A server's protocol refusal, from this client's side: both versions and which side to upgrade. */
|
|
574
|
+
function serverMismatchMessage(server, where) {
|
|
575
|
+
if (typeof server.protocolVersion !== "number" || server.protocolVersion === 13) return null;
|
|
576
|
+
const upgrade = server.protocolVersion < 13 ? "server" : "client";
|
|
577
|
+
return `Protocol version mismatch with ${where}: the server speaks v${server.protocolVersion}, this client v13. Upgrade the ${upgrade}.`;
|
|
578
|
+
}
|
|
579
|
+
async function handshake(channel, options) {
|
|
580
|
+
let helloTimer;
|
|
581
|
+
try {
|
|
582
|
+
return await Promise.race([channel.rpc.sendRequest("ipc.hello", {
|
|
583
|
+
protocolVersion: 13,
|
|
584
|
+
appVersion: options.appVersion ?? "dev",
|
|
585
|
+
pid: process.pid,
|
|
586
|
+
buildId: options.buildFence ? IPC_BUILD_ID : "unknown",
|
|
587
|
+
codeVersion: ZIDANE_VERSION
|
|
588
|
+
}), new Promise((_, reject) => {
|
|
589
|
+
helloTimer = setTimeout(() => reject(/* @__PURE__ */ new Error(`Daemon handshake timed out after ${HELLO_TIMEOUT_MS}ms on ${channel.where}.`)), HELLO_TIMEOUT_MS);
|
|
590
|
+
})]);
|
|
591
|
+
} catch (err) {
|
|
592
|
+
if (err instanceof JsonRpcRemoteError && err.code === IpcErrorCode.VersionMismatch) throw await refusedHello(channel, err, options.drain);
|
|
593
|
+
channel.close();
|
|
594
|
+
throw err;
|
|
595
|
+
} finally {
|
|
596
|
+
clearTimeout(helloTimer);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
/** Handshake over `channel`, then the typed client around it. On failure the channel is closed. */
|
|
600
|
+
async function openIpcClient(channel, listeners, options) {
|
|
601
|
+
const hello = await handshake(channel, options);
|
|
602
|
+
const release = hostRelease(hello);
|
|
603
|
+
if (!hello.retiring && hello.hostKind !== "server" && release !== void 0 && compareVersions(release, ZIDANE_VERSION) < 0) {
|
|
604
|
+
channel.close();
|
|
605
|
+
throw new IpcVersionMismatchError(`Daemon release ${release} is older than client ${ZIDANE_VERSION}. Restart the daemon when active runs have finished.`, hello);
|
|
606
|
+
}
|
|
607
|
+
const requestTimeoutMs = Number(process.env.ZIDANE_IPC_REQUEST_TIMEOUT_MS) || 3e4;
|
|
608
|
+
const stopHeartbeat = options.heartbeatMs ? startHeartbeat(channel, options.heartbeatMs) : () => void 0;
|
|
609
|
+
return {
|
|
610
|
+
hello,
|
|
611
|
+
notify: (method, params) => {
|
|
612
|
+
try {
|
|
613
|
+
channel.rpc.sendNotification(method, params);
|
|
614
|
+
} catch {}
|
|
615
|
+
},
|
|
616
|
+
request: async (method, params) => {
|
|
617
|
+
if (method === "machine.call") return channel.rpc.sendRequest(method, params);
|
|
618
|
+
const timeoutMs = LONG_REQUEST_METHODS.has(method) ? LONG_REQUEST_TIMEOUT_MS : requestTimeoutMs;
|
|
619
|
+
let timer;
|
|
620
|
+
try {
|
|
621
|
+
return await Promise.race([channel.rpc.sendRequest(method, params), new Promise((_, reject) => {
|
|
622
|
+
timer = setTimeout(() => {
|
|
623
|
+
reject(/* @__PURE__ */ new Error(`Daemon request ${method} timed out after ${timeoutMs}ms, closing the connection.`));
|
|
624
|
+
channel.abort();
|
|
625
|
+
}, timeoutMs);
|
|
626
|
+
timer.unref?.();
|
|
627
|
+
})]);
|
|
628
|
+
} finally {
|
|
629
|
+
clearTimeout(timer);
|
|
630
|
+
}
|
|
631
|
+
},
|
|
632
|
+
onSignal: (cb) => {
|
|
633
|
+
listeners.add(cb);
|
|
634
|
+
return () => listeners.delete(cb);
|
|
635
|
+
},
|
|
636
|
+
close: () => {
|
|
637
|
+
stopHeartbeat();
|
|
638
|
+
channel.close();
|
|
639
|
+
}
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
//#endregion
|
|
643
|
+
//#region src/chat/sync/hash.ts
|
|
644
|
+
/** Stable hashes of sync values: equal values (whatever their key order) hash the same, on both sides. */
|
|
645
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
646
|
+
/** JSON with sorted keys (undefined members dropped). */
|
|
647
|
+
function stableStringify(value) {
|
|
648
|
+
if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
|
|
649
|
+
if (isRecord(value)) return `{${Object.keys(value).sort().filter((k) => value[k] !== void 0).map((k) => `${JSON.stringify(k)}:${stableStringify(value[k])}`).join(",")}}`;
|
|
650
|
+
return JSON.stringify(value) ?? "undefined";
|
|
651
|
+
}
|
|
652
|
+
function hashValue(value) {
|
|
653
|
+
return createHash("sha256").update(stableStringify(value)).digest("hex");
|
|
654
|
+
}
|
|
655
|
+
//#endregion
|
|
656
|
+
//#region src/chat/sync/settings-keys.ts
|
|
657
|
+
/**
|
|
658
|
+
* Host-scoped settings that still don't sync: they describe this computer
|
|
659
|
+
* (its environments, its daemon, remote hosts on it) or would turn off what
|
|
660
|
+
* the server has that this computer doesn't (the enabled allowlists, its OS
|
|
661
|
+
* sandbox). Every `sandbox*` key, present and future, is the server's own:
|
|
662
|
+
* a client turning it off there would be a sandbox escape.
|
|
663
|
+
*/
|
|
664
|
+
const NOT_SYNCED_SETTINGS = /* @__PURE__ */ new Set([
|
|
665
|
+
"environments",
|
|
666
|
+
"useDaemon",
|
|
667
|
+
"remoteHosts",
|
|
668
|
+
...HOST_ENABLED_LISTS
|
|
669
|
+
]);
|
|
670
|
+
/** A setting the `settings` category carries: host-scoped (never window-only) and not machine-specific. */
|
|
671
|
+
function isSyncableSetting(key) {
|
|
672
|
+
return !isWindowOnlySetting(key) && !NOT_SYNCED_SETTINGS.has(key) && !key.startsWith("sandbox");
|
|
673
|
+
}
|
|
674
|
+
//#endregion
|
|
675
|
+
export { IPC_BUILD_ID as C, legacySocketPath as D, ensureDaemonRunning as E, probeSocket as O, compareVersions as S, defaultSocketPath as T, loadAllEvents as _, createSignalListeners as a, loadSessionDocument as b, IpcErrorCode as c, PING_METHOD as d, REDACTED as f, hostRefOf as g, SIGNAL_SEQ_FIELD as h, IpcVersionMismatchError as i, selfDaemonSpawnCommand as k, LOAD_EVENTS_MAX_PAGE_TURNS as l, SESSION_TURNS_PAGE as m, hashValue as n, openIpcClient as o, SESSION_TURNS_MAX_PAGE as p, isRecord as r, IPC_PROTOCOL_VERSION as s, isSyncableSetting as t, LOAD_EVENTS_PAGE_TURNS as u, loadEventsPage as v, daemonSocketName as w, ZIDANE_VERSION as x, loadEventsTail as y };
|
|
676
|
+
|
|
677
|
+
//# sourceMappingURL=settings-keys-Ckf29NeM.js.map
|