chainlesschain 0.162.174 → 0.162.176

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 (281) hide show
  1. package/package.json +10 -10
  2. package/src/assets/web-panel/assets/{AIOps-Dcl-X1Hw.js → AIOps-BDLu5Elz.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-ClMh9HzT.js → ActionButton-DH5us-CK.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-DPj0rSQ5.js → Analytics-BZ0u8IFG.js} +3 -3
  5. package/src/assets/web-panel/assets/AppLayout-Duu8xR14.js +9 -0
  6. package/src/assets/web-panel/assets/{Artifacts-L8781rE8.js → Artifacts-Br2YBbh_.js} +1 -1
  7. package/src/assets/web-panel/assets/{Audit-CffB6WIP.js → Audit-C3C6a482.js} +1 -1
  8. package/src/assets/web-panel/assets/{BackgroundAgents-BkLhayyY.js → BackgroundAgents-CzHvebcj.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-BQnwFI78.js → Backup-DZNHYDFd.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-xuUGHQch.js → BaseInput-VRiC4fIx.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-feQXwWrg.js → Chat-Cm08WWAD.js} +5 -5
  12. package/src/assets/web-panel/assets/ChatBubbleRenderer-CGHYrugQ.js +1 -0
  13. package/src/assets/web-panel/assets/{Checkbox-DVaIiUGW.js → Checkbox-DtByk7d7.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-D2kEnzeU.js → Codegen-CphXXOfD.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-azDoyusS.js → Col-Hz86TnLR.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-OZdnPWM5.js → Community-HP03ltpD.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-VDMvBN-C.js → Compact-B_N1mqQz.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-CPJ_zgQ1.js → Compliance-CVztRpi8.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-iRBwcsOA.js → Cowork-wUVOyZih.js} +4 -4
  20. package/src/assets/web-panel/assets/{Cron-DrxrspUz.js → Cron-DW5TLJKw.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-D-rkAZXF.js → Crosschain-CrAFGhWH.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-5Pp1Xnmr.js → DID-pA-oD8ke.js} +2 -2
  23. package/src/assets/web-panel/assets/Dashboard-CXrd5gAw.js +3 -0
  24. package/src/assets/web-panel/assets/{Dropdown-BWj_E0Ie.js → Dropdown-EweJcsek.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-BT-wgSEh.js → EmailListRenderer-C9xVLPG4.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-1PzH23pa.js → FamilyGuardDashboard-CDcEEqlu.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-BxMIXGC6.js → Federation-DtZda9A_.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-CyJobBln.js → FormItemContext-CiYdcVz3.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-YkjFuQTN.js → GenericCardRenderer-DA13uwA0.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-C2a98Wp_.js → Git-DzRhZD1O.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-DKL3Fl84.js → Governance-D5RMgOSb.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-BJ2cQC_3.js → Inference-BgrPfSNk.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-DBAsOngt.js → KnowledgeGraph-DzjnD571.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-COt8g9LO.js → Logs-BhWzVDtN.js} +2 -2
  35. package/src/assets/web-panel/assets/{MarkdownRenderer-3Lfht1Fd.js → MarkdownRenderer-BDape9cx.js} +1 -1
  36. package/src/assets/web-panel/assets/{Marketplace-C9Zk9Pb2.js → Marketplace-DJtL5GV7.js} +1 -1
  37. package/src/assets/web-panel/assets/{McpTools-DDWDFWPO.js → McpTools-CZcQygI7.js} +5 -5
  38. package/src/assets/web-panel/assets/{Memory-BRmVye_o.js → Memory-DUWSDUUu.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileBridge-CppBbWpD.js → MobileBridge-BTwq2WKY.js} +1 -1
  40. package/src/assets/web-panel/assets/MobileProjects-NZvvfDME.js +1 -0
  41. package/src/assets/web-panel/assets/{Mtc-CcWpeGa6.js → Mtc-BiGugEQm.js} +6 -6
  42. package/src/assets/web-panel/assets/{MtcAudit-BcllEq0K.js → MtcAudit-DY7a6gUe.js} +4 -4
  43. package/src/assets/web-panel/assets/{Multisig-BFD1CarL.js → Multisig-BQbDu_w7.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-QNXXYvjz.js → NLProgramming-CM2wXTLv.js} +1 -1
  45. package/src/assets/web-panel/assets/{Notes-07YwgQVy.js → Notes-DI6gGs1v.js} +4 -4
  46. package/src/assets/web-panel/assets/{NotificationSettings-bOccEInE.js → NotificationSettings-BsZOLWAB.js} +1 -1
  47. package/src/assets/web-panel/assets/{OrderTableRenderer-DlRi29WL.js → OrderTableRenderer-C48mu09U.js} +1 -1
  48. package/src/assets/web-panel/assets/{Organization-CBaezzEr.js → Organization-Cds0_tXr.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-Bl5NohFO.js → Overflow-WunYMD87.js} +1 -1
  50. package/src/assets/web-panel/assets/{P2P-CLMal9Aw.js → P2P-Bo6j4DDv.js} +2 -2
  51. package/src/assets/web-panel/assets/{PdhVaultBrowser-CGO0NITk.js → PdhVaultBrowser-Bh2XPD5f.js} +3 -3
  52. package/src/assets/web-panel/assets/{Permissions-CPSw48E2.js → Permissions-EMvMMC8N.js} +3 -3
  53. package/src/assets/web-panel/assets/{PersonalDataHub-CDM5n134.js → PersonalDataHub-AX3ypUDV.js} +2 -2
  54. package/src/assets/web-panel/assets/{Pipeline-BdsqG7WV.js → Pipeline-BOx8HOgL.js} +1 -1
  55. package/src/assets/web-panel/assets/{Privacy-B6L4E-M7.js → Privacy-tBeTVQVM.js} +1 -1
  56. package/src/assets/web-panel/assets/{ProjectInit-DXPyZKRs.js → ProjectInit-CVYg1W4M.js} +2 -2
  57. package/src/assets/web-panel/assets/{ProjectSettings-BrCC3xYT.js → ProjectSettings-Dvt5I7y1.js} +2 -2
  58. package/src/assets/web-panel/assets/{Projects-BYmuHC2q.js → Projects-Cc7FC9-e.js} +1 -1
  59. package/src/assets/web-panel/assets/{Providers-CbCe2eUl.js → Providers-Ct8xqY-E.js} +1 -1
  60. package/src/assets/web-panel/assets/{QrScannerModal-DkukgCrR.js → QrScannerModal-Cni8Ooja.js} +1 -1
  61. package/src/assets/web-panel/assets/{QuickAsk-D-htOrV8.js → QuickAsk-BJVLKdxr.js} +1 -1
  62. package/src/assets/web-panel/assets/{Recommend-Bm7SIfzu.js → Recommend-DPG8Rbbm.js} +1 -1
  63. package/src/assets/web-panel/assets/{RemoteSession-C9rP-iMc.js → RemoteSession-DsdR7dCt.js} +2 -2
  64. package/src/assets/web-panel/assets/{Reputation-kGlUgbsl.js → Reputation-Csg1YM-b.js} +1 -1
  65. package/src/assets/web-panel/assets/{Row-PBupbbUA.js → Row-D9DoFoEf.js} +1 -1
  66. package/src/assets/web-panel/assets/{RssFeed-njlwKUGK.js → RssFeed-BsvKrXMS.js} +2 -2
  67. package/src/assets/web-panel/assets/{Search-DLdEmgBw.js → Search-DFUStfgQ.js} +1 -1
  68. package/src/assets/web-panel/assets/{Security-SXGPSHdu.js → Security-ILg1zxdK.js} +4 -4
  69. package/src/assets/web-panel/assets/{Services-CuFGnNsb.js → Services-Dd41PCaY.js} +2 -2
  70. package/src/assets/web-panel/assets/{Skeleton-CtUC0mDa.js → Skeleton-Bzo1cN80.js} +1 -1
  71. package/src/assets/web-panel/assets/{Skills-P1qgOVFn.js → Skills-BDHh17P0.js} +1 -1
  72. package/src/assets/web-panel/assets/{Sla-CsppE8YV.js → Sla-jl7UTiRY.js} +1 -1
  73. package/src/assets/web-panel/assets/{SpeechSettings-Cq1oG56m.js → SpeechSettings-BePa-RF6.js} +1 -1
  74. package/src/assets/web-panel/assets/{SyncSettings-DdKW6V-C.js → SyncSettings-DiqqDKGZ.js} +2 -2
  75. package/src/assets/web-panel/assets/{Tasks-BCc9san5.js → Tasks-DYQ_6lxj.js} +1 -1
  76. package/src/assets/web-panel/assets/{Templates-CcHC1dMA.js → Templates-JiDeI06L.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tenant-CA4PqU22.js → Tenant-hhgI6zwS.js} +1 -1
  78. package/src/assets/web-panel/assets/Terminal-CjTZPa37.js +3 -0
  79. package/src/assets/web-panel/assets/{TimelineRenderer-DHWTSvOy.js → TimelineRenderer-B8uB5Llk.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tokens-Ddz-P_yh.js → Tokens-C3b_6r2z.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trigger-ePmrmLZ1.js → Trigger-tIP7HKVe.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trust-DmuK1CCE.js → Trust-vjoc11vJ.js} +1 -1
  83. package/src/assets/web-panel/assets/{UkeySign-CqqBuRrT.js → UkeySign-DUPBnGuH.js} +1 -1
  84. package/src/assets/web-panel/assets/{VideoEditing-BGlR3uWM.js → VideoEditing-CBvhUY5T.js} +1 -1
  85. package/src/assets/web-panel/assets/{Wallet-Ba_Qx6Ga.js → Wallet-DUaQ0uA5.js} +4 -4
  86. package/src/assets/web-panel/assets/{WebAuthn-29neXKt2.js → WebAuthn-DllSivjE.js} +5 -5
  87. package/src/assets/web-panel/assets/{WorkflowEditor-lD0lR0UQ.js → WorkflowEditor-xc8D3uO6.js} +1 -1
  88. package/src/assets/web-panel/assets/{chat-B3stH01u.js → chat-BVicU7oA.js} +1 -1
  89. package/src/assets/web-panel/assets/{colors-Czly56MN.js → colors-DJzLmhLm.js} +1 -1
  90. package/src/assets/web-panel/assets/{compact-item-C0TkbkAJ.js → compact-item-BvYRfThE.js} +1 -1
  91. package/src/assets/web-panel/assets/{createContext-BJmpSlf1.js → createContext-DGXxCBKR.js} +1 -1
  92. package/src/assets/web-panel/assets/devWarning-BT46Y_QI.js +1 -0
  93. package/src/assets/web-panel/assets/{hasIn-D1q-zw7u.js → hasIn-SBDJB1y4.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-DV-twjNO.js → index-1SdDS6lR.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-B-kTvMq7.js → index-9gdI7uUW.js} +1 -1
  96. package/src/assets/web-panel/assets/index-B7nuIywP.js +1 -0
  97. package/src/assets/web-panel/assets/{index-Bm_-RKal.js → index-BJZf9DhV.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-CQftlZn-.js → index-BO1itZaY.js} +3 -3
  99. package/src/assets/web-panel/assets/{index-Dw3L_smW.js → index-BTrBGBJs.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-C7sFKQ53.js → index-BYqz4Wrr.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DlvsSuBC.js → index-Bf-ctERC.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-ChESIe5r.js → index-CKyEivf8.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DaqEHaCg.js → index-CdGY9P8a.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-DZeoKL6t.js → index-Cf-O_g_8.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-XWV8JWMc.js → index-CloCgBUR.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-CpMIdPJ0.js → index-CoJAO1Lm.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-CgS8XUBU.js → index-Crk5NTb0.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DmUta2lw.js → index-Cs2rmLFt.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Dpz_7sf-.js → index-CtwqO5qo.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-DRcQsPez.js → index-D7HimK0M.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-BEt2-3x5.js → index-DCdRAgjy.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-CHvPlzWJ.js → index-DCqRS6da.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-BDHXx65P.js → index-DHVLJ8q0.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-K4YaPDOn.js → index-DKrvvWm4.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-C1pOqU7D.js → index-DMarmfrv.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-DAhrn9EJ.js → index-DRfiXB_p.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-cPjWjvmW.js → index-Dm_77jgR.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-C27TnOoT.js → index-DnjPdvR6.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-upY9rkGZ.js → index-DonCnfMr.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CbvNJUwu.js → index-DvUTDYXX.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-BVwJ3jht.js → index-FxZzRyE1.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DIF6XHIi.js → index-MjC4G09d.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-B8KqsomG.js → index-VMfwIH5G.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-8GKykbS4.js → index-YJkzy8ZF.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-DpGs96FC.js → index-d5BVd-cL.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-DO8xOwxi.js → index-e4fXH_WO.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-Cu_4HaUS.js → index-hxTODbM1.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-Cf7Gr3NG.js → index-lpaGoTH3.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-DBqAm8es.js → index-wcCL-miV.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-ZDUhX41Z.js → index-xfluRkCT.js} +1 -1
  131. package/src/assets/web-panel/assets/index-ycwAfC-i.js +1 -0
  132. package/src/assets/web-panel/assets/{index-z8ATo2aQ.js → index-z1ZylsLq.js} +1 -1
  133. package/src/assets/web-panel/assets/{initDefaultProps-QWEXi6-t.js → initDefaultProps-C1zO1KnY.js} +1 -1
  134. package/src/assets/web-panel/assets/{motion-BfrQwvV1.js → motion-CWLtEGmC.js} +1 -1
  135. package/src/assets/web-panel/assets/{move-Dn7x0H9t.js → move-DzD_C3Vm.js} +1 -1
  136. package/src/assets/web-panel/assets/{mtc-parser-F61D_TgE.js → mtc-parser-D880PYJl.js} +1 -1
  137. package/src/assets/web-panel/assets/{omit-4SQZ39PF.js → omit-CFR_z2ov.js} +1 -1
  138. package/src/assets/web-panel/assets/{pickAttrs-C7DTe126.js → pickAttrs-srIhgrSC.js} +1 -1
  139. package/src/assets/web-panel/assets/{placementArrow-40NeyzDK.js → placementArrow-C1rXpibP.js} +1 -1
  140. package/src/assets/web-panel/assets/{responsiveObserve-BiUJ6qWs.js → responsiveObserve-C30gRcSS.js} +1 -1
  141. package/src/assets/web-panel/assets/{slide-CacJTM3f.js → slide-CvtKiMfV.js} +1 -1
  142. package/src/assets/web-panel/assets/{statusUtils-K812HB-k.js → statusUtils-DNHO7ITG.js} +1 -1
  143. package/src/assets/web-panel/assets/{styleChecker-CKeHA2eM.js → styleChecker-Dt_Sl-g4.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFlexGapSupport-CKl4FqXF.js → useFlexGapSupport-Cjev42Gh.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFs-DPoiJjSZ.js → useFs-Baxglj2V.js} +1 -1
  146. package/src/assets/web-panel/assets/{usePersonalDataHub-aHwBspmt.js → usePersonalDataHub-B4NkcLaP.js} +1 -1
  147. package/src/assets/web-panel/assets/{vnode-DrA-GuCT.js → vnode-mIRkdT7o.js} +1 -1
  148. package/src/assets/web-panel/assets/{zoom-G3LMswgy.js → zoom-HzI5DlH_.js} +1 -1
  149. package/src/assets/web-panel/index.html +1 -1
  150. package/src/auth/npm-auth.js +30 -5
  151. package/src/commands/agenda.js +64 -2
  152. package/src/commands/agent.js +45 -3
  153. package/src/commands/background-session.js +103 -0
  154. package/src/commands/config.js +70 -5
  155. package/src/commands/context.js +36 -2
  156. package/src/commands/hub.js +19 -1
  157. package/src/commands/memory.js +21 -6
  158. package/src/commands/permissions.js +57 -1
  159. package/src/commands/plugin.js +2 -0
  160. package/src/commands/review.js +23 -11
  161. package/src/commands/routine.js +31 -8
  162. package/src/commands/session.js +11 -3
  163. package/src/commands/team.js +20 -7
  164. package/src/commands/update.js +65 -10
  165. package/src/esm-bridge.js +3 -0
  166. package/src/gateways/terminal/PtyManager.js +8 -1
  167. package/src/gateways/ws/message-dispatcher.js +3 -0
  168. package/src/gateways/ws/session-protocol.js +26 -0
  169. package/src/gateways/ws/ws-agent-handler.js +107 -69
  170. package/src/gateways/ws/ws-server.js +92 -4
  171. package/src/harness/jsonl-session-store.js +13 -6
  172. package/src/harness/mcp-client.js +200 -1
  173. package/src/index.js +123 -55
  174. package/src/lazy-dispatch.js +86 -85
  175. package/src/lib/__tests__/personal-data-hub-aichat-wizard.test.js +15 -0
  176. package/src/lib/agent-coordinator.js +4 -0
  177. package/src/lib/agent-ipc-bus.js +32 -2
  178. package/src/lib/agent-sandbox.js +16 -2
  179. package/src/lib/agent-schedule-store.js +55 -0
  180. package/src/lib/agent-tool-admission.js +104 -0
  181. package/src/lib/api-key-helper.js +10 -2
  182. package/src/lib/async-hook-supervisor.cjs +26 -4
  183. package/src/lib/background-interaction-resolver.js +71 -0
  184. package/src/lib/background-session-transport.js +59 -1
  185. package/src/lib/changelog.js +19 -11
  186. package/src/lib/channels/channel-manager.js +6 -0
  187. package/src/lib/channels/telegram-channel.js +11 -1
  188. package/src/lib/channels/webhook-channel.js +15 -3
  189. package/src/lib/checkpoint-store.js +10 -2
  190. package/src/lib/cloud/bundle.js +12 -2
  191. package/src/lib/code-review.js +32 -8
  192. package/src/lib/computer-use/control-backend.js +18 -3
  193. package/src/lib/context-breakdown.js +46 -0
  194. package/src/lib/context-source-ledger.js +43 -0
  195. package/src/lib/crash-reporter.js +6 -0
  196. package/src/lib/diff-review-follow-up.js +154 -0
  197. package/src/lib/downloader.js +17 -3
  198. package/src/lib/ensure-utf8.js +11 -3
  199. package/src/lib/event-runtime-producer.js +58 -0
  200. package/src/lib/event-runtime-store.js +354 -0
  201. package/src/lib/event-runtime-worker.js +109 -0
  202. package/src/lib/execution-backend.js +72 -21
  203. package/src/lib/git-integration.js +19 -4
  204. package/src/lib/hook-manager.js +34 -15
  205. package/src/lib/hook-runner.cjs +48 -3
  206. package/src/lib/hooks-v2-producers.js +15 -0
  207. package/src/lib/hooks-v2-runtime.js +70 -21
  208. package/src/lib/host-adb-bridge.js +111 -21
  209. package/src/lib/ide-context.js +128 -1
  210. package/src/lib/interaction-adapter.js +39 -0
  211. package/src/lib/ipc-attach-protocol.js +98 -0
  212. package/src/lib/json-schema-validate.js +190 -36
  213. package/src/lib/lan-pairing-preflight.js +13 -2
  214. package/src/lib/lsp/__tests__/lsp-server-registry.test.js +18 -0
  215. package/src/lib/lsp/lsp-client.js +18 -1
  216. package/src/lib/lsp/lsp-manager.js +4 -0
  217. package/src/lib/lsp/lsp-server-registry.js +11 -0
  218. package/src/lib/mcp-oauth.js +8 -2
  219. package/src/lib/npm-invocation.js +29 -0
  220. package/src/lib/packer/pkg-runner.js +13 -2
  221. package/src/lib/packer/precheck.js +33 -16
  222. package/src/lib/packer/web-panel-builder.js +16 -2
  223. package/src/lib/permission-rules.cjs +5 -1
  224. package/src/lib/personal-data-hub-aichat-wizard.js +22 -6
  225. package/src/lib/personal-data-hub-wiring.js +27 -3
  226. package/src/lib/plan-mode.js +204 -11
  227. package/src/lib/plugin-monitor-supervisor.js +39 -4
  228. package/src/lib/plugin-runtime/bin.js +45 -0
  229. package/src/lib/plugin-runtime/hooks.js +14 -1
  230. package/src/lib/plugin-runtime/install.js +2 -1
  231. package/src/lib/plugin-runtime/lsp.js +3 -0
  232. package/src/lib/plugin-runtime/mcp.js +8 -1
  233. package/src/lib/plugin-runtime/monitors.js +4 -0
  234. package/src/lib/plugin-runtime/plugin-options.js +74 -7
  235. package/src/lib/plugin-runtime/signature.js +45 -0
  236. package/src/lib/pr-create.js +21 -8
  237. package/src/lib/pr-link-ledger.js +15 -3
  238. package/src/lib/process-execution-broker/credential-agent.js +295 -0
  239. package/src/lib/process-execution-broker/index.js +440 -14
  240. package/src/lib/process-execution-broker/patch-child-process.js +2 -3
  241. package/src/lib/process-execution-broker/platform-sandbox.js +351 -0
  242. package/src/lib/process-manager.js +18 -3
  243. package/src/lib/provenance-api.js +6 -0
  244. package/src/lib/proxy-bootstrap.js +19 -0
  245. package/src/lib/publish-workspace.js +14 -6
  246. package/src/lib/repl-rewind.js +9 -4
  247. package/src/lib/secret-store.js +159 -0
  248. package/src/lib/service-manager.js +64 -29
  249. package/src/lib/session-hooks.js +328 -473
  250. package/src/lib/session-telemetry-middleware.js +6 -0
  251. package/src/lib/settings-hook-events.cjs +61 -1
  252. package/src/lib/settings-hooks.cjs +4 -0
  253. package/src/lib/side-effect-ledger.js +22 -0
  254. package/src/lib/sub-agent-context.js +5 -0
  255. package/src/lib/sub-agent-profiles.js +4 -0
  256. package/src/lib/trace-api.js +6 -0
  257. package/src/lib/turn-context.js +14 -8
  258. package/src/lib/unattended-action-policy.js +83 -0
  259. package/src/lib/update-notice.js +9 -45
  260. package/src/lib/with-file-lock.js +7 -0
  261. package/src/lib/ws-server.js +1 -0
  262. package/src/repl/agent-repl.js +71 -13
  263. package/src/repl/clipboard-copy.js +8 -2
  264. package/src/repl/pr-comments.js +30 -7
  265. package/src/runtime/agent-core.js +439 -87
  266. package/src/runtime/agent-runtime.js +1 -0
  267. package/src/runtime/coding-agent-contract-shared.cjs +52 -0
  268. package/src/runtime/coding-agent-policy.cjs +20 -0
  269. package/src/runtime/diagnostics.js +73 -8
  270. package/src/runtime/headless-runner.js +63 -0
  271. package/src/runtime/headless-stream.js +269 -17
  272. package/src/runtime/mcp-config.js +16 -1
  273. package/src/workers/background-agent-worker.js +80 -1
  274. package/src/assets/web-panel/assets/AppLayout-7iSKDmlI.js +0 -9
  275. package/src/assets/web-panel/assets/ChatBubbleRenderer-DcbUHeGW.js +0 -1
  276. package/src/assets/web-panel/assets/Dashboard-BAKYNavw.js +0 -3
  277. package/src/assets/web-panel/assets/MobileProjects-C4GKn1dH.js +0 -1
  278. package/src/assets/web-panel/assets/Terminal-Fj7ea0In.js +0 -3
  279. package/src/assets/web-panel/assets/devWarning-CDI8Sbaj.js +0 -1
  280. package/src/assets/web-panel/assets/index-96LBR96V.js +0 -1
  281. package/src/assets/web-panel/assets/index-DyQkiW24.js +0 -1
@@ -100,12 +100,17 @@ export function registerContextCommand(program) {
100
100
  // different window.
101
101
  let recordedModel = "";
102
102
  let recordedProvider = "";
103
+ let recordedContextSources = null;
103
104
  try {
104
- const start = (readEvents(sessionId) || []).find(
105
+ const sessionEvents = readEvents(sessionId) || [];
106
+ const start = sessionEvents.find(
105
107
  (e) => e.type === "session_start",
106
108
  );
107
109
  recordedModel = start?.data?.model || "";
108
110
  recordedProvider = start?.data?.provider || "";
111
+ recordedContextSources = [...sessionEvents]
112
+ .reverse()
113
+ .find((e) => e.type === "context_sources")?.data || null;
109
114
  } catch {
110
115
  // header optional — fall through to flags/defaults
111
116
  }
@@ -129,7 +134,12 @@ export function registerContextCommand(program) {
129
134
  try {
130
135
  const { loadProjectInstructions } =
131
136
  await import("../lib/project-instructions.js");
132
- const { breakdownInstructionSources, rankContextSources } =
137
+ const {
138
+ breakdownInstructionSources,
139
+ breakdownMcpSchemas,
140
+ breakdownSkillSources,
141
+ rankContextSources,
142
+ } =
133
143
  await import("../lib/context-breakdown.js");
134
144
  const cwd = process.cwd();
135
145
  let instructionExcludes;
@@ -151,15 +161,37 @@ export function registerContextCommand(program) {
151
161
  estimateTokens,
152
162
  cwd,
153
163
  );
164
+ const mcp = breakdownMcpSchemas(
165
+ recordedContextSources?.mcp || [],
166
+ estimateTokens,
167
+ );
168
+ const skills = breakdownSkillSources(
169
+ recordedContextSources?.skills || [],
170
+ estimateTokens,
171
+ );
154
172
  const ranked = rankContextSources({
155
173
  instructionTotal: instr.total,
156
174
  buckets,
157
175
  counts,
176
+ extraSources: [
177
+ ...mcp.sources.map((source) => ({
178
+ ...source,
179
+ kind: "mcp_schema",
180
+ })),
181
+ ...skills.sources.map((source) => ({
182
+ ...source,
183
+ kind: "skill",
184
+ })),
185
+ ],
158
186
  });
159
187
  sourceReport = {
160
188
  cwd,
161
189
  instructions: instr.sources,
162
190
  instructionTokens: instr.total,
191
+ mcpSchemas: mcp.sources,
192
+ mcpSchemaTokens: mcp.total,
193
+ skills: skills.sources,
194
+ skillTokens: skills.total,
163
195
  ranked: ranked.sources,
164
196
  combinedTotal: ranked.total,
165
197
  };
@@ -189,6 +221,8 @@ export function registerContextCommand(program) {
189
221
  sources: sourceReport.ranked,
190
222
  instructions: sourceReport.instructions,
191
223
  instructionTokens: sourceReport.instructionTokens,
224
+ mcpSchemas: sourceReport.mcpSchemas,
225
+ mcpSchemaTokens: sourceReport.mcpSchemaTokens,
192
226
  combinedTotal: sourceReport.combinedTotal,
193
227
  cwd: sourceReport.cwd,
194
228
  }
@@ -531,6 +531,12 @@ async function cmdSyncAdapter(name, options) {
531
531
  // sources (wechat-pc), --db-path as an explicit alias for the DB file.
532
532
  if (options.key) opts.key = String(options.key);
533
533
  if (options.dbPath) opts.dbPath = String(options.dbPath);
534
+ // WhatsApp public-backup ADB path. `--key` accepts the crypt15 64-hex
535
+ // root key or a crypt14/encrypted_backup.key file path. Device selection
536
+ // follows --serial, then ADB_SERIAL, then the single connected device.
537
+ if (options.serial) opts.serial = String(options.serial);
538
+ if (options.whatsappBusiness) opts.business = true;
539
+ if (options.remotePath) opts.remotePath = String(options.remotePath);
534
540
  // QQ NT (qq-pc): the SQLCipher passphrase from qq-win-db-key (ASCII, e.g.
535
541
  // "5{sww#,6aq=)8=A@"). Routes qq-pc through the decrypt+parse sidecar.
536
542
  if (options.passphrase) opts.passphrase = String(options.passphrase);
@@ -3013,7 +3019,19 @@ export function registerHubCommand(program) {
3013
3019
  )
3014
3020
  .option(
3015
3021
  "--key <hex>",
3016
- "SQLCipher key (64-hex) for encrypted local DBs (e.g. wechat-pc)",
3022
+ "Encryption key: SQLCipher 64-hex, WhatsApp crypt15 64-hex, or WhatsApp key-file path",
3023
+ )
3024
+ .option(
3025
+ "--serial <adb-serial>",
3026
+ "Android device serial for ADB-backed adapters (otherwise ADB_SERIAL or the single connected device)",
3027
+ )
3028
+ .option(
3029
+ "--whatsapp-business",
3030
+ "Pull the WhatsApp Business public backup instead of the personal app backup",
3031
+ )
3032
+ .option(
3033
+ "--remote-path <android-path>",
3034
+ "Explicit WhatsApp msgstore backup path inside an allowed public Databases directory",
3017
3035
  )
3018
3036
  .option(
3019
3037
  "--passphrase <key>",
@@ -4,8 +4,11 @@
4
4
  */
5
5
 
6
6
  import chalk from "chalk";
7
+ import path from "node:path";
7
8
  import { logger } from "../lib/logger.js";
8
9
  import { bootstrap, shutdown } from "../runtime/bootstrap.js";
10
+ import { parseEditorCommand } from "./config.js";
11
+ import { executionBroker } from "../lib/process-execution-broker/index.js";
9
12
  import {
10
13
  getMemoryDir,
11
14
  addMemory,
@@ -50,6 +53,22 @@ import {
50
53
  getMemoryManagerStatsV2,
51
54
  } from "../lib/memory-manager.js";
52
55
 
56
+ export const _deps = {
57
+ execFileSync: (...args) => executionBroker.execFileSync(...args),
58
+ };
59
+
60
+ export function openMemoryEditor(editor, filePath, deps = _deps) {
61
+ const [file, ...editorArgs] = parseEditorCommand(editor);
62
+ if (!file) throw new Error("EDITOR command is empty");
63
+ return deps.execFileSync(file, [...editorArgs, filePath], {
64
+ stdio: "inherit",
65
+ origin: "memory:editor",
66
+ policy: "allow",
67
+ scope: "memory",
68
+ shell: false,
69
+ });
70
+ }
71
+
53
72
  export function registerMemoryCommand(program) {
54
73
  const memory = program
55
74
  .command("memory")
@@ -596,17 +615,13 @@ export function registerMemoryCommand(program) {
596
615
  const content = getMemoryFile(memoryDir);
597
616
 
598
617
  if (options.edit) {
599
- const { execSync } = await import("child_process");
600
618
  const editor =
601
619
  process.env.EDITOR ||
602
620
  process.env.VISUAL ||
603
621
  (process.platform === "win32" ? "notepad" : "nano");
604
- const filePath = `${memoryDir}/MEMORY.md`;
622
+ const filePath = path.join(memoryDir, "MEMORY.md");
605
623
  try {
606
- // Escape any `"` in the path so it can't break out of the quoted
607
- // arg (editor stays unquoted so `$EDITOR` values with args work).
608
- const safePath = filePath.replace(/"/g, '\\"');
609
- execSync(`${editor} "${safePath}"`, { stdio: "inherit" });
624
+ openMemoryEditor(editor, filePath);
610
625
  logger.success("Memory file updated");
611
626
  } catch {
612
627
  logger.error(
@@ -5,6 +5,7 @@
5
5
  * cc permissions list [--json] merged ruleset + source file
6
6
  * cc permissions test <tool> <args...> dry-run: which rule decides?
7
7
  * cc permissions add <allow|ask|deny> <rule> append a rule to a settings file
8
+ * cc permissions allow|ask|deny <rule> convenience aliases for add
8
9
  * [--local | --user] (default target: project)
9
10
  *
10
11
  * The ruleset is loaded by settings-loader (user < project < local < env) and
@@ -23,7 +24,7 @@ const KIND_COLOR = {
23
24
  };
24
25
 
25
26
  const RUNTIME_ADVISORY =
26
- "advisory/not enforced: this command edits and dry-runs settings rules; the Agent runtime still has separate ApprovalGate/managed-policy wiring.";
27
+ "settings rules are enforced by the Agent Core when loaded into the active runtime; managed host policy and ApprovalGate still apply.";
27
28
 
28
29
  function printRuntimeAdvisory() {
29
30
  logger.log(chalk.yellow(RUNTIME_ADVISORY));
@@ -48,6 +49,48 @@ function buildArgs(tool, positional, rulesMod) {
48
49
  return {};
49
50
  }
50
51
 
52
+ async function persistPermissionRule(decision, rule, options, operation = "add") {
53
+ try {
54
+ const kind = String(decision || "").toLowerCase();
55
+ if (!["allow", "ask", "deny"].includes(kind)) {
56
+ logger.error(
57
+ chalk.red(`decision must be allow | ask | deny (got "${decision}")`),
58
+ );
59
+ process.exitCode = 1;
60
+ return;
61
+ }
62
+ const rulesMod = await import("../lib/permission-rules.cjs");
63
+ const mod = rulesMod.default || rulesMod;
64
+ if (!mod.parseRule(rule)) {
65
+ logger.error(
66
+ chalk.red(
67
+ `not a valid rule: "${rule}" (expected Tool or Tool(pattern), e.g. Bash(rm:*))`,
68
+ ),
69
+ );
70
+ process.exitCode = 1;
71
+ return;
72
+ }
73
+ const scope = options.user ? "user" : options.local ? "local" : "project";
74
+ const { addRule } = await import("../lib/settings-loader.cjs");
75
+ const { file, added } = addRule({
76
+ cwd: process.cwd(),
77
+ kind,
78
+ rule,
79
+ scope,
80
+ });
81
+ if (!added) {
82
+ logger.log(chalk.gray(`already present in ${file}: ${kind} ${rule}`));
83
+ return;
84
+ }
85
+ logger.log(
86
+ `${KIND_COLOR[kind].bold("✓ " + kind)} ${rule} ${chalk.gray("→ " + file)}`,
87
+ );
88
+ } catch (err) {
89
+ logger.error(chalk.red(`permissions ${operation} failed: ${err.message}`));
90
+ process.exitCode = 1;
91
+ }
92
+ }
93
+
51
94
  export function registerPermissionsCommand(program) {
52
95
  const cmd = program
53
96
  .command("permissions")
@@ -336,4 +379,17 @@ export function registerPermissionsCommand(program) {
336
379
  process.exitCode = 1;
337
380
  }
338
381
  });
382
+
383
+ // Explicit decision commands make the management surface easier to script
384
+ // and match the common `allow <rule>` / `deny <rule>` workflow.
385
+ for (const decision of ["allow", "ask", "deny"]) {
386
+ cmd
387
+ .command(`${decision} <rule>`)
388
+ .description(`Append an ${decision} permission rule`)
389
+ .option("--local", "Write to .claude/settings.local.json")
390
+ .option("--user", "Write to ~/.claude/settings.json")
391
+ .action(async (rule, options) => {
392
+ await persistPermissionRule(decision, rule, options, decision);
393
+ });
394
+ }
339
395
  }
@@ -1314,6 +1314,7 @@ export function registerPluginCommand(program) {
1314
1314
  const scope = options.scope === "project" ? "project" : "user";
1315
1315
  const current = optsMod.loadPluginOptionValues(name, scope, {
1316
1316
  cwd: process.cwd(),
1317
+ schema,
1317
1318
  });
1318
1319
  for (const pair of options.set) {
1319
1320
  const eq = pair.indexOf("=");
@@ -1326,6 +1327,7 @@ export function registerPluginCommand(program) {
1326
1327
  }
1327
1328
  optsMod.setPluginOptionValues(name, current, scope, {
1328
1329
  cwd: process.cwd(),
1330
+ schema,
1329
1331
  });
1330
1332
  logger.success(`Set option(s) for ${name} at ${scope} scope`);
1331
1333
  }
@@ -28,18 +28,22 @@
28
28
  * .chainlesschain/config.json `llm` exactly like `cc agent` / `cc ask`.
29
29
  */
30
30
 
31
- import { spawnSync } from "node:child_process";
32
31
  import fs from "node:fs";
33
32
  import path from "node:path";
34
33
  import chalk from "chalk";
35
34
  import { logger } from "../lib/logger.js";
36
35
  import { firstBalancedJson } from "../lib/json-schema-output.js";
36
+ import { executionBroker } from "../lib/process-execution-broker/index.js";
37
37
  import {
38
38
  dedupeFindings,
39
39
  buildReviewReport,
40
40
  findingKey,
41
41
  } from "../lib/review-pipeline.js";
42
42
 
43
+ export const _deps = {
44
+ spawnSync: (...args) => executionBroker.spawnSync(...args),
45
+ };
46
+
43
47
  /** Diffs larger than this are truncated before going to the model. */
44
48
  const MAX_DIFF_CHARS = 200_000;
45
49
  /** Per-untracked-file and total caps when inlining brand-new files. */
@@ -52,12 +56,16 @@ const VALID_EFFORTS = Object.freeze(["low", "medium", "high"]);
52
56
  * Run git with an argv array (no shell → no quoting hazards). UTF-8 in/out.
53
57
  * Returns trimmed stdout; throws with git's stderr on failure.
54
58
  */
55
- function gitCli(args, { cwd } = {}) {
56
- const res = spawnSync("git", args, {
59
+ export function gitCli(args, { cwd } = {}) {
60
+ const res = _deps.spawnSync("git", args, {
57
61
  cwd,
58
62
  encoding: "utf-8",
59
63
  windowsHide: true,
60
64
  maxBuffer: 256 * 1024 * 1024,
65
+ origin: "review:command-git",
66
+ policy: "allow",
67
+ scope: "review",
68
+ shell: false,
61
69
  });
62
70
  if (res.error) throw res.error;
63
71
  if (res.status !== 0) {
@@ -86,28 +94,28 @@ function isGitRepo(cwd, git = gitCli) {
86
94
  */
87
95
  export function resolveDiffArgs(opts = {}, stat = false) {
88
96
  const { staged, base, range, paths } = opts;
89
- let args;
97
+ const args = ["diff"];
98
+ if (stat) args.push("--stat");
90
99
  let scope;
91
100
  let label;
92
101
  if (range) {
93
- args = ["diff", range];
102
+ args.push("--end-of-options", range);
94
103
  scope = "range";
95
104
  label = `range ${range}`;
96
105
  } else if (base) {
97
106
  // three-dot: changes on HEAD since it diverged from <base> (PR-style).
98
- args = ["diff", `${base}...HEAD`];
107
+ args.push("--end-of-options", `${base}...HEAD`);
99
108
  scope = "base";
100
109
  label = `${base}...HEAD`;
101
110
  } else if (staged) {
102
- args = ["diff", "--cached"];
111
+ args.push("--cached");
103
112
  scope = "staged";
104
113
  label = "staged changes";
105
114
  } else {
106
- args = ["diff", "HEAD"];
115
+ args.push("HEAD");
107
116
  scope = "working";
108
117
  label = "working tree vs HEAD";
109
118
  }
110
- if (stat) args.push("--stat");
111
119
  const cleanPaths = Array.isArray(paths) ? paths.filter(Boolean) : [];
112
120
  if (cleanPaths.length) args.push("--", ...cleanPaths);
113
121
  return { args, scope, label };
@@ -361,13 +369,17 @@ function collectReviewDiff(scopeOpts, { cwd, git, includeUntracked }) {
361
369
  }
362
370
 
363
371
  /** Run `gh` with an argv array (no shell). UTF-8 in/out; throws on failure. */
364
- function ghCli(args, { cwd, input } = {}) {
365
- const res = spawnSync("gh", args, {
372
+ export function ghCli(args, { cwd, input } = {}) {
373
+ const res = _deps.spawnSync("gh", args, {
366
374
  cwd,
367
375
  input,
368
376
  encoding: "utf-8",
369
377
  windowsHide: true,
370
378
  maxBuffer: 64 * 1024 * 1024,
379
+ origin: "review:command-gh",
380
+ policy: "allow",
381
+ scope: "review",
382
+ shell: false,
371
383
  });
372
384
  if (res.error) throw res.error;
373
385
  if (res.status !== 0) {
@@ -13,11 +13,16 @@
13
13
  * agenda wakeup), exactly like `cc agenda run`.
14
14
  */
15
15
 
16
- import { spawn, execFile } from "node:child_process";
17
16
  import { readFileSync, existsSync } from "node:fs";
18
17
  import { fileURLToPath } from "node:url";
19
18
  import chalk from "chalk";
20
19
  import { logger } from "../lib/logger.js";
20
+ import { executionBroker } from "../lib/process-execution-broker/index.js";
21
+
22
+ export const _deps = {
23
+ spawn: (...args) => executionBroker.spawn(...args),
24
+ execFile: (...args) => executionBroker.execFile(...args),
25
+ };
21
26
 
22
27
  const BIN_PATH = fileURLToPath(
23
28
  new URL("../../bin/chainlesschain.js", import.meta.url),
@@ -29,12 +34,18 @@ async function loadStore() {
29
34
  }
30
35
 
31
36
  /** Production runner: `cc agent -p <prompt> --output-format json`. */
32
- function defaultRunAgent({ prompt }) {
37
+ export function defaultRunAgent({ prompt }) {
33
38
  return new Promise((resolve) => {
34
- const child = spawn(
39
+ const child = _deps.spawn(
35
40
  process.execPath,
36
- [BIN_PATH, "agent", "-p", prompt, "--output-format", "json"],
37
- { windowsHide: true },
41
+ [BIN_PATH, "agent", "--output-format", "json"],
42
+ {
43
+ windowsHide: true,
44
+ origin: "routine:agent",
45
+ policy: "allow",
46
+ scope: "routine",
47
+ shell: false,
48
+ },
38
49
  );
39
50
  let out = "";
40
51
  let err = "";
@@ -42,6 +53,10 @@ function defaultRunAgent({ prompt }) {
42
53
  child.stderr?.setEncoding("utf8");
43
54
  child.stdout?.on("data", (d) => (out += d));
44
55
  child.stderr?.on("data", (d) => (err += d));
56
+ if (child.stdin) {
57
+ child.stdin.on("error", () => {});
58
+ child.stdin.end(prompt);
59
+ }
45
60
  child.on("error", (error) =>
46
61
  resolve({ exitCode: -1, output: `spawn error: ${error.message}` }),
47
62
  );
@@ -70,12 +85,20 @@ function defaultRunAgent({ prompt }) {
70
85
  }
71
86
 
72
87
  /** Production github events fetch via gh CLI. */
73
- function defaultFetchEvents(repo) {
88
+ export function defaultFetchEvents(repo) {
74
89
  return new Promise((resolve) => {
75
- execFile(
90
+ _deps.execFile(
76
91
  "gh",
77
92
  ["api", `repos/${repo}/events`, "--paginate=false"],
78
- { encoding: "utf8", timeout: 8000, windowsHide: true },
93
+ {
94
+ encoding: "utf8",
95
+ timeout: 8000,
96
+ windowsHide: true,
97
+ origin: "routine:github-events",
98
+ policy: "allow",
99
+ scope: "routine",
100
+ shell: false,
101
+ },
79
102
  (err, stdout) => {
80
103
  if (err) return resolve([]);
81
104
  try {
@@ -61,6 +61,11 @@ import {
61
61
  listWorkflowSessions,
62
62
  readWorkflowSession,
63
63
  } from "../lib/workflow-state-reader.js";
64
+ import { executionBroker } from "../lib/process-execution-broker/index.js";
65
+
66
+ export const _deps = {
67
+ execFileSync: (...args) => executionBroker.execFileSync(...args),
68
+ };
64
69
 
65
70
  // DB sessions store `updated_at` as SQLite datetime('now') → "YYYY-MM-DD
66
71
  // HH:MM:SS" (UTC, space at index 10); JSONL sessions store toISOString() →
@@ -149,8 +154,7 @@ export function mapGhPrToSignals(gh = {}) {
149
154
  * mapped signals, or throws (caller degrades to a "pass --checks-file" hint).
150
155
  * 8s timeout, stderr suppressed — a missing / unauthenticated gh just fails.
151
156
  */
152
- async function fetchPrSignalsViaGh(target) {
153
- const { execFileSync } = await import("node:child_process");
157
+ export async function fetchPrSignalsViaGh(target) {
154
158
  const args = [
155
159
  "pr",
156
160
  "view",
@@ -159,10 +163,14 @@ async function fetchPrSignalsViaGh(target) {
159
163
  "number,state,headRefName,headRefOid,reviewDecision,statusCheckRollup",
160
164
  ];
161
165
  if (target.repo) args.push("--repo", String(target.repo));
162
- const out = execFileSync("gh", args, {
166
+ const out = _deps.execFileSync("gh", args, {
163
167
  encoding: "utf-8",
164
168
  timeout: 8000,
165
169
  stdio: ["ignore", "pipe", "ignore"],
170
+ origin: "session:pr-status",
171
+ policy: "allow",
172
+ scope: "pr",
173
+ shell: false,
166
174
  });
167
175
  return mapGhPrToSignals(JSON.parse(out));
168
176
  }
@@ -18,12 +18,16 @@
18
18
  import fs from "fs";
19
19
  import path from "path";
20
20
  import { fileURLToPath } from "url";
21
- import { spawn } from "child_process";
22
21
  import { TaskLeaseRegistry } from "../lib/agent-team/task-lease.js";
23
22
  import { TeamRunner } from "../lib/agent-team/team-runner.js";
24
23
  import { TeamWorktreeCoordinator } from "../lib/agent-team/team-worktree.js";
25
24
  import { TeamBudget } from "../lib/agent-team/team-budget.js";
26
25
  import { TeamMailbox } from "../lib/agent-team/team-mailbox.js";
26
+ import { executionBroker } from "../lib/process-execution-broker/index.js";
27
+
28
+ export const _deps = {
29
+ spawn: (...args) => executionBroker.spawn(...args),
30
+ };
27
31
 
28
32
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
29
33
  const BIN = path.resolve(__dirname, "..", "..", "bin", "chainlesschain.js");
@@ -94,17 +98,20 @@ function planWaves(reg) {
94
98
  }
95
99
 
96
100
  /** Real executor: run a task's shell `command`, success = exit 0. */
97
- function makeShellRunTask(logger) {
101
+ export function makeShellRunTask(logger) {
98
102
  return function runTask({ task }) {
99
103
  const command = task.metadata?.command || task?.command;
100
104
  if (!command) {
101
105
  throw new Error(`task "${task.key}" has no \`command\` to --exec`);
102
106
  }
103
107
  return new Promise((resolve, reject) => {
104
- const child = spawn(command, {
108
+ const child = _deps.spawn(command, [], {
105
109
  cwd: process.cwd(),
106
110
  shell: true,
107
111
  env: process.env,
112
+ origin: "team:shell",
113
+ policy: "allow",
114
+ scope: "team",
108
115
  });
109
116
  let err = "";
110
117
  child.stderr?.on("data", (d) => (err += d.toString("utf8")));
@@ -118,26 +125,32 @@ function makeShellRunTask(logger) {
118
125
  }
119
126
 
120
127
  /** Spawn a headless `cc agent -p` for one prompt in `cwd`; resolve on exit 0. */
121
- function spawnAgent(prompt, cwd, opts = {}) {
128
+ export function spawnAgent(prompt, cwd, opts = {}) {
122
129
  return new Promise((resolve, reject) => {
123
130
  const args = [
124
131
  BIN,
125
132
  "agent",
126
- "-p",
127
- prompt,
128
133
  "--permission-mode",
129
134
  opts.permissionMode || "acceptEdits",
130
135
  "--output-format",
131
136
  "text",
132
137
  ];
133
138
  if (opts.model) args.push("--model", opts.model);
134
- const child = spawn(process.execPath, args, {
139
+ const child = _deps.spawn(process.execPath, args, {
135
140
  cwd,
136
141
  env: { ...process.env, CLAUDECODE: "1" },
137
142
  windowsHide: true,
143
+ origin: "team:agent",
144
+ policy: "allow",
145
+ scope: "team",
146
+ shell: false,
138
147
  });
139
148
  let err = "";
140
149
  child.stderr?.on("data", (d) => (err += d.toString("utf8")));
150
+ if (child.stdin) {
151
+ child.stdin.on("error", () => {});
152
+ child.stdin.end(prompt);
153
+ }
141
154
  child.on("error", (e) => reject(new Error(e.message)));
142
155
  child.on("close", (code) =>
143
156
  code === 0
@@ -1,11 +1,58 @@
1
1
  import chalk from "chalk";
2
2
  import semver from "semver";
3
- import { execSync } from "node:child_process";
4
3
  import { checkForUpdates } from "../lib/version-checker.js";
5
4
  import { downloadRelease } from "../lib/downloader.js";
6
5
  import { VERSION } from "../constants.js";
7
6
  import { askConfirm } from "../lib/prompts.js";
8
7
  import logger from "../lib/logger.js";
8
+ import { executionBroker } from "../lib/process-execution-broker/index.js";
9
+ import { resolveNpmInvocation } from "../lib/npm-invocation.js";
10
+
11
+ export const _deps = {
12
+ platform: process.platform,
13
+ execPath: process.execPath,
14
+ cliEntryPath: process.argv[1] || null,
15
+ spawnSync: (...args) => executionBroker.spawnSync(...args),
16
+ };
17
+
18
+ export function updateProcessInvocations(
19
+ platform = _deps.platform,
20
+ execPath = _deps.execPath,
21
+ cliEntryPath = _deps.cliEntryPath,
22
+ ) {
23
+ return {
24
+ npm: resolveNpmInvocation({ platform, execPath }),
25
+ chainlesschain: cliEntryPath
26
+ ? { command: execPath, prefixArgs: [cliEntryPath] }
27
+ : {
28
+ command:
29
+ platform === "win32" ? "chainlesschain.cmd" : "chainlesschain",
30
+ prefixArgs: [],
31
+ },
32
+ };
33
+ }
34
+
35
+ function runUpdateProcess(command, args, origin) {
36
+ const result = _deps.spawnSync(command, args, {
37
+ encoding: "utf-8",
38
+ stdio: "pipe",
39
+ origin,
40
+ policy: "allow",
41
+ scope: "update",
42
+ shell: false,
43
+ });
44
+ if (result?.error) throw result.error;
45
+ if (result?.status != null && result.status !== 0) {
46
+ const error = new Error(
47
+ `Update process failed (exit ${result.status}): ${command}`,
48
+ );
49
+ error.status = result.status;
50
+ error.stdout = result.stdout;
51
+ error.stderr = result.stderr;
52
+ throw error;
53
+ }
54
+ return String(result?.stdout || "");
55
+ }
9
56
 
10
57
  /**
11
58
  * A version that is safe to interpolate into `npm install -g chainlesschain@<v>`.
@@ -19,7 +66,7 @@ export function isInstallableVersion(v) {
19
66
  return typeof v === "string" && semver.valid(v) !== null;
20
67
  }
21
68
 
22
- async function selfUpdateCli(targetVersion) {
69
+ export async function selfUpdateCli(targetVersion) {
23
70
  if (VERSION === targetVersion) {
24
71
  return true; // Already at the target version
25
72
  }
@@ -33,16 +80,24 @@ async function selfUpdateCli(targetVersion) {
33
80
 
34
81
  try {
35
82
  logger.info("Updating CLI package...");
36
- execSync(`npm install -g chainlesschain@${targetVersion}`, {
37
- encoding: "utf-8",
38
- stdio: "pipe",
39
- });
83
+ const invocations = updateProcessInvocations();
84
+ runUpdateProcess(
85
+ invocations.npm.command,
86
+ [
87
+ ...invocations.npm.prefixArgs,
88
+ "install",
89
+ "-g",
90
+ `chainlesschain@${targetVersion}`,
91
+ ],
92
+ "update:npm-install",
93
+ );
40
94
  // Verify the update actually took effect
41
95
  try {
42
- const newVersion = execSync("chainlesschain --version", {
43
- encoding: "utf-8",
44
- stdio: "pipe",
45
- }).trim();
96
+ const newVersion = runUpdateProcess(
97
+ invocations.chainlesschain.command,
98
+ [...invocations.chainlesschain.prefixArgs, "--version"],
99
+ "update:version-check",
100
+ ).trim();
46
101
  if (newVersion === targetVersion) {
47
102
  logger.success(`CLI updated to v${targetVersion}`);
48
103
  return true;
@@ -0,0 +1,3 @@
1
+ /**
2
+ * ESM bridge stub for unit tests
3
+ */