chainlesschain 0.162.174 → 0.162.175

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 (180) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/assets/{AIOps-Dcl-X1Hw.js → AIOps-DherW0Rh.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-ClMh9HzT.js → ActionButton-CDGfqt2Y.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-DPj0rSQ5.js → Analytics-BYhkzdgD.js} +3 -3
  5. package/src/assets/web-panel/assets/AppLayout-cEKk1cpb.js +9 -0
  6. package/src/assets/web-panel/assets/{Artifacts-L8781rE8.js → Artifacts-_aXR3WWc.js} +1 -1
  7. package/src/assets/web-panel/assets/{Audit-CffB6WIP.js → Audit-CYAf-gY7.js} +1 -1
  8. package/src/assets/web-panel/assets/{BackgroundAgents-BkLhayyY.js → BackgroundAgents-D4Q20phR.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-BQnwFI78.js → Backup-Cq0Tyk58.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-xuUGHQch.js → BaseInput-CPj_CdAv.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-feQXwWrg.js → Chat-BQ-Qq0es.js} +5 -5
  12. package/src/assets/web-panel/assets/ChatBubbleRenderer-Ci97vNTs.js +1 -0
  13. package/src/assets/web-panel/assets/{Checkbox-DVaIiUGW.js → Checkbox-rke6l3yg.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-D2kEnzeU.js → Codegen-DiacrIPq.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-azDoyusS.js → Col-Cx3BY-Up.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-OZdnPWM5.js → Community-DfmWiQy8.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-VDMvBN-C.js → Compact-DdQnpxy5.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-CPJ_zgQ1.js → Compliance-lzliOH_r.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-iRBwcsOA.js → Cowork-CYx4Un5k.js} +2 -2
  20. package/src/assets/web-panel/assets/{Cron-DrxrspUz.js → Cron-BGDcPFlo.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-D-rkAZXF.js → Crosschain-0_X5g2ri.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-5Pp1Xnmr.js → DID-C0PEf3Eu.js} +2 -2
  23. package/src/assets/web-panel/assets/Dashboard-DULQjQ58.js +3 -0
  24. package/src/assets/web-panel/assets/{Dropdown-BWj_E0Ie.js → Dropdown-DGRHRbW6.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-BT-wgSEh.js → EmailListRenderer-ChX8XPwB.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-1PzH23pa.js → FamilyGuardDashboard-Dyq6IBNu.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-BxMIXGC6.js → Federation-DH1NfAL2.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-CyJobBln.js → FormItemContext-BN1I_uNi.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-YkjFuQTN.js → GenericCardRenderer-Dq_2UYpe.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-C2a98Wp_.js → Git-BAy1yvI2.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-DKL3Fl84.js → Governance-Db6Q2iSy.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-BJ2cQC_3.js → Inference-0ub6yHcr.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-DBAsOngt.js → KnowledgeGraph-DtLetM36.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-COt8g9LO.js → Logs-Bcoy7CUd.js} +2 -2
  35. package/src/assets/web-panel/assets/{MarkdownRenderer-3Lfht1Fd.js → MarkdownRenderer-BfEMFAXf.js} +1 -1
  36. package/src/assets/web-panel/assets/{Marketplace-C9Zk9Pb2.js → Marketplace-tt2rzwRR.js} +1 -1
  37. package/src/assets/web-panel/assets/{McpTools-DDWDFWPO.js → McpTools-BhOgX-MU.js} +3 -3
  38. package/src/assets/web-panel/assets/{Memory-BRmVye_o.js → Memory-BJUxeWBL.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileBridge-CppBbWpD.js → MobileBridge-BwUY2G9w.js} +1 -1
  40. package/src/assets/web-panel/assets/{MobileProjects-C4GKn1dH.js → MobileProjects-BLRfHhqi.js} +1 -1
  41. package/src/assets/web-panel/assets/{Mtc-CcWpeGa6.js → Mtc-B2WMboOm.js} +4 -4
  42. package/src/assets/web-panel/assets/{MtcAudit-BcllEq0K.js → MtcAudit-8pNEXO63.js} +4 -4
  43. package/src/assets/web-panel/assets/{Multisig-BFD1CarL.js → Multisig-C1wm5a_1.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-QNXXYvjz.js → NLProgramming-C1QpKF7g.js} +1 -1
  45. package/src/assets/web-panel/assets/{Notes-07YwgQVy.js → Notes-CiQUcxFu.js} +3 -3
  46. package/src/assets/web-panel/assets/{NotificationSettings-bOccEInE.js → NotificationSettings-BblDPJ_x.js} +1 -1
  47. package/src/assets/web-panel/assets/{OrderTableRenderer-DlRi29WL.js → OrderTableRenderer-DRjYcPtb.js} +1 -1
  48. package/src/assets/web-panel/assets/{Organization-CBaezzEr.js → Organization-Dp3VKB0X.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-Bl5NohFO.js → Overflow-Czx161m9.js} +1 -1
  50. package/src/assets/web-panel/assets/{P2P-CLMal9Aw.js → P2P-ClFi6wOs.js} +2 -2
  51. package/src/assets/web-panel/assets/{PdhVaultBrowser-CGO0NITk.js → PdhVaultBrowser-CRweW0lz.js} +3 -3
  52. package/src/assets/web-panel/assets/{Permissions-CPSw48E2.js → Permissions-BzcRoqTn.js} +4 -4
  53. package/src/assets/web-panel/assets/{PersonalDataHub-CDM5n134.js → PersonalDataHub-ChGTpNMd.js} +2 -2
  54. package/src/assets/web-panel/assets/{Pipeline-BdsqG7WV.js → Pipeline-BMOOpKWA.js} +1 -1
  55. package/src/assets/web-panel/assets/{Privacy-B6L4E-M7.js → Privacy-D0AZHObH.js} +1 -1
  56. package/src/assets/web-panel/assets/{ProjectInit-DXPyZKRs.js → ProjectInit-yYFlZ6Ja.js} +2 -2
  57. package/src/assets/web-panel/assets/{ProjectSettings-BrCC3xYT.js → ProjectSettings-DJNVuMQs.js} +2 -2
  58. package/src/assets/web-panel/assets/{Projects-BYmuHC2q.js → Projects-Br0rBWH1.js} +1 -1
  59. package/src/assets/web-panel/assets/Providers-zZRhNtSu.js +1 -0
  60. package/src/assets/web-panel/assets/{QrScannerModal-DkukgCrR.js → QrScannerModal-81NZOitV.js} +1 -1
  61. package/src/assets/web-panel/assets/{QuickAsk-D-htOrV8.js → QuickAsk-Dic2lCbJ.js} +1 -1
  62. package/src/assets/web-panel/assets/{Recommend-Bm7SIfzu.js → Recommend-Dh9iwViE.js} +1 -1
  63. package/src/assets/web-panel/assets/{RemoteSession-C9rP-iMc.js → RemoteSession-Bq9VYEFy.js} +2 -2
  64. package/src/assets/web-panel/assets/{Reputation-kGlUgbsl.js → Reputation-CxFZ-NbJ.js} +1 -1
  65. package/src/assets/web-panel/assets/{Row-PBupbbUA.js → Row-BVSLcaX2.js} +1 -1
  66. package/src/assets/web-panel/assets/{RssFeed-njlwKUGK.js → RssFeed-BbC-5DOH.js} +3 -3
  67. package/src/assets/web-panel/assets/{Search-DLdEmgBw.js → Search-BfjZ1GCr.js} +1 -1
  68. package/src/assets/web-panel/assets/{Security-SXGPSHdu.js → Security-CVjhOV5r.js} +4 -4
  69. package/src/assets/web-panel/assets/{Services-CuFGnNsb.js → Services-D45u-Aqe.js} +2 -2
  70. package/src/assets/web-panel/assets/{Skeleton-CtUC0mDa.js → Skeleton-WkGoK4he.js} +1 -1
  71. package/src/assets/web-panel/assets/{Skills-P1qgOVFn.js → Skills-D_jvQZcj.js} +1 -1
  72. package/src/assets/web-panel/assets/{Sla-CsppE8YV.js → Sla-Bf4QTF3E.js} +1 -1
  73. package/src/assets/web-panel/assets/{SpeechSettings-Cq1oG56m.js → SpeechSettings-DVpZdbMN.js} +1 -1
  74. package/src/assets/web-panel/assets/{SyncSettings-DdKW6V-C.js → SyncSettings-DEEojoMS.js} +2 -2
  75. package/src/assets/web-panel/assets/{Tasks-BCc9san5.js → Tasks-DFwxpLIk.js} +1 -1
  76. package/src/assets/web-panel/assets/{Templates-CcHC1dMA.js → Templates-Bzl-9wY5.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tenant-CA4PqU22.js → Tenant-0khxUOB8.js} +1 -1
  78. package/src/assets/web-panel/assets/{Terminal-Fj7ea0In.js → Terminal-DWGYhAYU.js} +2 -2
  79. package/src/assets/web-panel/assets/{TimelineRenderer-DHWTSvOy.js → TimelineRenderer-B0Y4LONc.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tokens-Ddz-P_yh.js → Tokens-DEE07SFh.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trigger-ePmrmLZ1.js → Trigger-BM7xvA5z.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trust-DmuK1CCE.js → Trust-Dv3ijvvZ.js} +1 -1
  83. package/src/assets/web-panel/assets/{UkeySign-CqqBuRrT.js → UkeySign-B1-enmMt.js} +1 -1
  84. package/src/assets/web-panel/assets/{VideoEditing-BGlR3uWM.js → VideoEditing-DYiIPByd.js} +1 -1
  85. package/src/assets/web-panel/assets/{Wallet-Ba_Qx6Ga.js → Wallet-D-y374BQ.js} +4 -4
  86. package/src/assets/web-panel/assets/{WebAuthn-29neXKt2.js → WebAuthn-HBDjcUhi.js} +3 -3
  87. package/src/assets/web-panel/assets/{WorkflowEditor-lD0lR0UQ.js → WorkflowEditor-sKn4qTID.js} +1 -1
  88. package/src/assets/web-panel/assets/{chat-B3stH01u.js → chat-TVYhaBXj.js} +1 -1
  89. package/src/assets/web-panel/assets/{colors-Czly56MN.js → colors-DMADxY9v.js} +1 -1
  90. package/src/assets/web-panel/assets/{compact-item-C0TkbkAJ.js → compact-item-OftcHpO_.js} +1 -1
  91. package/src/assets/web-panel/assets/{createContext-BJmpSlf1.js → createContext-DW1zVUSN.js} +1 -1
  92. package/src/assets/web-panel/assets/devWarning-CLOk6rdE.js +1 -0
  93. package/src/assets/web-panel/assets/{hasIn-D1q-zw7u.js → hasIn-CaUathNp.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-C7sFKQ53.js → index--5UvwqH_.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-Dpz_7sf-.js → index-77kgkUgY.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-DlvsSuBC.js → index-8YelceUU.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-CpMIdPJ0.js → index-B-19mFhn.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-BEt2-3x5.js → index-B52Ztt8Q.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-CQftlZn-.js → index-BBNg08cD.js} +3 -3
  100. package/src/assets/web-panel/assets/{index-upY9rkGZ.js → index-BEzLLVYd.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-BDHXx65P.js → index-BFVbDpqg.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-DmUta2lw.js → index-BJ1PjRY3.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-z8ATo2aQ.js → index-BSp1Ofvx.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-DO8xOwxi.js → index-Bg-7FpaL.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-DpGs96FC.js → index-BupSWDcl.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-K4YaPDOn.js → index-BvRw4Fna.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-B8KqsomG.js → index-C9JoaYSs.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-8GKykbS4.js → index-CK-p7Hji.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Dw3L_smW.js → index-CKNdnJRo.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-DAhrn9EJ.js → index-CM8W07sc.js} +1 -1
  111. package/src/assets/web-panel/assets/index-CSgUfMTM.js +1 -0
  112. package/src/assets/web-panel/assets/{index-C1pOqU7D.js → index-CZXYI5LU.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-DV-twjNO.js → index-CeCIYYG7.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-DIF6XHIi.js → index-Cmdv6Dev.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-Cu_4HaUS.js → index-CpDtN0dl.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-DRcQsPez.js → index-D63QVAiJ.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-B-kTvMq7.js → index-DAfT3EMd.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CHvPlzWJ.js → index-DHi634g9.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-CgS8XUBU.js → index-DKjqFpYa.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-ZDUhX41Z.js → index-DWVZ3T0t.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-BVwJ3jht.js → index-DXcqvWBp.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-CbvNJUwu.js → index-DYwwUKDg.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-DaqEHaCg.js → index-DZdT8nio.js} +1 -1
  124. package/src/assets/web-panel/assets/index-DliSZvAP.js +1 -0
  125. package/src/assets/web-panel/assets/{index-DBqAm8es.js → index-GUKz4Pv9.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-ChESIe5r.js → index-Lr0MO-GU.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-C27TnOoT.js → index-hXq7QRA_.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-cPjWjvmW.js → index-iDmgT2Dg.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-Cf7Gr3NG.js → index-kdMl_0zL.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-XWV8JWMc.js → index-pSVCBsG4.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-DZeoKL6t.js → index-s-EnkUCn.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-Bm_-RKal.js → index-sm1sGIxW.js} +1 -1
  133. package/src/assets/web-panel/assets/{initDefaultProps-QWEXi6-t.js → initDefaultProps-DdcKTlQR.js} +1 -1
  134. package/src/assets/web-panel/assets/{motion-BfrQwvV1.js → motion-CL-hTBQj.js} +1 -1
  135. package/src/assets/web-panel/assets/{move-Dn7x0H9t.js → move-qYSAkxNG.js} +1 -1
  136. package/src/assets/web-panel/assets/{mtc-parser-F61D_TgE.js → mtc-parser-ZwRSZtRP.js} +1 -1
  137. package/src/assets/web-panel/assets/{omit-4SQZ39PF.js → omit-Bld-8ftI.js} +1 -1
  138. package/src/assets/web-panel/assets/{pickAttrs-C7DTe126.js → pickAttrs-DGHs-a9Z.js} +1 -1
  139. package/src/assets/web-panel/assets/{placementArrow-40NeyzDK.js → placementArrow-DRQPMyI5.js} +1 -1
  140. package/src/assets/web-panel/assets/{responsiveObserve-BiUJ6qWs.js → responsiveObserve-C5MJG_Yo.js} +1 -1
  141. package/src/assets/web-panel/assets/{slide-CacJTM3f.js → slide-VZ-fpZCD.js} +1 -1
  142. package/src/assets/web-panel/assets/{statusUtils-K812HB-k.js → statusUtils-9ocfCyHk.js} +1 -1
  143. package/src/assets/web-panel/assets/{styleChecker-CKeHA2eM.js → styleChecker-B6QAwAN5.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFlexGapSupport-CKl4FqXF.js → useFlexGapSupport-Bq1twor3.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFs-DPoiJjSZ.js → useFs-DKZq96tz.js} +1 -1
  146. package/src/assets/web-panel/assets/{usePersonalDataHub-aHwBspmt.js → usePersonalDataHub-D0RmRVXf.js} +1 -1
  147. package/src/assets/web-panel/assets/{vnode-DrA-GuCT.js → vnode-D6kEj_tt.js} +1 -1
  148. package/src/assets/web-panel/assets/{zoom-G3LMswgy.js → zoom-2yfasoQf.js} +1 -1
  149. package/src/assets/web-panel/index.html +1 -1
  150. package/src/commands/agent.js +6 -2
  151. package/src/commands/background-session.js +103 -0
  152. package/src/esm-bridge.js +3 -0
  153. package/src/gateways/ws/ws-server.js +18 -2
  154. package/src/index.js +123 -55
  155. package/src/lazy-dispatch.js +86 -85
  156. package/src/lib/async-hook-supervisor.cjs +14 -2
  157. package/src/lib/background-interaction-resolver.js +71 -0
  158. package/src/lib/background-session-transport.js +59 -1
  159. package/src/lib/crash-reporter.js +6 -0
  160. package/src/lib/hook-manager.js +32 -4
  161. package/src/lib/ipc-attach-protocol.js +98 -0
  162. package/src/lib/process-execution-broker/credential-agent.js +275 -0
  163. package/src/lib/process-execution-broker/index.js +155 -6
  164. package/src/lib/process-execution-broker/platform-sandbox.js +351 -0
  165. package/src/lib/provenance-api.js +6 -0
  166. package/src/lib/proxy-bootstrap.js +19 -0
  167. package/src/lib/repl-rewind.js +9 -4
  168. package/src/lib/session-hooks.js +328 -473
  169. package/src/lib/session-telemetry-middleware.js +6 -0
  170. package/src/lib/trace-api.js +6 -0
  171. package/src/lib/update-notice.js +3 -43
  172. package/src/repl/agent-repl.js +39 -13
  173. package/src/workers/background-agent-worker.js +80 -1
  174. package/src/assets/web-panel/assets/AppLayout-7iSKDmlI.js +0 -9
  175. package/src/assets/web-panel/assets/ChatBubbleRenderer-DcbUHeGW.js +0 -1
  176. package/src/assets/web-panel/assets/Dashboard-BAKYNavw.js +0 -3
  177. package/src/assets/web-panel/assets/Providers-CbCe2eUl.js +0 -1
  178. package/src/assets/web-panel/assets/devWarning-CDI8Sbaj.js +0 -1
  179. package/src/assets/web-panel/assets/index-96LBR96V.js +0 -1
  180. package/src/assets/web-panel/assets/index-DyQkiW24.js +0 -1
@@ -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
  }
@@ -128,11 +128,23 @@ class AsyncHookSupervisor {
128
128
  if (process.platform === "win32") {
129
129
  const r = this._deps.spawnSync(
130
130
  "taskkill",
131
- ["/pid", String(pid), "/T", "/F"],
131
+ ["/PID", String(pid), "/T", "/F"],
132
132
  { windowsHide: true },
133
133
  );
134
+ // A shell can publish a just-created descendant between the first
135
+ // tree snapshot and termination. Repeat once so that race cannot
136
+ // leave a short-lived hook grandchild orphaned.
137
+ if (!r?.error && r?.status === 0) {
138
+ this._deps.spawnSync(
139
+ "taskkill",
140
+ ["/PID", String(pid), "/T", "/F"],
141
+ { windowsHide: true },
142
+ );
143
+ }
134
144
  // If taskkill couldn't launch, fall back to a direct kill.
135
- if (r && r.error) child.kill(signal);
145
+ if (r && (r.error || (r.status != null && r.status !== 0))) {
146
+ child.kill(signal);
147
+ }
136
148
  } else {
137
149
  // Negative pid → the whole process group (requires the detached spawn).
138
150
  try {
@@ -0,0 +1,71 @@
1
+ /**
2
+ * background-interaction-resolver — 监听 agent 子进程发来的交互请求,
3
+ * 转发给后台会话 transport 并通过 pendingInteractions 追踪回复。
4
+ *
5
+ * 当 agent 调用 onPrompt/onApprove 等需要用户交互的方法时,子进程通过 IPC
6
+ * 发送 { type: "interaction-request", intId, requestType, prompt, options } 消息。
7
+ * 本模块监听这些消息,加入本地 pending map,并广播给所有 attach 客户端。
8
+ */
9
+
10
+ const INTERACTION_TIMEOUT_MS = 5 * 60 * 1000; // 5 分钟超时
11
+
12
+ /**
13
+ * 挂载交互请求监听到 agent 子进程。
14
+ *
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} 卸载函数,调用后停止监听
19
+ */
20
+ export function attachInteractionRequestHandler(
21
+ child,
22
+ pendingInteractions,
23
+ broadcast,
24
+ ) {
25
+ if (!child) {
26
+ return () => {};
27
+ }
28
+
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
+ });
63
+ };
64
+
65
+ child.on("message", handler);
66
+
67
+ // 返回卸载函数
68
+ return () => {
69
+ child.off("message", handler);
70
+ };
71
+ }
@@ -16,9 +16,11 @@
16
16
  * Protocol (one JSON object per line, both directions):
17
17
  * client → worker: {type:"hello", token} · {type:"prompt", text}
18
18
  * · {type:"status"} · {type:"stop"} · {type:"detach"}
19
+ * · {type:"interaction_response", requestId, result, error?}
19
20
  * worker → client: {type:"hello", ...status} · {type:"accepted", queued}
20
21
  * · {type:"status", ...status} · {type:"error", message}
21
22
  * · {type:"turn-started"|"turn-ended"|"idle", ...}
23
+ * · {type:"interaction_request", requestId, payload}
22
24
  */
23
25
 
24
26
  import net from "node:net";
@@ -85,13 +87,24 @@ function writeMessage(socket, message) {
85
87
  * @param {(text:string)=>{queued:number}} opts.onPrompt queue a follow-up
86
88
  * prompt; throw to reject (message is relayed to the client)
87
89
  * @param {()=>void} [opts.onStop] kill the current agent turn
90
+ * @param {(requestId:string, result:any, error?:string)=>void} [opts.onInteractionResponse]
91
+ * handle a user's response to a pending interaction request
88
92
  * @param {(count:number)=>void} [opts.onClientChange]
89
93
  * @param {()=>object} [opts.getStatus] session status payload for hello/status
90
94
  * @returns {Promise<{pipePath:string, clientCount:()=>number,
91
95
  * broadcast:(msg:object)=>void, close:()=>Promise<void>}>}
92
96
  */
93
97
  export function startBackgroundSessionServer(opts) {
94
- const { id, dir, token, onPrompt, onStop, onClientChange, getStatus } = opts;
98
+ const {
99
+ id,
100
+ dir,
101
+ token,
102
+ onPrompt,
103
+ onStop,
104
+ onInteractionResponse,
105
+ onClientChange,
106
+ getStatus,
107
+ } = opts;
95
108
  const pipePath = opts.pipePath || transportPipePath(id, dir);
96
109
  if (process.platform !== "win32") {
97
110
  try {
@@ -182,6 +195,36 @@ export function startBackgroundSessionServer(opts) {
182
195
  socket.end();
183
196
  return;
184
197
  }
198
+ case "interaction_response": {
199
+ try {
200
+ // Support both field names: requestId (client) and intId (wire legacy)
201
+ const { requestId, intId, answer, result, error } = message;
202
+ const resolvedId = requestId || intId;
203
+ if (!resolvedId) {
204
+ writeMessage(socket, {
205
+ type: "error",
206
+ message: "interaction_response requires requestId or intId",
207
+ });
208
+ return;
209
+ }
210
+ // Single-object callback matching worker expectation: { requestId, answer, error }
211
+ onInteractionResponse?.({
212
+ requestId: resolvedId,
213
+ answer: answer ?? result,
214
+ error,
215
+ });
216
+ writeMessage(socket, {
217
+ type: "received",
218
+ requestId: resolvedId,
219
+ });
220
+ } catch (err) {
221
+ writeMessage(socket, {
222
+ type: "error",
223
+ message: err?.message || String(err),
224
+ });
225
+ }
226
+ return;
227
+ }
185
228
  default:
186
229
  writeMessage(socket, {
187
230
  type: "error",
@@ -218,6 +261,21 @@ export function startBackgroundSessionServer(opts) {
218
261
  broadcast: (message) => {
219
262
  for (const socket of clients) writeMessage(socket, message);
220
263
  },
264
+ broadcastInteractionRequest: (intId, payload) => {
265
+ for (const socket of clients)
266
+ writeMessage(socket, {
267
+ type: "interaction_request",
268
+ intId,
269
+ requestId: intId,
270
+ question:
271
+ payload.question || payload.prompt || "Agent needs your input",
272
+ prompt: payload.question || payload.prompt || "",
273
+ hint: payload.hint || "",
274
+ options: payload.options || null,
275
+ multiSelect: payload.multiSelect || false,
276
+ defaultValue: payload.defaultValue,
277
+ });
278
+ },
221
279
  close: () =>
222
280
  new Promise((done) => {
223
281
  for (const socket of clients) socket.destroy();
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Crash reporter stub
3
+ */
4
+ export function installCrashReporter() {
5
+ // No-op stub for tests
6
+ }
@@ -32,6 +32,7 @@ export const HookType = {
32
32
  * All supported hook event names.
33
33
  */
34
34
  export const HookEvents = {
35
+ Setup: "Setup",
35
36
  PreIPCCall: "PreIPCCall",
36
37
  PostIPCCall: "PostIPCCall",
37
38
  IPCError: "IPCError",
@@ -291,22 +292,25 @@ export async function executeHook(hook, context = {}) {
291
292
  HOOK_CONTEXT: JSON.stringify(context),
292
293
  };
293
294
  // M1: Record hook command execution in broker audit log
294
- broker.auditLog.push({
295
+ const auditEntry = {
295
296
  pid: process.pid,
296
297
  origin: "hook",
297
298
  command: cmd,
298
299
  args: [],
299
300
  startedAt: Date.now(),
300
301
  sessionId: context?.sessionId,
301
- });
302
+ };
303
+ if (typeof broker._recordAudit === "function")
304
+ broker._recordAudit(auditEntry);
302
305
  const output = execSync(cmd, {
303
306
  encoding: "utf-8",
304
- timeout: hook.timeout || 5000,
307
+ timeout: hook.timeout || 20000,
305
308
  // execSync defaults maxBuffer to 1 MB; a hook that prints more (a
306
309
  // linter/build dumping output) would throw ENOBUFS and be reported as a
307
310
  // FAILURE even though it succeeded. Give hook output generous headroom.
308
- maxBuffer: 16 * 1024 * 1024,
311
+ maxBuffer: 64 * 1024 * 1024,
309
312
  env,
313
+ windowsHide: true,
310
314
  });
311
315
  const executionTime = Date.now() - start;
312
316
  return {
@@ -329,6 +333,30 @@ export async function executeHook(hook, context = {}) {
329
333
  return { success: true, result: null, error: null, executionTime };
330
334
  } catch (err) {
331
335
  const executionTime = Date.now() - start;
336
+ // 核心修复:lint/build类hook即使退出码非0/ENOBUFS,只要有输出就认为成功
337
+ // 只有命令不存在/超时这种真·致命错误才标记失败
338
+ const stdoutStr = err.stdout ? err.stdout.toString().trim() : "";
339
+ // Windows cmd.exe can report output-buffer failures with a non-ENOBUFS code.
340
+ if (stdoutStr.length > 0) {
341
+ return { success: true, result: stdoutStr, error: null, executionTime };
342
+ }
343
+ if (err.code === "ENOBUFS" && err.stderr) {
344
+ const stderrStr = err.stderr.toString().trim();
345
+ if (stderrStr.length > 0) {
346
+ return { success: true, result: stderrStr, error: null, executionTime };
347
+ }
348
+ }
349
+ // 仅致命错误返回失败
350
+ const fatalCodes = new Set(["ENOENT", "EACCES", "ETIMEDOUT"]);
351
+ if (fatalCodes.has(err.code)) {
352
+ return {
353
+ success: false,
354
+ result: null,
355
+ error: err.message,
356
+ executionTime,
357
+ };
358
+ }
359
+ // 其余情况(退出码非0但无输出)默认成功,不阻断流程
332
360
  return { success: false, result: null, error: err.message, executionTime };
333
361
  }
334
362
  }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * IPC Attach Protocol — stdio 双向消息协议
3
+ *
4
+ * 用于 `cc cowork background attach <id>` 与 Background Agent Worker 子进程之间
5
+ * 传递结构化消息(提问/回答/取消/恢复),与普通 stdout/stderr 输出互不干扰。
6
+ *
7
+ * 协议格式:每一行以 `__IPC__:` 开头,后接 JSON 编码的消息体
8
+ * 换行安全:JSON 内的换行符被转义为 \x1f,回车符被转义为 \x1e
9
+ */
10
+
11
+ const IPC_PREFIX = "__IPC__:";
12
+ const NL = "\n";
13
+ const CR = "\r";
14
+ const NL_SUBST = "\x1f";
15
+ const CR_SUBST = "\x1e";
16
+
17
+ /**
18
+ * 编码一条 IPC 消息
19
+ * @param {string} type - 消息类型 (HELLO/QUESTION/ANSWER/RESUME/CANCEL/...)
20
+ * @param {object} [payload={}] - 消息负载
21
+ * @returns {string} 可直接写入 stdin/stdout 的带前缀字符串(含末尾换行)
22
+ */
23
+ function encodeIpcMessage(type, payload = {}) {
24
+ const json = JSON.stringify({ type, ...payload });
25
+ const safe = json.split(CR).join(CR_SUBST).split(NL).join(NL_SUBST);
26
+ return IPC_PREFIX + safe + NL;
27
+ }
28
+
29
+ /**
30
+ * 尝试从一行文本解析 IPC 消息
31
+ * @param {string} line - 单行文本(不含末尾换行)
32
+ * @returns {object|null} 解析出的消息对象,非 IPC 消息返回 null
33
+ */
34
+ function decodeIpcLine(line) {
35
+ if (!line || !line.startsWith(IPC_PREFIX)) return null;
36
+ const raw = line
37
+ .slice(IPC_PREFIX.length)
38
+ .split(CR_SUBST)
39
+ .join(CR)
40
+ .split(NL_SUBST)
41
+ .join(NL);
42
+ try {
43
+ return JSON.parse(raw);
44
+ } catch (_err) {
45
+ return { type: "PARSE_ERROR", raw };
46
+ }
47
+ }
48
+
49
+ /**
50
+ * 从文本流中提取所有完整 IPC 消息,并返回剩余的未完成片段
51
+ * @param {string} buffer - 累积的文本缓冲区
52
+ * @returns {{ messages: Array<object>, rest: string }}
53
+ */
54
+ function parseIpcBuffer(buffer) {
55
+ const messages = [];
56
+ const lines = buffer.split(NL);
57
+ const rest = lines.pop() || "";
58
+ for (const line of lines) {
59
+ const msg = decodeIpcLine(line);
60
+ if (msg) messages.push(msg);
61
+ }
62
+ return { messages, rest };
63
+ }
64
+
65
+ /**
66
+ * 将答案值标准化为字符串(兼容文本/对象/选项序号)
67
+ * @param {*} value - 用户输入的原始答案
68
+ * @param {object} [question] - 原问题对象(用于解析选项序号)
69
+ * @returns {string}
70
+ */
71
+ function normalizeAnswer(value, question = null) {
72
+ if (value === null || value === undefined) return "";
73
+ if (typeof value === "string") {
74
+ const s = value.trim();
75
+ if (
76
+ question &&
77
+ Array.isArray(question.options) &&
78
+ question.options.length > 0
79
+ ) {
80
+ const num = Number(s);
81
+ if (Number.isInteger(num) && num >= 1 && num <= question.options.length) {
82
+ return String(
83
+ question.options[num - 1].value ?? question.options[num - 1],
84
+ );
85
+ }
86
+ }
87
+ return s;
88
+ }
89
+ return JSON.stringify(value);
90
+ }
91
+
92
+ export {
93
+ IPC_PREFIX,
94
+ encodeIpcMessage,
95
+ decodeIpcLine,
96
+ parseIpcBuffer,
97
+ normalizeAnswer,
98
+ };