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.
- package/package.json +10 -10
- package/src/assets/web-panel/assets/{AIOps-Dcl-X1Hw.js → AIOps-BDLu5Elz.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-ClMh9HzT.js → ActionButton-DH5us-CK.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DPj0rSQ5.js → Analytics-BZ0u8IFG.js} +3 -3
- package/src/assets/web-panel/assets/AppLayout-Duu8xR14.js +9 -0
- package/src/assets/web-panel/assets/{Artifacts-L8781rE8.js → Artifacts-Br2YBbh_.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CffB6WIP.js → Audit-C3C6a482.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-BkLhayyY.js → BackgroundAgents-CzHvebcj.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-BQnwFI78.js → Backup-DZNHYDFd.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-xuUGHQch.js → BaseInput-VRiC4fIx.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-feQXwWrg.js → Chat-Cm08WWAD.js} +5 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-CGHYrugQ.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-DVaIiUGW.js → Checkbox-DtByk7d7.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-D2kEnzeU.js → Codegen-CphXXOfD.js} +1 -1
- package/src/assets/web-panel/assets/{Col-azDoyusS.js → Col-Hz86TnLR.js} +1 -1
- package/src/assets/web-panel/assets/{Community-OZdnPWM5.js → Community-HP03ltpD.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-VDMvBN-C.js → Compact-B_N1mqQz.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CPJ_zgQ1.js → Compliance-CVztRpi8.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-iRBwcsOA.js → Cowork-wUVOyZih.js} +4 -4
- package/src/assets/web-panel/assets/{Cron-DrxrspUz.js → Cron-DW5TLJKw.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-D-rkAZXF.js → Crosschain-CrAFGhWH.js} +1 -1
- package/src/assets/web-panel/assets/{DID-5Pp1Xnmr.js → DID-pA-oD8ke.js} +2 -2
- package/src/assets/web-panel/assets/Dashboard-CXrd5gAw.js +3 -0
- package/src/assets/web-panel/assets/{Dropdown-BWj_E0Ie.js → Dropdown-EweJcsek.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-BT-wgSEh.js → EmailListRenderer-C9xVLPG4.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-1PzH23pa.js → FamilyGuardDashboard-CDcEEqlu.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BxMIXGC6.js → Federation-DtZda9A_.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-CyJobBln.js → FormItemContext-CiYdcVz3.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-YkjFuQTN.js → GenericCardRenderer-DA13uwA0.js} +1 -1
- package/src/assets/web-panel/assets/{Git-C2a98Wp_.js → Git-DzRhZD1O.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DKL3Fl84.js → Governance-D5RMgOSb.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BJ2cQC_3.js → Inference-BgrPfSNk.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DBAsOngt.js → KnowledgeGraph-DzjnD571.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-COt8g9LO.js → Logs-BhWzVDtN.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-3Lfht1Fd.js → MarkdownRenderer-BDape9cx.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-C9Zk9Pb2.js → Marketplace-DJtL5GV7.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DDWDFWPO.js → McpTools-CZcQygI7.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-BRmVye_o.js → Memory-DUWSDUUu.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-CppBbWpD.js → MobileBridge-BTwq2WKY.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-NZvvfDME.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-CcWpeGa6.js → Mtc-BiGugEQm.js} +6 -6
- package/src/assets/web-panel/assets/{MtcAudit-BcllEq0K.js → MtcAudit-DY7a6gUe.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-BFD1CarL.js → Multisig-BQbDu_w7.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-QNXXYvjz.js → NLProgramming-CM2wXTLv.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-07YwgQVy.js → Notes-DI6gGs1v.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-bOccEInE.js → NotificationSettings-BsZOLWAB.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DlRi29WL.js → OrderTableRenderer-C48mu09U.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-CBaezzEr.js → Organization-Cds0_tXr.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Bl5NohFO.js → Overflow-WunYMD87.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CLMal9Aw.js → P2P-Bo6j4DDv.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-CGO0NITk.js → PdhVaultBrowser-Bh2XPD5f.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-CPSw48E2.js → Permissions-EMvMMC8N.js} +3 -3
- package/src/assets/web-panel/assets/{PersonalDataHub-CDM5n134.js → PersonalDataHub-AX3ypUDV.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-BdsqG7WV.js → Pipeline-BOx8HOgL.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-B6L4E-M7.js → Privacy-tBeTVQVM.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-DXPyZKRs.js → ProjectInit-CVYg1W4M.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BrCC3xYT.js → ProjectSettings-Dvt5I7y1.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-BYmuHC2q.js → Projects-Cc7FC9-e.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-CbCe2eUl.js → Providers-Ct8xqY-E.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-DkukgCrR.js → QrScannerModal-Cni8Ooja.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-D-htOrV8.js → QuickAsk-BJVLKdxr.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Bm7SIfzu.js → Recommend-DPG8Rbbm.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-C9rP-iMc.js → RemoteSession-DsdR7dCt.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-kGlUgbsl.js → Reputation-Csg1YM-b.js} +1 -1
- package/src/assets/web-panel/assets/{Row-PBupbbUA.js → Row-D9DoFoEf.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-njlwKUGK.js → RssFeed-BsvKrXMS.js} +2 -2
- package/src/assets/web-panel/assets/{Search-DLdEmgBw.js → Search-DFUStfgQ.js} +1 -1
- package/src/assets/web-panel/assets/{Security-SXGPSHdu.js → Security-ILg1zxdK.js} +4 -4
- package/src/assets/web-panel/assets/{Services-CuFGnNsb.js → Services-Dd41PCaY.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CtUC0mDa.js → Skeleton-Bzo1cN80.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-P1qgOVFn.js → Skills-BDHh17P0.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-CsppE8YV.js → Sla-jl7UTiRY.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-Cq1oG56m.js → SpeechSettings-BePa-RF6.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DdKW6V-C.js → SyncSettings-DiqqDKGZ.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-BCc9san5.js → Tasks-DYQ_6lxj.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CcHC1dMA.js → Templates-JiDeI06L.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CA4PqU22.js → Tenant-hhgI6zwS.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-CjTZPa37.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-DHWTSvOy.js → TimelineRenderer-B8uB5Llk.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-Ddz-P_yh.js → Tokens-C3b_6r2z.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-ePmrmLZ1.js → Trigger-tIP7HKVe.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DmuK1CCE.js → Trust-vjoc11vJ.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CqqBuRrT.js → UkeySign-DUPBnGuH.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-BGlR3uWM.js → VideoEditing-CBvhUY5T.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-Ba_Qx6Ga.js → Wallet-DUaQ0uA5.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-29neXKt2.js → WebAuthn-DllSivjE.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-lD0lR0UQ.js → WorkflowEditor-xc8D3uO6.js} +1 -1
- package/src/assets/web-panel/assets/{chat-B3stH01u.js → chat-BVicU7oA.js} +1 -1
- package/src/assets/web-panel/assets/{colors-Czly56MN.js → colors-DJzLmhLm.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-C0TkbkAJ.js → compact-item-BvYRfThE.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BJmpSlf1.js → createContext-DGXxCBKR.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BT46Y_QI.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-D1q-zw7u.js → hasIn-SBDJB1y4.js} +1 -1
- package/src/assets/web-panel/assets/{index-DV-twjNO.js → index-1SdDS6lR.js} +1 -1
- package/src/assets/web-panel/assets/{index-B-kTvMq7.js → index-9gdI7uUW.js} +1 -1
- package/src/assets/web-panel/assets/index-B7nuIywP.js +1 -0
- package/src/assets/web-panel/assets/{index-Bm_-RKal.js → index-BJZf9DhV.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQftlZn-.js → index-BO1itZaY.js} +3 -3
- package/src/assets/web-panel/assets/{index-Dw3L_smW.js → index-BTrBGBJs.js} +1 -1
- package/src/assets/web-panel/assets/{index-C7sFKQ53.js → index-BYqz4Wrr.js} +1 -1
- package/src/assets/web-panel/assets/{index-DlvsSuBC.js → index-Bf-ctERC.js} +1 -1
- package/src/assets/web-panel/assets/{index-ChESIe5r.js → index-CKyEivf8.js} +1 -1
- package/src/assets/web-panel/assets/{index-DaqEHaCg.js → index-CdGY9P8a.js} +1 -1
- package/src/assets/web-panel/assets/{index-DZeoKL6t.js → index-Cf-O_g_8.js} +1 -1
- package/src/assets/web-panel/assets/{index-XWV8JWMc.js → index-CloCgBUR.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpMIdPJ0.js → index-CoJAO1Lm.js} +1 -1
- package/src/assets/web-panel/assets/{index-CgS8XUBU.js → index-Crk5NTb0.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmUta2lw.js → index-Cs2rmLFt.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dpz_7sf-.js → index-CtwqO5qo.js} +1 -1
- package/src/assets/web-panel/assets/{index-DRcQsPez.js → index-D7HimK0M.js} +1 -1
- package/src/assets/web-panel/assets/{index-BEt2-3x5.js → index-DCdRAgjy.js} +1 -1
- package/src/assets/web-panel/assets/{index-CHvPlzWJ.js → index-DCqRS6da.js} +1 -1
- package/src/assets/web-panel/assets/{index-BDHXx65P.js → index-DHVLJ8q0.js} +1 -1
- package/src/assets/web-panel/assets/{index-K4YaPDOn.js → index-DKrvvWm4.js} +1 -1
- package/src/assets/web-panel/assets/{index-C1pOqU7D.js → index-DMarmfrv.js} +1 -1
- package/src/assets/web-panel/assets/{index-DAhrn9EJ.js → index-DRfiXB_p.js} +1 -1
- package/src/assets/web-panel/assets/{index-cPjWjvmW.js → index-Dm_77jgR.js} +1 -1
- package/src/assets/web-panel/assets/{index-C27TnOoT.js → index-DnjPdvR6.js} +1 -1
- package/src/assets/web-panel/assets/{index-upY9rkGZ.js → index-DonCnfMr.js} +1 -1
- package/src/assets/web-panel/assets/{index-CbvNJUwu.js → index-DvUTDYXX.js} +1 -1
- package/src/assets/web-panel/assets/{index-BVwJ3jht.js → index-FxZzRyE1.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIF6XHIi.js → index-MjC4G09d.js} +1 -1
- package/src/assets/web-panel/assets/{index-B8KqsomG.js → index-VMfwIH5G.js} +1 -1
- package/src/assets/web-panel/assets/{index-8GKykbS4.js → index-YJkzy8ZF.js} +1 -1
- package/src/assets/web-panel/assets/{index-DpGs96FC.js → index-d5BVd-cL.js} +1 -1
- package/src/assets/web-panel/assets/{index-DO8xOwxi.js → index-e4fXH_WO.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cu_4HaUS.js → index-hxTODbM1.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cf7Gr3NG.js → index-lpaGoTH3.js} +1 -1
- package/src/assets/web-panel/assets/{index-DBqAm8es.js → index-wcCL-miV.js} +1 -1
- package/src/assets/web-panel/assets/{index-ZDUhX41Z.js → index-xfluRkCT.js} +1 -1
- package/src/assets/web-panel/assets/index-ycwAfC-i.js +1 -0
- package/src/assets/web-panel/assets/{index-z8ATo2aQ.js → index-z1ZylsLq.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-QWEXi6-t.js → initDefaultProps-C1zO1KnY.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BfrQwvV1.js → motion-CWLtEGmC.js} +1 -1
- package/src/assets/web-panel/assets/{move-Dn7x0H9t.js → move-DzD_C3Vm.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-F61D_TgE.js → mtc-parser-D880PYJl.js} +1 -1
- package/src/assets/web-panel/assets/{omit-4SQZ39PF.js → omit-CFR_z2ov.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-C7DTe126.js → pickAttrs-srIhgrSC.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-40NeyzDK.js → placementArrow-C1rXpibP.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BiUJ6qWs.js → responsiveObserve-C30gRcSS.js} +1 -1
- package/src/assets/web-panel/assets/{slide-CacJTM3f.js → slide-CvtKiMfV.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-K812HB-k.js → statusUtils-DNHO7ITG.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-CKeHA2eM.js → styleChecker-Dt_Sl-g4.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-CKl4FqXF.js → useFlexGapSupport-Cjev42Gh.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-DPoiJjSZ.js → useFs-Baxglj2V.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-aHwBspmt.js → usePersonalDataHub-B4NkcLaP.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DrA-GuCT.js → vnode-mIRkdT7o.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-G3LMswgy.js → zoom-HzI5DlH_.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/auth/npm-auth.js +30 -5
- package/src/commands/agenda.js +64 -2
- package/src/commands/agent.js +45 -3
- package/src/commands/background-session.js +103 -0
- package/src/commands/config.js +70 -5
- package/src/commands/context.js +36 -2
- package/src/commands/hub.js +19 -1
- package/src/commands/memory.js +21 -6
- package/src/commands/permissions.js +57 -1
- package/src/commands/plugin.js +2 -0
- package/src/commands/review.js +23 -11
- package/src/commands/routine.js +31 -8
- package/src/commands/session.js +11 -3
- package/src/commands/team.js +20 -7
- package/src/commands/update.js +65 -10
- package/src/esm-bridge.js +3 -0
- package/src/gateways/terminal/PtyManager.js +8 -1
- package/src/gateways/ws/message-dispatcher.js +3 -0
- package/src/gateways/ws/session-protocol.js +26 -0
- package/src/gateways/ws/ws-agent-handler.js +107 -69
- package/src/gateways/ws/ws-server.js +92 -4
- package/src/harness/jsonl-session-store.js +13 -6
- package/src/harness/mcp-client.js +200 -1
- package/src/index.js +123 -55
- package/src/lazy-dispatch.js +86 -85
- package/src/lib/__tests__/personal-data-hub-aichat-wizard.test.js +15 -0
- package/src/lib/agent-coordinator.js +4 -0
- package/src/lib/agent-ipc-bus.js +32 -2
- package/src/lib/agent-sandbox.js +16 -2
- package/src/lib/agent-schedule-store.js +55 -0
- package/src/lib/agent-tool-admission.js +104 -0
- package/src/lib/api-key-helper.js +10 -2
- package/src/lib/async-hook-supervisor.cjs +26 -4
- package/src/lib/background-interaction-resolver.js +71 -0
- package/src/lib/background-session-transport.js +59 -1
- package/src/lib/changelog.js +19 -11
- package/src/lib/channels/channel-manager.js +6 -0
- package/src/lib/channels/telegram-channel.js +11 -1
- package/src/lib/channels/webhook-channel.js +15 -3
- package/src/lib/checkpoint-store.js +10 -2
- package/src/lib/cloud/bundle.js +12 -2
- package/src/lib/code-review.js +32 -8
- package/src/lib/computer-use/control-backend.js +18 -3
- package/src/lib/context-breakdown.js +46 -0
- package/src/lib/context-source-ledger.js +43 -0
- package/src/lib/crash-reporter.js +6 -0
- package/src/lib/diff-review-follow-up.js +154 -0
- package/src/lib/downloader.js +17 -3
- package/src/lib/ensure-utf8.js +11 -3
- package/src/lib/event-runtime-producer.js +58 -0
- package/src/lib/event-runtime-store.js +354 -0
- package/src/lib/event-runtime-worker.js +109 -0
- package/src/lib/execution-backend.js +72 -21
- package/src/lib/git-integration.js +19 -4
- package/src/lib/hook-manager.js +34 -15
- package/src/lib/hook-runner.cjs +48 -3
- package/src/lib/hooks-v2-producers.js +15 -0
- package/src/lib/hooks-v2-runtime.js +70 -21
- package/src/lib/host-adb-bridge.js +111 -21
- package/src/lib/ide-context.js +128 -1
- package/src/lib/interaction-adapter.js +39 -0
- package/src/lib/ipc-attach-protocol.js +98 -0
- package/src/lib/json-schema-validate.js +190 -36
- package/src/lib/lan-pairing-preflight.js +13 -2
- package/src/lib/lsp/__tests__/lsp-server-registry.test.js +18 -0
- package/src/lib/lsp/lsp-client.js +18 -1
- package/src/lib/lsp/lsp-manager.js +4 -0
- package/src/lib/lsp/lsp-server-registry.js +11 -0
- package/src/lib/mcp-oauth.js +8 -2
- package/src/lib/npm-invocation.js +29 -0
- package/src/lib/packer/pkg-runner.js +13 -2
- package/src/lib/packer/precheck.js +33 -16
- package/src/lib/packer/web-panel-builder.js +16 -2
- package/src/lib/permission-rules.cjs +5 -1
- package/src/lib/personal-data-hub-aichat-wizard.js +22 -6
- package/src/lib/personal-data-hub-wiring.js +27 -3
- package/src/lib/plan-mode.js +204 -11
- package/src/lib/plugin-monitor-supervisor.js +39 -4
- package/src/lib/plugin-runtime/bin.js +45 -0
- package/src/lib/plugin-runtime/hooks.js +14 -1
- package/src/lib/plugin-runtime/install.js +2 -1
- package/src/lib/plugin-runtime/lsp.js +3 -0
- package/src/lib/plugin-runtime/mcp.js +8 -1
- package/src/lib/plugin-runtime/monitors.js +4 -0
- package/src/lib/plugin-runtime/plugin-options.js +74 -7
- package/src/lib/plugin-runtime/signature.js +45 -0
- package/src/lib/pr-create.js +21 -8
- package/src/lib/pr-link-ledger.js +15 -3
- package/src/lib/process-execution-broker/credential-agent.js +295 -0
- package/src/lib/process-execution-broker/index.js +440 -14
- package/src/lib/process-execution-broker/patch-child-process.js +2 -3
- package/src/lib/process-execution-broker/platform-sandbox.js +351 -0
- package/src/lib/process-manager.js +18 -3
- package/src/lib/provenance-api.js +6 -0
- package/src/lib/proxy-bootstrap.js +19 -0
- package/src/lib/publish-workspace.js +14 -6
- package/src/lib/repl-rewind.js +9 -4
- package/src/lib/secret-store.js +159 -0
- package/src/lib/service-manager.js +64 -29
- package/src/lib/session-hooks.js +328 -473
- package/src/lib/session-telemetry-middleware.js +6 -0
- package/src/lib/settings-hook-events.cjs +61 -1
- package/src/lib/settings-hooks.cjs +4 -0
- package/src/lib/side-effect-ledger.js +22 -0
- package/src/lib/sub-agent-context.js +5 -0
- package/src/lib/sub-agent-profiles.js +4 -0
- package/src/lib/trace-api.js +6 -0
- package/src/lib/turn-context.js +14 -8
- package/src/lib/unattended-action-policy.js +83 -0
- package/src/lib/update-notice.js +9 -45
- package/src/lib/with-file-lock.js +7 -0
- package/src/lib/ws-server.js +1 -0
- package/src/repl/agent-repl.js +71 -13
- package/src/repl/clipboard-copy.js +8 -2
- package/src/repl/pr-comments.js +30 -7
- package/src/runtime/agent-core.js +439 -87
- package/src/runtime/agent-runtime.js +1 -0
- package/src/runtime/coding-agent-contract-shared.cjs +52 -0
- package/src/runtime/coding-agent-policy.cjs +20 -0
- package/src/runtime/diagnostics.js +73 -8
- package/src/runtime/headless-runner.js +63 -0
- package/src/runtime/headless-stream.js +269 -17
- package/src/runtime/mcp-config.js +16 -1
- package/src/workers/background-agent-worker.js +80 -1
- package/src/assets/web-panel/assets/AppLayout-7iSKDmlI.js +0 -9
- package/src/assets/web-panel/assets/ChatBubbleRenderer-DcbUHeGW.js +0 -1
- package/src/assets/web-panel/assets/Dashboard-BAKYNavw.js +0 -3
- package/src/assets/web-panel/assets/MobileProjects-C4GKn1dH.js +0 -1
- package/src/assets/web-panel/assets/Terminal-Fj7ea0In.js +0 -3
- package/src/assets/web-panel/assets/devWarning-CDI8Sbaj.js +0 -1
- package/src/assets/web-panel/assets/index-96LBR96V.js +0 -1
- 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
|
|
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
|
-
*
|
|
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
|
|
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
|
-
//
|
|
11
|
-
|
|
12
|
-
import
|
|
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
|
-
//
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
|
|
39
|
-
// 非阻塞更新检查,不影响启动流程
|
|
23
|
+
for (const entry of manifest.commands) {
|
|
40
24
|
try {
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
//
|
|
51
|
-
|
|
52
|
-
|
|
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
|
-
//
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
111
|
+
return program;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Backward compat alias
|
|
115
|
+
export { createProgram as createProgramSync };
|
|
64
116
|
|
|
65
|
-
|
|
66
|
-
|
|
117
|
+
/**
|
|
118
|
+
* Async version (alias for consistency)
|
|
119
|
+
*/
|
|
120
|
+
export async function createProgramAsync() {
|
|
121
|
+
return createProgram();
|
|
67
122
|
}
|
|
68
123
|
|
|
69
|
-
main()
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
+
}
|
package/src/lazy-dispatch.js
CHANGED
|
@@ -1,107 +1,108 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Lazy CLI dispatch
|
|
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 {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
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(
|
|
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
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (
|
|
46
|
-
|
|
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
|
|
52
|
-
|
|
53
|
-
}
|
|
32
|
+
export async function runCli(argv) {
|
|
33
|
+
const args = argv.slice(2);
|
|
54
34
|
|
|
55
|
-
|
|
56
|
-
//
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
//
|
|
80
|
-
|
|
81
|
-
const
|
|
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
|
-
|
|
84
|
-
const
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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 }))],
|