zidane 7.2.4 → 8.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 -27242
- 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-zVSyo6K1.js +0 -331
- package/dist/ipc-zVSyo6K1.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-h5czzllR.js +0 -1549
- package/dist/shell-path-h5czzllR.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
package/dist/session/sqlite.js
CHANGED
|
@@ -1,616 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { c as mergeArtifact, u as selectArtifactEvictions } from "../artifacts-CV2hUKnL.js";
|
|
3
|
-
import { dirname } from "node:path";
|
|
4
|
-
import { copyFileSync, existsSync, mkdirSync } from "node:fs";
|
|
5
|
-
import { Database } from "bun:sqlite";
|
|
6
|
-
//#region src/session/sqlite.ts
|
|
7
|
-
const SCHEMA_VERSION = 4;
|
|
8
|
-
/**
|
|
9
|
-
* True when `err` is SQLite reporting a damaged file (`SQLITE_CORRUPT`,
|
|
10
|
-
* `SQLITE_NOTADB`). Matched on the message because bun:sqlite's error
|
|
11
|
-
* class exposes the code inconsistently across versions.
|
|
12
|
-
*/
|
|
13
|
-
function isCorruptDbError(err) {
|
|
14
|
-
const msg = errorMessage(err);
|
|
15
|
-
return /database disk image is malformed|SQLITE_CORRUPT|SQLITE_NOTADB|file is not a database/i.test(msg);
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Re-wrap a corruption error with the file path and a recovery recipe.
|
|
19
|
-
* The bare SQLite string ("database disk image is malformed") tells the
|
|
20
|
-
* user nothing about WHICH file or what to do; every host (TUI, daemon,
|
|
21
|
-
* headless) surfaces this message instead. Non-corruption errors pass
|
|
22
|
-
* through untouched.
|
|
23
|
-
*
|
|
24
|
-
* Deliberately no auto-repair / quarantine: the file is the only copy of
|
|
25
|
-
* the user's history and `.recover` salvages most of it. Never touch it.
|
|
26
|
-
*/
|
|
27
|
-
function describeCorruptDb(err, dbPath) {
|
|
28
|
-
if (!isCorruptDbError(err)) return err;
|
|
29
|
-
return new Error(`[zidane/sqlite] sessions database at "${dbPath}" is corrupt (${errorMessage(err)}).\n Your sessions are still on disk; zidane will not modify the file. To recover:\n 1. quit zidane (and any running daemon)\n 2. sqlite3 "${dbPath}" ".recover" | sqlite3 "${dbPath}.recovered"\n 3. mv "${dbPath}" "${dbPath}.corrupt" && rm -f "${dbPath}-wal" "${dbPath}-shm" && mv "${dbPath}.recovered" "${dbPath}"\n Common causes: git checkout/stash swapping a project .zidane/sessions.db under its -wal, a cloud-synced or network folder (iCloud, Dropbox, SMB), or a backup restored without deleting -wal / -shm.`, { cause: err });
|
|
30
|
-
}
|
|
31
|
-
function createSqliteStore(options) {
|
|
32
|
-
let store;
|
|
33
|
-
try {
|
|
34
|
-
store = openSqliteStore(options);
|
|
35
|
-
} catch (err) {
|
|
36
|
-
throw describeCorruptDb(err, options.path);
|
|
37
|
-
}
|
|
38
|
-
const wrapped = { ...store };
|
|
39
|
-
for (const key of Object.keys(store)) {
|
|
40
|
-
const fn = store[key];
|
|
41
|
-
if (typeof fn !== "function" || key === "close") continue;
|
|
42
|
-
wrapped[key] = async (...args) => {
|
|
43
|
-
try {
|
|
44
|
-
return await fn.apply(store, args);
|
|
45
|
-
} catch (err) {
|
|
46
|
-
throw describeCorruptDb(err, options.path);
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
return wrapped;
|
|
51
|
-
}
|
|
52
|
-
function openSqliteStore(options) {
|
|
53
|
-
const db = new Database(options.path);
|
|
54
|
-
db.run("PRAGMA busy_timeout = 5000");
|
|
55
|
-
db.run("PRAGMA journal_mode = WAL");
|
|
56
|
-
db.run("PRAGMA foreign_keys = ON");
|
|
57
|
-
db.run(`
|
|
58
|
-
CREATE TABLE IF NOT EXISTS sessions (
|
|
59
|
-
id TEXT PRIMARY KEY,
|
|
60
|
-
agent_id TEXT,
|
|
61
|
-
project_root TEXT,
|
|
62
|
-
status TEXT NOT NULL DEFAULT 'idle',
|
|
63
|
-
metadata TEXT NOT NULL DEFAULT '{}',
|
|
64
|
-
created_at INTEGER NOT NULL,
|
|
65
|
-
updated_at INTEGER NOT NULL
|
|
66
|
-
)
|
|
67
|
-
`);
|
|
68
|
-
db.run(`CREATE INDEX IF NOT EXISTS idx_sessions_agent_id ON sessions(agent_id)`);
|
|
69
|
-
db.run(`CREATE INDEX IF NOT EXISTS idx_sessions_project_root ON sessions(project_root)`);
|
|
70
|
-
db.run(`
|
|
71
|
-
CREATE TABLE IF NOT EXISTS turns (
|
|
72
|
-
session_id TEXT NOT NULL,
|
|
73
|
-
seq INTEGER NOT NULL,
|
|
74
|
-
role TEXT,
|
|
75
|
-
data TEXT NOT NULL,
|
|
76
|
-
PRIMARY KEY (session_id, seq),
|
|
77
|
-
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
|
78
|
-
)
|
|
79
|
-
`);
|
|
80
|
-
db.run(`
|
|
81
|
-
CREATE TABLE IF NOT EXISTS runs (
|
|
82
|
-
session_id TEXT NOT NULL,
|
|
83
|
-
run_id TEXT NOT NULL,
|
|
84
|
-
started_at INTEGER NOT NULL,
|
|
85
|
-
data TEXT NOT NULL,
|
|
86
|
-
PRIMARY KEY (session_id, run_id),
|
|
87
|
-
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
|
88
|
-
)
|
|
89
|
-
`);
|
|
90
|
-
migrate(db, options.path);
|
|
91
|
-
db.run(`
|
|
92
|
-
CREATE TABLE IF NOT EXISTS artifacts (
|
|
93
|
-
id TEXT PRIMARY KEY,
|
|
94
|
-
session_id TEXT NOT NULL,
|
|
95
|
-
run_id TEXT,
|
|
96
|
-
turn_id TEXT,
|
|
97
|
-
kind TEXT NOT NULL,
|
|
98
|
-
uri TEXT NOT NULL,
|
|
99
|
-
label TEXT NOT NULL,
|
|
100
|
-
project_root TEXT,
|
|
101
|
-
meta TEXT,
|
|
102
|
-
created_at INTEGER NOT NULL,
|
|
103
|
-
updated_at INTEGER NOT NULL,
|
|
104
|
-
UNIQUE (session_id, kind, uri),
|
|
105
|
-
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
|
106
|
-
)
|
|
107
|
-
`);
|
|
108
|
-
db.run(`CREATE INDEX IF NOT EXISTS idx_artifacts_session ON artifacts(session_id, updated_at)`);
|
|
109
|
-
db.run(`CREATE INDEX IF NOT EXISTS idx_artifacts_project_kind ON artifacts(project_root, kind, updated_at)`);
|
|
110
|
-
db.run(`CREATE INDEX IF NOT EXISTS idx_artifacts_kind_uri ON artifacts(kind, uri)`);
|
|
111
|
-
const stmtLoadHeader = db.prepare(`
|
|
112
|
-
SELECT id, agent_id, project_root, status, metadata, created_at, updated_at
|
|
113
|
-
FROM sessions WHERE id = ?
|
|
114
|
-
`);
|
|
115
|
-
const stmtLoadTurns = db.prepare("SELECT data FROM turns WHERE session_id = ? ORDER BY seq");
|
|
116
|
-
const stmtLoadTurnsRange = db.prepare("SELECT data FROM turns WHERE session_id = ? ORDER BY seq LIMIT ? OFFSET ?");
|
|
117
|
-
const stmtLoadRuns = db.prepare("SELECT data FROM runs WHERE session_id = ? ORDER BY started_at, run_id");
|
|
118
|
-
const stmtUpsertHeader = db.prepare(`
|
|
119
|
-
INSERT INTO sessions (id, agent_id, project_root, status, metadata, created_at, updated_at)
|
|
120
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
121
|
-
ON CONFLICT(id) DO UPDATE SET
|
|
122
|
-
agent_id = excluded.agent_id,
|
|
123
|
-
project_root = excluded.project_root,
|
|
124
|
-
status = excluded.status,
|
|
125
|
-
metadata = excluded.metadata,
|
|
126
|
-
updated_at = excluded.updated_at
|
|
127
|
-
`);
|
|
128
|
-
const stmtDelete = db.prepare("DELETE FROM sessions WHERE id = ?");
|
|
129
|
-
const stmtDeleteTurnsForSession = db.prepare("DELETE FROM turns WHERE session_id = ?");
|
|
130
|
-
const stmtDeleteRunsForSession = db.prepare("DELETE FROM runs WHERE session_id = ?");
|
|
131
|
-
const stmtInsertTurn = db.prepare("INSERT INTO turns (session_id, seq, role, data) VALUES (?, ?, ?, ?)");
|
|
132
|
-
const stmtUpsertRun = db.prepare(`
|
|
133
|
-
INSERT INTO runs (session_id, run_id, started_at, data) VALUES (?, ?, ?, ?)
|
|
134
|
-
ON CONFLICT(session_id, run_id) DO UPDATE SET
|
|
135
|
-
data = excluded.data,
|
|
136
|
-
started_at = excluded.started_at
|
|
137
|
-
`);
|
|
138
|
-
const stmtMaxSeq = db.prepare("SELECT MAX(seq) as m FROM turns WHERE session_id = ?");
|
|
139
|
-
const stmtTouch = db.prepare("UPDATE sessions SET updated_at = ? WHERE id = ?");
|
|
140
|
-
const stmtUpdateStatus = db.prepare("UPDATE sessions SET status = ?, updated_at = ? WHERE id = ?");
|
|
141
|
-
const stmtUpdateStatusOnly = db.prepare("UPDATE sessions SET status = ? WHERE id = ?");
|
|
142
|
-
const ARTIFACT_COLUMNS = "id, session_id, run_id, turn_id, kind, uri, label, project_root, meta, created_at, updated_at";
|
|
143
|
-
const stmtFindArtifact = db.prepare(`SELECT ${ARTIFACT_COLUMNS} FROM artifacts WHERE session_id = ? AND kind = ? AND uri = ?`);
|
|
144
|
-
const stmtSessionArtifacts = db.prepare(`SELECT ${ARTIFACT_COLUMNS} FROM artifacts WHERE session_id = ? ORDER BY created_at, rowid`);
|
|
145
|
-
const stmtInsertArtifact = db.prepare(`
|
|
146
|
-
INSERT INTO artifacts (${ARTIFACT_COLUMNS}) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
147
|
-
`);
|
|
148
|
-
const stmtRefreshArtifact = db.prepare(`
|
|
149
|
-
UPDATE artifacts SET label = ?, project_root = ?, meta = ?, updated_at = ? WHERE id = ?
|
|
150
|
-
`);
|
|
151
|
-
const stmtDeleteArtifact = db.prepare("DELETE FROM artifacts WHERE session_id = ? AND id = ?");
|
|
152
|
-
const loadSync = (sessionId) => {
|
|
153
|
-
const header = stmtLoadHeader.get(sessionId);
|
|
154
|
-
if (!header) return null;
|
|
155
|
-
const turnRows = stmtLoadTurns.all(sessionId);
|
|
156
|
-
const runRows = stmtLoadRuns.all(sessionId);
|
|
157
|
-
return {
|
|
158
|
-
id: header.id,
|
|
159
|
-
...header.agent_id ? { agentId: header.agent_id } : {},
|
|
160
|
-
...header.project_root ? { projectRoot: header.project_root } : {},
|
|
161
|
-
turns: turnRows.map((r) => safeParseRow(r.data, header.id, "turn")).filter((t) => t !== null),
|
|
162
|
-
runs: runRows.map((r) => safeParseRow(r.data, header.id, "run")).filter((r) => r !== null),
|
|
163
|
-
status: header.status,
|
|
164
|
-
metadata: safeParseRecord(header.metadata),
|
|
165
|
-
createdAt: header.created_at,
|
|
166
|
-
updatedAt: header.updated_at
|
|
167
|
-
};
|
|
168
|
-
};
|
|
169
|
-
const txnSave = db.transaction((session) => {
|
|
170
|
-
stmtUpsertHeader.run(session.id, session.agentId ?? null, session.projectRoot ?? null, session.status, JSON.stringify(session.metadata ?? {}), session.createdAt, session.updatedAt);
|
|
171
|
-
stmtDeleteTurnsForSession.run(session.id);
|
|
172
|
-
stmtDeleteRunsForSession.run(session.id);
|
|
173
|
-
session.turns.forEach((t, i) => stmtInsertTurn.run(session.id, i, t.role ?? null, JSON.stringify(t)));
|
|
174
|
-
for (const run of session.runs) stmtUpsertRun.run(session.id, run.id, run.startedAt, JSON.stringify(run));
|
|
175
|
-
});
|
|
176
|
-
const txnSaveMeta = db.transaction((session) => {
|
|
177
|
-
stmtUpsertHeader.run(session.id, session.agentId ?? null, session.projectRoot ?? null, session.status, JSON.stringify(session.metadata ?? {}), session.createdAt, session.updatedAt);
|
|
178
|
-
for (const run of session.runs) stmtUpsertRun.run(session.id, run.id, run.startedAt, JSON.stringify(run));
|
|
179
|
-
});
|
|
180
|
-
const ensureHeaderSync = (sessionId) => {
|
|
181
|
-
if (stmtLoadHeader.get(sessionId)) return;
|
|
182
|
-
const now = Date.now();
|
|
183
|
-
stmtUpsertHeader.run(sessionId, null, null, "idle", "{}", now, now);
|
|
184
|
-
};
|
|
185
|
-
const txnAppendTurns = db.transaction((sessionId, turns) => {
|
|
186
|
-
ensureHeaderSync(sessionId);
|
|
187
|
-
let nextSeq = (stmtMaxSeq.get(sessionId).m ?? -1) + 1;
|
|
188
|
-
for (const turn of turns) {
|
|
189
|
-
stmtInsertTurn.run(sessionId, nextSeq, turn.role ?? null, JSON.stringify(turn));
|
|
190
|
-
nextSeq += 1;
|
|
191
|
-
}
|
|
192
|
-
stmtTouch.run(Date.now(), sessionId);
|
|
193
|
-
});
|
|
194
|
-
const txnUpdateRun = db.transaction((sessionId, run) => {
|
|
195
|
-
if (!stmtLoadHeader.get(sessionId)) return;
|
|
196
|
-
stmtUpsertRun.run(sessionId, run.id, run.startedAt, JSON.stringify(run));
|
|
197
|
-
stmtTouch.run(Date.now(), sessionId);
|
|
198
|
-
});
|
|
199
|
-
const txnUpdateStatus = db.transaction((sessionId, status, preserveUpdatedAt) => {
|
|
200
|
-
if (preserveUpdatedAt) stmtUpdateStatusOnly.run(status, sessionId);
|
|
201
|
-
else stmtUpdateStatus.run(status, Date.now(), sessionId);
|
|
202
|
-
});
|
|
203
|
-
const rowToArtifact = (r) => {
|
|
204
|
-
let meta;
|
|
205
|
-
if (r.meta) try {
|
|
206
|
-
meta = JSON.parse(r.meta);
|
|
207
|
-
} catch {
|
|
208
|
-
meta = void 0;
|
|
209
|
-
}
|
|
210
|
-
return {
|
|
211
|
-
id: r.id,
|
|
212
|
-
sessionId: r.session_id,
|
|
213
|
-
...r.run_id ? { runId: r.run_id } : {},
|
|
214
|
-
...r.turn_id ? { turnId: r.turn_id } : {},
|
|
215
|
-
kind: r.kind,
|
|
216
|
-
uri: r.uri,
|
|
217
|
-
label: r.label,
|
|
218
|
-
...r.project_root ? { projectRoot: r.project_root } : {},
|
|
219
|
-
...meta !== void 0 ? { meta } : {},
|
|
220
|
-
createdAt: r.created_at,
|
|
221
|
-
updatedAt: r.updated_at
|
|
222
|
-
};
|
|
223
|
-
};
|
|
224
|
-
const txnUpsertArtifact = db.transaction((artifact) => {
|
|
225
|
-
if (!stmtLoadHeader.get(artifact.sessionId)) return null;
|
|
226
|
-
const existingRow = stmtFindArtifact.get(artifact.sessionId, artifact.kind, artifact.uri);
|
|
227
|
-
if (existingRow) {
|
|
228
|
-
const merged = mergeArtifact(rowToArtifact(existingRow), artifact);
|
|
229
|
-
stmtRefreshArtifact.run(merged.label, merged.projectRoot ?? null, merged.meta !== void 0 ? JSON.stringify(merged.meta) : null, merged.updatedAt, merged.id);
|
|
230
|
-
return merged;
|
|
231
|
-
}
|
|
232
|
-
const current = stmtSessionArtifacts.all(artifact.sessionId).map(rowToArtifact);
|
|
233
|
-
for (const id of selectArtifactEvictions(current)) stmtDeleteArtifact.run(artifact.sessionId, id);
|
|
234
|
-
stmtInsertArtifact.run(artifact.id, artifact.sessionId, artifact.runId ?? null, artifact.turnId ?? null, artifact.kind, artifact.uri, artifact.label, artifact.projectRoot ?? null, artifact.meta !== void 0 ? JSON.stringify(artifact.meta) : null, artifact.createdAt, artifact.updatedAt);
|
|
235
|
-
return artifact;
|
|
236
|
-
});
|
|
237
|
-
return {
|
|
238
|
-
async load(sessionId) {
|
|
239
|
-
return loadSync(sessionId);
|
|
240
|
-
},
|
|
241
|
-
async save(session) {
|
|
242
|
-
txnSave.immediate(session);
|
|
243
|
-
},
|
|
244
|
-
async saveMeta(session) {
|
|
245
|
-
txnSaveMeta.immediate(session);
|
|
246
|
-
},
|
|
247
|
-
async delete(sessionId) {
|
|
248
|
-
stmtDelete.run(sessionId);
|
|
249
|
-
},
|
|
250
|
-
async list(filter) {
|
|
251
|
-
const { where, limit, params } = buildListFilter(filter);
|
|
252
|
-
const sql = `SELECT id FROM sessions ${where} ORDER BY updated_at DESC ${limit}`.replace(/\s+/g, " ").trim();
|
|
253
|
-
return db.query(sql).all(...params).map((r) => r.id);
|
|
254
|
-
},
|
|
255
|
-
async getMeta(sessionId) {
|
|
256
|
-
const row = db.query(`
|
|
257
|
-
SELECT
|
|
258
|
-
s.id,
|
|
259
|
-
s.project_root,
|
|
260
|
-
s.metadata,
|
|
261
|
-
s.updated_at,
|
|
262
|
-
s.agent_id,
|
|
263
|
-
s.created_at,
|
|
264
|
-
s.status,
|
|
265
|
-
(SELECT COUNT(*) FROM turns t WHERE t.session_id = s.id) AS turn_count,
|
|
266
|
-
(SELECT COUNT(*) FROM turns t WHERE t.session_id = s.id AND t.role = 'user') AS user_count,
|
|
267
|
-
(SELECT COUNT(*) FROM runs r WHERE r.session_id = s.id) AS run_count,
|
|
268
|
-
(SELECT COUNT(*) FROM artifacts a WHERE a.session_id = s.id) AS artifact_count,
|
|
269
|
-
NULL AS first_user_turn
|
|
270
|
-
FROM sessions s WHERE s.id = ?
|
|
271
|
-
`).get(sessionId);
|
|
272
|
-
if (!row) return null;
|
|
273
|
-
return {
|
|
274
|
-
id: row.id,
|
|
275
|
-
metadata: safeParseRecord(row.metadata),
|
|
276
|
-
...row.project_root ? { projectRoot: row.project_root } : {},
|
|
277
|
-
updatedAt: row.updated_at,
|
|
278
|
-
...row.agent_id ? { agentId: row.agent_id } : {},
|
|
279
|
-
createdAt: row.created_at,
|
|
280
|
-
status: row.status,
|
|
281
|
-
turnCount: row.turn_count,
|
|
282
|
-
userMessageCount: row.user_count,
|
|
283
|
-
runCount: row.run_count,
|
|
284
|
-
artifactCount: row.artifact_count
|
|
285
|
-
};
|
|
286
|
-
},
|
|
287
|
-
async listMeta(filter) {
|
|
288
|
-
const { where, limit, params } = buildListFilter(filter);
|
|
289
|
-
const sql = `
|
|
290
|
-
SELECT
|
|
291
|
-
s.id,
|
|
292
|
-
s.project_root,
|
|
293
|
-
s.metadata,
|
|
294
|
-
s.updated_at,
|
|
295
|
-
s.agent_id,
|
|
296
|
-
s.created_at,
|
|
297
|
-
s.status,
|
|
298
|
-
(SELECT COUNT(*) FROM turns t WHERE t.session_id = s.id) AS turn_count,
|
|
299
|
-
(SELECT COUNT(*) FROM turns t WHERE t.session_id = s.id AND t.role = 'user') AS user_count,
|
|
300
|
-
(SELECT COUNT(*) FROM runs r WHERE r.session_id = s.id) AS run_count,
|
|
301
|
-
(SELECT COUNT(*) FROM artifacts a WHERE a.session_id = s.id) AS artifact_count,
|
|
302
|
-
CASE WHEN json_valid(s.metadata)
|
|
303
|
-
AND TRIM(COALESCE(json_extract(s.metadata, '$.title'), '')) <> '' THEN NULL
|
|
304
|
-
ELSE (SELECT t.data FROM turns t WHERE t.session_id = s.id AND t.role = 'user'
|
|
305
|
-
ORDER BY t.seq LIMIT 1)
|
|
306
|
-
END AS first_user_turn
|
|
307
|
-
FROM sessions s ${where} ORDER BY s.updated_at DESC ${limit}
|
|
308
|
-
`;
|
|
309
|
-
return db.query(sql).all(...params).map((r) => {
|
|
310
|
-
const firstUserTurn = r.first_user_turn ? safeParseRow(r.first_user_turn, r.id, "turn") : null;
|
|
311
|
-
return {
|
|
312
|
-
id: r.id,
|
|
313
|
-
metadata: safeParseRecord(r.metadata),
|
|
314
|
-
...r.project_root ? { projectRoot: r.project_root } : {},
|
|
315
|
-
updatedAt: r.updated_at,
|
|
316
|
-
...r.agent_id ? { agentId: r.agent_id } : {},
|
|
317
|
-
createdAt: r.created_at,
|
|
318
|
-
status: r.status,
|
|
319
|
-
turnCount: r.turn_count,
|
|
320
|
-
userMessageCount: r.user_count,
|
|
321
|
-
runCount: r.run_count,
|
|
322
|
-
artifactCount: r.artifact_count,
|
|
323
|
-
...firstUserTurn ? { firstUserTurn } : {}
|
|
324
|
-
};
|
|
325
|
-
});
|
|
326
|
-
},
|
|
327
|
-
async appendTurns(sessionId, turns) {
|
|
328
|
-
txnAppendTurns.immediate(sessionId, turns);
|
|
329
|
-
},
|
|
330
|
-
async getTurns(sessionId, from = 0, limit) {
|
|
331
|
-
const lim = typeof limit === "number" ? limit : -1;
|
|
332
|
-
return stmtLoadTurnsRange.all(sessionId, lim, from).map((r) => safeParseRow(r.data, sessionId, "turn")).filter((t) => t !== null);
|
|
333
|
-
},
|
|
334
|
-
async updateRun(sessionId, run) {
|
|
335
|
-
txnUpdateRun.immediate(sessionId, run);
|
|
336
|
-
},
|
|
337
|
-
async updateStatus(sessionId, status, options) {
|
|
338
|
-
txnUpdateStatus.immediate(sessionId, status, options?.preserveUpdatedAt === true);
|
|
339
|
-
},
|
|
340
|
-
async upsertArtifact(artifact) {
|
|
341
|
-
return txnUpsertArtifact.immediate(artifact);
|
|
342
|
-
},
|
|
343
|
-
async listArtifacts(filter) {
|
|
344
|
-
const { where, limit, params } = buildArtifactFilter(filter);
|
|
345
|
-
const sql = `SELECT ${ARTIFACT_COLUMNS} FROM artifacts ${where} ORDER BY updated_at DESC, created_at DESC, id ${limit}`.replace(/\s+/g, " ").trim();
|
|
346
|
-
return db.query(sql).all(...params).map(rowToArtifact);
|
|
347
|
-
},
|
|
348
|
-
async deleteArtifact(sessionId, artifactId) {
|
|
349
|
-
stmtDeleteArtifact.run(sessionId, artifactId);
|
|
350
|
-
},
|
|
351
|
-
close() {
|
|
352
|
-
db.close(false);
|
|
353
|
-
}
|
|
354
|
-
};
|
|
355
|
-
}
|
|
356
|
-
/**
|
|
357
|
-
* Forward-only schema migration runner. Idempotent — every step
|
|
358
|
-
* feature-detects rather than relying on the `PRAGMA user_version`
|
|
359
|
-
* number alone, so a partially-migrated DB (e.g. interrupted v3→v4
|
|
360
|
-
* backfill) is brought to a consistent v4 state on the next open.
|
|
361
|
-
*
|
|
362
|
-
* The legacy `data` column is the v3 sentinel: when present we treat
|
|
363
|
-
* the DB as v3-or-older and run the backfill. Before any destructive
|
|
364
|
-
* change we copy the entire DB file to `<path>.zidane-pre-v4.bak` (see
|
|
365
|
-
* {@link backupBeforeV3Migration}) so the user has a guaranteed
|
|
366
|
-
* recovery path if anything goes sideways.
|
|
367
|
-
*
|
|
368
|
-
* After backfill we attempt to drop the column (SQLite 3.35+; Bun
|
|
369
|
-
* ships ≥ 3.43 so this always succeeds in practice). If it does fail,
|
|
370
|
-
* we throw rather than limp along — leaving the column with `NOT NULL`
|
|
371
|
-
* while the new write paths omit it would silently break every future
|
|
372
|
-
* `INSERT`. The `.bak` file lets the user roll back and report the bug.
|
|
373
|
-
*/
|
|
374
|
-
function migrate(db, dbPath) {
|
|
375
|
-
const onDiskVersion = db.query("PRAGMA user_version").get()?.user_version ?? 0;
|
|
376
|
-
if (onDiskVersion > SCHEMA_VERSION && onDiskVersion !== 5) throw new Error(`[zidane/sqlite] "${dbPath}" has schema version ${onDiskVersion}, but this zidane build only supports up to ${SCHEMA_VERSION}. It was written by a newer zidane — upgrade zidane, or point this build at a different sessions DB.`);
|
|
377
|
-
const sessionCols = db.query("PRAGMA table_info(sessions)").all();
|
|
378
|
-
const hasCol = (n) => sessionCols.some((c) => c.name === n);
|
|
379
|
-
if (!hasCol("project_root")) db.run("ALTER TABLE sessions ADD COLUMN project_root TEXT");
|
|
380
|
-
if (!hasCol("status")) db.run(`ALTER TABLE sessions ADD COLUMN status TEXT NOT NULL DEFAULT 'idle'`);
|
|
381
|
-
if (!hasCol("metadata")) db.run(`ALTER TABLE sessions ADD COLUMN metadata TEXT NOT NULL DEFAULT '{}'`);
|
|
382
|
-
if (hasCol("data")) {
|
|
383
|
-
backupBeforeV3Migration(db, dbPath);
|
|
384
|
-
backfillV3Blobs(db);
|
|
385
|
-
try {
|
|
386
|
-
db.run("ALTER TABLE sessions DROP COLUMN data");
|
|
387
|
-
} catch (err) {
|
|
388
|
-
throw new Error(`[zidane/sqlite] v3→v4 migration could not drop legacy "data" column: ${errorMessage(err)}. Restore from "${dbPath}.zidane-pre-v4.bak" with an older zidane build and report this — your sessions are intact in the backup file.`);
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
if (!db.query("PRAGMA table_info(turns)").all().some((c) => c.name === "role")) db.run("ALTER TABLE turns ADD COLUMN role TEXT");
|
|
392
|
-
db.run("CREATE INDEX IF NOT EXISTS idx_turns_role_null ON turns(session_id) WHERE role IS NULL");
|
|
393
|
-
if (db.query(`SELECT 1 FROM turns WHERE role IS NULL AND json_valid(data) LIMIT 1`).get()) db.run(`UPDATE turns SET role = json_extract(data, '$.role') WHERE role IS NULL AND json_valid(data)`);
|
|
394
|
-
db.run("CREATE INDEX IF NOT EXISTS idx_turns_session_role ON turns(session_id, role, seq)");
|
|
395
|
-
if ((db.query("PRAGMA user_version").get()?.user_version ?? 0) !== SCHEMA_VERSION) db.run(`PRAGMA user_version = ${SCHEMA_VERSION}`);
|
|
396
|
-
}
|
|
397
|
-
/**
|
|
398
|
-
* Pre-migration safety net for v3 → v4: copy the source DB file to
|
|
399
|
-
* `<path>.zidane-pre-v4.bak` so the user can recover by restoring the
|
|
400
|
-
* snapshot if anything in the migration goes sideways.
|
|
401
|
-
*
|
|
402
|
-
* - Skipped for non-filesystem paths (`:memory:`, empty string) — no
|
|
403
|
-
* file to copy.
|
|
404
|
-
* - Skipped when the file is missing (fresh install, never reached
|
|
405
|
-
* migration territory).
|
|
406
|
-
* - Skipped when the backup already exists — re-runs of the migration
|
|
407
|
-
* (idempotent path) reuse the same snapshot rather than overwrite a
|
|
408
|
-
* potentially-earlier good copy with a later partial state.
|
|
409
|
-
* - WAL is checkpointed first so the .db file contains everything that
|
|
410
|
-
* was committed up to this point (otherwise pending WAL frames would
|
|
411
|
-
* be missing from the snapshot).
|
|
412
|
-
* - On copy failure the whole migration is aborted with a thrown error
|
|
413
|
-
* — we refuse to modify the DB without a recovery path. The user
|
|
414
|
-
* sees a clear diagnostic; their sessions stay intact.
|
|
415
|
-
*
|
|
416
|
-
* Surfaces a one-line stderr message on success so the user knows where
|
|
417
|
-
* the snapshot landed. They can delete it once they've confirmed the
|
|
418
|
-
* post-migration TUI behaves correctly.
|
|
419
|
-
*/
|
|
420
|
-
function backupBeforeV3Migration(db, dbPath) {
|
|
421
|
-
if (dbPath === "" || dbPath === ":memory:" || dbPath.startsWith("file::memory:")) return;
|
|
422
|
-
if (!existsSync(dbPath)) return;
|
|
423
|
-
const backupPath = `${dbPath}.zidane-pre-v4.bak`;
|
|
424
|
-
if (existsSync(backupPath)) return;
|
|
425
|
-
let checkpointed = true;
|
|
426
|
-
try {
|
|
427
|
-
db.run("PRAGMA wal_checkpoint(TRUNCATE)");
|
|
428
|
-
} catch {
|
|
429
|
-
checkpointed = false;
|
|
430
|
-
}
|
|
431
|
-
try {
|
|
432
|
-
copyFileSync(dbPath, backupPath);
|
|
433
|
-
if (!checkpointed) for (const ext of ["-wal", "-shm"]) {
|
|
434
|
-
const sidecar = `${dbPath}${ext}`;
|
|
435
|
-
if (existsSync(sidecar)) copyFileSync(sidecar, `${backupPath}${ext}`);
|
|
436
|
-
}
|
|
437
|
-
process.stderr.write(`[zidane/sqlite] v3→v4 migration: backed up your sessions DB to "${backupPath}".\n To roll back if anything looks wrong:\n 1. quit zidane\n 2. cp "${backupPath}" "${dbPath}" && rm -f "${dbPath}-wal" "${dbPath}-shm"\n 3. pin an older zidane that knows the v3 schema, or upgrade to a fix\n Delete the .bak once every session loads correctly.\n`);
|
|
438
|
-
} catch (err) {
|
|
439
|
-
throw new Error(`[zidane/sqlite] failed to back up "${dbPath}" before v3→v4 migration: ${errorMessage(err)}. Refusing to modify the DB without a recovery path. Move the file aside or fix the permissions and retry.`);
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
/**
|
|
443
|
-
* Parse each session's legacy `data` blob and fan its `turns` + `runs`
|
|
444
|
-
* arrays out into the dedicated tables, then overwrite the synthetic
|
|
445
|
-
* `status`/`metadata` defaults with the values from the blob.
|
|
446
|
-
*
|
|
447
|
-
* Skips rows that already have at least one entry in `turns` for them —
|
|
448
|
-
* a previous run of this migration already landed those bytes, and
|
|
449
|
-
* re-inserting them would either duplicate (if seq numbering shifted)
|
|
450
|
-
* or crash on the PK. The "header already exists, turns table populated"
|
|
451
|
-
* combination is the idempotency signal.
|
|
452
|
-
*
|
|
453
|
-
* Per-row failures (corrupt JSON, …) log + skip rather than abort the
|
|
454
|
-
* whole migration: one bad row shouldn't prevent the rest of the DB
|
|
455
|
-
* from coming forward to v4.
|
|
456
|
-
*/
|
|
457
|
-
function backfillV3Blobs(db) {
|
|
458
|
-
const rows = db.query("SELECT id, data FROM sessions").all();
|
|
459
|
-
if (rows.length === 0) return;
|
|
460
|
-
const insertTurn = db.prepare("INSERT INTO turns (session_id, seq, data) VALUES (?, ?, ?)");
|
|
461
|
-
const upsertRun = db.prepare(`
|
|
462
|
-
INSERT INTO runs (session_id, run_id, started_at, data) VALUES (?, ?, ?, ?)
|
|
463
|
-
ON CONFLICT(session_id, run_id) DO UPDATE SET
|
|
464
|
-
data = excluded.data,
|
|
465
|
-
started_at = excluded.started_at
|
|
466
|
-
`);
|
|
467
|
-
const updateHeader = db.prepare("UPDATE sessions SET status = ?, metadata = ? WHERE id = ?");
|
|
468
|
-
const countTurns = db.prepare("SELECT COUNT(*) as c FROM turns WHERE session_id = ?");
|
|
469
|
-
for (const row of rows) {
|
|
470
|
-
if (!row.data) continue;
|
|
471
|
-
try {
|
|
472
|
-
const data = JSON.parse(row.data);
|
|
473
|
-
if (countTurns.get(row.id).c > 0) continue;
|
|
474
|
-
const turns = Array.isArray(data.turns) ? data.turns : [];
|
|
475
|
-
const runs = Array.isArray(data.runs) ? data.runs : [];
|
|
476
|
-
db.transaction(() => {
|
|
477
|
-
turns.forEach((t, i) => insertTurn.run(row.id, i, JSON.stringify(t)));
|
|
478
|
-
for (const run of runs) {
|
|
479
|
-
if (!run || typeof run.id !== "string") continue;
|
|
480
|
-
upsertRun.run(row.id, run.id, run.startedAt ?? 0, JSON.stringify(run));
|
|
481
|
-
}
|
|
482
|
-
updateHeader.run(data.status ?? "idle", JSON.stringify(data.metadata ?? {}), row.id);
|
|
483
|
-
}).immediate();
|
|
484
|
-
} catch (err) {
|
|
485
|
-
process.stderr.write(`[zidane/sqlite] v3→v4 migrate: session "${row.id}" skipped: ${errorMessage(err)}\n`);
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
/**
|
|
490
|
-
* Compose the WHERE / LIMIT fragments shared by `list` and `listMeta`.
|
|
491
|
-
*
|
|
492
|
-
* `projectRoot: string` → `WHERE project_root = ?` (excludes untagged).
|
|
493
|
-
* `projectRoot: null` → `WHERE project_root IS NULL` (untagged only).
|
|
494
|
-
* `projectRoot: undefined` → axis omitted (untagged + tagged).
|
|
495
|
-
*
|
|
496
|
-
* The `null` case lets a future "show legacy" debug toggle query pre-v3
|
|
497
|
-
* sessions explicitly without leaking them into normal per-project lists.
|
|
498
|
-
*/
|
|
499
|
-
function buildListFilter(filter) {
|
|
500
|
-
const conditions = [];
|
|
501
|
-
const params = [];
|
|
502
|
-
if (filter?.agentId) {
|
|
503
|
-
conditions.push("agent_id = ?");
|
|
504
|
-
params.push(filter.agentId);
|
|
505
|
-
}
|
|
506
|
-
if ("projectRoot" in (filter ?? {})) {
|
|
507
|
-
const v = filter.projectRoot;
|
|
508
|
-
if (v === null) conditions.push("project_root IS NULL");
|
|
509
|
-
else if (typeof v === "string") {
|
|
510
|
-
conditions.push("project_root = ?");
|
|
511
|
-
params.push(v);
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
return {
|
|
515
|
-
where: conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "",
|
|
516
|
-
limit: typeof filter?.limit === "number" && filter.limit > 0 ? `LIMIT ${filter.limit}` : "",
|
|
517
|
-
params
|
|
518
|
-
};
|
|
519
|
-
}
|
|
520
|
-
/**
|
|
521
|
-
* WHERE / LIMIT fragments for `listArtifacts`. `projectRoot` follows the
|
|
522
|
-
* same tri-state contract as {@link buildListFilter}.
|
|
523
|
-
*/
|
|
524
|
-
function buildArtifactFilter(filter) {
|
|
525
|
-
const conditions = [];
|
|
526
|
-
const params = [];
|
|
527
|
-
if (filter?.sessionId !== void 0) {
|
|
528
|
-
conditions.push("session_id = ?");
|
|
529
|
-
params.push(filter.sessionId);
|
|
530
|
-
}
|
|
531
|
-
if (filter?.kind !== void 0) {
|
|
532
|
-
conditions.push("kind = ?");
|
|
533
|
-
params.push(filter.kind);
|
|
534
|
-
}
|
|
535
|
-
if (filter?.uri !== void 0) {
|
|
536
|
-
conditions.push("uri = ?");
|
|
537
|
-
params.push(filter.uri);
|
|
538
|
-
}
|
|
539
|
-
if (filter && "projectRoot" in filter) {
|
|
540
|
-
if (filter.projectRoot === null) conditions.push("project_root IS NULL");
|
|
541
|
-
else if (typeof filter.projectRoot === "string") {
|
|
542
|
-
conditions.push("project_root = ?");
|
|
543
|
-
params.push(filter.projectRoot);
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
if (typeof filter?.since === "number") {
|
|
547
|
-
conditions.push("updated_at >= ?");
|
|
548
|
-
params.push(filter.since);
|
|
549
|
-
}
|
|
550
|
-
return {
|
|
551
|
-
where: conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "",
|
|
552
|
-
limit: typeof filter?.limit === "number" && filter.limit > 0 ? `LIMIT ${filter.limit}` : "",
|
|
553
|
-
params
|
|
554
|
-
};
|
|
555
|
-
}
|
|
556
|
-
/**
|
|
557
|
-
* Guarded per-row parse for `turns.data` / `runs.data`. One corrupt row
|
|
558
|
-
* (truncated write, hand-edited DB, disk bitflip) must not make the whole
|
|
559
|
-
* session unloadable — log + skip it instead, mirroring the migration's
|
|
560
|
-
* per-row backfill policy. The structural check matches the minimal shape
|
|
561
|
-
* both `SessionTurn` and `SessionRun` share (an object with a string `id`).
|
|
562
|
-
*/
|
|
563
|
-
function safeParseRow(text, sessionId, kind) {
|
|
564
|
-
try {
|
|
565
|
-
const parsed = JSON.parse(text);
|
|
566
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed) || typeof parsed.id !== "string") {
|
|
567
|
-
console.error(`[zidane/sqlite] session "${sessionId}": skipping malformed ${kind} row (not a ${kind}-shaped object)`);
|
|
568
|
-
return null;
|
|
569
|
-
}
|
|
570
|
-
return parsed;
|
|
571
|
-
} catch (err) {
|
|
572
|
-
console.error(`[zidane/sqlite] session "${sessionId}": skipping corrupt ${kind} row: ${errorMessage(err)}`);
|
|
573
|
-
return null;
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
/**
|
|
577
|
-
* `JSON.parse` with a fallback to `{}` for the metadata column. v3→v4
|
|
578
|
-
* migration writes well-formed JSON, fresh v4 writes go through
|
|
579
|
-
* `JSON.stringify(metadata ?? {})` — but a hand-edited DB or a botched
|
|
580
|
-
* external migration could leave a row with malformed JSON, and we'd
|
|
581
|
-
* rather surface an empty metadata object than crash the entire load
|
|
582
|
-
* path. Logged under `ZIDANE_DEBUG` so the corruption isn't fully
|
|
583
|
-
* silent.
|
|
584
|
-
*/
|
|
585
|
-
function safeParseRecord(text) {
|
|
586
|
-
try {
|
|
587
|
-
const parsed = JSON.parse(text);
|
|
588
|
-
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
589
|
-
} catch (err) {
|
|
590
|
-
if (process.env.ZIDANE_DEBUG) process.stderr.write(`[zidane/sqlite] metadata JSON parse failed, defaulting to {}: ${errorMessage(err)}\n`);
|
|
591
|
-
return {};
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
/**
|
|
595
|
-
* Convenience: open a SQLite store at `dbPath`, creating its parent
|
|
596
|
-
* directory if it doesn't yet exist. Used by the TUI launcher to spin up
|
|
597
|
-
* the default session store at `~/.zidane/sessions.db`.
|
|
598
|
-
*
|
|
599
|
-
* Lives here (and not in `chat/store.ts`) so the renderer-agnostic
|
|
600
|
-
* `zidane/chat` entry stays free of `bun:sqlite` — non-Bun consumers
|
|
601
|
-
* (a future GUI, an SDK) can import `zidane/chat` without pulling in the
|
|
602
|
-
* Bun-only binding.
|
|
603
|
-
*/
|
|
604
|
-
function createTuiStore(dbPath) {
|
|
605
|
-
const dir = dirname(dbPath);
|
|
606
|
-
if (!existsSync(dir)) try {
|
|
607
|
-
mkdirSync(dir, { recursive: true });
|
|
608
|
-
} catch (err) {
|
|
609
|
-
throw new Error(`Could not create TUI storage directory at "${dir}". Override the location via \`runTui({ storageDir, prefix })\` or the \`ZIDANE_STORAGE_DIR\` env var. Original error: ${errorMessage(err)}`);
|
|
610
|
-
}
|
|
611
|
-
return createSqliteStore({ path: dbPath });
|
|
612
|
-
}
|
|
613
|
-
//#endregion
|
|
614
|
-
export { createSqliteStore, createTuiStore, describeCorruptDb, isCorruptDbError };
|
|
615
|
-
|
|
616
|
-
//# sourceMappingURL=sqlite.js.map
|
|
1
|
+
export { t as createSqliteStore, n as createTuiStore, r as describeCorruptDb, i as isCorruptDbError } from "../sqlite-DV1DQzN2.js";
|