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
@@ -22,8 +22,20 @@ import {
22
22
  mutateSecurityStore,
23
23
  readSecurityStore,
24
24
  } from "./durable-security-store.js";
25
+ import {
26
+ checkRecordedWorkspaceTrust,
27
+ evaluateWorkspaceTrustDecision,
28
+ projectWorkspaceTrustAudit,
29
+ recordWorkspaceTrustConsent,
30
+ resolveCanonicalWorkspaceRepoIdentity,
31
+ workspaceTrustPathSubject,
32
+ } from "./workspace-trust.js";
25
33
 
26
- export const _deps = { withFileLock };
34
+ export const _deps = {
35
+ withFileLock,
36
+ // Test-only seam. Production uses workspace-trust.js's one shared ledger.
37
+ workspaceTrustStorePath: () => null,
38
+ };
27
39
  const workspaceAuthorities = new WeakMap();
28
40
 
29
41
  function storePath(opts = {}) {
@@ -38,6 +50,62 @@ export function projectMcpFingerprint(content) {
38
50
  return createHash("sha256").update(String(content), "utf-8").digest("hex");
39
51
  }
40
52
 
53
+ const PROJECT_MCP_WORKSPACE_TRUST_SOURCE = "project-mcp";
54
+
55
+ function workspaceTrustStoreOptions(opts = {}) {
56
+ const store =
57
+ opts.workspaceTrustStorePath ||
58
+ process.env.CC_WORKSPACE_TRUST_STORE ||
59
+ _deps.workspaceTrustStorePath() ||
60
+ // Custom source-store callers (notably isolated tests) get an adjacent
61
+ // shared ledger. Normal CLI calls omit storePath and therefore use the
62
+ // single workspace-trust.js default shared by all entry points.
63
+ (opts.storePath
64
+ ? path.join(path.dirname(opts.storePath), "workspace-trust-v1.json")
65
+ : null);
66
+ return store ? { storePath: store } : {};
67
+ }
68
+
69
+ function projectMcpWorkspaceTrustContext(file, content, opts = {}) {
70
+ const identity = resolveCanonicalWorkspaceRepoIdentity(
71
+ opts.workspaceRoot || path.dirname(file),
72
+ );
73
+ const subject = workspaceTrustPathSubject(identity, file);
74
+ const fingerprint = projectMcpFingerprint(content);
75
+ return { identity, subject, fingerprint };
76
+ }
77
+
78
+ function projectMcpWorkspaceRecordKey(context) {
79
+ const subjectDigest = createHash("sha256")
80
+ .update(context.subject, "utf8")
81
+ .digest("hex");
82
+ return `workspace-v1:${context.identity.workspaceId}:${subjectDigest}`;
83
+ }
84
+
85
+ function projectMcpDecision(status, context) {
86
+ const decision = evaluateWorkspaceTrustDecision({
87
+ identity: context.identity,
88
+ evidence: [
89
+ {
90
+ source: PROJECT_MCP_WORKSPACE_TRUST_SOURCE,
91
+ consent: status === "trusted" ? "explicit" : "missing",
92
+ fingerprint: context.fingerprint,
93
+ decision:
94
+ status === "trusted"
95
+ ? "allow"
96
+ : status === "first-use"
97
+ ? "ask"
98
+ : "deny",
99
+ },
100
+ ],
101
+ });
102
+ return {
103
+ status,
104
+ fingerprint: context.fingerprint,
105
+ workspaceTrust: projectWorkspaceTrustAudit(decision),
106
+ };
107
+ }
108
+
41
109
  /**
42
110
  * Issue an in-process authority only after the caller has verified the exact
43
111
  * project file fingerprint. Plain config fields cannot forge this token.
@@ -50,7 +118,23 @@ export function issueProjectMcpWorkspaceAuthority({
50
118
  config = {},
51
119
  }) {
52
120
  const canonicalFile = fs.realpathSync.native(path.resolve(file));
53
- const canonicalRoot = fs.realpathSync.native(path.resolve(workspaceRoot));
121
+ const workspaceIdentity =
122
+ resolveCanonicalWorkspaceRepoIdentity(workspaceRoot);
123
+ const canonicalRoot = workspaceIdentity.canonicalWorkspaceRoot;
124
+ const trustDecision = evaluateWorkspaceTrustDecision({
125
+ identity: workspaceIdentity,
126
+ evidence: [
127
+ {
128
+ source: PROJECT_MCP_WORKSPACE_TRUST_SOURCE,
129
+ consent: "host-bound",
130
+ fingerprint: projectMcpFingerprint(content),
131
+ decision: "allow",
132
+ },
133
+ ],
134
+ });
135
+ if (trustDecision.decision !== "allow") {
136
+ throw new Error("project MCP workspace identity is unavailable");
137
+ }
54
138
  const token = Object.freeze({});
55
139
  workspaceAuthorities.set(
56
140
  token,
@@ -58,6 +142,9 @@ export function issueProjectMcpWorkspaceAuthority({
58
142
  file: canonicalFile,
59
143
  fingerprint: projectMcpFingerprint(content),
60
144
  workspaceRoot: canonicalRoot,
145
+ workspaceId: workspaceIdentity.workspaceId,
146
+ repositoryId: workspaceIdentity.repositoryId,
147
+ workspaceTrust: projectWorkspaceTrustAudit(trustDecision),
61
148
  serverName: String(serverName || ""),
62
149
  url: typeof config.url === "string" ? config.url : "",
63
150
  transport: typeof config.transport === "string" ? config.transport : "",
@@ -100,6 +187,19 @@ export function resolveProjectMcpWorkspaceAuthority(token, expected = {}) {
100
187
  ) {
101
188
  return null;
102
189
  }
190
+ try {
191
+ const currentIdentity = resolveCanonicalWorkspaceRepoIdentity(
192
+ record.workspaceRoot,
193
+ );
194
+ if (
195
+ currentIdentity.workspaceId !== record.workspaceId ||
196
+ currentIdentity.repositoryId !== record.repositoryId
197
+ ) {
198
+ return null;
199
+ }
200
+ } catch {
201
+ return null;
202
+ }
103
203
  return record.workspaceRoot;
104
204
  }
105
205
 
@@ -112,29 +212,84 @@ function readStore(opts) {
112
212
  * @returns {{status:"first-use"|"trusted"|"changed", fingerprint:string}}
113
213
  */
114
214
  export function checkProjectMcpTrust(file, content, opts = {}) {
115
- const fingerprint = projectMcpFingerprint(content);
116
- const record = readStore(opts)[path.resolve(file)];
117
- if (!record || !record.fingerprint) {
118
- return { status: "first-use", fingerprint };
215
+ const context = projectMcpWorkspaceTrustContext(file, content, opts);
216
+ const store = readStore(opts);
217
+ const record = store[projectMcpWorkspaceRecordKey(context)];
218
+ const legacyRecord = store[path.resolve(file)];
219
+ if (!record || typeof record !== "object" || Array.isArray(record)) {
220
+ // A pre-v1 path-keyed grant cannot be shown to bind the current canonical
221
+ // workspace identity. Treat it as changed rather than silently widening
222
+ // it; the existing explicit re-trust path records the v1 intersection.
223
+ const shared = checkRecordedWorkspaceTrust({
224
+ identity: context.identity,
225
+ source: PROJECT_MCP_WORKSPACE_TRUST_SOURCE,
226
+ subject: context.subject,
227
+ evidenceFingerprint: context.fingerprint,
228
+ ...workspaceTrustStoreOptions(opts),
229
+ });
230
+ return {
231
+ status:
232
+ legacyRecord?.fingerprint || shared.status === "changed"
233
+ ? "changed"
234
+ : "first-use",
235
+ fingerprint: context.fingerprint,
236
+ workspaceTrust: shared.audit,
237
+ };
238
+ }
239
+ const binding = record.workspaceTrust;
240
+ if (
241
+ record.fingerprint !== context.fingerprint ||
242
+ !binding ||
243
+ binding.workspaceId !== context.identity.workspaceId ||
244
+ binding.repositoryId !== context.identity.repositoryId ||
245
+ binding.subject !== context.subject
246
+ ) {
247
+ return projectMcpDecision("changed", context);
119
248
  }
249
+ const shared = checkRecordedWorkspaceTrust({
250
+ identity: context.identity,
251
+ source: PROJECT_MCP_WORKSPACE_TRUST_SOURCE,
252
+ subject: context.subject,
253
+ evidenceFingerprint: context.fingerprint,
254
+ ...workspaceTrustStoreOptions(opts),
255
+ });
120
256
  return {
121
- status: record.fingerprint === fingerprint ? "trusted" : "changed",
122
- fingerprint,
257
+ status: shared.status === "trusted" ? "trusted" : "changed",
258
+ fingerprint: context.fingerprint,
259
+ workspaceTrust: shared.audit,
123
260
  };
124
261
  }
125
262
 
126
263
  /** Record (or re-record) the trusted fingerprint for a file. */
127
264
  export function recordProjectMcpTrust(file, content, opts = {}) {
128
265
  const target = storePath(opts);
266
+ const context = projectMcpWorkspaceTrustContext(file, content, opts);
267
+ // Persist the shared record first. If the legacy/source-specific store
268
+ // fails afterwards, the checker still requires both records and therefore
269
+ // cannot accidentally authorize from the shared ledger alone.
270
+ recordWorkspaceTrustConsent({
271
+ identity: context.identity,
272
+ source: PROJECT_MCP_WORKSPACE_TRUST_SOURCE,
273
+ subject: context.subject,
274
+ evidenceFingerprint: context.fingerprint,
275
+ consent: "explicit",
276
+ ...workspaceTrustStoreOptions(opts),
277
+ });
129
278
  return mutateSecurityStore(
130
279
  target,
131
280
  "project MCP trust",
132
281
  (store) => {
133
- store[path.resolve(file)] = {
134
- fingerprint: projectMcpFingerprint(content),
282
+ store[projectMcpWorkspaceRecordKey(context)] = {
283
+ fingerprint: context.fingerprint,
135
284
  trustedAt: new Date(
136
285
  typeof opts.now === "number" ? opts.now : Date.now(),
137
286
  ).toISOString(),
287
+ workspaceTrust: {
288
+ schemaVersion: context.identity.schemaVersion,
289
+ workspaceId: context.identity.workspaceId,
290
+ repositoryId: context.identity.repositoryId,
291
+ subject: context.subject,
292
+ },
138
293
  };
139
294
  return true;
140
295
  },
@@ -43,11 +43,15 @@ import {
43
43
  REMOTE_MEMBERSHIP_HOST_UNAVAILABLE_CODE,
44
44
  } from "./remote-membership-host-store.js";
45
45
  import {
46
+ assertDirectWsUrlAllowed,
46
47
  buildDirectPairingUri,
48
+ isLoopbackBindHost,
47
49
  pickLanAddress,
48
50
  renderQrCode,
49
51
  resolveRemoteControlOptions,
52
+ resolveRemoteControlWsUrl,
50
53
  } from "./remote-control.js";
54
+ import { logger } from "./logger.js";
51
55
 
52
56
  const DEFAULT_DECISION_TIMEOUT_MS = 5 * 60 * 1000;
53
57
  const REMOTE_LEASE_AUTHORIZATION_KIND =
@@ -345,7 +349,8 @@ export class RemoteApprovalBridge {
345
349
 
346
350
  /**
347
351
  * Pairing descriptor for devices. Relay-configured servers return a ready
348
- * E2EE URI; otherwise build the direct-LAN URI from the caller's endpoint.
352
+ * E2EE URI; otherwise build a direct URI from the explicitly selected
353
+ * loopback/LAN endpoint.
349
354
  */
350
355
  pairingInfo({ lanWsUrl = null } = {}) {
351
356
  if (!this.pairing) return null;
@@ -363,6 +368,7 @@ export class RemoteApprovalBridge {
363
368
  });
364
369
  return {
365
370
  uri,
371
+ mode: this.pairing.uri ? "relay" : "direct",
366
372
  remoteSessionId: this.remoteSessionId,
367
373
  scopes: this.pairing.scopes,
368
374
  expiresAt: this.pairing.expiresAt,
@@ -1297,21 +1303,60 @@ export class RemoteApprovalBridge {
1297
1303
  * self-hosts a lightweight WS server on an OS-assigned port (no sessionManager
1298
1304
  * needed — the session stays client-hosted), starts a bridge for this run's
1299
1305
  * session, prints the pairing URI (+ optional QR) to stderr, and returns the
1300
- * gate confirmer + teardown. Relay settings (env/config) flow through, so a
1301
- * configured relay yields an E2EE pairing URI reaching devices off-LAN.
1306
+ * gate confirmer + teardown. Relay settings flow through the startup
1307
+ * environment; LAN exposure remains a separate explicit caller authority.
1302
1308
  */
1303
1309
  export async function startHeadlessRemoteApproval({
1304
1310
  agentSessionId,
1311
+ allowLan = false,
1305
1312
  env = process.env,
1306
- config = {},
1313
+ config = undefined,
1307
1314
  writeErr = () => {},
1308
1315
  isText = false,
1309
1316
  decisionTimeoutMs = undefined,
1310
1317
  deps = {},
1311
1318
  } = {}) {
1319
+ let effectiveConfig = config;
1320
+ if (effectiveConfig === undefined) {
1321
+ try {
1322
+ const configModule =
1323
+ deps.configModule || (await import("./config-manager.js"));
1324
+ effectiveConfig = configModule.loadConfig();
1325
+ } catch {
1326
+ effectiveConfig = {};
1327
+ }
1328
+ }
1329
+ const resolved = resolveRemoteControlOptions({
1330
+ flags: { allowApprove: true, allowLan: allowLan === true },
1331
+ env,
1332
+ config: effectiveConfig || {},
1333
+ });
1334
+ if (!resolved.relayUrl && !resolved.lanAccessible) {
1335
+ throw new Error(
1336
+ "remote approval is loopback-only by default; configure a relay, or enable " +
1337
+ "allowLan with a non-loopback host (omit host to use 0.0.0.0) on a trusted network",
1338
+ );
1339
+ }
1340
+ const lanAddress = resolved.lanAccessible
1341
+ ? deps.lanAddress ||
1342
+ (deps.pickLanAddress ? deps.pickLanAddress() : pickLanAddress())
1343
+ : null;
1344
+ const preflightLanWsUrl = resolveRemoteControlWsUrl(
1345
+ { ...resolved, port: 1 },
1346
+ { lanAddress },
1347
+ );
1348
+ if (
1349
+ !resolved.relayUrl &&
1350
+ resolved.lanAccessible &&
1351
+ isLoopbackBindHost(new URL(preflightLanWsUrl).hostname)
1352
+ ) {
1353
+ throw new Error(
1354
+ "LAN binding is enabled but no private LAN address can be advertised; " +
1355
+ "configure a private host or a relay",
1356
+ );
1357
+ }
1312
1358
  const { ChainlessChainWSServer } =
1313
1359
  deps.serverModule || (await import("../gateways/ws/ws-server.js"));
1314
- const resolved = resolveRemoteControlOptions({ flags: {}, env, config });
1315
1360
  const server = new ChainlessChainWSServer({
1316
1361
  port: 0,
1317
1362
  host: resolved.host,
@@ -1319,50 +1364,95 @@ export async function startHeadlessRemoteApproval({
1319
1364
  remoteSessionRelayUrl: resolved.relayUrl,
1320
1365
  remoteSessionPeerId: resolved.peerId,
1321
1366
  });
1322
- await server.start();
1323
- const bridge = new RemoteApprovalBridge({
1324
- wsUrl: `ws://127.0.0.1:${server.port}`,
1325
- token: resolved.token,
1326
- agentSessionId,
1327
- scopes: ["observe", "approve"],
1328
- decisionTimeoutMs,
1329
- });
1367
+ let bridge;
1330
1368
  try {
1331
- await bridge.start();
1369
+ await server.start();
1370
+ const createBridge =
1371
+ deps.createBridge || ((options) => new RemoteApprovalBridge(options));
1372
+ bridge = createBridge({
1373
+ wsUrl: resolveRemoteControlWsUrl(
1374
+ { ...resolved, port: server.port, allowLan: resolved.lanAccessible },
1375
+ { lanAddress: null },
1376
+ ),
1377
+ token: resolved.token,
1378
+ agentSessionId,
1379
+ scopes: ["observe", "approve"],
1380
+ decisionTimeoutMs,
1381
+ });
1382
+ try {
1383
+ await bridge.start();
1384
+ } catch (err) {
1385
+ await server.stop().catch(() => undefined);
1386
+ throw err;
1387
+ }
1388
+ const lanWsUrl = resolveRemoteControlWsUrl(
1389
+ { ...resolved, port: server.port },
1390
+ { lanAddress },
1391
+ );
1392
+ const pairing = bridge.pairingInfo({ lanWsUrl });
1393
+ if (resolved.relayUrl && pairing?.mode !== "relay") {
1394
+ throw new Error(
1395
+ "the configured relay did not provide a pairing URI; refusing to fall back to direct pairing",
1396
+ );
1397
+ }
1398
+ if (
1399
+ !resolved.relayUrl &&
1400
+ pairing?.mode !== "relay" &&
1401
+ !resolved.lanAccessible
1402
+ ) {
1403
+ throw new Error(
1404
+ "direct remote approval requires explicit allowLan on a trusted network",
1405
+ );
1406
+ }
1407
+ if (pairing?.mode === "direct") {
1408
+ if (isLoopbackBindHost(new URL(lanWsUrl).hostname)) {
1409
+ throw new Error(
1410
+ "LAN binding is enabled but no private LAN address can be advertised",
1411
+ );
1412
+ }
1413
+ assertDirectWsUrlAllowed(lanWsUrl);
1414
+ const warn = deps.warn || ((message) => logger.warn(message));
1415
+ warn(
1416
+ `LAN remote approval enabled on ${resolved.host}:${server.port}. ` +
1417
+ "Direct pairing uses plaintext ws:// with bearer credentials; use only on a trusted network.",
1418
+ );
1419
+ }
1420
+ if (!pairing?.uri) {
1421
+ throw new Error("remote approval did not produce a pairing URI");
1422
+ }
1423
+ if (isText) {
1424
+ writeErr(
1425
+ " remote-control: approvals can be answered from a paired device\n",
1426
+ );
1427
+ writeErr(` pairing: ${pairing.uri}\n`);
1428
+ const qr = await renderQrCode(pairing.uri, deps);
1429
+ if (qr) writeErr(qr + "\n");
1430
+ }
1431
+ return {
1432
+ pairing,
1433
+ server,
1434
+ bridge,
1435
+ confirmer: bridge.makeConfirmer({
1436
+ onAsk: (ask) => {
1437
+ if (isText) {
1438
+ writeErr(
1439
+ ` permission(${ask.tool || "?"}): waiting for remote approval…\n`,
1440
+ );
1441
+ }
1442
+ },
1443
+ }),
1444
+ consumeAuthorization: (authorization, context) =>
1445
+ bridge.consumeAuthorization(authorization, context),
1446
+ close: async () => {
1447
+ await bridge.close().catch(() => undefined);
1448
+ await server.stop().catch(() => undefined);
1449
+ },
1450
+ };
1332
1451
  } catch (err) {
1452
+ if (bridge) {
1453
+ await bridge.close().catch(() => undefined);
1454
+ }
1333
1455
  await server.stop().catch(() => undefined);
1334
1456
  throw err;
1335
1457
  }
1336
- const lanAddress = deps.lanAddress || pickLanAddress() || "127.0.0.1";
1337
- const pairing = bridge.pairingInfo({
1338
- lanWsUrl: `ws://${lanAddress}:${server.port}`,
1339
- });
1340
- if (isText) {
1341
- writeErr(
1342
- " remote-control: approvals can be answered from a paired device\n",
1343
- );
1344
- writeErr(` pairing: ${pairing.uri}\n`);
1345
- const qr = await renderQrCode(pairing.uri, deps);
1346
- if (qr) writeErr(qr + "\n");
1347
- }
1348
- return {
1349
- pairing,
1350
- server,
1351
- bridge,
1352
- confirmer: bridge.makeConfirmer({
1353
- onAsk: (ask) => {
1354
- if (isText) {
1355
- writeErr(
1356
- ` permission(${ask.tool || "?"}): waiting for remote approval…\n`,
1357
- );
1358
- }
1359
- },
1360
- }),
1361
- consumeAuthorization: (authorization, context) =>
1362
- bridge.consumeAuthorization(authorization, context),
1363
- close: async () => {
1364
- await bridge.close().catch(() => undefined);
1365
- await server.stop().catch(() => undefined);
1366
- },
1367
- };
1368
1458
  }