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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_generated": "scripts/gen-command-manifest.mjs — do not edit by hand",
|
|
3
|
-
"commandCount":
|
|
3
|
+
"commandCount": 175,
|
|
4
4
|
"commands": [
|
|
5
5
|
{
|
|
6
6
|
"name": "a2a",
|
|
@@ -177,6 +177,13 @@
|
|
|
177
177
|
"register": "registerCliAnythingCommand",
|
|
178
178
|
"summary": "CLI-Anything — discover and register Agent-native CLI tools as skills"
|
|
179
179
|
},
|
|
180
|
+
{
|
|
181
|
+
"name": "cloud",
|
|
182
|
+
"aliases": [],
|
|
183
|
+
"module": "./commands/cloud.js",
|
|
184
|
+
"register": "registerCloudCommand",
|
|
185
|
+
"summary": "Self-hosted cloud handoff — offload a task to a private runner (bundle → run → reflow)"
|
|
186
|
+
},
|
|
180
187
|
{
|
|
181
188
|
"name": "code-intel",
|
|
182
189
|
"aliases": ["ci"],
|
|
@@ -340,10 +347,10 @@
|
|
|
340
347
|
},
|
|
341
348
|
{
|
|
342
349
|
"name": "doctor",
|
|
343
|
-
"aliases": [],
|
|
350
|
+
"aliases": ["checkup"],
|
|
344
351
|
"module": "./commands/doctor.js",
|
|
345
352
|
"register": "registerDoctorCommand",
|
|
346
|
-
"summary": "Diagnose your ChainlessChain environment"
|
|
353
|
+
"summary": "Diagnose your ChainlessChain environment (alias: checkup)"
|
|
347
354
|
},
|
|
348
355
|
{
|
|
349
356
|
"name": "economy",
|
|
@@ -884,6 +891,13 @@
|
|
|
884
891
|
"register": "registerOrchestrateCommand",
|
|
885
892
|
"summary": "Agent router V2 governance"
|
|
886
893
|
},
|
|
894
|
+
{
|
|
895
|
+
"name": "routine",
|
|
896
|
+
"aliases": [],
|
|
897
|
+
"module": "./commands/routine.js",
|
|
898
|
+
"register": "registerRoutineCommand",
|
|
899
|
+
"summary": "Named scheduled/triggered agent tasks with run history (cron/once/webhook/github)"
|
|
900
|
+
},
|
|
887
901
|
{
|
|
888
902
|
"name": "runtime",
|
|
889
903
|
"aliases": [],
|
package/src/commands/agent.js
CHANGED
|
@@ -16,7 +16,10 @@ import {
|
|
|
16
16
|
} from "../runtime/fallback-model.js";
|
|
17
17
|
import { resolveImages, resolveVisionLlm } from "../lib/image-input.js";
|
|
18
18
|
import { loadConfig } from "../lib/config-manager.js";
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
normalizeAgentSandbox,
|
|
21
|
+
assertSandboxAvailable,
|
|
22
|
+
} from "../lib/agent-sandbox.js";
|
|
20
23
|
|
|
21
24
|
/**
|
|
22
25
|
* Resolve + validate `--add-dir` values into absolute, existing, de-duped
|
|
@@ -172,6 +175,14 @@ export function registerAgentCommand(program) {
|
|
|
172
175
|
"--bare",
|
|
173
176
|
"Everything --safe-mode disables PLUS skills, plugins and MCP/IDE auto-connect — minimal fast surface for scripted calls (explicit --mcp-config still loads; permission rules STAY active)",
|
|
174
177
|
)
|
|
178
|
+
.option(
|
|
179
|
+
"--ephemeral",
|
|
180
|
+
"No session persistence: nothing is written to the session store (headless; a --resume id still replays history read-only)",
|
|
181
|
+
)
|
|
182
|
+
.option(
|
|
183
|
+
"--capabilities",
|
|
184
|
+
"Print a machine-readable capability manifest (JSON: protocol version, tools, permission modes, exit codes) and exit",
|
|
185
|
+
)
|
|
175
186
|
.option(
|
|
176
187
|
"--disable-slash-commands",
|
|
177
188
|
"Interactive REPL: don't dispatch '/' input as slash commands — it reaches the model verbatim (/exit and /quit stay live)",
|
|
@@ -331,6 +342,10 @@ export function registerAgentCommand(program) {
|
|
|
331
342
|
"--remote-control",
|
|
332
343
|
"Route confirm-tier approvals to paired mobile/web devices — prints a pairing URI/QR. Headless waits for the remote allow/deny (fail-closed on timeout); interactive races the terminal prompt (first answer wins; also /remote-control)",
|
|
333
344
|
)
|
|
345
|
+
.option(
|
|
346
|
+
"--channels <list>",
|
|
347
|
+
"Inbound channels for the interactive session (webhook[:port],telegram) — external events enter as user turns; webhook needs its bearer token, telegram needs channels.telegram.allowFrom",
|
|
348
|
+
)
|
|
334
349
|
.option(
|
|
335
350
|
"--settings <file>",
|
|
336
351
|
"Merge an extra .claude/settings.json-shaped file for this run: permission rules (allow/ask/deny) + native config overrides (model, env)",
|
|
@@ -363,12 +378,31 @@ export function registerAgentCommand(program) {
|
|
|
363
378
|
false,
|
|
364
379
|
)
|
|
365
380
|
.action(async (task, options, command) => {
|
|
381
|
+
// --capabilities: print the machine-readable manifest and exit — no
|
|
382
|
+
// config, no bootstrap, no network (gap-analysis 2026-07-11 快速收益 #6).
|
|
383
|
+
if (options.capabilities) {
|
|
384
|
+
const { buildAgentCapabilities } =
|
|
385
|
+
await import("../lib/headless-manifest.js");
|
|
386
|
+
console.log(JSON.stringify(buildAgentCapabilities(), null, 2));
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
366
389
|
// CC_API_KEY env fallback for --api-key: lets callers (IDE plugins,
|
|
367
390
|
// scripts) pass the key via the environment instead of argv, where it
|
|
368
391
|
// is visible to every local process (/proc/<pid>/cmdline, Win32_Process).
|
|
369
392
|
// An explicit --api-key still wins.
|
|
370
393
|
if (!options.apiKey && process.env.CC_API_KEY) {
|
|
371
394
|
options.apiKey = process.env.CC_API_KEY;
|
|
395
|
+
} else if (
|
|
396
|
+
options.apiKey &&
|
|
397
|
+
process.argv.includes("--api-key") &&
|
|
398
|
+
!process.env.VITEST &&
|
|
399
|
+
!process.env.VITEST_WORKER_ID
|
|
400
|
+
) {
|
|
401
|
+
// gap-analysis 2026-07-11: argv keys leak into shell history, process
|
|
402
|
+
// lists and logs — steer callers to the env/helper paths.
|
|
403
|
+
process.stderr.write(
|
|
404
|
+
"⚠️ --api-key on the command line is visible to every local process (shell history, ps). Prefer CC_API_KEY env or config llm.apiKeyHelper.\n",
|
|
405
|
+
);
|
|
372
406
|
}
|
|
373
407
|
const bypassPermissions = !!(
|
|
374
408
|
options.allowDangerousBypass ||
|
|
@@ -826,6 +860,7 @@ export function registerAgentCommand(program) {
|
|
|
826
860
|
outputStyle: options.outputStyle || null,
|
|
827
861
|
strictMcpConfig: options.strictMcpConfig === true,
|
|
828
862
|
replayUserMessages: options.replayUserMessages === true,
|
|
863
|
+
ephemeral: options.ephemeral === true,
|
|
829
864
|
maxCostUsd,
|
|
830
865
|
priceTable,
|
|
831
866
|
chatFn: fallbackChatFn,
|
|
@@ -933,6 +968,15 @@ export function registerAgentCommand(program) {
|
|
|
933
968
|
network: options.sandboxNetwork === true,
|
|
934
969
|
settings: settingsSandbox,
|
|
935
970
|
});
|
|
971
|
+
// Strict sandbox mode: failIfUnavailable refuses to START when the
|
|
972
|
+
// configured engine can't run — no silent per-command degradation.
|
|
973
|
+
try {
|
|
974
|
+
assertSandboxAvailable(agentSandbox);
|
|
975
|
+
} catch (err) {
|
|
976
|
+
process.stderr.write(`Error: ${err.message}\n`);
|
|
977
|
+
await _finishWorktree();
|
|
978
|
+
process.exit(6); // config error (see lib/exit-codes.cjs)
|
|
979
|
+
}
|
|
936
980
|
// Resume requested onto a session with no headless (JSONL) transcript?
|
|
937
981
|
// Warn instead of silently starting empty 鈥?headless resume rebuilds
|
|
938
982
|
// from the JSONL store only (DB-only sessions are not replayable here).
|
|
@@ -1021,6 +1065,8 @@ export function registerAgentCommand(program) {
|
|
|
1021
1065
|
// --settings: extra .claude/settings.json permission rules
|
|
1022
1066
|
settingsFile: options.settings || null,
|
|
1023
1067
|
outputStyle: options.outputStyle || null,
|
|
1068
|
+
// --ephemeral: no session persistence (resume replay stays read-only)
|
|
1069
|
+
ephemeral: options.ephemeral === true,
|
|
1024
1070
|
// --max-budget-usd: hard spend cap (+ price table from config llm.pricing)
|
|
1025
1071
|
maxCostUsd,
|
|
1026
1072
|
priceTable,
|
|
@@ -1070,6 +1116,13 @@ export function registerAgentCommand(program) {
|
|
|
1070
1116
|
return;
|
|
1071
1117
|
}
|
|
1072
1118
|
|
|
1119
|
+
// --ephemeral is a headless contract (the interactive REPL owns its own
|
|
1120
|
+
// session lifecycle) — warn instead of silently dropping the flag.
|
|
1121
|
+
if (options.ephemeral) {
|
|
1122
|
+
process.stderr.write(
|
|
1123
|
+
"--ephemeral is only used in headless mode (-p / a task / piped stdin); ignoring for the interactive session.\n",
|
|
1124
|
+
);
|
|
1125
|
+
}
|
|
1073
1126
|
// Reached only for an interactive session, where --image has no turn to
|
|
1074
1127
|
// attach to 鈥?warn instead of silently dropping the attachment.
|
|
1075
1128
|
if (images.length) {
|
|
@@ -1078,6 +1131,20 @@ export function registerAgentCommand(program) {
|
|
|
1078
1131
|
);
|
|
1079
1132
|
}
|
|
1080
1133
|
|
|
1134
|
+
// Strict sandbox mode also guards the interactive session: refuse to
|
|
1135
|
+
// start when failIfUnavailable is set and the engine can't run.
|
|
1136
|
+
const interactiveSandbox = normalizeAgentSandbox(options.sandbox, {
|
|
1137
|
+
cwd: process.cwd(),
|
|
1138
|
+
network: options.sandboxNetwork === true,
|
|
1139
|
+
settings: settingsSandbox,
|
|
1140
|
+
});
|
|
1141
|
+
try {
|
|
1142
|
+
assertSandboxAvailable(interactiveSandbox);
|
|
1143
|
+
} catch (err) {
|
|
1144
|
+
process.stderr.write(`Error: ${err.message}\n`);
|
|
1145
|
+
process.exit(6); // config error (see lib/exit-codes.cjs)
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1081
1148
|
const runtime = createAgentRuntimeFactory().createAgentRuntime({
|
|
1082
1149
|
model: options.model,
|
|
1083
1150
|
thinking,
|
|
@@ -1099,11 +1166,7 @@ export function registerAgentCommand(program) {
|
|
|
1099
1166
|
parkOnExit: options.parkOnExit, // false when --no-park-on-exit
|
|
1100
1167
|
bundlePath: options.bundle || null,
|
|
1101
1168
|
additionalDirectories,
|
|
1102
|
-
sandbox:
|
|
1103
|
-
cwd: process.cwd(),
|
|
1104
|
-
network: options.sandboxNetwork === true,
|
|
1105
|
-
settings: settingsSandbox,
|
|
1106
|
-
}),
|
|
1169
|
+
sandbox: interactiveSandbox,
|
|
1107
1170
|
autoCheckpoint,
|
|
1108
1171
|
// --vim: start the REPL in vim-mode editing (also CC_VIM=1 or /vim).
|
|
1109
1172
|
vimMode: options.vim === true,
|
|
@@ -1133,6 +1196,9 @@ export function registerAgentCommand(program) {
|
|
|
1133
1196
|
// --remote-control: start the paired-device approval bridge for the
|
|
1134
1197
|
// interactive session too (terminal prompt races the device).
|
|
1135
1198
|
remoteControl: options.remoteControl === true,
|
|
1199
|
+
// --channels: inbound channel listeners (webhook/telegram) whose
|
|
1200
|
+
// events become user turns in this session.
|
|
1201
|
+
channels: options.channels || null,
|
|
1136
1202
|
});
|
|
1137
1203
|
await runtime.startAgentSession();
|
|
1138
1204
|
// Interactive session ended (REPL closed) — settle the worktree.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
import { logger } from "../lib/logger.js";
|
|
4
|
+
import { readPrLinkLedger } from "../lib/pr-link-ledger.js";
|
|
4
5
|
|
|
5
6
|
function formatAge(ms) {
|
|
6
7
|
const n = Math.max(0, Math.round(Number(ms || 0) / 1000));
|
|
@@ -67,6 +68,11 @@ export function formatBackgroundAgentDetails(
|
|
|
67
68
|
` log: ${session.logFile || "-"}`,
|
|
68
69
|
];
|
|
69
70
|
if (session.phase) lines.push(` phase: ${session.phase}`);
|
|
71
|
+
if (session.pr?.number) {
|
|
72
|
+
lines.push(
|
|
73
|
+
` pr: #${session.pr.number}${session.pr.state ? ` ${session.pr.state}` : ""}${session.pr.url ? ` ${session.pr.url}` : ""}`,
|
|
74
|
+
);
|
|
75
|
+
}
|
|
70
76
|
if (Number.isFinite(Number(session.turnCount))) {
|
|
71
77
|
lines.push(` turns: ${session.turnCount}`);
|
|
72
78
|
}
|
|
@@ -146,7 +152,7 @@ async function followBackgroundAgent(id, options = {}) {
|
|
|
146
152
|
* when the transport is unavailable so the caller can fall back to the
|
|
147
153
|
* log-only follow.
|
|
148
154
|
*/
|
|
149
|
-
async function interactiveAttach(id, state, options = {}) {
|
|
155
|
+
export async function interactiveAttach(id, state, options = {}) {
|
|
150
156
|
const { connectBackgroundSession } =
|
|
151
157
|
await import("../lib/background-session-transport.js");
|
|
152
158
|
const { readBackgroundAgentLog, logPath } = await loadSupervisor();
|
|
@@ -279,6 +285,134 @@ async function interactiveAttach(id, state, options = {}) {
|
|
|
279
285
|
return true;
|
|
280
286
|
}
|
|
281
287
|
|
|
288
|
+
/**
|
|
289
|
+
* `cc daemon view` (no id) — the interactive agent dashboard. Wires the real
|
|
290
|
+
* supervisor/transport into the injectable controller (repl/bg-dashboard.js).
|
|
291
|
+
* Non-TTY (or --json) degrades to the status listing.
|
|
292
|
+
*/
|
|
293
|
+
async function runDashboardView(options = {}) {
|
|
294
|
+
const supervisor = await loadSupervisor();
|
|
295
|
+
const {
|
|
296
|
+
listBackgroundAgents,
|
|
297
|
+
readBackgroundAgentLog,
|
|
298
|
+
stopBackgroundAgent,
|
|
299
|
+
renameBackgroundAgent,
|
|
300
|
+
setBackgroundAgentPinned,
|
|
301
|
+
resumeBackgroundAgent,
|
|
302
|
+
readBackgroundAgentState,
|
|
303
|
+
effectiveBackgroundAgentState,
|
|
304
|
+
} = supervisor;
|
|
305
|
+
|
|
306
|
+
const listAll = () => {
|
|
307
|
+
const sessions = listBackgroundAgents({ all: true });
|
|
308
|
+
// PR/session linking: decorate rows whose conversation touched a PR
|
|
309
|
+
// (`#123 open`). One ledger read per refresh; best-effort.
|
|
310
|
+
try {
|
|
311
|
+
const ledger = readPrLinkLedger();
|
|
312
|
+
for (const s of sessions) {
|
|
313
|
+
const links = s.sessionId ? ledger[s.sessionId] : null;
|
|
314
|
+
if (Array.isArray(links) && links.length > 0 && !s.pr) {
|
|
315
|
+
s.pr = [...links].sort(
|
|
316
|
+
(a, b) => (b.updatedAt || 0) - (a.updatedAt || 0),
|
|
317
|
+
)[0];
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
} catch {
|
|
321
|
+
/* PR decoration is cosmetic */
|
|
322
|
+
}
|
|
323
|
+
return sessions;
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
if (options.json || !process.stdout.isTTY || !process.stdin.isTTY) {
|
|
327
|
+
const sessions = listAll();
|
|
328
|
+
if (options.json) {
|
|
329
|
+
console.log(JSON.stringify({ sessions }, null, 2));
|
|
330
|
+
} else {
|
|
331
|
+
printBackgroundAgents(sessions);
|
|
332
|
+
logger.log(
|
|
333
|
+
chalk.gray("(interactive dashboard needs a TTY — showing a snapshot)"),
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const { runBgDashboard } = await import("../repl/bg-dashboard.js");
|
|
340
|
+
const { fileURLToPath } = await import("node:url");
|
|
341
|
+
const { spawn } = await import("node:child_process");
|
|
342
|
+
const BIN_PATH = fileURLToPath(
|
|
343
|
+
new URL("../../bin/chainlesschain.js", import.meta.url),
|
|
344
|
+
);
|
|
345
|
+
|
|
346
|
+
await runBgDashboard({
|
|
347
|
+
listAgents: listAll,
|
|
348
|
+
readLog: (id, lines) => {
|
|
349
|
+
try {
|
|
350
|
+
return readBackgroundAgentLog(id, { lines });
|
|
351
|
+
} catch {
|
|
352
|
+
return "";
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
stopAgent: (id) => stopBackgroundAgent(id),
|
|
356
|
+
renameAgent: (id, title) => renameBackgroundAgent(id, title),
|
|
357
|
+
pinAgent: (id, pinned) => setBackgroundAgentPinned(id, pinned),
|
|
358
|
+
replyAgent: async (session, text) => {
|
|
359
|
+
// Running with a live transport → queue a follow-up turn; otherwise
|
|
360
|
+
// continue the finished conversation as a new background session.
|
|
361
|
+
if (
|
|
362
|
+
session.status === "running" &&
|
|
363
|
+
session.transport?.pipe &&
|
|
364
|
+
session.transport?.token
|
|
365
|
+
) {
|
|
366
|
+
const { connectBackgroundSession } =
|
|
367
|
+
await import("../lib/background-session-transport.js");
|
|
368
|
+
const conn = await connectBackgroundSession({
|
|
369
|
+
pipePath: session.transport.pipe,
|
|
370
|
+
token: session.transport.token,
|
|
371
|
+
onEvent: () => {},
|
|
372
|
+
onClose: () => {},
|
|
373
|
+
});
|
|
374
|
+
try {
|
|
375
|
+
conn.send({ type: "prompt", text });
|
|
376
|
+
// give the frame a beat to flush before closing
|
|
377
|
+
await new Promise((r) => setTimeout(r, 150));
|
|
378
|
+
} finally {
|
|
379
|
+
try {
|
|
380
|
+
conn.close();
|
|
381
|
+
} catch {
|
|
382
|
+
/* worker already closed it */
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
resumeBackgroundAgent(session.id, text);
|
|
388
|
+
},
|
|
389
|
+
attachAgent: async (session) => {
|
|
390
|
+
const fresh = effectiveBackgroundAgentState(
|
|
391
|
+
readBackgroundAgentState(session.id),
|
|
392
|
+
);
|
|
393
|
+
if (!fresh) return;
|
|
394
|
+
if (
|
|
395
|
+
fresh.status === "running" &&
|
|
396
|
+
fresh.transport?.pipe &&
|
|
397
|
+
fresh.transport?.token
|
|
398
|
+
) {
|
|
399
|
+
const attached = await interactiveAttach(session.id, fresh, {});
|
|
400
|
+
if (attached) return;
|
|
401
|
+
}
|
|
402
|
+
await followBackgroundAgent(session.id, { lines: 40 });
|
|
403
|
+
},
|
|
404
|
+
dispatchAgent: async (text) => {
|
|
405
|
+
const child = spawn(
|
|
406
|
+
process.execPath,
|
|
407
|
+
[BIN_PATH, "agent", "--bg", "-p", text],
|
|
408
|
+
{ detached: true, stdio: "ignore", windowsHide: true },
|
|
409
|
+
);
|
|
410
|
+
child.unref();
|
|
411
|
+
return null; // id is minted by the launcher; the next refresh shows it
|
|
412
|
+
},
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
|
|
282
416
|
export function registerBackgroundSessionCommands(program) {
|
|
283
417
|
program
|
|
284
418
|
.command("logs <id>")
|
|
@@ -378,12 +512,18 @@ export function registerBackgroundSessionCommands(program) {
|
|
|
378
512
|
});
|
|
379
513
|
|
|
380
514
|
daemon
|
|
381
|
-
.command("view
|
|
382
|
-
.description(
|
|
515
|
+
.command("view [id]")
|
|
516
|
+
.description(
|
|
517
|
+
"Detailed view of one background agent, or the interactive agent dashboard when no id is given",
|
|
518
|
+
)
|
|
383
519
|
.option("-n, --lines <n>", "Recent log lines to include", "40")
|
|
384
520
|
.option("--json", "Output as JSON")
|
|
385
521
|
.action(async (id, options) => {
|
|
386
522
|
try {
|
|
523
|
+
if (!id) {
|
|
524
|
+
await runDashboardView(options);
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
387
527
|
const {
|
|
388
528
|
readBackgroundAgentState,
|
|
389
529
|
effectiveBackgroundAgentState,
|
|
@@ -457,6 +597,36 @@ export function registerBackgroundSessionCommands(program) {
|
|
|
457
597
|
}
|
|
458
598
|
});
|
|
459
599
|
|
|
600
|
+
// daemon rm — record cleanup (gap-analysis 2026-07-11 P0 后台 Supervisor).
|
|
601
|
+
daemon
|
|
602
|
+
.command("rm <id>")
|
|
603
|
+
.description(
|
|
604
|
+
"Remove a finished background agent's record + log (running agents need --force; the conversation session itself is untouched)",
|
|
605
|
+
)
|
|
606
|
+
.option("--force", "Stop a still-running agent first, then remove")
|
|
607
|
+
.option("--keep-log", "Keep the log file, remove only the state record")
|
|
608
|
+
.option("--json", "Output as JSON")
|
|
609
|
+
.action(async (id, options) => {
|
|
610
|
+
try {
|
|
611
|
+
const { removeBackgroundAgent } = await loadSupervisor();
|
|
612
|
+
const result = removeBackgroundAgent(id, {
|
|
613
|
+
force: options.force === true,
|
|
614
|
+
keepLog: options.keepLog === true,
|
|
615
|
+
});
|
|
616
|
+
if (options.json) {
|
|
617
|
+
console.log(JSON.stringify(result, null, 2));
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
logger.log(
|
|
621
|
+
chalk.green(`Removed background agent ${result.id}`) +
|
|
622
|
+
chalk.gray(` (was ${result.status})`),
|
|
623
|
+
);
|
|
624
|
+
} catch (error) {
|
|
625
|
+
logger.error(chalk.red(error.message));
|
|
626
|
+
process.exitCode = 1;
|
|
627
|
+
}
|
|
628
|
+
});
|
|
629
|
+
|
|
460
630
|
daemon
|
|
461
631
|
.command("stop [id]")
|
|
462
632
|
.description("Stop one background agent, or all running agents with --any")
|
package/src/commands/browse.js
CHANGED
|
@@ -391,6 +391,92 @@ export function registerBrowseChromeCommand(browse) {
|
|
|
391
391
|
logger.success(`Screenshot: ${state.screenshotPath}`);
|
|
392
392
|
}
|
|
393
393
|
});
|
|
394
|
+
|
|
395
|
+
chrome
|
|
396
|
+
.command("act")
|
|
397
|
+
.description(
|
|
398
|
+
"Perform EXPLICIT actions (click/type/press/navigate/waitForSelector/screenshot/assertText) in the connected Chrome — unlike 'state', this DRIVES your logged-in browser",
|
|
399
|
+
)
|
|
400
|
+
.option("-p, --port <port>", "CDP port", "9222")
|
|
401
|
+
.option("-t, --tab <n>", "Tab index", "0")
|
|
402
|
+
.requiredOption(
|
|
403
|
+
"--actions <json|@file>",
|
|
404
|
+
'JSON array of steps, e.g. \'[{"type":"click","selector":"#go"}]\', or @steps.json',
|
|
405
|
+
)
|
|
406
|
+
.option(
|
|
407
|
+
"--continue-on-error",
|
|
408
|
+
"Keep executing the remaining steps after a failed one (default: fail fast)",
|
|
409
|
+
)
|
|
410
|
+
.option("--json", "Output as JSON")
|
|
411
|
+
.action(async (options) => {
|
|
412
|
+
const { discoverCdp, performActions } =
|
|
413
|
+
await import("../lib/chrome-connector.js");
|
|
414
|
+
const port = numericOption(options.port, {
|
|
415
|
+
name: "--port",
|
|
416
|
+
integer: true,
|
|
417
|
+
min: 1,
|
|
418
|
+
fallback: 9222,
|
|
419
|
+
});
|
|
420
|
+
let actions;
|
|
421
|
+
try {
|
|
422
|
+
const raw = options.actions.startsWith("@")
|
|
423
|
+
? (await import("fs")).readFileSync(options.actions.slice(1), "utf-8")
|
|
424
|
+
: options.actions;
|
|
425
|
+
actions = JSON.parse(raw);
|
|
426
|
+
} catch (err) {
|
|
427
|
+
logger.error(
|
|
428
|
+
`--actions must be a JSON array (or @file.json): ${err.message}`,
|
|
429
|
+
);
|
|
430
|
+
process.exit(1);
|
|
431
|
+
}
|
|
432
|
+
// Refuse outright when nothing is listening — an action command must
|
|
433
|
+
// never silently no-op or launch a browser on its own.
|
|
434
|
+
const probe = await discoverCdp({ port });
|
|
435
|
+
if (!probe.ok) {
|
|
436
|
+
const msg = `No debuggable Chrome on port ${port} — refusing to act. Start one first: cc browse chrome launch`;
|
|
437
|
+
if (options.json) {
|
|
438
|
+
console.log(JSON.stringify({ ok: false, error: msg }, null, 2));
|
|
439
|
+
} else {
|
|
440
|
+
logger.error(msg);
|
|
441
|
+
}
|
|
442
|
+
process.exitCode = 1;
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
const res = await performActions(actions, {
|
|
446
|
+
port,
|
|
447
|
+
tab: numericOption(options.tab, {
|
|
448
|
+
name: "--tab",
|
|
449
|
+
integer: true,
|
|
450
|
+
min: 0,
|
|
451
|
+
fallback: 0,
|
|
452
|
+
}),
|
|
453
|
+
continueOnError: options.continueOnError === true,
|
|
454
|
+
});
|
|
455
|
+
if (options.json) {
|
|
456
|
+
console.log(JSON.stringify(res, null, 2));
|
|
457
|
+
if (!res.ok) process.exitCode = 1;
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
if (res.error) {
|
|
461
|
+
logger.error(res.error);
|
|
462
|
+
process.exitCode = 1;
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
if (res.profileWarning) logger.warn(res.profileWarning);
|
|
466
|
+
for (const step of res.steps) {
|
|
467
|
+
const mark = step.ok ? chalk.green("ok") : chalk.red("FAIL");
|
|
468
|
+
logger.log(
|
|
469
|
+
` [${mark}] ${step.action} ${chalk.gray(`(${step.durationMs}ms)`)} ${step.detail}`,
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
logger.log(
|
|
473
|
+
` ${res.executed}/${actions.length} step(s) executed → ${chalk.cyan(res.url)}${res.title ? ` (${res.title})` : ""}`,
|
|
474
|
+
);
|
|
475
|
+
if (res.auditError) {
|
|
476
|
+
logger.warn(`audit log write failed: ${res.auditError}`);
|
|
477
|
+
}
|
|
478
|
+
if (!res.ok) process.exitCode = 1;
|
|
479
|
+
});
|
|
394
480
|
}
|
|
395
481
|
|
|
396
482
|
import {
|