chainlesschain 0.163.8 → 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 (228) hide show
  1. package/package.json +4 -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-CavM7W3k.js → AIOps-D2MEn7fI.js} +1 -1
  6. package/src/assets/web-panel/assets/{ActionButton-CUvZGabQ.js → ActionButton-lCW_4Gf0.js} +1 -1
  7. package/src/assets/web-panel/assets/{Analytics-DeBnWnbe.js → Analytics-Bs7i-nsS.js} +3 -3
  8. package/src/assets/web-panel/assets/{AppLayout-DbI5kxvd.js → AppLayout-CK7B6S_j.js} +5 -5
  9. package/src/assets/web-panel/assets/{Artifacts-D93bigKm.js → Artifacts-C8ILjpyo.js} +1 -1
  10. package/src/assets/web-panel/assets/{Audit-CBNvfUZa.js → Audit-Bb9cNaWc.js} +1 -1
  11. package/src/assets/web-panel/assets/{BackgroundAgents-CJLyh_YU.js → BackgroundAgents-sC9ooXIf.js} +1 -1
  12. package/src/assets/web-panel/assets/{Backup-D_0yoehD.js → Backup-D-DrsplT.js} +1 -1
  13. package/src/assets/web-panel/assets/{BaseInput-TJxmbObW.js → BaseInput-uCNZpwSK.js} +1 -1
  14. package/src/assets/web-panel/assets/{Chat-CE0dto1q.js → Chat-CsDK1uE9.js} +6 -6
  15. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CZ5-yYiD.js → ChatBubbleRenderer-OqSDt50w.js} +1 -1
  16. package/src/assets/web-panel/assets/{Checkbox-Ck1RVIVo.js → Checkbox-JhTXM1-K.js} +1 -1
  17. package/src/assets/web-panel/assets/{Codegen-qpoyf6DK.js → Codegen-BbzZLnyD.js} +1 -1
  18. package/src/assets/web-panel/assets/{Col-DUyPWjIE.js → Col-D4VW4m4j.js} +1 -1
  19. package/src/assets/web-panel/assets/{Community-D_S1BemS.js → Community-BXrYawxV.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compact-BjxeK-Gc.js → Compact-DCihGy1u.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compliance-Dd3CEJsu.js → Compliance-DlyZ-lk8.js} +1 -1
  22. package/src/assets/web-panel/assets/{Cowork-B4QG7-ad.js → Cowork-DvGZrhbO.js} +3 -3
  23. package/src/assets/web-panel/assets/{Cron-BtZnids5.js → Cron-DUncZi8h.js} +2 -2
  24. package/src/assets/web-panel/assets/{Crosschain-CHPfCBFD.js → Crosschain-C_hLuUcm.js} +1 -1
  25. package/src/assets/web-panel/assets/{DID-DT8DCEOK.js → DID-b6YSUqxr.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dashboard-COQab5_U.js → Dashboard-uvM15Cfb.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dropdown-BY1PsQuU.js → Dropdown-D1-Nd4qY.js} +1 -1
  28. package/src/assets/web-panel/assets/{EmailListRenderer-CsuAuaq3.js → EmailListRenderer-8ApvL6Zc.js} +1 -1
  29. package/src/assets/web-panel/assets/{FamilyGuardDashboard-BqpinD-j.js → FamilyGuardDashboard-LYJt8811.js} +1 -1
  30. package/src/assets/web-panel/assets/{Federation-D0gkfQFv.js → Federation-BbI3HGpv.js} +1 -1
  31. package/src/assets/web-panel/assets/{FormItemContext-BqgE-axK.js → FormItemContext-DSoEKuFu.js} +1 -1
  32. package/src/assets/web-panel/assets/{GenericCardRenderer-D0hJ2KvC.js → GenericCardRenderer-B0S9OWd5.js} +1 -1
  33. package/src/assets/web-panel/assets/{Git-CmMB0uPY.js → Git-DIs9Zhf3.js} +2 -2
  34. package/src/assets/web-panel/assets/{Governance-BnVEI0Dk.js → Governance-jzZXrxcl.js} +1 -1
  35. package/src/assets/web-panel/assets/{Inference-YTAMihRP.js → Inference-JUPjf2ZI.js} +1 -1
  36. package/src/assets/web-panel/assets/{KnowledgeGraph-0ax7VHop.js → KnowledgeGraph-DxnfJvlP.js} +1 -1
  37. package/src/assets/web-panel/assets/{Logs-B9TRcokL.js → Logs-iXiz8BEE.js} +2 -2
  38. package/src/assets/web-panel/assets/MarkdownRenderer-GmB6DOr6.js +1 -0
  39. package/src/assets/web-panel/assets/{Marketplace-B6CSuD_H.js → Marketplace-Y3Xch312.js} +1 -1
  40. package/src/assets/web-panel/assets/{McpTools-CjMXvOVU.js → McpTools-D7kGGbO7.js} +3 -3
  41. package/src/assets/web-panel/assets/{Memory-CXRF71U3.js → Memory-Do_hVxzh.js} +2 -2
  42. package/src/assets/web-panel/assets/{MobileBridge-DQgNp_oS.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-6hDTRPe1.js → Mtc-qo5QCTGd.js} +2 -2
  45. package/src/assets/web-panel/assets/{MtcAudit-BlVHU1DS.js → MtcAudit-cq5mnjYj.js} +2 -2
  46. package/src/assets/web-panel/assets/{Multisig-DP9pzEbV.js → Multisig-Bq0MAQHw.js} +3 -3
  47. package/src/assets/web-panel/assets/{NLProgramming-Djorh8EV.js → NLProgramming-DdWE6Vi2.js} +1 -1
  48. package/src/assets/web-panel/assets/{Notes-oLZ-JkUg.js → Notes-BxMBFcIp.js} +4 -4
  49. package/src/assets/web-panel/assets/{NotificationSettings-Cg288VH3.js → NotificationSettings-RTrAcbUe.js} +1 -1
  50. package/src/assets/web-panel/assets/{OrderTableRenderer-Bb1O3Ofr.js → OrderTableRenderer-DJbpGqzT.js} +1 -1
  51. package/src/assets/web-panel/assets/{Organization-CBdo-bHs.js → Organization-SQzIPdqC.js} +2 -2
  52. package/src/assets/web-panel/assets/{Overflow-qZdnVumx.js → Overflow-02yECh22.js} +1 -1
  53. package/src/assets/web-panel/assets/{P2P-D4kNfGNQ.js → P2P-BNg4pNCM.js} +2 -2
  54. package/src/assets/web-panel/assets/{PdhVaultBrowser-DnlMemM7.js → PdhVaultBrowser-BxPJZsD3.js} +5 -5
  55. package/src/assets/web-panel/assets/{Permissions-DHucHFBJ.js → Permissions-CLnDnPAz.js} +3 -3
  56. package/src/assets/web-panel/assets/{PersonalDataHub-BovlOIPR.js → PersonalDataHub-C5m0AjGf.js} +4 -4
  57. package/src/assets/web-panel/assets/{Pipeline-Deru3CQY.js → Pipeline-VwOf5Dhv.js} +1 -1
  58. package/src/assets/web-panel/assets/{Privacy-Bq5oTTbU.js → Privacy-CC0W2hZd.js} +1 -1
  59. package/src/assets/web-panel/assets/{ProjectInit-BfzxVWAz.js → ProjectInit-Dz893Bob.js} +2 -2
  60. package/src/assets/web-panel/assets/{ProjectSettings-CKC6XBtH.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-C_jx4TWX.js → Providers-DeB9IkxK.js} +1 -1
  63. package/src/assets/web-panel/assets/{QrScannerModal-BdIHeVGC.js → QrScannerModal-OCeoaswn.js} +1 -1
  64. package/src/assets/web-panel/assets/{QuickAsk-BwZwAcPD.js → QuickAsk-DenotaAj.js} +1 -1
  65. package/src/assets/web-panel/assets/{Recommend-BNTt0L-m.js → Recommend-Cies_jjI.js} +1 -1
  66. package/src/assets/web-panel/assets/{RemoteSession-Biyn2-Ro.js → RemoteSession-Dxzl5n2T.js} +3 -3
  67. package/src/assets/web-panel/assets/{Reputation-D6VpG32B.js → Reputation-CW0mvxgZ.js} +1 -1
  68. package/src/assets/web-panel/assets/{Row-D_74OvQQ.js → Row-SEd32qZU.js} +1 -1
  69. package/src/assets/web-panel/assets/{RssFeed-BTr0a-BQ.js → RssFeed-BSwnJ3Lm.js} +3 -3
  70. package/src/assets/web-panel/assets/{Search-C3MCFoNU.js → Search-xe2m8bkC.js} +1 -1
  71. package/src/assets/web-panel/assets/{Security-CqW9aJ6s.js → Security-Mq2F9Nro.js} +3 -3
  72. package/src/assets/web-panel/assets/{Services-Cw5GNaHF.js → Services-BKGw2V3P.js} +2 -2
  73. package/src/assets/web-panel/assets/{Skeleton-DZps5qeY.js → Skeleton-DW95-Rxf.js} +1 -1
  74. package/src/assets/web-panel/assets/{Skills-C6NQ1znT.js → Skills-CHgChCv_.js} +1 -1
  75. package/src/assets/web-panel/assets/{Sla-DFP8G2Sh.js → Sla-tKh6k3R7.js} +1 -1
  76. package/src/assets/web-panel/assets/{SpeechSettings-ESt6MB6v.js → SpeechSettings-D6UL3dA5.js} +1 -1
  77. package/src/assets/web-panel/assets/{SyncSettings-BHnN98aM.js → SyncSettings-D0Fw8fVL.js} +2 -2
  78. package/src/assets/web-panel/assets/{Tasks-NiSCaOf-.js → Tasks-20x1GB3D.js} +1 -1
  79. package/src/assets/web-panel/assets/{Templates-DsKFhW2C.js → Templates-DJ-lts-a.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tenant-CQ0E0ze5.js → Tenant-BFdGpbs7.js} +1 -1
  81. package/src/assets/web-panel/assets/{Terminal-D_rBu_by.js → Terminal-Xpx61vHL.js} +2 -2
  82. package/src/assets/web-panel/assets/{TimelineRenderer-D3Vm4Po4.js → TimelineRenderer-C6UIvyZQ.js} +1 -1
  83. package/src/assets/web-panel/assets/{Tokens-DNTxRH6q.js → Tokens-Dellq08f.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trigger-Dgprz1ms.js → Trigger-VKw8d0J-.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trust-B2rUnVBD.js → Trust-DNftdKT5.js} +1 -1
  86. package/src/assets/web-panel/assets/{UkeySign-DEGQNc6_.js → UkeySign-DX9VAKJI.js} +1 -1
  87. package/src/assets/web-panel/assets/{VideoEditing-jlsAx3Eh.js → VideoEditing-B2h3jO8q.js} +1 -1
  88. package/src/assets/web-panel/assets/{Wallet-8jQih1ij.js → Wallet-CjGkof7f.js} +4 -4
  89. package/src/assets/web-panel/assets/{WebAuthn-XLeO6xIB.js → WebAuthn-2Zfcu55P.js} +4 -4
  90. package/src/assets/web-panel/assets/{WorkflowEditor-De_dgDAG.js → WorkflowEditor-B9eZ8UxZ.js} +1 -1
  91. package/src/assets/web-panel/assets/{chat-CI19R_Sk.js → chat-CQNfD-YO.js} +1 -1
  92. package/src/assets/web-panel/assets/{colors-DsYTOYN3.js → colors-D4usyFT2.js} +1 -1
  93. package/src/assets/web-panel/assets/{compact-item-CM3-t_Qr.js → compact-item-s4TpjvjX.js} +1 -1
  94. package/src/assets/web-panel/assets/{createContext-BjxlBRZv.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-RDaWX_4i.js → hasIn-AdkUbkV-.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-BN6UPD2E.js → index--00U6vXZ.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-CiECJi-Q.js → index-B2V-eKfK.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-CnHH7bnD.js → index-B4JJCfQ2.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CjTrRt13.js → index-BIoG5yYf.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-Dxge-xWl.js → index-BMcimU-2.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-9R6BxAr0.js → index-BPhkFZ1I.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BHNYPO0b.js → index-BQ3DXBtD.js} +3 -3
  104. package/src/assets/web-panel/assets/{index-Cpqm1qfU.js → index-Bad4VNvz.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-B9O9YyWE.js → index-BgiXR_-_.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-B5REnKt8.js → index-BtobShro.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-D6sm5-Xq.js → index-Bw2MEnUk.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DcPFB8qJ.js → index-C1mJtE6q.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-BKJr-TZp.js → index-C484EJiS.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-Drlnwr8F.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-Dsij_KsN.js → index-C7Y8Aluc.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-IeiL9RKc.js → index-CCsM_Ybx.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-B-Z8eFUJ.js → index-CJCFe2Qf.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-CyOGN6a5.js → index-CJVEOa4i.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-B0PMlbMs.js → index-CJdQrZth.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-nAH87mQP.js → index-CKC1t3Ic.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-BGqqJfL0.js → index-CQhAVU5t.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-Cd9OJhHG.js → index-CYdoQsa1.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-D0zcy54x.js → index-Cduu2Hhr.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-DIUnNOjG.js → index-CkwiSLhU.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-CVQMeiwH.js → index-Cvyt-zhm.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-BlT2VAEK.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-C0yx-jtQ.js → index-DARsAyUp.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-Bi46Xu4u.js → index-DVKfQ0Ux.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-Cd3euP_4.js → index-DZT36ZYq.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-BCnZyIMA.js → index-D_XBHopw.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-C4gkzxkw.js → index-DdCB70SS.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-B7WBt_4T.js → index-DzRjHxEv.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-DX7tuWVJ.js → index-MMN9V6JF.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-DoQA0-52.js → index-RfMr79MW.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-DXXtGMUJ.js → index-_IRVsV9X.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-pPL66J85.js → index-nXyk8GZ9.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-DyIWssPC.js → index-s_buFMEG.js} +1 -1
  136. package/src/assets/web-panel/assets/{initDefaultProps-BTL88of4.js → initDefaultProps-Blmpk7HL.js} +1 -1
  137. package/src/assets/web-panel/assets/{motion-BUB2pXwB.js → motion-DPBJMv1n.js} +1 -1
  138. package/src/assets/web-panel/assets/{move-egCkkOMm.js → move-ButdzCM7.js} +1 -1
  139. package/src/assets/web-panel/assets/{mtc-parser-DAWhZC8c.js → mtc-parser-cyRC_QCe.js} +1 -1
  140. package/src/assets/web-panel/assets/{omit-CvOxe_6d.js → omit-1epSV7hz.js} +1 -1
  141. package/src/assets/web-panel/assets/{pickAttrs-DZUSLZ5Z.js → pickAttrs-DuPY8xJs.js} +1 -1
  142. package/src/assets/web-panel/assets/{placementArrow-BERxGNMY.js → placementArrow-6XZqarhe.js} +1 -1
  143. package/src/assets/web-panel/assets/{responsiveObserve-DZuDfZ9n.js → responsiveObserve-B40pXBWM.js} +1 -1
  144. package/src/assets/web-panel/assets/{slide-DO756sgI.js → slide-jbZ9Wu4n.js} +1 -1
  145. package/src/assets/web-panel/assets/{statusUtils-BRQlIz28.js → statusUtils-BKQQcVy4.js} +1 -1
  146. package/src/assets/web-panel/assets/{styleChecker-DCSfdybl.js → styleChecker-NiKfWjUT.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFlexGapSupport-LD8dWVve.js → useFlexGapSupport-bQUCvPeb.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFs-BX9uW2LK.js → useFs-CUGji7ph.js} +1 -1
  149. package/src/assets/web-panel/assets/{usePersonalDataHub-BPSlPuHU.js → usePersonalDataHub-4veyN2N2.js} +1 -1
  150. package/src/assets/web-panel/assets/{vnode-BmOILC9V.js → vnode-1-nLug-Z.js} +1 -1
  151. package/src/assets/web-panel/assets/{zoom-1iKowKGg.js → zoom-dhCeRDMo.js} +1 -1
  152. package/src/assets/web-panel/index.html +1 -1
  153. package/src/command-help-index.json +3 -3
  154. package/src/commands/cowork.js +174 -19
  155. package/src/commands/permissions.js +240 -16
  156. package/src/commands/plugin.js +1293 -56
  157. package/src/commands/session-location.js +276 -0
  158. package/src/commands/session.js +2 -0
  159. package/src/data/changelog.json +15 -2
  160. package/src/gateways/ws/action-protocol.js +35 -10
  161. package/src/gateways/ws/remote-session-protocol.js +24 -1
  162. package/src/gateways/ws/ws-agent-handler.js +12 -0
  163. package/src/gateways/ws/ws-server.js +48 -12
  164. package/src/harness/jsonl-session-store.js +341 -24
  165. package/src/harness/mcp-client.js +8 -1
  166. package/src/harness/remote-session-audit.js +1 -0
  167. package/src/harness/remote-session-crypto.js +210 -2
  168. package/src/harness/remote-session-registry.js +159 -6
  169. package/src/harness/session-list-index.js +233 -14
  170. package/src/lib/agent-authority.js +6 -0
  171. package/src/lib/background-agent-keeper-client.js +248 -0
  172. package/src/lib/background-agent-keeper-protocol.js +147 -0
  173. package/src/lib/background-agent-supervisor.js +520 -40
  174. package/src/lib/background-interaction-resolver.js +12 -0
  175. package/src/lib/background-turn-bootstrap-protocol.js +126 -0
  176. package/src/lib/cowork-workflow.js +336 -16
  177. package/src/lib/dynamic-workflow-facade.js +648 -0
  178. package/src/lib/execution-location-contract.js +551 -0
  179. package/src/lib/execution-location-runtime.js +130 -0
  180. package/src/lib/ide-context.js +94 -6
  181. package/src/lib/mcp-stdio-package-materialization.js +166 -14
  182. package/src/lib/packer/pkg-config-generator.js +2 -0
  183. package/src/lib/permission-authority.js +77 -0
  184. package/src/lib/permission-side-effect-center.js +495 -0
  185. package/src/lib/plugin-runtime/install.js +514 -13
  186. package/src/lib/plugin-runtime/marketplace-artifact-readback.js +900 -0
  187. package/src/lib/plugin-runtime/marketplace-catalog.js +1181 -0
  188. package/src/lib/plugin-runtime/marketplace-impact.js +408 -0
  189. package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +1567 -0
  190. package/src/lib/plugin-security.js +60 -3
  191. package/src/lib/process-execution-broker/index.js +1095 -57
  192. package/src/lib/process-execution-broker/linux-bwrap-descriptor-launch.js +375 -0
  193. package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +90 -16
  194. package/src/lib/process-execution-broker/linux-generic-bwrap.js +159 -18
  195. package/src/lib/process-execution-broker/macos-mcp-launcher-contract.js +278 -0
  196. package/src/lib/process-execution-broker/macos-mcp-launcher-protocol.json +23 -0
  197. package/src/lib/process-execution-broker/macos-mcp-launcher.c +1497 -0
  198. package/src/lib/process-execution-broker/mcp-fd-entry-bootstrap.js +37 -0
  199. package/src/lib/process-execution-broker/platform-sandbox.js +2330 -279
  200. package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
  201. package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
  202. package/src/lib/process-execution-broker/windows-sandbox.cs +50 -4
  203. package/src/lib/public-ide-capability-manifest.js +3 -0
  204. package/src/lib/remote-approval-bridge.js +123 -17
  205. package/src/lib/remote-membership-authority.js +632 -0
  206. package/src/lib/remote-membership-coordinator.js +2409 -0
  207. package/src/lib/remote-membership-host-store.js +1750 -0
  208. package/src/lib/scoped-permission-store.js +369 -0
  209. package/src/lib/session-anti-rollback-anchor.js +262 -5
  210. package/src/lib/sub-agent-context.js +4 -0
  211. package/src/lib/workflow-definition-contract.js +149 -0
  212. package/src/repl/agent-repl.js +41 -7
  213. package/src/repl/chat-repl.js +2 -0
  214. package/src/repl/clipboard-image.js +735 -16
  215. package/src/repl/ide-status.js +1 -1
  216. package/src/repl/prompt-interactions.js +59 -6
  217. package/src/runtime/agent-core.js +83 -3
  218. package/src/runtime/headless-runner.js +30 -25
  219. package/src/runtime/headless-stream.js +32 -25
  220. package/src/workers/background-agent-keeper.js +498 -0
  221. package/src/workers/background-agent-worker.js +358 -13
  222. package/src/workers/background-turn-bootstrap.js +143 -0
  223. package/src/assets/web-panel/assets/MarkdownRenderer-yySN5YNM.js +0 -1
  224. package/src/assets/web-panel/assets/MobileProjects-DlPwcCbq.js +0 -1
  225. package/src/assets/web-panel/assets/Projects-CMolGhae.js +0 -1
  226. package/src/assets/web-panel/assets/devWarning-S1ld2LwU.js +0 -1
  227. package/src/assets/web-panel/assets/index-Drz6yq0m.js +0 -1
  228. package/src/assets/web-panel/assets/index-uWiUs7S_.js +0 -1
@@ -0,0 +1,495 @@
1
+ /**
2
+ * CLI-owned projection for the Permission & Side-effect Center.
3
+ *
4
+ * Runtime producers persist only bounded resource identifiers: file paths,
5
+ * network origins, executable/runtime names, and credential VARIABLE names.
6
+ * Credential values, URL credentials/query strings, file contents, and full
7
+ * shell commands are never copied into this projection.
8
+ */
9
+
10
+ import { planOpRecovery } from "./side-effect-ledger.js";
11
+ import { redactSecrets } from "./secret-scan.js";
12
+
13
+ export const PERMISSION_SIDE_EFFECT_CENTER_SCHEMA =
14
+ "cc-permission-side-effect-center/v1";
15
+
16
+ const MAX_ITEMS = 100;
17
+ const MAX_RESOURCE_ITEMS = 32;
18
+ const MAX_RESOURCE_LENGTH = 512;
19
+ const MAX_REASON_LENGTH = 500;
20
+ const COVERAGE = new Set(["full", "partial", "none"]);
21
+ const SECRET_NAME =
22
+ /(?:^|[_-])(?:api[_-]?key|access[_-]?key|secret|token|password|passwd|credential|authorization|auth)(?:$|[_-])/i;
23
+ const FILE_KEY =
24
+ /^(?:path|file|file_path|target_path|targetPath|notebook_path|cwd|workspace|workspacePath|repo|repository|project|projectPath)$/i;
25
+ const NETWORK_KEY = /(?:url|uri|endpoint|origin|host)$/i;
26
+ const IRREVERSIBLE_KINDS = new Set([
27
+ "shell",
28
+ "git-push",
29
+ "package-install",
30
+ "network-mutation",
31
+ "payment",
32
+ ]);
33
+
34
+ function bounded(value, limit = MAX_RESOURCE_LENGTH) {
35
+ const text = String(value ?? "").trim();
36
+ return text ? text.slice(0, limit) : "";
37
+ }
38
+
39
+ function addUnique(list, value, limit = MAX_RESOURCE_ITEMS) {
40
+ const text = bounded(value);
41
+ if (!text || list.includes(text) || list.length >= limit) return;
42
+ list.push(text);
43
+ }
44
+
45
+ function redacted(value, limit) {
46
+ return bounded(redactSecrets(String(value ?? "")), limit);
47
+ }
48
+
49
+ function executableFromCommand(value) {
50
+ let command = bounded(value, 4096);
51
+ if (!command) return "";
52
+ // Skip simple POSIX-style leading environment assignments without retaining
53
+ // their values. Complex shell syntax is deliberately not parsed.
54
+ command = command.replace(
55
+ /^(?:[A-Za-z_][A-Za-z0-9_]*=(?:"[^"]*"|'[^']*'|[^\s]+)\s+)*/,
56
+ "",
57
+ );
58
+ const match = command.match(/^(?:"([^"]+)"|'([^']+)'|([^\s;&|]+))/);
59
+ const token = match ? match[1] || match[2] || match[3] : "";
60
+ return bounded(token, 160);
61
+ }
62
+
63
+ function safeNetworkOrigin(value, key) {
64
+ const text = bounded(value, 2048);
65
+ if (!text) return "";
66
+ try {
67
+ const parsed = new URL(text);
68
+ if (parsed.protocol && parsed.host) {
69
+ return `${parsed.protocol}//${parsed.host}`;
70
+ }
71
+ } catch {
72
+ // A host field is still useful when it is not a complete URL.
73
+ }
74
+ if (/host$/i.test(key)) {
75
+ return bounded(text.replace(/^.*@/, "").split(/[/?#]/, 1)[0], 255);
76
+ }
77
+ return "";
78
+ }
79
+
80
+ function safeFileIdentifier(value) {
81
+ const text = bounded(value);
82
+ if (!text) return "";
83
+ if (/^[A-Za-z][A-Za-z0-9+.-]*:\/\//.test(text)) {
84
+ try {
85
+ const parsed = new URL(text);
86
+ if (parsed.protocol !== "file:") return "";
87
+ return bounded(
88
+ `file://${parsed.host}${parsed.pathname}`,
89
+ MAX_RESOURCE_LENGTH,
90
+ );
91
+ } catch {
92
+ return "";
93
+ }
94
+ }
95
+ return text;
96
+ }
97
+
98
+ function normalizedResources(value) {
99
+ const out = { files: [], network: [], processes: [], credentials: [] };
100
+ if (!value || typeof value !== "object" || Array.isArray(value)) return out;
101
+ for (const item of Array.isArray(value.files) ? value.files : []) {
102
+ const networkOrigin = safeNetworkOrigin(item, "url");
103
+ if (networkOrigin) addUnique(out.network, networkOrigin);
104
+ else addUnique(out.files, safeFileIdentifier(item));
105
+ }
106
+ for (const item of Array.isArray(value.network) ? value.network : []) {
107
+ addUnique(out.network, safeNetworkOrigin(item, "origin"));
108
+ }
109
+ for (const item of Array.isArray(value.processes) ? value.processes : []) {
110
+ addUnique(out.processes, executableFromCommand(item));
111
+ }
112
+ for (const item of Array.isArray(value.credentials)
113
+ ? value.credentials
114
+ : []) {
115
+ const name = bounded(item, 128);
116
+ if (
117
+ /^[A-Za-z_][A-Za-z0-9_.-]{0,127}$/.test(name) &&
118
+ SECRET_NAME.test(name)
119
+ ) {
120
+ addUnique(out.credentials, name);
121
+ }
122
+ }
123
+ return out;
124
+ }
125
+
126
+ /** Safely derive actual resource identifiers from one executed tool call. */
127
+ export function collectToolResourceIdentifiers(toolName, args = {}) {
128
+ const resources = normalizedResources(null);
129
+ const tool = bounded(toolName, 128);
130
+ const visit = (value, key = "", depth = 0) => {
131
+ if (depth > 4 || value == null) return;
132
+ if (Array.isArray(value)) {
133
+ value
134
+ .slice(0, MAX_RESOURCE_ITEMS)
135
+ .forEach((entry) => visit(entry, key, depth + 1));
136
+ return;
137
+ }
138
+ if (typeof value === "object") {
139
+ for (const [childKey, childValue] of Object.entries(value).slice(0, 64)) {
140
+ if (SECRET_NAME.test(childKey)) {
141
+ addUnique(resources.credentials, childKey, MAX_RESOURCE_ITEMS);
142
+ continue;
143
+ }
144
+ visit(childValue, childKey, depth + 1);
145
+ }
146
+ return;
147
+ }
148
+ if (typeof value !== "string") return;
149
+ if (SECRET_NAME.test(key)) {
150
+ addUnique(resources.credentials, key, MAX_RESOURCE_ITEMS);
151
+ return;
152
+ }
153
+ if (FILE_KEY.test(key)) {
154
+ const networkOrigin = safeNetworkOrigin(value, "url");
155
+ if (networkOrigin) addUnique(resources.network, networkOrigin);
156
+ else addUnique(resources.files, safeFileIdentifier(value));
157
+ }
158
+ if (NETWORK_KEY.test(key)) {
159
+ addUnique(resources.network, safeNetworkOrigin(value, key));
160
+ }
161
+ };
162
+ visit(args && typeof args === "object" ? args : {});
163
+
164
+ if (tool === "run_shell") {
165
+ addUnique(resources.processes, executableFromCommand(args?.command));
166
+ } else if (tool === "run_code") {
167
+ addUnique(
168
+ resources.processes,
169
+ args?.language ? `runtime:${bounded(args.language, 80)}` : "runtime:code",
170
+ );
171
+ } else if (tool === "git") {
172
+ addUnique(resources.processes, "git");
173
+ } else if (tool === "browser_act") {
174
+ addUnique(resources.processes, "browser");
175
+ }
176
+ return resources;
177
+ }
178
+
179
+ function inferLegacyResources(op) {
180
+ const resources = normalizedResources(op?.meta?.resources);
181
+ if (Object.values(resources).some((items) => items.length > 0)) {
182
+ return resources;
183
+ }
184
+ const key = bounded(op?.key);
185
+ if (/^file-(?:write|delete|move)/.test(String(op?.kind || "")) && key) {
186
+ addUnique(resources.files, key);
187
+ }
188
+ if (op?.kind === "git-push") addUnique(resources.processes, "git");
189
+ if (op?.kind === "shell" && key) {
190
+ addUnique(resources.processes, executableFromCommand(key));
191
+ }
192
+ return resources;
193
+ }
194
+
195
+ function findTurn(turns, op) {
196
+ const turnId = bounded(op?.meta?.turnId, 320);
197
+ if (turnId) return turns.find((turn) => turn?.turnId === turnId) || null;
198
+ const toolUseId = bounded(op?.meta?.toolUseId, 320);
199
+ if (!toolUseId) return null;
200
+ return (
201
+ turns.find(
202
+ (turn) =>
203
+ Array.isArray(turn?.toolCallIds) &&
204
+ turn.toolCallIds.includes(toolUseId),
205
+ ) || null
206
+ );
207
+ }
208
+
209
+ function flattenResources(resources) {
210
+ return Object.entries(resources).flatMap(([kind, values]) =>
211
+ values.map((value) => `${kind}:${value}`),
212
+ );
213
+ }
214
+
215
+ function recoveryForResources({
216
+ resources,
217
+ turnCoverage,
218
+ checkpointId,
219
+ externalOwner = false,
220
+ }) {
221
+ const allResources = flattenResources(resources);
222
+ const coveredResources =
223
+ !externalOwner && turnCoverage === "full" && checkpointId
224
+ ? resources.files.map((value) => `files:${value}`)
225
+ : [];
226
+ const covered = new Set(coveredResources);
227
+ const uncoveredResources = allResources.filter((item) => !covered.has(item));
228
+ let coverage = COVERAGE.has(turnCoverage) ? turnCoverage : "unknown";
229
+ if (allResources.length > 0) {
230
+ if (uncoveredResources.length === 0 && coveredResources.length > 0) {
231
+ coverage = "full";
232
+ } else if (coveredResources.length > 0) {
233
+ coverage = "partial";
234
+ } else {
235
+ coverage = "none";
236
+ }
237
+ }
238
+ return { coverage, coveredResources, uncoveredResources };
239
+ }
240
+
241
+ function normalizeDecision(value, state) {
242
+ const decision = value && typeof value === "object" ? value : null;
243
+ if (!decision) {
244
+ return {
245
+ decision: ["started", "committed", "failed", "unknown"].includes(state)
246
+ ? "executed"
247
+ : "not-executed",
248
+ via: "runtime-admission",
249
+ rule: null,
250
+ source: null,
251
+ reason: "no discrete gate decision was emitted",
252
+ };
253
+ }
254
+ return {
255
+ decision: redacted(decision.decision, 32) || "unknown",
256
+ via: redacted(decision.via, 120) || "policy",
257
+ rule: redacted(decision.rule, 256) || null,
258
+ source: redacted(decision.source, 512) || null,
259
+ reason: redacted(decision.reason, MAX_REASON_LENGTH),
260
+ };
261
+ }
262
+
263
+ function unresolvedResources(kind, resources) {
264
+ const unresolved = [];
265
+ if (
266
+ ["network-mutation", "payment"].includes(kind) &&
267
+ resources.network.length === 0
268
+ ) {
269
+ unresolved.push("network target was not present in the recorded arguments");
270
+ }
271
+ if (kind === "shell" && resources.processes.length === 0) {
272
+ unresolved.push("process identity was not present in the legacy record");
273
+ }
274
+ return unresolved;
275
+ }
276
+
277
+ function projectMcpRecord(record, sessionId, turns) {
278
+ const resources = normalizedResources(null);
279
+ const unresolved = [];
280
+ for (const scope of Array.isArray(record?.resourceScopes)
281
+ ? record.resourceScopes
282
+ : []) {
283
+ const match = bounded(scope).match(/^([A-Za-z][A-Za-z0-9_-]*)[:=](.*)$/);
284
+ if (match && /^(?:file|path|repo|project|workspace)$/i.test(match[1])) {
285
+ const networkOrigin = safeNetworkOrigin(match[2], "url");
286
+ if (networkOrigin) {
287
+ addUnique(resources.network, networkOrigin);
288
+ addUnique(
289
+ unresolved,
290
+ `${match[1]} MCP scope carried a URL; only its origin is shown`,
291
+ );
292
+ } else {
293
+ const identifier = safeFileIdentifier(match[2]);
294
+ if (identifier) addUnique(resources.files, `${match[1]}:${identifier}`);
295
+ }
296
+ } else {
297
+ addUnique(
298
+ unresolved,
299
+ `untyped MCP resource scope (${match?.[1] || "unknown"}) was redacted`,
300
+ );
301
+ }
302
+ }
303
+ for (const scope of Array.isArray(record?.networkScopes)
304
+ ? record.networkScopes
305
+ : []) {
306
+ addUnique(resources.network, safeNetworkOrigin(scope, "origin"));
307
+ }
308
+ const serverName = bounded(record?.serverName, 128) || "unknown-server";
309
+ addUnique(resources.processes, `mcp:${serverName}`);
310
+ const turn = findTurn(turns, {
311
+ meta: {
312
+ turnId: record?.turnId,
313
+ toolUseId: record?.ledgerId,
314
+ },
315
+ });
316
+ const effect = bounded(record?.effectContract?.effect, 32) || "unknown";
317
+ const sideEffecting =
318
+ record?.effectContract?.sideEffecting === true ||
319
+ ["write", "destructive", "unknown"].includes(effect);
320
+ if (
321
+ sideEffecting &&
322
+ resources.files.length === 0 &&
323
+ resources.network.length === 0
324
+ ) {
325
+ unresolved.push("side-effect target was absent from the MCP ledger scopes");
326
+ }
327
+ const checkpointId = bounded(turn?.fileCheckpointId, 320) || null;
328
+ const resourceRecovery = sideEffecting
329
+ ? recoveryForResources({
330
+ resources,
331
+ turnCoverage: COVERAGE.has(turn?.coverage) ? turn.coverage : "none",
332
+ checkpointId,
333
+ // MCP effects are owned by the external host. A local file checkpoint
334
+ // is evidence for the workspace, never proof that the host-owned
335
+ // resource can be restored.
336
+ externalOwner: true,
337
+ })
338
+ : { coverage: "full", coveredResources: [], uncoveredResources: [] };
339
+ const status = bounded(record?.status, 32) || "unknown";
340
+ const idempotent = record?.effectContract?.idempotent === true;
341
+ const recoveryAction =
342
+ status === "completed"
343
+ ? "skip"
344
+ : !sideEffecting
345
+ ? "redo"
346
+ : status === "started"
347
+ ? idempotent
348
+ ? "redo"
349
+ : "inspect"
350
+ : idempotent
351
+ ? "redo"
352
+ : "inspect";
353
+ const startedAt = Date.parse(record?.startedAt || "") || 0;
354
+ const settledAt = Date.parse(record?.settledAt || "") || null;
355
+ return {
356
+ opId: bounded(record?.ledgerId, 320),
357
+ tool: `mcp:${serverName}/${bounded(record?.toolName, 128) || "unknown-tool"}`,
358
+ kind: `mcp-${effect}`,
359
+ state: status,
360
+ idempotent,
361
+ irreversible: sideEffecting && resourceRecovery.coverage !== "full",
362
+ resources,
363
+ unresolvedResources: unresolved,
364
+ decision: {
365
+ decision: ["started", "completed", "failed", "cancelled"].includes(status)
366
+ ? "executed"
367
+ : "unknown",
368
+ via: "mcp-host-admission",
369
+ rule: null,
370
+ source: redacted(record?.effectContract?.source, 512) || null,
371
+ reason:
372
+ record?.effectContract?.trusted === true
373
+ ? "host-authorized effect contract"
374
+ : "untrusted or open-world MCP effect contract",
375
+ },
376
+ callChain: {
377
+ sessionId: bounded(sessionId, 320),
378
+ turnId: bounded(record?.turnId, 320) || null,
379
+ toolUseId: bounded(record?.ledgerId, 320) || null,
380
+ opId: bounded(record?.ledgerId, 320),
381
+ },
382
+ recovery: {
383
+ coverage: resourceRecovery.coverage,
384
+ action: recoveryAction,
385
+ reason:
386
+ recoveryAction === "inspect"
387
+ ? "MCP effect outcome or rollback coverage requires inspection"
388
+ : recoveryAction === "redo"
389
+ ? sideEffecting
390
+ ? "MCP effect contract declares the call idempotent"
391
+ : "host contract records no side effect; the call may be retried"
392
+ : "MCP ledger records a terminal result; do not replay it",
393
+ coveredResources: resourceRecovery.coveredResources,
394
+ uncoveredResources: resourceRecovery.uncoveredResources,
395
+ checkpointId,
396
+ },
397
+ preparedAt: startedAt,
398
+ settledAt,
399
+ };
400
+ }
401
+
402
+ /** Join the actual side-effect ledger with its turn/checkpoint coverage. */
403
+ export function buildPermissionSideEffectCenter({
404
+ sessionId,
405
+ operations = [],
406
+ mcpRecords = [],
407
+ turns = [],
408
+ limit = 50,
409
+ } = {}) {
410
+ const safeLimit = Number.isSafeInteger(Number(limit))
411
+ ? Math.max(1, Math.min(MAX_ITEMS, Number(limit)))
412
+ : 50;
413
+ const opList = (Array.isArray(operations) ? operations : [])
414
+ .slice(-safeLimit)
415
+ .reverse();
416
+ const turnList = Array.isArray(turns) ? turns : [];
417
+ const operationEntries = opList.map((op) => {
418
+ const resources = inferLegacyResources(op);
419
+ const turn = findTurn(turnList, op);
420
+ const turnCoverage = COVERAGE.has(turn?.coverage)
421
+ ? turn.coverage
422
+ : "unknown";
423
+ const checkpointId = bounded(turn?.fileCheckpointId, 320) || null;
424
+ const resourceRecovery = recoveryForResources({
425
+ resources,
426
+ turnCoverage,
427
+ checkpointId,
428
+ });
429
+ const recoveryPlan = planOpRecovery(op);
430
+ const kind = bounded(op?.kind, 80) || "unknown";
431
+ const state = bounded(op?.state, 32) || "unknown";
432
+ const effectMayHaveApplied = ["started", "committed", "unknown"].includes(
433
+ state,
434
+ );
435
+ const irreversible =
436
+ effectMayHaveApplied &&
437
+ (IRREVERSIBLE_KINDS.has(kind) ||
438
+ (["file-write", "file-delete", "file-move"].includes(kind) &&
439
+ resourceRecovery.coverage !== "full"));
440
+ return {
441
+ opId: bounded(op?.opId, 320),
442
+ tool: bounded(op?.meta?.tool, 128) || "unknown",
443
+ kind,
444
+ state,
445
+ idempotent: op?.idempotent === true,
446
+ irreversible,
447
+ resources,
448
+ unresolvedResources: unresolvedResources(kind, resources),
449
+ decision: normalizeDecision(op?.meta?.permissionDecision, state),
450
+ callChain: {
451
+ sessionId: bounded(sessionId, 320),
452
+ turnId: bounded(turn?.turnId || op?.meta?.turnId, 320) || null,
453
+ toolUseId: bounded(op?.meta?.toolUseId, 320) || null,
454
+ opId: bounded(op?.opId, 320),
455
+ },
456
+ recovery: {
457
+ coverage: resourceRecovery.coverage,
458
+ action: recoveryPlan.action,
459
+ reason: bounded(recoveryPlan.reason, MAX_REASON_LENGTH),
460
+ coveredResources: resourceRecovery.coveredResources,
461
+ uncoveredResources: resourceRecovery.uncoveredResources,
462
+ checkpointId,
463
+ },
464
+ preparedAt: Number(op?.preparedAt) || 0,
465
+ settledAt: op?.settledAt == null ? null : Number(op.settledAt) || 0,
466
+ };
467
+ });
468
+ const mcpEntries = (Array.isArray(mcpRecords) ? mcpRecords : [])
469
+ .slice(-safeLimit)
470
+ .map((record) => projectMcpRecord(record, sessionId, turnList));
471
+ const entries = [...operationEntries, ...mcpEntries]
472
+ .sort(
473
+ (left, right) =>
474
+ (right.settledAt || right.preparedAt || 0) -
475
+ (left.settledAt || left.preparedAt || 0) ||
476
+ left.opId.localeCompare(right.opId),
477
+ )
478
+ .slice(0, safeLimit);
479
+
480
+ return {
481
+ schema: PERMISSION_SIDE_EFFECT_CENTER_SCHEMA,
482
+ authority: "cli",
483
+ sessionId: bounded(sessionId, 320),
484
+ entries,
485
+ summary: {
486
+ total: entries.length,
487
+ irreversible: entries.filter((entry) => entry.irreversible).length,
488
+ inspect: entries.filter((entry) => entry.recovery.action === "inspect")
489
+ .length,
490
+ incompleteCoverage: entries.filter(
491
+ (entry) => entry.recovery.coverage !== "full",
492
+ ).length,
493
+ },
494
+ };
495
+ }