chainlesschain 0.162.176 → 0.162.178

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 (260) hide show
  1. package/README.md +10 -0
  2. package/package.json +1 -1
  3. package/src/assets/web-panel/.build-hash +1 -1
  4. package/src/assets/web-panel/assets/{AIOps-BDLu5Elz.js → AIOps-DRftcSue.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-DH5us-CK.js → ActionButton-BFvUaMKR.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-BZ0u8IFG.js → Analytics-C0-Rru4P.js} +3 -3
  7. package/src/assets/web-panel/assets/AppLayout-bx-BCljj.js +9 -0
  8. package/src/assets/web-panel/assets/{Artifacts-Br2YBbh_.js → Artifacts-DAJ8B3Un.js} +1 -1
  9. package/src/assets/web-panel/assets/{Audit-C3C6a482.js → Audit-hOk4L1lr.js} +1 -1
  10. package/src/assets/web-panel/assets/{BackgroundAgents-CzHvebcj.js → BackgroundAgents-3pbDpM9z.js} +1 -1
  11. package/src/assets/web-panel/assets/{Backup-DZNHYDFd.js → Backup-BtziGDn9.js} +1 -1
  12. package/src/assets/web-panel/assets/{BaseInput-VRiC4fIx.js → BaseInput-kmshphJ3.js} +1 -1
  13. package/src/assets/web-panel/assets/{Chat-Cm08WWAD.js → Chat-d7tGSosA.js} +5 -5
  14. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CGHYrugQ.js → ChatBubbleRenderer-p-_PBpX_.js} +1 -1
  15. package/src/assets/web-panel/assets/{Checkbox-DtByk7d7.js → Checkbox-C4Eh4Tz5.js} +1 -1
  16. package/src/assets/web-panel/assets/{Codegen-CphXXOfD.js → Codegen-r7gmhZyA.js} +1 -1
  17. package/src/assets/web-panel/assets/{Col-Hz86TnLR.js → Col-U7mDaGlL.js} +1 -1
  18. package/src/assets/web-panel/assets/{Community-HP03ltpD.js → Community-Bpu8aH1T.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compact-B_N1mqQz.js → Compact-CHb2XBJe.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compliance-CVztRpi8.js → Compliance-Cn_r4dey.js} +1 -1
  21. package/src/assets/web-panel/assets/{Cowork-wUVOyZih.js → Cowork-CdMWfDcz.js} +4 -4
  22. package/src/assets/web-panel/assets/{Cron-DW5TLJKw.js → Cron-BtnREHWy.js} +2 -2
  23. package/src/assets/web-panel/assets/{Crosschain-CrAFGhWH.js → Crosschain-BKI9TSzr.js} +1 -1
  24. package/src/assets/web-panel/assets/{DID-pA-oD8ke.js → DID-pkNubzzJ.js} +2 -2
  25. package/src/assets/web-panel/assets/Dashboard-1rrz1snN.js +3 -0
  26. package/src/assets/web-panel/assets/{Dropdown-EweJcsek.js → Dropdown-DLyFVxDc.js} +1 -1
  27. package/src/assets/web-panel/assets/{EmailListRenderer-C9xVLPG4.js → EmailListRenderer-CtUWfYVq.js} +1 -1
  28. package/src/assets/web-panel/assets/{FamilyGuardDashboard-CDcEEqlu.js → FamilyGuardDashboard-B8eX2Qe4.js} +1 -1
  29. package/src/assets/web-panel/assets/{Federation-DtZda9A_.js → Federation-D8lsDGus.js} +1 -1
  30. package/src/assets/web-panel/assets/{FormItemContext-CiYdcVz3.js → FormItemContext-CRYt_aIw.js} +1 -1
  31. package/src/assets/web-panel/assets/{GenericCardRenderer-DA13uwA0.js → GenericCardRenderer-ClKzY8_N.js} +1 -1
  32. package/src/assets/web-panel/assets/{Git-DzRhZD1O.js → Git-BXj5Dney.js} +2 -2
  33. package/src/assets/web-panel/assets/{Governance-D5RMgOSb.js → Governance-Cm-I8RMz.js} +1 -1
  34. package/src/assets/web-panel/assets/{Inference-BgrPfSNk.js → Inference-CPvbhvgt.js} +1 -1
  35. package/src/assets/web-panel/assets/{KnowledgeGraph-DzjnD571.js → KnowledgeGraph-sYNDZaoi.js} +1 -1
  36. package/src/assets/web-panel/assets/{Logs-BhWzVDtN.js → Logs-BZY_3CRZ.js} +2 -2
  37. package/src/assets/web-panel/assets/{MarkdownRenderer-BDape9cx.js → MarkdownRenderer-up0BW6pv.js} +1 -1
  38. package/src/assets/web-panel/assets/{Marketplace-DJtL5GV7.js → Marketplace-C5MEJ2Qe.js} +1 -1
  39. package/src/assets/web-panel/assets/{McpTools-CZcQygI7.js → McpTools-ihdrn43I.js} +5 -5
  40. package/src/assets/web-panel/assets/{Memory-DUWSDUUu.js → Memory-Br8bPMlh.js} +2 -2
  41. package/src/assets/web-panel/assets/{MobileBridge-BTwq2WKY.js → MobileBridge-BNntgrYW.js} +1 -1
  42. package/src/assets/web-panel/assets/MobileProjects-BdV915mw.js +1 -0
  43. package/src/assets/web-panel/assets/{Mtc-BiGugEQm.js → Mtc-A3wDmlqL.js} +5 -5
  44. package/src/assets/web-panel/assets/{MtcAudit-DY7a6gUe.js → MtcAudit-CF-mBLWM.js} +2 -2
  45. package/src/assets/web-panel/assets/{Multisig-BQbDu_w7.js → Multisig-Iy2k_MSo.js} +3 -3
  46. package/src/assets/web-panel/assets/{NLProgramming-CM2wXTLv.js → NLProgramming-kk0W7HUb.js} +1 -1
  47. package/src/assets/web-panel/assets/{Notes-DI6gGs1v.js → Notes-B5u5t_4S.js} +3 -3
  48. package/src/assets/web-panel/assets/{NotificationSettings-BsZOLWAB.js → NotificationSettings-BN0POf6_.js} +1 -1
  49. package/src/assets/web-panel/assets/OrderTableRenderer-CHkSUrXB.js +1 -0
  50. package/src/assets/web-panel/assets/{Organization-Cds0_tXr.js → Organization-DwWQESuN.js} +4 -4
  51. package/src/assets/web-panel/assets/{Overflow-WunYMD87.js → Overflow-DG6klrcC.js} +1 -1
  52. package/src/assets/web-panel/assets/{P2P-Bo6j4DDv.js → P2P-BwJcKkgZ.js} +2 -2
  53. package/src/assets/web-panel/assets/{PdhVaultBrowser-Bh2XPD5f.js → PdhVaultBrowser-BwOHG0in.js} +5 -5
  54. package/src/assets/web-panel/assets/{Permissions-EMvMMC8N.js → Permissions-CGMXe4TX.js} +4 -4
  55. package/src/assets/web-panel/assets/PersonalDataHub-ziYqg7-A.js +8 -0
  56. package/src/assets/web-panel/assets/{Pipeline-BOx8HOgL.js → Pipeline-BzJfeoGt.js} +1 -1
  57. package/src/assets/web-panel/assets/{Privacy-tBeTVQVM.js → Privacy-DLh3Bblx.js} +1 -1
  58. package/src/assets/web-panel/assets/{ProjectInit-CVYg1W4M.js → ProjectInit-USVWW36c.js} +2 -2
  59. package/src/assets/web-panel/assets/{ProjectSettings-Dvt5I7y1.js → ProjectSettings-CiiOn62h.js} +2 -2
  60. package/src/assets/web-panel/assets/Projects-6V-PNmcA.js +1 -0
  61. package/src/assets/web-panel/assets/{Providers-Ct8xqY-E.js → Providers-CBPWWzpu.js} +1 -1
  62. package/src/assets/web-panel/assets/{QrScannerModal-Cni8Ooja.js → QrScannerModal-QVwoRUq3.js} +1 -1
  63. package/src/assets/web-panel/assets/{QuickAsk-BJVLKdxr.js → QuickAsk-CXnR-2Vn.js} +1 -1
  64. package/src/assets/web-panel/assets/{Recommend-DPG8Rbbm.js → Recommend-ClaNzjmF.js} +1 -1
  65. package/src/assets/web-panel/assets/{RemoteSession-DsdR7dCt.js → RemoteSession-C3rGw8vJ.js} +2 -2
  66. package/src/assets/web-panel/assets/{Reputation-Csg1YM-b.js → Reputation-Ci-OWAoP.js} +1 -1
  67. package/src/assets/web-panel/assets/{Row-D9DoFoEf.js → Row-DRhAwXOS.js} +1 -1
  68. package/src/assets/web-panel/assets/{RssFeed-BsvKrXMS.js → RssFeed-BQLJQ2_y.js} +3 -3
  69. package/src/assets/web-panel/assets/{Search-DFUStfgQ.js → Search-QQUpkfFd.js} +1 -1
  70. package/src/assets/web-panel/assets/{Security-ILg1zxdK.js → Security-DdXKzuKT.js} +4 -4
  71. package/src/assets/web-panel/assets/{Services-Dd41PCaY.js → Services-x2Zh62Qd.js} +2 -2
  72. package/src/assets/web-panel/assets/{Skeleton-Bzo1cN80.js → Skeleton-GdY4KwRz.js} +1 -1
  73. package/src/assets/web-panel/assets/{Skills-BDHh17P0.js → Skills-Bv4tY1Fd.js} +1 -1
  74. package/src/assets/web-panel/assets/{Sla-jl7UTiRY.js → Sla-C3QnM-11.js} +1 -1
  75. package/src/assets/web-panel/assets/{SpeechSettings-BePa-RF6.js → SpeechSettings-Bl3ytvmI.js} +1 -1
  76. package/src/assets/web-panel/assets/{SyncSettings-DiqqDKGZ.js → SyncSettings-Wp9IwTsP.js} +2 -2
  77. package/src/assets/web-panel/assets/{Tasks-DYQ_6lxj.js → Tasks-CF3rIrDe.js} +1 -1
  78. package/src/assets/web-panel/assets/{Templates-JiDeI06L.js → Templates-CGfvVVM9.js} +1 -1
  79. package/src/assets/web-panel/assets/{Tenant-hhgI6zwS.js → Tenant-CVXmwQ3U.js} +1 -1
  80. package/src/assets/web-panel/assets/Terminal-bvwrt03E.js +3 -0
  81. package/src/assets/web-panel/assets/{TimelineRenderer-B8uB5Llk.js → TimelineRenderer-D0g74KhH.js} +1 -1
  82. package/src/assets/web-panel/assets/{Tokens-C3b_6r2z.js → Tokens-BH4IwzlT.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trigger-tIP7HKVe.js → Trigger-DJOpM533.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trust-vjoc11vJ.js → Trust-B43EPRLr.js} +1 -1
  85. package/src/assets/web-panel/assets/{UkeySign-DUPBnGuH.js → UkeySign-BmBFG-em.js} +1 -1
  86. package/src/assets/web-panel/assets/{VideoEditing-CBvhUY5T.js → VideoEditing-n9oJwB8k.js} +1 -1
  87. package/src/assets/web-panel/assets/{Wallet-DUaQ0uA5.js → Wallet-D5QeivHp.js} +4 -4
  88. package/src/assets/web-panel/assets/{WebAuthn-DllSivjE.js → WebAuthn-DcNy7igO.js} +5 -5
  89. package/src/assets/web-panel/assets/{WorkflowEditor-xc8D3uO6.js → WorkflowEditor-BVjc7-5-.js} +1 -1
  90. package/src/assets/web-panel/assets/{chat-BVicU7oA.js → chat-Dy5Tfj3m.js} +1 -1
  91. package/src/assets/web-panel/assets/{colors-DJzLmhLm.js → colors-C4c2CNZU.js} +1 -1
  92. package/src/assets/web-panel/assets/{compact-item-BvYRfThE.js → compact-item-DPa3O5vN.js} +1 -1
  93. package/src/assets/web-panel/assets/{createContext-DGXxCBKR.js → createContext-TLcfNA6_.js} +1 -1
  94. package/src/assets/web-panel/assets/devWarning-BAwdDA_5.js +1 -0
  95. package/src/assets/web-panel/assets/{hasIn-SBDJB1y4.js → hasIn-D41LVFkp.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-D7HimK0M.js → index-0oevYjfT.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-DCdRAgjy.js → index-388pLGJ1.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-BO1itZaY.js → index-B8nLBZbv.js} +3 -3
  99. package/src/assets/web-panel/assets/{index-DvUTDYXX.js → index-BPTGAjee.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-hxTODbM1.js → index-BPtrOBmW.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-wcCL-miV.js → index-BQiIxHBy.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CKyEivf8.js → index-BSM1cHVK.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BJZf9DhV.js → index-BYPr9fkz.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-DHVLJ8q0.js → index-BsQ7Ev6i.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-Cs2rmLFt.js → index-Btk9qLL2.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-z1ZylsLq.js → index-BvmziZSG.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-Cf-O_g_8.js → index-BvopLC_T.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DMarmfrv.js → index-C7xhTVyP.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-CoJAO1Lm.js → index-CNk_ZooP.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-9gdI7uUW.js → index-CQrEHoOG.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Bf-ctERC.js → index-CSxex23J.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-MjC4G09d.js → index-CVjgm992.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-e4fXH_WO.js → index-CWK4zOPe.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-xfluRkCT.js → index-CX0VsoP4.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-DRfiXB_p.js → index-CXl0YPNG.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-d5BVd-cL.js → index-Cip7LWml.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-Dm_77jgR.js → index-Cq_hlWNt.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-YJkzy8ZF.js → index-CzZ49YZL.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-CtwqO5qo.js → index-D2Nkivlm.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-BYqz4Wrr.js → index-DBUgRs4D.js} +1 -1
  121. package/src/assets/web-panel/assets/index-DEjVkdzq.js +1 -0
  122. package/src/assets/web-panel/assets/{index-CdGY9P8a.js → index-DNsBj2Ob.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-DonCnfMr.js → index-Di4X8cfI.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-1SdDS6lR.js → index-DljFsVGI.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-DnjPdvR6.js → index-Korc3QIe.js} +1 -1
  126. package/src/assets/web-panel/assets/index-LMOc5xrS.js +1 -0
  127. package/src/assets/web-panel/assets/{index-VMfwIH5G.js → index-MKZDje0H.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-DKrvvWm4.js → index-OHAfRu_3.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-FxZzRyE1.js → index-WEJr8PL5.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-Crk5NTb0.js → index-WinCp6du.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-DCqRS6da.js → index-Yjr6cqSK.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-BTrBGBJs.js → index-iQ6gtFih.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-lpaGoTH3.js → index-pt3s7yvV.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-CloCgBUR.js → index-tQ3igERQ.js} +1 -1
  135. package/src/assets/web-panel/assets/{initDefaultProps-C1zO1KnY.js → initDefaultProps-BFZu87WZ.js} +1 -1
  136. package/src/assets/web-panel/assets/{motion-CWLtEGmC.js → motion-DJIo7qvt.js} +1 -1
  137. package/src/assets/web-panel/assets/{move-DzD_C3Vm.js → move-Cfr5qknL.js} +1 -1
  138. package/src/assets/web-panel/assets/{mtc-parser-D880PYJl.js → mtc-parser-Bgc-OadH.js} +1 -1
  139. package/src/assets/web-panel/assets/{omit-CFR_z2ov.js → omit-X3WI-TNp.js} +1 -1
  140. package/src/assets/web-panel/assets/{pickAttrs-srIhgrSC.js → pickAttrs-pJhU9IxK.js} +1 -1
  141. package/src/assets/web-panel/assets/{placementArrow-C1rXpibP.js → placementArrow-BNg_Vj3T.js} +1 -1
  142. package/src/assets/web-panel/assets/{responsiveObserve-C30gRcSS.js → responsiveObserve-TeSEGQ5-.js} +1 -1
  143. package/src/assets/web-panel/assets/{slide-CvtKiMfV.js → slide-D_t_P0bv.js} +1 -1
  144. package/src/assets/web-panel/assets/{statusUtils-DNHO7ITG.js → statusUtils-DrrIMwAT.js} +1 -1
  145. package/src/assets/web-panel/assets/{styleChecker-Dt_Sl-g4.js → styleChecker-BjZCuFRm.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFlexGapSupport-Cjev42Gh.js → useFlexGapSupport-rTFdlqdQ.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFs-Baxglj2V.js → useFs-BidCpfLX.js} +1 -1
  148. package/src/assets/web-panel/assets/usePersonalDataHub-C5mHttA9.js +1 -0
  149. package/src/assets/web-panel/assets/{vnode-mIRkdT7o.js → vnode-BrbcRiHZ.js} +1 -1
  150. package/src/assets/web-panel/assets/{zoom-HzI5DlH_.js → zoom-PISX7AkR.js} +1 -1
  151. package/src/assets/web-panel/index.html +1 -1
  152. package/src/commands/__tests__/hub-wechat.test.js +45 -0
  153. package/src/commands/agenda.js +22 -6
  154. package/src/commands/agent.js +3 -3
  155. package/src/commands/background-session.js +16 -6
  156. package/src/commands/batch.js +79 -27
  157. package/src/commands/changelog.js +15 -4
  158. package/src/commands/context.js +33 -1
  159. package/src/commands/eval.js +21 -6
  160. package/src/commands/hook.js +2 -2
  161. package/src/commands/hub.js +473 -39
  162. package/src/commands/init.js +212 -110
  163. package/src/commands/llm.js +22 -6
  164. package/src/commands/loop.js +9 -2
  165. package/src/commands/skill.js +13 -1
  166. package/src/commands/statusline.js +3 -3
  167. package/src/data/changelog.json +53 -5
  168. package/src/gateways/ws/personal-data-hub-protocol.js +22 -2
  169. package/src/harness/background-task-manager.js +18 -6
  170. package/src/harness/background-task-worker.js +11 -18
  171. package/src/harness/golden-transcript.js +3 -0
  172. package/src/harness/mcp-client.js +9 -15
  173. package/src/harness/worktree-isolator.js +18 -21
  174. package/src/index.js +18 -7
  175. package/src/lib/agent-core.js +5 -0
  176. package/src/lib/agent-ipc-bus.js +12 -3
  177. package/src/lib/agent-team/team-worktree.js +28 -6
  178. package/src/lib/agent-worktree.js +20 -19
  179. package/src/lib/approval-authority-store.js +891 -0
  180. package/src/lib/async-hook-supervisor.cjs +134 -24
  181. package/src/lib/async-hook-supervisor.js +47 -0
  182. package/src/lib/background-agent-supervisor.js +35 -12
  183. package/src/lib/background-interaction-resolver.js +399 -54
  184. package/src/lib/background-session-transport.js +3 -1
  185. package/src/lib/background-task-manager.js +5 -1
  186. package/src/lib/changelog.js +57 -0
  187. package/src/lib/chrome-connector.js +6 -2
  188. package/src/lib/claude-code-bridge.js +24 -8
  189. package/src/lib/cli-anything-bridge.js +82 -25
  190. package/src/lib/context-breakdown.js +82 -3
  191. package/src/lib/doctor-checkup.js +18 -6
  192. package/src/lib/eval/tasks.js +25 -31
  193. package/src/lib/event-runtime-host.js +225 -0
  194. package/src/lib/event-runtime-store.js +102 -21
  195. package/src/lib/event-runtime-worker.js +70 -2
  196. package/src/lib/hook-runner.cjs +71 -36
  197. package/src/lib/hook-runner.js +55 -0
  198. package/src/lib/hooks-v2-producers.js +33 -8
  199. package/src/lib/hooks-v2-runtime.js +360 -40
  200. package/src/lib/host-adb-bridge.js +18 -3
  201. package/src/lib/interaction-adapter.js +66 -0
  202. package/src/lib/lsp/__tests__/benchmark.test.js +61 -0
  203. package/src/lib/lsp/__tests__/lsp-client.test.js +6 -1
  204. package/src/lib/lsp/benchmark.js +20 -4
  205. package/src/lib/lsp/lsp-client.js +6 -4
  206. package/src/lib/lsp/lsp-server-registry.js +0 -2
  207. package/src/lib/operation-fingerprint.js +107 -2
  208. package/src/lib/orchestrator.js +8 -2
  209. package/src/lib/packer/pack-update-applier.js +14 -2
  210. package/src/lib/packer/smoke-runner.js +18 -5
  211. package/src/lib/paths.js +1 -1
  212. package/src/lib/pdh-dedicated-batch-collectors.js +124 -0
  213. package/src/lib/personal-data-hub-wiring.js +327 -52
  214. package/src/lib/plugin-monitor-supervisor.js +20 -13
  215. package/src/lib/plugin-runtime/install.js +10 -3
  216. package/src/lib/process-execution-broker/credential-agent.js +954 -111
  217. package/src/lib/process-execution-broker/index.js +369 -85
  218. package/src/lib/process-execution-broker/platform-sandbox.js +320 -140
  219. package/src/lib/provider-http-error.js +94 -0
  220. package/src/lib/remote-approval-bridge.js +222 -26
  221. package/src/lib/repl-bang-memorize.js +10 -2
  222. package/src/lib/repl-goal.js +19 -2
  223. package/src/lib/settings-hook-events.cjs +13 -8
  224. package/src/lib/settings-hook-events.js +20 -0
  225. package/src/lib/side-effect-ledger-store.js +65 -14
  226. package/src/lib/skill-loader.js +215 -12
  227. package/src/lib/skill-packs/generator.js +18 -9
  228. package/src/lib/skill-process-broker.js +85 -0
  229. package/src/lib/slash-commands.js +10 -2
  230. package/src/lib/status-line.cjs +28 -7
  231. package/src/lib/status-line.js +33 -0
  232. package/src/lib/sub-agent-context.js +42 -0
  233. package/src/lib/turn-binding-store.js +64 -15
  234. package/src/lib/turn-binding.js +85 -16
  235. package/src/repl/agent-repl.js +88 -49
  236. package/src/repl/remote-approval.js +13 -13
  237. package/src/repl/repl-turn-binding.js +46 -16
  238. package/src/runtime/agent-core.js +419 -84
  239. package/src/runtime/coding-agent-contract-shared.cjs +16 -0
  240. package/src/runtime/headless-runner.js +172 -44
  241. package/src/runtime/headless-stream.js +221 -11
  242. package/src/runtime/session-slash-commands.js +506 -0
  243. package/src/skills/video-editing/extractors/audio-extractor.js +13 -5
  244. package/src/skills/video-editing/extractors/video-extractor.js +13 -3
  245. package/src/skills/video-editing/media-process.js +20 -0
  246. package/src/skills/video-editing/render/audio-mix.js +13 -3
  247. package/src/skills/video-editing/render/ffmpeg-concat.js +7 -2
  248. package/src/skills/video-editing/render/ffmpeg-extract.js +7 -2
  249. package/src/workers/background-agent-worker.js +76 -40
  250. package/src/assets/web-panel/assets/AppLayout-Duu8xR14.js +0 -9
  251. package/src/assets/web-panel/assets/Dashboard-CXrd5gAw.js +0 -3
  252. package/src/assets/web-panel/assets/MobileProjects-NZvvfDME.js +0 -1
  253. package/src/assets/web-panel/assets/OrderTableRenderer-C48mu09U.js +0 -1
  254. package/src/assets/web-panel/assets/PersonalDataHub-AX3ypUDV.js +0 -9
  255. package/src/assets/web-panel/assets/Projects-Cc7FC9-e.js +0 -1
  256. package/src/assets/web-panel/assets/Terminal-CjTZPa37.js +0 -3
  257. package/src/assets/web-panel/assets/devWarning-BT46Y_QI.js +0 -1
  258. package/src/assets/web-panel/assets/index-B7nuIywP.js +0 -1
  259. package/src/assets/web-panel/assets/index-ycwAfC-i.js +0 -1
  260. package/src/assets/web-panel/assets/usePersonalDataHub-B4NkcLaP.js +0 -1
@@ -1,71 +1,416 @@
1
1
  /**
2
- * background-interaction-resolver — 监听 agent 子进程发来的交互请求,
3
- * 转发给后台会话 transport 并通过 pendingInteractions 追踪回复。
2
+ * Background turn interaction protocol.
4
3
  *
5
- * 当 agent 调用 onPrompt/onApprove 等需要用户交互的方法时,子进程通过 IPC
6
- * 发送 { type: "interaction-request", intId, requestType, prompt, options } 消息。
7
- * 本模块监听这些消息,加入本地 pending map,并广播给所有 attach 客户端。
4
+ * A background worker starts the headless turn with a Node IPC channel. The
5
+ * turn child uses `createBackgroundInteractionClient()` to suspend the active
6
+ * tool call until the worker resolves it. The worker uses
7
+ * `attachInteractionRequestHandler()` to validate the request binding, route
8
+ * it to attach/Desktop/IDE, and return the answer to the same child process.
9
+ *
10
+ * Every response is bound to the original background session, agent, turn,
11
+ * tool call, and monotonically increasing sequence. A stale or cross-session
12
+ * response is ignored by the child and can never resolve another request.
8
13
  */
9
14
 
10
- const INTERACTION_TIMEOUT_MS = 5 * 60 * 1000; // 5 分钟超时
15
+ import { randomUUID } from "node:crypto";
16
+
17
+ export const BACKGROUND_INTERACTION_PROTOCOL_VERSION = 1;
18
+ export const DEFAULT_BACKGROUND_INTERACTION_TIMEOUT_MS = 60_000;
19
+
20
+ const MAX_COMPLETED_RESPONSES = 256;
21
+
22
+ function protocolError(message, code = "INTERACTION_PROTOCOL_ERROR") {
23
+ const error = new Error(message);
24
+ error.code = code;
25
+ return error;
26
+ }
27
+
28
+ function asNullableString(value) {
29
+ if (value === undefined || value === null || value === "") return null;
30
+ return String(value);
31
+ }
32
+
33
+ function normalizeBinding(binding = {}) {
34
+ return {
35
+ backgroundAgentId: asNullableString(binding.backgroundAgentId),
36
+ sessionId: asNullableString(binding.sessionId),
37
+ turnId: asNullableString(binding.turnId),
38
+ toolUseId: asNullableString(binding.toolUseId),
39
+ sequence:
40
+ Number.isSafeInteger(binding.sequence) && binding.sequence > 0
41
+ ? binding.sequence
42
+ : null,
43
+ };
44
+ }
45
+
46
+ function sameBinding(left, right) {
47
+ const a = normalizeBinding(left);
48
+ const b = normalizeBinding(right);
49
+ return (
50
+ a.backgroundAgentId === b.backgroundAgentId &&
51
+ a.sessionId === b.sessionId &&
52
+ a.turnId === b.turnId &&
53
+ a.toolUseId === b.toolUseId &&
54
+ a.sequence === b.sequence
55
+ );
56
+ }
57
+
58
+ function validRequest(message) {
59
+ return (
60
+ message &&
61
+ message.type === "interaction-request" &&
62
+ message.protocolVersion === BACKGROUND_INTERACTION_PROTOCOL_VERSION &&
63
+ typeof message.requestId === "string" &&
64
+ message.requestId.length > 0 &&
65
+ message.requestId.length <= 256 &&
66
+ message.payload &&
67
+ typeof message.payload === "object" &&
68
+ normalizeBinding(message.binding).sequence !== null
69
+ );
70
+ }
71
+
72
+ function sendIpc(target, message, onError = () => {}) {
73
+ if (!target || typeof target.send !== "function" || target.connected === false)
74
+ return false;
75
+ try {
76
+ target.send(message, (error) => {
77
+ if (error) onError(error);
78
+ });
79
+ return true;
80
+ } catch (error) {
81
+ onError(error);
82
+ return false;
83
+ }
84
+ }
11
85
 
12
86
  /**
13
- * 挂载交互请求监听到 agent 子进程。
87
+ * Create the turn-child side of the interaction channel.
14
88
  *
15
- * @param {import('node:child_process').ChildProcess} child - agent 子进程实例
16
- * @param {Map<string, { resolve: Function, reject: Function, timer: NodeJS.Timeout }>} pendingInteractions - 待处理交互映射
17
- * @param {Function} broadcast - 广播消息给所有 attach 客户端的函数
18
- * @returns {Function} 卸载函数,调用后停止监听
89
+ * @param {object} [options]
90
+ * @param {NodeJS.Process|object} [options.processLike]
91
+ * @param {string} [options.backgroundAgentId]
92
+ * @param {string|null} [options.sessionId]
93
+ * @param {string|null} [options.turnId]
94
+ * @param {number} [options.defaultTimeoutMs]
95
+ * @param {()=>string} [options.idFactory]
96
+ */
97
+ export function createBackgroundInteractionClient(options = {}) {
98
+ const processLike = options.processLike || process;
99
+ const backgroundAgentId =
100
+ options.backgroundAgentId ?? processLike?.env?.CC_BACKGROUND_AGENT_ID;
101
+ const sessionId = options.sessionId ?? null;
102
+ const turnId = options.turnId ?? null;
103
+ const defaultTimeoutMs =
104
+ Number.isFinite(options.defaultTimeoutMs) && options.defaultTimeoutMs > 0
105
+ ? options.defaultTimeoutMs
106
+ : DEFAULT_BACKGROUND_INTERACTION_TIMEOUT_MS;
107
+ const idFactory = options.idFactory || randomUUID;
108
+ const enabled =
109
+ typeof backgroundAgentId === "string" &&
110
+ backgroundAgentId.trim() !== "" &&
111
+ typeof processLike?.send === "function";
112
+ const pending = new Map();
113
+ let sequence = 0;
114
+ let closed = false;
115
+
116
+ const removeMessageListener = () => {
117
+ if (typeof processLike?.off === "function") {
118
+ processLike.off("message", onMessage);
119
+ } else if (typeof processLike?.removeListener === "function") {
120
+ processLike.removeListener("message", onMessage);
121
+ }
122
+ };
123
+
124
+ function settle(entry, action, value) {
125
+ if (!entry || entry.settled) return;
126
+ entry.settled = true;
127
+ clearTimeout(entry.timer);
128
+ pending.delete(entry.requestId);
129
+ action(value);
130
+ }
131
+
132
+ function onMessage(message) {
133
+ if (
134
+ !message ||
135
+ message.type !== "interaction-response" ||
136
+ message.protocolVersion !== BACKGROUND_INTERACTION_PROTOCOL_VERSION
137
+ ) {
138
+ return;
139
+ }
140
+ const entry = pending.get(message.requestId);
141
+ if (!entry || !sameBinding(entry.binding, message.binding)) return;
142
+
143
+ if (message.status === "resolved") {
144
+ settle(entry, entry.resolve, message.answer);
145
+ return;
146
+ }
147
+ const error = protocolError(
148
+ message.error?.message || "Background interaction was rejected",
149
+ message.error?.code || "INTERACTION_REJECTED",
150
+ );
151
+ settle(entry, entry.reject, error);
152
+ }
153
+
154
+ if (enabled && typeof processLike.on === "function") {
155
+ processLike.on("message", onMessage);
156
+ }
157
+
158
+ return {
159
+ enabled,
160
+ pendingCount() {
161
+ return pending.size;
162
+ },
163
+ async request(payload = {}) {
164
+ if (!enabled || closed) {
165
+ throw protocolError(
166
+ "Background interaction IPC channel is unavailable",
167
+ "USER_NOT_REACHABLE",
168
+ );
169
+ }
170
+
171
+ sequence += 1;
172
+ const requestId = `${backgroundAgentId}:${idFactory()}`;
173
+ const binding = normalizeBinding({
174
+ backgroundAgentId,
175
+ sessionId: payload.sessionId ?? sessionId,
176
+ turnId: payload.turnId ?? turnId,
177
+ toolUseId: payload.toolUseId,
178
+ sequence,
179
+ });
180
+ const timeoutMs =
181
+ Number.isFinite(payload.timeoutMs) && payload.timeoutMs > 0
182
+ ? payload.timeoutMs
183
+ : defaultTimeoutMs;
184
+
185
+ return new Promise((resolve, reject) => {
186
+ const entry = {
187
+ requestId,
188
+ binding,
189
+ resolve,
190
+ reject,
191
+ timer: null,
192
+ settled: false,
193
+ };
194
+ entry.timer = setTimeout(() => {
195
+ const error = protocolError(
196
+ "User did not respond before the interaction timed out",
197
+ "USER_TIMEOUT",
198
+ );
199
+ sendIpc(processLike, {
200
+ type: "interaction-cancel",
201
+ protocolVersion: BACKGROUND_INTERACTION_PROTOCOL_VERSION,
202
+ requestId,
203
+ binding,
204
+ reason: "timeout",
205
+ });
206
+ settle(entry, reject, error);
207
+ }, timeoutMs);
208
+ entry.timer.unref?.();
209
+ pending.set(requestId, entry);
210
+
211
+ const sent = sendIpc(
212
+ processLike,
213
+ {
214
+ type: "interaction-request",
215
+ protocolVersion: BACKGROUND_INTERACTION_PROTOCOL_VERSION,
216
+ requestId,
217
+ binding,
218
+ payload: {
219
+ kind: payload.kind || "question",
220
+ question: String(payload.question || payload.prompt || ""),
221
+ options: Array.isArray(payload.options) ? payload.options : null,
222
+ multiSelect: payload.multiSelect === true,
223
+ defaultValue: payload.defaultValue,
224
+ timeoutMs,
225
+ policyDigest: asNullableString(payload.policyDigest),
226
+ },
227
+ },
228
+ (error) => {
229
+ settle(
230
+ entry,
231
+ reject,
232
+ protocolError(
233
+ `Failed to send background interaction: ${error.message}`,
234
+ "INTERACTION_CHANNEL_ERROR",
235
+ ),
236
+ );
237
+ },
238
+ );
239
+ if (!sent) {
240
+ settle(
241
+ entry,
242
+ reject,
243
+ protocolError(
244
+ "Background interaction IPC channel is unavailable",
245
+ "USER_NOT_REACHABLE",
246
+ ),
247
+ );
248
+ }
249
+ });
250
+ },
251
+ close(reason = "Background interaction channel closed") {
252
+ if (closed) return;
253
+ closed = true;
254
+ removeMessageListener();
255
+ for (const entry of [...pending.values()]) {
256
+ settle(
257
+ entry,
258
+ entry.reject,
259
+ protocolError(reason, "INTERACTION_CHANNEL_CLOSED"),
260
+ );
261
+ }
262
+ },
263
+ };
264
+ }
265
+
266
+ /**
267
+ * Attach the worker side of the interaction channel to one turn child.
268
+ *
269
+ * @param {import("node:child_process").ChildProcess|object} child
270
+ * @param {(payload:object, request:object, context:{signal:AbortSignal})=>Promise<any>|any} resolveRequest
271
+ * @param {object} [options]
272
+ * @param {string|null} [options.backgroundAgentId]
273
+ * @param {string|null} [options.sessionId]
274
+ * @returns {()=>void} detach function
19
275
  */
20
276
  export function attachInteractionRequestHandler(
21
277
  child,
22
- pendingInteractions,
23
- broadcast,
278
+ resolveRequest,
279
+ options = {},
24
280
  ) {
25
- if (!child) {
26
- return () => {};
27
- }
281
+ if (!child || typeof child.on !== "function") return () => {};
28
282
 
29
- const handler = (message) => {
30
- if (!message || typeof message !== "object") return;
31
- if (message.type !== "interaction-request") return;
32
-
33
- const { intId, requestType, prompt, options = {} } = message;
34
- if (!intId) return;
35
-
36
- // 加入 pending 映射,设置超时
37
- const timer = setTimeout(() => {
38
- const entry = pendingInteractions.get(intId);
39
- if (!entry) return;
40
- pendingInteractions.delete(intId);
41
- // 超时返回默认值:confirm 返回 false,其他返回 null
42
- const defaultAnswer = requestType === "confirm" ? false : null;
43
- entry.resolve(defaultAnswer);
44
- broadcast?.({
45
- type: "interaction-timeout",
46
- intId,
47
- });
48
- }, INTERACTION_TIMEOUT_MS);
49
- // 不保持事件循环存活
50
- timer.unref?.();
51
-
52
- // 这里不存 resolve/reject — 调用方 (worker) 已经在 agentAskUser 中存了
53
- // 我们只负责广播给 attach 客户端
54
- // 但为了超时能触发 worker 的 resolve,需要把 entry 透传?不,worker 自己存 entry
55
- // 只需要广播消息即可
56
- broadcast?.({
57
- type: "interaction_request",
58
- intId,
59
- requestType,
60
- prompt,
61
- options,
62
- });
283
+ const inflight = new Map();
284
+ const completed = new Map();
285
+ let detached = false;
286
+
287
+ const rememberCompleted = (requestId, response) => {
288
+ completed.set(requestId, response);
289
+ if (completed.size > MAX_COMPLETED_RESPONSES) {
290
+ completed.delete(completed.keys().next().value);
291
+ }
292
+ };
293
+
294
+ const sendResponse = (response) => {
295
+ if (!detached) sendIpc(child, response);
63
296
  };
64
297
 
65
- child.on("message", handler);
298
+ const rejectRequest = (message, code, detail) => {
299
+ const response = {
300
+ type: "interaction-response",
301
+ protocolVersion: BACKGROUND_INTERACTION_PROTOCOL_VERSION,
302
+ requestId:
303
+ typeof message?.requestId === "string" ? message.requestId : "",
304
+ binding: normalizeBinding(message?.binding),
305
+ status: "rejected",
306
+ error: { code, message: detail },
307
+ };
308
+ if (response.requestId) rememberCompleted(response.requestId, response);
309
+ sendResponse(response);
310
+ };
311
+
312
+ const onMessage = (message) => {
313
+ if (
314
+ message?.type === "interaction-cancel" &&
315
+ message.protocolVersion === BACKGROUND_INTERACTION_PROTOCOL_VERSION
316
+ ) {
317
+ const active = inflight.get(message.requestId);
318
+ if (active && sameBinding(active.binding, message.binding)) {
319
+ inflight.delete(message.requestId);
320
+ active.controller.abort(message.reason || "cancelled");
321
+ }
322
+ return;
323
+ }
324
+ if (message?.type !== "interaction-request") return;
325
+ if (!validRequest(message)) {
326
+ rejectRequest(
327
+ message,
328
+ "INVALID_INTERACTION_REQUEST",
329
+ "Malformed background interaction request",
330
+ );
331
+ return;
332
+ }
333
+
334
+ const binding = normalizeBinding(message.binding);
335
+ const expectedAgentId = asNullableString(options.backgroundAgentId);
336
+ const expectedSessionId = asNullableString(options.sessionId);
337
+ if (
338
+ (expectedAgentId &&
339
+ binding.backgroundAgentId !== expectedAgentId) ||
340
+ (expectedSessionId && binding.sessionId !== expectedSessionId)
341
+ ) {
342
+ rejectRequest(
343
+ message,
344
+ "INTERACTION_BINDING_MISMATCH",
345
+ "Background interaction does not belong to this worker/session",
346
+ );
347
+ return;
348
+ }
349
+
350
+ const prior = completed.get(message.requestId);
351
+ if (prior) {
352
+ sendResponse(prior);
353
+ return;
354
+ }
355
+ if (inflight.has(message.requestId)) return;
356
+
357
+ const controller = new AbortController();
358
+ inflight.set(message.requestId, { binding, controller });
359
+ Promise.resolve()
360
+ .then(() =>
361
+ resolveRequest(message.payload, message, {
362
+ signal: controller.signal,
363
+ }),
364
+ )
365
+ .then(
366
+ (answer) => {
367
+ const active = inflight.get(message.requestId);
368
+ if (!active || controller.signal.aborted) return;
369
+ inflight.delete(message.requestId);
370
+ const response = {
371
+ type: "interaction-response",
372
+ protocolVersion: BACKGROUND_INTERACTION_PROTOCOL_VERSION,
373
+ requestId: message.requestId,
374
+ binding,
375
+ status: "resolved",
376
+ answer,
377
+ };
378
+ rememberCompleted(message.requestId, response);
379
+ sendResponse(response);
380
+ },
381
+ (error) => {
382
+ const active = inflight.get(message.requestId);
383
+ if (!active || controller.signal.aborted) return;
384
+ inflight.delete(message.requestId);
385
+ const response = {
386
+ type: "interaction-response",
387
+ protocolVersion: BACKGROUND_INTERACTION_PROTOCOL_VERSION,
388
+ requestId: message.requestId,
389
+ binding,
390
+ status: "rejected",
391
+ error: {
392
+ code: error?.code || "INTERACTION_REJECTED",
393
+ message: error?.message || String(error),
394
+ },
395
+ };
396
+ rememberCompleted(message.requestId, response);
397
+ sendResponse(response);
398
+ },
399
+ );
400
+ };
66
401
 
67
- // 返回卸载函数
68
- return () => {
69
- child.off("message", handler);
402
+ child.on("message", onMessage);
403
+ const detach = () => {
404
+ if (detached) return;
405
+ detached = true;
406
+ if (typeof child.off === "function") child.off("message", onMessage);
407
+ else child.removeListener?.("message", onMessage);
408
+ for (const active of inflight.values()) {
409
+ active.controller.abort("child detached");
410
+ }
411
+ inflight.clear();
70
412
  };
413
+ child.once?.("exit", detach);
414
+ child.once?.("disconnect", detach);
415
+ return detach;
71
416
  }
@@ -261,12 +261,13 @@ export function startBackgroundSessionServer(opts) {
261
261
  broadcast: (message) => {
262
262
  for (const socket of clients) writeMessage(socket, message);
263
263
  },
264
- broadcastInteractionRequest: (intId, payload) => {
264
+ broadcastInteractionRequest: (intId, payload, binding = null) => {
265
265
  for (const socket of clients)
266
266
  writeMessage(socket, {
267
267
  type: "interaction_request",
268
268
  intId,
269
269
  requestId: intId,
270
+ binding,
270
271
  question:
271
272
  payload.question || payload.prompt || "Agent needs your input",
272
273
  prompt: payload.question || payload.prompt || "",
@@ -274,6 +275,7 @@ export function startBackgroundSessionServer(opts) {
274
275
  options: payload.options || null,
275
276
  multiSelect: payload.multiSelect || false,
276
277
  defaultValue: payload.defaultValue,
278
+ policyDigest: payload.policyDigest || null,
277
279
  });
278
280
  },
279
281
  close: () =>
@@ -1 +1,5 @@
1
- export { TaskStatus, BackgroundTaskManager } from "../harness/background-task-manager.js";
1
+ export {
2
+ _deps,
3
+ TaskStatus,
4
+ BackgroundTaskManager,
5
+ } from "../harness/background-task-manager.js";
@@ -91,6 +91,41 @@ export function compareSemver(a, b) {
91
91
  return 0;
92
92
  }
93
93
 
94
+ /**
95
+ * Whether a parsed changelog documents an exact CLI package version.
96
+ *
97
+ * A product block can cover more than one CLI release (notably the root
98
+ * `Unreleased` block), so check both its primary `cliVersion` and the complete
99
+ * `cliVersions` set. This is also the publish-time stale-artifact guard.
100
+ */
101
+ export function hasCliVersion(releases, version) {
102
+ if (!version || !Array.isArray(releases)) return false;
103
+ return releases.some(
104
+ (release) =>
105
+ release?.cliVersion === version ||
106
+ (Array.isArray(release?.cliVersions) &&
107
+ release.cliVersions.includes(version)),
108
+ );
109
+ }
110
+
111
+ /** Highest exact CLI version documented by the parsed release list. */
112
+ export function latestCliVersion(releases) {
113
+ if (!Array.isArray(releases)) return null;
114
+ const versions = releases.flatMap((release) => {
115
+ const covered = Array.isArray(release?.cliVersions)
116
+ ? release.cliVersions
117
+ : [];
118
+ return release?.cliVersion ? [...covered, release.cliVersion] : covered;
119
+ });
120
+ return versions.length === 0
121
+ ? null
122
+ : versions.reduce(
123
+ (latest, version) =>
124
+ compareSemver(version, latest) > 0 ? version : latest,
125
+ versions[0],
126
+ );
127
+ }
128
+
94
129
  /**
95
130
  * Parse a raw CHANGELOG.md string into CLI-focused release entries.
96
131
  *
@@ -135,6 +170,28 @@ export function parseChangelog(md) {
135
170
  const sections = extractCliSections(block.lines, block.header);
136
171
  if (!sections) continue;
137
172
 
173
+ // The root changelog keeps multiple still-unreleased CLI versions as
174
+ // sibling `###` sections. Treating the whole `## [Unreleased]` block as
175
+ // one record collapses many CLI releases into a single entry and makes
176
+ // `-n 5` mean five product blocks instead of five CLI versions.
177
+ if (parsed.version.toLowerCase() === "unreleased") {
178
+ for (const section of sections) {
179
+ const sectionText = `${section.heading}\n${section.body}`;
180
+ const sectionVersions = extractCliVersions(sectionText);
181
+ if (!sectionVersions.primary) continue;
182
+ const dateMatch = sectionText.match(/\b(\d{4}-\d{2}-\d{2})\b/);
183
+ releases.push({
184
+ productVersion: null,
185
+ cliVersion: sectionVersions.primary,
186
+ cliVersions: sectionVersions.all.sort(compareSemver),
187
+ date: dateMatch ? dateMatch[1] : null,
188
+ title: "",
189
+ sections: [section],
190
+ });
191
+ }
192
+ continue;
193
+ }
194
+
138
195
  releases.push({
139
196
  productVersion: parsed.version,
140
197
  cliVersion: primary,
@@ -26,11 +26,11 @@
26
26
  * Chrome when done. This is the same trade Claude-Code's Chrome connector
27
27
  * makes.
28
28
  */
29
- import { spawn } from "child_process";
30
29
  import fs from "fs";
31
30
  import os from "os";
32
31
  import path from "path";
33
32
  import http from "http";
33
+ import executionBroker from "./process-execution-broker/index.js";
34
34
 
35
35
  export const DEFAULT_CDP_PORT = 9222;
36
36
 
@@ -69,7 +69,7 @@ export const DEFAULT_DOM_CAP = 150000;
69
69
 
70
70
  const _deps = {
71
71
  fs,
72
- spawn,
72
+ spawn: executionBroker.spawn.bind(executionBroker),
73
73
  homedir: () => os.homedir(),
74
74
  platform: () => process.platform,
75
75
  env: () => process.env,
@@ -215,6 +215,10 @@ export function launchChrome(opts = {}) {
215
215
  detached: true,
216
216
  stdio: "ignore",
217
217
  windowsHide: false,
218
+ origin: "chrome-connector:launch",
219
+ policy: "allow",
220
+ scope: "browser",
221
+ shell: false,
218
222
  });
219
223
  child.unref();
220
224
  return { ok: true, executable, args, pid: child.pid };
@@ -13,11 +13,14 @@
13
13
  * ], { cwd: "/path/to/project" });
14
14
  */
15
15
 
16
- import { spawn, execSync } from "child_process";
17
16
  import { EventEmitter } from "events";
17
+ import executionBroker from "./process-execution-broker/index.js";
18
18
 
19
19
  /* ---------- _deps injection (Vitest CJS mock pattern) ---------- */
20
- export const _deps = { spawn, execSync };
20
+ export const _deps = {
21
+ spawn: executionBroker.spawn.bind(executionBroker),
22
+ execSync: executionBroker.execSync.bind(executionBroker),
23
+ };
21
24
 
22
25
  // ─── Agent status constants ───────────────────────────────────────
23
26
 
@@ -36,6 +39,19 @@ export const AGENT_STATUS = {
36
39
  // only thing _parseStreamJson needs — is at the end.
37
40
  export const MAX_AGENT_OUTPUT_BYTES = 32 * 1024 * 1024;
38
41
 
42
+ function detectCliVersion(command) {
43
+ return _deps
44
+ .execSync(`${command} --version`, {
45
+ encoding: "utf-8",
46
+ timeout: 5000,
47
+ origin: `claude-code-bridge:detect-${command}`,
48
+ policy: "allow",
49
+ scope: "orchestrator",
50
+ shell: true,
51
+ })
52
+ .trim();
53
+ }
54
+
39
55
  // ─── Detection ───────────────────────────────────────────────────
40
56
 
41
57
  /**
@@ -44,9 +60,7 @@ export const MAX_AGENT_OUTPUT_BYTES = 32 * 1024 * 1024;
44
60
  */
45
61
  export function detectClaudeCode() {
46
62
  try {
47
- const version = _deps
48
- .execSync("claude --version", { encoding: "utf-8", timeout: 5000 })
49
- .trim();
63
+ const version = detectCliVersion("claude");
50
64
  return { found: true, version };
51
65
  } catch (_err) {
52
66
  return { found: false };
@@ -59,9 +73,7 @@ export function detectClaudeCode() {
59
73
  */
60
74
  export function detectCodex() {
61
75
  try {
62
- const version = _deps
63
- .execSync("codex --version", { encoding: "utf-8", timeout: 5000 })
64
- .trim();
76
+ const version = detectCliVersion("codex");
65
77
  return { found: true, version };
66
78
  } catch (_err) {
67
79
  return { found: false };
@@ -152,6 +164,10 @@ export class ClaudeCodeAgent extends EventEmitter {
152
164
  cwd,
153
165
  env: { ...process.env },
154
166
  windowsHide: true,
167
+ origin: "claude-code-bridge:agent",
168
+ policy: "allow",
169
+ scope: "orchestrator",
170
+ shell: false,
155
171
  });
156
172
  this._proc = proc;
157
173