chainlesschain 0.162.158 → 0.162.160
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/README.md +1 -1
- package/package.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-BwpTJTN_.js → AIOps-CkRHjW8e.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BtQOoo3l.js → ActionButton-BP3MeNi2.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-Duf_rXZa.js → Analytics-CjbjQsOr.js} +2 -2
- package/src/assets/web-panel/assets/{AppLayout-XQK3wjvB.js → AppLayout-i0adH1M8.js} +5 -5
- package/src/assets/web-panel/assets/Artifacts-CCCG2GOU.js +1 -0
- package/src/assets/web-panel/assets/{Audit-DNjOGQLh.js → Audit-DrsgvwHC.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-FH9RAfB5.js → BackgroundAgents-DkXNkbZM.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-ZIbrR4-U.js → Backup-DarTWCex.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-DSt3NaND.js → BaseInput-DaDzhcto.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CY-wvbjv.js → Chat-C4EzGw6V.js} +5 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-lkavIWMS.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-8JVadE_B.js → Checkbox-gddNgaQi.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CN83nPYI.js → Codegen-BKldFWf9.js} +1 -1
- package/src/assets/web-panel/assets/{Col-xPSvqdN8.js → Col-ChR-brDs.js} +1 -1
- package/src/assets/web-panel/assets/{Community-D78cnIjG.js → Community-DlHtZX86.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-CSw6Csbp.js → Compact-BAhfcBpC.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-E_HhjcYR.js → Compliance-gIrKkm6m.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DybeQjmm.js → Cowork-BYnzLBO3.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-DS0BJeLY.js → Cron-ByUDIljI.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BOwVgkbs.js → Crosschain-DOdNbHFp.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DRUr9YuX.js → DID-BJHaNWD2.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-Cht-yUKW.js → Dashboard-Drm_tClz.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-BLr_EJ9X.js → Dropdown-CA1WLzGN.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-Drexuh5W.js → EmailListRenderer-Di1SKjNO.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-D9Q2Kq63.js → FamilyGuardDashboard-44Ve7ZFe.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-C-Z1xI-T.js → Federation-CubPwv_N.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DLHPMkQF.js → FormItemContext-CsUFe5bU.js} +1 -1
- package/src/assets/web-panel/assets/GenericCardRenderer-D7xRjPjZ.js +1 -0
- package/src/assets/web-panel/assets/{Git-syATcaBt.js → Git-D-Qx9dhO.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CYe_r8Zf.js → Governance-_YMYaU4n.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-GWxErB7k.js → Inference-J7Yzh-K_.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-qQvVCZoi.js → KnowledgeGraph-D37iI_Mo.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BenAU2W8.js → Logs-oMTSYfGY.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-7agE3Or1.js → MarkdownRenderer-BqaPmC0W.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-D4Jn5fpD.js → Marketplace-DKUqYDaF.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DtAwoqiQ.js → McpTools-BEv3Gx61.js} +4 -4
- package/src/assets/web-panel/assets/{Memory-BI_O50I8.js → Memory-CtA8XD2y.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-CQWE2lqx.js → MobileBridge-ug7c1mMj.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-BpX5g9It.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-Dnr16qsn.js → Mtc-WJaMs4i2.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-CQ5Xe4-a.js → MtcAudit-DXnK_-ru.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-Bjr8O-wy.js → Multisig-C4Ev7726.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-CEe-KirU.js → NLProgramming-BMFb9_zk.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-spKJIKF9.js → Notes-Bl93nvBX.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-DRp83LFG.js → NotificationSettings-BN2W5cl6.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-h1A0XB2a.js → OrderTableRenderer-Dxc9oN4o.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BlgB0IYg.js → Organization-CAs48637.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-a_35HqZI.js → Overflow-Bhq27Zoc.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CSNHCNPC.js → P2P-D61-2542.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-C8M1JH-1.js → PdhVaultBrowser-C1j4iUxz.js} +5 -5
- package/src/assets/web-panel/assets/{Permissions-DmjJi9Ms.js → Permissions-rJ2-fScM.js} +3 -3
- package/src/assets/web-panel/assets/{PersonalDataHub-DfuwRyf4.js → PersonalDataHub-DFIlTok6.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-B2-S4ekE.js → Pipeline-BjIgEWoZ.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-B1dOiBLC.js → Privacy-BQoH5wcX.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-_pNmc-DX.js → ProjectInit-CYR_-_Ub.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-DmwG2Ii1.js → ProjectSettings-nkatCq-9.js} +2 -2
- package/src/assets/web-panel/assets/Projects-SS9uZKCl.js +1 -0
- package/src/assets/web-panel/assets/{Providers-C6HSjg1d.js → Providers-BnKM9fsF.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-CrDmS7l1.js → QrScannerModal-Cfe82dbz.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-CfKvWt-x.js → QuickAsk-r1RbPufV.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DMa6Kuzv.js → Recommend-CjCbM2WE.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-DrktUo5x.js → RemoteSession-BuMGPH6V.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-BTPQ1vjL.js → Reputation-Bmj3NY1F.js} +1 -1
- package/src/assets/web-panel/assets/{Row-B6Q7QkMG.js → Row-BIsNcE_1.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-B1IJhAmX.js → RssFeed-BObmojD2.js} +3 -3
- package/src/assets/web-panel/assets/{Search-xbea1kGD.js → Search-BRmbkQNS.js} +1 -1
- package/src/assets/web-panel/assets/{Security-7rs0cO3F.js → Security-_rF3DRpY.js} +2 -2
- package/src/assets/web-panel/assets/{Services-0fjixK0S.js → Services-D0If9ZV4.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-B_rVq9Cu.js → Skeleton-o7zIksUg.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-C5uM90b9.js → Skills-oUR7zi9u.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-U4pYCIZH.js → Sla-fqKyGi03.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-Cdz4yTWx.js → SpeechSettings-B1wZ_gxx.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-Me3aetHv.js → SyncSettings-B3qJWYXq.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-Cf6aNkL_.js → Tasks-BH5_dUfr.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CYatk4tU.js → Templates-CCIVpjRP.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-DIMKLw7o.js → Tenant-2GZtTGnB.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-C_cp-uSJ.js → Terminal-BlMkfs_u.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-cUPVNADp.js → TimelineRenderer-U6hi5OMc.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-CiaEIXVf.js → Tokens-C-_BerGJ.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-DB1WU5lQ.js → Trigger-DaKzBgN3.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-Cfht9Ijy.js → Trust-CLvcsco3.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-K3P4Vt9S.js → UkeySign-BFn_Y1zZ.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-DWjhjXRh.js → VideoEditing-B0V18dLT.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-D9-Q1Kan.js → Wallet-BbmP7Imu.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-BDszy-oV.js → WebAuthn-Dewj_0kt.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-DIhij4rA.js → WorkflowEditor-DOxz3Lwa.js} +1 -1
- package/src/assets/web-panel/assets/{chat-D7VCiKbh.js → chat-B1OIpZnh.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BvOd9pVn.js → colors-CSGNVdri.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-DoqXBiAO.js → compact-item-8S0vcg0u.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-CrKRzUtp.js → createContext-vZyc27TN.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DYEZcY55.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-BWAev4WC.js → hasIn-DWw3-UhA.js} +1 -1
- package/src/assets/web-panel/assets/{index-DvDOpsJB.js → index-B4pP2ycr.js} +1 -1
- package/src/assets/web-panel/assets/{index-oY45XrkG.js → index-BDHyovnK.js} +1 -1
- package/src/assets/web-panel/assets/{index-CmJ6xKBO.js → index-BKEmQQvR.js} +1 -1
- package/src/assets/web-panel/assets/{index-BoYrS_L2.js → index-BQssf0EQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-ww1QtLnX.js → index-BZnauCqN.js} +1 -1
- package/src/assets/web-panel/assets/{index-BWWsaimP.js → index-BdyokEau.js} +1 -1
- package/src/assets/web-panel/assets/{index-CoD31Ndm.js → index-BeBv896m.js} +1 -1
- package/src/assets/web-panel/assets/{index-DlGu7As6.js → index-BjC-TrOb.js} +1 -1
- package/src/assets/web-panel/assets/{index-zH-tuuGZ.js → index-BkWd6YL7.js} +1 -1
- package/src/assets/web-panel/assets/{index-CEXfKSiI.js → index-BoIPHP4R.js} +1 -1
- package/src/assets/web-panel/assets/{index-CEPHMSih.js → index-BuB5P0TR.js} +1 -1
- package/src/assets/web-panel/assets/{index-PDxGjKRu.js → index-BwKrTVV0.js} +1 -1
- package/src/assets/web-panel/assets/{index-BkgnGX7v.js → index-C6r27A-o.js} +1 -1
- package/src/assets/web-panel/assets/{index-DV-Rfmfx.js → index-CB2MOS_8.js} +3 -3
- package/src/assets/web-panel/assets/{index-KR1-Em9C.js → index-CFQWZvak.js} +1 -1
- package/src/assets/web-panel/assets/{index-8g5TJCZ3.js → index-CI3slBKI.js} +1 -1
- package/src/assets/web-panel/assets/{index-BCyP071m.js → index-CJgKP2cm.js} +1 -1
- package/src/assets/web-panel/assets/{index-CSb-tnIo.js → index-CLPr2vC_.js} +1 -1
- package/src/assets/web-panel/assets/{index-1poMpMU0.js → index-CbZqw7pg.js} +1 -1
- package/src/assets/web-panel/assets/{index-BZGk8AbZ.js → index-CfEvacz7.js} +1 -1
- package/src/assets/web-panel/assets/{index-BXyl8O23.js → index-CwXBblm-.js} +1 -1
- package/src/assets/web-panel/assets/{index-BHOcVYrx.js → index-D1i_8oop.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bq_ctRpz.js → index-D8qXVfoV.js} +1 -1
- package/src/assets/web-panel/assets/{index-gmxqu5Kk.js → index-DKwl1AkQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-D23L1V76.js → index-DLAvUtOH.js} +1 -1
- package/src/assets/web-panel/assets/{index-CDGLdn12.js → index-DLgkAhEE.js} +1 -1
- package/src/assets/web-panel/assets/{index-YGDy7nNq.js → index-DPgY5GLy.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cx7M7PSF.js → index-Dc40pX3F.js} +1 -1
- package/src/assets/web-panel/assets/{index-JzUmJMvn.js → index-DcfLXAW7.js} +1 -1
- package/src/assets/web-panel/assets/{index-HwHdTusY.js → index-DeCS12Mh.js} +1 -1
- package/src/assets/web-panel/assets/{index-B30NvR21.js → index-Dg0Izipr.js} +1 -1
- package/src/assets/web-panel/assets/index-DmVFfcNR.js +1 -0
- package/src/assets/web-panel/assets/{index-B0vGEbJT.js → index-DtHWHJnj.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bf9YlbDn.js → index-Q6oyLnKC.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bj7EgmOp.js → index-dxocDVD_.js} +1 -1
- package/src/assets/web-panel/assets/{index-ISvPZ05r.js → index-t-q3rkVm.js} +1 -1
- package/src/assets/web-panel/assets/{index-C5kRmj3P.js → index-tr1x96W9.js} +1 -1
- package/src/assets/web-panel/assets/index-x7YyhMUa.js +1 -0
- package/src/assets/web-panel/assets/{index-BN9m4Ux2.js → index-xx5M5Rbj.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-XW-OR3mL.js → initDefaultProps-Di5YFId0.js} +1 -1
- package/src/assets/web-panel/assets/{motion-CeuEHh20.js → motion-BVSN0aeL.js} +1 -1
- package/src/assets/web-panel/assets/{move-Dva79Keg.js → move-DHNiaP2l.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-C0B6bD2j.js → mtc-parser-xJPf3gQD.js} +1 -1
- package/src/assets/web-panel/assets/{omit-AkZvO-a2.js → omit-C7qzUdkN.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-B4r55qGc.js → pickAttrs-pSpjg3Le.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BLH-z7YE.js → placementArrow-cs_jL_UC.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-ksEGZ2Wf.js → responsiveObserve-DkS_Zs4r.js} +1 -1
- package/src/assets/web-panel/assets/{slide-Cth4OD1Z.js → slide-B5O1Kpxo.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-9S83ezxw.js → statusUtils-BX02GnZp.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-7yQmQGZ4.js → styleChecker-EmBYRftd.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-DpGnMmPc.js → useFlexGapSupport-ZGzN1cU8.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-C4zDZIXH.js → useFs-CfP7M1m7.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-CoLICdUZ.js → usePersonalDataHub-CbIPHgNh.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-CKyH-35X.js → vnode-7xh0If_O.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-DRDGit17.js → zoom-DmitvTR2.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-manifest.json +17 -3
- package/src/commands/agent.js +72 -6
- package/src/commands/background-session.js +173 -3
- package/src/commands/browse.js +86 -0
- package/src/commands/cloud.js +232 -0
- package/src/commands/doctor.js +61 -6
- package/src/commands/mcp.js +107 -0
- package/src/commands/plugin.js +63 -1
- package/src/commands/routine.js +367 -0
- package/src/commands/session.js +396 -0
- package/src/data/changelog.json +12 -2
- package/src/harness/jsonl-session-store.js +152 -3
- package/src/harness/mcp-client.js +50 -0
- package/src/harness/session-index.js +295 -0
- package/src/harness/session-mirror.js +142 -0
- package/src/harness/transcript-integrity.js +182 -0
- package/src/index.js +8 -0
- package/src/lib/agent-sandbox.js +68 -0
- package/src/lib/agents.js +12 -4
- package/src/lib/api-key-helper.js +62 -0
- package/src/lib/background-agent-supervisor.js +158 -2
- package/src/lib/channels/channel-manager.js +126 -0
- package/src/lib/channels/telegram-channel.js +112 -0
- package/src/lib/channels/webhook-channel.js +140 -0
- package/src/lib/chrome-connector.js +386 -0
- package/src/lib/cloud/bundle.js +110 -0
- package/src/lib/cloud/cloud-client.js +152 -0
- package/src/lib/computer-use/authorization.js +173 -0
- package/src/lib/computer-use/computer-use-server.js +276 -0
- package/src/lib/computer-use/control-backend.js +150 -0
- package/src/lib/dependency-install-policy.js +130 -0
- package/src/lib/doctor-checkup.js +652 -0
- package/src/lib/exit-codes.cjs +77 -0
- package/src/lib/headless-manifest.js +175 -0
- package/src/lib/hook-runner.cjs +70 -4
- package/src/lib/ide-context-redaction.js +130 -0
- package/src/lib/ide-context.js +89 -13
- package/src/lib/jsonl-session-store.js +6 -0
- package/src/lib/llm-config-defaults.js +24 -8
- package/src/lib/lsp/lsp-server-registry.js +48 -21
- package/src/lib/plugin-runtime/governance.js +174 -0
- package/src/lib/pr-link-ledger.js +221 -0
- package/src/lib/project-mcp-trust.js +87 -0
- package/src/lib/routine-store.js +352 -0
- package/src/lib/sensitive-file-guard.js +51 -0
- package/src/lib/session-store-guard.js +40 -0
- package/src/lib/session-usage.js +318 -2
- package/src/lib/sub-agent-context.js +30 -3
- package/src/repl/agent-repl.js +361 -3
- package/src/repl/bg-dashboard.js +355 -0
- package/src/repl/fast-mode.js +103 -0
- package/src/repl/fullscreen-tui.js +197 -0
- package/src/repl/slash-command-registry.js +11 -3
- package/src/repl/voice-dictation.js +132 -0
- package/src/runtime/agent-core.js +344 -7
- package/src/runtime/coding-agent-contract-shared.cjs +107 -2
- package/src/runtime/coding-agent-policy.cjs +17 -0
- package/src/runtime/headless-runner.js +137 -14
- package/src/runtime/headless-stream.js +43 -9
- package/src/runtime/mcp-config.js +32 -1
- package/src/runtime/policies/agent-policy.js +3 -0
- package/src/assets/web-panel/assets/Artifacts-DQvJoQ6E.js +0 -1
- package/src/assets/web-panel/assets/ChatBubbleRenderer-BAV9V-t-.js +0 -1
- package/src/assets/web-panel/assets/GenericCardRenderer-DxxEdn2r.js +0 -1
- package/src/assets/web-panel/assets/MobileProjects-CVtTqgtg.js +0 -1
- package/src/assets/web-panel/assets/Projects-COATmHxF.js +0 -1
- package/src/assets/web-panel/assets/devWarning-nDB--2xr.js +0 -1
- package/src/assets/web-panel/assets/index-B1_pRTtB.js +0 -1
- package/src/assets/web-panel/assets/index-TMM9FuW-.js +0 -1
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cc cloud` — self-hosted cloud handoff (gap-2026-07-11 P1#7).
|
|
3
|
+
*
|
|
4
|
+
* cc cloud run "<task>" bundle branch → submit to the private runner → record job
|
|
5
|
+
* cc cloud status [id] poll job(s) (last job when id omitted)
|
|
6
|
+
* cc cloud attach <id> wait for completion, reflow patch/plan/pr/artifacts locally
|
|
7
|
+
* cc cloud list local job ledger
|
|
8
|
+
*
|
|
9
|
+
* Runner endpoint + token come from config (cloud.baseUrl / cloud.token) or
|
|
10
|
+
* env (CC_CLOUD_URL / CC_CLOUD_TOKEN). See src/lib/cloud/cloud-client.js for
|
|
11
|
+
* the runner protocol.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
16
|
+
import chalk from "chalk";
|
|
17
|
+
import { logger } from "../lib/logger.js";
|
|
18
|
+
|
|
19
|
+
async function resolveRunner() {
|
|
20
|
+
let cfg = {};
|
|
21
|
+
try {
|
|
22
|
+
cfg = (await import("../lib/config-manager.js")).loadConfig()?.cloud || {};
|
|
23
|
+
} catch {
|
|
24
|
+
cfg = {};
|
|
25
|
+
}
|
|
26
|
+
const baseUrl = process.env.CC_CLOUD_URL || cfg.baseUrl || "";
|
|
27
|
+
const token = process.env.CC_CLOUD_TOKEN || cfg.token || null;
|
|
28
|
+
return { baseUrl, token };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function statusColor(status) {
|
|
32
|
+
if (status === "done") return chalk.green;
|
|
33
|
+
if (status === "failed" || status === "timeout") return chalk.red;
|
|
34
|
+
if (status === "running") return chalk.cyan;
|
|
35
|
+
return chalk.gray;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function registerCloudCommand(program) {
|
|
39
|
+
const cloud = program
|
|
40
|
+
.command("cloud")
|
|
41
|
+
.description(
|
|
42
|
+
"Self-hosted cloud handoff — offload a task to a private runner (bundle → run → reflow)",
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
cloud
|
|
46
|
+
.command("run <task...>")
|
|
47
|
+
.description(
|
|
48
|
+
"Bundle the current branch and submit a task to the private runner",
|
|
49
|
+
)
|
|
50
|
+
.option("--json", "Output as JSON")
|
|
51
|
+
.option("--attach", "Wait for completion and reflow the result")
|
|
52
|
+
.action(async (taskWords, options) => {
|
|
53
|
+
try {
|
|
54
|
+
const task = taskWords.join(" ");
|
|
55
|
+
const { baseUrl, token } = await resolveRunner();
|
|
56
|
+
const { CloudClient, saveJob } =
|
|
57
|
+
await import("../lib/cloud/cloud-client.js");
|
|
58
|
+
const { bundleBranch } = await import("../lib/cloud/bundle.js");
|
|
59
|
+
const client = new CloudClient({ baseUrl, token });
|
|
60
|
+
|
|
61
|
+
logger.log(chalk.gray("Bundling current branch…"));
|
|
62
|
+
const snap = bundleBranch(process.cwd());
|
|
63
|
+
logger.log(
|
|
64
|
+
chalk.gray(
|
|
65
|
+
` ${snap.branch} @ ${snap.baseSha.slice(0, 8)} (${(snap.bytes / 1024).toFixed(0)} KB)`,
|
|
66
|
+
),
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
const submitted = await client.submit({
|
|
70
|
+
task,
|
|
71
|
+
bundle: snap.bundle,
|
|
72
|
+
branch: snap.branch,
|
|
73
|
+
baseSha: snap.baseSha,
|
|
74
|
+
});
|
|
75
|
+
const job = saveJob({
|
|
76
|
+
jobId: submitted.jobId,
|
|
77
|
+
task,
|
|
78
|
+
branch: snap.branch,
|
|
79
|
+
baseSha: snap.baseSha,
|
|
80
|
+
baseUrl,
|
|
81
|
+
status: "queued",
|
|
82
|
+
submittedAt: Date.now(),
|
|
83
|
+
cwd: process.cwd(),
|
|
84
|
+
});
|
|
85
|
+
if (options.json && !options.attach) {
|
|
86
|
+
return console.log(JSON.stringify(job, null, 2));
|
|
87
|
+
}
|
|
88
|
+
logger.success(`Submitted cloud job ${job.jobId} → ${baseUrl}`);
|
|
89
|
+
logger.log(chalk.gray(` cc cloud attach ${job.jobId}`));
|
|
90
|
+
if (options.attach) await attachJob(job.jobId, options);
|
|
91
|
+
} catch (err) {
|
|
92
|
+
logger.error(err.message);
|
|
93
|
+
process.exitCode = 1;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
cloud
|
|
98
|
+
.command("status [id]")
|
|
99
|
+
.description("Poll a cloud job's status (most recent when id omitted)")
|
|
100
|
+
.option("--json", "Output as JSON")
|
|
101
|
+
.action(async (id, options) => {
|
|
102
|
+
try {
|
|
103
|
+
const { CloudClient, readJob, listJobs, saveJob } =
|
|
104
|
+
await import("../lib/cloud/cloud-client.js");
|
|
105
|
+
const job = id ? readJob(id) : listJobs()[0];
|
|
106
|
+
if (!job)
|
|
107
|
+
throw new Error(id ? `job not found: ${id}` : "no cloud jobs");
|
|
108
|
+
const client = new CloudClient({
|
|
109
|
+
baseUrl: job.baseUrl,
|
|
110
|
+
token: (await resolveRunner()).token,
|
|
111
|
+
});
|
|
112
|
+
const status = await client.status(job.jobId);
|
|
113
|
+
saveJob({ ...job, status: status.status, lastSummary: status.summary });
|
|
114
|
+
if (options.json) return console.log(JSON.stringify(status, null, 2));
|
|
115
|
+
logger.log(
|
|
116
|
+
`${statusColor(status.status)(status.status)} ${job.jobId} ${chalk.gray(job.task)}`,
|
|
117
|
+
);
|
|
118
|
+
if (status.summary) logger.log(chalk.gray(` ${status.summary}`));
|
|
119
|
+
} catch (err) {
|
|
120
|
+
logger.error(err.message);
|
|
121
|
+
process.exitCode = 1;
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
cloud
|
|
126
|
+
.command("attach <id>")
|
|
127
|
+
.description("Wait for a cloud job to finish and reflow its result locally")
|
|
128
|
+
.option("--json", "Output as JSON")
|
|
129
|
+
.option("--no-apply", "Fetch the result but do not apply the patch")
|
|
130
|
+
.action(async (id, options) => {
|
|
131
|
+
try {
|
|
132
|
+
await attachJob(id, options);
|
|
133
|
+
} catch (err) {
|
|
134
|
+
logger.error(err.message);
|
|
135
|
+
process.exitCode = 1;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
cloud
|
|
140
|
+
.command("list", { isDefault: true })
|
|
141
|
+
.description("List local cloud jobs")
|
|
142
|
+
.option("--json", "Output as JSON")
|
|
143
|
+
.action(async (options) => {
|
|
144
|
+
try {
|
|
145
|
+
const { listJobs } = await import("../lib/cloud/cloud-client.js");
|
|
146
|
+
const jobs = listJobs();
|
|
147
|
+
if (options.json) return console.log(JSON.stringify(jobs, null, 2));
|
|
148
|
+
if (jobs.length === 0) {
|
|
149
|
+
logger.log(
|
|
150
|
+
chalk.gray("No cloud jobs. Submit one with `cc cloud run`."),
|
|
151
|
+
);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
for (const j of jobs) {
|
|
155
|
+
logger.log(
|
|
156
|
+
`${statusColor(j.status)((j.status || "?").padEnd(8))} ${j.jobId} ${chalk.gray(j.branch)} ${j.task}`,
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
} catch (err) {
|
|
160
|
+
logger.error(err.message);
|
|
161
|
+
process.exitCode = 1;
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async function attachJob(id, options = {}) {
|
|
167
|
+
const { CloudClient, readJob, saveJob, pollUntilDone } =
|
|
168
|
+
await import("../lib/cloud/cloud-client.js");
|
|
169
|
+
const { applyResultPatch, persistResultArtifacts } =
|
|
170
|
+
await import("../lib/cloud/bundle.js");
|
|
171
|
+
const { token } = await resolveRunner();
|
|
172
|
+
|
|
173
|
+
const job = readJob(id);
|
|
174
|
+
if (!job) throw new Error(`job not found: ${id}`);
|
|
175
|
+
const client = new CloudClient({ baseUrl: job.baseUrl, token });
|
|
176
|
+
|
|
177
|
+
logger.log(chalk.gray(`Waiting for ${id}…`));
|
|
178
|
+
const final = await pollUntilDone(client, id, {
|
|
179
|
+
onTick: (s) =>
|
|
180
|
+
logger.log(
|
|
181
|
+
chalk.gray(` ${s.status}${s.summary ? `: ${s.summary}` : ""}`),
|
|
182
|
+
),
|
|
183
|
+
});
|
|
184
|
+
saveJob({ ...job, status: final.status, lastSummary: final.summary });
|
|
185
|
+
|
|
186
|
+
if (final.status !== "done") {
|
|
187
|
+
logger.error(`Job ${id} ended ${final.status}: ${final.summary || ""}`);
|
|
188
|
+
process.exitCode = 1;
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const result = await client.result(id);
|
|
193
|
+
|
|
194
|
+
// Persist plan/artifacts under the job's local dir.
|
|
195
|
+
const { cloudJobsDir } = await import("../lib/cloud/cloud-client.js");
|
|
196
|
+
const destDir = join(cloudJobsDir(), `${id}-result`);
|
|
197
|
+
if (!existsSync(destDir)) mkdirSync(destDir, { recursive: true });
|
|
198
|
+
const written = persistResultArtifacts(result, destDir);
|
|
199
|
+
|
|
200
|
+
let applied = null;
|
|
201
|
+
if (result.patch && options.apply !== false) {
|
|
202
|
+
applied = applyResultPatch(result.patch, job.cwd || process.cwd());
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (options.json) {
|
|
206
|
+
return console.log(
|
|
207
|
+
JSON.stringify(
|
|
208
|
+
{ jobId: id, status: final.status, applied, written, pr: result.pr },
|
|
209
|
+
null,
|
|
210
|
+
2,
|
|
211
|
+
),
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
logger.success(`Job ${id} done`);
|
|
215
|
+
if (result.pr)
|
|
216
|
+
logger.log(chalk.magenta(` PR: ${result.pr.url || result.pr}`));
|
|
217
|
+
if (applied) {
|
|
218
|
+
logger.log(
|
|
219
|
+
applied.applied
|
|
220
|
+
? chalk.green(` patch: ${applied.reason}`)
|
|
221
|
+
: chalk.yellow(` patch: ${applied.reason} (saved under ${destDir})`),
|
|
222
|
+
);
|
|
223
|
+
if (!applied.applied) {
|
|
224
|
+
// Save the unapplied patch so the user can resolve it by hand.
|
|
225
|
+
persistResultArtifacts(
|
|
226
|
+
{ artifacts: [{ name: "result.patch", content: result.patch }] },
|
|
227
|
+
destDir,
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
for (const w of written) logger.log(chalk.gray(` wrote ${w}`));
|
|
232
|
+
}
|
package/src/commands/doctor.js
CHANGED
|
@@ -1,18 +1,40 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import logger from "../lib/logger.js";
|
|
3
3
|
import { collectDoctorReport } from "../runtime/diagnostics.js";
|
|
4
|
+
import {
|
|
5
|
+
collectCheckupSections,
|
|
6
|
+
runCheckupFixes,
|
|
7
|
+
unsafeFixCommands,
|
|
8
|
+
} from "../lib/doctor-checkup.js";
|
|
9
|
+
|
|
10
|
+
const LEVEL_ICON = {
|
|
11
|
+
ok: () => chalk.green("✔"),
|
|
12
|
+
warn: () => chalk.yellow("⚠"),
|
|
13
|
+
err: () => chalk.red("✖"),
|
|
14
|
+
info: () => chalk.gray("·"),
|
|
15
|
+
};
|
|
4
16
|
|
|
5
17
|
export function registerDoctorCommand(program) {
|
|
6
18
|
program
|
|
7
19
|
.command("doctor")
|
|
8
|
-
.
|
|
20
|
+
.alias("checkup")
|
|
21
|
+
.description("Diagnose your ChainlessChain environment (alias: checkup)")
|
|
9
22
|
.option("--json", "Output as machine-readable JSON")
|
|
23
|
+
.option("--fix", "Apply safe fixes (stale job files, git worktree prune)")
|
|
10
24
|
.action(async (options) => {
|
|
11
25
|
const report = await collectDoctorReport();
|
|
26
|
+
const sections = await collectCheckupSections({ cwd: process.cwd() });
|
|
27
|
+
const fixResults = options.fix ? await runCheckupFixes(sections) : null;
|
|
28
|
+
|
|
29
|
+
const checkupErrs = sections
|
|
30
|
+
.flatMap((s) => s.checks)
|
|
31
|
+
.filter((c) => c.level === "err").length;
|
|
12
32
|
|
|
13
33
|
if (options.json) {
|
|
14
|
-
console.log(
|
|
15
|
-
|
|
34
|
+
console.log(
|
|
35
|
+
JSON.stringify({ ...report, checkup: sections, fixResults }, null, 2),
|
|
36
|
+
);
|
|
37
|
+
if (report.summary.criticalFailed > 0 || checkupErrs > 0) {
|
|
16
38
|
process.exitCode = 1;
|
|
17
39
|
}
|
|
18
40
|
return;
|
|
@@ -41,6 +63,17 @@ export function registerDoctorCommand(program) {
|
|
|
41
63
|
logger.log(` ${icon} ${check.name}${detail}`);
|
|
42
64
|
}
|
|
43
65
|
|
|
66
|
+
// Layered checkup sections (config chain / provider / MCP / IDE /
|
|
67
|
+
// plugins / subagents / transcripts / background agents / worktrees).
|
|
68
|
+
for (const section of sections) {
|
|
69
|
+
logger.log(chalk.bold(`\n ${section.title}\n`));
|
|
70
|
+
for (const c of section.checks) {
|
|
71
|
+
const icon = (LEVEL_ICON[c.level] || LEVEL_ICON.info)();
|
|
72
|
+
const detail = c.detail ? chalk.gray(` — ${c.detail}`) : "";
|
|
73
|
+
logger.log(` ${icon} ${c.name}${detail}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
44
77
|
logger.log(chalk.bold("\n Port Status\n"));
|
|
45
78
|
for (const p of report.ports) {
|
|
46
79
|
const icon = p.open ? chalk.green("●") : chalk.gray("○");
|
|
@@ -54,13 +87,35 @@ export function registerDoctorCommand(program) {
|
|
|
54
87
|
logger.log(` ${icon} Free space: ${report.disk.freeGB.toFixed(1)} GB`);
|
|
55
88
|
}
|
|
56
89
|
|
|
90
|
+
// Applied fixes (--fix) and copyable commands for the rest.
|
|
91
|
+
if (fixResults && fixResults.length > 0) {
|
|
92
|
+
logger.log(chalk.bold("\n Fixes applied\n"));
|
|
93
|
+
for (const f of fixResults) {
|
|
94
|
+
const icon = f.applied ? chalk.green("✔") : chalk.red("✖");
|
|
95
|
+
logger.log(` ${icon} ${f.id}: ${f.detail}`);
|
|
96
|
+
}
|
|
97
|
+
} else if (options.fix) {
|
|
98
|
+
logger.log(chalk.gray("\n No safe fixes needed.\n"));
|
|
99
|
+
}
|
|
100
|
+
const manual = unsafeFixCommands(sections);
|
|
101
|
+
if (manual.length > 0) {
|
|
102
|
+
logger.log(
|
|
103
|
+
chalk.bold("\n Suggested commands (need your judgement)\n"),
|
|
104
|
+
);
|
|
105
|
+
for (const m of manual) {
|
|
106
|
+
logger.log(` ${chalk.gray("#")} ${m.description}`);
|
|
107
|
+
logger.log(` ${chalk.cyan(m.command)}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
57
111
|
logger.newline();
|
|
58
|
-
|
|
112
|
+
const totalIssues = report.summary.criticalFailed + checkupErrs;
|
|
113
|
+
if (report.summary.failed === 0 && checkupErrs === 0) {
|
|
59
114
|
logger.log(chalk.bold.green(" All checks passed!\n"));
|
|
60
|
-
} else if (
|
|
115
|
+
} else if (totalIssues > 0) {
|
|
61
116
|
logger.log(
|
|
62
117
|
chalk.bold.red(
|
|
63
|
-
` ${
|
|
118
|
+
` ${totalIssues} issue(s) found. See details above.\n`,
|
|
64
119
|
),
|
|
65
120
|
);
|
|
66
121
|
process.exitCode = 1;
|
package/src/commands/mcp.js
CHANGED
|
@@ -342,6 +342,67 @@ export function registerMcpCommand(program) {
|
|
|
342
342
|
}
|
|
343
343
|
});
|
|
344
344
|
|
|
345
|
+
// mcp computer-use — expose GUI control verbs as an MCP server (opt-in)
|
|
346
|
+
mcp
|
|
347
|
+
.command("computer-use")
|
|
348
|
+
.description(
|
|
349
|
+
"Expose GUI control (screenshot/window-list/click/type/scroll/clipboard/app-launch) as a Streamable-HTTP MCP server. OFF by default; input verbs need confirm:true; high-risk apps (terminals/IDEs/settings/password managers) always confirm",
|
|
350
|
+
)
|
|
351
|
+
.option("--port <n>", "Port to listen on (default: random free port)", "0")
|
|
352
|
+
.option(
|
|
353
|
+
"--capabilities <list>",
|
|
354
|
+
"Comma-separated subset (default: all): screenshot,window_list,app_launch,click,type,scroll,clipboard_read,clipboard_write",
|
|
355
|
+
)
|
|
356
|
+
.option(
|
|
357
|
+
"--allow-apps <list>",
|
|
358
|
+
"Comma-separated app allowlist for input/launch verbs (default: any app)",
|
|
359
|
+
)
|
|
360
|
+
.option(
|
|
361
|
+
"--confirm-all",
|
|
362
|
+
"Require confirm:true for every verb, not just input verbs",
|
|
363
|
+
)
|
|
364
|
+
.option("--token <token>", "Fixed Bearer token (default: random)")
|
|
365
|
+
.option("--no-auth", "Disable Bearer auth (server binds 127.0.0.1 only)")
|
|
366
|
+
.action(async (options) => {
|
|
367
|
+
try {
|
|
368
|
+
const { startComputerUseServer } =
|
|
369
|
+
await import("../lib/computer-use/computer-use-server.js");
|
|
370
|
+
const handle = await startComputerUseServer({
|
|
371
|
+
port: Number(options.port) || 0,
|
|
372
|
+
token: options.auth === false ? false : options.token || null,
|
|
373
|
+
config: {
|
|
374
|
+
capabilities: options.capabilities
|
|
375
|
+
? options.capabilities.split(",").map((s) => s.trim())
|
|
376
|
+
: undefined,
|
|
377
|
+
appAllowlist: options.allowApps
|
|
378
|
+
? options.allowApps.split(",").map((s) => s.trim())
|
|
379
|
+
: undefined,
|
|
380
|
+
confirmAll: options.confirmAll === true,
|
|
381
|
+
},
|
|
382
|
+
});
|
|
383
|
+
logger.log(
|
|
384
|
+
chalk.bold("Computer-use MCP server ready (Streamable-HTTP)"),
|
|
385
|
+
);
|
|
386
|
+
logger.log(` URL: ${chalk.cyan(handle.url)}`);
|
|
387
|
+
logger.log(` Capabilities: ${handle.capabilities.join(", ")}`);
|
|
388
|
+
if (handle.token) {
|
|
389
|
+
logger.log(` Auth: Bearer ${handle.token}`);
|
|
390
|
+
} else {
|
|
391
|
+
logger.log(chalk.yellow(" Auth: disabled (--no-auth)"));
|
|
392
|
+
}
|
|
393
|
+
logger.log(
|
|
394
|
+
chalk.yellow(
|
|
395
|
+
" ⚠ GUI control can act on anything on screen. Input verbs need confirm:true; high-risk apps always confirm.",
|
|
396
|
+
),
|
|
397
|
+
);
|
|
398
|
+
logger.log(chalk.gray("\nCtrl+C to stop."));
|
|
399
|
+
await new Promise(() => {});
|
|
400
|
+
} catch (err) {
|
|
401
|
+
logger.error(chalk.red(`mcp computer-use failed: ${err.message}`));
|
|
402
|
+
process.exitCode = 1;
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
|
|
345
406
|
// mcp servers — list configured servers
|
|
346
407
|
mcp
|
|
347
408
|
.command("servers")
|
|
@@ -938,6 +999,52 @@ export function registerMcpCommand(program) {
|
|
|
938
999
|
});
|
|
939
1000
|
|
|
940
1001
|
// mcp scaffold — generate a boilerplate MCP server project
|
|
1002
|
+
mcp
|
|
1003
|
+
.command("trust-project")
|
|
1004
|
+
.description(
|
|
1005
|
+
"Re-trust the project .mcp.json after reviewing a content change (records its fingerprint for --project-mcp runs)",
|
|
1006
|
+
)
|
|
1007
|
+
.option("--json", "Output as JSON")
|
|
1008
|
+
.action(async (options) => {
|
|
1009
|
+
try {
|
|
1010
|
+
const fsMod = await import("node:fs");
|
|
1011
|
+
const { projectRootBase } = await import("../lib/project-root.cjs");
|
|
1012
|
+
const { recordProjectMcpTrust, projectMcpFingerprint } =
|
|
1013
|
+
await import("../lib/project-mcp-trust.js");
|
|
1014
|
+
const cwd = process.cwd();
|
|
1015
|
+
const candidates = [path.join(cwd, ".mcp.json")];
|
|
1016
|
+
const root = projectRootBase(cwd, { fs: fsMod.default, path });
|
|
1017
|
+
if (root) candidates.push(path.join(root, ".mcp.json"));
|
|
1018
|
+
const results = [];
|
|
1019
|
+
for (const file of [...new Set(candidates)]) {
|
|
1020
|
+
if (!fsMod.existsSync(file)) continue;
|
|
1021
|
+
const content = fsMod.readFileSync(file, "utf-8");
|
|
1022
|
+
const ok = recordProjectMcpTrust(file, content);
|
|
1023
|
+
results.push({
|
|
1024
|
+
file,
|
|
1025
|
+
trusted: ok,
|
|
1026
|
+
fingerprint: projectMcpFingerprint(content).slice(0, 16),
|
|
1027
|
+
});
|
|
1028
|
+
}
|
|
1029
|
+
if (options.json) {
|
|
1030
|
+
console.log(JSON.stringify(results, null, 2));
|
|
1031
|
+
return;
|
|
1032
|
+
}
|
|
1033
|
+
if (results.length === 0) {
|
|
1034
|
+
console.log("No .mcp.json found in this project.");
|
|
1035
|
+
return;
|
|
1036
|
+
}
|
|
1037
|
+
for (const r of results) {
|
|
1038
|
+
console.log(
|
|
1039
|
+
`${r.trusted ? "Trusted" : "FAILED to record"} ${r.file} (${r.fingerprint})`,
|
|
1040
|
+
);
|
|
1041
|
+
}
|
|
1042
|
+
} catch (err) {
|
|
1043
|
+
console.error(`Failed: ${err.message}`);
|
|
1044
|
+
process.exitCode = 1;
|
|
1045
|
+
}
|
|
1046
|
+
});
|
|
1047
|
+
|
|
941
1048
|
mcp
|
|
942
1049
|
.command("scaffold <name>")
|
|
943
1050
|
.description("Scaffold a new MCP server project (stdio or http+sse)")
|
package/src/commands/plugin.js
CHANGED
|
@@ -538,10 +538,61 @@ export function registerPluginCommand(program) {
|
|
|
538
538
|
|
|
539
539
|
const counts = summarizeComponents(manifest);
|
|
540
540
|
|
|
541
|
+
// Dependency version constraints (gap P2#13): if the manifest declares
|
|
542
|
+
// `dependencies` (plugin name → semver range, plus reserved host/cc),
|
|
543
|
+
// check them against what's installed and the running cc version. Unmet
|
|
544
|
+
// deps are surfaced but do not by themselves fail structural validation —
|
|
545
|
+
// they may simply be absent in this environment.
|
|
546
|
+
let dependencyCheck = null;
|
|
547
|
+
try {
|
|
548
|
+
const rawManifest = manifest.manifestPath
|
|
549
|
+
? JSON.parse(
|
|
550
|
+
(await import("node:fs")).readFileSync(
|
|
551
|
+
manifest.manifestPath,
|
|
552
|
+
"utf8",
|
|
553
|
+
),
|
|
554
|
+
)
|
|
555
|
+
: {};
|
|
556
|
+
if (rawManifest && rawManifest.dependencies) {
|
|
557
|
+
const { checkPluginDependencies, formatDependencyIssues } =
|
|
558
|
+
await import("../lib/plugin-runtime/governance.js");
|
|
559
|
+
const { discoverPlugins } =
|
|
560
|
+
await import("../lib/plugin-runtime/scopes.js");
|
|
561
|
+
const { VERSION } = await import("../constants.js");
|
|
562
|
+
const installed = {};
|
|
563
|
+
try {
|
|
564
|
+
for (const p of discoverPlugins({ skipPolicy: true })) {
|
|
565
|
+
installed[p.name] = p.version;
|
|
566
|
+
}
|
|
567
|
+
} catch {
|
|
568
|
+
/* discovery best-effort */
|
|
569
|
+
}
|
|
570
|
+
const result = checkPluginDependencies(rawManifest, {
|
|
571
|
+
installed,
|
|
572
|
+
hostVersion: VERSION,
|
|
573
|
+
});
|
|
574
|
+
dependencyCheck = {
|
|
575
|
+
ok: result.ok,
|
|
576
|
+
issues: formatDependencyIssues(
|
|
577
|
+
manifest.metadata?.name || dir,
|
|
578
|
+
result,
|
|
579
|
+
),
|
|
580
|
+
...result,
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
} catch {
|
|
584
|
+
/* dependency inspection is best-effort */
|
|
585
|
+
}
|
|
586
|
+
|
|
541
587
|
if (options.json) {
|
|
542
588
|
console.log(
|
|
543
589
|
JSON.stringify(
|
|
544
|
-
{
|
|
590
|
+
{
|
|
591
|
+
...manifest,
|
|
592
|
+
componentCounts: counts,
|
|
593
|
+
verification,
|
|
594
|
+
dependencyCheck,
|
|
595
|
+
},
|
|
545
596
|
null,
|
|
546
597
|
2,
|
|
547
598
|
),
|
|
@@ -570,6 +621,17 @@ export function registerPluginCommand(program) {
|
|
|
570
621
|
(verification.ok ? chalk.green("passed") : chalk.red("FAILED")),
|
|
571
622
|
);
|
|
572
623
|
}
|
|
624
|
+
if (dependencyCheck) {
|
|
625
|
+
logger.log(
|
|
626
|
+
chalk.bold("\nDependencies: ") +
|
|
627
|
+
(dependencyCheck.ok
|
|
628
|
+
? chalk.green("satisfied")
|
|
629
|
+
: chalk.yellow("unmet")),
|
|
630
|
+
);
|
|
631
|
+
for (const issue of dependencyCheck.issues) {
|
|
632
|
+
logger.log(chalk.yellow(` ⚠ ${issue}`));
|
|
633
|
+
}
|
|
634
|
+
}
|
|
573
635
|
for (const w of manifest.warnings) logger.log(chalk.yellow(` ⚠ ${w}`));
|
|
574
636
|
for (const e of manifest.errors) logger.log(chalk.red(` ✖ ${e}`));
|
|
575
637
|
if (manifest.ok) {
|