chainlesschain 0.162.181 → 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 +2 -1
- package/scripts/build-windows-sandbox-helper.ps1 +163 -0
- package/src/assets/web-panel/assets/{AIOps-cq0dwbnf.js → AIOps-BapS7lz4.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CvcgGl3w.js → ActionButton-CXYdXEUI.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-hM2-jFqg.js → Analytics-CKR5Lexn.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-B9_Gsd_g.js → AppLayout-DATVUOXB.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-B7bu52Og.js → Artifacts-vb_0ZlV1.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-DThfDgqB.js → Audit-BI1l9GWt.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-DjlFiD4v.js → BackgroundAgents-BFXbaUEf.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-CK9xJKnG.js → Backup-DEYBJJ6H.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-DEiSU8K8.js → BaseInput-COdzeO0M.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CpT96czj.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-C1GfDnO0.js → Checkbox-BezEa4tm.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-3DAKgiLx.js → Codegen-CNEL0Ife.js} +1 -1
- package/src/assets/web-panel/assets/{Col-74cOwZU1.js → Col-Bf2Y2Bn1.js} +1 -1
- package/src/assets/web-panel/assets/{Community-tn9Kkz9j.js → Community-BfUlu4Hc.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BcoXH7m4.js → Compact-BN4xWP9e.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-DIPGUBgi.js → Compliance-Bt6BKmEP.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-doD5_91c.js → Cowork-DKLp8YxO.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-C-IDvubz.js → Cron-o7Hhw6ky.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CdcCoBdj.js → Crosschain-DaNXWJIw.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DdH5aMMA.js → DID-B-Qa2mha.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-DHLA4mm0.js → Dashboard-CMX0Qnxw.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-dEeCt7Md.js → Dropdown-BLuLyRu_.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-BMaecFv9.js → EmailListRenderer-CFBAeMij.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-DUaUukTN.js → FamilyGuardDashboard-DWzXQ67V.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-CMBE0_rp.js → Federation-DB1QSLgr.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-PG-JDbXq.js → FormItemContext-C-OKCToP.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-Bcb0p88m.js → GenericCardRenderer-DMJFtFZf.js} +1 -1
- package/src/assets/web-panel/assets/{Git-Bgv15myB.js → Git-DsGSujOV.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DB8YTArI.js → Governance-B0iS9NEW.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BQMwCWaS.js → Inference-CH004H7c.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-B1_ZziiB.js → KnowledgeGraph-Q9MTQ83c.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-DovEEnt_.js → Logs-B_fyjZK9.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-D201OL4T.js → MarkdownRenderer-C0o4FtpD.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-BlCXSpyB.js → Marketplace-BIStF9d1.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CsCR09Wj.js → McpTools-pGfal768.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-CBVRLKno.js → Memory-xbNqpIqB.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-C9OIafgA.js → MobileBridge-B5EQGrIK.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-VTc3gT1y.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-vE-HdvLj.js → Mtc-a_rmfxJH.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-CPLaekCd.js → MtcAudit-BmKuofUr.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-C_UP9C2o.js → Multisig-BQbJ-CAN.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-2nODJcU1.js → NLProgramming-JtPJKX25.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-BhE-SJGu.js → Notes-ZFKznTSG.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-D21q7BNU.js → NotificationSettings-B6aHRBBR.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-0b62GYOD.js → OrderTableRenderer-DdcsOqEz.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-CEqmw_sb.js → Organization-BFDTAUgS.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-MW-gMDO_.js → Overflow-0FoTfbWH.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CY0hjI_G.js → P2P-CWd90etw.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-BbWh7Man.js → PdhVaultBrowser-DtCGC-W-.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-ChqEA_4Q.js → Permissions-CvQ7nr7T.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-B3YrbYfD.js → PersonalDataHub-rdNPcR-Z.js} +5 -5
- package/src/assets/web-panel/assets/{Pipeline-B8WBhhlW.js → Pipeline-CmrfiNOs.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-Cmb0PXNx.js → Privacy-D7ep1h_t.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-hF6zW3Nz.js → ProjectInit-C0xKINHS.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BFSVfpW0.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-B8yux8Dx.js → Providers-Cb7JCTPL.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-N76cQluO.js → QrScannerModal-BDMehcXC.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-ClvZ0KYR.js → QuickAsk-BF6_1nvx.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-B-GfgBpT.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-DJIZzQeG.js → Reputation-CsWHLEcj.js} +1 -1
- package/src/assets/web-panel/assets/{Row-COzxu_bb.js → Row-D6srnWhm.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CoYsJQuE.js → RssFeed-Xhr-KyVd.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DC77Mq9S.js → Search-vIbIJvwL.js} +1 -1
- package/src/assets/web-panel/assets/{Security-Loy2EdMO.js → Security-Bzi5Aiko.js} +4 -4
- package/src/assets/web-panel/assets/{Services-GUD07Eu0.js → Services-BHtVX52P.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DWzkptYU.js → Skeleton-C0R8B2jf.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CEDn1r-Z.js → Skills-DtT6rWOX.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-ub_k4pXh.js → Sla-0B37mxVU.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-D7HLX9CA.js → SpeechSettings-0V2jE1Bs.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DbwOvl6m.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-BNVeIhud.js → Templates-BKoHztGT.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-PS9AzhXU.js → Tenant--17nwVNZ.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-Cgb4eLB_.js → Terminal-Dnkos7vW.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-CrmXMOkg.js → TimelineRenderer-C5jx4AE3.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DD-VDHw1.js → Tokens-DYJKYa9t.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BsoN_n-n.js → Trigger-DChpWiQ9.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-n8LmN4ZV.js → Trust-DfWG52EA.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-C9_7MImA.js → UkeySign-CMugYcyA.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-DyBteNgn.js → VideoEditing-BOSmrHAd.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BS5ixeXI.js → Wallet-D5g3k3Sa.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-spc4UImU.js → WebAuthn-D-7u4Mkc.js} +3 -3
- package/src/assets/web-panel/assets/{WorkflowEditor-D7iVvaBO.js → WorkflowEditor-CFzZMSUJ.js} +1 -1
- package/src/assets/web-panel/assets/{chat-6CmBkHrL.js → chat-VbR6l6mc.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BGoCLkxI.js → colors-BSZn8EDS.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-fYZBetMO.js → compact-item-y74obMEq.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BeM-1UVj.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-CE7ZuEnV.js → hasIn-D_INJQT_.js} +1 -1
- package/src/assets/web-panel/assets/{index-ukg99D1V.js → index-4PIeTM--.js} +1 -1
- package/src/assets/web-panel/assets/{index-B2U-ObMq.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-CRLjEP1H.js → index-9PIVuXqo.js} +1 -1
- package/src/assets/web-panel/assets/{index-BfPL-m46.js → index-B7SrC-On.js} +1 -1
- package/src/assets/web-panel/assets/{index--lap6cf7.js → index-BJi3UqBt.js} +1 -1
- package/src/assets/web-panel/assets/{index-B3CDgvNW.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-De0quFDw.js → index-Bfw2hf2s.js} +1 -1
- package/src/assets/web-panel/assets/{index-BunaQCa0.js → index-BjcWKg1S.js} +1 -1
- package/src/assets/web-panel/assets/{index-BsMfoaeo.js → index-BnSfnSMP.js} +1 -1
- package/src/assets/web-panel/assets/{index-C0v6YKKO.js → index-Bnua8IX3.js} +1 -1
- package/src/assets/web-panel/assets/{index-C4SJVjs4.js → index-C-ZCaUJc.js} +1 -1
- package/src/assets/web-panel/assets/{index-BNZDILcO.js → index-C2NyllnW.js} +1 -1
- package/src/assets/web-panel/assets/{index-YjcumOZ4.js → index-C327pLbw.js} +1 -1
- package/src/assets/web-panel/assets/{index-CRnUE8Cb.js → index-CMHqs3Jb.js} +1 -1
- package/src/assets/web-panel/assets/{index-CIpVrf5P.js → index-CfLJ42kv.js} +1 -1
- package/src/assets/web-panel/assets/{index-BEVm0lCS.js → index-Cr3uuz0C.js} +3 -3
- package/src/assets/web-panel/assets/{index-Dw1PyYPm.js → index-CsovTpx9.js} +1 -1
- package/src/assets/web-panel/assets/{index-lJBjB1QX.js → index-CzE53HiB.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpIGIB85.js → index-DBkzrpiL.js} +1 -1
- package/src/assets/web-panel/assets/{index-DoXk5KJ8.js → index-DNMxIsDg.js} +1 -1
- package/src/assets/web-panel/assets/{index-DsvfrESp.js → index-DUU2606o.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cip8emOQ.js → index-DdyjrCAu.js} +1 -1
- package/src/assets/web-panel/assets/{index-ATcSr_2O.js → index-DkH1JvEt.js} +1 -1
- package/src/assets/web-panel/assets/{index-BV551878.js → index-Dlxh9D8D.js} +1 -1
- package/src/assets/web-panel/assets/{index-BU_2qiDk.js → index-DuIkfnTF.js} +1 -1
- package/src/assets/web-panel/assets/{index-zb7rVOhV.js → index-DwHSZLXg.js} +1 -1
- package/src/assets/web-panel/assets/{index-MtOuq2i6.js → index-E_v1ZCTP.js} +1 -1
- package/src/assets/web-panel/assets/{index-B8BsdNV_.js → index-FQBsuExX.js} +1 -1
- package/src/assets/web-panel/assets/{index-WUrJ6S1j.js → index-GA80ir_u.js} +1 -1
- package/src/assets/web-panel/assets/{index-RMZ8a7Yt.js → index-IZAWt0H8.js} +1 -1
- package/src/assets/web-panel/assets/{index-D1r9tT3J.js → index-Iw0FfqUz.js} +1 -1
- package/src/assets/web-panel/assets/{index-BowH1eLQ.js → index-KF9Zmqln.js} +1 -1
- package/src/assets/web-panel/assets/{index-Puq6Luf1.js → index-abmn_8Yz.js} +1 -1
- package/src/assets/web-panel/assets/{index-QIpnpZgz.js → index-gINyI1rh.js} +1 -1
- package/src/assets/web-panel/assets/{index-C9Y3k0HI.js → index-jYaogFE8.js} +1 -1
- package/src/assets/web-panel/assets/{index-B4wiTEOM.js → index-nSn2-C4N.js} +1 -1
- package/src/assets/web-panel/assets/{index-DT3zPSVX.js → index-qMA4GYdQ.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-CYHMs1ag.js → initDefaultProps-DI0Zaf8-.js} +1 -1
- package/src/assets/web-panel/assets/{motion-DDB2Ffk5.js → motion-BZDKSy3Z.js} +1 -1
- package/src/assets/web-panel/assets/{move-Bg3cD-dX.js → move-DsIW01Vp.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-B5nedjTS.js → mtc-parser-CohkDhsf.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BHyuUILu.js → omit-DpiN5rzg.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-C9YQnEN9.js → pickAttrs-qbuqni3y.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-DBUFYUe7.js → placementArrow-mBky6714.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-nBs2Obnk.js → responsiveObserve-Bas3eQ2K.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DkCEaXNU.js → slide-CBx_SKoK.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-aqE1Wi6U.js → statusUtils-BlYguJSV.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-CN5bhfHB.js → styleChecker-BCYQmRGv.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-B_oX_kvJ.js → useFlexGapSupport-Dp5dybLM.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-rCuXHeme.js → useFs-DHAMBgA2.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-DZR9Abyd.js → usePersonalDataHub-W6jsSw76.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-ConCYQlX.js → vnode-BkI6aayc.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-CUdDxG5M.js → zoom-C_IMGueq.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agenda.js +115 -3
- package/src/commands/agent.js +15 -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 +26 -0
- package/src/gateways/terminal/PtyManager.js +45 -4
- package/src/gateways/ws/ws-server.js +10 -1
- package/src/harness/background-task-manager.js +70 -2
- package/src/harness/jsonl-session-store.js +6 -4
- package/src/harness/worktree-isolator.js +14 -3
- package/src/lib/agent-core.js +1 -0
- package/src/lib/agent-schedule-store.js +45 -22
- package/src/lib/agent-team/team-runner.js +19 -1
- package/src/lib/background-agent-supervisor.js +49 -0
- package/src/lib/hook-runner.js +6 -2
- package/src/lib/packer/pkg-config-generator.js +3 -1
- package/src/lib/plugin-runtime/bin.js +1148 -70
- package/src/lib/plugin-runtime/install.js +226 -7
- package/src/lib/plugin-runtime/manifest.js +68 -12
- package/src/lib/plugin-runtime/scopes.js +33 -12
- package/src/lib/plugin-usage-attribution.js +44 -0
- package/src/lib/process-execution-broker/index.js +626 -48
- package/src/lib/process-execution-broker/platform-sandbox.js +4971 -266
- package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
- package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
- package/src/lib/process-execution-broker/windows-sandbox.cs +3856 -0
- package/src/lib/repl-bang-memorize.js +67 -10
- package/src/lib/session-usage.js +77 -0
- package/src/lib/slash-commands.js +27 -4
- package/src/repl/agent-repl.js +10 -9
- package/src/runtime/agent-core.js +376 -52
- package/src/runtime/agent-runtime.js +13 -1
- package/src/runtime/headless-runner.js +13 -4
- package/src/runtime/headless-stream.js +20 -1
- package/src/runtime/mcp-config.js +15 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-BKPPNmZI.js +0 -1
- package/src/assets/web-panel/assets/MobileProjects-D_zoJ8Xs.js +0 -1
- package/src/assets/web-panel/assets/Projects-DAWkVFkc.js +0 -1
- package/src/assets/web-panel/assets/RemoteSession-mlglCdQi.js +0 -5
- package/src/assets/web-panel/assets/Tasks-CBQzoAu5.js +0 -1
- package/src/assets/web-panel/assets/devWarning-BzPwHnw8.js +0 -1
- package/src/assets/web-panel/assets/index-DacrAdc-.js +0 -1
- package/src/assets/web-panel/assets/index-EHzNJozo.js +0 -1
- package/src/lib/process-execution-broker/windows-sandbox.ps1 +0 -999
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { existsSync, mkdirSync, appendFileSync, readFileSync } from "node:fs";
|
|
12
|
-
import { join } from "node:path";
|
|
12
|
+
import { join, resolve } from "node:path";
|
|
13
13
|
import { createHash } from "node:crypto";
|
|
14
14
|
import { EventEmitter } from "node:events";
|
|
15
15
|
import { getHomeDir } from "../lib/paths.js";
|
|
@@ -42,9 +42,55 @@ const RECOVERABLE_TASK_STATUSES = new Set([
|
|
|
42
42
|
TaskStatus.RUNNING,
|
|
43
43
|
]);
|
|
44
44
|
|
|
45
|
+
function validatePinnedSandboxPolicy(policy) {
|
|
46
|
+
if (policy == null) return null;
|
|
47
|
+
if (
|
|
48
|
+
typeof policy !== "object" ||
|
|
49
|
+
Array.isArray(policy) ||
|
|
50
|
+
typeof policy.then === "function" ||
|
|
51
|
+
!Array.isArray(policy.requiredBoundaries) ||
|
|
52
|
+
policy.requiredBoundaries.length === 0 ||
|
|
53
|
+
policy.requiredBoundaries.some(
|
|
54
|
+
(boundary) => typeof boundary !== "string" || boundary.length === 0,
|
|
55
|
+
) ||
|
|
56
|
+
!Object.isFrozen(policy) ||
|
|
57
|
+
!Object.isFrozen(policy.requiredBoundaries)
|
|
58
|
+
) {
|
|
59
|
+
const error = new TypeError("invalid_background_task_sandbox_policy");
|
|
60
|
+
error.code = "ERR_BACKGROUND_TASK_SANDBOX_POLICY_INVALID";
|
|
61
|
+
error.sandboxReason = "invalid_background_task_sandbox_policy";
|
|
62
|
+
error.sandboxFailClosed = true;
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
return policy;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function createUnsupportedSandboxError(sandboxPolicy) {
|
|
69
|
+
const requiredBoundaries = [...sandboxPolicy.requiredBoundaries];
|
|
70
|
+
const error = new Error(
|
|
71
|
+
`Background tasks cannot run without their required sandbox boundaries: ${requiredBoundaries.join(", ")}`,
|
|
72
|
+
);
|
|
73
|
+
error.code = "ERR_BACKGROUND_TASK_SANDBOX_UNSUPPORTED";
|
|
74
|
+
error.sandboxReason = "background_execution_unsupported";
|
|
75
|
+
error.sandboxFailClosed = true;
|
|
76
|
+
error.requiredBoundaries = requiredBoundaries;
|
|
77
|
+
error.actualGuarantees = [];
|
|
78
|
+
error.missingBoundaries = [...requiredBoundaries];
|
|
79
|
+
error.sandboxBackend = null;
|
|
80
|
+
error.sandboxCandidateBackend = null;
|
|
81
|
+
return error;
|
|
82
|
+
}
|
|
83
|
+
|
|
45
84
|
export class BackgroundTaskManager extends EventEmitter {
|
|
46
85
|
constructor(options = {}) {
|
|
47
86
|
super();
|
|
87
|
+
const resolveSandboxPolicy = options.resolveSandboxPolicy ?? null;
|
|
88
|
+
if (
|
|
89
|
+
resolveSandboxPolicy !== null &&
|
|
90
|
+
typeof resolveSandboxPolicy !== "function"
|
|
91
|
+
) {
|
|
92
|
+
throw new TypeError("resolveSandboxPolicy must be a function or null");
|
|
93
|
+
}
|
|
48
94
|
this.maxConcurrent = options.maxConcurrent || 3;
|
|
49
95
|
this.heartbeatTimeout = options.heartbeatTimeout || 60000;
|
|
50
96
|
this.historyLimit = options.historyLimit || 50;
|
|
@@ -54,6 +100,10 @@ export class BackgroundTaskManager extends EventEmitter {
|
|
|
54
100
|
`${process.pid}@${process.platform}`;
|
|
55
101
|
this.recoveryPolicy = options.recoveryPolicy || "claim-stale";
|
|
56
102
|
this.staleNodeTimeout = options.staleNodeTimeout || 5 * 60 * 1000;
|
|
103
|
+
this._policyCwd = resolveSandboxPolicy
|
|
104
|
+
? resolve(options.policyCwd || process.cwd())
|
|
105
|
+
: null;
|
|
106
|
+
this._resolveSandboxPolicy = resolveSandboxPolicy;
|
|
57
107
|
this.tasks = new Map();
|
|
58
108
|
this.processes = new Map();
|
|
59
109
|
this._checkInterval = null;
|
|
@@ -72,12 +122,15 @@ export class BackgroundTaskManager extends EventEmitter {
|
|
|
72
122
|
);
|
|
73
123
|
}
|
|
74
124
|
|
|
125
|
+
const cwd = spec.cwd || process.cwd();
|
|
126
|
+
this._assertSandboxSupported(cwd);
|
|
127
|
+
|
|
75
128
|
const id = `task-${Date.now()}-${createHash("sha256").update(Math.random().toString()).digest("hex").slice(0, 6)}`;
|
|
76
129
|
const task = {
|
|
77
130
|
id,
|
|
78
131
|
type: spec.type || "shell",
|
|
79
132
|
command: spec.command,
|
|
80
|
-
cwd
|
|
133
|
+
cwd,
|
|
81
134
|
description: spec.description || spec.command,
|
|
82
135
|
status: TaskStatus.PENDING,
|
|
83
136
|
createdAt: Date.now(),
|
|
@@ -111,6 +164,8 @@ export class BackgroundTaskManager extends EventEmitter {
|
|
|
111
164
|
throw new Error(`Task ${taskId} is not pending (status: ${task.status})`);
|
|
112
165
|
}
|
|
113
166
|
|
|
167
|
+
this._assertSandboxSupported(task.cwd);
|
|
168
|
+
|
|
114
169
|
task.status = TaskStatus.RUNNING;
|
|
115
170
|
task.startedAt = Date.now();
|
|
116
171
|
task.lastHeartbeat = Date.now();
|
|
@@ -185,6 +240,19 @@ export class BackgroundTaskManager extends EventEmitter {
|
|
|
185
240
|
return task;
|
|
186
241
|
}
|
|
187
242
|
|
|
243
|
+
_assertSandboxSupported(executionCwd) {
|
|
244
|
+
if (!this._resolveSandboxPolicy) return;
|
|
245
|
+
const sandboxPolicy = validatePinnedSandboxPolicy(
|
|
246
|
+
this._resolveSandboxPolicy({
|
|
247
|
+
workspaceCwd: this._policyCwd,
|
|
248
|
+
executionCwd,
|
|
249
|
+
}),
|
|
250
|
+
);
|
|
251
|
+
if (sandboxPolicy) {
|
|
252
|
+
throw createUnsupportedSandboxError(sandboxPolicy);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
188
256
|
get(taskId) {
|
|
189
257
|
return this.tasks.get(taskId) || null;
|
|
190
258
|
}
|
|
@@ -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
|
|
|
@@ -456,7 +456,11 @@ export function previewWorktreeMerge(repoDir, branchName, options = {}) {
|
|
|
456
456
|
|
|
457
457
|
let mergeStarted = false;
|
|
458
458
|
try {
|
|
459
|
-
|
|
459
|
+
// Use argv form here rather than routing through a shell. Besides avoiding
|
|
460
|
+
// another quoting surface, this is important on Windows where a conflicted
|
|
461
|
+
// `git merge` followed immediately by another shell-wrapped git process can
|
|
462
|
+
// race the hosted runner's process/job cleanup and hide the unmerged index.
|
|
463
|
+
gitExecArgs(["merge", baseBranch, "--no-commit", "--no-ff"], worktree.path);
|
|
460
464
|
mergeStarted = true;
|
|
461
465
|
|
|
462
466
|
return {
|
|
@@ -713,7 +717,14 @@ function _hasBranchCommits(repoDir, branchName) {
|
|
|
713
717
|
|
|
714
718
|
function _collectConflictFiles(repoDir) {
|
|
715
719
|
try {
|
|
716
|
-
|
|
720
|
+
// A conflict is expected to make the preceding merge exit non-zero. Query
|
|
721
|
+
// the index with a direct git argv invocation so Windows shell/process
|
|
722
|
+
// teardown cannot turn the authoritative conflict probe into an empty
|
|
723
|
+
// best-effort result.
|
|
724
|
+
const output = gitExecArgs(
|
|
725
|
+
["diff", "--name-only", "--diff-filter=U"],
|
|
726
|
+
repoDir,
|
|
727
|
+
);
|
|
717
728
|
return output
|
|
718
729
|
.split("\n")
|
|
719
730
|
.map((line) => line.trim())
|
|
@@ -988,7 +999,7 @@ function _resolveAutomationCandidate(type, filePath, branchName, candidateId) {
|
|
|
988
999
|
|
|
989
1000
|
function _abortMergeIfPresent(repoDir) {
|
|
990
1001
|
try {
|
|
991
|
-
|
|
1002
|
+
gitExecArgs(["merge", "--abort"], repoDir);
|
|
992
1003
|
} catch (_e) {
|
|
993
1004
|
// Ignore if there is no in-progress merge.
|
|
994
1005
|
}
|
package/src/lib/agent-core.js
CHANGED
|
@@ -48,6 +48,14 @@ function normalizeJitterMs(v) {
|
|
|
48
48
|
return Number.isFinite(n) && n > 0 ? n : 0;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
function normalizeMonitorWorkspaceCwd(value) {
|
|
52
|
+
if (value == null) return null;
|
|
53
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
54
|
+
throw new Error("monitor workspaceCwd must be a non-empty string");
|
|
55
|
+
}
|
|
56
|
+
return path.resolve(value);
|
|
57
|
+
}
|
|
58
|
+
|
|
51
59
|
/**
|
|
52
60
|
* A per-task execution policy for wakeup/cron entries — how the spawned
|
|
53
61
|
* `cc agent` run should behave when this entry fires. Each field maps to a real
|
|
@@ -388,6 +396,7 @@ export class AgentScheduleStore {
|
|
|
388
396
|
|
|
389
397
|
createMonitor({
|
|
390
398
|
command,
|
|
399
|
+
workspaceCwd = null,
|
|
391
400
|
watchFile = null,
|
|
392
401
|
watchUrl = null,
|
|
393
402
|
watchChange = false,
|
|
@@ -443,16 +452,22 @@ export class AgentScheduleStore {
|
|
|
443
452
|
if (stopWhen != null) {
|
|
444
453
|
// Validate the regex up-front so a bad pattern errors at creation, not
|
|
445
454
|
// silently at the first check.
|
|
446
|
-
|
|
455
|
+
|
|
447
456
|
new RegExp(stopWhen);
|
|
448
457
|
}
|
|
449
458
|
const now = this._now();
|
|
450
459
|
const source = hasFile ? "file" : hasUrl ? "http" : "command";
|
|
460
|
+
const normalizedWorkspaceCwd = hasCommand
|
|
461
|
+
? normalizeMonitorWorkspaceCwd(workspaceCwd)
|
|
462
|
+
: null;
|
|
451
463
|
const entry = {
|
|
452
464
|
id: randomUUID(),
|
|
453
465
|
kind: "monitor",
|
|
454
466
|
source,
|
|
455
467
|
command: hasCommand ? command : null,
|
|
468
|
+
...(normalizedWorkspaceCwd
|
|
469
|
+
? { workspaceCwd: normalizedWorkspaceCwd }
|
|
470
|
+
: {}),
|
|
456
471
|
watchFile: hasFile ? watchFile : null,
|
|
457
472
|
watchUrl: hasUrl ? watchUrl : null,
|
|
458
473
|
watchChange: hasFile ? Boolean(watchChange) : false,
|
|
@@ -513,28 +528,36 @@ export class AgentScheduleStore {
|
|
|
513
528
|
const now = atMs != null ? Number(atMs) : this._now();
|
|
514
529
|
const ttl = Math.max(1000, Number(leaseMs) || 120000);
|
|
515
530
|
this._ensureDir();
|
|
516
|
-
return withFileLock(
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
const
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
531
|
+
return withFileLock(
|
|
532
|
+
path.join(this.dir, ".agenda-claims"),
|
|
533
|
+
() => {
|
|
534
|
+
const claimed = [];
|
|
535
|
+
for (const kind of SCHEDULE_KINDS) {
|
|
536
|
+
const entries = this._readAll(kind);
|
|
537
|
+
let changed = false;
|
|
538
|
+
for (const entry of entries) {
|
|
539
|
+
if (!isSchedulableStatus(entry) || isEntryExpired(entry, now))
|
|
540
|
+
continue;
|
|
541
|
+
if (hasLiveExecutionLease(entry, now)) continue;
|
|
542
|
+
const fireAt = effectiveFireAt(entry);
|
|
543
|
+
if (fireAt == null || fireAt > now) continue;
|
|
544
|
+
entry.executionLease = {
|
|
545
|
+
owner: `${process.pid}:${randomUUID()}`,
|
|
546
|
+
claimedAt: now,
|
|
547
|
+
expiresAt: now + ttl,
|
|
548
|
+
};
|
|
549
|
+
claimed.push({
|
|
550
|
+
...entry,
|
|
551
|
+
executionLease: { ...entry.executionLease },
|
|
552
|
+
});
|
|
553
|
+
changed = true;
|
|
554
|
+
}
|
|
555
|
+
if (changed) this._writeAll(kind, entries);
|
|
533
556
|
}
|
|
534
|
-
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
|
|
557
|
+
return claimed;
|
|
558
|
+
},
|
|
559
|
+
{ failIfUnavailable: true },
|
|
560
|
+
);
|
|
538
561
|
}
|
|
539
562
|
|
|
540
563
|
/** Release a failed/aborted claim so a later runner can retry it. */
|
|
@@ -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;
|
package/src/lib/hook-runner.js
CHANGED
|
@@ -35,8 +35,12 @@ function runHookProcessSync(file, argsOrOptions, maybeOptions) {
|
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
runner._deps.
|
|
38
|
+
export function _restoreProcessRunners() {
|
|
39
|
+
runner._deps.run = runHookProcess;
|
|
40
|
+
runner._deps.runSync = runHookProcessSync;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
_restoreProcessRunners();
|
|
40
44
|
|
|
41
45
|
export const {
|
|
42
46
|
runCommandHook,
|
|
@@ -385,7 +385,9 @@ export function generatePkgConfig(ctx) {
|
|
|
385
385
|
const assets = [
|
|
386
386
|
`${posixify(distDir)}/**/*`,
|
|
387
387
|
`${posixify(templatesDir)}/**/*`,
|
|
388
|
-
`${posixify(cliRoot)}/src/lib/process-execution-broker
|
|
388
|
+
`${posixify(cliRoot)}/src/lib/process-execution-broker/windows-sandbox-helper.dll`,
|
|
389
|
+
`${posixify(cliRoot)}/src/lib/process-execution-broker/windows-sandbox-helper.exe`,
|
|
390
|
+
`${posixify(cliRoot)}/src/lib/process-execution-broker/windows-sandbox.cs`,
|
|
389
391
|
];
|
|
390
392
|
if (prebuildsDir) assets.push(`${posixify(prebuildsDir)}/**/*`);
|
|
391
393
|
// Project mode: bundle the collected .chainlesschain/ snapshot as an asset.
|