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
package/src/commands/plugin.js
CHANGED
|
@@ -20,10 +20,8 @@ import {
|
|
|
20
20
|
removePlugin,
|
|
21
21
|
updatePlugin,
|
|
22
22
|
getPluginSettings,
|
|
23
|
-
setPluginSetting,
|
|
24
23
|
searchRegistry,
|
|
25
24
|
listRegistry,
|
|
26
|
-
registerInMarketplace,
|
|
27
25
|
getPluginSummary,
|
|
28
26
|
installPluginSkills,
|
|
29
27
|
removePluginSkills,
|
|
@@ -404,8 +402,28 @@ export function registerPluginCommand(program) {
|
|
|
404
402
|
.command("enable")
|
|
405
403
|
.description("Enable a plugin")
|
|
406
404
|
.argument("<name>", "Plugin name")
|
|
407
|
-
.
|
|
405
|
+
.option(
|
|
406
|
+
"--scope <scope>",
|
|
407
|
+
"Enable the unified-runtime install at this scope (user|project|local)",
|
|
408
|
+
)
|
|
409
|
+
.option("--json", "Output unified-runtime result as JSON")
|
|
410
|
+
.action(async (name, options) => {
|
|
408
411
|
try {
|
|
412
|
+
if (options.scope) {
|
|
413
|
+
const { setPluginEnabled } =
|
|
414
|
+
await import("../lib/plugin-runtime/install.js");
|
|
415
|
+
const result = setPluginEnabled(name, true, {
|
|
416
|
+
scope: options.scope,
|
|
417
|
+
cwd: process.cwd(),
|
|
418
|
+
});
|
|
419
|
+
if (options.json) console.log(JSON.stringify(result, null, 2));
|
|
420
|
+
else {
|
|
421
|
+
logger.success(
|
|
422
|
+
`Enabled ${name} (${options.scope} scope). Reload active plugin sessions to apply the change.`,
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
409
427
|
enforcePluginPolicy(
|
|
410
428
|
{ name, action: "enable" },
|
|
411
429
|
loadPluginManagedPolicy(),
|
|
@@ -436,8 +454,28 @@ export function registerPluginCommand(program) {
|
|
|
436
454
|
.command("disable")
|
|
437
455
|
.description("Disable a plugin")
|
|
438
456
|
.argument("<name>", "Plugin name")
|
|
439
|
-
.
|
|
457
|
+
.option(
|
|
458
|
+
"--scope <scope>",
|
|
459
|
+
"Disable the unified-runtime install at this scope (user|project|local)",
|
|
460
|
+
)
|
|
461
|
+
.option("--json", "Output unified-runtime result as JSON")
|
|
462
|
+
.action(async (name, options) => {
|
|
440
463
|
try {
|
|
464
|
+
if (options.scope) {
|
|
465
|
+
const { setPluginEnabled } =
|
|
466
|
+
await import("../lib/plugin-runtime/install.js");
|
|
467
|
+
const result = setPluginEnabled(name, false, {
|
|
468
|
+
scope: options.scope,
|
|
469
|
+
cwd: process.cwd(),
|
|
470
|
+
});
|
|
471
|
+
if (options.json) console.log(JSON.stringify(result, null, 2));
|
|
472
|
+
else {
|
|
473
|
+
logger.success(
|
|
474
|
+
`Disabled ${name} (${options.scope} scope). Reload active plugin sessions to apply the change.`,
|
|
475
|
+
);
|
|
476
|
+
}
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
441
479
|
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
442
480
|
if (!ctx.db) {
|
|
443
481
|
logger.error("Database not available");
|
|
@@ -860,6 +898,7 @@ export function registerPluginCommand(program) {
|
|
|
860
898
|
// plugin name) resolves to a git source the installer already handles.
|
|
861
899
|
let installSource = source;
|
|
862
900
|
let integritySha = null;
|
|
901
|
+
let sourceMetadata = null;
|
|
863
902
|
const { isRemoteSource, resolveRemoteSource } =
|
|
864
903
|
await import("../lib/plugin-runtime/remote-source.js");
|
|
865
904
|
if (options.registry || isRemoteSource(source)) {
|
|
@@ -883,6 +922,19 @@ export function registerPluginCommand(program) {
|
|
|
883
922
|
});
|
|
884
923
|
installSource = resolved.source;
|
|
885
924
|
integritySha = resolved.sha256;
|
|
925
|
+
sourceMetadata = {
|
|
926
|
+
type: "registry",
|
|
927
|
+
source: url,
|
|
928
|
+
registry: url,
|
|
929
|
+
package: name || source,
|
|
930
|
+
resolvedSource: resolved.source,
|
|
931
|
+
ref:
|
|
932
|
+
(typeof resolved.source === "string" &&
|
|
933
|
+
resolved.source.includes("#") &&
|
|
934
|
+
resolved.source.slice(resolved.source.indexOf("#") + 1)) ||
|
|
935
|
+
null,
|
|
936
|
+
offline: resolved.fromCache === true,
|
|
937
|
+
};
|
|
886
938
|
if (resolved.fromCache) {
|
|
887
939
|
logger.warn(
|
|
888
940
|
chalk.yellow(
|
|
@@ -897,13 +949,31 @@ export function registerPluginCommand(program) {
|
|
|
897
949
|
}
|
|
898
950
|
}
|
|
899
951
|
|
|
952
|
+
let managed = null;
|
|
953
|
+
try {
|
|
954
|
+
managed = loadPluginManagedPolicy();
|
|
955
|
+
} catch (err) {
|
|
956
|
+
logger.error(`Managed plugin policy is invalid: ${err.message}`);
|
|
957
|
+
process.exitCode = 1;
|
|
958
|
+
return;
|
|
959
|
+
}
|
|
960
|
+
const requiresManagedSignature =
|
|
961
|
+
managed?.requireSignedPlugins === true ||
|
|
962
|
+
managed?.requireSignedPlugins === "require";
|
|
900
963
|
const signature =
|
|
901
|
-
options.sha256 ||
|
|
964
|
+
options.sha256 ||
|
|
965
|
+
options.signature ||
|
|
966
|
+
options.publicKey ||
|
|
967
|
+
integritySha ||
|
|
968
|
+
requiresManagedSignature
|
|
902
969
|
? {
|
|
903
970
|
sha256: options.sha256 || integritySha,
|
|
904
971
|
signatureFile: options.signature,
|
|
905
972
|
publicKeyFile: options.publicKey,
|
|
906
|
-
requireSignature:
|
|
973
|
+
requireSignature:
|
|
974
|
+
Boolean(options.signature) || requiresManagedSignature,
|
|
975
|
+
trustedKeySha256: managed?.trustedPluginKeySha256 || null,
|
|
976
|
+
requireTrustedKey: requiresManagedSignature,
|
|
907
977
|
}
|
|
908
978
|
: null;
|
|
909
979
|
try {
|
|
@@ -912,6 +982,9 @@ export function registerPluginCommand(program) {
|
|
|
912
982
|
cwd: process.cwd(),
|
|
913
983
|
force: options.force === true,
|
|
914
984
|
signature,
|
|
985
|
+
sourceMetadata,
|
|
986
|
+
managedPolicy: managed,
|
|
987
|
+
policySource: options.registry || source,
|
|
915
988
|
});
|
|
916
989
|
const capNotice = await resolvePluginCapabilityNotice(
|
|
917
990
|
res.name,
|
|
@@ -1060,8 +1133,21 @@ export function registerPluginCommand(program) {
|
|
|
1060
1133
|
const trust = isPluginTrusted(r)
|
|
1061
1134
|
? chalk.green("trusted")
|
|
1062
1135
|
: chalk.yellow("untrusted");
|
|
1136
|
+
const state =
|
|
1137
|
+
r.enabled === false
|
|
1138
|
+
? chalk.yellow("disabled")
|
|
1139
|
+
: chalk.green("enabled");
|
|
1140
|
+
const signed = r.integrity?.signature?.verified
|
|
1141
|
+
? chalk.green("signed")
|
|
1142
|
+
: chalk.gray("unsigned");
|
|
1143
|
+
const policy =
|
|
1144
|
+
r.policy?.allowed === false
|
|
1145
|
+
? chalk.red("policy-blocked")
|
|
1146
|
+
: r.policy?.managed
|
|
1147
|
+
? chalk.cyan("managed")
|
|
1148
|
+
: "";
|
|
1063
1149
|
logger.log(
|
|
1064
|
-
` ${ok} ${chalk.cyan(r.name)} v${r.version} ${chalk.gray(`[${r.scope}]`)} ${trust}`,
|
|
1150
|
+
` ${ok} ${chalk.cyan(r.name)} v${r.version} ${chalk.gray(`[${r.scope}]`)} ${state} ${trust} ${signed}${policy ? ` ${policy}` : ""}`,
|
|
1065
1151
|
);
|
|
1066
1152
|
}
|
|
1067
1153
|
});
|
|
@@ -1456,22 +1542,162 @@ export function registerPluginCommand(program) {
|
|
|
1456
1542
|
plugin
|
|
1457
1543
|
.command("upgrade <source>")
|
|
1458
1544
|
.description(
|
|
1459
|
-
"Update a runtime plugin from its
|
|
1545
|
+
"Update a runtime plugin from its pinned local, git, or registry source; repoints .active",
|
|
1460
1546
|
)
|
|
1461
1547
|
.option("--scope <scope>", `Scope to update in (${SCOPES})`, "user")
|
|
1462
1548
|
.option("--force", "Reinstall even if the version is unchanged")
|
|
1549
|
+
.option("--sha256 <hex>", "Expected SHA-256 of the manifest file")
|
|
1550
|
+
.option("--signature <path>", "Detached Ed25519 signature of the manifest")
|
|
1551
|
+
.option("--public-key <path>", "Public key for signature verification")
|
|
1552
|
+
.option(
|
|
1553
|
+
"--registry <url>",
|
|
1554
|
+
"Resolve <source> as a plugin NAME in this registry URL",
|
|
1555
|
+
)
|
|
1556
|
+
.option(
|
|
1557
|
+
"--name <plugin>",
|
|
1558
|
+
"Plugin name to select from a multi-plugin registry",
|
|
1559
|
+
)
|
|
1560
|
+
.option("--token <token>", "Bearer token for a private registry")
|
|
1561
|
+
.option(
|
|
1562
|
+
"--allow-insecure-registry",
|
|
1563
|
+
"Allow a plain-HTTP registry URL (MITM risk — trusted networks only)",
|
|
1564
|
+
)
|
|
1463
1565
|
.option(
|
|
1464
1566
|
"--grant-capabilities",
|
|
1465
1567
|
"Grant any newly declared capabilities during the upgrade (no separate consent step)",
|
|
1466
1568
|
)
|
|
1569
|
+
.option("--json", "Output as JSON")
|
|
1467
1570
|
.action(async (source, options) => {
|
|
1468
1571
|
const { updatePlugin } = await import("../lib/plugin-runtime/install.js");
|
|
1572
|
+
let installSource = source;
|
|
1573
|
+
let integritySha = null;
|
|
1574
|
+
let sourceMetadata = null;
|
|
1575
|
+
const { isRemoteSource, resolveRemoteSource } =
|
|
1576
|
+
await import("../lib/plugin-runtime/remote-source.js");
|
|
1577
|
+
if (options.registry || isRemoteSource(source)) {
|
|
1578
|
+
const url = options.registry || source;
|
|
1579
|
+
const name = options.registry ? source : options.name;
|
|
1580
|
+
let config = null;
|
|
1581
|
+
try {
|
|
1582
|
+
const cm = await import("../lib/config-manager.js");
|
|
1583
|
+
config = cm.loadConfig();
|
|
1584
|
+
} catch {
|
|
1585
|
+
config = null;
|
|
1586
|
+
}
|
|
1587
|
+
try {
|
|
1588
|
+
const resolved = await resolveRemoteSource(url, {
|
|
1589
|
+
name,
|
|
1590
|
+
token: options.token,
|
|
1591
|
+
config,
|
|
1592
|
+
allowInsecure: options.allowInsecureRegistry === true,
|
|
1593
|
+
});
|
|
1594
|
+
installSource = resolved.source;
|
|
1595
|
+
integritySha = resolved.sha256;
|
|
1596
|
+
sourceMetadata = {
|
|
1597
|
+
type: "registry",
|
|
1598
|
+
source: url,
|
|
1599
|
+
registry: url,
|
|
1600
|
+
package: name || source,
|
|
1601
|
+
resolvedSource: resolved.source,
|
|
1602
|
+
ref:
|
|
1603
|
+
(typeof resolved.source === "string" &&
|
|
1604
|
+
resolved.source.includes("#") &&
|
|
1605
|
+
resolved.source.slice(resolved.source.indexOf("#") + 1)) ||
|
|
1606
|
+
null,
|
|
1607
|
+
offline: resolved.fromCache === true,
|
|
1608
|
+
};
|
|
1609
|
+
if (resolved.fromCache && !options.json) {
|
|
1610
|
+
logger.warn(
|
|
1611
|
+
chalk.yellow(
|
|
1612
|
+
" ⚠ registry unreachable — using cached copy (offline)",
|
|
1613
|
+
),
|
|
1614
|
+
);
|
|
1615
|
+
}
|
|
1616
|
+
} catch (err) {
|
|
1617
|
+
logger.error(`Registry resolution failed: ${err.message}`);
|
|
1618
|
+
process.exitCode = 1;
|
|
1619
|
+
return;
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
let managed = null;
|
|
1469
1624
|
try {
|
|
1470
|
-
|
|
1625
|
+
managed = loadPluginManagedPolicy();
|
|
1626
|
+
} catch (err) {
|
|
1627
|
+
logger.error(`Managed plugin policy is invalid: ${err.message}`);
|
|
1628
|
+
process.exitCode = 1;
|
|
1629
|
+
return;
|
|
1630
|
+
}
|
|
1631
|
+
const requiresManagedSignature =
|
|
1632
|
+
managed?.requireSignedPlugins === true ||
|
|
1633
|
+
managed?.requireSignedPlugins === "require";
|
|
1634
|
+
const signature =
|
|
1635
|
+
options.sha256 ||
|
|
1636
|
+
options.signature ||
|
|
1637
|
+
options.publicKey ||
|
|
1638
|
+
integritySha ||
|
|
1639
|
+
requiresManagedSignature
|
|
1640
|
+
? {
|
|
1641
|
+
sha256: options.sha256 || integritySha,
|
|
1642
|
+
signatureFile: options.signature,
|
|
1643
|
+
publicKeyFile: options.publicKey,
|
|
1644
|
+
requireSignature:
|
|
1645
|
+
Boolean(options.signature) || requiresManagedSignature,
|
|
1646
|
+
trustedKeySha256: managed?.trustedPluginKeySha256 || null,
|
|
1647
|
+
requireTrustedKey: requiresManagedSignature,
|
|
1648
|
+
}
|
|
1649
|
+
: null;
|
|
1650
|
+
try {
|
|
1651
|
+
const res = updatePlugin(installSource, {
|
|
1471
1652
|
scope: options.scope,
|
|
1472
1653
|
cwd: process.cwd(),
|
|
1473
1654
|
force: options.force,
|
|
1655
|
+
signature,
|
|
1656
|
+
sourceMetadata,
|
|
1657
|
+
managedPolicy: managed,
|
|
1658
|
+
policySource: options.registry || source,
|
|
1474
1659
|
});
|
|
1660
|
+
const upgradeNotice = await resolvePluginCapabilityNotice(
|
|
1661
|
+
res.name,
|
|
1662
|
+
options.scope,
|
|
1663
|
+
process.cwd(),
|
|
1664
|
+
);
|
|
1665
|
+
if (res.updated || res.reinstalled)
|
|
1666
|
+
await auditPluginInstall(
|
|
1667
|
+
"upgrade",
|
|
1668
|
+
{ ...res, scope: options.scope },
|
|
1669
|
+
installSource,
|
|
1670
|
+
upgradeNotice,
|
|
1671
|
+
);
|
|
1672
|
+
|
|
1673
|
+
if (options.json) {
|
|
1674
|
+
let capabilitiesGranted = false;
|
|
1675
|
+
if (
|
|
1676
|
+
options.grantCapabilities &&
|
|
1677
|
+
upgradeNotice &&
|
|
1678
|
+
!upgradeNotice.consented
|
|
1679
|
+
) {
|
|
1680
|
+
capabilitiesGranted = await grantInstalledPluginCapabilities(
|
|
1681
|
+
res.name,
|
|
1682
|
+
options.scope,
|
|
1683
|
+
process.cwd(),
|
|
1684
|
+
);
|
|
1685
|
+
}
|
|
1686
|
+
console.log(
|
|
1687
|
+
JSON.stringify(
|
|
1688
|
+
{
|
|
1689
|
+
...res,
|
|
1690
|
+
scope: options.scope,
|
|
1691
|
+
capabilities: upgradeNotice,
|
|
1692
|
+
capabilitiesGranted,
|
|
1693
|
+
},
|
|
1694
|
+
null,
|
|
1695
|
+
2,
|
|
1696
|
+
),
|
|
1697
|
+
);
|
|
1698
|
+
return;
|
|
1699
|
+
}
|
|
1700
|
+
|
|
1475
1701
|
if (res.updated) {
|
|
1476
1702
|
logger.success(
|
|
1477
1703
|
`Updated ${res.name}: ${res.previousVersion ? `v${res.previousVersion} → ` : ""}v${res.version} (${options.scope} scope)`,
|
|
@@ -1489,20 +1715,6 @@ export function registerPluginCommand(program) {
|
|
|
1489
1715
|
// upgrade that adds a capability shows a `⚠ capability consent required`
|
|
1490
1716
|
// notice diffed against the prior consent, then either auto-grants
|
|
1491
1717
|
// (--grant-capabilities) or blocks interactively to re-consent now.
|
|
1492
|
-
const upgradeNotice = await resolvePluginCapabilityNotice(
|
|
1493
|
-
res.name,
|
|
1494
|
-
options.scope,
|
|
1495
|
-
process.cwd(),
|
|
1496
|
-
);
|
|
1497
|
-
// Only a version that actually landed on disk is an install; an
|
|
1498
|
-
// already-up-to-date no-op fetched nothing new to run.
|
|
1499
|
-
if (res.updated || res.reinstalled)
|
|
1500
|
-
await auditPluginInstall(
|
|
1501
|
-
"upgrade",
|
|
1502
|
-
{ ...res, scope: options.scope },
|
|
1503
|
-
source,
|
|
1504
|
-
upgradeNotice,
|
|
1505
|
-
);
|
|
1506
1718
|
await applyCapabilityConsentGate(
|
|
1507
1719
|
res.name,
|
|
1508
1720
|
options.scope,
|
package/src/commands/session.js
CHANGED
|
@@ -1333,6 +1333,7 @@ export function registerSessionCommand(program) {
|
|
|
1333
1333
|
"subagent",
|
|
1334
1334
|
"tool",
|
|
1335
1335
|
"mcp",
|
|
1336
|
+
"plugin",
|
|
1336
1337
|
"model",
|
|
1337
1338
|
];
|
|
1338
1339
|
|
|
@@ -1403,6 +1404,18 @@ export function registerSessionCommand(program) {
|
|
|
1403
1404
|
);
|
|
1404
1405
|
return;
|
|
1405
1406
|
}
|
|
1407
|
+
case "plugin": {
|
|
1408
|
+
const rows = a.tools?.byPlugin || [];
|
|
1409
|
+
if (rows.length === 0) return empty("plugin-attributed tool calls");
|
|
1410
|
+
for (const r of rows)
|
|
1411
|
+
toolRow(`${r.plugin}${r.version ? `@${r.version}` : ""}`, r);
|
|
1412
|
+
logger.log(
|
|
1413
|
+
chalk.gray(
|
|
1414
|
+
" turnTokens = tokens of turns that used the plugin (approximation; do not sum across rows)",
|
|
1415
|
+
),
|
|
1416
|
+
);
|
|
1417
|
+
return;
|
|
1418
|
+
}
|
|
1406
1419
|
default:
|
|
1407
1420
|
break;
|
|
1408
1421
|
}
|
package/src/data/changelog.json
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"source": "CHANGELOG.md",
|
|
3
3
|
"releases": [
|
|
4
|
+
{
|
|
5
|
+
"productVersion": null,
|
|
6
|
+
"cliVersion": "0.162.183",
|
|
7
|
+
"cliVersions": ["0.4.74", "0.37.35", "0.162.182", "0.162.183"],
|
|
8
|
+
"date": "2026-07-27",
|
|
9
|
+
"title": "",
|
|
10
|
+
"sections": [
|
|
11
|
+
{
|
|
12
|
+
"heading": "Added — cc CLI 0.162.183 + IDE quality, plugin, and worktree governance",
|
|
13
|
+
"body": "> `chainlesschain` **0.162.182 → 0.162.183**, VS Code\n> **0.37.34 → 0.37.35**, and JetBrains **0.4.73 → 0.4.74** (2026-07-27).\n> `@chainlesschain/personal-data-hub` remains **0.4.57** and\n> `@chainlesschain/agent-sdk` remains **0.1.7**.\n\n- **IDE-native quality context**: both IDE bridges negotiate bounded\n `cc-ide-quality/v1` test-result, coverage, and debugger snapshots with\n Context v2 freshness metadata; VS Code notebook execution now carries its\n real notebook context.\n- **Installation Doctor depth**: VS Code and JetBrains report Node/Java\n availability plus managed-CLI and plugin-registry offline recovery state,\n without probing executables from an untrusted workspace directory.\n- **Plugin lifecycle and supply-chain UI**: scoped enable/disable, source-aware\n upgrades, live-session reload, signature/SBOM summaries, managed-policy\n provenance, and sanitized registry/Git/local source metadata stay governed\n by the CLI runtime.\n- **Plugin usage attribution**: compact transcripts and usage reports now\n attribute plugin-bin and plugin-provided MCP calls by plugin/version without\n persisting tool arguments.\n- **Supervised worktree tasks**: IDE-created isolated tasks run as background\n worktree agents and display canonical lifecycle, owner/session, permission\n mode, resource budget, and bounded side-effect counts. Team and batch rows\n remain explicitly unmanaged until they expose equivalent durable state.\n- **Release validation**: publication remains gated on the exact release\n commit passing CLI CI, CLI Strict Sandbox, background reconnect E2E, packaged\n VSIX Extension Host gates, JetBrains unit/build/Remote Robot gates, and\n public marketplace readback."
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
4
17
|
{
|
|
5
18
|
"productVersion": null,
|
|
6
19
|
"cliVersion": "0.162.182",
|
|
@@ -164,20 +164,22 @@ export function appendToolCall(sessionId, toolName, args) {
|
|
|
164
164
|
|
|
165
165
|
/**
|
|
166
166
|
* Compact tool-call record for usage attribution (用量归因): tool name +
|
|
167
|
-
* error flag (+
|
|
167
|
+
* error flag (+ optional skill and plugin/version hints) — deliberately NOT
|
|
168
168
|
* the args, which can carry whole file bodies (write_file content) and would
|
|
169
169
|
* bloat the transcript. Written at tool-result time by the agent drivers so
|
|
170
|
-
* `cc session usage --by tool|mcp` and `cc insights` can aggregate tool
|
|
171
|
-
* for any persisted session.
|
|
170
|
+
* `cc session usage --by tool|mcp|plugin` and `cc insights` can aggregate tool
|
|
171
|
+
* use for any persisted session.
|
|
172
172
|
*/
|
|
173
173
|
export function appendToolCallCompact(
|
|
174
174
|
sessionId,
|
|
175
|
-
{ tool, isError, skill } = {},
|
|
175
|
+
{ tool, isError, skill, plugin, pluginVersion } = {},
|
|
176
176
|
) {
|
|
177
177
|
appendEvent(sessionId, "tool_call", {
|
|
178
178
|
tool: tool || "?",
|
|
179
179
|
is_error: Boolean(isError),
|
|
180
180
|
...(skill ? { skill: String(skill) } : {}),
|
|
181
|
+
...(plugin ? { plugin: String(plugin) } : {}),
|
|
182
|
+
...(pluginVersion ? { plugin_version: String(pluginVersion) } : {}),
|
|
181
183
|
});
|
|
182
184
|
}
|
|
183
185
|
|
|
@@ -51,6 +51,10 @@ export class TeamRunner {
|
|
|
51
51
|
this._executions = 0;
|
|
52
52
|
this._inFlight = 0;
|
|
53
53
|
this._maxInFlight = 0;
|
|
54
|
+
// Keys executing in this runner process. An event-loop stall may let a
|
|
55
|
+
// short lease expire before its heartbeat callback runs; peer loops in the
|
|
56
|
+
// same process must not steal and double-run that still-active task.
|
|
57
|
+
this._activeKeys = new Set();
|
|
54
58
|
this._members = new Map(); // holder → lifecycle record
|
|
55
59
|
this._budgetStopped = false;
|
|
56
60
|
}
|
|
@@ -208,6 +212,7 @@ export class TeamRunner {
|
|
|
208
212
|
let best = null;
|
|
209
213
|
let bestScore = Infinity;
|
|
210
214
|
for (const key of claimable) {
|
|
215
|
+
if (this._activeKeys.has(key)) continue;
|
|
211
216
|
const t = this.registry.getTask(key);
|
|
212
217
|
const score = rank[t?.priority] ?? 1;
|
|
213
218
|
if (score < bestScore) {
|
|
@@ -222,10 +227,22 @@ export class TeamRunner {
|
|
|
222
227
|
const task = this.registry.getTask(key);
|
|
223
228
|
this._executions++;
|
|
224
229
|
this._inFlight++;
|
|
230
|
+
this._activeKeys.add(key);
|
|
225
231
|
this._maxInFlight = Math.max(this._maxInFlight, this._inFlight);
|
|
226
232
|
this._setState(holder, "running", { key });
|
|
227
233
|
this._emit("task:claimed", { key, holder, attempts: task.attempts });
|
|
228
|
-
const renew = () =>
|
|
234
|
+
const renew = () => {
|
|
235
|
+
const result = this.registry.renew(key, {
|
|
236
|
+
holder,
|
|
237
|
+
ttlMs: this.ttlMs,
|
|
238
|
+
});
|
|
239
|
+
// A delayed timer may wake just after expiry. Reacquire is safe and
|
|
240
|
+
// optimistic: it succeeds only if no external runner has taken the
|
|
241
|
+
// lease; a real takeover remains authoritative and stops the heartbeat.
|
|
242
|
+
return !result?.ok && result?.reason === "not_holder_or_expired"
|
|
243
|
+
? this.registry.acquire(key, { holder, ttlMs: this.ttlMs })
|
|
244
|
+
: result;
|
|
245
|
+
};
|
|
229
246
|
// Heartbeat: the built-in executors (shell / agent / worktree) never call
|
|
230
247
|
// `renew` themselves, so before this ANY task outliving the lease TTL was
|
|
231
248
|
// indistinguishable from a crash — a peer could steal it and the SAME task
|
|
@@ -338,6 +355,7 @@ export class TeamRunner {
|
|
|
338
355
|
});
|
|
339
356
|
} finally {
|
|
340
357
|
clearInterval(heartbeat);
|
|
358
|
+
this._activeKeys.delete(key);
|
|
341
359
|
this._inFlight--;
|
|
342
360
|
}
|
|
343
361
|
}
|
|
@@ -762,6 +762,47 @@ export function normalizeBackgroundWorktree(worktree, cwd) {
|
|
|
762
762
|
return normalized;
|
|
763
763
|
}
|
|
764
764
|
|
|
765
|
+
/**
|
|
766
|
+
* Persist only the bounded, secret-free governance envelope needed by IDE task
|
|
767
|
+
* rows. The supervisor owns `owner`; callers cannot forge it. Prompt text,
|
|
768
|
+
* argv, credentials and tool arguments are deliberately excluded.
|
|
769
|
+
*/
|
|
770
|
+
export function normalizeBackgroundGovernance(
|
|
771
|
+
governance,
|
|
772
|
+
{ id, sessionId } = {},
|
|
773
|
+
) {
|
|
774
|
+
const source = governance && typeof governance === "object" ? governance : {};
|
|
775
|
+
const budget =
|
|
776
|
+
source.resourceBudget && typeof source.resourceBudget === "object"
|
|
777
|
+
? source.resourceBudget
|
|
778
|
+
: {};
|
|
779
|
+
const positive = (value) => {
|
|
780
|
+
const n = Number(value);
|
|
781
|
+
return Number.isFinite(n) && n > 0 ? n : null;
|
|
782
|
+
};
|
|
783
|
+
const permissionMode = new Set([
|
|
784
|
+
"manual",
|
|
785
|
+
"auto",
|
|
786
|
+
"dontAsk",
|
|
787
|
+
"default",
|
|
788
|
+
"plan",
|
|
789
|
+
"acceptEdits",
|
|
790
|
+
"bypassPermissions",
|
|
791
|
+
]).has(source.permissionMode)
|
|
792
|
+
? source.permissionMode
|
|
793
|
+
: "default";
|
|
794
|
+
return {
|
|
795
|
+
version: 1,
|
|
796
|
+
owner: `background:${String(id || "").slice(0, 160)}`,
|
|
797
|
+
sessionId: sessionId ? String(sessionId).slice(0, 256) : null,
|
|
798
|
+
permissionMode,
|
|
799
|
+
resourceBudget: {
|
|
800
|
+
maxTurns: positive(budget.maxTurns),
|
|
801
|
+
maxCostUsd: positive(budget.maxCostUsd),
|
|
802
|
+
},
|
|
803
|
+
};
|
|
804
|
+
}
|
|
805
|
+
|
|
765
806
|
function persistedWorktree(state) {
|
|
766
807
|
if (!state?.worktreePath) return null;
|
|
767
808
|
return {
|
|
@@ -817,6 +858,7 @@ export function resumeBackgroundAgent(id, prompt, options = {}) {
|
|
|
817
858
|
cliEntry: options.cliEntry,
|
|
818
859
|
followUpArgv: ["agent", "--session", state.sessionId],
|
|
819
860
|
worktree,
|
|
861
|
+
governance: state.governance,
|
|
820
862
|
});
|
|
821
863
|
}
|
|
822
864
|
|
|
@@ -855,10 +897,15 @@ export function launchBackgroundAgent({
|
|
|
855
897
|
cliEntry,
|
|
856
898
|
followUpArgv,
|
|
857
899
|
worktree,
|
|
900
|
+
governance,
|
|
858
901
|
}) {
|
|
859
902
|
assertUsableCwd(cwd);
|
|
860
903
|
const worktreeState = normalizeBackgroundWorktree(worktree, cwd);
|
|
861
904
|
const id = createBackgroundAgentId();
|
|
905
|
+
const governanceState = normalizeBackgroundGovernance(governance, {
|
|
906
|
+
id,
|
|
907
|
+
sessionId,
|
|
908
|
+
});
|
|
862
909
|
const dir = backgroundAgentsDir();
|
|
863
910
|
const jobFile = join(dir, `${id}.job.${process.pid}.json`);
|
|
864
911
|
const worker = fileURLToPath(
|
|
@@ -873,6 +920,7 @@ export function launchBackgroundAgent({
|
|
|
873
920
|
cliEntry: cliEntry || process.argv[1],
|
|
874
921
|
logFile: logPath(id),
|
|
875
922
|
...(worktreeState || {}),
|
|
923
|
+
governance: governanceState,
|
|
876
924
|
// Present = interactive attach can start follow-up turns; absent = the
|
|
877
925
|
// transport rejects prompts (log-only session).
|
|
878
926
|
...(Array.isArray(followUpArgv) ? { followUpArgv } : {}),
|
|
@@ -897,6 +945,7 @@ export function launchBackgroundAgent({
|
|
|
897
945
|
exitCode: null,
|
|
898
946
|
logFile: job.logFile,
|
|
899
947
|
...(worktreeState || {}),
|
|
948
|
+
governance: governanceState,
|
|
900
949
|
};
|
|
901
950
|
writeBackgroundAgentState(state);
|
|
902
951
|
let child;
|