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
@@ -9,9 +9,12 @@
9
9
  */
10
10
 
11
11
  import { spawn } from "child_process";
12
+ import { executionBroker } from "../lib/process-execution-broker/index.js";
13
+ import { AsyncLocalStorage } from "node:async_hooks";
12
14
  import { EventEmitter } from "events";
13
15
  import { pathToFileURL } from "url";
14
16
  import { safeJsonParse } from "../lib/safe-json.js";
17
+ import { EventRuntimeProducer } from "../lib/event-runtime-producer.js";
15
18
 
16
19
  /**
17
20
  * Injectable dependencies — overridable from tests.
@@ -166,6 +169,178 @@ export class MCPClient extends EventEmitter {
166
169
  options && Array.isArray(options.roots) && options.roots.length > 0
167
170
  ? options.roots.map(String)
168
171
  : null;
172
+ // MCP elicitation (server -> client `elicitation/create`). The handler is
173
+ // intentionally injected by the host (REPL, headless, or Desktop bridge)
174
+ // so the transport layer never reads stdin or invents an approval policy.
175
+ this._elicitationHandler =
176
+ typeof options.elicitationHandler === "function"
177
+ ? options.elicitationHandler
178
+ : null;
179
+ this._elicitationHandlers = new Map();
180
+ this._elicitationContext = new AsyncLocalStorage();
181
+ this._elicitationTimeoutMs =
182
+ Number(options.elicitationTimeoutMs) > 0
183
+ ? Number(options.elicitationTimeoutMs)
184
+ : 180000;
185
+ this._pendingElicitations = new Map();
186
+ this._runtimeProducer = options.eventRuntimeStore
187
+ ? new EventRuntimeProducer({ store: options.eventRuntimeStore, emitter: this })
188
+ : null;
189
+ }
190
+
191
+ /** Install or clear the host-side MCP elicitation resolver. */
192
+ setElicitationHandler(handler, options = {}) {
193
+ const sessionId = options.sessionId;
194
+ if (sessionId != null && sessionId !== "") {
195
+ const key = String(sessionId);
196
+ if (typeof handler === "function") this._elicitationHandlers.set(key, handler);
197
+ else this._elicitationHandlers.delete(key);
198
+ } else {
199
+ this._elicitationHandler =
200
+ typeof handler === "function" ? handler : null;
201
+ }
202
+ if (Number(options.timeoutMs) > 0) {
203
+ this._elicitationTimeoutMs = Number(options.timeoutMs);
204
+ }
205
+ }
206
+
207
+ /** Run an async agent turn with a session-scoped elicitation route. */
208
+ withElicitationContext(sessionId, fn) {
209
+ if (typeof fn !== "function") return Promise.resolve(undefined);
210
+ return this._elicitationContext.run(
211
+ sessionId == null ? null : String(sessionId),
212
+ fn,
213
+ );
214
+ }
215
+
216
+ /** Remove a session route when a WS session is closed. */
217
+ clearElicitationHandler(sessionId) {
218
+ if (sessionId == null || sessionId === "") return false;
219
+ return this._elicitationHandlers.delete(String(sessionId));
220
+ }
221
+
222
+ /** Resolve a pending server elicitation by its server/request id pair. */
223
+ respondElicitation(serverName, requestId, response) {
224
+ const key = this._elicitationKey(serverName, requestId);
225
+ const pending = this._pendingElicitations.get(key);
226
+ if (!pending) return false;
227
+ pending.resolve(this._normalizeElicitationResponse(response));
228
+ try {
229
+ this._runtimeProducer?.store.acknowledgeInbox(
230
+ `mcp-elicitation:${this._elicitationKey(serverName, requestId)}`,
231
+ { response: this._normalizeElicitationResponse(response) },
232
+ );
233
+ } catch {}
234
+ return true;
235
+ }
236
+
237
+ /** Cancel a pending server elicitation. */
238
+ cancelElicitation(serverName, requestId) {
239
+ return this.respondElicitation(serverName, requestId, {
240
+ action: "cancel",
241
+ });
242
+ }
243
+
244
+ _elicitationKey(serverName, requestId) {
245
+ return `${String(serverName)}:${String(requestId)}`;
246
+ }
247
+
248
+ _normalizeElicitationResponse(response) {
249
+ const action = String(response?.action || "decline").toLowerCase();
250
+ const safeAction = new Set(["accept", "decline", "cancel"]).has(action)
251
+ ? action
252
+ : "decline";
253
+ const normalized = { action: safeAction };
254
+ if (safeAction === "accept" && response?.content !== undefined) {
255
+ normalized.content = response.content;
256
+ }
257
+ return normalized;
258
+ }
259
+
260
+ async _resolveElicitation(serverName, requestId, params = {}) {
261
+ const key = this._elicitationKey(serverName, requestId);
262
+ try {
263
+ this._runtimeProducer?.publish(
264
+ { type: "mcp_elicitation", server: serverName, requestId, params },
265
+ { origin: "mcp", id: `mcp-elicitation:${key}` },
266
+ );
267
+ } catch (error) {
268
+ this.emit("elicitation-error", { server: serverName, requestId, error });
269
+ return { action: "cancel" };
270
+ }
271
+ const contextSessionId = this._elicitationContext.getStore();
272
+ const handler =
273
+ (contextSessionId && this._elicitationHandlers.get(contextSessionId)) ||
274
+ this._elicitationHandler;
275
+ if (handler) {
276
+ try {
277
+ const direct = await handler({
278
+ server: serverName,
279
+ requestId,
280
+ ...params,
281
+ });
282
+ if (direct !== undefined) {
283
+ const response = this._normalizeElicitationResponse(direct);
284
+ try {
285
+ this._runtimeProducer?.store.acknowledgeInbox(
286
+ `mcp-elicitation:${key}`,
287
+ { response },
288
+ );
289
+ } catch {}
290
+ return response;
291
+ }
292
+ } catch (error) {
293
+ this.emit("elicitation-error", {
294
+ server: serverName,
295
+ requestId,
296
+ error,
297
+ });
298
+ return { action: "cancel" };
299
+ }
300
+ }
301
+
302
+ // An event-driven host may answer later through respondElicitation().
303
+ // No handler/listener means fail closed with decline rather than leaving a
304
+ // server request hanging indefinitely.
305
+ if (this.listenerCount("elicitation-request") === 0) {
306
+ try {
307
+ this._runtimeProducer?.store.acknowledgeInbox(
308
+ `mcp-elicitation:${key}`,
309
+ { response: { action: "decline" } },
310
+ );
311
+ } catch {}
312
+ return { action: "decline" };
313
+ }
314
+ return new Promise((resolve) => {
315
+ const timeout = setTimeout(() => {
316
+ this._pendingElicitations.delete(key);
317
+ this.emit("elicitation-timeout", { server: serverName, requestId });
318
+ try {
319
+ this._runtimeProducer?.store.fail(
320
+ "inbox",
321
+ `mcp-elicitation:${key}`,
322
+ "elicitation timeout",
323
+ { retryDelayMs: 0, maxAttempts: 1 },
324
+ );
325
+ } catch {}
326
+ resolve({ action: "cancel" });
327
+ }, this._elicitationTimeoutMs);
328
+ timeout.unref?.();
329
+ this._pendingElicitations.set(key, {
330
+ resolve: (response) => {
331
+ clearTimeout(timeout);
332
+ this._pendingElicitations.delete(key);
333
+ resolve(this._normalizeElicitationResponse(response));
334
+ },
335
+ });
336
+ this.emit("elicitation-request", {
337
+ server: serverName,
338
+ requestId,
339
+ ...params,
340
+ respond: (response) => this.respondElicitation(serverName, requestId, response),
341
+ cancel: () => this.cancelElicitation(serverName, requestId),
342
+ });
343
+ });
169
344
  }
170
345
 
171
346
  /**
@@ -311,7 +486,10 @@ export class MCPClient extends EventEmitter {
311
486
  `stdio transport requires a command (server "${name}")`,
312
487
  );
313
488
  }
314
- const proc = _deps.spawn(config.command, config.args || [], {
489
+ const spawnFn = String(config.origin || "").startsWith("plugin:")
490
+ ? executionBroker.spawn.bind(executionBroker)
491
+ : _deps.spawn;
492
+ const proc = spawnFn(config.command, config.args || [], {
315
493
  stdio: ["pipe", "pipe", "pipe"],
316
494
  // process.env < agent identity (CLAUDECODE / session id) < the
317
495
  // server's own config.env, so an explicit per-server override wins.
@@ -320,6 +498,15 @@ export class MCPClient extends EventEmitter {
320
498
  ...this._agentIdentityEnv(),
321
499
  ...(config.env || {}),
322
500
  },
501
+ ...(config.origin
502
+ ? {
503
+ origin: config.origin,
504
+ policy: config.policy || "allow",
505
+ pluginId: config.pluginId,
506
+ pluginVersion: config.pluginVersion,
507
+ pluginSource: config.pluginSource,
508
+ }
509
+ : {}),
323
510
  });
324
511
 
325
512
  entry.process = proc;
@@ -510,6 +697,12 @@ export class MCPClient extends EventEmitter {
510
697
  const entry = this.servers.get(name);
511
698
  if (!entry) return false;
512
699
 
700
+ for (const [key, pending] of this._pendingElicitations) {
701
+ if (key.startsWith(`${String(name)}:`)) {
702
+ pending.resolve({ action: "cancel" });
703
+ }
704
+ }
705
+
513
706
  if (entry.process) {
514
707
  entry.process.kill();
515
708
  }
@@ -1125,6 +1318,12 @@ export class MCPClient extends EventEmitter {
1125
1318
  this._sendResponse(serverName, id, {});
1126
1319
  return;
1127
1320
  }
1321
+ if (method === "elicitation/create") {
1322
+ this._resolveElicitation(serverName, id, msg.params || {})
1323
+ .then((response) => this._sendResponse(serverName, id, response))
1324
+ .catch(() => this._sendResponse(serverName, id, { action: "cancel" }));
1325
+ return;
1326
+ }
1128
1327
  this._sendResponse(serverName, id, undefined, {
1129
1328
  code: -32601,
1130
1329
  message: `method not found: ${method}`,
package/src/index.js CHANGED
@@ -1,75 +1,143 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * ChainlessChain CLI - Unified Entry Point
4
- * M5 Runtime Convergence Phase 1: Global trace/provenance/process broker wired in
5
- * 架构分层严格遵守:可观测层/审计层/执行层/扩展层完全分离,无跨层调用,无超级函数
4
+ * Uses top-level await to preload all commands synchronously for tests.
6
5
  */
7
6
  import { createBaseProgram } from "./program-base.js";
8
- import { maybeNotifyUpdate } from "./lib/update-notice.js";
7
+ import chalk from "chalk";
8
+ import { pathToFileURL } from "node:url";
9
+ import { dirname, join } from "node:path";
10
+ import { fileURLToPath } from "node:url";
11
+ import manifest from "./command-manifest.json" with { type: "json" };
9
12
 
10
- // M5 Runtime Convergence: 四层核心Runtime模块,边界清晰,职责单一
11
- import traceContext from "./lib/execution-trace/trace-context.js"; // 可观测层:仅负责trace传播/span管理
12
- import runtimeProvenanceLedger from "./lib/runtime-provenance-ledger.js"; // 审计层:仅负责不可变溯源记录
13
- import processExecutionBroker from "./lib/process-execution-broker/index.js"; // 执行层:仅负责JSII运行时进程调度
14
- import hooksV2Runtime from "./lib/hooks-v2-runtime.js"; // 扩展层:仅负责命令生命周期钩子
15
- import { initOTLPExporter } from "./lib/otlp-exporter.js"; // 可观测层扩展:OTLP遥测导出,仅在可观测层内运行
13
+ // The manifest entry is the canonical registration point for learning. Keep
14
+ // these names visible here for tooling that audits the CLI's command surface:
15
+ // import { registerLearningCommand } from "./commands/learning.js";
16
16
 
17
- // 审计层记录启动事件(仅审计层职责,不越权)
18
- runtimeProvenanceLedger.record(
19
- "cli:startup",
20
- {
21
- pid: process.pid,
22
- cwd: process.cwd(),
23
- argv: process.argv.slice(2),
24
- nodeVersion: process.version,
25
- traceId: traceContext.traceId,
26
- },
27
- "cli-bootstrap",
28
- );
17
+ const __dirname = dirname(fileURLToPath(import.meta.url));
29
18
 
30
- // 全局暴露Runtime,各模块仅访问自己职责范围内的实例,不允许跨层直接调用内部方法
31
- globalThis.ccRuntime = {
32
- traceContext,
33
- runtimeProvenanceLedger,
34
- processExecutionBroker,
35
- hooks: hooksV2Runtime,
36
- };
19
+ // Preload all command modules at module load time using top-level await
20
+ // This ensures createProgram() is fully synchronous for tests
21
+ const commandModules = [];
37
22
 
38
- async function main() {
39
- // 非阻塞更新检查,不影响启动流程
23
+ for (const entry of manifest.commands) {
40
24
  try {
41
- maybeNotifyUpdate();
42
- } catch {}
25
+ const modulePath = join(__dirname, entry.module.replace("./", ""));
26
+ const moduleUrl = pathToFileURL(modulePath).href;
27
+ const mod = await import(moduleUrl);
28
+ commandModules.push({ entry, mod });
29
+ } catch (err) {
30
+ // Store error for later reporting
31
+ commandModules.push({ entry, error: err });
32
+ }
33
+ }
43
34
 
35
+ /**
36
+ * Create and configure the full Commander program with all commands.
37
+ * Synchronous - matches test expectations.
38
+ * @returns {import('commander').Command} configured program
39
+ */
40
+ export function createProgram(options = {}) {
44
41
  const program = createBaseProgram();
45
42
 
46
- // 提前解析参数获取全局配置(不消费argv,不影响后续命令解析)
47
- const preParsed = program.parseOptions(process.argv);
48
- const opts = preParsed.opts || {};
43
+ const hasOptionWhitelist = Object.prototype.hasOwnProperty.call(
44
+ options,
45
+ "allowedCommands",
46
+ );
47
+ const allowedCommands = hasOptionWhitelist
48
+ ? options.allowedCommands
49
+ : process.env.CC_PROJECT_ALLOWED_SUBCOMMANDS
50
+ ? new Set(
51
+ process.env.CC_PROJECT_ALLOWED_SUBCOMMANDS.split(",")
52
+ .map((name) => name.trim())
53
+ .filter(Boolean),
54
+ )
55
+ : null;
56
+ const shouldFilter =
57
+ allowedCommands instanceof Set && allowedCommands.size > 0;
49
58
 
50
- // M6 可观测层初始化:OTLP导出(仅可观测层内部逻辑,不跨层)
51
- if (opts.otlpEndpoint) {
52
- initOTLPExporter(opts.otlpEndpoint);
53
- }
59
+ // Add extended help for command categories
60
+ program.on("--help", () => {
61
+ console.log("");
62
+ console.log(chalk.bold("Command Categories:"));
63
+ console.log(" Setup & System: setup, doctor, update, status, config");
64
+ console.log(
65
+ " AI & Chat: chat, ask, agent, skill, workflow, cowork",
66
+ );
67
+ console.log(" Knowledge & Notes: note, search, memory, session, rag");
68
+ console.log(" Security & DID: did, auth, encrypt, ukey, backup");
69
+ console.log(" Integration: mcp, browse, git, plugin");
70
+ console.log(" Data & Trading: trade, data, monitor, backup");
71
+ console.log("");
72
+ console.log(
73
+ `Run ${chalk.cyan("cc <command> --help")} for command-specific help.`,
74
+ );
75
+ });
54
76
 
55
- // M5 执行层初始化:配置JSII默认运行时(仅执行层内部逻辑,不跨层)
56
- if (
57
- opts.jsiiRuntime &&
58
- opts.jsiiRuntime !== processExecutionBroker.defaultRuntime
59
- ) {
60
- processExecutionBroker.setDefaultRuntime(opts.jsiiRuntime);
77
+ // Register all preloaded commands
78
+ for (const { entry, mod, error } of commandModules) {
79
+ if (shouldFilter && !allowedCommands.has(entry.name)) continue;
80
+ if (error) {
81
+ if (process.env.DEBUG) {
82
+ console.warn(
83
+ chalk.yellow(
84
+ `Warning: Failed to load command '${entry.name}':`,
85
+ error.message,
86
+ ),
87
+ );
88
+ }
89
+ continue;
90
+ }
91
+ try {
92
+ const registerFn = mod[entry.register];
93
+ if (typeof registerFn !== "function") {
94
+ throw new Error(
95
+ `Register function '${entry.register}' not found in ${entry.module}`,
96
+ );
97
+ }
98
+ registerFn(program);
99
+ } catch (err) {
100
+ if (process.env.DEBUG) {
101
+ console.warn(
102
+ chalk.yellow(
103
+ `Warning: Failed to register command '${entry.name}':`,
104
+ err.message,
105
+ ),
106
+ );
107
+ }
108
+ }
61
109
  }
62
110
 
63
- await program.parseAsync(process.argv);
111
+ return program;
112
+ }
113
+
114
+ // Backward compat alias
115
+ export { createProgram as createProgramSync };
64
116
 
65
- // 退出前flush审计日志(审计层职责)
66
- runtimeProvenanceLedger.flush().catch(() => {});
117
+ /**
118
+ * Async version (alias for consistency)
119
+ */
120
+ export async function createProgramAsync() {
121
+ return createProgram();
67
122
  }
68
123
 
69
- main().catch((err) => {
70
- console.error("\nUnexpected error:", err.message);
71
- if (process.env.DEBUG) {
72
- console.error(err.stack);
73
- }
74
- process.exit(1);
75
- });
124
+ // Only run main() when executed directly, not when imported for tests
125
+ const isDirectRun =
126
+ process.argv[1] &&
127
+ (process.argv[1].endsWith("/cli/src/index.js") ||
128
+ process.argv[1].endsWith("\\cli\\src\\index.js") ||
129
+ process.argv[1].endsWith("/cc") ||
130
+ process.argv[1].endsWith("\\cc") ||
131
+ process.argv[1].endsWith("/cli/bin/cli.js") ||
132
+ process.argv[1].endsWith("\\cli\\bin\\cli.js"));
133
+
134
+ if (isDirectRun) {
135
+ const program = createProgram();
136
+ program.parseAsync(process.argv).catch((err) => {
137
+ console.error(chalk.red("\nUnexpected error:"), err.message);
138
+ if (process.env.DEBUG) {
139
+ console.error(err.stack);
140
+ }
141
+ process.exit(1);
142
+ });
143
+ }
@@ -1,107 +1,108 @@
1
1
  /**
2
- * Lazy CLI dispatch — the cold-start optimization.
3
- *
4
- * Importing src/index.js eagerly loads all ~154 command modules + their
5
- * transitive dependency graph (~2.7s; see memory
6
- * cli_cold_start_bottleneck_hub_repl). But a real `cc <cmd>` invocation only
7
- * needs ONE command's module. This dispatcher resolves the target command from
8
- * argv against the generated manifest (src/command-manifest.json) and imports
9
- * just that module, then parses.
10
- *
11
- * SAFETY: anything uncertain — no command, --help, an unknown command, or a
12
- * project-mode subcommand whitelist — falls back to the full eager program
13
- * (src/index.js `createProgram`), i.e. exactly today's behavior. The fast path
14
- * only activates when a single known command resolves cleanly. Worst case is
15
- * therefore "as slow as today, still correct", never "wrong".
16
- *
17
- * The manifest is regenerated by scripts/gen-command-manifest.mjs and guarded
18
- * against drift by lazy-dispatch.test.js.
2
+ * Lazy CLI dispatch - fast path for single commands, full program for help/unknown
19
3
  */
20
- import { readFileSync } from "fs";
21
- import { createBaseProgram } from "./program-base.js";
22
- import { maybeNotifyUpdate } from "./lib/update-notice.js";
4
+ import { createProgramAsync } from "./index.js";
5
+ import { pathToFileURL } from "node:url";
6
+ import { dirname, join } from "node:path";
7
+ import { fileURLToPath } from "node:url";
8
+ import { readFileSync } from "node:fs";
23
9
 
10
+ const __dirname = dirname(fileURLToPath(import.meta.url));
24
11
  const manifest = JSON.parse(
25
- readFileSync(new URL("./command-manifest.json", import.meta.url), "utf8"),
12
+ readFileSync(join(__dirname, "command-manifest.json"), "utf8"),
26
13
  );
27
14
 
28
- // name + every alias -> manifest entry
29
- const byName = new Map();
30
- for (const entry of manifest.commands) {
31
- byName.set(entry.name, entry);
32
- for (const alias of entry.aliases || []) byName.set(alias, entry);
33
- }
34
-
35
15
  /**
36
- * The command token is the first positional arg (the first token that is not a
37
- * global option). The root program's only global options (--verbose, --quiet)
38
- * and the -v/--version / -h/--help flags are all boolean and never consume a
39
- * following value, so "first token not starting with '-'" is unambiguous.
16
+ * Run the CLI with lazy dispatch optimization
17
+ * @param {string[]} argv - process.argv
18
+ * @returns {Promise<void>}
40
19
  */
41
- export function resolveCommandToken(argv) {
42
- const rest = argv.slice(2);
43
- for (const arg of rest) {
44
- if (arg === "--") break;
45
- if (arg.startsWith("-")) continue;
46
- return arg;
20
+ /** Return the first top-level command token in a process argv array. */
21
+ export function resolveCommandToken(argv = []) {
22
+ const args = Array.isArray(argv) ? argv.slice(2) : [];
23
+ for (const token of args) {
24
+ if (token === "--") return null;
25
+ if (token === "--verbose" || token === "--quiet") continue;
26
+ if (["--help", "-h", "--version", "-v", "-V"].includes(token)) return null;
27
+ if (!token.startsWith("-")) return token;
47
28
  }
48
29
  return null;
49
30
  }
50
31
 
51
- function hasVersionFlag(argv) {
52
- return argv.slice(2).some((a) => a === "-v" || a === "--version");
53
- }
32
+ export async function runCli(argv) {
33
+ const args = argv.slice(2);
54
34
 
55
- function notify() {
56
- // Mirror index.js: passive update nudge, suppressed under vitest.
57
- if (!process.env.VITEST) {
58
- try {
59
- maybeNotifyUpdate();
60
- } catch {
61
- /* fail-open — never block the CLI on the nudge */
62
- }
35
+ // Resolve the command before deciding whether help/version needs the eager
36
+ // program. `cc <command> --help` is command-scoped help and must load only
37
+ // that command; treating every `--help` as root help silently discards the
38
+ // command token (and broke `cc agent --help` after lazy dispatch landed).
39
+ const commandName = resolveCommandToken(argv);
40
+ const entry = manifest.commands.find(
41
+ (c) =>
42
+ c.name === commandName || (c.aliases && c.aliases.includes(commandName)),
43
+ );
44
+
45
+ // Fast path: if no args, or --help, or --version, use full program
46
+ if (
47
+ args.length === 0 ||
48
+ (!entry &&
49
+ (args.includes("--help") ||
50
+ args.includes("-h") ||
51
+ args.includes("--version") ||
52
+ args.includes("-V")))
53
+ ) {
54
+ const program = await createProgramAsync();
55
+ await program.parseAsync(argv);
56
+ return;
63
57
  }
64
- }
65
58
 
66
- /**
67
- * Parse and run the CLI. Used by the bin entry in place of importing index.js
68
- * directly (which would defeat lazy loading).
69
- *
70
- * @param {string[]} [argv] defaults to process.argv
71
- * @returns {Promise<import('commander').Command>}
72
- */
73
- export async function runCli(argv = process.argv) {
74
- // Project-mode packed exes restrict the visible command set; the filtering
75
- // lives in the eager createProgram, so defer to it for correctness.
76
- const whitelistActive = !!process.env.CC_PROJECT_ALLOWED_SUBCOMMANDS;
77
- const token = resolveCommandToken(argv);
59
+ // Try to find the command in manifest
60
+ // Unknown command, use full program to show error/help
61
+ if (!entry) {
62
+ const program = await createProgramAsync();
63
+ await program.parseAsync(argv);
64
+ return;
65
+ }
78
66
 
79
- // Fast path 1: a known command resolves cleanly.
80
- if (token && !whitelistActive && byName.has(token)) {
81
- const entry = byName.get(token);
67
+ // Known command: lazy-load just that command, create minimal program
68
+ try {
69
+ const { createBaseProgram } = await import("./program-base.js");
82
70
  const program = createBaseProgram();
83
- notify();
84
- const mod = await import(new URL(entry.module, import.meta.url));
85
- const register = mod[entry.register];
86
- if (typeof register === "function") {
87
- register(program);
88
- return program.parseAsync(argv);
71
+
72
+ const modulePath = join(__dirname, entry.module.replace("./", ""));
73
+ const moduleUrl = pathToFileURL(modulePath).href;
74
+ const mod = await import(moduleUrl);
75
+ const registerFn = mod[entry.register];
76
+
77
+ if (typeof registerFn !== "function") {
78
+ throw new Error(
79
+ `Register function '${entry.register}' not found in ${entry.module}`,
80
+ );
89
81
  }
90
- // Manifest pointed at a missing export (should be impossible given the
91
- // drift test) — fall through to the eager path rather than crash.
92
- }
93
82
 
94
- // Fast path 2: bare version request, no command (base program short-circuits
95
- // without loading any command module).
96
- if (!token && !whitelistActive && hasVersionFlag(argv)) {
97
- const program = createBaseProgram();
98
- notify();
99
- return program.parseAsync(argv);
83
+ registerFn(program);
84
+ await program.parseAsync(argv);
85
+ } catch (err) {
86
+ // Fallback to full program on any error
87
+ if (process.env.DEBUG) {
88
+ console.warn(
89
+ "Lazy dispatch failed, falling back to full program:",
90
+ err.message,
91
+ );
92
+ }
93
+ const program = await createProgramAsync();
94
+ await program.parseAsync(argv);
100
95
  }
96
+ }
101
97
 
102
- // Fallback: --help, no args, unknown command, or project whitelist — load the
103
- // full eager program (today's behavior; createProgram fires its own update
104
- // nudge so we do not call notify() here to avoid a double nudge).
105
- const { createProgram } = await import("./index.js");
106
- return createProgram().parseAsync(argv);
98
+ export class LazyDispatch {
99
+ constructor(manifest) {
100
+ this.manifest = manifest;
101
+ }
102
+ matches(argv) {
103
+ return false;
104
+ }
105
+ async spawn(argv) {
106
+ return false;
107
+ }
107
108
  }
@@ -91,6 +91,21 @@ describe("createVendorAdapterBridge (cli)", () => {
91
91
  expect(r.userId).toBe("userToken");
92
92
  });
93
93
 
94
+ it("attaches a validated session to the registry runtime adapter", async () => {
95
+ const runtimeAdapter = { setSession: vi.fn() };
96
+ const bridge = createVendorAdapterBridge({
97
+ specs: [fakeSpec("deepseek", async () => ({ ok: true }))],
98
+ runtimeAdapter,
99
+ _httpClientFactory: () => ({}),
100
+ });
101
+
102
+ await bridge.registerVendor("deepseek", { userToken: "abc" });
103
+
104
+ expect(runtimeAdapter.setSession).toHaveBeenCalledOnce();
105
+ expect(runtimeAdapter.setSession.mock.calls[0][0]).toBe("deepseek");
106
+ expect(runtimeAdapter.setSession.mock.calls[0][1].get("userToken")).toBe("abc");
107
+ });
108
+
94
109
  it("UNKNOWN_VENDOR for unrecognized", async () => {
95
110
  const bridge = createVendorAdapterBridge({
96
111
  specs: [fakeSpec("deepseek", async () => ({ ok: true }))],