chainlesschain 0.162.162 → 0.162.164
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 +3 -1
- package/src/assets/web-panel/assets/{AIOps-ClI2ALgv.js → AIOps-BqRkaHGb.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BDjRcJaK.js → ActionButton-DWO7OZLC.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DikSRsaT.js → Analytics-C5oaVezM.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-9mLhMFmz.js → AppLayout-CsUESDoZ.js} +3 -3
- package/src/assets/web-panel/assets/{Artifacts-BSr88BrH.js → Artifacts-Dragqu5k.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CdvyimOF.js → Audit-CQsaHctY.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-D3_hCedh.js → BackgroundAgents-DdG1jNSM.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-Cyvv9RHf.js → Backup-DN6sjK4z.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-BZM14kt8.js → BaseInput-Cxm_ZTCl.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-DrQSokVz.js → Chat-DVXGmA56.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-HwJR-C6B.js → ChatBubbleRenderer-BdaCL_iE.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-bFLYeWMV.js → Checkbox-DEc4vD_A.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-7mN7xJXT.js → Codegen-CKiTcv36.js} +1 -1
- package/src/assets/web-panel/assets/{Col-DAB5ZWm7.js → Col-Br9UUNN0.js} +1 -1
- package/src/assets/web-panel/assets/{Community-B_1TymaK.js → Community-NeUH_70T.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-Bq1uSWLJ.js → Compact-BqR-z2Df.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CyiE1jEe.js → Compliance-DcWB_SgZ.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-Cpk0D7vm.js → Cowork-BfhgcudF.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-d_Lv3rdB.js → Cron-LaU29LgD.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-DMqhHjMR.js → Crosschain-B2ZB9uwW.js} +1 -1
- package/src/assets/web-panel/assets/{DID-Br-oPuBw.js → DID-BuHl38A2.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-CfLW_RaP.js → Dashboard-m627yqvZ.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DZnTOExV.js → Dropdown-C7bxF8F5.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DHIUHDv1.js → EmailListRenderer-DPLPQzLp.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-Bw3t3myu.js → FamilyGuardDashboard-cOiH6ike.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-D9cpQPAY.js → Federation-Bvkzg88z.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-Jdczr9Mr.js → FormItemContext-BTsiA7h_.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-BT8ZMpC5.js → GenericCardRenderer-BGnVE5qu.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DjARip2b.js → Git-DS_j6r25.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BgWbSRcj.js → Governance-CKRG3Rsl.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CfouJciM.js → Inference-DW8INoNQ.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-50l7mrAr.js → KnowledgeGraph-BhEYeFhC.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-rq50H84B.js → Logs-wqi0uxuR.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-DUPIEdQH.js → MarkdownRenderer-DS8dE8ty.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-BYgPDmHU.js → Marketplace-CMlTuPLT.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-5DVgcFdx.js → McpTools-CSx4m5JJ.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-B70LPk7f.js → Memory-vnQCUy-_.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-De8ssA5Y.js → MobileBridge-BV2NA742.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-Bw0k8e1B.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-RJsOTsIA.js → Mtc-CzK_FPB1.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-Crh-6BEK.js → MtcAudit-Cb7G9oL3.js} +5 -5
- package/src/assets/web-panel/assets/{Multisig-wuoR5l3x.js → Multisig-qJxlUyzr.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-U2Mji4fZ.js → NLProgramming-DqaBJ7Te.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-CdTZAyDH.js → Notes-CwhTJkRi.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-C-FucWE7.js → NotificationSettings-YDs4Fal4.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DCYFTeaI.js → OrderTableRenderer-CvEALpq7.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-an3OF85L.js → Organization-CEmQm9n8.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-C-1vmYFe.js → Overflow-zby_P_LA.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-Cwh47xKg.js → P2P-DsmDNFNT.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Dm38GT0k.js → PdhVaultBrowser-FWwFlZGF.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-DS2Y8awD.js → Permissions-DuzQ6me5.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-BQNziA0I.js → PersonalDataHub-DZbeN613.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-DF85L1ue.js → Pipeline-CoNSVAUS.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-BuLornF-.js → Privacy-OYJEAaMC.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-C3Y31IwX.js → ProjectInit-CWIapV--.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BCPiI8aD.js → ProjectSettings-CX8xMxZn.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-BZ6s4k6g.js → Projects-BLCN8YyY.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-D3Wp022X.js → Providers-BV_sxp75.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-CUJfQkH4.js → QrScannerModal-BTnRrHRp.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-UAc0EO8l.js → QuickAsk-D1KZg018.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-BaxKupcs.js → Recommend-COm5cuNg.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-C75NNnXZ.js → RemoteSession-0saWEkYI.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-BVXynZAk.js → Reputation-Dr7iKLS2.js} +1 -1
- package/src/assets/web-panel/assets/{Row-C5MRZ0bi.js → Row-C1vpPBcr.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-DAKkEYka.js → RssFeed-CxlWrtNj.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DvWv9YOA.js → Search-BT2V8dPN.js} +1 -1
- package/src/assets/web-panel/assets/{Security-B5peafW1.js → Security-bm9V3c5k.js} +4 -4
- package/src/assets/web-panel/assets/{Services-UQmvPEaG.js → Services-CocH1yyX.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-C3bhWpuF.js → Skeleton-DHItlMdd.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-DfkKf9_H.js → Skills-C59sLc4w.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DqMSjlBM.js → Sla-Crj4BMc8.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-C-WbxWUX.js → SpeechSettings-DX4KFceY.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-CYuHZ4N2.js → SyncSettings-BD_iwQLr.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-CyeAyB9d.js → Tasks-BmCTzYsH.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BTCeQnpq.js → Templates-BGUaxZYl.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-BifQuA9Y.js → Tenant-BS0tJx2O.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-Bx_9Bocf.js → Terminal--tHSAsld.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-BX0RFCOm.js → TimelineRenderer-D9-MFxS4.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-CGHrCmUS.js → Tokens-CiCB485f.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-DlqaY4SO.js → Trigger-SmCFuW_l.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DfOmj-ay.js → Trust-DkK3Rqe0.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-B72jH5fE.js → UkeySign-CDM4LGdB.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-BT-63fqv.js → VideoEditing-IDB7DJXt.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-Dsul3sHr.js → Wallet-Bikj5cmt.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-Izkwwdgy.js → WebAuthn-C9abWlAw.js} +2 -2
- package/src/assets/web-panel/assets/{WorkflowEditor-D3FHSiH1.js → WorkflowEditor-DrbRKVky.js} +1 -1
- package/src/assets/web-panel/assets/{chat-CmVz5z3U.js → chat-CccCSDQf.js} +1 -1
- package/src/assets/web-panel/assets/{colors-CuLgyJBp.js → colors-CXObXLhb.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-Ml1YkXpw.js → compact-item-B5kfYAxC.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BvjJ48bs.js → createContext-DmiPBfip.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-CvKrADNa.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DVC0157C.js → hasIn-Q6lYteAc.js} +1 -1
- package/src/assets/web-panel/assets/{index-C229ABfy.js → index-25Wlqps4.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ck_52dz_.js → index-33U29UNV.js} +1 -1
- package/src/assets/web-panel/assets/{index-QXzlT9KD.js → index-4oXBDczR.js} +1 -1
- package/src/assets/web-panel/assets/{index-4SBta3d7.js → index-BGYXvMc5.js} +1 -1
- package/src/assets/web-panel/assets/{index-B0S8NzO6.js → index-BJCCa0s_.js} +1 -1
- package/src/assets/web-panel/assets/{index-DJyN28Et.js → index-BJJ5DhKI.js} +1 -1
- package/src/assets/web-panel/assets/{index-DC_OI9H2.js → index-BLOzViJ6.js} +1 -1
- package/src/assets/web-panel/assets/{index-C_XuRgGn.js → index-BRrbUMoG.js} +1 -1
- package/src/assets/web-panel/assets/{index-wvb_FtaV.js → index-BUFpT17Q.js} +1 -1
- package/src/assets/web-panel/assets/{index-KMqhcF7l.js → index-BkRDiqGc.js} +1 -1
- package/src/assets/web-panel/assets/{index-vG4XSJ1d.js → index-BsfvW6my.js} +1 -1
- package/src/assets/web-panel/assets/{index-DYXHFr4r.js → index-By-kfPED.js} +1 -1
- package/src/assets/web-panel/assets/{index-DuGszaWY.js → index-BzFTcQsc.js} +1 -1
- package/src/assets/web-panel/assets/{index-CXkJH-lK.js → index-C2FXdboq.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dt5KMjwJ.js → index-C5XOlTHN.js} +1 -1
- package/src/assets/web-panel/assets/{index-4wcgvPoF.js → index-CLhBDS2w.js} +1 -1
- package/src/assets/web-panel/assets/{index-C_H_S-DY.js → index-CMq7UeoT.js} +1 -1
- package/src/assets/web-panel/assets/{index-BydjdZnl.js → index-CVMTWNKl.js} +1 -1
- package/src/assets/web-panel/assets/{index-BjHBpRYZ.js → index-Caghi-yL.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bzr0rB5T.js → index-CdB6FuSH.js} +1 -1
- package/src/assets/web-panel/assets/{index-BbPtzB8M.js → index-CoK8-kWQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BUt8kTIB.js → index-CsO3GUAY.js} +1 -1
- package/src/assets/web-panel/assets/{index-C_vRgTl9.js → index-CwZBa20Z.js} +1 -1
- package/src/assets/web-panel/assets/{index-DukDVXCv.js → index-D-kASucw.js} +1 -1
- package/src/assets/web-panel/assets/{index-BbepULSc.js → index-D8eBw7vW.js} +1 -1
- package/src/assets/web-panel/assets/{index-BfuKP4qe.js → index-D9wgifk4.js} +1 -1
- package/src/assets/web-panel/assets/{index-BiC6dQZG.js → index-DAYCTc07.js} +1 -1
- package/src/assets/web-panel/assets/{index-CmFNvNLZ.js → index-DF6Q8l2h.js} +1 -1
- package/src/assets/web-panel/assets/index-DTdFUWc_.js +1 -0
- package/src/assets/web-panel/assets/{index-KjgKdZe-.js → index-DgTLApS9.js} +1 -1
- package/src/assets/web-panel/assets/{index-BpFJHiTv.js → index-DgxVJ8pg.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cw0Rjy87.js → index-DlJvIqoR.js} +1 -1
- package/src/assets/web-panel/assets/{index-CFYVQMvu.js → index-Dw4eHfsG.js} +1 -1
- package/src/assets/web-panel/assets/{index-CudmwNBV.js → index-Rh-ytwow.js} +3 -3
- package/src/assets/web-panel/assets/{index-DDGaOWBV.js → index-StAEt2pq.js} +1 -1
- package/src/assets/web-panel/assets/{index-D3lD5qap.js → index-bzfw951k.js} +1 -1
- package/src/assets/web-panel/assets/{index-BzG-x9p4.js → index-fSUMbMvv.js} +1 -1
- package/src/assets/web-panel/assets/{index-B_EvG_GW.js → index-tFHy5Wol.js} +1 -1
- package/src/assets/web-panel/assets/index-zQ0M_kz-.js +1 -0
- package/src/assets/web-panel/assets/{initDefaultProps-BDgd2YZ8.js → initDefaultProps-BNq7X72N.js} +1 -1
- package/src/assets/web-panel/assets/{motion-ErtrXdYe.js → motion-DOf9viTc.js} +1 -1
- package/src/assets/web-panel/assets/{move-_GPPNCgs.js → move-CRHTcW4x.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-DRLL-8V2.js → mtc-parser-Cyoozgm2.js} +1 -1
- package/src/assets/web-panel/assets/{omit-p86sl023.js → omit-6-TjFNru.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-BTu7cMLH.js → pickAttrs-DlUmO1zi.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BEKz6Isr.js → placementArrow-CFOL8mIR.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-Ck42c9MP.js → responsiveObserve-BtaFK5zd.js} +1 -1
- package/src/assets/web-panel/assets/{slide-1CEvuPsB.js → slide-BIbc2bur.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BDfdx1GJ.js → statusUtils-BXX9d6-w.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-B4K46m5w.js → styleChecker-BGv10Bpn.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-DoIVpJNq.js → useFlexGapSupport-bKnKT8tw.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-DdAWi-ln.js → useFs-FY4IL4jn.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-iUu6k8dx.js → usePersonalDataHub-Bwl9TEgu.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DZz4R6Tw.js → vnode-BM3OHxAT.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-DXlf9sA3.js → zoom-D1fbFiHB.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agenda.js +320 -32
- package/src/commands/agent.js +105 -11
- package/src/commands/context.js +125 -14
- package/src/commands/doctor.js +85 -1
- package/src/commands/hook.js +181 -7
- package/src/commands/plugin.js +456 -1
- package/src/commands/review.js +363 -2
- package/src/commands/session.js +191 -0
- package/src/commands/team.js +19 -1
- package/src/data/changelog.json +10 -4
- package/src/gateways/ws/remote-session-protocol.js +39 -0
- package/src/gateways/ws/session-protocol.js +55 -2
- package/src/gateways/ws/ws-agent-handler.js +50 -0
- package/src/harness/jsonl-session-store.js +60 -0
- package/src/harness/worktree-isolator.js +140 -5
- package/src/lib/agent-schedule-store.js +318 -10
- package/src/lib/agent-team/team-worktree.js +37 -2
- package/src/lib/agent-tool-admission.js +125 -0
- package/src/lib/app-preview.js +360 -0
- package/src/lib/async-hook-supervisor.cjs +54 -0
- package/src/lib/capability-manifest.js +319 -0
- package/src/lib/capability-negotiation.js +23 -12
- package/src/lib/channels/channel-manager.js +54 -2
- package/src/lib/cli-context-engineering.js +9 -2
- package/src/lib/context-breakdown.js +116 -0
- package/src/lib/diagnostic-bundle.js +230 -0
- package/src/lib/doctor-checkup.js +275 -4
- package/src/lib/execution-location.js +286 -0
- package/src/lib/headless-manifest.js +13 -40
- package/src/lib/hook-event-log.cjs +193 -0
- package/src/lib/hook-stats-store.cjs +197 -0
- package/src/lib/idempotency.js +109 -0
- package/src/lib/interaction-adapter.js +34 -4
- package/src/lib/json-schema-output.js +46 -12
- package/src/lib/json-schema-validate.js +143 -3
- package/src/lib/jsonl-session-store.js +1 -0
- package/src/lib/lsp/__tests__/lsp-manager.test.js +58 -0
- package/src/lib/lsp/lsp-manager.js +56 -0
- package/src/lib/monitor-event.js +290 -0
- package/src/lib/operation-fingerprint.js +217 -0
- package/src/lib/plugin-runtime/bin.js +37 -0
- package/src/lib/plugin-runtime/capabilities.js +19 -0
- package/src/lib/plugin-runtime/capability-consent.js +203 -0
- package/src/lib/plugin-runtime/hooks.js +37 -0
- package/src/lib/plugin-runtime/lsp.js +38 -0
- package/src/lib/plugin-runtime/mcp.js +40 -0
- package/src/lib/plugin-runtime/monitors.js +37 -0
- package/src/lib/plugin-runtime/plugin-options.js +151 -0
- package/src/lib/plugin-runtime/policy.js +62 -0
- package/src/lib/plugin-runtime/scopes.js +20 -4
- package/src/lib/pr-automation-policy.js +224 -0
- package/src/lib/project-instructions.js +128 -0
- package/src/lib/remote-approval-bridge.js +66 -13
- package/src/lib/repl-goal.js +132 -0
- package/src/lib/repl-rewind.js +153 -0
- package/src/lib/review-comment-anchor.js +241 -0
- package/src/lib/review-pipeline.js +46 -7
- package/src/lib/runtime-checkup.js +221 -0
- package/src/lib/schedule-planner.js +17 -1
- package/src/lib/secret-scan.js +409 -0
- package/src/lib/session-branch.js +0 -0
- package/src/lib/settings-hook-events.cjs +13 -0
- package/src/lib/settings-loader.cjs +42 -0
- package/src/lib/side-effect-ledger-store.js +88 -0
- package/src/lib/side-effect-ledger.js +401 -0
- package/src/lib/skill-loader.js +32 -0
- package/src/lib/skill-path-scope.js +63 -0
- package/src/lib/sub-agent-context.js +110 -9
- package/src/lib/sub-agent-registry.js +19 -0
- package/src/lib/subagent-inheritance.js +112 -0
- package/src/lib/telemetry/span-recorder.js +17 -4
- package/src/lib/terminal-context.js +195 -0
- package/src/lib/turn-binding-store.js +119 -0
- package/src/lib/unattended-action-policy.js +182 -0
- package/src/lib/worktree-cleanup-safety.js +138 -0
- package/src/lib/worktree-isolator.js +8 -0
- package/src/lib/worktree-sparse.js +131 -0
- package/src/repl/agent-repl.js +280 -30
- package/src/repl/permission-tier.js +28 -0
- package/src/runtime/agent-core.js +565 -21
- package/src/runtime/coding-agent-contract-shared.cjs +60 -1
- package/src/runtime/diagnostics.js +60 -0
- package/src/runtime/headless-runner.js +393 -1
- package/src/runtime/headless-stream.js +60 -1
- package/src/assets/web-panel/assets/MobileProjects-D10VISps.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DhiGrbsh.js +0 -1
- package/src/assets/web-panel/assets/index-B7a1TrU6.js +0 -1
- package/src/assets/web-panel/assets/index-C2B1KRja.js +0 -1
package/src/commands/plugin.js
CHANGED
|
@@ -30,6 +30,135 @@ import {
|
|
|
30
30
|
getPluginSkills,
|
|
31
31
|
} from "../harness/plugin-manager.js";
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* After an install/upgrade, resolve the just-installed plugin's DECLARED
|
|
35
|
+
* capabilities and its current consent status, so `cc plugin add`/`upgrade`
|
|
36
|
+
* surface a capability list + diff and tell the user when a WIDENING requires
|
|
37
|
+
* re-consent (mirroring `cc plugin consent`). Best-effort: capability rendering
|
|
38
|
+
* must never fail an otherwise-successful install. Returns a structured summary
|
|
39
|
+
* (for --json folding) or null when the plugin declares nothing / can't be
|
|
40
|
+
* resolved.
|
|
41
|
+
*/
|
|
42
|
+
async function resolvePluginCapabilityNotice(name, scope, cwd) {
|
|
43
|
+
try {
|
|
44
|
+
const { discoverPlugins } = await import("../lib/plugin-runtime/scopes.js");
|
|
45
|
+
const { describeCapabilities } =
|
|
46
|
+
await import("../lib/plugin-runtime/capabilities.js");
|
|
47
|
+
const consent = await import("../lib/plugin-runtime/capability-consent.js");
|
|
48
|
+
const installed = discoverPlugins({ cwd, skipPolicy: true }).find(
|
|
49
|
+
(p) => p.name === name && p.scope === scope,
|
|
50
|
+
);
|
|
51
|
+
if (!installed) return null;
|
|
52
|
+
const declared = installed.manifest?.capabilities;
|
|
53
|
+
if (!declared || consent.capabilitiesAreEmpty(declared)) return null;
|
|
54
|
+
const entry = consent.loadConsentStore()[`${scope}:${name}`] || null;
|
|
55
|
+
const status = consent.capabilityConsentStatus(declared, entry);
|
|
56
|
+
return {
|
|
57
|
+
declared: describeCapabilities(declared),
|
|
58
|
+
consented: status.consented,
|
|
59
|
+
reason: status.reason,
|
|
60
|
+
added: status.added,
|
|
61
|
+
};
|
|
62
|
+
} catch {
|
|
63
|
+
return null; // capability rendering is advisory — never break an install
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Print the capability notice (text mode) after an install/upgrade. Pass
|
|
69
|
+
* `{ hint: false }` to omit the trailing `cc plugin consent … --grant` pointer
|
|
70
|
+
* when consent is being granted inline (explicit flag or interactive prompt).
|
|
71
|
+
*/
|
|
72
|
+
function printPluginCapabilityNotice(name, notice, { hint = true } = {}) {
|
|
73
|
+
if (!notice) return;
|
|
74
|
+
logger.log(chalk.bold("\nCapabilities (declared):"));
|
|
75
|
+
for (const l of notice.declared) logger.log(` ${chalk.magenta(l)}`);
|
|
76
|
+
if (notice.consented) {
|
|
77
|
+
logger.log(chalk.gray(` capability consent: ${notice.reason}`));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
logger.log(
|
|
81
|
+
chalk.yellow(` ⚠ capability consent required (${notice.reason})`),
|
|
82
|
+
);
|
|
83
|
+
if (notice.added.length)
|
|
84
|
+
logger.log(chalk.yellow(` new: ${notice.added.join(", ")}`));
|
|
85
|
+
if (hint)
|
|
86
|
+
logger.log(
|
|
87
|
+
chalk.dim(` run \`cc plugin consent ${name} --grant\` to allow them`),
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Record consent for a freshly installed/upgraded plugin's currently-declared
|
|
93
|
+
* capabilities (re-discovers to get the raw declared set + version). Best-effort
|
|
94
|
+
* — returns false rather than throwing so it can never break an install.
|
|
95
|
+
*/
|
|
96
|
+
async function grantInstalledPluginCapabilities(name, scope, cwd) {
|
|
97
|
+
try {
|
|
98
|
+
const { discoverPlugins } = await import("../lib/plugin-runtime/scopes.js");
|
|
99
|
+
const consent = await import("../lib/plugin-runtime/capability-consent.js");
|
|
100
|
+
const installed = discoverPlugins({ cwd, skipPolicy: true }).find(
|
|
101
|
+
(p) => p.name === name && p.scope === scope,
|
|
102
|
+
);
|
|
103
|
+
if (!installed) return false;
|
|
104
|
+
const declared = installed.manifest?.capabilities;
|
|
105
|
+
if (!declared || consent.capabilitiesAreEmpty(declared)) return false;
|
|
106
|
+
consent.consentPluginCapabilities(name, {
|
|
107
|
+
scope,
|
|
108
|
+
version: installed.version,
|
|
109
|
+
capabilities: declared,
|
|
110
|
+
});
|
|
111
|
+
return true;
|
|
112
|
+
} catch {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Handle the capability-consent gate after a text-mode install/upgrade: print
|
|
119
|
+
* the notice and, when consent is required, either auto-grant (explicit
|
|
120
|
+
* `--grant-capabilities`) or block interactively (TTY) to grant it right away
|
|
121
|
+
* instead of forcing a separate `cc plugin consent --grant` step. Returns true
|
|
122
|
+
* if consent was recorded during this call.
|
|
123
|
+
*/
|
|
124
|
+
async function applyCapabilityConsentGate(name, scope, notice, cwd, opts = {}) {
|
|
125
|
+
const consent = await import("../lib/plugin-runtime/capability-consent.js");
|
|
126
|
+
const action = consent.resolveConsentAction(notice, {
|
|
127
|
+
grant: opts.grant === true,
|
|
128
|
+
interactive: opts.interactive === true,
|
|
129
|
+
});
|
|
130
|
+
if (action === "advisory") {
|
|
131
|
+
printPluginCapabilityNotice(name, notice);
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
// Show the ⚠ notice + new-capability diff before deciding; suppress the
|
|
135
|
+
// "run cc plugin consent" pointer since we grant inline here.
|
|
136
|
+
printPluginCapabilityNotice(name, notice, { hint: false });
|
|
137
|
+
if (action === "prompt") {
|
|
138
|
+
let ok = false;
|
|
139
|
+
try {
|
|
140
|
+
const { confirm } = await import("@inquirer/prompts");
|
|
141
|
+
ok = await confirm({
|
|
142
|
+
message: `Grant these capabilities to ${name} now?`,
|
|
143
|
+
default: false,
|
|
144
|
+
});
|
|
145
|
+
} catch {
|
|
146
|
+
ok = false; // Ctrl-C / non-interactive → treat as decline (fail closed)
|
|
147
|
+
}
|
|
148
|
+
if (!ok) {
|
|
149
|
+
logger.log(
|
|
150
|
+
chalk.dim(
|
|
151
|
+
" capabilities not granted — components needing them stay disabled",
|
|
152
|
+
),
|
|
153
|
+
);
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
const granted = await grantInstalledPluginCapabilities(name, scope, cwd);
|
|
158
|
+
if (granted) logger.success(` ✔ capability consent granted for ${name}`);
|
|
159
|
+
return granted;
|
|
160
|
+
}
|
|
161
|
+
|
|
33
162
|
export function registerPluginCommand(program) {
|
|
34
163
|
const plugin = program
|
|
35
164
|
.command("plugin")
|
|
@@ -632,6 +761,17 @@ export function registerPluginCommand(program) {
|
|
|
632
761
|
logger.log(chalk.yellow(` ⚠ ${issue}`));
|
|
633
762
|
}
|
|
634
763
|
}
|
|
764
|
+
// Declared capabilities (Phase 3 gap): show what the plugin says it needs
|
|
765
|
+
// so a user can compare against the components it ships (the audit findings
|
|
766
|
+
// for an under-declared manifest already surface in manifest.warnings).
|
|
767
|
+
if (manifest.capabilitiesDeclared) {
|
|
768
|
+
const { describeCapabilities } =
|
|
769
|
+
await import("../lib/plugin-runtime/capabilities.js");
|
|
770
|
+
const capLines = describeCapabilities(manifest.capabilities);
|
|
771
|
+
logger.log(chalk.bold("\nCapabilities (declared):"));
|
|
772
|
+
if (capLines.length === 0) logger.log(chalk.gray(" (none)"));
|
|
773
|
+
for (const l of capLines) logger.log(` ${chalk.magenta(l)}`);
|
|
774
|
+
}
|
|
635
775
|
for (const w of manifest.warnings) logger.log(chalk.yellow(` ⚠ ${w}`));
|
|
636
776
|
for (const e of manifest.errors) logger.log(chalk.red(` ✖ ${e}`));
|
|
637
777
|
if (manifest.ok) {
|
|
@@ -674,6 +814,10 @@ export function registerPluginCommand(program) {
|
|
|
674
814
|
"--allow-insecure-registry",
|
|
675
815
|
"Allow a plain-HTTP registry URL (MITM risk — trusted networks only)",
|
|
676
816
|
)
|
|
817
|
+
.option(
|
|
818
|
+
"--grant-capabilities",
|
|
819
|
+
"Grant the plugin's declared capabilities at install time (no separate consent step)",
|
|
820
|
+
)
|
|
677
821
|
.option("--json", "Output as JSON")
|
|
678
822
|
.action(async (source, options) => {
|
|
679
823
|
const { installFromSource } =
|
|
@@ -736,8 +880,28 @@ export function registerPluginCommand(program) {
|
|
|
736
880
|
force: options.force === true,
|
|
737
881
|
signature,
|
|
738
882
|
});
|
|
883
|
+
const capNotice = await resolvePluginCapabilityNotice(
|
|
884
|
+
res.name,
|
|
885
|
+
res.scope,
|
|
886
|
+
process.cwd(),
|
|
887
|
+
);
|
|
739
888
|
if (options.json) {
|
|
740
|
-
|
|
889
|
+
// Non-interactive JSON path: honor an explicit --grant-capabilities so
|
|
890
|
+
// scripted installs can consent atomically; never prompt.
|
|
891
|
+
let capabilitiesGranted = false;
|
|
892
|
+
if (options.grantCapabilities && capNotice && !capNotice.consented)
|
|
893
|
+
capabilitiesGranted = await grantInstalledPluginCapabilities(
|
|
894
|
+
res.name,
|
|
895
|
+
res.scope,
|
|
896
|
+
process.cwd(),
|
|
897
|
+
);
|
|
898
|
+
console.log(
|
|
899
|
+
JSON.stringify(
|
|
900
|
+
{ ...res, capabilities: capNotice, capabilitiesGranted },
|
|
901
|
+
null,
|
|
902
|
+
2,
|
|
903
|
+
),
|
|
904
|
+
);
|
|
741
905
|
} else {
|
|
742
906
|
logger.success(
|
|
743
907
|
`Installed ${res.name} v${res.version} (${res.scope} scope)` +
|
|
@@ -746,6 +910,16 @@ export function registerPluginCommand(program) {
|
|
|
746
910
|
logger.log(chalk.gray(` → ${res.dir}`));
|
|
747
911
|
for (const w of res.warnings || [])
|
|
748
912
|
logger.log(chalk.yellow(` ⚠ ${w}`));
|
|
913
|
+
await applyCapabilityConsentGate(
|
|
914
|
+
res.name,
|
|
915
|
+
res.scope,
|
|
916
|
+
capNotice,
|
|
917
|
+
process.cwd(),
|
|
918
|
+
{
|
|
919
|
+
grant: options.grantCapabilities === true,
|
|
920
|
+
interactive: Boolean(process.stdin.isTTY),
|
|
921
|
+
},
|
|
922
|
+
);
|
|
749
923
|
}
|
|
750
924
|
} catch (err) {
|
|
751
925
|
logger.error(`Install failed: ${err.message}`);
|
|
@@ -905,6 +1079,265 @@ export function registerPluginCommand(program) {
|
|
|
905
1079
|
}
|
|
906
1080
|
});
|
|
907
1081
|
|
|
1082
|
+
// plugin consent [name] — view / grant a plugin's CAPABILITY consent
|
|
1083
|
+
// (process / network / filesystem / mcp / monitor / credential). Distinct from
|
|
1084
|
+
// `trust`, which pins the code VERSION: consent pins the capability SET, and
|
|
1085
|
+
// any widening re-prompts even for an already-trusted plugin.
|
|
1086
|
+
plugin
|
|
1087
|
+
.command("consent [name]")
|
|
1088
|
+
.description(
|
|
1089
|
+
"View or grant a plugin's capability consent (--grant / --revoke / --list)",
|
|
1090
|
+
)
|
|
1091
|
+
.option("--scope <scope>", "Scope of the plugin", "project")
|
|
1092
|
+
.option(
|
|
1093
|
+
"--grant",
|
|
1094
|
+
"Grant consent for the plugin's currently-declared capabilities",
|
|
1095
|
+
)
|
|
1096
|
+
.option("--revoke", "Revoke capability consent")
|
|
1097
|
+
.option("--list", "List all capability consent entries")
|
|
1098
|
+
.option("--json", "Output as JSON")
|
|
1099
|
+
.action(async (name, options) => {
|
|
1100
|
+
const consent =
|
|
1101
|
+
await import("../lib/plugin-runtime/capability-consent.js");
|
|
1102
|
+
const { describeCapabilities } =
|
|
1103
|
+
await import("../lib/plugin-runtime/capabilities.js");
|
|
1104
|
+
|
|
1105
|
+
if (!name || options.list) {
|
|
1106
|
+
const rows = consent.listCapabilityConsent();
|
|
1107
|
+
if (options.json) {
|
|
1108
|
+
console.log(JSON.stringify(rows, null, 2));
|
|
1109
|
+
return;
|
|
1110
|
+
}
|
|
1111
|
+
if (rows.length === 0) {
|
|
1112
|
+
logger.info("No capability consent recorded.");
|
|
1113
|
+
return;
|
|
1114
|
+
}
|
|
1115
|
+
logger.log(chalk.bold(`Capability consent (${rows.length}):`));
|
|
1116
|
+
for (const r of rows) {
|
|
1117
|
+
logger.log(` ${chalk.cyan(r.name)} v${r.version} [${r.scope}]`);
|
|
1118
|
+
for (const c of r.capabilities) logger.log(` ${chalk.magenta(c)}`);
|
|
1119
|
+
}
|
|
1120
|
+
return;
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
if (options.revoke) {
|
|
1124
|
+
const res = consent.revokeCapabilityConsent(name, {
|
|
1125
|
+
scope: options.scope,
|
|
1126
|
+
});
|
|
1127
|
+
if (res.removed) {
|
|
1128
|
+
logger.success(
|
|
1129
|
+
`Revoked capability consent for ${name} (${options.scope} scope)`,
|
|
1130
|
+
);
|
|
1131
|
+
} else {
|
|
1132
|
+
logger.info(
|
|
1133
|
+
`${name} had no capability consent at ${options.scope} scope`,
|
|
1134
|
+
);
|
|
1135
|
+
}
|
|
1136
|
+
return;
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
// Resolve the installed plugin + its declared capabilities.
|
|
1140
|
+
const { discoverPlugins } =
|
|
1141
|
+
await import("../lib/plugin-runtime/scopes.js");
|
|
1142
|
+
let installed = null;
|
|
1143
|
+
try {
|
|
1144
|
+
installed = discoverPlugins({
|
|
1145
|
+
cwd: process.cwd(),
|
|
1146
|
+
skipPolicy: true,
|
|
1147
|
+
}).find((p) => p.name === name && p.scope === options.scope);
|
|
1148
|
+
} catch {
|
|
1149
|
+
/* discovery best-effort */
|
|
1150
|
+
}
|
|
1151
|
+
if (!installed) {
|
|
1152
|
+
logger.error(`${name} is not installed at ${options.scope} scope`);
|
|
1153
|
+
process.exitCode = 1;
|
|
1154
|
+
return;
|
|
1155
|
+
}
|
|
1156
|
+
const declared = installed.manifest?.capabilities;
|
|
1157
|
+
const entry =
|
|
1158
|
+
consent.loadConsentStore()[`${options.scope}:${name}`] || null;
|
|
1159
|
+
const status = consent.capabilityConsentStatus(declared, entry);
|
|
1160
|
+
|
|
1161
|
+
if (options.grant) {
|
|
1162
|
+
consent.consentPluginCapabilities(name, {
|
|
1163
|
+
scope: options.scope,
|
|
1164
|
+
version: installed.version,
|
|
1165
|
+
capabilities: declared,
|
|
1166
|
+
});
|
|
1167
|
+
const capLines = describeCapabilities(declared);
|
|
1168
|
+
if (options.json) {
|
|
1169
|
+
console.log(
|
|
1170
|
+
JSON.stringify(
|
|
1171
|
+
{
|
|
1172
|
+
granted: true,
|
|
1173
|
+
name,
|
|
1174
|
+
scope: options.scope,
|
|
1175
|
+
version: installed.version,
|
|
1176
|
+
capabilities: capLines,
|
|
1177
|
+
},
|
|
1178
|
+
null,
|
|
1179
|
+
2,
|
|
1180
|
+
),
|
|
1181
|
+
);
|
|
1182
|
+
return;
|
|
1183
|
+
}
|
|
1184
|
+
logger.success(
|
|
1185
|
+
`Granted capability consent for ${name} v${installed.version} (${options.scope} scope)`,
|
|
1186
|
+
);
|
|
1187
|
+
for (const l of capLines) logger.log(` ${chalk.magenta(l)}`);
|
|
1188
|
+
return;
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
// Show status.
|
|
1192
|
+
const capLines = describeCapabilities(declared);
|
|
1193
|
+
if (options.json) {
|
|
1194
|
+
console.log(
|
|
1195
|
+
JSON.stringify(
|
|
1196
|
+
{
|
|
1197
|
+
name,
|
|
1198
|
+
scope: options.scope,
|
|
1199
|
+
version: installed.version,
|
|
1200
|
+
declared: capLines,
|
|
1201
|
+
...status,
|
|
1202
|
+
},
|
|
1203
|
+
null,
|
|
1204
|
+
2,
|
|
1205
|
+
),
|
|
1206
|
+
);
|
|
1207
|
+
return;
|
|
1208
|
+
}
|
|
1209
|
+
logger.log(
|
|
1210
|
+
chalk.bold("Capability consent: ") +
|
|
1211
|
+
`${chalk.cyan(name)} v${installed.version} [${options.scope}]`,
|
|
1212
|
+
);
|
|
1213
|
+
logger.log(chalk.bold("Declared capabilities:"));
|
|
1214
|
+
if (capLines.length === 0) logger.log(chalk.gray(" (none)"));
|
|
1215
|
+
for (const l of capLines) logger.log(` ${chalk.magenta(l)}`);
|
|
1216
|
+
logger.log(
|
|
1217
|
+
chalk.bold("Status: ") +
|
|
1218
|
+
(status.consented
|
|
1219
|
+
? chalk.green("consented")
|
|
1220
|
+
: chalk.yellow("NEEDS CONSENT")),
|
|
1221
|
+
);
|
|
1222
|
+
logger.log(chalk.gray(` ${status.reason}`));
|
|
1223
|
+
if (status.added.length) {
|
|
1224
|
+
logger.log(
|
|
1225
|
+
chalk.yellow(` new since consent: ${status.added.join(", ")}`),
|
|
1226
|
+
);
|
|
1227
|
+
}
|
|
1228
|
+
if (!status.consented) {
|
|
1229
|
+
logger.log(
|
|
1230
|
+
chalk.dim(
|
|
1231
|
+
` run \`cc plugin consent ${name} --grant\` to allow them`,
|
|
1232
|
+
),
|
|
1233
|
+
);
|
|
1234
|
+
}
|
|
1235
|
+
});
|
|
1236
|
+
|
|
1237
|
+
// plugin options — view a plugin's resolved typed options, or set values at a
|
|
1238
|
+
// scope. The security-critical rule: a SENSITIVE option can never be set from
|
|
1239
|
+
// PROJECT scope (a checked-in file must not inject secrets) — such values are
|
|
1240
|
+
// dropped + warned; use `--scope user`.
|
|
1241
|
+
plugin
|
|
1242
|
+
.command("options <name>")
|
|
1243
|
+
.description(
|
|
1244
|
+
"View or set a plugin's typed options (--set key=value, --scope user|project)",
|
|
1245
|
+
)
|
|
1246
|
+
.option("--scope <scope>", "Scope for --set (user|project)", "user")
|
|
1247
|
+
.option(
|
|
1248
|
+
"--set <pair>",
|
|
1249
|
+
"Set an option value (key=value); repeatable",
|
|
1250
|
+
(v, acc) => {
|
|
1251
|
+
acc.push(v);
|
|
1252
|
+
return acc;
|
|
1253
|
+
},
|
|
1254
|
+
[],
|
|
1255
|
+
)
|
|
1256
|
+
.option("--json", "Output as JSON")
|
|
1257
|
+
.action(async (name, options) => {
|
|
1258
|
+
const { discoverPlugins } =
|
|
1259
|
+
await import("../lib/plugin-runtime/scopes.js");
|
|
1260
|
+
const optsMod = await import("../lib/plugin-runtime/plugin-options.js");
|
|
1261
|
+
|
|
1262
|
+
let installed = null;
|
|
1263
|
+
try {
|
|
1264
|
+
installed = discoverPlugins({
|
|
1265
|
+
cwd: process.cwd(),
|
|
1266
|
+
skipPolicy: true,
|
|
1267
|
+
}).find((p) => p.name === name);
|
|
1268
|
+
} catch {
|
|
1269
|
+
/* discovery best-effort */
|
|
1270
|
+
}
|
|
1271
|
+
if (!installed) {
|
|
1272
|
+
logger.error(`${name} is not installed`);
|
|
1273
|
+
process.exitCode = 1;
|
|
1274
|
+
return;
|
|
1275
|
+
}
|
|
1276
|
+
const schema = installed.manifest?.optionsSchema || {};
|
|
1277
|
+
|
|
1278
|
+
// --set: persist values at the requested scope (then fall through to show).
|
|
1279
|
+
if (options.set && options.set.length) {
|
|
1280
|
+
const scope = options.scope === "project" ? "project" : "user";
|
|
1281
|
+
const current = optsMod.loadPluginOptionValues(name, scope, {
|
|
1282
|
+
cwd: process.cwd(),
|
|
1283
|
+
});
|
|
1284
|
+
for (const pair of options.set) {
|
|
1285
|
+
const eq = pair.indexOf("=");
|
|
1286
|
+
if (eq <= 0) {
|
|
1287
|
+
logger.error(`Invalid --set "${pair}" (expected key=value)`);
|
|
1288
|
+
process.exitCode = 1;
|
|
1289
|
+
return;
|
|
1290
|
+
}
|
|
1291
|
+
current[pair.slice(0, eq)] = pair.slice(eq + 1);
|
|
1292
|
+
}
|
|
1293
|
+
optsMod.setPluginOptionValues(name, current, scope, {
|
|
1294
|
+
cwd: process.cwd(),
|
|
1295
|
+
});
|
|
1296
|
+
logger.success(`Set option(s) for ${name} at ${scope} scope`);
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
const resolved = optsMod.getResolvedPluginOptions(name, schema, {
|
|
1300
|
+
cwd: process.cwd(),
|
|
1301
|
+
});
|
|
1302
|
+
if (options.json) {
|
|
1303
|
+
console.log(
|
|
1304
|
+
JSON.stringify(
|
|
1305
|
+
{
|
|
1306
|
+
name,
|
|
1307
|
+
scope: installed.scope,
|
|
1308
|
+
options: resolved.redacted,
|
|
1309
|
+
sources: resolved.sources,
|
|
1310
|
+
warnings: resolved.warnings,
|
|
1311
|
+
droppedFromProject: resolved.droppedFromProject,
|
|
1312
|
+
},
|
|
1313
|
+
null,
|
|
1314
|
+
2,
|
|
1315
|
+
),
|
|
1316
|
+
);
|
|
1317
|
+
return;
|
|
1318
|
+
}
|
|
1319
|
+
logger.log(chalk.bold(`Options: ${chalk.cyan(name)}`));
|
|
1320
|
+
const keys = Object.keys(resolved.redacted);
|
|
1321
|
+
if (keys.length === 0) logger.log(chalk.gray(" (no options)"));
|
|
1322
|
+
for (const k of keys) {
|
|
1323
|
+
logger.log(
|
|
1324
|
+
` ${chalk.cyan(k)} = ${resolved.redacted[k]} ${chalk.gray(
|
|
1325
|
+
`[${resolved.sources[k] || "default"}]`,
|
|
1326
|
+
)}`,
|
|
1327
|
+
);
|
|
1328
|
+
}
|
|
1329
|
+
if (resolved.droppedFromProject.length) {
|
|
1330
|
+
logger.log(
|
|
1331
|
+
chalk.yellow(
|
|
1332
|
+
` ⚠ dropped from project config (sensitive/user-only): ${resolved.droppedFromProject.join(
|
|
1333
|
+
", ",
|
|
1334
|
+
)} — set with --scope user`,
|
|
1335
|
+
),
|
|
1336
|
+
);
|
|
1337
|
+
}
|
|
1338
|
+
for (const w of resolved.warnings) logger.log(chalk.gray(` ${w}`));
|
|
1339
|
+
});
|
|
1340
|
+
|
|
908
1341
|
// plugin monitors — list (and optionally run) trusted plugins' background
|
|
909
1342
|
// monitors. `--run --seconds N` actually starts the supervisor for N seconds,
|
|
910
1343
|
// prints captured output, then reaps everything (verifies no leaked process).
|
|
@@ -991,6 +1424,10 @@ export function registerPluginCommand(program) {
|
|
|
991
1424
|
)
|
|
992
1425
|
.option("--scope <scope>", `Scope to update in (${SCOPES})`, "user")
|
|
993
1426
|
.option("--force", "Reinstall even if the version is unchanged")
|
|
1427
|
+
.option(
|
|
1428
|
+
"--grant-capabilities",
|
|
1429
|
+
"Grant any newly declared capabilities during the upgrade (no separate consent step)",
|
|
1430
|
+
)
|
|
994
1431
|
.action(async (source, options) => {
|
|
995
1432
|
const { updatePlugin } = await import("../lib/plugin-runtime/install.js");
|
|
996
1433
|
try {
|
|
@@ -1012,6 +1449,24 @@ export function registerPluginCommand(program) {
|
|
|
1012
1449
|
`${res.name} is already up to date at v${res.version} (use --force to reinstall)`,
|
|
1013
1450
|
);
|
|
1014
1451
|
}
|
|
1452
|
+
// Surface the (possibly widened) capability set + re-consent hint. An
|
|
1453
|
+
// upgrade that adds a capability shows a `⚠ capability consent required`
|
|
1454
|
+
// notice diffed against the prior consent, then either auto-grants
|
|
1455
|
+
// (--grant-capabilities) or blocks interactively to re-consent now.
|
|
1456
|
+
await applyCapabilityConsentGate(
|
|
1457
|
+
res.name,
|
|
1458
|
+
options.scope,
|
|
1459
|
+
await resolvePluginCapabilityNotice(
|
|
1460
|
+
res.name,
|
|
1461
|
+
options.scope,
|
|
1462
|
+
process.cwd(),
|
|
1463
|
+
),
|
|
1464
|
+
process.cwd(),
|
|
1465
|
+
{
|
|
1466
|
+
grant: options.grantCapabilities === true,
|
|
1467
|
+
interactive: Boolean(process.stdin.isTTY),
|
|
1468
|
+
},
|
|
1469
|
+
);
|
|
1015
1470
|
} catch (err) {
|
|
1016
1471
|
logger.error(`Upgrade failed: ${err.message}`);
|
|
1017
1472
|
process.exitCode = 1;
|