chainlesschain 0.165.5 → 0.165.8
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/package.json +2 -1
- package/src/assets/web-panel/assets/{AIOps-CEeYTeDB.js → AIOps-B3gWmXjo.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BeRUQ3V2.js → ActionButton-G9pdT-0e.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DrV718XF.js → Analytics-Ca30J7m2.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-Cd2Frt7Q.js → AppLayout-BtVTm8PU.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-CUJMlORU.js → Artifacts-BhViNa6u.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CXJcfT6p.js → Audit-DhKq-FnY.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-DOv6Z7H9.js → BackgroundAgents-BL0SVbnE.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-BwdDyBI0.js → Backup-BWkblnFi.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-BmLn4kYH.js → BaseInput-ClaRNrF8.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-COg8pAW2.js → Chat-sZE2Z77o.js} +4 -4
- package/src/assets/web-panel/assets/ChatBubbleRenderer-BAfKOnRe.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-BCP4uoU8.js → Checkbox-Cvhay5WM.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-pRt6Y9JI.js → Codegen-BpejL-4N.js} +1 -1
- package/src/assets/web-panel/assets/{Col-DLaprKhS.js → Col-g2Ki6g_1.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DyATsz5f.js → Community-D2xKbNo9.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BXAaupZK.js → Compact-DbL1Pds3.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-DpcJBELr.js → Compliance-DGtZCV4c.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DG4EFWyd.js → Cowork-4kQpoNsI.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-F6Oy5n2P.js → Cron-BxTYXXAN.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BOdgtalX.js → Crosschain-k0J0LT2N.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DT1dSkjH.js → DID-BaqhoPgN.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-NBUIqWzC.js → Dashboard-T4RVPIM1.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-CSpHeMYB.js → Dropdown-DszOToWq.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-CEG0xISr.js → EmailListRenderer-C9KJU7HF.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-BTZ0BZna.js → FamilyGuardDashboard-Cmr0JnsA.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BuuCTn2V.js → Federation-BI-_2xZX.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-KAVceevk.js → FormItemContext-DsnDEPsl.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DnHpcQvW.js → GenericCardRenderer-BLncAKKK.js} +1 -1
- package/src/assets/web-panel/assets/{Git-C_B_0HwB.js → Git-BPQhGXDn.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DPSZuzuu.js → Governance-CyElbUQW.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BV-06V7q.js → Inference-CcSntBQD.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-wpDuupn6.js → KnowledgeGraph-p6e7HZ2r.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-Bseca1_I.js → Logs-CNEtr-wz.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-Bj9xI0YH.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-d3kM4DDL.js → Marketplace-Dd2notAJ.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DQ_xZ23i.js → McpTools-BBsN2CSW.js} +4 -4
- package/src/assets/web-panel/assets/{Memory-CRIeYO4L.js → Memory-Dg2uTvwx.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BsllIa9l.js → MobileBridge-r1YMRiJV.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-BUuQy30X.js → MobileProjects-C-89kSm4.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-BOFDIzrC.js → Mtc-CrPZcVgf.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-BQg-vyvG.js → MtcAudit-sxi7hqJb.js} +5 -5
- package/src/assets/web-panel/assets/{Multisig-Bo1jrPdN.js → Multisig-CAgOMfF1.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-Bmod8alw.js → NLProgramming-DafaPts3.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-CGGFL8w-.js → Notes-CJM-xUW_.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-BsZvCJxC.js → NotificationSettings-L0ZjfAh_.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-C1-Quo_h.js → OrderTableRenderer-BB1CvCK0.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BjOeDYOi.js → Organization-DeLtgAD8.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-DwVV3l5A.js → Overflow-CKC2b10z.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-Cu3DQT9W.js → P2P-eyf2rzY1.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Cg0gR7dH.js → PdhVaultBrowser-5upNIOW8.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-CsAXxRN5.js → Permissions-B8p3W6JK.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-C-nNmnYp.js → PersonalDataHub-BnRMxTq3.js} +5 -5
- package/src/assets/web-panel/assets/{Pipeline-BOnW7nNc.js → Pipeline-DjCNI1li.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-ClLSyGKt.js → Privacy-u6gXLbWT.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-DuLvjjq7.js → ProjectInit-BZAw4tkM.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-DQYYbDD9.js → ProjectSettings-B1Tr72q7.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-Drw8MBGK.js → Projects-DO7HFuBQ.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-ckqHQe6K.js → Providers-BjCztyhj.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-DW5BXk-G.js → QrScannerModal-ZWyCUbR1.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-DDLnhNTp.js → QuickAsk-DhDjeW4G.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-PJQ2C91U.js → Recommend-R_CN2MuU.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-s6wmda34.js → RemoteSession-uxFcujeu.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-DC2sb-I3.js → Reputation-DX8D7rks.js} +1 -1
- package/src/assets/web-panel/assets/{Row-hPGk1eGj.js → Row-BYahQILD.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-RIvfZql0.js → RssFeed-CUSQ2tm-.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DFg1G1eR.js → Search-CnN_S8Cs.js} +1 -1
- package/src/assets/web-panel/assets/{Security-D6H5p8Dp.js → Security-DcZlh-O4.js} +4 -4
- package/src/assets/web-panel/assets/{Services-nxYiFV_w.js → Services-ZhBOjzIX.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-BmgFNAdB.js → Skeleton-D5Qnq_lI.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CsaaD2av.js → Skills-BC9cZ3Be.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-yM5y9yvK.js → Sla-DauJ3E8_.js} +1 -1
- package/src/assets/web-panel/assets/SpeechSettings-DbNeZ_fh.js +1 -0
- package/src/assets/web-panel/assets/{SyncSettings-CFVhEyyr.js → SyncSettings-DUvJbSct.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-DdO02Inn.js → Tasks-BXa-5noQ.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-Eo2d8Llu.js → Templates-JxaiUt_3.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-ChESOXgy.js → Tenant-BW4ERQN8.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-BJ7oDxTI.js → Terminal-DltUbdtv.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-hWX0fUvz.js → TimelineRenderer-CMoZz0Tc.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DVBZQnd-.js → Tokens-D_VEV60K.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-D89cQfVq.js → Trigger-CCXTCs0R.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-BIVSb4-V.js → Trust-lkGRIPcG.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-B58gWopl.js → UkeySign-BfGeQ9HX.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-DhHI7bmG.js → VideoEditing-BEC7pYvc.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-C4FheWS_.js → Wallet-BZdG24o0.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DnPRq-Bx.js → WebAuthn-yoEddedp.js} +3 -3
- package/src/assets/web-panel/assets/{WorkflowEditor-BerRPjpJ.js → WorkflowEditor-BXZEprOW.js} +1 -1
- package/src/assets/web-panel/assets/{chat-BzZ52iKr.js → chat-gg0bzZal.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BI_E4BAn.js → colors-DjRVRuin.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-d50mr3yk.js → compact-item-su-dieAc.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-C6FsQ1IH.js → createContext-Ci3S8oKF.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-CxbFX9uH.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DLZEMgLP.js → hasIn-D8F10heH.js} +1 -1
- package/src/assets/web-panel/assets/{index-D-aBumtY.js → index-11wtYQiF.js} +1 -1
- package/src/assets/web-panel/assets/{index-CjuKZBqJ.js → index-1IgxgALJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-9H_M2jju.js → index-1agckWSq.js} +1 -1
- package/src/assets/web-panel/assets/{index-DE0V6cp-.js → index-5JqhujnR.js} +1 -1
- package/src/assets/web-panel/assets/{index-Y2-q7QLm.js → index-6Tniqk1s.js} +1 -1
- package/src/assets/web-panel/assets/{index-DoFtCVZ7.js → index-8Z-8BIlN.js} +1 -1
- package/src/assets/web-panel/assets/{index-KNGgO4Wm.js → index-BCI5v0yB.js} +1 -1
- package/src/assets/web-panel/assets/{index-DY4j5zkF.js → index-BDJntYmJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BZjjdQ62.js → index-BGzixOGZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BTpIOTfR.js → index-BMMOVoLD.js} +1 -1
- package/src/assets/web-panel/assets/{index-BB9SqVSt.js → index-BTFpdBtt.js} +1 -1
- package/src/assets/web-panel/assets/{index-AHr7ryWf.js → index-Ba_HyPnE.js} +1 -1
- package/src/assets/web-panel/assets/{index-Pvf30m8Q.js → index-BbF1IHof.js} +1 -1
- package/src/assets/web-panel/assets/{index-CRN5TRTQ.js → index-BgT9su_e.js} +1 -1
- package/src/assets/web-panel/assets/{index-CUaEHfQ0.js → index-BzPB6kGZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CdKt9fOd.js → index-C6ygzplr.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dec0Kf_Z.js → index-CC3ZDjzY.js} +1 -1
- package/src/assets/web-panel/assets/{index-IPkwSAW_.js → index-CEmXRhAE.js} +1 -1
- package/src/assets/web-panel/assets/index-CJGOlduY.js +1 -0
- package/src/assets/web-panel/assets/{index-C3k8kevG.js → index-CMPqd5Cv.js} +1 -1
- package/src/assets/web-panel/assets/{index-A5CDWP7y.js → index-COWd8uGx.js} +1 -1
- package/src/assets/web-panel/assets/{index-CO8DAF7U.js → index-CPIYSp4H.js} +1 -1
- package/src/assets/web-panel/assets/{index-CVzuawCX.js → index-CR0h6seT.js} +1 -1
- package/src/assets/web-panel/assets/{index-Co7s9LsB.js → index-CUmDhC4j.js} +1 -1
- package/src/assets/web-panel/assets/index-CkBCN5yH.js +1 -0
- package/src/assets/web-panel/assets/{index-CLoTQr0W.js → index-CusgZPtc.js} +1 -1
- package/src/assets/web-panel/assets/{index-B81mo1Et.js → index-DBAETXft.js} +1 -1
- package/src/assets/web-panel/assets/{index-BcSUl9fA.js → index-DIJ2qFOC.js} +1 -1
- package/src/assets/web-panel/assets/{index-Q5Tn735s.js → index-Dbq4NMET.js} +1 -1
- package/src/assets/web-panel/assets/{index-GXE0D8Nx.js → index-DkMEF5VT.js} +1 -1
- package/src/assets/web-panel/assets/{index-TWG-_D1M.js → index-DkfQR3hM.js} +1 -1
- package/src/assets/web-panel/assets/{index-BAE3hwev.js → index-DnLucOn9.js} +1 -1
- package/src/assets/web-panel/assets/{index-CgkoH3_g.js → index-DugB_aKa.js} +1 -1
- package/src/assets/web-panel/assets/{index-BRGx3w6T.js → index-DyLUarhZ.js} +3 -3
- package/src/assets/web-panel/assets/{index-BeM4hfht.js → index-T6_6ygJZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DsscwxPE.js → index-Tu8eWqh-.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bmr_vxXD.js → index-W7XUgdVL.js} +1 -1
- package/src/assets/web-panel/assets/{index-BoNZlzhQ.js → index-dHZinfko.js} +1 -1
- package/src/assets/web-panel/assets/{index-DqkbHHg8.js → index-jyNgp5FI.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-D-4Hzgej.js → initDefaultProps-Cv4p8e4w.js} +1 -1
- package/src/assets/web-panel/assets/{motion-D4Wl4xU7.js → motion-B8EwmMOw.js} +1 -1
- package/src/assets/web-panel/assets/{move-Cd5eQvL0.js → move-B8R9F8TK.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-B4ilslCW.js → mtc-parser-DoFYz5Bp.js} +1 -1
- package/src/assets/web-panel/assets/{omit-Ckarx-tf.js → omit-CHWYLBjI.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-QJ0bpCmc.js → pickAttrs-CXuPDO77.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-CKHm-tq8.js → placementArrow-BaAtUUon.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-CV6a_w_Y.js → responsiveObserve-DCc4zcDD.js} +1 -1
- package/src/assets/web-panel/assets/{slide-mHpeQFgk.js → slide-B_lx89oZ.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-DIaQNQWA.js → statusUtils-DE8DPmR0.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-PJpzavV8.js → styleChecker-1ktXOsL_.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-BH7zTw8S.js → useFlexGapSupport-xH89-wjh.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-BDNG3JDd.js → useFs-DscvfW5p.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-CY2VWdUg.js → usePersonalDataHub-RdMKQta7.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-D0kw9jhz.js → vnode-Z3wTni2T.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-B5g7TN7r.js → zoom-B0iChCsm.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +3 -3
- package/src/commands/agent.js +105 -62
- package/src/commands/background-session.js +100 -10
- package/src/commands/git.js +39 -0
- package/src/commands/mcp.js +5 -0
- package/src/commands/plugin.js +160 -29
- package/src/commands/remote-control.js +295 -110
- package/src/commands/session-group.js +131 -0
- package/src/commands/session-location.js +48 -0
- package/src/commands/session-message.js +171 -0
- package/src/commands/session.js +22 -0
- package/src/commands/sync-providers.js +4 -1
- package/src/commands/update.js +1 -0
- package/src/data/changelog.json +41 -2
- package/src/gateways/ws/ws-agent-handler.js +20 -12
- package/src/harness/jsonl-session-store.js +279 -37
- package/src/harness/mcp-client.js +832 -91
- package/src/harness/session-index.js +15 -4
- package/src/lib/agent-worktree.js +8 -1
- package/src/lib/auto-mode-safety-classifier.js +3 -17
- package/src/lib/background-agent-keeper-protocol.js +26 -6
- package/src/lib/background-agent-supervisor.js +17 -1
- package/src/lib/background-session-transport.js +153 -27
- package/src/lib/browser-evidence.js +1405 -0
- package/src/lib/chrome-connector.js +465 -79
- package/src/lib/claude-project-auto-memory.js +481 -0
- package/src/lib/claude-project-storage-layout.js +104 -0
- package/src/lib/cloud/cloud-client.js +40 -0
- package/src/lib/execution-location-local-supervisor.mjs +226 -0
- package/src/lib/execution-location-runner-lifecycle.js +991 -0
- package/src/lib/execution-location-target-preflight.js +333 -0
- package/src/lib/execution-location-target.js +783 -13
- package/src/lib/file-lines.js +6 -1
- package/src/lib/gateway-client-resilience.js +571 -0
- package/src/lib/gitlab-mr-worktree.js +176 -0
- package/src/lib/hooks-v2-producers.js +119 -15
- package/src/lib/hooks-v2-workspace-context.js +44 -1
- package/src/lib/host-resource-budget.js +295 -0
- package/src/lib/ide-context.js +15 -2
- package/src/lib/llm-config-defaults.js +43 -0
- package/src/lib/mcp-client.js +2 -0
- package/src/lib/mcp-headers-helper.js +47 -5
- package/src/lib/mcp-lifecycle-authority.js +887 -0
- package/src/lib/mcp-oauth.js +156 -26
- package/src/lib/mcp-tls.js +330 -0
- package/src/lib/output-styles.js +12 -0
- package/src/lib/paths.js +260 -32
- package/src/lib/permission-request.js +48 -0
- package/src/lib/plugin-runtime/bin.js +3 -1
- package/src/lib/plugin-runtime/hooks.js +3 -1
- package/src/lib/plugin-runtime/install.js +730 -71
- package/src/lib/plugin-runtime/lsp.js +4 -4
- package/src/lib/plugin-runtime/marketplace-archive-source.js +366 -0
- package/src/lib/plugin-runtime/marketplace-catalog.js +63 -6
- package/src/lib/plugin-runtime/marketplace-command-descriptor.js +343 -0
- package/src/lib/plugin-runtime/marketplace-command-source.js +580 -0
- package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +1 -0
- package/src/lib/plugin-runtime/marketplace-source-adapter.js +188 -0
- package/src/lib/plugin-runtime/marketplace-source-cache.js +11 -1
- package/src/lib/plugin-runtime/mcp.js +3 -1
- package/src/lib/plugin-runtime/monitors.js +3 -1
- package/src/lib/plugin-runtime/remote-source.js +583 -58
- package/src/lib/plugin-runtime/settings.js +3 -1
- package/src/lib/plugin-runtime/trust.js +274 -13
- package/src/lib/plugin-security.js +393 -41
- package/src/lib/plugin-source-identity.js +850 -0
- package/src/lib/process-execution-broker/credential-agent.js +210 -41
- package/src/lib/process-execution-broker/index.js +15 -1
- package/src/lib/process-execution-broker/linux-cgroup-v2.js +391 -0
- package/src/lib/process-execution-broker/platform-sandbox.js +50 -28
- package/src/lib/project-mcp-trust.js +165 -10
- package/src/lib/remote-approval-bridge.js +136 -46
- package/src/lib/remote-control.js +217 -31
- package/src/lib/resume-session.js +9 -6
- package/src/lib/session-core-singletons.js +26 -11
- package/src/lib/session-host-lease.js +52 -16
- package/src/lib/session-lifecycle-scope.js +153 -0
- package/src/lib/session-message-fabric.js +1252 -0
- package/src/lib/session-projection.js +286 -3
- package/src/lib/session-runtime-retention.js +155 -0
- package/src/lib/session-store-guard.js +3 -1
- package/src/lib/session-workbench-store.js +466 -0
- package/src/lib/settings-loader.cjs +29 -0
- package/src/lib/spellcheck.js +211 -0
- package/src/lib/sub-agent-context.js +9 -9
- package/src/lib/sync-cli-db.js +485 -129
- package/src/lib/sync-credentials.js +31 -20
- package/src/lib/web-fetch.js +112 -40
- package/src/lib/web-search.js +127 -61
- package/src/lib/workspace-trust.js +793 -0
- package/src/repl/agent-repl.js +175 -19
- package/src/repl/permission-prompt.js +29 -8
- package/src/repl/repl-keybindings.js +55 -0
- package/src/runtime/agent-core.js +362 -20
- package/src/runtime/bootstrap.js +37 -13
- package/src/runtime/coding-agent-contract-shared.cjs +11 -4
- package/src/runtime/headless-runner.js +281 -102
- package/src/runtime/headless-stream.js +199 -30
- package/src/runtime/mcp-config.js +298 -6
- package/src/runtime/policies/agent-policy.js +10 -0
- package/src/runtime/status-diagnostics-lite.js +9 -1
- package/src/assets/web-panel/assets/ChatBubbleRenderer-4gGkdGgA.js +0 -1
- package/src/assets/web-panel/assets/MarkdownRenderer-B4RLp2zs.js +0 -1
- package/src/assets/web-panel/assets/SpeechSettings-DPy1XMYh.js +0 -1
- package/src/assets/web-panel/assets/devWarning-CagEcIex.js +0 -1
- package/src/assets/web-panel/assets/index-pzT9PpOU.js +0 -1
- package/src/assets/web-panel/assets/index-z1kFadaX.js +0 -1
package/src/lib/sync-cli-db.js
CHANGED
|
@@ -1,112 +1,315 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* CLI sync vault
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* tombstones, and knowledge_items. CLI vault lives at
|
|
7
|
-
* `~/.chainlesschain/cli-vault.db` and is plain SQLite (no SQLCipher) —
|
|
8
|
-
* encryption is at the OS file-permission layer; users wanting strong
|
|
9
|
-
* crypto should use desktop with hardware U-Key.
|
|
10
|
-
*
|
|
11
|
-
* Schema mirrors desktop `database-schema.js` for the 3 sync-relevant
|
|
12
|
-
* tables (auto-initialized on first open):
|
|
13
|
-
* - knowledge_items user notes (source of truth for sync)
|
|
14
|
-
* - sync_external_provider_cursor per-provider state
|
|
15
|
-
* - sync_external_tombstones per-provider delete queue
|
|
16
|
-
* - trg_sync_ext_tombstone_on_delete trigger (auto-fan tombstone on delete)
|
|
2
|
+
* CLI sync vault. The native better-sqlite3 driver is preferred, with a
|
|
3
|
+
* sql.js fallback for installations where an optional native addon cannot
|
|
4
|
+
* load. Both backends use the same strict per-operation file lock so a WASM
|
|
5
|
+
* snapshot can never overwrite a newer vault written by another cc process.
|
|
17
6
|
*/
|
|
18
7
|
|
|
19
8
|
"use strict";
|
|
20
9
|
|
|
21
10
|
import fs from "node:fs";
|
|
22
11
|
import path from "node:path";
|
|
23
|
-
import
|
|
12
|
+
import { randomUUID } from "node:crypto";
|
|
13
|
+
import { createRequire } from "node:module";
|
|
14
|
+
import { ensureDir, getHomeDir } from "./paths.js";
|
|
15
|
+
import { ensurePrivateFile } from "./secure-fs.js";
|
|
16
|
+
import { withFileLock } from "./with-file-lock.js";
|
|
17
|
+
|
|
18
|
+
const requireCjs = createRequire(import.meta.url);
|
|
19
|
+
|
|
20
|
+
const CLI_VAULT_SCHEMA = [
|
|
21
|
+
"CREATE TABLE IF NOT EXISTS knowledge_items (",
|
|
22
|
+
" id TEXT PRIMARY KEY,",
|
|
23
|
+
" title TEXT NOT NULL,",
|
|
24
|
+
" type TEXT NOT NULL DEFAULT 'note',",
|
|
25
|
+
" content TEXT,",
|
|
26
|
+
" tags TEXT,",
|
|
27
|
+
" created_at INTEGER NOT NULL,",
|
|
28
|
+
" updated_at INTEGER NOT NULL",
|
|
29
|
+
");",
|
|
30
|
+
"",
|
|
31
|
+
"CREATE TABLE IF NOT EXISTS sync_external_provider_cursor (",
|
|
32
|
+
" provider_id TEXT NOT NULL,",
|
|
33
|
+
" account_key TEXT NOT NULL DEFAULT '',",
|
|
34
|
+
" last_sync_at INTEGER NOT NULL DEFAULT 0,",
|
|
35
|
+
" last_item_id TEXT,",
|
|
36
|
+
" remote_etag_map TEXT NOT NULL DEFAULT '{}',",
|
|
37
|
+
" remote_filename_map TEXT NOT NULL DEFAULT '{}',",
|
|
38
|
+
" last_run_status TEXT,",
|
|
39
|
+
" last_run_error TEXT,",
|
|
40
|
+
" last_run_duration_ms INTEGER,",
|
|
41
|
+
" items_pushed INTEGER NOT NULL DEFAULT 0,",
|
|
42
|
+
" items_skipped INTEGER NOT NULL DEFAULT 0,",
|
|
43
|
+
" items_deleted INTEGER NOT NULL DEFAULT 0,",
|
|
44
|
+
" created_at INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000),",
|
|
45
|
+
" updated_at INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000),",
|
|
46
|
+
" PRIMARY KEY (provider_id, account_key)",
|
|
47
|
+
");",
|
|
48
|
+
"",
|
|
49
|
+
"CREATE TABLE IF NOT EXISTS sync_external_tombstones (",
|
|
50
|
+
" id INTEGER PRIMARY KEY AUTOINCREMENT,",
|
|
51
|
+
" provider_id TEXT NOT NULL,",
|
|
52
|
+
" account_key TEXT NOT NULL DEFAULT '',",
|
|
53
|
+
" item_id TEXT NOT NULL,",
|
|
54
|
+
" resource_type TEXT,",
|
|
55
|
+
" deleted_at INTEGER NOT NULL,",
|
|
56
|
+
" retry_count INTEGER NOT NULL DEFAULT 0,",
|
|
57
|
+
" last_error TEXT,",
|
|
58
|
+
" UNIQUE(provider_id, account_key, item_id)",
|
|
59
|
+
");",
|
|
60
|
+
"",
|
|
61
|
+
"CREATE TRIGGER IF NOT EXISTS trg_sync_ext_tombstone_on_delete",
|
|
62
|
+
"AFTER DELETE ON knowledge_items",
|
|
63
|
+
"FOR EACH ROW",
|
|
64
|
+
"BEGIN",
|
|
65
|
+
" INSERT OR IGNORE INTO sync_external_tombstones",
|
|
66
|
+
" (provider_id, account_key, item_id, resource_type, deleted_at)",
|
|
67
|
+
" SELECT c.provider_id, c.account_key, OLD.id, 'KNOWLEDGE_ITEM',",
|
|
68
|
+
" (strftime('%s','now') * 1000)",
|
|
69
|
+
" FROM sync_external_provider_cursor c;",
|
|
70
|
+
"END;",
|
|
71
|
+
].join("\n");
|
|
72
|
+
|
|
73
|
+
const VAULT_LOCK_OPTIONS = Object.freeze({
|
|
74
|
+
failIfUnavailable: true,
|
|
75
|
+
timeoutMs: 3000,
|
|
76
|
+
retryMs: 25,
|
|
77
|
+
maxRetryMs: 150,
|
|
78
|
+
retryJitterMs: 25,
|
|
79
|
+
yieldAfterReleaseMs: 5,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const defaultDeps = Object.freeze({
|
|
83
|
+
fs,
|
|
84
|
+
ensureDir,
|
|
85
|
+
ensurePrivateFile,
|
|
86
|
+
randomUUID,
|
|
87
|
+
withFileLock,
|
|
88
|
+
platform: () => process.platform,
|
|
89
|
+
async loadNativeDatabase() {
|
|
90
|
+
return requireCjs("better-sqlite3");
|
|
91
|
+
},
|
|
92
|
+
async loadSqlJs() {
|
|
93
|
+
return requireCjs("sql.js");
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Injectable only for focused driver-loading tests. Production callers must
|
|
99
|
+
* leave these dependencies at their secure defaults.
|
|
100
|
+
*/
|
|
101
|
+
const _deps = { ...defaultDeps };
|
|
102
|
+
|
|
103
|
+
let _ccDirOverride = null;
|
|
24
104
|
|
|
25
105
|
function _ccDir() {
|
|
26
|
-
return (
|
|
27
|
-
process.env.CHAINLESSCHAIN_HOME ||
|
|
28
|
-
path.join(os.homedir(), ".chainlesschain")
|
|
29
|
-
);
|
|
106
|
+
return _ccDirOverride ?? getHomeDir();
|
|
30
107
|
}
|
|
31
108
|
|
|
32
109
|
function _vaultPath() {
|
|
33
110
|
return path.join(_ccDir(), "cli-vault.db");
|
|
34
111
|
}
|
|
35
112
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
113
|
+
function vaultError(code, message, cause) {
|
|
114
|
+
const error = cause ? new Error(message, { cause }) : new Error(message);
|
|
115
|
+
error.code = code;
|
|
116
|
+
return error;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function isVaultLockFailure(error) {
|
|
120
|
+
return [
|
|
121
|
+
"STATE_LOCK_UNAVAILABLE",
|
|
122
|
+
"STATE_LOCK_OWNERSHIP_LOST",
|
|
123
|
+
"STATE_LOCK_RELEASE_HANDOFF_FAILED",
|
|
124
|
+
].includes(error?.code);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function withVaultLock(vaultPath, callback) {
|
|
128
|
+
try {
|
|
129
|
+
return _deps.withFileLock(vaultPath, callback, VAULT_LOCK_OPTIONS);
|
|
130
|
+
} catch (error) {
|
|
131
|
+
if (isVaultLockFailure(error)) {
|
|
132
|
+
throw vaultError(
|
|
133
|
+
"CLI_VAULT_LOCK_UNAVAILABLE",
|
|
134
|
+
"CLI vault is busy and could not acquire its exclusive state lock. Retry the sync after the other ChainlessChain process finishes.",
|
|
135
|
+
error,
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function ensureVaultDirectory(directory) {
|
|
143
|
+
_deps.ensureDir(directory);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function ensureVaultFile(vaultPath) {
|
|
147
|
+
_deps.ensurePrivateFile(vaultPath, {
|
|
148
|
+
applyWindowsAcl: true,
|
|
149
|
+
failIfUnavailable: true,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function nativeSqliteSidecarPaths(vaultPath) {
|
|
154
|
+
return [vaultPath + "-wal", vaultPath + "-shm", vaultPath + "-journal"];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function assertNoNativeSqliteSidecars(vaultPath) {
|
|
158
|
+
const sidecar = nativeSqliteSidecarPaths(vaultPath).find((candidate) =>
|
|
159
|
+
_deps.fs.existsSync(candidate),
|
|
160
|
+
);
|
|
161
|
+
if (sidecar) {
|
|
162
|
+
throw vaultError(
|
|
163
|
+
"CLI_VAULT_WASM_NATIVE_CONCURRENCY_UNSAFE",
|
|
164
|
+
"CLI vault has an active native SQLite journal. Refusing the sql.js fallback because concurrent native access could lose vault updates. Close the other SQLite user and retry.",
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function syncVaultDirectory(vaultPath) {
|
|
170
|
+
let descriptor = null;
|
|
171
|
+
try {
|
|
172
|
+
descriptor = _deps.fs.openSync(path.dirname(vaultPath), "r");
|
|
173
|
+
_deps.fs.fsyncSync(descriptor);
|
|
174
|
+
} catch (error) {
|
|
175
|
+
// Windows does not consistently permit directory fsync. The staged file
|
|
176
|
+
// itself is always fsynced before rename, so retain the platform-specific
|
|
177
|
+
// best effort used by the repository's other durable stores.
|
|
178
|
+
if (
|
|
179
|
+
_deps.platform() !== "win32" ||
|
|
180
|
+
!["EACCES", "EINVAL", "ENOTSUP", "EPERM"].includes(error?.code)
|
|
181
|
+
) {
|
|
182
|
+
throw error;
|
|
183
|
+
}
|
|
184
|
+
} finally {
|
|
185
|
+
if (descriptor != null) _deps.fs.closeSync(descriptor);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function persistSqlJsBytes(vaultPath, bytes) {
|
|
190
|
+
const temporary = path.join(
|
|
191
|
+
path.dirname(vaultPath),
|
|
192
|
+
"." +
|
|
193
|
+
path.basename(vaultPath) +
|
|
194
|
+
"." +
|
|
195
|
+
process.pid +
|
|
196
|
+
"." +
|
|
197
|
+
_deps.randomUUID() +
|
|
198
|
+
".tmp",
|
|
199
|
+
);
|
|
200
|
+
let descriptor = null;
|
|
201
|
+
try {
|
|
202
|
+
descriptor = _deps.fs.openSync(temporary, "wx", 0o600);
|
|
203
|
+
// The parent is already private. Repair this file before it receives
|
|
204
|
+
// database content so a Windows inherited ACL can never expose a staging
|
|
205
|
+
// snapshot during the write window.
|
|
206
|
+
_deps.ensurePrivateFile(temporary, {
|
|
207
|
+
applyWindowsAcl: true,
|
|
208
|
+
failIfUnavailable: true,
|
|
209
|
+
});
|
|
210
|
+
_deps.fs.writeFileSync(descriptor, bytes);
|
|
211
|
+
_deps.fs.fsyncSync(descriptor);
|
|
212
|
+
_deps.fs.closeSync(descriptor);
|
|
213
|
+
descriptor = null;
|
|
214
|
+
|
|
215
|
+
// Verify a pre-existing destination before replacement. The strict lock
|
|
216
|
+
// serializes cooperating cc processes; this check additionally refuses a
|
|
217
|
+
// symlink or broad ACL introduced by a local filesystem race.
|
|
218
|
+
ensureVaultFile(vaultPath);
|
|
219
|
+
_deps.fs.renameSync(temporary, vaultPath);
|
|
220
|
+
ensureVaultFile(vaultPath);
|
|
221
|
+
syncVaultDirectory(vaultPath);
|
|
222
|
+
} catch (error) {
|
|
223
|
+
if (error?.code?.startsWith("CLI_VAULT_")) throw error;
|
|
224
|
+
throw vaultError(
|
|
225
|
+
"CLI_VAULT_WASM_WRITE_FAILED",
|
|
226
|
+
"Could not atomically persist the sql.js CLI vault. No further sync work was performed.",
|
|
227
|
+
error,
|
|
228
|
+
);
|
|
229
|
+
} finally {
|
|
230
|
+
if (descriptor != null) {
|
|
231
|
+
try {
|
|
232
|
+
_deps.fs.closeSync(descriptor);
|
|
233
|
+
} catch {
|
|
234
|
+
// Preserve the primary write failure.
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
try {
|
|
238
|
+
if (_deps.fs.existsSync(temporary)) {
|
|
239
|
+
_deps.fs.rmSync(temporary, { force: true });
|
|
240
|
+
}
|
|
241
|
+
} catch {
|
|
242
|
+
// A uniquely named stale temp cannot be selected as the vault.
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function openSqlJsDatabase(SQL, vaultPath) {
|
|
248
|
+
if (_deps.fs.existsSync(vaultPath)) {
|
|
249
|
+
ensureVaultFile(vaultPath);
|
|
250
|
+
return new SQL.Database(_deps.fs.readFileSync(vaultPath));
|
|
251
|
+
}
|
|
252
|
+
return new SQL.Database();
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function runSqlJsStatement(sqlDb, sql, params) {
|
|
256
|
+
const statement = sqlDb.prepare(sql);
|
|
257
|
+
try {
|
|
258
|
+
statement.bind(params);
|
|
259
|
+
statement.step();
|
|
260
|
+
return {
|
|
261
|
+
changes: sqlDb.getRowsModified(),
|
|
262
|
+
lastInsertRowid: 0,
|
|
263
|
+
};
|
|
264
|
+
} finally {
|
|
265
|
+
statement.free();
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function getSqlJsStatement(sqlDb, sql, params) {
|
|
270
|
+
const statement = sqlDb.prepare(sql);
|
|
271
|
+
try {
|
|
272
|
+
statement.bind(params);
|
|
273
|
+
return statement.step() ? statement.getAsObject() : undefined;
|
|
274
|
+
} finally {
|
|
275
|
+
statement.free();
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function allSqlJsStatement(sqlDb, sql, params) {
|
|
280
|
+
const statement = sqlDb.prepare(sql);
|
|
281
|
+
try {
|
|
282
|
+
statement.bind(params);
|
|
283
|
+
const rows = [];
|
|
284
|
+
while (statement.step()) rows.push(statement.getAsObject());
|
|
285
|
+
return rows;
|
|
286
|
+
} finally {
|
|
287
|
+
statement.free();
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function closedVaultError() {
|
|
292
|
+
return vaultError("CLI_VAULT_CLOSED", "CLI vault handle is already closed.");
|
|
293
|
+
}
|
|
88
294
|
|
|
89
295
|
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
296
|
+
* Existing direct wrapper retained for users that already supply a
|
|
297
|
+
* better-sqlite3-compatible database object.
|
|
92
298
|
*/
|
|
93
299
|
class CliVaultDbManager {
|
|
94
300
|
constructor(db) {
|
|
95
301
|
this.db = db;
|
|
96
302
|
}
|
|
97
303
|
|
|
98
|
-
/** Match desktop dbManager.run(sql, params=[]) */
|
|
99
304
|
run(sql, params = []) {
|
|
100
305
|
this.db.prepare(sql).run(...params);
|
|
101
306
|
}
|
|
102
307
|
|
|
103
|
-
/** Match desktop dbManager.get(sql, params=[]) → row or undefined */
|
|
104
308
|
get(sql, params = []) {
|
|
105
309
|
const row = this.db.prepare(sql).get(...params);
|
|
106
310
|
return row ?? undefined;
|
|
107
311
|
}
|
|
108
312
|
|
|
109
|
-
/** Match desktop dbManager.all(sql, params=[]) → rows */
|
|
110
313
|
all(sql, params = []) {
|
|
111
314
|
return this.db.prepare(sql).all(...params);
|
|
112
315
|
}
|
|
@@ -117,78 +320,231 @@ class CliVaultDbManager {
|
|
|
117
320
|
}
|
|
118
321
|
|
|
119
322
|
/**
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
323
|
+
* Native connections reopen under the shared vault lock for every operation.
|
|
324
|
+
* This is intentional: a sql.js writer atomically replaces the database file,
|
|
325
|
+
* so retaining a native descriptor across calls could otherwise write to the
|
|
326
|
+
* old, unlinked inode after a fallback operation.
|
|
123
327
|
*/
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
328
|
+
class SerializedNativeCliVaultDbManager {
|
|
329
|
+
constructor(vaultPath, Database) {
|
|
330
|
+
this.vaultPath = vaultPath;
|
|
331
|
+
this.Database = Database;
|
|
332
|
+
this.backend = "better-sqlite3";
|
|
333
|
+
this.closed = false;
|
|
334
|
+
}
|
|
127
335
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
(err?.message || String(err)),
|
|
140
|
-
);
|
|
141
|
-
e.code = "BETTER_SQLITE3_MISSING";
|
|
142
|
-
throw e;
|
|
336
|
+
_withDatabase(callback) {
|
|
337
|
+
if (this.closed) throw closedVaultError();
|
|
338
|
+
return withVaultLock(this.vaultPath, () => {
|
|
339
|
+
ensureVaultFile(this.vaultPath);
|
|
340
|
+
const db = new this.Database(this.vaultPath);
|
|
341
|
+
try {
|
|
342
|
+
return callback(db);
|
|
343
|
+
} finally {
|
|
344
|
+
if (db?.open) db.close();
|
|
345
|
+
}
|
|
346
|
+
});
|
|
143
347
|
}
|
|
144
348
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
349
|
+
run(sql, params = []) {
|
|
350
|
+
this._withDatabase((db) => db.prepare(sql).run(...params));
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
get(sql, params = []) {
|
|
354
|
+
return this._withDatabase((db) => {
|
|
355
|
+
const row = db.prepare(sql).get(...params);
|
|
356
|
+
return row ?? undefined;
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
all(sql, params = []) {
|
|
361
|
+
return this._withDatabase((db) => db.prepare(sql).all(...params));
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
close() {
|
|
365
|
+
this.closed = true;
|
|
366
|
+
}
|
|
149
367
|
}
|
|
150
368
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
369
|
+
/**
|
|
370
|
+
* sql.js has no filesystem locking. Each operation therefore opens the latest
|
|
371
|
+
* committed bytes while holding the same strict lock as the native backend.
|
|
372
|
+
* Writes export, fsync and atomically rename before releasing that lock.
|
|
373
|
+
*/
|
|
374
|
+
class SerializedSqlJsCliVaultDbManager {
|
|
375
|
+
constructor(vaultPath, SQL) {
|
|
376
|
+
this.vaultPath = vaultPath;
|
|
377
|
+
this.SQL = SQL;
|
|
378
|
+
this.backend = "sql.js";
|
|
379
|
+
this.closed = false;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
_withDatabase(write, callback) {
|
|
383
|
+
if (this.closed) throw closedVaultError();
|
|
384
|
+
return withVaultLock(this.vaultPath, () => {
|
|
385
|
+
assertNoNativeSqliteSidecars(this.vaultPath);
|
|
386
|
+
const db = openSqlJsDatabase(this.SQL, this.vaultPath);
|
|
387
|
+
try {
|
|
388
|
+
const result = callback(db);
|
|
389
|
+
if (write) {
|
|
390
|
+
const bytes = Buffer.from(db.export());
|
|
391
|
+
persistSqlJsBytes(this.vaultPath, bytes);
|
|
392
|
+
}
|
|
393
|
+
return result;
|
|
394
|
+
} finally {
|
|
395
|
+
db.close();
|
|
396
|
+
}
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
run(sql, params = []) {
|
|
401
|
+
this._withDatabase(true, (db) => runSqlJsStatement(db, sql, params));
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
get(sql, params = []) {
|
|
405
|
+
return this._withDatabase(false, (db) =>
|
|
406
|
+
getSqlJsStatement(db, sql, params),
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
all(sql, params = []) {
|
|
411
|
+
return this._withDatabase(false, (db) =>
|
|
412
|
+
allSqlJsStatement(db, sql, params),
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
close() {
|
|
417
|
+
this.closed = true;
|
|
418
|
+
}
|
|
154
419
|
}
|
|
155
|
-
|
|
156
|
-
|
|
420
|
+
|
|
421
|
+
function initializeNativeVault(vaultPath, Database) {
|
|
422
|
+
withVaultLock(vaultPath, () => {
|
|
423
|
+
ensureVaultFile(vaultPath);
|
|
424
|
+
const db = new Database(vaultPath);
|
|
425
|
+
try {
|
|
426
|
+
db.exec(CLI_VAULT_SCHEMA);
|
|
427
|
+
} finally {
|
|
428
|
+
if (db?.open) db.close();
|
|
429
|
+
}
|
|
430
|
+
ensureVaultFile(vaultPath);
|
|
431
|
+
});
|
|
157
432
|
}
|
|
158
433
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
434
|
+
function initializeSqlJsVault(vaultPath, SQL) {
|
|
435
|
+
withVaultLock(vaultPath, () => {
|
|
436
|
+
assertNoNativeSqliteSidecars(vaultPath);
|
|
437
|
+
const db = openSqlJsDatabase(SQL, vaultPath);
|
|
438
|
+
try {
|
|
439
|
+
db.exec(CLI_VAULT_SCHEMA);
|
|
440
|
+
persistSqlJsBytes(vaultPath, Buffer.from(db.export()));
|
|
441
|
+
} finally {
|
|
442
|
+
db.close();
|
|
443
|
+
}
|
|
444
|
+
});
|
|
163
445
|
}
|
|
164
|
-
|
|
165
|
-
|
|
446
|
+
|
|
447
|
+
async function loadSqlJsFallback(vaultPath, nativeError) {
|
|
448
|
+
let initialize;
|
|
449
|
+
try {
|
|
450
|
+
initialize = await _deps.loadSqlJs();
|
|
451
|
+
} catch (error) {
|
|
452
|
+
throw vaultError(
|
|
453
|
+
"CLI_VAULT_SQLJS_UNAVAILABLE",
|
|
454
|
+
"CLI vault could not load better-sqlite3 and its sql.js fallback is unavailable. Reinstall ChainlessChain with its runtime dependencies.",
|
|
455
|
+
error,
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
let SQL;
|
|
460
|
+
try {
|
|
461
|
+
SQL = await initialize();
|
|
462
|
+
} catch (error) {
|
|
463
|
+
throw vaultError(
|
|
464
|
+
"CLI_VAULT_SQLJS_UNAVAILABLE",
|
|
465
|
+
"CLI vault could not initialize its sql.js fallback. Reinstall ChainlessChain with its runtime dependencies.",
|
|
466
|
+
error,
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
if (!SQL || typeof SQL.Database !== "function") {
|
|
470
|
+
throw vaultError(
|
|
471
|
+
"CLI_VAULT_SQLJS_UNAVAILABLE",
|
|
472
|
+
"CLI vault sql.js fallback did not provide a SQLite database constructor.",
|
|
473
|
+
nativeError,
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
try {
|
|
478
|
+
initializeSqlJsVault(vaultPath, SQL);
|
|
479
|
+
} catch (error) {
|
|
480
|
+
if (error?.code?.startsWith("CLI_VAULT_")) throw error;
|
|
481
|
+
throw vaultError(
|
|
482
|
+
"CLI_VAULT_WASM_OPEN_FAILED",
|
|
483
|
+
"Could not open the sql.js CLI vault. Check the vault file permissions and integrity.",
|
|
484
|
+
error,
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
return {
|
|
488
|
+
dbManager: new SerializedSqlJsCliVaultDbManager(vaultPath, SQL),
|
|
489
|
+
vaultPath,
|
|
490
|
+
backend: "sql.js",
|
|
491
|
+
};
|
|
166
492
|
}
|
|
167
493
|
|
|
168
|
-
async function
|
|
169
|
-
const
|
|
170
|
-
|
|
494
|
+
async function openCliVault() {
|
|
495
|
+
const directory = _ccDir();
|
|
496
|
+
ensureVaultDirectory(directory);
|
|
497
|
+
const vaultPath = _vaultPath();
|
|
498
|
+
|
|
171
499
|
let Database;
|
|
500
|
+
let nativeError = null;
|
|
172
501
|
try {
|
|
173
|
-
Database =
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
502
|
+
Database = await _deps.loadNativeDatabase();
|
|
503
|
+
if (typeof Database !== "function") {
|
|
504
|
+
throw new TypeError(
|
|
505
|
+
"better-sqlite3 did not export a database constructor",
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
// A memory probe distinguishes an unavailable native binding from a vault
|
|
509
|
+
// schema/permission failure. The latter must remain visible and must not
|
|
510
|
+
// silently switch backends.
|
|
511
|
+
const probe = new Database(":memory:");
|
|
512
|
+
if (probe?.open) probe.close();
|
|
513
|
+
} catch (error) {
|
|
514
|
+
nativeError = error;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
if (!nativeError) {
|
|
518
|
+
initializeNativeVault(vaultPath, Database);
|
|
519
|
+
return {
|
|
520
|
+
dbManager: new SerializedNativeCliVaultDbManager(vaultPath, Database),
|
|
521
|
+
vaultPath,
|
|
522
|
+
backend: "better-sqlite3",
|
|
523
|
+
};
|
|
180
524
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
525
|
+
return loadSqlJsFallback(vaultPath, nativeError);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
function _setCcDirForTest(directory) {
|
|
529
|
+
_ccDirOverride = directory;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
function _resetCcDirForTest() {
|
|
533
|
+
_ccDirOverride = null;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
function _resetDepsForTest() {
|
|
537
|
+
for (const key of Object.keys(_deps)) delete _deps[key];
|
|
538
|
+
Object.assign(_deps, defaultDeps);
|
|
185
539
|
}
|
|
186
540
|
|
|
187
541
|
export {
|
|
188
|
-
|
|
542
|
+
openCliVault,
|
|
189
543
|
CliVaultDbManager,
|
|
190
544
|
CLI_VAULT_SCHEMA,
|
|
545
|
+
_deps,
|
|
191
546
|
_setCcDirForTest,
|
|
192
547
|
_resetCcDirForTest,
|
|
193
|
-
|
|
548
|
+
_resetDepsForTest,
|
|
549
|
+
_vaultPath,
|
|
194
550
|
};
|