chainlesschain 0.163.7 → 0.164.0

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 (252) hide show
  1. package/package.json +5 -1
  2. package/scripts/macos-mcp-launcher-build.mjs +317 -0
  3. package/scripts/macos-mcp-launcher-postinstall.sh +54 -0
  4. package/scripts/macos-mcp-launcher-preinstall.sh +61 -0
  5. package/src/assets/web-panel/assets/{AIOps-axqQfwv8.js → AIOps-D2MEn7fI.js} +1 -1
  6. package/src/assets/web-panel/assets/{ActionButton-DV-Ro0By.js → ActionButton-lCW_4Gf0.js} +1 -1
  7. package/src/assets/web-panel/assets/{Analytics-Bt72WEVu.js → Analytics-Bs7i-nsS.js} +3 -3
  8. package/src/assets/web-panel/assets/{AppLayout-BtepG55E.js → AppLayout-CK7B6S_j.js} +5 -5
  9. package/src/assets/web-panel/assets/{Artifacts-B7KaJ7S_.js → Artifacts-C8ILjpyo.js} +1 -1
  10. package/src/assets/web-panel/assets/{Audit-FNFaUg7A.js → Audit-Bb9cNaWc.js} +1 -1
  11. package/src/assets/web-panel/assets/{BackgroundAgents-DFb6J2wQ.js → BackgroundAgents-sC9ooXIf.js} +1 -1
  12. package/src/assets/web-panel/assets/{Backup-CC7YBhyj.js → Backup-D-DrsplT.js} +1 -1
  13. package/src/assets/web-panel/assets/{BaseInput-RkgTNVtj.js → BaseInput-uCNZpwSK.js} +1 -1
  14. package/src/assets/web-panel/assets/{Chat-hHEmGZy-.js → Chat-CsDK1uE9.js} +6 -6
  15. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CAP9YhHv.js → ChatBubbleRenderer-OqSDt50w.js} +1 -1
  16. package/src/assets/web-panel/assets/{Checkbox-z5wXOQP1.js → Checkbox-JhTXM1-K.js} +1 -1
  17. package/src/assets/web-panel/assets/{Codegen-DVaDJnxy.js → Codegen-BbzZLnyD.js} +1 -1
  18. package/src/assets/web-panel/assets/{Col-CJmaRDR5.js → Col-D4VW4m4j.js} +1 -1
  19. package/src/assets/web-panel/assets/{Community-DF29_2bI.js → Community-BXrYawxV.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compact-DtkQkBzn.js → Compact-DCihGy1u.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compliance-xoHDxp7I.js → Compliance-DlyZ-lk8.js} +1 -1
  22. package/src/assets/web-panel/assets/{Cowork-BUm-R7ht.js → Cowork-DvGZrhbO.js} +2 -2
  23. package/src/assets/web-panel/assets/{Cron-Cgl14ZkB.js → Cron-DUncZi8h.js} +2 -2
  24. package/src/assets/web-panel/assets/{Crosschain-BNcbmoqh.js → Crosschain-C_hLuUcm.js} +1 -1
  25. package/src/assets/web-panel/assets/{DID-Bwja0Zo9.js → DID-b6YSUqxr.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dashboard-Bk5XjEdJ.js → Dashboard-uvM15Cfb.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dropdown-Ci36Oitq.js → Dropdown-D1-Nd4qY.js} +1 -1
  28. package/src/assets/web-panel/assets/{EmailListRenderer--U04ZN4q.js → EmailListRenderer-8ApvL6Zc.js} +1 -1
  29. package/src/assets/web-panel/assets/{FamilyGuardDashboard-B2gNPR2s.js → FamilyGuardDashboard-LYJt8811.js} +1 -1
  30. package/src/assets/web-panel/assets/{Federation-C4KghYn7.js → Federation-BbI3HGpv.js} +1 -1
  31. package/src/assets/web-panel/assets/{FormItemContext-QL7x_Q_0.js → FormItemContext-DSoEKuFu.js} +1 -1
  32. package/src/assets/web-panel/assets/{GenericCardRenderer-F3Ryltwm.js → GenericCardRenderer-B0S9OWd5.js} +1 -1
  33. package/src/assets/web-panel/assets/{Git-2HassK5k.js → Git-DIs9Zhf3.js} +2 -2
  34. package/src/assets/web-panel/assets/{Governance-DoBIp7oe.js → Governance-jzZXrxcl.js} +1 -1
  35. package/src/assets/web-panel/assets/{Inference--W01QhZ-.js → Inference-JUPjf2ZI.js} +1 -1
  36. package/src/assets/web-panel/assets/{KnowledgeGraph-DmvwqGpT.js → KnowledgeGraph-DxnfJvlP.js} +1 -1
  37. package/src/assets/web-panel/assets/{Logs-BBJ4yAel.js → Logs-iXiz8BEE.js} +2 -2
  38. package/src/assets/web-panel/assets/{MarkdownRenderer-BLCZMzhJ.js → MarkdownRenderer-GmB6DOr6.js} +1 -1
  39. package/src/assets/web-panel/assets/{Marketplace-D5lNngSI.js → Marketplace-Y3Xch312.js} +1 -1
  40. package/src/assets/web-panel/assets/{McpTools-CkEVOMKH.js → McpTools-D7kGGbO7.js} +4 -4
  41. package/src/assets/web-panel/assets/{Memory-B1Ow1xVE.js → Memory-Do_hVxzh.js} +2 -2
  42. package/src/assets/web-panel/assets/{MobileBridge-SgYbUfb6.js → MobileBridge-CtrR0Tas.js} +1 -1
  43. package/src/assets/web-panel/assets/MobileProjects-BL0Czcoj.js +1 -0
  44. package/src/assets/web-panel/assets/{Mtc-DcTXSSma.js → Mtc-qo5QCTGd.js} +2 -2
  45. package/src/assets/web-panel/assets/{MtcAudit-Dt3WG4oj.js → MtcAudit-cq5mnjYj.js} +2 -2
  46. package/src/assets/web-panel/assets/{Multisig-B9B38UZx.js → Multisig-Bq0MAQHw.js} +3 -3
  47. package/src/assets/web-panel/assets/{NLProgramming-B0S4GGvG.js → NLProgramming-DdWE6Vi2.js} +1 -1
  48. package/src/assets/web-panel/assets/{Notes-DZ5U58Ng.js → Notes-BxMBFcIp.js} +3 -3
  49. package/src/assets/web-panel/assets/{NotificationSettings-PjL5ZW34.js → NotificationSettings-RTrAcbUe.js} +1 -1
  50. package/src/assets/web-panel/assets/{OrderTableRenderer-DrAX2ESt.js → OrderTableRenderer-DJbpGqzT.js} +1 -1
  51. package/src/assets/web-panel/assets/{Organization-Cv1GYs-c.js → Organization-SQzIPdqC.js} +4 -4
  52. package/src/assets/web-panel/assets/{Overflow-Bbkp_PL3.js → Overflow-02yECh22.js} +1 -1
  53. package/src/assets/web-panel/assets/{P2P-BD8QUgoZ.js → P2P-BNg4pNCM.js} +2 -2
  54. package/src/assets/web-panel/assets/{PdhVaultBrowser-BO-2PeaB.js → PdhVaultBrowser-BxPJZsD3.js} +3 -3
  55. package/src/assets/web-panel/assets/{Permissions-D_OPVa02.js → Permissions-CLnDnPAz.js} +4 -4
  56. package/src/assets/web-panel/assets/{PersonalDataHub-mh-pEmaB.js → PersonalDataHub-C5m0AjGf.js} +4 -4
  57. package/src/assets/web-panel/assets/{Pipeline-6JC2EDdb.js → Pipeline-VwOf5Dhv.js} +1 -1
  58. package/src/assets/web-panel/assets/{Privacy-CUshzUAG.js → Privacy-CC0W2hZd.js} +1 -1
  59. package/src/assets/web-panel/assets/{ProjectInit-Cs2Aalri.js → ProjectInit-Dz893Bob.js} +2 -2
  60. package/src/assets/web-panel/assets/{ProjectSettings-1ak49tcj.js → ProjectSettings-CxQkvl0k.js} +2 -2
  61. package/src/assets/web-panel/assets/Projects-DDAjkUkT.js +1 -0
  62. package/src/assets/web-panel/assets/{Providers-CXXxvafH.js → Providers-DeB9IkxK.js} +1 -1
  63. package/src/assets/web-panel/assets/{QrScannerModal-PTcDsF58.js → QrScannerModal-OCeoaswn.js} +1 -1
  64. package/src/assets/web-panel/assets/{QuickAsk-CDwucrJw.js → QuickAsk-DenotaAj.js} +1 -1
  65. package/src/assets/web-panel/assets/{Recommend-CJlLVRXR.js → Recommend-Cies_jjI.js} +1 -1
  66. package/src/assets/web-panel/assets/{RemoteSession-DlN-ETsO.js → RemoteSession-Dxzl5n2T.js} +3 -3
  67. package/src/assets/web-panel/assets/{Reputation-DI23LR6m.js → Reputation-CW0mvxgZ.js} +1 -1
  68. package/src/assets/web-panel/assets/{Row-Cl7UQMrM.js → Row-SEd32qZU.js} +1 -1
  69. package/src/assets/web-panel/assets/{RssFeed-CexHNfh8.js → RssFeed-BSwnJ3Lm.js} +3 -3
  70. package/src/assets/web-panel/assets/{Search-BneBWvRN.js → Search-xe2m8bkC.js} +1 -1
  71. package/src/assets/web-panel/assets/{Security-DX7Phgrp.js → Security-Mq2F9Nro.js} +4 -4
  72. package/src/assets/web-panel/assets/{Services-BWXO8Mte.js → Services-BKGw2V3P.js} +2 -2
  73. package/src/assets/web-panel/assets/{Skeleton-DCyOjKPJ.js → Skeleton-DW95-Rxf.js} +1 -1
  74. package/src/assets/web-panel/assets/{Skills-CXqERsTB.js → Skills-CHgChCv_.js} +1 -1
  75. package/src/assets/web-panel/assets/{Sla-bhbrbz8E.js → Sla-tKh6k3R7.js} +1 -1
  76. package/src/assets/web-panel/assets/{SpeechSettings-3IPU0HBZ.js → SpeechSettings-D6UL3dA5.js} +1 -1
  77. package/src/assets/web-panel/assets/{SyncSettings-DBNTQLbM.js → SyncSettings-D0Fw8fVL.js} +2 -2
  78. package/src/assets/web-panel/assets/{Tasks-quP0bkN-.js → Tasks-20x1GB3D.js} +1 -1
  79. package/src/assets/web-panel/assets/{Templates-BouWmgho.js → Templates-DJ-lts-a.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tenant-qv0D9s7z.js → Tenant-BFdGpbs7.js} +1 -1
  81. package/src/assets/web-panel/assets/{Terminal-BxvbE8BB.js → Terminal-Xpx61vHL.js} +2 -2
  82. package/src/assets/web-panel/assets/{TimelineRenderer-D-IeLnJ2.js → TimelineRenderer-C6UIvyZQ.js} +1 -1
  83. package/src/assets/web-panel/assets/{Tokens-CFMKKyVG.js → Tokens-Dellq08f.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trigger-L8as3UuJ.js → Trigger-VKw8d0J-.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trust-MxmA4VZG.js → Trust-DNftdKT5.js} +1 -1
  86. package/src/assets/web-panel/assets/{UkeySign-C0VvJYRi.js → UkeySign-DX9VAKJI.js} +1 -1
  87. package/src/assets/web-panel/assets/{VideoEditing-Bf5QZj8N.js → VideoEditing-B2h3jO8q.js} +1 -1
  88. package/src/assets/web-panel/assets/{Wallet-BIJ9riRz.js → Wallet-CjGkof7f.js} +4 -4
  89. package/src/assets/web-panel/assets/{WebAuthn-B8p9Mhkw.js → WebAuthn-2Zfcu55P.js} +4 -4
  90. package/src/assets/web-panel/assets/{WorkflowEditor-BVsuaPen.js → WorkflowEditor-B9eZ8UxZ.js} +1 -1
  91. package/src/assets/web-panel/assets/{chat-BfkjoKpV.js → chat-CQNfD-YO.js} +1 -1
  92. package/src/assets/web-panel/assets/{colors-DeAlsWK8.js → colors-D4usyFT2.js} +1 -1
  93. package/src/assets/web-panel/assets/{compact-item-Cs97bz5j.js → compact-item-s4TpjvjX.js} +1 -1
  94. package/src/assets/web-panel/assets/{createContext-BqbG60LH.js → createContext-BRCSvYxj.js} +1 -1
  95. package/src/assets/web-panel/assets/devWarning-DKJjSWRn.js +1 -0
  96. package/src/assets/web-panel/assets/{hasIn-i_RY0b1X.js → hasIn-AdkUbkV-.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-BOVkf1K3.js → index--00U6vXZ.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-B-3tEpTc.js → index-B2V-eKfK.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-D2B4VPyP.js → index-B4JJCfQ2.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BkBi5TmC.js → index-BIoG5yYf.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-79V_zv1s.js → index-BMcimU-2.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-U4f5izHz.js → index-BPhkFZ1I.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DiSkx4UB.js → index-BQ3DXBtD.js} +3 -3
  104. package/src/assets/web-panel/assets/{index-dIHr4B_u.js → index-Bad4VNvz.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-CIG8fQ2_.js → index-BgiXR_-_.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DqBgBpgp.js → index-BtobShro.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-ZxO_-E8a.js → index-Bw2MEnUk.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DUUrv141.js → index-C1mJtE6q.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Bm7lLR4c.js → index-C484EJiS.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-COdGA-8n.js → index-C5KAQFPQ.js} +1 -1
  111. package/src/assets/web-panel/assets/index-C61cnl3K.js +1 -0
  112. package/src/assets/web-panel/assets/{index-CED2PL_y.js → index-C7Y8Aluc.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-YXgLng0K.js → index-CCsM_Ybx.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-0-agYlWL.js → index-CJCFe2Qf.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-B5UkyA3c.js → index-CJVEOa4i.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-B1CbOH1i.js → index-CJdQrZth.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-s1opAL-M.js → index-CKC1t3Ic.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-yObj1O4n.js → index-CQhAVU5t.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-CgsqdnRV.js → index-CYdoQsa1.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-Dk7-v4hP.js → index-Cduu2Hhr.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-B-JVTrpr.js → index-CkwiSLhU.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-CeWoNHau.js → index-Cvyt-zhm.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-CE2VtTlp.js → index-D2GjI2oe.js} +1 -1
  124. package/src/assets/web-panel/assets/index-D4XFHxBr.js +1 -0
  125. package/src/assets/web-panel/assets/{index-DmbfhJUP.js → index-DARsAyUp.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-BESLFt4q.js → index-DVKfQ0Ux.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-PT_5sBMA.js → index-DZT36ZYq.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-gyFpvL7l.js → index-D_XBHopw.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-BYUVuwKt.js → index-DdCB70SS.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-BcUXAB2s.js → index-DzRjHxEv.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-Dk2qouAz.js → index-MMN9V6JF.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-D9evtvg2.js → index-RfMr79MW.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-BuLQobzW.js → index-_IRVsV9X.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-Cf3WCLmy.js → index-nXyk8GZ9.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-CG3PRyAL.js → index-s_buFMEG.js} +1 -1
  136. package/src/assets/web-panel/assets/{initDefaultProps-C9h9yKL3.js → initDefaultProps-Blmpk7HL.js} +1 -1
  137. package/src/assets/web-panel/assets/{motion-BvmLsPdu.js → motion-DPBJMv1n.js} +1 -1
  138. package/src/assets/web-panel/assets/{move-CoL4ekU1.js → move-ButdzCM7.js} +1 -1
  139. package/src/assets/web-panel/assets/{mtc-parser-C4pMy6xV.js → mtc-parser-cyRC_QCe.js} +1 -1
  140. package/src/assets/web-panel/assets/{omit-DPuJfNxx.js → omit-1epSV7hz.js} +1 -1
  141. package/src/assets/web-panel/assets/{pickAttrs-D0KEeaK2.js → pickAttrs-DuPY8xJs.js} +1 -1
  142. package/src/assets/web-panel/assets/{placementArrow-BpkyINxt.js → placementArrow-6XZqarhe.js} +1 -1
  143. package/src/assets/web-panel/assets/{responsiveObserve-DQI_wOq8.js → responsiveObserve-B40pXBWM.js} +1 -1
  144. package/src/assets/web-panel/assets/{slide-DYfdDiRg.js → slide-jbZ9Wu4n.js} +1 -1
  145. package/src/assets/web-panel/assets/{statusUtils-B5dtvb0D.js → statusUtils-BKQQcVy4.js} +1 -1
  146. package/src/assets/web-panel/assets/{styleChecker-CF310mSj.js → styleChecker-NiKfWjUT.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFlexGapSupport-D1Qp4BLp.js → useFlexGapSupport-bQUCvPeb.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFs-C7_iyvJK.js → useFs-CUGji7ph.js} +1 -1
  149. package/src/assets/web-panel/assets/{usePersonalDataHub-DZUt_fIm.js → usePersonalDataHub-4veyN2N2.js} +1 -1
  150. package/src/assets/web-panel/assets/{vnode-D3dsi0lZ.js → vnode-1-nLug-Z.js} +1 -1
  151. package/src/assets/web-panel/assets/{zoom-WdbOlvdQ.js → zoom-dhCeRDMo.js} +1 -1
  152. package/src/assets/web-panel/index.html +1 -1
  153. package/src/command-help-index.json +6 -6
  154. package/src/commands/automation.js +103 -1
  155. package/src/commands/cowork.js +174 -19
  156. package/src/commands/permissions.js +240 -16
  157. package/src/commands/plugin.js +1293 -56
  158. package/src/commands/session-location.js +276 -0
  159. package/src/commands/session.js +2 -0
  160. package/src/commands/team-merge-review.js +937 -0
  161. package/src/commands/team.js +2 -0
  162. package/src/data/changelog.json +27 -1
  163. package/src/gateways/ws/action-protocol.js +35 -10
  164. package/src/gateways/ws/remote-session-protocol.js +24 -1
  165. package/src/gateways/ws/ws-agent-handler.js +12 -0
  166. package/src/gateways/ws/ws-server.js +48 -12
  167. package/src/harness/jsonl-session-store.js +341 -24
  168. package/src/harness/mcp-client.js +8 -1
  169. package/src/harness/remote-session-audit.js +1 -0
  170. package/src/harness/remote-session-crypto.js +210 -2
  171. package/src/harness/remote-session-registry.js +159 -6
  172. package/src/harness/session-list-index.js +233 -14
  173. package/src/lib/agent-authority.js +6 -0
  174. package/src/lib/agent-schedule-store.js +139 -28
  175. package/src/lib/agent-team/team-merge-review-store.js +765 -0
  176. package/src/lib/agent-team/team-merge-review-transaction.js +1223 -0
  177. package/src/lib/agent-team/team-merge-review.js +1847 -0
  178. package/src/lib/automation-center-incidents.js +314 -0
  179. package/src/lib/automation-center-runtime.js +448 -0
  180. package/src/lib/automation-center.js +182 -38
  181. package/src/lib/automation-engine.js +41 -0
  182. package/src/lib/automation-execution-authority.js +241 -12
  183. package/src/lib/automation-execution-incident.js +737 -0
  184. package/src/lib/background-agent-keeper-client.js +248 -0
  185. package/src/lib/background-agent-keeper-protocol.js +147 -0
  186. package/src/lib/background-agent-supervisor.js +520 -40
  187. package/src/lib/background-interaction-resolver.js +12 -0
  188. package/src/lib/background-turn-bootstrap-protocol.js +126 -0
  189. package/src/lib/cowork-cron.js +85 -14
  190. package/src/lib/cowork-workflow.js +336 -16
  191. package/src/lib/dynamic-workflow-facade.js +648 -0
  192. package/src/lib/execution-location-contract.js +551 -0
  193. package/src/lib/execution-location-runtime.js +130 -0
  194. package/src/lib/ide-context.js +94 -6
  195. package/src/lib/mcp-stdio-package-materialization.js +166 -14
  196. package/src/lib/packer/pkg-config-generator.js +2 -0
  197. package/src/lib/permission-authority.js +77 -0
  198. package/src/lib/permission-side-effect-center.js +495 -0
  199. package/src/lib/plugin-runtime/install.js +514 -13
  200. package/src/lib/plugin-runtime/marketplace-artifact-readback.js +900 -0
  201. package/src/lib/plugin-runtime/marketplace-catalog.js +1181 -0
  202. package/src/lib/plugin-runtime/marketplace-impact.js +408 -0
  203. package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +1567 -0
  204. package/src/lib/plugin-security.js +60 -3
  205. package/src/lib/process-execution-broker/index.js +1095 -57
  206. package/src/lib/process-execution-broker/linux-bwrap-descriptor-launch.js +375 -0
  207. package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +90 -16
  208. package/src/lib/process-execution-broker/linux-generic-bwrap.js +159 -18
  209. package/src/lib/process-execution-broker/macos-mcp-launcher-contract.js +278 -0
  210. package/src/lib/process-execution-broker/macos-mcp-launcher-protocol.json +23 -0
  211. package/src/lib/process-execution-broker/macos-mcp-launcher.c +1497 -0
  212. package/src/lib/process-execution-broker/mcp-fd-entry-bootstrap.js +37 -0
  213. package/src/lib/process-execution-broker/platform-sandbox.js +2330 -279
  214. package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
  215. package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
  216. package/src/lib/process-execution-broker/windows-sandbox.cs +50 -4
  217. package/src/lib/public-ide-capability-manifest.js +3 -0
  218. package/src/lib/remote-approval-bridge.js +123 -17
  219. package/src/lib/remote-membership-authority.js +632 -0
  220. package/src/lib/remote-membership-coordinator.js +2409 -0
  221. package/src/lib/remote-membership-host-store.js +1750 -0
  222. package/src/lib/scheduler-kernel/agenda-adapter.js +17 -7
  223. package/src/lib/scheduler-kernel/automation-adapter.js +105 -11
  224. package/src/lib/scheduler-kernel/automation-event-adapter.js +87 -11
  225. package/src/lib/scheduler-kernel/contract.js +91 -0
  226. package/src/lib/scheduler-kernel/cowork-cron-adapter.js +12 -1
  227. package/src/lib/scheduler-kernel/loop-adapter.js +7 -1
  228. package/src/lib/scheduler-kernel/routine-adapter.js +7 -1
  229. package/src/lib/scheduler-kernel/runtime-control-capabilities.js +31 -0
  230. package/src/lib/scheduler-kernel/runtime.js +176 -3
  231. package/src/lib/scheduler-kernel/store.js +1253 -45
  232. package/src/lib/scoped-permission-store.js +369 -0
  233. package/src/lib/session-anti-rollback-anchor.js +262 -5
  234. package/src/lib/sub-agent-context.js +4 -0
  235. package/src/lib/workflow-definition-contract.js +149 -0
  236. package/src/repl/agent-repl.js +41 -7
  237. package/src/repl/chat-repl.js +2 -0
  238. package/src/repl/clipboard-image.js +735 -16
  239. package/src/repl/ide-status.js +1 -1
  240. package/src/repl/prompt-interactions.js +59 -6
  241. package/src/runtime/agent-core.js +93 -3
  242. package/src/runtime/headless-runner.js +30 -25
  243. package/src/runtime/headless-stream.js +32 -25
  244. package/src/runtime/mcp-config.js +81 -10
  245. package/src/workers/background-agent-keeper.js +498 -0
  246. package/src/workers/background-agent-worker.js +358 -13
  247. package/src/workers/background-turn-bootstrap.js +143 -0
  248. package/src/assets/web-panel/assets/MobileProjects-BWdOvQAj.js +0 -1
  249. package/src/assets/web-panel/assets/Projects-BV4oApsm.js +0 -1
  250. package/src/assets/web-panel/assets/devWarning-DPty0mGN.js +0 -1
  251. package/src/assets/web-panel/assets/index-Bt7g0Vq_.js +0 -1
  252. package/src/assets/web-panel/assets/index-ChVT0p9u.js +0 -1
@@ -12,6 +12,15 @@ import {
12
12
 
13
13
  const PROTOCOL = "chainlesschain.remote-session.e2ee.v1";
14
14
  const PAIRING_SCHEME = "chainlesschain://remote-session/pair#";
15
+ const RELAY_POSSESSION_SCHEMA =
16
+ "chainlesschain.remote-session.relay-possession-capability/v1";
17
+ const relayPossessionCapabilities = new WeakMap();
18
+ const RELAY_AUTHORITY_SCOPES = new Set([
19
+ "observe",
20
+ "prompt",
21
+ "approve",
22
+ "interrupt",
23
+ ]);
15
24
 
16
25
  function b64(value) {
17
26
  return Buffer.from(value).toString("base64url");
@@ -34,6 +43,91 @@ function importPublicKey(value) {
34
43
  return createPublicKey({ key: der, type: "spki", format: "der" });
35
44
  }
36
45
 
46
+ function canonicalPublicKey(value) {
47
+ const key = importPublicKey(value);
48
+ if (key.asymmetricKeyType !== "x25519") {
49
+ throw new Error("Remote Session peer key must be X25519");
50
+ }
51
+ return exportPublicKey(key);
52
+ }
53
+
54
+ function digest(domain, value) {
55
+ return createHash("sha256")
56
+ .update(domain, "utf8")
57
+ .update("\0", "utf8")
58
+ .update(value)
59
+ .digest("hex");
60
+ }
61
+
62
+ export function remoteSessionPairingTokenDigest(pairingToken) {
63
+ if (typeof pairingToken !== "string" || pairingToken.length === 0) {
64
+ throw new Error("Remote Session pairing token is required");
65
+ }
66
+ return digest("chainlesschain.remote-session.pairing-token.v1", pairingToken);
67
+ }
68
+
69
+ function relayEnvelopeTranscriptHash(envelope) {
70
+ const normalized = {
71
+ v: envelope.v,
72
+ sessionId: envelope.sessionId,
73
+ senderId: envelope.senderId,
74
+ sequence: envelope.sequence,
75
+ nonce: envelope.nonce,
76
+ ciphertext: envelope.ciphertext,
77
+ tag: envelope.tag,
78
+ };
79
+ return digest(
80
+ "chainlesschain.remote-session.relay-envelope.v1",
81
+ JSON.stringify(normalized),
82
+ );
83
+ }
84
+
85
+ export function consumeRemoteRelayPossessionCapability(
86
+ capability,
87
+ {
88
+ sessionId,
89
+ mobilePeerId,
90
+ mobilePublicKey,
91
+ pairingTokenDigest,
92
+ coordinatorId,
93
+ serverInstanceId,
94
+ authorityVersion,
95
+ } = {},
96
+ ) {
97
+ const proof = relayPossessionCapabilities.get(capability);
98
+ // Consume before checking the caller's expectation. A confused-deputy or
99
+ // stale binding attempt cannot probe and then reuse the capability.
100
+ relayPossessionCapabilities.delete(capability);
101
+ const expectedPublicKey = canonicalPublicKey(mobilePublicKey);
102
+ if (
103
+ !proof ||
104
+ proof.sessionId !== sessionId ||
105
+ proof.mobilePeerId !== mobilePeerId ||
106
+ proof.mobilePublicKey !== expectedPublicKey ||
107
+ proof.pairingTokenDigest !== pairingTokenDigest ||
108
+ proof.coordinatorId !== coordinatorId ||
109
+ proof.serverInstanceId !== serverInstanceId ||
110
+ proof.authorityVersion !== authorityVersion
111
+ ) {
112
+ throw new Error("Remote relay possession capability is invalid or stale");
113
+ }
114
+ return Object.freeze({
115
+ ...proof,
116
+ authorizedScopes: Object.freeze([...proof.authorizedScopes]),
117
+ });
118
+ }
119
+
120
+ function normalizeRelayAuthorityScopes(scopes) {
121
+ if (!Array.isArray(scopes) || scopes.length === 0) {
122
+ throw new Error("Durable Remote relay scopes are required");
123
+ }
124
+ const normalized = [...new Set(scopes.map(String))].sort();
125
+ if (normalized.some((scope) => !RELAY_AUTHORITY_SCOPES.has(scope))) {
126
+ throw new Error("Durable Remote relay scopes are invalid");
127
+ }
128
+ return Object.freeze(normalized);
129
+ }
130
+
37
131
  function aad(sessionId, senderId, sequence) {
38
132
  return Buffer.from(
39
133
  `${PROTOCOL}\n${sessionId}\n${senderId}\n${sequence}`,
@@ -121,7 +215,13 @@ export function parseRemotePairingUri(uri, now = Date.now()) {
121
215
  }
122
216
 
123
217
  export class RemoteSessionCryptoContext {
124
- constructor({ sessionId, localPeerId, privateKey, publicKey } = {}) {
218
+ constructor({
219
+ sessionId,
220
+ localPeerId,
221
+ privateKey,
222
+ publicKey,
223
+ now = () => Date.now(),
224
+ } = {}) {
125
225
  if (!sessionId || !localPeerId)
126
226
  throw new Error("sessionId and localPeerId are required");
127
227
  let keyPair;
@@ -134,23 +234,88 @@ export class RemoteSessionCryptoContext {
134
234
  format: "der",
135
235
  });
136
236
  this.publicKey = publicKey || keyPair.publicKey;
237
+ this._now = now;
137
238
  this.keys = new Map();
239
+ this.pairingMaterial = new Map();
240
+ this.pendingRelayCapabilities = new Map();
241
+ this.outstandingRelayCapabilities = new Map();
138
242
  this.sendSequence = 0;
139
243
  this.receivedSequences = new Map();
140
244
  }
141
245
 
142
246
  pair(peerId, peerPublicKey, pairingToken) {
247
+ return this._pair(peerId, peerPublicKey, pairingToken, null);
248
+ }
249
+
250
+ pairForDurableMembership(
251
+ peerId,
252
+ peerPublicKey,
253
+ pairingToken,
254
+ {
255
+ authorizedScopes,
256
+ expiresAtMs,
257
+ coordinatorId,
258
+ serverInstanceId,
259
+ authorityVersion,
260
+ } = {},
261
+ ) {
262
+ const normalizedExpiry = Number(expiresAtMs);
263
+ if (
264
+ !Number.isSafeInteger(normalizedExpiry) ||
265
+ normalizedExpiry <= this._now()
266
+ ) {
267
+ throw new Error("Durable Remote relay pairing authority is expired");
268
+ }
269
+ if (
270
+ typeof coordinatorId !== "string" ||
271
+ coordinatorId.length === 0 ||
272
+ typeof serverInstanceId !== "string" ||
273
+ serverInstanceId.length === 0 ||
274
+ typeof authorityVersion !== "string" ||
275
+ authorityVersion.length === 0
276
+ ) {
277
+ throw new Error("Durable Remote relay authority domain is required");
278
+ }
279
+ return this._pair(peerId, peerPublicKey, pairingToken, {
280
+ authorizedScopes: normalizeRelayAuthorityScopes(authorizedScopes),
281
+ expiresAtMs: normalizedExpiry,
282
+ coordinatorId,
283
+ serverInstanceId,
284
+ authorityVersion,
285
+ });
286
+ }
287
+
288
+ _pair(peerId, peerPublicKey, pairingToken, durableAuthority) {
143
289
  if (!peerId || !peerPublicKey || !pairingToken)
144
290
  throw new Error("Incomplete peer key material");
291
+ // Preserve the legacy re-pair/rotated-token behavior. Re-pairing replaces
292
+ // the transport key, but first invalidates any not-yet-consumed authority
293
+ // capability minted under the old key/token tuple.
294
+ const outstandingCapability = this.outstandingRelayCapabilities.get(peerId);
295
+ if (outstandingCapability) {
296
+ relayPossessionCapabilities.delete(outstandingCapability);
297
+ }
298
+ this.pendingRelayCapabilities.delete(peerId);
299
+ this.outstandingRelayCapabilities.delete(peerId);
300
+ const normalizedPublicKey = canonicalPublicKey(peerPublicKey);
145
301
  this.keys.set(
146
302
  peerId,
147
303
  deriveKey(
148
304
  this.privateKey,
149
- importPublicKey(peerPublicKey),
305
+ importPublicKey(normalizedPublicKey),
150
306
  this.sessionId,
151
307
  pairingToken,
152
308
  ),
153
309
  );
310
+ this.pairingMaterial.set(peerId, {
311
+ mobilePublicKey: normalizedPublicKey,
312
+ pairingTokenDigest: remoteSessionPairingTokenDigest(pairingToken),
313
+ authorizedScopes: durableAuthority?.authorizedScopes || null,
314
+ expiresAtMs: durableAuthority?.expiresAtMs || null,
315
+ coordinatorId: durableAuthority?.coordinatorId || null,
316
+ serverInstanceId: durableAuthority?.serverInstanceId || null,
317
+ authorityVersion: durableAuthority?.authorityVersion || null,
318
+ });
154
319
  }
155
320
 
156
321
  encrypt(peerId, message) {
@@ -207,6 +372,38 @@ export class RemoteSessionCryptoContext {
207
372
  ]);
208
373
  const message = JSON.parse(plaintext.toString("utf8"));
209
374
  this.receivedSequences.set(envelope.senderId, envelope.sequence);
375
+ const pairing = this.pairingMaterial.get(envelope.senderId);
376
+ if (
377
+ pairing &&
378
+ pairing.authorizedScopes !== null &&
379
+ pairing.coordinatorId !== null &&
380
+ pairing.serverInstanceId !== null &&
381
+ pairing.authorityVersion !== null &&
382
+ pairing.expiresAtMs > this._now() &&
383
+ message?.type === "pair.join" &&
384
+ typeof message.token === "string" &&
385
+ remoteSessionPairingTokenDigest(message.token) ===
386
+ pairing.pairingTokenDigest
387
+ ) {
388
+ const proof = Object.freeze({
389
+ schema: RELAY_POSSESSION_SCHEMA,
390
+ sessionId: this.sessionId,
391
+ mobilePeerId: envelope.senderId,
392
+ mobilePublicKey: pairing.mobilePublicKey,
393
+ pairingTokenDigest: pairing.pairingTokenDigest,
394
+ coordinatorId: pairing.coordinatorId,
395
+ serverInstanceId: pairing.serverInstanceId,
396
+ authorityVersion: pairing.authorityVersion,
397
+ authorizedScopes: pairing.authorizedScopes,
398
+ pairingExpiresAtMs: pairing.expiresAtMs,
399
+ envelopeSequence: envelope.sequence,
400
+ envelopeTranscriptHash: relayEnvelopeTranscriptHash(envelope),
401
+ });
402
+ relayPossessionCapabilities.set(proof, { ...proof });
403
+ this.pendingRelayCapabilities.set(envelope.senderId, proof);
404
+ this.outstandingRelayCapabilities.set(envelope.senderId, proof);
405
+ this.pairingMaterial.delete(envelope.senderId);
406
+ }
210
407
  return message;
211
408
  } catch (error) {
212
409
  throw new Error(
@@ -214,4 +411,15 @@ export class RemoteSessionCryptoContext {
214
411
  );
215
412
  }
216
413
  }
414
+
415
+ takeRelayPossessionCapability(peerId) {
416
+ const capability = this.pendingRelayCapabilities.get(peerId);
417
+ this.pendingRelayCapabilities.delete(peerId);
418
+ if (!capability) {
419
+ throw new Error(
420
+ "No authenticated Remote relay pairing transcript is available",
421
+ );
422
+ }
423
+ return capability;
424
+ }
217
425
  }
@@ -167,6 +167,12 @@ function publicSession(session) {
167
167
  createdAt: session.createdAt,
168
168
  expiresAt: session.expiresAt,
169
169
  memberCount: session.members.size,
170
+ ...(session.membershipAuthority
171
+ ? {
172
+ membershipAuthority: session.membershipAuthority,
173
+ sessionEpoch: session.sessionEpoch,
174
+ }
175
+ : {}),
170
176
  };
171
177
  }
172
178
 
@@ -177,21 +183,54 @@ export class RemoteSessionRegistry {
177
183
  this.tokenTtlMs = options.tokenTtlMs || DEFAULT_TOKEN_TTL_MS;
178
184
  this.sessionTtlMs = options.sessionTtlMs || DEFAULT_SESSION_TTL_MS;
179
185
  this.policy = options.policy || new RemoteSessionPolicy();
186
+ // A factory keeps ordinary/in-memory Remote Session tests and deployments
187
+ // from touching the machine security store. Client-hosted approval bridges
188
+ // explicitly require this authority and trigger its lazy construction.
189
+ this._membershipAuthority = options.membershipAuthority ?? null;
180
190
  this.sessions = new Map();
181
191
  this.tokens = new Map();
182
192
  }
183
193
 
184
- create({ hostClientId, agentSessionId, name, scopes } = {}) {
194
+ _requireMembershipAuthority() {
195
+ if (typeof this._membershipAuthority === "function") {
196
+ this._membershipAuthority = this._membershipAuthority();
197
+ }
198
+ if (!this._membershipAuthority) {
199
+ throw new Error(
200
+ "Durable Remote membership authority is required for client-hosted approvals",
201
+ );
202
+ }
203
+ return this._membershipAuthority;
204
+ }
205
+
206
+ create({
207
+ hostClientId,
208
+ agentSessionId,
209
+ name,
210
+ scopes,
211
+ durableMembership = false,
212
+ } = {}) {
185
213
  if (!hostClientId) throw new Error("hostClientId is required");
186
214
  if (!agentSessionId) throw new Error("agentSessionId is required");
187
215
  const now = this.now();
216
+ const expiresAt = now + this.policy.capSessionTtl(this.sessionTtlMs);
217
+ const sessionId = randomUUID();
218
+ const durable = durableMembership
219
+ ? this._requireMembershipAuthority().createSession({
220
+ sessionId,
221
+ agentSessionId,
222
+ hostPrincipalId: hostClientId,
223
+ scopes: REMOTE_SESSION_SCOPES,
224
+ expiresAt,
225
+ })
226
+ : null;
188
227
  const session = {
189
- sessionId: randomUUID(),
228
+ sessionId,
190
229
  agentSessionId,
191
230
  name: name || agentSessionId,
192
231
  hostClientId,
193
232
  createdAt: now,
194
- expiresAt: now + this.policy.capSessionTtl(this.sessionTtlMs),
233
+ expiresAt,
195
234
  members: new Map([
196
235
  [
197
236
  hostClientId,
@@ -199,9 +238,16 @@ export class RemoteSessionRegistry {
199
238
  clientId: hostClientId,
200
239
  scopes: REMOTE_SESSION_SCOPES,
201
240
  joinedAt: now,
241
+ ...(durable ? { membershipEpoch: durable.membershipEpoch } : {}),
202
242
  },
203
243
  ],
204
244
  ]),
245
+ ...(durable
246
+ ? {
247
+ membershipAuthority: durable.authorityVersion,
248
+ sessionEpoch: durable.sessionEpoch,
249
+ }
250
+ : {}),
205
251
  };
206
252
  this.sessions.set(session.sessionId, session);
207
253
  return {
@@ -251,6 +297,9 @@ export class RemoteSessionRegistry {
251
297
  if (!tokensMatch(token, pairing.digest)) {
252
298
  throw new Error("Invalid pairing token");
253
299
  }
300
+ if (clientId === session.hostClientId) {
301
+ throw new Error("Cannot replace the host membership through pairing");
302
+ }
254
303
  // Org policy is enforced only after the token proves the caller is invited,
255
304
  // so a device-limit / relay-disabled message never leaks to unauthenticated
256
305
  // probes. Existing (non-host) devices count against the limit.
@@ -258,8 +307,17 @@ export class RemoteSessionRegistry {
258
307
  (member) => member.clientId !== session.hostClientId,
259
308
  ).length;
260
309
  this.policy.enforceJoin({ deviceCount, via });
310
+ const durable = session.membershipAuthority
311
+ ? this._requireMembershipAuthority().joinMember({
312
+ sessionId,
313
+ principalId: clientId,
314
+ scopes: pairing.scopes,
315
+ expectedSessionEpoch: session.sessionEpoch,
316
+ })
317
+ : null;
261
318
  // Pairing credentials are deliberately one-time. The host must explicitly
262
- // issue another token for each additional device.
319
+ // issue another token for each additional device. For durable sessions the
320
+ // authority commit happens first, so a persistence failure stays retryable.
263
321
  this.tokens.delete(sessionId);
264
322
  const member = {
265
323
  clientId,
@@ -267,6 +325,7 @@ export class RemoteSessionRegistry {
267
325
  joinedAt: this.now(),
268
326
  pushToken: pushToken || null,
269
327
  pushProvider: pushToken ? pushProvider || null : null,
328
+ ...(durable ? { membershipEpoch: durable.membershipEpoch } : {}),
270
329
  };
271
330
  session.members.set(clientId, member);
272
331
  return { session: publicSession(session), member: { ...member } };
@@ -311,13 +370,41 @@ export class RemoteSessionRegistry {
311
370
 
312
371
  authorize(sessionId, clientId, scope) {
313
372
  const session = this.requireSession(sessionId);
373
+ if (session.membershipQuarantined) {
374
+ throw new Error(
375
+ "Remote membership session is quarantined after an unknown durable transition",
376
+ );
377
+ }
314
378
  const member = session.members.get(clientId);
315
379
  if (!member)
316
380
  throw new Error("Client is not paired with this remote session");
381
+ if (member.membershipQuarantined) {
382
+ throw new Error(
383
+ "Remote membership is quarantined after an unknown durable transition",
384
+ );
385
+ }
317
386
  if (!member.scopes.includes(scope)) {
318
387
  throw new Error(`Remote session scope required: ${scope}`);
319
388
  }
320
- return { session, member };
389
+ let membership = null;
390
+ if (session.membershipAuthority) {
391
+ const verdict = this._requireMembershipAuthority().readMembership(
392
+ {
393
+ sessionId,
394
+ principalId: clientId,
395
+ sessionEpoch: session.sessionEpoch,
396
+ membershipEpoch: member.membershipEpoch,
397
+ },
398
+ scope,
399
+ );
400
+ if (!verdict.ok) {
401
+ throw new Error(
402
+ `Remote membership authority denied: ${verdict.reason}`,
403
+ );
404
+ }
405
+ membership = verdict.binding;
406
+ }
407
+ return { session, member, membership };
321
408
  }
322
409
 
323
410
  members(sessionId) {
@@ -364,6 +451,21 @@ export class RemoteSessionRegistry {
364
451
  const member = session.members.get(clientId);
365
452
  if (!member)
366
453
  throw new Error("Device is not paired with this remote session");
454
+ if (session.membershipAuthority) {
455
+ try {
456
+ this._requireMembershipAuthority().revokeMember({
457
+ sessionId,
458
+ principalId: clientId,
459
+ expectedSessionEpoch: session.sessionEpoch,
460
+ expectedMembershipEpoch: member.membershipEpoch,
461
+ });
462
+ } catch (error) {
463
+ // The durable outcome may be unknown. Keep the record for diagnostics,
464
+ // but locally quarantine it so no later frame can authorize.
465
+ member.membershipQuarantined = true;
466
+ throw error;
467
+ }
468
+ }
367
469
  session.members.delete(clientId);
368
470
  return { session: publicSession(session), member: { ...member } };
369
471
  }
@@ -385,12 +487,39 @@ export class RemoteSessionRegistry {
385
487
  removeClient(clientId) {
386
488
  const affected = [];
387
489
  for (const [sessionId, session] of this.sessions) {
388
- if (!session.members.delete(clientId)) continue;
490
+ const member = session.members.get(clientId);
491
+ if (!member) continue;
389
492
  if (session.hostClientId === clientId) {
493
+ if (session.membershipAuthority) {
494
+ try {
495
+ this._requireMembershipAuthority().closeSession({
496
+ sessionId,
497
+ hostPrincipalId: clientId,
498
+ expectedSessionEpoch: session.sessionEpoch,
499
+ });
500
+ } catch (error) {
501
+ session.membershipQuarantined = true;
502
+ throw error;
503
+ }
504
+ }
390
505
  this.sessions.delete(sessionId);
391
506
  this.tokens.delete(sessionId);
392
507
  affected.push({ sessionId, closed: true });
393
508
  } else {
509
+ if (session.membershipAuthority) {
510
+ try {
511
+ this._requireMembershipAuthority().revokeMember({
512
+ sessionId,
513
+ principalId: clientId,
514
+ expectedSessionEpoch: session.sessionEpoch,
515
+ expectedMembershipEpoch: member.membershipEpoch,
516
+ });
517
+ } catch (error) {
518
+ member.membershipQuarantined = true;
519
+ throw error;
520
+ }
521
+ }
522
+ session.members.delete(clientId);
394
523
  affected.push({ sessionId, closed: false });
395
524
  }
396
525
  }
@@ -402,6 +531,18 @@ export class RemoteSessionRegistry {
402
531
  if (session.hostClientId !== clientId) {
403
532
  throw new Error("Only the host can close a Remote Session");
404
533
  }
534
+ if (session.membershipAuthority) {
535
+ try {
536
+ this._requireMembershipAuthority().closeSession({
537
+ sessionId,
538
+ hostPrincipalId: clientId,
539
+ expectedSessionEpoch: session.sessionEpoch,
540
+ });
541
+ } catch (error) {
542
+ session.membershipQuarantined = true;
543
+ throw error;
544
+ }
545
+ }
405
546
  this.sessions.delete(sessionId);
406
547
  this.tokens.delete(sessionId);
407
548
  return publicSession(session);
@@ -411,6 +552,18 @@ export class RemoteSessionRegistry {
411
552
  const session = this.sessions.get(sessionId);
412
553
  if (!session) throw new Error("Remote session not found");
413
554
  if (session.expiresAt <= this.now()) {
555
+ if (session.membershipAuthority) {
556
+ try {
557
+ this._requireMembershipAuthority().closeSession({
558
+ sessionId,
559
+ hostPrincipalId: session.hostClientId,
560
+ expectedSessionEpoch: session.sessionEpoch,
561
+ });
562
+ } catch (error) {
563
+ session.membershipQuarantined = true;
564
+ throw error;
565
+ }
566
+ }
414
567
  this.sessions.delete(sessionId);
415
568
  this.tokens.delete(sessionId);
416
569
  throw new Error("Remote session expired");