chainlesschain 0.162.182 → 0.162.183
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 +1 -1
- package/src/assets/web-panel/assets/{AIOps-DzZ5_xoj.js → AIOps-BapS7lz4.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-DeLXddIg.js → ActionButton-CXYdXEUI.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-rvDCmet1.js → Analytics-CKR5Lexn.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-Yt6QVDnp.js → AppLayout-DATVUOXB.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-BS112K5L.js → Artifacts-vb_0ZlV1.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-0wJuQrNu.js → Audit-BI1l9GWt.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-B90PMgbn.js → BackgroundAgents-BFXbaUEf.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-TkgMglQQ.js → Backup-DEYBJJ6H.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-CQVS9p1l.js → BaseInput-COdzeO0M.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-YTjQHoC7.js → Chat-oSN6sfM5.js} +6 -6
- package/src/assets/web-panel/assets/ChatBubbleRenderer-CI_jT0ru.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-5bwaOabq.js → Checkbox-BezEa4tm.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-BFmNQ_Xe.js → Codegen-CNEL0Ife.js} +1 -1
- package/src/assets/web-panel/assets/{Col-BT_u4Dzp.js → Col-Bf2Y2Bn1.js} +1 -1
- package/src/assets/web-panel/assets/{Community-CJP52u5b.js → Community-BfUlu4Hc.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BpzhJE9i.js → Compact-BN4xWP9e.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-Cg7rfslp.js → Compliance-Bt6BKmEP.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-JisxL6Yy.js → Cowork-DKLp8YxO.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-Bu7Ug_MC.js → Cron-o7Hhw6ky.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CvuqoLdj.js → Crosschain-DaNXWJIw.js} +1 -1
- package/src/assets/web-panel/assets/{DID-C2u9G8Pu.js → DID-B-Qa2mha.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-BFt5Yv3d.js → Dashboard-CMX0Qnxw.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DIaT9Wxq.js → Dropdown-BLuLyRu_.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-D_A601Y4.js → EmailListRenderer-CFBAeMij.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard--IyQ8I8w.js → FamilyGuardDashboard-DWzXQ67V.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BihWHxuY.js → Federation-DB1QSLgr.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-BB8dOXc_.js → FormItemContext-C-OKCToP.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DQYhj1HH.js → GenericCardRenderer-DMJFtFZf.js} +1 -1
- package/src/assets/web-panel/assets/{Git-B-2QZxGf.js → Git-DsGSujOV.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CusSb-nG.js → Governance-B0iS9NEW.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BAjmvPPL.js → Inference-CH004H7c.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DoNYWKYq.js → KnowledgeGraph-Q9MTQ83c.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-B8fKWD-n.js → Logs-B_fyjZK9.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-BlJm1J7E.js → MarkdownRenderer-C0o4FtpD.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-CyOscbSL.js → Marketplace-BIStF9d1.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-Ex6Om5da.js → McpTools-pGfal768.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-CDcD8l8r.js → Memory-xbNqpIqB.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-xfBqoFDg.js → MobileBridge-B5EQGrIK.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-VTc3gT1y.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-CIWd36OV.js → Mtc-a_rmfxJH.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-CPX0ouuA.js → MtcAudit-BmKuofUr.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-BDJsIUuW.js → Multisig-BQbJ-CAN.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-DEkbuD3N.js → NLProgramming-JtPJKX25.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-DJpHRhH1.js → Notes-ZFKznTSG.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-C1UZ-Qd5.js → NotificationSettings-B6aHRBBR.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-GlJtqLjT.js → OrderTableRenderer-DdcsOqEz.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-Bbhj0fac.js → Organization-BFDTAUgS.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-1H04x3kx.js → Overflow-0FoTfbWH.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CDpPe3et.js → P2P-CWd90etw.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-MUX0Bpvw.js → PdhVaultBrowser-DtCGC-W-.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-A07-0Ci1.js → Permissions-CvQ7nr7T.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-DhhDWxAZ.js → PersonalDataHub-rdNPcR-Z.js} +5 -5
- package/src/assets/web-panel/assets/{Pipeline-CyfbJfe-.js → Pipeline-CmrfiNOs.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-CNFps3ED.js → Privacy-D7ep1h_t.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit--T-u3Dr5.js → ProjectInit-C0xKINHS.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-DJmrK2fC.js → ProjectSettings-AOmZFp-F.js} +2 -2
- package/src/assets/web-panel/assets/Projects-BWHSkXZP.js +1 -0
- package/src/assets/web-panel/assets/{Providers-DLzzbOZd.js → Providers-Cb7JCTPL.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-CexOomKS.js → QrScannerModal-BDMehcXC.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-QklGi19_.js → QuickAsk-BF6_1nvx.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Bb9kwSw8.js → Recommend-BHfT-A28.js} +1 -1
- package/src/assets/web-panel/assets/RemoteSession-B6EEf8hh.js +5 -0
- package/src/assets/web-panel/assets/{Reputation-Dr5cLP0N.js → Reputation-CsWHLEcj.js} +1 -1
- package/src/assets/web-panel/assets/{Row-oCQHYv5t.js → Row-D6srnWhm.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-IFDEykIR.js → RssFeed-Xhr-KyVd.js} +3 -3
- package/src/assets/web-panel/assets/{Search-CspVIxDc.js → Search-vIbIJvwL.js} +1 -1
- package/src/assets/web-panel/assets/{Security-Bm66o_DH.js → Security-Bzi5Aiko.js} +4 -4
- package/src/assets/web-panel/assets/{Services-DvanNqXl.js → Services-BHtVX52P.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CHjEe9_O.js → Skeleton-C0R8B2jf.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-Cb8jWjMX.js → Skills-DtT6rWOX.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DxZm1491.js → Sla-0B37mxVU.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DWxEEclC.js → SpeechSettings-0V2jE1Bs.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-FIvOFw5p.js → SyncSettings-CYedRzaj.js} +2 -2
- package/src/assets/web-panel/assets/Tasks-D-R1x8vm.js +1 -0
- package/src/assets/web-panel/assets/{Templates-CaNjzV_t.js → Templates-BKoHztGT.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-DjlP6TmH.js → Tenant--17nwVNZ.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-Dnkos7vW.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-DoZ8y7y8.js → TimelineRenderer-C5jx4AE3.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-390cg2TC.js → Tokens-DYJKYa9t.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-CLrtCj5_.js → Trigger-DChpWiQ9.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DpESfSPn.js → Trust-DfWG52EA.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CN6279O0.js → UkeySign-CMugYcyA.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-DPtAUlSe.js → VideoEditing-BOSmrHAd.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-nKOMV_1n.js → Wallet-D5g3k3Sa.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-HuXlSOc4.js → WebAuthn-D-7u4Mkc.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-CUfFjARi.js → WorkflowEditor-CFzZMSUJ.js} +1 -1
- package/src/assets/web-panel/assets/{chat-6Eq0PcZJ.js → chat-VbR6l6mc.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BP_Sf6Iy.js → colors-BSZn8EDS.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BufMKIh5.js → compact-item-y74obMEq.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BBMXxWSW.js → createContext-C326bjex.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-D3Bho_6u.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-fUK_tRO2.js → hasIn-D_INJQT_.js} +1 -1
- package/src/assets/web-panel/assets/{index-LvCBfTLo.js → index-4PIeTM--.js} +1 -1
- package/src/assets/web-panel/assets/{index-CgiECHu2.js → index-4eyH-eC2.js} +1 -1
- package/src/assets/web-panel/assets/index-5iAFwYx1.js +1 -0
- package/src/assets/web-panel/assets/{index-DLpIs_P_.js → index-9PIVuXqo.js} +1 -1
- package/src/assets/web-panel/assets/{index-cpEli44X.js → index-B7SrC-On.js} +1 -1
- package/src/assets/web-panel/assets/{index-6GmBa4Kg.js → index-BJi3UqBt.js} +1 -1
- package/src/assets/web-panel/assets/{index-D9vU25ij.js → index-BY8-nCgs.js} +1 -1
- package/src/assets/web-panel/assets/index-BfnB7LPx.js +1 -0
- package/src/assets/web-panel/assets/{index-B2vS66eI.js → index-Bfw2hf2s.js} +1 -1
- package/src/assets/web-panel/assets/{index-DVsqvI4M.js → index-BjcWKg1S.js} +1 -1
- package/src/assets/web-panel/assets/{index-C44atv4k.js → index-BnSfnSMP.js} +1 -1
- package/src/assets/web-panel/assets/{index-BWKoBU8R.js → index-Bnua8IX3.js} +1 -1
- package/src/assets/web-panel/assets/{index-GwdRUZ-x.js → index-C-ZCaUJc.js} +1 -1
- package/src/assets/web-panel/assets/{index-pum7HYBA.js → index-C2NyllnW.js} +1 -1
- package/src/assets/web-panel/assets/{index-B9WYSn4m.js → index-C327pLbw.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bkg4ZePE.js → index-CMHqs3Jb.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmkMXwnR.js → index-CfLJ42kv.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dyngbd29.js → index-Cr3uuz0C.js} +19 -19
- package/src/assets/web-panel/assets/{index-t8N1tSeX.js → index-CsovTpx9.js} +1 -1
- package/src/assets/web-panel/assets/{index-DocdRcbd.js → index-CzE53HiB.js} +1 -1
- package/src/assets/web-panel/assets/{index-fzaMtSJ8.js → index-DBkzrpiL.js} +1 -1
- package/src/assets/web-panel/assets/{index-CE2DdTP2.js → index-DNMxIsDg.js} +1 -1
- package/src/assets/web-panel/assets/{index-wKTLbKyc.js → index-DUU2606o.js} +1 -1
- package/src/assets/web-panel/assets/{index-uCbEN7cY.js → index-DdyjrCAu.js} +1 -1
- package/src/assets/web-panel/assets/{index-CZ6Yt17L.js → index-DkH1JvEt.js} +1 -1
- package/src/assets/web-panel/assets/{index-CwSf5pnf.js → index-Dlxh9D8D.js} +1 -1
- package/src/assets/web-panel/assets/{index-3FuwBewR.js → index-DuIkfnTF.js} +1 -1
- package/src/assets/web-panel/assets/{index-CW_G-MXw.js → index-DwHSZLXg.js} +1 -1
- package/src/assets/web-panel/assets/{index-BHy6yNiF.js → index-E_v1ZCTP.js} +1 -1
- package/src/assets/web-panel/assets/{index-wV6iGdpY.js → index-FQBsuExX.js} +1 -1
- package/src/assets/web-panel/assets/{index-DASluSqY.js → index-GA80ir_u.js} +1 -1
- package/src/assets/web-panel/assets/{index-BMLHv389.js → index-IZAWt0H8.js} +1 -1
- package/src/assets/web-panel/assets/{index-B7Etk0Te.js → index-Iw0FfqUz.js} +1 -1
- package/src/assets/web-panel/assets/{index-D4_MuGkd.js → index-KF9Zmqln.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cp8vhyZy.js → index-abmn_8Yz.js} +1 -1
- package/src/assets/web-panel/assets/{index-2A5ph8b2.js → index-gINyI1rh.js} +1 -1
- package/src/assets/web-panel/assets/{index-CeASi4fr.js → index-jYaogFE8.js} +1 -1
- package/src/assets/web-panel/assets/{index-CGjmILDm.js → index-nSn2-C4N.js} +1 -1
- package/src/assets/web-panel/assets/{index-DPdUNk1i.js → index-qMA4GYdQ.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-V5Fo95FM.js → initDefaultProps-DI0Zaf8-.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BYWU0hUT.js → motion-BZDKSy3Z.js} +1 -1
- package/src/assets/web-panel/assets/{move-Cr1M-J2h.js → move-DsIW01Vp.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-BysQKi2N.js → mtc-parser-CohkDhsf.js} +1 -1
- package/src/assets/web-panel/assets/{omit-D1zHU8GC.js → omit-DpiN5rzg.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-CUArxtfi.js → pickAttrs-qbuqni3y.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-ChoYEys0.js → placementArrow-mBky6714.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BQRs3Mo7.js → responsiveObserve-Bas3eQ2K.js} +1 -1
- package/src/assets/web-panel/assets/{slide-B8zbsCkg.js → slide-CBx_SKoK.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-C2U8Gs6h.js → statusUtils-BlYguJSV.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-Dd8MgL_V.js → styleChecker-BCYQmRGv.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-hknqY5NH.js → useFlexGapSupport-Dp5dybLM.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-CLTAmcfw.js → useFs-DHAMBgA2.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-ByegHbiB.js → usePersonalDataHub-W6jsSw76.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DqlAy5DP.js → vnode-BkI6aayc.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-DiXiztQn.js → zoom-C_IMGueq.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agent.js +9 -0
- package/src/commands/background-session.js +49 -0
- package/src/commands/plugin.js +235 -23
- package/src/commands/session.js +13 -0
- package/src/data/changelog.json +13 -0
- package/src/harness/jsonl-session-store.js +6 -4
- package/src/lib/agent-team/team-runner.js +19 -1
- package/src/lib/background-agent-supervisor.js +49 -0
- package/src/lib/plugin-runtime/install.js +226 -7
- package/src/lib/plugin-runtime/scopes.js +13 -2
- package/src/lib/plugin-usage-attribution.js +44 -0
- package/src/lib/process-execution-broker/index.js +252 -1
- package/src/lib/process-execution-broker/platform-sandbox.js +1251 -101
- package/src/lib/session-usage.js +77 -0
- package/src/repl/agent-repl.js +6 -6
- package/src/runtime/headless-runner.js +9 -1
- package/src/runtime/headless-stream.js +20 -1
- package/src/runtime/mcp-config.js +15 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-PR074hUN.js +0 -1
- package/src/assets/web-panel/assets/MobileProjects-BwObMMA2.js +0 -1
- package/src/assets/web-panel/assets/Projects-Qx_MdX9k.js +0 -1
- package/src/assets/web-panel/assets/RemoteSession-DZuVNNN5.js +0 -5
- package/src/assets/web-panel/assets/Tasks-CyuLnDFR.js +0 -1
- package/src/assets/web-panel/assets/Terminal-DwzGMniO.js +0 -3
- package/src/assets/web-panel/assets/devWarning-DgVKduH2.js +0 -1
- package/src/assets/web-panel/assets/index-DOZTSoS7.js +0 -1
- package/src/assets/web-panel/assets/index-DhpvjpqI.js +0 -1
|
@@ -26,22 +26,32 @@ import {
|
|
|
26
26
|
listInstalledVersions,
|
|
27
27
|
activeVersion,
|
|
28
28
|
discoverPlugins,
|
|
29
|
+
DISABLED_FILENAME,
|
|
29
30
|
} from "./scopes.js";
|
|
30
|
-
import {
|
|
31
|
+
import {
|
|
32
|
+
enforcePluginPolicy,
|
|
33
|
+
verifyPluginManifest,
|
|
34
|
+
} from "../plugin-security.js";
|
|
31
35
|
import {
|
|
32
36
|
writePluginLock,
|
|
33
37
|
buildPluginSbom,
|
|
34
38
|
LOCK_FILENAME,
|
|
39
|
+
readPluginLock,
|
|
40
|
+
verifyInstalledSignature,
|
|
35
41
|
} from "./signature.js";
|
|
42
|
+
import { loadManagedPluginPolicy, filterByManagedPolicy } from "./policy.js";
|
|
43
|
+
import { managedSettingsPath } from "../settings-loader.cjs";
|
|
36
44
|
import executionBroker from "../process-execution-broker/index.js";
|
|
37
45
|
|
|
38
46
|
export const MAX_LISTED_PLUGIN_VERSIONS = 64;
|
|
47
|
+
export const SOURCE_METADATA_FILENAME = ".plugin-source.json";
|
|
39
48
|
|
|
40
49
|
export const _deps = {
|
|
41
50
|
existsSync: fs.existsSync,
|
|
42
51
|
mkdirSync: fs.mkdirSync,
|
|
43
52
|
rmSync: fs.rmSync,
|
|
44
53
|
readdirSync: fs.readdirSync,
|
|
54
|
+
readFileSync: fs.readFileSync,
|
|
45
55
|
copyFileSync: fs.copyFileSync,
|
|
46
56
|
lstatSync: fs.lstatSync,
|
|
47
57
|
writeFileSync: fs.writeFileSync,
|
|
@@ -69,6 +79,17 @@ export function installFromDirectory(srcDir, opts = {}) {
|
|
|
69
79
|
);
|
|
70
80
|
}
|
|
71
81
|
const { name, version } = manifest.metadata;
|
|
82
|
+
const sourceMetadata = normalizeSourceMetadata(opts.sourceMetadata);
|
|
83
|
+
if (opts.managedPolicy) {
|
|
84
|
+
enforcePluginPolicy(
|
|
85
|
+
{
|
|
86
|
+
name,
|
|
87
|
+
source: opts.policySource || sourceMetadata?.source || null,
|
|
88
|
+
action: "install",
|
|
89
|
+
},
|
|
90
|
+
opts.managedPolicy,
|
|
91
|
+
);
|
|
92
|
+
}
|
|
72
93
|
|
|
73
94
|
// Optional signature/integrity verification of the manifest at install time
|
|
74
95
|
// (Phase 3.3l). verifyPluginManifest THROWS on any mismatch/failure — a signed
|
|
@@ -108,6 +129,15 @@ export function installFromDirectory(srcDir, opts = {}) {
|
|
|
108
129
|
// unsigned install that forged lock would otherwise survive into the
|
|
109
130
|
// "immutable" version dir and defeat load-time requireSignedPlugins.
|
|
110
131
|
_deps.rmSync(path.join(dest, LOCK_FILENAME), { force: true });
|
|
132
|
+
_deps.rmSync(path.join(dest, SOURCE_METADATA_FILENAME), { force: true });
|
|
133
|
+
|
|
134
|
+
if (sourceMetadata) {
|
|
135
|
+
_deps.writeFileSync(
|
|
136
|
+
path.join(dest, SOURCE_METADATA_FILENAME),
|
|
137
|
+
JSON.stringify(sourceMetadata, null, 2),
|
|
138
|
+
"utf8",
|
|
139
|
+
);
|
|
140
|
+
}
|
|
111
141
|
|
|
112
142
|
// Record the verified signature into the installed (immutable) version dir so
|
|
113
143
|
// load-time enforcement can re-check it. The manifest was copied verbatim, so
|
|
@@ -138,6 +168,8 @@ export function installFromDirectory(srcDir, opts = {}) {
|
|
|
138
168
|
dir: dest,
|
|
139
169
|
warnings: manifest.warnings,
|
|
140
170
|
signatureVerified: verification?.signatureVerified === true,
|
|
171
|
+
sourceMetadata,
|
|
172
|
+
enabled: isPluginEnabled(name, { scope, cwd: opts.cwd }),
|
|
141
173
|
};
|
|
142
174
|
}
|
|
143
175
|
|
|
@@ -150,8 +182,21 @@ export function installFromDirectory(srcDir, opts = {}) {
|
|
|
150
182
|
*/
|
|
151
183
|
export function installFromSource(source, opts = {}) {
|
|
152
184
|
return _withMaterializedSource(source, (dir, info) => {
|
|
153
|
-
const
|
|
154
|
-
|
|
185
|
+
const sourceMetadata =
|
|
186
|
+
normalizeSourceMetadata(opts.sourceMetadata) ||
|
|
187
|
+
normalizeSourceMetadata(
|
|
188
|
+
info
|
|
189
|
+
? { type: "git", source: info.url, ref: info.ref || null }
|
|
190
|
+
: { type: "local", source: path.resolve(String(source || "")) },
|
|
191
|
+
);
|
|
192
|
+
const res = installFromDirectory(dir, { ...opts, sourceMetadata });
|
|
193
|
+
return info
|
|
194
|
+
? {
|
|
195
|
+
...res,
|
|
196
|
+
source: sourceMetadata?.source || null,
|
|
197
|
+
ref: sourceMetadata?.ref || null,
|
|
198
|
+
}
|
|
199
|
+
: res;
|
|
155
200
|
});
|
|
156
201
|
}
|
|
157
202
|
|
|
@@ -202,6 +247,13 @@ export function updatePlugin(source, opts = {}) {
|
|
|
202
247
|
);
|
|
203
248
|
}
|
|
204
249
|
const { name, version } = manifest.metadata;
|
|
250
|
+
const sourceMetadata =
|
|
251
|
+
normalizeSourceMetadata(opts.sourceMetadata) ||
|
|
252
|
+
normalizeSourceMetadata(
|
|
253
|
+
info
|
|
254
|
+
? { type: "git", source: info.url, ref: info.ref || null }
|
|
255
|
+
: { type: "local", source: path.resolve(String(source || "")) },
|
|
256
|
+
);
|
|
205
257
|
const previousVersion = getActiveVersion(name, { scope, cwd: opts.cwd });
|
|
206
258
|
const dest = pluginVersionDir(scope, name, version, { cwd: opts.cwd });
|
|
207
259
|
const sameVersionExists = _deps.existsSync(dest);
|
|
@@ -218,18 +270,24 @@ export function updatePlugin(source, opts = {}) {
|
|
|
218
270
|
previousVersion,
|
|
219
271
|
updated: previousVersion !== version,
|
|
220
272
|
reinstalled: false,
|
|
221
|
-
source:
|
|
273
|
+
source: sourceMetadata?.source || null,
|
|
274
|
+
ref: sourceMetadata?.ref || null,
|
|
222
275
|
};
|
|
223
276
|
}
|
|
224
277
|
|
|
225
|
-
const res = installFromDirectory(dir, {
|
|
278
|
+
const res = installFromDirectory(dir, {
|
|
279
|
+
...opts,
|
|
280
|
+
scope,
|
|
281
|
+
force: true,
|
|
282
|
+
sourceMetadata,
|
|
283
|
+
});
|
|
226
284
|
return {
|
|
227
285
|
...res,
|
|
228
286
|
previousVersion,
|
|
229
287
|
updated: previousVersion !== version,
|
|
230
288
|
reinstalled: sameVersionExists,
|
|
231
|
-
source:
|
|
232
|
-
ref:
|
|
289
|
+
source: sourceMetadata?.source || null,
|
|
290
|
+
ref: sourceMetadata?.ref || null,
|
|
233
291
|
};
|
|
234
292
|
});
|
|
235
293
|
}
|
|
@@ -319,10 +377,26 @@ export function fetchGitRepo(url, ref) {
|
|
|
319
377
|
* invisible and impossible to inspect / uninstall / un-deny.
|
|
320
378
|
*/
|
|
321
379
|
export function listInstalled(opts = {}) {
|
|
380
|
+
let managed = null;
|
|
381
|
+
let managedError = null;
|
|
382
|
+
try {
|
|
383
|
+
managed = loadManagedPluginPolicy({
|
|
384
|
+
env: opts.env,
|
|
385
|
+
managedSettingsFile: opts.managedSettingsFile,
|
|
386
|
+
});
|
|
387
|
+
} catch (error) {
|
|
388
|
+
managedError = error;
|
|
389
|
+
}
|
|
390
|
+
const policySource = managedSettingsPath({
|
|
391
|
+
env: opts.env,
|
|
392
|
+
managedSettingsFile: opts.managedSettingsFile,
|
|
393
|
+
});
|
|
394
|
+
|
|
322
395
|
return discoverPlugins({
|
|
323
396
|
cwd: opts.cwd,
|
|
324
397
|
scopes: opts.scopes,
|
|
325
398
|
skipPolicy: true,
|
|
399
|
+
includeDisabled: true,
|
|
326
400
|
}).map((p) => {
|
|
327
401
|
const allVersions = listInstalledVersions(p.scope, p.name, {
|
|
328
402
|
cwd: opts.cwd,
|
|
@@ -335,6 +409,16 @@ export function listInstalled(opts = {}) {
|
|
|
335
409
|
) {
|
|
336
410
|
versions[versions.length - 1] = p.version;
|
|
337
411
|
}
|
|
412
|
+
const lock = readPluginLock(p.root);
|
|
413
|
+
const signature = verifyInstalledSignature(p);
|
|
414
|
+
const policyResult =
|
|
415
|
+
managed && !managedError
|
|
416
|
+
? filterByManagedPolicy([p], managed)
|
|
417
|
+
: { kept: [p], dropped: [] };
|
|
418
|
+
const policyDrop = policyResult.dropped[0] || null;
|
|
419
|
+
const sbomFiles = Array.isArray(lock?.sbom?.files)
|
|
420
|
+
? lock.sbom.files.slice(0, 100000)
|
|
421
|
+
: [];
|
|
338
422
|
return {
|
|
339
423
|
name: p.name,
|
|
340
424
|
version: p.version,
|
|
@@ -342,6 +426,45 @@ export function listInstalled(opts = {}) {
|
|
|
342
426
|
scope: p.scope,
|
|
343
427
|
dir: p.root,
|
|
344
428
|
ok: p.manifest?.ok === true,
|
|
429
|
+
enabled: p.enabled !== false,
|
|
430
|
+
source: readSourceMetadata(p.root),
|
|
431
|
+
integrity: {
|
|
432
|
+
signature: {
|
|
433
|
+
present: Boolean(lock?.signatureBase64 && lock?.publicKeyPem),
|
|
434
|
+
verified: signature.signed === true,
|
|
435
|
+
reason: signature.signed ? null : signature.reason || "unsigned",
|
|
436
|
+
manifestSha256: lock?.sha256 || null,
|
|
437
|
+
publicKeySha256:
|
|
438
|
+
signature.publicKeySha256 || lock?.publicKeySha256 || null,
|
|
439
|
+
},
|
|
440
|
+
sbom: {
|
|
441
|
+
present: Boolean(lock?.sbom),
|
|
442
|
+
digest: lock?.sbom?.digest || null,
|
|
443
|
+
fileCount: sbomFiles.length,
|
|
444
|
+
totalBytes: Math.min(
|
|
445
|
+
Number.MAX_SAFE_INTEGER,
|
|
446
|
+
sbomFiles.reduce(
|
|
447
|
+
(sum, file) =>
|
|
448
|
+
sum +
|
|
449
|
+
(Number.isFinite(Number(file?.bytes)) && Number(file.bytes) > 0
|
|
450
|
+
? Number(file.bytes)
|
|
451
|
+
: 0),
|
|
452
|
+
0,
|
|
453
|
+
),
|
|
454
|
+
),
|
|
455
|
+
},
|
|
456
|
+
},
|
|
457
|
+
policy: {
|
|
458
|
+
managed: Boolean(managed) || Boolean(managedError),
|
|
459
|
+
source: policySource,
|
|
460
|
+
allowed: !managedError && !policyDrop,
|
|
461
|
+
reason: managedError
|
|
462
|
+
? managedError.message
|
|
463
|
+
: policyDrop?.reason || (managed ? "allowed by managed policy" : ""),
|
|
464
|
+
requireSigned:
|
|
465
|
+
managed?.requireSignedPlugins === true ||
|
|
466
|
+
managed?.requireSignedPlugins === "require",
|
|
467
|
+
},
|
|
345
468
|
};
|
|
346
469
|
});
|
|
347
470
|
}
|
|
@@ -412,11 +535,107 @@ export function setActiveVersion(name, version, opts = {}) {
|
|
|
412
535
|
return { name, version, scope, active: version };
|
|
413
536
|
}
|
|
414
537
|
|
|
538
|
+
/** Enable or disable one scoped plugin without deleting immutable versions. */
|
|
539
|
+
export function setPluginEnabled(name, enabled, opts = {}) {
|
|
540
|
+
const scope = opts.scope || "user";
|
|
541
|
+
const cwd = opts.cwd;
|
|
542
|
+
const nameDir = pluginNameDir(scope, name, { cwd });
|
|
543
|
+
if (
|
|
544
|
+
!_deps.existsSync(nameDir) ||
|
|
545
|
+
listInstalledVersions(scope, name, { cwd }).length === 0
|
|
546
|
+
) {
|
|
547
|
+
throw new Error(`${name} is not installed at ${scope} scope`);
|
|
548
|
+
}
|
|
549
|
+
const marker = path.join(nameDir, DISABLED_FILENAME);
|
|
550
|
+
if (enabled) {
|
|
551
|
+
_deps.rmSync(marker, { force: true });
|
|
552
|
+
} else {
|
|
553
|
+
_deps.writeFileSync(
|
|
554
|
+
marker,
|
|
555
|
+
JSON.stringify(
|
|
556
|
+
{
|
|
557
|
+
disabled: true,
|
|
558
|
+
reason: String(opts.reason || "disabled by user").slice(0, 256),
|
|
559
|
+
},
|
|
560
|
+
null,
|
|
561
|
+
2,
|
|
562
|
+
),
|
|
563
|
+
"utf8",
|
|
564
|
+
);
|
|
565
|
+
}
|
|
566
|
+
return { name, scope, enabled: Boolean(enabled) };
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
/** Current lifecycle state for one scoped plugin. */
|
|
570
|
+
export function isPluginEnabled(name, opts = {}) {
|
|
571
|
+
const scope = opts.scope || "user";
|
|
572
|
+
return !_deps.existsSync(
|
|
573
|
+
path.join(pluginNameDir(scope, name, { cwd: opts.cwd }), DISABLED_FILENAME),
|
|
574
|
+
);
|
|
575
|
+
}
|
|
576
|
+
|
|
415
577
|
/** Which version is active for a plugin at a scope (or null). */
|
|
416
578
|
export function getActiveVersion(name, opts = {}) {
|
|
417
579
|
return activeVersion(opts.scope || "user", name, { cwd: opts.cwd });
|
|
418
580
|
}
|
|
419
581
|
|
|
582
|
+
function readSourceMetadata(versionDir) {
|
|
583
|
+
const file = path.join(versionDir, SOURCE_METADATA_FILENAME);
|
|
584
|
+
if (!_deps.existsSync(file)) return null;
|
|
585
|
+
try {
|
|
586
|
+
return normalizeSourceMetadata(
|
|
587
|
+
JSON.parse(_deps.readFileSync(file, "utf8")),
|
|
588
|
+
);
|
|
589
|
+
} catch {
|
|
590
|
+
return null;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
function normalizeSourceMetadata(value) {
|
|
595
|
+
if (!value || typeof value !== "object") return null;
|
|
596
|
+
const type = ["local", "git", "registry"].includes(value.type)
|
|
597
|
+
? value.type
|
|
598
|
+
: "git";
|
|
599
|
+
const source = sanitizeSource(value.source, type === "local");
|
|
600
|
+
if (!source) return null;
|
|
601
|
+
const metadata = {
|
|
602
|
+
version: 1,
|
|
603
|
+
type,
|
|
604
|
+
source,
|
|
605
|
+
ref: cleanBounded(value.ref, 256),
|
|
606
|
+
};
|
|
607
|
+
const registry = sanitizeSource(value.registry);
|
|
608
|
+
const resolvedSource = sanitizeSource(value.resolvedSource);
|
|
609
|
+
const packageName = cleanBounded(value.package, 256);
|
|
610
|
+
if (registry) metadata.registry = registry;
|
|
611
|
+
if (resolvedSource) metadata.resolvedSource = resolvedSource;
|
|
612
|
+
if (packageName) metadata.package = packageName;
|
|
613
|
+
if (value.offline === true) metadata.offline = true;
|
|
614
|
+
return metadata;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
function sanitizeSource(value, preservePath = false) {
|
|
618
|
+
const raw = cleanBounded(value, 4096);
|
|
619
|
+
if (!raw) return null;
|
|
620
|
+
if (preservePath) return raw;
|
|
621
|
+
try {
|
|
622
|
+
const parsed = new URL(raw);
|
|
623
|
+
parsed.username = "";
|
|
624
|
+
parsed.password = "";
|
|
625
|
+
parsed.search = "";
|
|
626
|
+
parsed.hash = "";
|
|
627
|
+
return parsed.toString();
|
|
628
|
+
} catch {
|
|
629
|
+
return raw;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
function cleanBounded(value, max) {
|
|
634
|
+
if (typeof value !== "string") return null;
|
|
635
|
+
const clean = value.replace(/\p{Cc}/gu, "").trim();
|
|
636
|
+
return clean ? clean.slice(0, max) : null;
|
|
637
|
+
}
|
|
638
|
+
|
|
420
639
|
// ── guarded recursive copy ────────────────────────────────────────────────
|
|
421
640
|
|
|
422
641
|
/**
|
|
@@ -42,6 +42,7 @@ export const _deps = {
|
|
|
42
42
|
|
|
43
43
|
// Lowest → highest precedence.
|
|
44
44
|
export const SCOPES = ["user", "project", "local"];
|
|
45
|
+
export const DISABLED_FILENAME = ".disabled";
|
|
45
46
|
|
|
46
47
|
/** Filesystem-safe encoding of a (possibly scoped, e.g. @org/name) plugin name. */
|
|
47
48
|
export function encodeName(name) {
|
|
@@ -105,6 +106,13 @@ export function activeVersion(scope, name, opts = {}) {
|
|
|
105
106
|
return versions[0];
|
|
106
107
|
}
|
|
107
108
|
|
|
109
|
+
/** Whether one scoped plugin install is eligible for runtime discovery. */
|
|
110
|
+
export function isPluginEnabled(scope, name, opts = {}) {
|
|
111
|
+
return !_deps.existsSync(
|
|
112
|
+
path.join(pluginNameDir(scope, name, opts), DISABLED_FILENAME),
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
108
116
|
/**
|
|
109
117
|
* Discover every installed plugin's ACTIVE version across all scopes, applying
|
|
110
118
|
* scope precedence (local > project > user) so a name installed at multiple
|
|
@@ -116,8 +124,8 @@ export function activeVersion(scope, name, opts = {}) {
|
|
|
116
124
|
* for tooling that must see even blocked plugins (e.g. `cc plugin installed`
|
|
117
125
|
* showing why something is blocked). No managed settings file → no filtering.
|
|
118
126
|
*
|
|
119
|
-
* @param {object} [opts] { cwd, scopes?, skipPolicy?, env?, managedSettingsFile? }
|
|
120
|
-
* @returns {Array<{scope, name, version, root, manifest}>}
|
|
127
|
+
* @param {object} [opts] { cwd, scopes?, skipPolicy?, includeDisabled?, env?, managedSettingsFile? }
|
|
128
|
+
* @returns {Array<{scope, name, version, root, manifest, enabled}>}
|
|
121
129
|
*/
|
|
122
130
|
export function discoverPlugins(opts = {}) {
|
|
123
131
|
// `cc agent --bare` (CC_PLUGINS=0): the plugin runtime is fully off. Every
|
|
@@ -139,6 +147,8 @@ export function discoverPlugins(opts = {}) {
|
|
|
139
147
|
if (!dirExists(root, opts.strictIo === true)) continue;
|
|
140
148
|
for (const encoded of listDirs(root, opts.strictIo === true)) {
|
|
141
149
|
const nameDir = path.join(root, encoded);
|
|
150
|
+
const enabled = !_deps.existsSync(path.join(nameDir, DISABLED_FILENAME));
|
|
151
|
+
if (!enabled && opts.includeDisabled !== true) continue;
|
|
142
152
|
const version = activeVersionForDir(nameDir, opts.strictIo === true);
|
|
143
153
|
if (!version) continue;
|
|
144
154
|
const versionDir = path.join(nameDir, version);
|
|
@@ -158,6 +168,7 @@ export function discoverPlugins(opts = {}) {
|
|
|
158
168
|
version: manifest.metadata?.version || version,
|
|
159
169
|
root: versionDir,
|
|
160
170
|
manifest,
|
|
171
|
+
enabled,
|
|
161
172
|
});
|
|
162
173
|
}
|
|
163
174
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract a secret-free plugin identity from a tool result. Plugin bins expose
|
|
3
|
+
* an explicit `plugin_bin` record; extension-tier tools may expose a
|
|
4
|
+
* `toolAttribution.source` in the stable `plugin:<id>` / `plugin/<id>` form.
|
|
5
|
+
*/
|
|
6
|
+
export function extractPluginUsageAttribution(result) {
|
|
7
|
+
const pluginBin =
|
|
8
|
+
result?.plugin_bin && typeof result.plugin_bin === "object"
|
|
9
|
+
? result.plugin_bin
|
|
10
|
+
: null;
|
|
11
|
+
if (pluginBin?.plugin) {
|
|
12
|
+
const plugin = boundedIdentity(pluginBin.plugin, 256);
|
|
13
|
+
if (!plugin) return {};
|
|
14
|
+
return {
|
|
15
|
+
plugin,
|
|
16
|
+
pluginVersion: pluginBin.version
|
|
17
|
+
? boundedIdentity(pluginBin.version, 128) || undefined
|
|
18
|
+
: undefined,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
const attribution =
|
|
22
|
+
result?.toolAttribution && typeof result.toolAttribution === "object"
|
|
23
|
+
? result.toolAttribution
|
|
24
|
+
: null;
|
|
25
|
+
const source =
|
|
26
|
+
typeof attribution?.source === "string" ? attribution.source : "";
|
|
27
|
+
const match = source.match(/^plugin(?::|\/)(.+)$/i);
|
|
28
|
+
const plugin = match ? boundedIdentity(match[1], 256) : null;
|
|
29
|
+
return plugin
|
|
30
|
+
? {
|
|
31
|
+
plugin,
|
|
32
|
+
pluginVersion: attribution.version
|
|
33
|
+
? boundedIdentity(attribution.version, 128) || undefined
|
|
34
|
+
: undefined,
|
|
35
|
+
}
|
|
36
|
+
: {};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function boundedIdentity(value, max) {
|
|
40
|
+
const clean = String(value ?? "")
|
|
41
|
+
.replace(/\p{Cc}/gu, "")
|
|
42
|
+
.trim();
|
|
43
|
+
return clean ? clean.slice(0, max) : null;
|
|
44
|
+
}
|