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.
Files changed (256) hide show
  1. package/package.json +2 -1
  2. package/src/assets/web-panel/assets/{AIOps-CEeYTeDB.js → AIOps-B3gWmXjo.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-BeRUQ3V2.js → ActionButton-G9pdT-0e.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-DrV718XF.js → Analytics-Ca30J7m2.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-Cd2Frt7Q.js → AppLayout-BtVTm8PU.js} +5 -5
  6. package/src/assets/web-panel/assets/{Artifacts-CUJMlORU.js → Artifacts-BhViNa6u.js} +1 -1
  7. package/src/assets/web-panel/assets/{Audit-CXJcfT6p.js → Audit-DhKq-FnY.js} +1 -1
  8. package/src/assets/web-panel/assets/{BackgroundAgents-DOv6Z7H9.js → BackgroundAgents-BL0SVbnE.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-BwdDyBI0.js → Backup-BWkblnFi.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-BmLn4kYH.js → BaseInput-ClaRNrF8.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-COg8pAW2.js → Chat-sZE2Z77o.js} +4 -4
  12. package/src/assets/web-panel/assets/ChatBubbleRenderer-BAfKOnRe.js +1 -0
  13. package/src/assets/web-panel/assets/{Checkbox-BCP4uoU8.js → Checkbox-Cvhay5WM.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-pRt6Y9JI.js → Codegen-BpejL-4N.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-DLaprKhS.js → Col-g2Ki6g_1.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-DyATsz5f.js → Community-D2xKbNo9.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-BXAaupZK.js → Compact-DbL1Pds3.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-DpcJBELr.js → Compliance-DGtZCV4c.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-DG4EFWyd.js → Cowork-4kQpoNsI.js} +3 -3
  20. package/src/assets/web-panel/assets/{Cron-F6Oy5n2P.js → Cron-BxTYXXAN.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-BOdgtalX.js → Crosschain-k0J0LT2N.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-DT1dSkjH.js → DID-BaqhoPgN.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-NBUIqWzC.js → Dashboard-T4RVPIM1.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-CSpHeMYB.js → Dropdown-DszOToWq.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-CEG0xISr.js → EmailListRenderer-C9KJU7HF.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-BTZ0BZna.js → FamilyGuardDashboard-Cmr0JnsA.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-BuuCTn2V.js → Federation-BI-_2xZX.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-KAVceevk.js → FormItemContext-DsnDEPsl.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-DnHpcQvW.js → GenericCardRenderer-BLncAKKK.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-C_B_0HwB.js → Git-BPQhGXDn.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-DPSZuzuu.js → Governance-CyElbUQW.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-BV-06V7q.js → Inference-CcSntBQD.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-wpDuupn6.js → KnowledgeGraph-p6e7HZ2r.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-Bseca1_I.js → Logs-CNEtr-wz.js} +2 -2
  35. package/src/assets/web-panel/assets/MarkdownRenderer-Bj9xI0YH.js +1 -0
  36. package/src/assets/web-panel/assets/{Marketplace-d3kM4DDL.js → Marketplace-Dd2notAJ.js} +1 -1
  37. package/src/assets/web-panel/assets/{McpTools-DQ_xZ23i.js → McpTools-BBsN2CSW.js} +4 -4
  38. package/src/assets/web-panel/assets/{Memory-CRIeYO4L.js → Memory-Dg2uTvwx.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileBridge-BsllIa9l.js → MobileBridge-r1YMRiJV.js} +1 -1
  40. package/src/assets/web-panel/assets/{MobileProjects-BUuQy30X.js → MobileProjects-C-89kSm4.js} +1 -1
  41. package/src/assets/web-panel/assets/{Mtc-BOFDIzrC.js → Mtc-CrPZcVgf.js} +5 -5
  42. package/src/assets/web-panel/assets/{MtcAudit-BQg-vyvG.js → MtcAudit-sxi7hqJb.js} +5 -5
  43. package/src/assets/web-panel/assets/{Multisig-Bo1jrPdN.js → Multisig-CAgOMfF1.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-Bmod8alw.js → NLProgramming-DafaPts3.js} +1 -1
  45. package/src/assets/web-panel/assets/{Notes-CGGFL8w-.js → Notes-CJM-xUW_.js} +3 -3
  46. package/src/assets/web-panel/assets/{NotificationSettings-BsZvCJxC.js → NotificationSettings-L0ZjfAh_.js} +1 -1
  47. package/src/assets/web-panel/assets/{OrderTableRenderer-C1-Quo_h.js → OrderTableRenderer-BB1CvCK0.js} +1 -1
  48. package/src/assets/web-panel/assets/{Organization-BjOeDYOi.js → Organization-DeLtgAD8.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-DwVV3l5A.js → Overflow-CKC2b10z.js} +1 -1
  50. package/src/assets/web-panel/assets/{P2P-Cu3DQT9W.js → P2P-eyf2rzY1.js} +2 -2
  51. package/src/assets/web-panel/assets/{PdhVaultBrowser-Cg0gR7dH.js → PdhVaultBrowser-5upNIOW8.js} +3 -3
  52. package/src/assets/web-panel/assets/{Permissions-CsAXxRN5.js → Permissions-B8p3W6JK.js} +4 -4
  53. package/src/assets/web-panel/assets/{PersonalDataHub-C-nNmnYp.js → PersonalDataHub-BnRMxTq3.js} +5 -5
  54. package/src/assets/web-panel/assets/{Pipeline-BOnW7nNc.js → Pipeline-DjCNI1li.js} +1 -1
  55. package/src/assets/web-panel/assets/{Privacy-ClLSyGKt.js → Privacy-u6gXLbWT.js} +1 -1
  56. package/src/assets/web-panel/assets/{ProjectInit-DuLvjjq7.js → ProjectInit-BZAw4tkM.js} +2 -2
  57. package/src/assets/web-panel/assets/{ProjectSettings-DQYYbDD9.js → ProjectSettings-B1Tr72q7.js} +2 -2
  58. package/src/assets/web-panel/assets/{Projects-Drw8MBGK.js → Projects-DO7HFuBQ.js} +1 -1
  59. package/src/assets/web-panel/assets/{Providers-ckqHQe6K.js → Providers-BjCztyhj.js} +1 -1
  60. package/src/assets/web-panel/assets/{QrScannerModal-DW5BXk-G.js → QrScannerModal-ZWyCUbR1.js} +1 -1
  61. package/src/assets/web-panel/assets/{QuickAsk-DDLnhNTp.js → QuickAsk-DhDjeW4G.js} +1 -1
  62. package/src/assets/web-panel/assets/{Recommend-PJQ2C91U.js → Recommend-R_CN2MuU.js} +1 -1
  63. package/src/assets/web-panel/assets/{RemoteSession-s6wmda34.js → RemoteSession-uxFcujeu.js} +2 -2
  64. package/src/assets/web-panel/assets/{Reputation-DC2sb-I3.js → Reputation-DX8D7rks.js} +1 -1
  65. package/src/assets/web-panel/assets/{Row-hPGk1eGj.js → Row-BYahQILD.js} +1 -1
  66. package/src/assets/web-panel/assets/{RssFeed-RIvfZql0.js → RssFeed-CUSQ2tm-.js} +3 -3
  67. package/src/assets/web-panel/assets/{Search-DFg1G1eR.js → Search-CnN_S8Cs.js} +1 -1
  68. package/src/assets/web-panel/assets/{Security-D6H5p8Dp.js → Security-DcZlh-O4.js} +4 -4
  69. package/src/assets/web-panel/assets/{Services-nxYiFV_w.js → Services-ZhBOjzIX.js} +2 -2
  70. package/src/assets/web-panel/assets/{Skeleton-BmgFNAdB.js → Skeleton-D5Qnq_lI.js} +1 -1
  71. package/src/assets/web-panel/assets/{Skills-CsaaD2av.js → Skills-BC9cZ3Be.js} +1 -1
  72. package/src/assets/web-panel/assets/{Sla-yM5y9yvK.js → Sla-DauJ3E8_.js} +1 -1
  73. package/src/assets/web-panel/assets/SpeechSettings-DbNeZ_fh.js +1 -0
  74. package/src/assets/web-panel/assets/{SyncSettings-CFVhEyyr.js → SyncSettings-DUvJbSct.js} +2 -2
  75. package/src/assets/web-panel/assets/{Tasks-DdO02Inn.js → Tasks-BXa-5noQ.js} +1 -1
  76. package/src/assets/web-panel/assets/{Templates-Eo2d8Llu.js → Templates-JxaiUt_3.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tenant-ChESOXgy.js → Tenant-BW4ERQN8.js} +1 -1
  78. package/src/assets/web-panel/assets/{Terminal-BJ7oDxTI.js → Terminal-DltUbdtv.js} +2 -2
  79. package/src/assets/web-panel/assets/{TimelineRenderer-hWX0fUvz.js → TimelineRenderer-CMoZz0Tc.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tokens-DVBZQnd-.js → Tokens-D_VEV60K.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trigger-D89cQfVq.js → Trigger-CCXTCs0R.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trust-BIVSb4-V.js → Trust-lkGRIPcG.js} +1 -1
  83. package/src/assets/web-panel/assets/{UkeySign-B58gWopl.js → UkeySign-BfGeQ9HX.js} +1 -1
  84. package/src/assets/web-panel/assets/{VideoEditing-DhHI7bmG.js → VideoEditing-BEC7pYvc.js} +1 -1
  85. package/src/assets/web-panel/assets/{Wallet-C4FheWS_.js → Wallet-BZdG24o0.js} +4 -4
  86. package/src/assets/web-panel/assets/{WebAuthn-DnPRq-Bx.js → WebAuthn-yoEddedp.js} +3 -3
  87. package/src/assets/web-panel/assets/{WorkflowEditor-BerRPjpJ.js → WorkflowEditor-BXZEprOW.js} +1 -1
  88. package/src/assets/web-panel/assets/{chat-BzZ52iKr.js → chat-gg0bzZal.js} +1 -1
  89. package/src/assets/web-panel/assets/{colors-BI_E4BAn.js → colors-DjRVRuin.js} +1 -1
  90. package/src/assets/web-panel/assets/{compact-item-d50mr3yk.js → compact-item-su-dieAc.js} +1 -1
  91. package/src/assets/web-panel/assets/{createContext-C6FsQ1IH.js → createContext-Ci3S8oKF.js} +1 -1
  92. package/src/assets/web-panel/assets/devWarning-CxbFX9uH.js +1 -0
  93. package/src/assets/web-panel/assets/{hasIn-DLZEMgLP.js → hasIn-D8F10heH.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-D-aBumtY.js → index-11wtYQiF.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-CjuKZBqJ.js → index-1IgxgALJ.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-9H_M2jju.js → index-1agckWSq.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-DE0V6cp-.js → index-5JqhujnR.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-Y2-q7QLm.js → index-6Tniqk1s.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-DoFtCVZ7.js → index-8Z-8BIlN.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-KNGgO4Wm.js → index-BCI5v0yB.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DY4j5zkF.js → index-BDJntYmJ.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-BZjjdQ62.js → index-BGzixOGZ.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BTpIOTfR.js → index-BMMOVoLD.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-BB9SqVSt.js → index-BTFpdBtt.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-AHr7ryWf.js → index-Ba_HyPnE.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-Pvf30m8Q.js → index-BbF1IHof.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-CRN5TRTQ.js → index-BgT9su_e.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-CUaEHfQ0.js → index-BzPB6kGZ.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-CdKt9fOd.js → index-C6ygzplr.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-Dec0Kf_Z.js → index-CC3ZDjzY.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-IPkwSAW_.js → index-CEmXRhAE.js} +1 -1
  112. package/src/assets/web-panel/assets/index-CJGOlduY.js +1 -0
  113. package/src/assets/web-panel/assets/{index-C3k8kevG.js → index-CMPqd5Cv.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-A5CDWP7y.js → index-COWd8uGx.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-CO8DAF7U.js → index-CPIYSp4H.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-CVzuawCX.js → index-CR0h6seT.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-Co7s9LsB.js → index-CUmDhC4j.js} +1 -1
  118. package/src/assets/web-panel/assets/index-CkBCN5yH.js +1 -0
  119. package/src/assets/web-panel/assets/{index-CLoTQr0W.js → index-CusgZPtc.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-B81mo1Et.js → index-DBAETXft.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-BcSUl9fA.js → index-DIJ2qFOC.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-Q5Tn735s.js → index-Dbq4NMET.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-GXE0D8Nx.js → index-DkMEF5VT.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-TWG-_D1M.js → index-DkfQR3hM.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-BAE3hwev.js → index-DnLucOn9.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CgkoH3_g.js → index-DugB_aKa.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-BRGx3w6T.js → index-DyLUarhZ.js} +3 -3
  128. package/src/assets/web-panel/assets/{index-BeM4hfht.js → index-T6_6ygJZ.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-DsscwxPE.js → index-Tu8eWqh-.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-Bmr_vxXD.js → index-W7XUgdVL.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-BoNZlzhQ.js → index-dHZinfko.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-DqkbHHg8.js → index-jyNgp5FI.js} +1 -1
  133. package/src/assets/web-panel/assets/{initDefaultProps-D-4Hzgej.js → initDefaultProps-Cv4p8e4w.js} +1 -1
  134. package/src/assets/web-panel/assets/{motion-D4Wl4xU7.js → motion-B8EwmMOw.js} +1 -1
  135. package/src/assets/web-panel/assets/{move-Cd5eQvL0.js → move-B8R9F8TK.js} +1 -1
  136. package/src/assets/web-panel/assets/{mtc-parser-B4ilslCW.js → mtc-parser-DoFYz5Bp.js} +1 -1
  137. package/src/assets/web-panel/assets/{omit-Ckarx-tf.js → omit-CHWYLBjI.js} +1 -1
  138. package/src/assets/web-panel/assets/{pickAttrs-QJ0bpCmc.js → pickAttrs-CXuPDO77.js} +1 -1
  139. package/src/assets/web-panel/assets/{placementArrow-CKHm-tq8.js → placementArrow-BaAtUUon.js} +1 -1
  140. package/src/assets/web-panel/assets/{responsiveObserve-CV6a_w_Y.js → responsiveObserve-DCc4zcDD.js} +1 -1
  141. package/src/assets/web-panel/assets/{slide-mHpeQFgk.js → slide-B_lx89oZ.js} +1 -1
  142. package/src/assets/web-panel/assets/{statusUtils-DIaQNQWA.js → statusUtils-DE8DPmR0.js} +1 -1
  143. package/src/assets/web-panel/assets/{styleChecker-PJpzavV8.js → styleChecker-1ktXOsL_.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFlexGapSupport-BH7zTw8S.js → useFlexGapSupport-xH89-wjh.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFs-BDNG3JDd.js → useFs-DscvfW5p.js} +1 -1
  146. package/src/assets/web-panel/assets/{usePersonalDataHub-CY2VWdUg.js → usePersonalDataHub-RdMKQta7.js} +1 -1
  147. package/src/assets/web-panel/assets/{vnode-D0kw9jhz.js → vnode-Z3wTni2T.js} +1 -1
  148. package/src/assets/web-panel/assets/{zoom-B5g7TN7r.js → zoom-B0iChCsm.js} +1 -1
  149. package/src/assets/web-panel/index.html +1 -1
  150. package/src/command-help-index.json +3 -3
  151. package/src/commands/agent.js +105 -62
  152. package/src/commands/background-session.js +100 -10
  153. package/src/commands/git.js +39 -0
  154. package/src/commands/mcp.js +5 -0
  155. package/src/commands/plugin.js +160 -29
  156. package/src/commands/remote-control.js +295 -110
  157. package/src/commands/session-group.js +131 -0
  158. package/src/commands/session-location.js +48 -0
  159. package/src/commands/session-message.js +171 -0
  160. package/src/commands/session.js +22 -0
  161. package/src/commands/sync-providers.js +4 -1
  162. package/src/commands/update.js +1 -0
  163. package/src/data/changelog.json +41 -2
  164. package/src/gateways/ws/ws-agent-handler.js +20 -12
  165. package/src/harness/jsonl-session-store.js +279 -37
  166. package/src/harness/mcp-client.js +832 -91
  167. package/src/harness/session-index.js +15 -4
  168. package/src/lib/agent-worktree.js +8 -1
  169. package/src/lib/auto-mode-safety-classifier.js +3 -17
  170. package/src/lib/background-agent-keeper-protocol.js +26 -6
  171. package/src/lib/background-agent-supervisor.js +17 -1
  172. package/src/lib/background-session-transport.js +153 -27
  173. package/src/lib/browser-evidence.js +1405 -0
  174. package/src/lib/chrome-connector.js +465 -79
  175. package/src/lib/claude-project-auto-memory.js +481 -0
  176. package/src/lib/claude-project-storage-layout.js +104 -0
  177. package/src/lib/cloud/cloud-client.js +40 -0
  178. package/src/lib/execution-location-local-supervisor.mjs +226 -0
  179. package/src/lib/execution-location-runner-lifecycle.js +991 -0
  180. package/src/lib/execution-location-target-preflight.js +333 -0
  181. package/src/lib/execution-location-target.js +783 -13
  182. package/src/lib/file-lines.js +6 -1
  183. package/src/lib/gateway-client-resilience.js +571 -0
  184. package/src/lib/gitlab-mr-worktree.js +176 -0
  185. package/src/lib/hooks-v2-producers.js +119 -15
  186. package/src/lib/hooks-v2-workspace-context.js +44 -1
  187. package/src/lib/host-resource-budget.js +295 -0
  188. package/src/lib/ide-context.js +15 -2
  189. package/src/lib/llm-config-defaults.js +43 -0
  190. package/src/lib/mcp-client.js +2 -0
  191. package/src/lib/mcp-headers-helper.js +47 -5
  192. package/src/lib/mcp-lifecycle-authority.js +887 -0
  193. package/src/lib/mcp-oauth.js +156 -26
  194. package/src/lib/mcp-tls.js +330 -0
  195. package/src/lib/output-styles.js +12 -0
  196. package/src/lib/paths.js +260 -32
  197. package/src/lib/permission-request.js +48 -0
  198. package/src/lib/plugin-runtime/bin.js +3 -1
  199. package/src/lib/plugin-runtime/hooks.js +3 -1
  200. package/src/lib/plugin-runtime/install.js +730 -71
  201. package/src/lib/plugin-runtime/lsp.js +4 -4
  202. package/src/lib/plugin-runtime/marketplace-archive-source.js +366 -0
  203. package/src/lib/plugin-runtime/marketplace-catalog.js +63 -6
  204. package/src/lib/plugin-runtime/marketplace-command-descriptor.js +343 -0
  205. package/src/lib/plugin-runtime/marketplace-command-source.js +580 -0
  206. package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +1 -0
  207. package/src/lib/plugin-runtime/marketplace-source-adapter.js +188 -0
  208. package/src/lib/plugin-runtime/marketplace-source-cache.js +11 -1
  209. package/src/lib/plugin-runtime/mcp.js +3 -1
  210. package/src/lib/plugin-runtime/monitors.js +3 -1
  211. package/src/lib/plugin-runtime/remote-source.js +583 -58
  212. package/src/lib/plugin-runtime/settings.js +3 -1
  213. package/src/lib/plugin-runtime/trust.js +274 -13
  214. package/src/lib/plugin-security.js +393 -41
  215. package/src/lib/plugin-source-identity.js +850 -0
  216. package/src/lib/process-execution-broker/credential-agent.js +210 -41
  217. package/src/lib/process-execution-broker/index.js +15 -1
  218. package/src/lib/process-execution-broker/linux-cgroup-v2.js +391 -0
  219. package/src/lib/process-execution-broker/platform-sandbox.js +50 -28
  220. package/src/lib/project-mcp-trust.js +165 -10
  221. package/src/lib/remote-approval-bridge.js +136 -46
  222. package/src/lib/remote-control.js +217 -31
  223. package/src/lib/resume-session.js +9 -6
  224. package/src/lib/session-core-singletons.js +26 -11
  225. package/src/lib/session-host-lease.js +52 -16
  226. package/src/lib/session-lifecycle-scope.js +153 -0
  227. package/src/lib/session-message-fabric.js +1252 -0
  228. package/src/lib/session-projection.js +286 -3
  229. package/src/lib/session-runtime-retention.js +155 -0
  230. package/src/lib/session-store-guard.js +3 -1
  231. package/src/lib/session-workbench-store.js +466 -0
  232. package/src/lib/settings-loader.cjs +29 -0
  233. package/src/lib/spellcheck.js +211 -0
  234. package/src/lib/sub-agent-context.js +9 -9
  235. package/src/lib/sync-cli-db.js +485 -129
  236. package/src/lib/sync-credentials.js +31 -20
  237. package/src/lib/web-fetch.js +112 -40
  238. package/src/lib/web-search.js +127 -61
  239. package/src/lib/workspace-trust.js +793 -0
  240. package/src/repl/agent-repl.js +175 -19
  241. package/src/repl/permission-prompt.js +29 -8
  242. package/src/repl/repl-keybindings.js +55 -0
  243. package/src/runtime/agent-core.js +362 -20
  244. package/src/runtime/bootstrap.js +37 -13
  245. package/src/runtime/coding-agent-contract-shared.cjs +11 -4
  246. package/src/runtime/headless-runner.js +281 -102
  247. package/src/runtime/headless-stream.js +199 -30
  248. package/src/runtime/mcp-config.js +298 -6
  249. package/src/runtime/policies/agent-policy.js +10 -0
  250. package/src/runtime/status-diagnostics-lite.js +9 -1
  251. package/src/assets/web-panel/assets/ChatBubbleRenderer-4gGkdGgA.js +0 -1
  252. package/src/assets/web-panel/assets/MarkdownRenderer-B4RLp2zs.js +0 -1
  253. package/src/assets/web-panel/assets/SpeechSettings-DPy1XMYh.js +0 -1
  254. package/src/assets/web-panel/assets/devWarning-CagEcIex.js +0 -1
  255. package/src/assets/web-panel/assets/index-pzT9PpOU.js +0 -1
  256. package/src/assets/web-panel/assets/index-z1kFadaX.js +0 -1
@@ -1,112 +1,315 @@
1
1
  /**
2
- * CLI sync vault — better-sqlite3 wrapper exposing dbManager.run/all/get
3
- * interface matching desktop's engine deps signature.
4
- *
5
- * Phase 3c follow-up Phase 2: cc sync run requires SQLite store for cursors,
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 os from "node:os";
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
- const CLI_VAULT_SCHEMA = `
37
- CREATE TABLE IF NOT EXISTS knowledge_items (
38
- id TEXT PRIMARY KEY,
39
- title TEXT NOT NULL,
40
- type TEXT NOT NULL DEFAULT 'note',
41
- content TEXT,
42
- tags TEXT,
43
- created_at INTEGER NOT NULL,
44
- updated_at INTEGER NOT NULL
45
- );
46
-
47
- CREATE TABLE IF NOT EXISTS sync_external_provider_cursor (
48
- provider_id TEXT NOT NULL,
49
- account_key TEXT NOT NULL DEFAULT '',
50
- last_sync_at INTEGER NOT NULL DEFAULT 0,
51
- last_item_id TEXT,
52
- remote_etag_map TEXT NOT NULL DEFAULT '{}',
53
- remote_filename_map TEXT NOT NULL DEFAULT '{}',
54
- last_run_status TEXT,
55
- last_run_error TEXT,
56
- last_run_duration_ms INTEGER,
57
- items_pushed INTEGER NOT NULL DEFAULT 0,
58
- items_skipped INTEGER NOT NULL DEFAULT 0,
59
- items_deleted INTEGER NOT NULL DEFAULT 0,
60
- created_at INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000),
61
- updated_at INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000),
62
- PRIMARY KEY (provider_id, account_key)
63
- );
64
-
65
- CREATE TABLE IF NOT EXISTS sync_external_tombstones (
66
- id INTEGER PRIMARY KEY AUTOINCREMENT,
67
- provider_id TEXT NOT NULL,
68
- account_key TEXT NOT NULL DEFAULT '',
69
- item_id TEXT NOT NULL,
70
- resource_type TEXT,
71
- deleted_at INTEGER NOT NULL,
72
- retry_count INTEGER NOT NULL DEFAULT 0,
73
- last_error TEXT,
74
- UNIQUE(provider_id, account_key, item_id)
75
- );
76
-
77
- CREATE TRIGGER IF NOT EXISTS trg_sync_ext_tombstone_on_delete
78
- AFTER DELETE ON knowledge_items
79
- FOR EACH ROW
80
- BEGIN
81
- INSERT OR IGNORE INTO sync_external_tombstones
82
- (provider_id, account_key, item_id, resource_type, deleted_at)
83
- SELECT c.provider_id, c.account_key, OLD.id, 'KNOWLEDGE_ITEM',
84
- (strftime('%s','now') * 1000)
85
- FROM sync_external_provider_cursor c;
86
- END;
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
- * Wraps better-sqlite3 Database with the {run, all, get} surface that
91
- * the desktop sync engine's deps.dbManager expects.
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
- * Open (or create) the CLI vault. Auto-initializes schema on first open.
121
- *
122
- * @returns {Promise<{dbManager: CliVaultDbManager, vaultPath: string}>}
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
- async function openCliVault() {
125
- const dir = _ccDir();
126
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
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
- // Lazy-import better-sqlite3 — heavy native dep, defer until run-time
129
- // (so the CLI doesn't even pay the require cost for non-sync commands).
130
- let Database;
131
- try {
132
- Database = (await import("better-sqlite3")).default;
133
- } catch (err) {
134
- const e = new Error(
135
- "CLI vault requires better-sqlite3 npm package. " +
136
- "Run `npm install -g chainlesschain` to fetch the prebuilt binary, " +
137
- "or `cd packages/cli && npm install` for the dev workspace. " +
138
- "Underlying error: " +
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
- const vp = _vaultPath();
146
- const db = new Database(vp);
147
- db.exec(CLI_VAULT_SCHEMA);
148
- return { dbManager: new CliVaultDbManager(db), vaultPath: vp };
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
- let _ccDirOverride = null;
152
- function _setCcDirForTest(dir) {
153
- _ccDirOverride = dir;
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
- function _resetCcDirForTest() {
156
- _ccDirOverride = null;
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
- // Re-wrap _ccDir/_vaultPath to honor override (test seam)
160
- const _originalCcDir = _ccDir;
161
- function _ccDirEffective() {
162
- return _ccDirOverride ?? _originalCcDir();
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
- function _vaultPathEffective() {
165
- return path.join(_ccDirEffective(), "cli-vault.db");
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 openCliVaultT() {
169
- const dir = _ccDirEffective();
170
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
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 = (await import("better-sqlite3")).default;
174
- } catch (err) {
175
- const e = new Error(
176
- "CLI vault requires better-sqlite3 npm package: " + (err?.message || err),
177
- );
178
- e.code = "BETTER_SQLITE3_MISSING";
179
- throw e;
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
- const vp = _vaultPathEffective();
182
- const db = new Database(vp);
183
- db.exec(CLI_VAULT_SCHEMA);
184
- return { dbManager: new CliVaultDbManager(db), vaultPath: vp };
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
- openCliVaultT as openCliVault,
542
+ openCliVault,
189
543
  CliVaultDbManager,
190
544
  CLI_VAULT_SCHEMA,
545
+ _deps,
191
546
  _setCcDirForTest,
192
547
  _resetCcDirForTest,
193
- _vaultPathEffective as _vaultPath,
548
+ _resetDepsForTest,
549
+ _vaultPath,
194
550
  };