chainlesschain 0.166.82 → 0.166.83
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/linux-subreaper/linux-arm64/manifest.json +1 -1
- package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-DMzLSUWK.js → AIOps-D5a4i3N7.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CgnA23oA.js → ActionButton-DxsRk5n1.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-CtXmm8Qe.js → Analytics-D-7EvH4S.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-C5RIh5jA.js → AppLayout-DDEWVr-d.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-DM525zx0.js → Artifacts-CAlJAjRB.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-ChBx6f2l.js → Audit-tuaWDOAM.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-BBHDxCda.js → BackgroundAgents-CIwRFJ50.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-B-qzCAoM.js → Backup-CpBepJlH.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-C5yoIWAD.js → BaseInput-eKguCzQc.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-NmTrci9a.js → Chat-CFrUfXDV.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-pPuUDG2V.js → ChatBubbleRenderer-DaRtY87l.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-KdFSU3vd.js → Checkbox-o5FEn6a1.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-L__BOv_4.js → Codegen-Dih8HogC.js} +1 -1
- package/src/assets/web-panel/assets/{Col-Dfuw4IQV.js → Col-D5r-6WZe.js} +1 -1
- package/src/assets/web-panel/assets/{Community-BRlEhSbx.js → Community-jeQ6bGey.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-D7dRkv8n.js → Compact-CEP7QsWp.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CdlFYNR3.js → Compliance-B8NydOHd.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-Ey7ksHq4.js → Cowork-Bmi1zuPy.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-DBH__wGJ.js → Cron-BAL9bwSp.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-D3nu9dw7.js → Crosschain-D8WUi2dS.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DS6vZBNv.js → DID-CQCkYcLY.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-DwFRk2T0.js → Dashboard-DogXg6kh.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-D7b73q3I.js → Dropdown-BJBJyQJn.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DPNaVH36.js → EmailListRenderer-CxPWquJx.js} +1 -1
- package/src/assets/web-panel/assets/{EvolutionSettings-BEsOtdpf.js → EvolutionSettings-BijH1x8G.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-ijSqsSsF.js → FamilyGuardDashboard-DStwf-00.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-C0BOzPDh.js → Federation-LU9_sNxC.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DkF5NoAg.js → FormItemContext-DNfWhj7P.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DQsMcyJj.js → GenericCardRenderer-DWYsPjzk.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DQRt88PU.js → Git-CA0O9ulB.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DIjPmDN8.js → Governance-ECShL7BJ.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BWMFtT7i.js → Inference-9GA2542e.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-M7TfkUVl.js → KnowledgeGraph-nC5mTbEH.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BZv9Z6BY.js → Logs-B7IqgnDy.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-BqlqrJkY.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-Crd9MYHg.js → Marketplace-CEr0suM8.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-C37yOQV0.js → McpTools-DhTPQKOE.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-BBsijJCd.js → Memory-mHRZP1w4.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-CiXIQCju.js → MobileBridge-BNfX6Rdo.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-C0KSvQm5.js → MobileProjects-8zG8f5li.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-C0XaQsOY.js → Mtc-CzkV3wsn.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-DPqggKhw.js → MtcAudit-DWYljJik.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-Bie0ZVHe.js → Multisig-kHgtvZY_.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-BbuJlQ5b.js → NLProgramming-56uQiPiY.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-CgqrJV8w.js → Notes-DxGOZqRf.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-CusdZEQl.js → NotificationSettings-DabaCpmo.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-B7RrCvCQ.js → OrderTableRenderer-SzeQNlGT.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BnFpz3bb.js → Organization-D9gnPpK2.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-C_4_HyyZ.js → Overflow-Cqp_bXm4.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-D0KpHxeg.js → P2P-DTeK-r0G.js} +2 -2
- package/src/assets/web-panel/assets/PdhVaultBrowser-CsjG85GT.js +7 -0
- package/src/assets/web-panel/assets/{Permissions-D2LxL66N.js → Permissions-B4ofZq3j.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-CvSNIxt0.js → PersonalDataHub-Cvas5cYd.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-rUl-SM7V.js → Pipeline-Er3wmAew.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-BD8cWSNd.js → Privacy-DMFYeZox.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-RM7J4X2F.js → ProjectInit-DaVaYPy0.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BIH38RsB.js → ProjectSettings-dPx5q2Ac.js} +2 -2
- package/src/assets/web-panel/assets/Projects-N0JNeCui.js +1 -0
- package/src/assets/web-panel/assets/{Providers-B9Kja2RK.js → Providers-BPQo_gQa.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-ByDKowTD.js → QrScannerModal-CD-sEsWh.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-DqEN1QOE.js → QuickAsk-LOKRJiN_.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-CLrYwNiv.js → Recommend-BwPXqcWy.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-DyDltVPC.js → RemoteSession-BjotndxF.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-BfP8rJ1-.js → Reputation-BlZ2gcbU.js} +1 -1
- package/src/assets/web-panel/assets/{Row-BpnP6r1H.js → Row-D399HM-d.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CBNI1lCN.js → RssFeed-C7H-ibnY.js} +2 -2
- package/src/assets/web-panel/assets/{Search-CLjrM-xj.js → Search-CNHCVmM1.js} +1 -1
- package/src/assets/web-panel/assets/{Security-dRXtg-Mq.js → Security-C70eDGYY.js} +3 -3
- package/src/assets/web-panel/assets/{Services-DAHCtOHL.js → Services-6xfq9G-H.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-D11Jgtur.js → Skeleton-BbY2zeZV.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-DchvTO4k.js → Skills-DYtyZ7_6.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-BFOc2SbL.js → Sla-CkWcl5OH.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-Dud1xDd2.js → SpeechSettings-CiknYk2P.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-CILfsA2S.js → SyncSettings-D-8JVip4.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-C6Qrah_5.js → Tasks-B2KnR9XC.js} +1 -1
- package/src/assets/web-panel/assets/{Templates--puiHyCR.js → Templates-CipXkOE-.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-cz5vITz_.js → Tenant-DbwgIMmx.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-YRs75Gz8.js → Terminal-OtCriHEE.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-C5myb_QZ.js → TimelineRenderer-B9LU5qrl.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-Bk60iMIj.js → Tokens-B4iFVxvH.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BAb-Fd4z.js → Trigger-BegM2v8q.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-BlqwmpEB.js → Trust-COkqnnFj.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-C6jvuF-7.js → UkeySign-BzqKPChj.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-7zbsdQUj.js → VideoEditing-D-F2XL3C.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BAouk_kp.js → Wallet-22PzRY9T.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-BQapv504.js → WebAuthn-eSMq_qtz.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-ChUXM-Qx.js → WorkflowEditor-BvdAakpq.js} +1 -1
- package/src/assets/web-panel/assets/{chat-7B6U8zgJ.js → chat-C6jhpF7E.js} +1 -1
- package/src/assets/web-panel/assets/{colors-C8UqaLpe.js → colors-BbbW2Pfv.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-x47giTCj.js → compact-item-CVFeLTqt.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-D6ZwjgaZ.js → createContext-DS0m7NZc.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-D50gzPS9.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-Cv3d9-Bu.js → hasIn-DVouP0t6.js} +1 -1
- package/src/assets/web-panel/assets/{index-DVBG0Jqz.js → index--AdzSlH7.js} +1 -1
- package/src/assets/web-panel/assets/{index-CXIUyx4U.js → index-54aHB4FL.js} +1 -1
- package/src/assets/web-panel/assets/{index-WhoNHp50.js → index-8QbwhE3i.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dv5E07PZ.js → index-B5JRIZXi.js} +1 -1
- package/src/assets/web-panel/assets/{index-BTBkdyLk.js → index-B8a_c_qZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DtBUgc0G.js → index-BE_u-rXr.js} +1 -1
- package/src/assets/web-panel/assets/{index-BMPk5D1m.js → index-BOOsA080.js} +1 -1
- package/src/assets/web-panel/assets/{index-jgN2e0Oy.js → index-BXw6ivB8.js} +1 -1
- package/src/assets/web-panel/assets/{index-CUtcWTSe.js → index-BaUah6TO.js} +1 -1
- package/src/assets/web-panel/assets/{index-DD-V-N_m.js → index-Be12HoCS.js} +3 -3
- package/src/assets/web-panel/assets/{index-CaPZ_8kP.js → index-BhvnNFfd.js} +1 -1
- package/src/assets/web-panel/assets/{index-C1ElqYDD.js → index-BrIv7C9a.js} +1 -1
- package/src/assets/web-panel/assets/{index-CrGQsbpb.js → index-BvCgzl0X.js} +1 -1
- package/src/assets/web-panel/assets/{index-D4ZHX6wo.js → index-Bw-ZGQCH.js} +1 -1
- package/src/assets/web-panel/assets/{index-CXG6yiAf.js → index-BwZnPiFd.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ce666S9v.js → index-BwozzG6k.js} +1 -1
- package/src/assets/web-panel/assets/{index-BTisPSqa.js → index-ByLsH9CL.js} +1 -1
- package/src/assets/web-panel/assets/{index-dbM4QvQZ.js → index-BzL3LWFX.js} +1 -1
- package/src/assets/web-panel/assets/{index-CUUgXcPh.js → index-C4xmLgLa.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dc0hePXV.js → index-C6q2MkIG.js} +1 -1
- package/src/assets/web-panel/assets/{index-CiVEatgH.js → index-C74emdKD.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGxo1YH0.js → index-CIg4nqyp.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cc2bhSuI.js → index-CIk7mg6G.js} +1 -1
- package/src/assets/web-panel/assets/{index-BM-NYjej.js → index-CPS8E-J6.js} +1 -1
- package/src/assets/web-panel/assets/index-CgensV-n.js +1 -0
- package/src/assets/web-panel/assets/{index-D9lFBkS4.js → index-CkdYB0_g.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQ0-ny-o.js → index-CpTbnbUI.js} +1 -1
- package/src/assets/web-panel/assets/index-Ctkf06Z_.js +1 -0
- package/src/assets/web-panel/assets/{index-Cc6jr0Yb.js → index-CwYFDMn_.js} +1 -1
- package/src/assets/web-panel/assets/{index-DLHnYXVa.js → index-DGYX17YW.js} +1 -1
- package/src/assets/web-panel/assets/{index-DvoMGeL9.js → index-DR6TDz5H.js} +1 -1
- package/src/assets/web-panel/assets/{index-EDWA9JL1.js → index-DUBkae39.js} +1 -1
- package/src/assets/web-panel/assets/{index-yYdCdtY1.js → index-DotRL126.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cbf4RqOd.js → index-DpReoAGb.js} +1 -1
- package/src/assets/web-panel/assets/{index-N9hNOl1i.js → index-Ds4wbrgk.js} +1 -1
- package/src/assets/web-panel/assets/{index-IVelXaiQ.js → index-DuVjTDcW.js} +1 -1
- package/src/assets/web-panel/assets/{index-BUzw-kDo.js → index-JeJqXbUU.js} +1 -1
- package/src/assets/web-panel/assets/{index-nogjrcQE.js → index-SdFkCtiC.js} +1 -1
- package/src/assets/web-panel/assets/{index-B7Dorc7r.js → index-eaXEQFuP.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-DkKS5xtR.js → initDefaultProps-CB5cUnQ5.js} +1 -1
- package/src/assets/web-panel/assets/{motion-CU-zBUIg.js → motion-bn_fWhQV.js} +1 -1
- package/src/assets/web-panel/assets/{move-zBE0VEd4.js → move-DY4-Odtu.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-B9WyO1je.js → mtc-parser-B5l5mjoh.js} +1 -1
- package/src/assets/web-panel/assets/{omit-6sCoBNTL.js → omit-rJ-Ci8CW.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DDRv_sFc.js → pickAttrs-BMwGJd6C.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-Cy_CBDw5.js → placementArrow-CaiQyGXG.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-CIczLq9K.js → responsiveObserve-DQTO5wDH.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DFfZCvnG.js → slide-Dg6ZDtbz.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-DW-0HUl-.js → statusUtils-bvjrktKc.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-BPYaBorP.js → styleChecker-C1geIU_x.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-DYPoOaZc.js → useFlexGapSupport-BzU3RJRi.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-ODUEWR17.js → useFs-B7l6OwLe.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-CstUt15X.js → usePersonalDataHub-BYF1L_8x.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-D2GW8xCL.js → vnode-6c2GVkT-.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-Bz6GoDwq.js → zoom-BYAY6QeD.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agent.js +21 -10
- package/src/data/changelog.json +26 -0
- package/src/gateways/ws/session-protocol.js +19 -5
- package/src/gateways/ws/ws-agent-handler.js +6 -0
- package/src/gateways/ws/ws-session-gateway.js +133 -21
- package/src/lib/agent-execution-policy.js +177 -0
- package/src/lib/authority-launch-environment.js +99 -0
- package/src/lib/claude-project-auto-memory.js +7 -30
- package/src/lib/evolution/volcengine-function-replay-store.js +38 -28
- package/src/lib/host-tool-policy-authority.js +151 -0
- package/src/lib/permission-authority.js +67 -5
- package/src/lib/plugin-runtime/settings.js +9 -1
- package/src/lib/sandbox-egress-authority-monitor.js +3 -2
- package/src/lib/session-manager.js +20 -5
- package/src/lib/settings-loader.cjs +175 -19
- package/src/lib/settings-source-observation.cjs +270 -0
- package/src/lib/sub-agent-context.js +36 -18
- package/src/lib/unattended-action-policy.js +456 -38
- package/src/repl/agent-repl.js +43 -15
- package/src/repl/repl-tool-executor.js +39 -0
- package/src/runtime/agent-core.js +272 -5
- package/src/runtime/agent-runtime.js +15 -3
- package/src/runtime/headless-runner.js +13 -4
- package/src/runtime/headless-stream.js +9 -0
- package/src/runtime/policies/agent-policy.js +5 -4
- package/src/assets/web-panel/assets/MarkdownRenderer-D5NZGdg3.js +0 -1
- package/src/assets/web-panel/assets/PdhVaultBrowser-Cfd_C9nc.js +0 -7
- package/src/assets/web-panel/assets/Projects-CTgx3Fxc.js +0 -1
- package/src/assets/web-panel/assets/devWarning-BFfV5AtN.js +0 -1
- package/src/assets/web-panel/assets/index-DUz_bv5i.js +0 -1
- package/src/assets/web-panel/assets/index-rQ59l7GO.js +0 -1
|
@@ -18,6 +18,42 @@
|
|
|
18
18
|
* PURE: no fs / clock / RNG / process.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
import { snapshotMcpJsonRpcInput } from "./mcp-call-ledger.js";
|
|
22
|
+
|
|
23
|
+
/** Bind startup-only authority without retaining caller-owned mutable data. */
|
|
24
|
+
export function captureUnattendedActionPolicy(policy) {
|
|
25
|
+
if (policy == null) return null;
|
|
26
|
+
try {
|
|
27
|
+
const snapshot = snapshotMcpJsonRpcInput(policy);
|
|
28
|
+
if (!snapshot || typeof snapshot !== "object" || Array.isArray(snapshot))
|
|
29
|
+
throw new TypeError();
|
|
30
|
+
for (const flag of ["unattended", "protectedBranch", "budgetExhausted"]) {
|
|
31
|
+
if (snapshot[flag] !== undefined && typeof snapshot[flag] !== "boolean")
|
|
32
|
+
throw new TypeError();
|
|
33
|
+
}
|
|
34
|
+
if (
|
|
35
|
+
snapshot.allowlist !== undefined &&
|
|
36
|
+
(!Array.isArray(snapshot.allowlist) ||
|
|
37
|
+
snapshot.allowlist.some((value) => typeof value !== "string"))
|
|
38
|
+
)
|
|
39
|
+
throw new TypeError();
|
|
40
|
+
if (
|
|
41
|
+
snapshot.trigger !== undefined &&
|
|
42
|
+
(!snapshot.trigger ||
|
|
43
|
+
typeof snapshot.trigger !== "object" ||
|
|
44
|
+
Array.isArray(snapshot.trigger) ||
|
|
45
|
+
(snapshot.trigger.trusted !== undefined &&
|
|
46
|
+
typeof snapshot.trigger.trusted !== "boolean"))
|
|
47
|
+
)
|
|
48
|
+
throw new TypeError();
|
|
49
|
+
return snapshot;
|
|
50
|
+
} catch {
|
|
51
|
+
const error = new TypeError("Unattended action policy is invalid");
|
|
52
|
+
error.code = "CC_UNATTENDED_POLICY_INVALID";
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
21
57
|
/** Canonical action classes, ordered low → high consequence. */
|
|
22
58
|
export const ACTION_CLASS = Object.freeze({
|
|
23
59
|
READ: "read",
|
|
@@ -86,6 +122,54 @@ export const TOOL_ACTION_CLASS = Object.freeze({
|
|
|
86
122
|
notify: ACTION_CLASS.EXTERNAL_MESSAGE,
|
|
87
123
|
});
|
|
88
124
|
|
|
125
|
+
// Fixed built-ins with local effects. Peer annotations and generic runtime
|
|
126
|
+
// descriptors cannot add to this list. Shell/Git have their own command
|
|
127
|
+
// ceilings; opaque executors and persistent/delegated runs remain unknown.
|
|
128
|
+
const LOCAL_TOOL_ACTION_CLASS = Object.freeze({
|
|
129
|
+
read_file: ACTION_CLASS.READ,
|
|
130
|
+
search_files: ACTION_CLASS.READ,
|
|
131
|
+
list_dir: ACTION_CLASS.READ,
|
|
132
|
+
list_skills: ACTION_CLASS.READ,
|
|
133
|
+
search_sessions: ACTION_CLASS.READ,
|
|
134
|
+
ask_user_question: ACTION_CLASS.READ,
|
|
135
|
+
write_file: ACTION_CLASS.LOCAL_WRITE,
|
|
136
|
+
edit_file: ACTION_CLASS.LOCAL_WRITE,
|
|
137
|
+
edit_file_hashed: ACTION_CLASS.LOCAL_WRITE,
|
|
138
|
+
delete_file: ACTION_CLASS.LOCAL_WRITE,
|
|
139
|
+
move_file: ACTION_CLASS.LOCAL_WRITE,
|
|
140
|
+
notebook_edit: ACTION_CLASS.LOCAL_WRITE,
|
|
141
|
+
todo_write: ACTION_CLASS.LOCAL_WRITE,
|
|
142
|
+
check_shell: ACTION_CLASS.LOCAL_WRITE,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
/** Execution guard for built-ins; an opaque host/MCP executor stays unknown. */
|
|
146
|
+
export function evaluateUnattendedToolAction(
|
|
147
|
+
name,
|
|
148
|
+
args,
|
|
149
|
+
policy,
|
|
150
|
+
{ external = false } = {},
|
|
151
|
+
) {
|
|
152
|
+
let actionClass = null;
|
|
153
|
+
if (!external) {
|
|
154
|
+
actionClass = Object.hasOwn(TOOL_ACTION_CLASS, name)
|
|
155
|
+
? TOOL_ACTION_CLASS[name]
|
|
156
|
+
: Object.hasOwn(LOCAL_TOOL_ACTION_CLASS, name)
|
|
157
|
+
? LOCAL_TOOL_ACTION_CLASS[name]
|
|
158
|
+
: null;
|
|
159
|
+
if (["run_shell", "git"].includes(name)) actionClass = ACTION_CLASS.READ;
|
|
160
|
+
// Persistent child runs do not yet carry a durable parent effect ceiling.
|
|
161
|
+
if (
|
|
162
|
+
name === "schedule" &&
|
|
163
|
+
["list", "cancel"].includes(String(args?.action || "").toLowerCase())
|
|
164
|
+
)
|
|
165
|
+
actionClass = ACTION_CLASS.LOCAL_WRITE;
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
actionClass,
|
|
169
|
+
...evaluateUnattendedAction({ ...policy, actionClass, attended: false }),
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
89
173
|
/**
|
|
90
174
|
* The agent tools an UNATTENDED run must be denied — the enforcement projection
|
|
91
175
|
* of `evaluateUnattendedAction` onto the tool layer (P1-8). A scheduled
|
|
@@ -127,10 +211,10 @@ export function classifyActionRisk(actionClass) {
|
|
|
127
211
|
* the highest-risk segment and unknown commands remain unknown so an
|
|
128
212
|
* unattended caller can fail closed.
|
|
129
213
|
*/
|
|
130
|
-
|
|
131
|
-
if (typeof command !== "string" || !command.trim()) return
|
|
214
|
+
function classifyShellSegments(command) {
|
|
215
|
+
if (typeof command !== "string" || !command.trim()) return [];
|
|
132
216
|
const segments = command
|
|
133
|
-
.split(/&&|\|\||[
|
|
217
|
+
.split(/&&|\|\||[;&\n]|\|/)
|
|
134
218
|
.map((part) =>
|
|
135
219
|
part
|
|
136
220
|
.trim()
|
|
@@ -139,15 +223,29 @@ export function classifyShellAction(command) {
|
|
|
139
223
|
)
|
|
140
224
|
.filter(Boolean);
|
|
141
225
|
const classifySegment = (segment) => {
|
|
142
|
-
|
|
143
|
-
|
|
226
|
+
// Substitution and executable search/filter options can hide effects
|
|
227
|
+
// inside a nominally read-only command. Unsupported syntax is unknown.
|
|
228
|
+
if (
|
|
229
|
+
/[$`'"\\^(){}]/.test(segment) ||
|
|
230
|
+
/(?:^|\s)(?:-exec(?:dir)?|-ok(?:dir)?|--pre)(?:\s|=|$)/.test(segment)
|
|
231
|
+
)
|
|
232
|
+
return null;
|
|
233
|
+
if (
|
|
234
|
+
/^git(?:\s|$)/.test(segment) &&
|
|
235
|
+
!hasKnownGitOptions(segment.split(/\s+/).slice(1))
|
|
236
|
+
)
|
|
237
|
+
return null;
|
|
238
|
+
if (/^git\s+push(?:\s|$)/.test(segment)) return ACTION_CLASS.PUSH;
|
|
239
|
+
if (/^git\s+(?:add|commit|fetch)(?:\s|$)/.test(segment))
|
|
240
|
+
return ACTION_CLASS.LOCAL_WRITE;
|
|
241
|
+
if (/^git\s+(?:merge|rebase|cherry-pick)(?:\s|$)/.test(segment)) {
|
|
144
242
|
return ACTION_CLASS.MERGE;
|
|
145
243
|
}
|
|
146
|
-
if (/^(?:npm|pnpm|yarn|bun)
|
|
244
|
+
if (/^(?:npm|pnpm|yarn|bun)(?:\.cmd)?\s+publish(?:\s|$)/.test(segment)) {
|
|
147
245
|
return ACTION_CLASS.PUBLISH;
|
|
148
246
|
}
|
|
149
247
|
if (
|
|
150
|
-
/^(?:terraform\s+(?:apply|destroy)|pulumi\s+up|kubectl\s+(?:apply|delete|rollout)|helm\s+(?:install|upgrade)|docker\s+push)
|
|
248
|
+
/^(?:terraform\s+(?:apply|destroy)|pulumi\s+up|kubectl\s+(?:apply|delete|rollout)|helm\s+(?:install|upgrade)|docker\s+push)(?:\s|$)/.test(
|
|
151
249
|
segment,
|
|
152
250
|
)
|
|
153
251
|
) {
|
|
@@ -155,55 +253,375 @@ export function classifyShellAction(command) {
|
|
|
155
253
|
? ACTION_CLASS.DEPLOY
|
|
156
254
|
: ACTION_CLASS.INFRA_MUTATION;
|
|
157
255
|
}
|
|
158
|
-
if (
|
|
159
|
-
|
|
256
|
+
if (
|
|
257
|
+
/^(?:npm|pnpm|yarn|bun)(?:\.cmd)?\s+run\s+(?:deploy|rollout)(?:\s|$)/.test(
|
|
258
|
+
segment,
|
|
259
|
+
)
|
|
260
|
+
)
|
|
261
|
+
return ACTION_CLASS.DEPLOY;
|
|
262
|
+
if (
|
|
263
|
+
/^(?:git\s+(?:status|diff|log|show)(?:\s|$)|git\s+branch\s*$|(?:ls|dir|pwd|cat|type|rg|grep|find|where)(?:\s|$))/.test(
|
|
264
|
+
segment,
|
|
265
|
+
)
|
|
266
|
+
) {
|
|
160
267
|
return ACTION_CLASS.READ;
|
|
161
268
|
}
|
|
162
|
-
if (
|
|
269
|
+
if (
|
|
270
|
+
/^(?:npm|pnpm|yarn|bun)(?:\.cmd)?\s+(?:test|run\s+(?:test|lint|build)|install)(?:\s|$)/.test(
|
|
271
|
+
segment,
|
|
272
|
+
) ||
|
|
273
|
+
/^(?:pytest|vitest|jest|cargo\s+test|go\s+test)(?:\s|$)/.test(segment)
|
|
274
|
+
) {
|
|
163
275
|
return ACTION_CLASS.LOCAL_WRITE;
|
|
164
276
|
}
|
|
165
|
-
if (/^echo
|
|
277
|
+
if (/^echo(?:\s|$)/.test(segment) && />/.test(segment)) {
|
|
166
278
|
return ACTION_CLASS.LOCAL_WRITE;
|
|
167
279
|
}
|
|
168
280
|
return null;
|
|
169
281
|
};
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
ACTION_CLASS.PUSH,
|
|
175
|
-
ACTION_CLASS.PUBLISH,
|
|
176
|
-
ACTION_CLASS.MERGE,
|
|
177
|
-
ACTION_CLASS.DEPLOY,
|
|
178
|
-
ACTION_CLASS.INFRA_MUTATION,
|
|
179
|
-
ACTION_CLASS.EXTERNAL_MESSAGE,
|
|
180
|
-
];
|
|
181
|
-
const classified = segments.map(classifySegment);
|
|
182
|
-
return classified.reduce((highest, current) => {
|
|
183
|
-
if (!current) return null;
|
|
184
|
-
if (!highest) return current;
|
|
185
|
-
return rank.indexOf(current) > rank.indexOf(highest) ? current : highest;
|
|
186
|
-
}, null);
|
|
282
|
+
return segments.map((segment) => ({
|
|
283
|
+
command: segment,
|
|
284
|
+
actionClass: classifySegment(segment),
|
|
285
|
+
}));
|
|
187
286
|
}
|
|
188
287
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
288
|
+
const ACTION_RANK = [
|
|
289
|
+
ACTION_CLASS.READ,
|
|
290
|
+
ACTION_CLASS.LOCAL_WRITE,
|
|
291
|
+
ACTION_CLASS.COMMIT,
|
|
292
|
+
ACTION_CLASS.PUSH,
|
|
293
|
+
ACTION_CLASS.PUBLISH,
|
|
294
|
+
ACTION_CLASS.MERGE,
|
|
295
|
+
ACTION_CLASS.DEPLOY,
|
|
296
|
+
ACTION_CLASS.INFRA_MUTATION,
|
|
297
|
+
ACTION_CLASS.EXTERNAL_MESSAGE,
|
|
298
|
+
];
|
|
299
|
+
|
|
300
|
+
// Unknown Git options may select executable helpers (upload-pack,
|
|
301
|
+
// receive-pack, rebase --exec, custom merge strategies, external diff, ...).
|
|
302
|
+
// Accept complete known options only; Git's long-option abbreviations do not
|
|
303
|
+
// inherit authority. These are command-specific because -s means different
|
|
304
|
+
// things for status, commit and merge.
|
|
305
|
+
const SAFE_GIT_OPTIONS = Object.freeze({
|
|
306
|
+
status: [
|
|
307
|
+
"--short",
|
|
308
|
+
"-s",
|
|
309
|
+
"--branch",
|
|
310
|
+
"-b",
|
|
311
|
+
"--porcelain",
|
|
312
|
+
"--porcelain=v1",
|
|
313
|
+
"--porcelain=v2",
|
|
314
|
+
"--untracked-files",
|
|
315
|
+
"--untracked-files=all",
|
|
316
|
+
"--untracked-files=no",
|
|
317
|
+
"--ignored",
|
|
318
|
+
],
|
|
319
|
+
diff: [
|
|
320
|
+
"--stat",
|
|
321
|
+
"--name-only",
|
|
322
|
+
"--name-status",
|
|
323
|
+
"--numstat",
|
|
324
|
+
"--shortstat",
|
|
325
|
+
"--patch",
|
|
326
|
+
"-p",
|
|
327
|
+
"--no-patch",
|
|
328
|
+
"-s",
|
|
329
|
+
"--cached",
|
|
330
|
+
"--staged",
|
|
331
|
+
"--no-ext-diff",
|
|
332
|
+
"--no-textconv",
|
|
333
|
+
"--no-renames",
|
|
334
|
+
"--no-color",
|
|
335
|
+
],
|
|
336
|
+
log: [
|
|
337
|
+
"--oneline",
|
|
338
|
+
"--stat",
|
|
339
|
+
"--name-only",
|
|
340
|
+
"--name-status",
|
|
341
|
+
"--patch",
|
|
342
|
+
"-p",
|
|
343
|
+
"--no-patch",
|
|
344
|
+
"--all",
|
|
345
|
+
"--graph",
|
|
346
|
+
"--decorate",
|
|
347
|
+
"--no-color",
|
|
348
|
+
"-n",
|
|
349
|
+
],
|
|
350
|
+
show: [
|
|
351
|
+
"--oneline",
|
|
352
|
+
"--stat",
|
|
353
|
+
"--name-only",
|
|
354
|
+
"--name-status",
|
|
355
|
+
"--patch",
|
|
356
|
+
"-p",
|
|
357
|
+
"--no-patch",
|
|
358
|
+
"--no-ext-diff",
|
|
359
|
+
"--no-textconv",
|
|
360
|
+
"--no-color",
|
|
361
|
+
],
|
|
362
|
+
"rev-parse": [
|
|
363
|
+
"--show-toplevel",
|
|
364
|
+
"--git-dir",
|
|
365
|
+
"--is-inside-work-tree",
|
|
366
|
+
"--verify",
|
|
367
|
+
"--short",
|
|
368
|
+
],
|
|
369
|
+
"ls-files": [
|
|
370
|
+
"--cached",
|
|
371
|
+
"--others",
|
|
372
|
+
"--modified",
|
|
373
|
+
"--deleted",
|
|
374
|
+
"--exclude-standard",
|
|
375
|
+
"--stage",
|
|
376
|
+
"--error-unmatch",
|
|
377
|
+
],
|
|
378
|
+
branch: [],
|
|
379
|
+
remote: ["-v"],
|
|
380
|
+
add: [
|
|
381
|
+
"--all",
|
|
382
|
+
"-A",
|
|
383
|
+
"--force",
|
|
384
|
+
"-f",
|
|
385
|
+
"--update",
|
|
386
|
+
"-u",
|
|
387
|
+
"--intent-to-add",
|
|
388
|
+
"-N",
|
|
389
|
+
"--dry-run",
|
|
390
|
+
"-n",
|
|
391
|
+
"--verbose",
|
|
392
|
+
"-v",
|
|
393
|
+
],
|
|
394
|
+
commit: [
|
|
395
|
+
"-m",
|
|
396
|
+
"--message",
|
|
397
|
+
"-a",
|
|
398
|
+
"--all",
|
|
399
|
+
"--amend",
|
|
400
|
+
"--no-verify",
|
|
401
|
+
"--allow-empty",
|
|
402
|
+
"--allow-empty-message",
|
|
403
|
+
"--signoff",
|
|
404
|
+
"-s",
|
|
405
|
+
"--no-gpg-sign",
|
|
406
|
+
"--quiet",
|
|
407
|
+
"-q",
|
|
408
|
+
"--dry-run",
|
|
409
|
+
],
|
|
410
|
+
fetch: [
|
|
411
|
+
"--all",
|
|
412
|
+
"--prune",
|
|
413
|
+
"-p",
|
|
414
|
+
"--tags",
|
|
415
|
+
"-t",
|
|
416
|
+
"--no-tags",
|
|
417
|
+
"--quiet",
|
|
418
|
+
"-q",
|
|
419
|
+
"--verbose",
|
|
420
|
+
"-v",
|
|
421
|
+
"--dry-run",
|
|
422
|
+
"--no-recurse-submodules",
|
|
423
|
+
"--unshallow",
|
|
424
|
+
],
|
|
425
|
+
push: [
|
|
426
|
+
"-u",
|
|
427
|
+
"--set-upstream",
|
|
428
|
+
"--force",
|
|
429
|
+
"-f",
|
|
430
|
+
"--force-with-lease",
|
|
431
|
+
"--no-verify",
|
|
432
|
+
"--dry-run",
|
|
433
|
+
"-n",
|
|
434
|
+
"--all",
|
|
435
|
+
"--mirror",
|
|
436
|
+
"--tags",
|
|
437
|
+
"--delete",
|
|
438
|
+
"-d",
|
|
439
|
+
],
|
|
440
|
+
merge: [
|
|
441
|
+
"--ff-only",
|
|
442
|
+
"--no-ff",
|
|
443
|
+
"--squash",
|
|
444
|
+
"--abort",
|
|
445
|
+
"--continue",
|
|
446
|
+
"--quit",
|
|
447
|
+
"--no-edit",
|
|
448
|
+
"--no-verify",
|
|
449
|
+
"--no-gpg-sign",
|
|
450
|
+
],
|
|
451
|
+
rebase: [
|
|
452
|
+
"--abort",
|
|
453
|
+
"--continue",
|
|
454
|
+
"--skip",
|
|
455
|
+
"--quit",
|
|
456
|
+
"--autostash",
|
|
457
|
+
"--no-autostash",
|
|
458
|
+
"--no-gpg-sign",
|
|
459
|
+
],
|
|
460
|
+
"cherry-pick": [
|
|
461
|
+
"--abort",
|
|
462
|
+
"--continue",
|
|
463
|
+
"--skip",
|
|
464
|
+
"--quit",
|
|
465
|
+
"--no-commit",
|
|
466
|
+
"-n",
|
|
467
|
+
"--no-gpg-sign",
|
|
468
|
+
],
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
function hasKnownGitOptions(argv) {
|
|
472
|
+
const [subcommand, ...args] = argv;
|
|
473
|
+
const known = SAFE_GIT_OPTIONS[subcommand];
|
|
474
|
+
if (!Array.isArray(known)) return false;
|
|
475
|
+
let pathOperands = false;
|
|
476
|
+
let valueOperand = false;
|
|
477
|
+
return args.every((value) => {
|
|
478
|
+
if (valueOperand) {
|
|
479
|
+
valueOperand = false;
|
|
480
|
+
return true;
|
|
481
|
+
}
|
|
482
|
+
if (/^[a-z][a-z0-9+.-]*::/i.test(value)) return false;
|
|
483
|
+
if (pathOperands) return true;
|
|
484
|
+
if (value === "--") {
|
|
485
|
+
pathOperands = true;
|
|
486
|
+
return true;
|
|
487
|
+
}
|
|
488
|
+
if (!value.startsWith("-")) return true;
|
|
489
|
+
if (
|
|
490
|
+
["log", "show"].includes(subcommand) &&
|
|
491
|
+
/^--(?:format|pretty)=/.test(value)
|
|
492
|
+
)
|
|
493
|
+
return true;
|
|
494
|
+
if (subcommand === "log" && /^(?:-\d+|--max-count=\d+)$/.test(value))
|
|
495
|
+
return true;
|
|
496
|
+
if (subcommand === "fetch" && /^--depth=\d+$/.test(value)) return true;
|
|
497
|
+
if (subcommand === "commit" && /^--message=/.test(value)) return true;
|
|
498
|
+
if (!known.includes(value)) return false;
|
|
499
|
+
if (
|
|
500
|
+
(subcommand === "commit" && ["-m", "--message"].includes(value)) ||
|
|
501
|
+
(subcommand === "log" && value === "-n")
|
|
502
|
+
)
|
|
503
|
+
valueOperand = true;
|
|
504
|
+
return true;
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
export function classifyShellAction(command) {
|
|
509
|
+
const segments = classifyShellSegments(command);
|
|
510
|
+
if (!segments.length || segments.some((segment) => !segment.actionClass))
|
|
511
|
+
return null;
|
|
512
|
+
return segments.reduce(
|
|
513
|
+
(highest, { actionClass }) =>
|
|
514
|
+
ACTION_RANK.indexOf(actionClass) > ACTION_RANK.indexOf(highest)
|
|
515
|
+
? actionClass
|
|
516
|
+
: highest,
|
|
517
|
+
null,
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
function pushNeedsMergeAuthorization(argv) {
|
|
522
|
+
const positional = [];
|
|
523
|
+
for (const value of argv) {
|
|
524
|
+
if (
|
|
525
|
+
[
|
|
526
|
+
"-u",
|
|
527
|
+
"--set-upstream",
|
|
528
|
+
"--force",
|
|
529
|
+
"-f",
|
|
530
|
+
"--force-with-lease",
|
|
531
|
+
"--no-verify",
|
|
532
|
+
"--dry-run",
|
|
533
|
+
"-n",
|
|
534
|
+
].includes(value)
|
|
535
|
+
)
|
|
536
|
+
continue;
|
|
537
|
+
if (value.startsWith("-")) return true;
|
|
538
|
+
positional.push(value);
|
|
539
|
+
}
|
|
540
|
+
// Require an explicit remote AND every destination ref. Git configuration
|
|
541
|
+
// controls omitted refspecs and may include protected branches.
|
|
542
|
+
if (positional.length < 2) return true;
|
|
543
|
+
return positional.slice(1).some((refspec) => {
|
|
544
|
+
const destination = refspec.replace(/^\+/, "").split(":").at(-1);
|
|
545
|
+
if (
|
|
546
|
+
!destination ||
|
|
547
|
+
!/^[a-z0-9._/-]+$/i.test(destination) ||
|
|
548
|
+
destination.toUpperCase() === "HEAD"
|
|
549
|
+
)
|
|
550
|
+
return true;
|
|
551
|
+
const branch = destination.replace(/^refs\/heads\//, "");
|
|
552
|
+
return (
|
|
553
|
+
/^(?:main|master|develop|production)$/i.test(branch) ||
|
|
554
|
+
(/^refs\//.test(destination) && !destination.startsWith("refs/heads/"))
|
|
196
555
|
);
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/** Classify the exact argv used by the git tool, never a shell string. */
|
|
560
|
+
export function evaluateUnattendedGitAction(argv, params = {}) {
|
|
561
|
+
const validArgv =
|
|
562
|
+
Array.isArray(argv) && argv.every((value) => typeof value === "string");
|
|
563
|
+
const subcommand = validArgv ? argv[0] : null;
|
|
564
|
+
const actionClass =
|
|
565
|
+
!validArgv || !hasKnownGitOptions(argv)
|
|
566
|
+
? null
|
|
567
|
+
: subcommand === "push"
|
|
568
|
+
? ACTION_CLASS.PUSH
|
|
569
|
+
: ["merge", "rebase", "cherry-pick"].includes(subcommand)
|
|
570
|
+
? ACTION_CLASS.MERGE
|
|
571
|
+
: ["add", "commit", "fetch"].includes(subcommand)
|
|
572
|
+
? ACTION_CLASS.LOCAL_WRITE
|
|
573
|
+
: [
|
|
574
|
+
"status",
|
|
575
|
+
"diff",
|
|
576
|
+
"log",
|
|
577
|
+
"show",
|
|
578
|
+
"rev-parse",
|
|
579
|
+
"ls-files",
|
|
580
|
+
].includes(subcommand) ||
|
|
581
|
+
(subcommand === "branch" && argv.length === 1) ||
|
|
582
|
+
(subcommand === "remote" &&
|
|
583
|
+
argv.slice(1).every((value) => value === "-v"))
|
|
584
|
+
? ACTION_CLASS.READ
|
|
585
|
+
: null;
|
|
197
586
|
return {
|
|
198
587
|
actionClass,
|
|
199
588
|
...evaluateUnattendedAction({
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
589
|
+
...params,
|
|
590
|
+
actionClass,
|
|
591
|
+
protectedBranch:
|
|
592
|
+
params.protectedBranch === true ||
|
|
593
|
+
(subcommand === "push" && pushNeedsMergeAuthorization(argv.slice(1))),
|
|
203
594
|
}),
|
|
204
595
|
};
|
|
205
596
|
}
|
|
206
597
|
|
|
598
|
+
/** Apply the unattended policy to a shell command, including protected push targets. */
|
|
599
|
+
export function evaluateUnattendedShellAction(command, params = {}) {
|
|
600
|
+
const segments = classifyShellSegments(command);
|
|
601
|
+
const verdicts = (segments.length ? segments : [{ actionClass: null }]).map(
|
|
602
|
+
(segment) => ({
|
|
603
|
+
actionClass: segment.actionClass,
|
|
604
|
+
...evaluateUnattendedAction({
|
|
605
|
+
...params,
|
|
606
|
+
actionClass: segment.actionClass,
|
|
607
|
+
protectedBranch:
|
|
608
|
+
params.protectedBranch === true ||
|
|
609
|
+
(segment.actionClass === ACTION_CLASS.PUSH &&
|
|
610
|
+
pushNeedsMergeAuthorization(segment.command.split(/\s+/).slice(2))),
|
|
611
|
+
}),
|
|
612
|
+
}),
|
|
613
|
+
);
|
|
614
|
+
// An allowlist grants individual classes, never all lower-ranked actions.
|
|
615
|
+
const denied = verdicts.find((verdict) => !verdict.allow);
|
|
616
|
+
if (denied) return denied;
|
|
617
|
+
return verdicts.reduce((highest, current) =>
|
|
618
|
+
ACTION_RANK.indexOf(current.actionClass) >
|
|
619
|
+
ACTION_RANK.indexOf(highest.actionClass)
|
|
620
|
+
? current
|
|
621
|
+
: highest,
|
|
622
|
+
);
|
|
623
|
+
}
|
|
624
|
+
|
|
207
625
|
/**
|
|
208
626
|
* Decide whether a fired task may perform one action. Fail-closed.
|
|
209
627
|
*
|
package/src/repl/agent-repl.js
CHANGED
|
@@ -18,6 +18,11 @@
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
import readline from "readline";
|
|
21
|
+
import {
|
|
22
|
+
captureAgentExecutionPolicy,
|
|
23
|
+
resolveAgentToolSelection,
|
|
24
|
+
} from "../lib/agent-execution-policy.js";
|
|
25
|
+
import { createReplToolExecutor } from "./repl-tool-executor.js";
|
|
21
26
|
import chalk from "chalk";
|
|
22
27
|
import fs from "fs";
|
|
23
28
|
import os from "os";
|
|
@@ -151,7 +156,6 @@ import {
|
|
|
151
156
|
AGENT_TOOLS,
|
|
152
157
|
buildSystemPrompt,
|
|
153
158
|
chatWithTools,
|
|
154
|
-
executeTool as coreExecuteTool,
|
|
155
159
|
agentLoop as coreAgentLoop,
|
|
156
160
|
formatToolArgs,
|
|
157
161
|
killAllBackgroundShellTasks,
|
|
@@ -486,6 +490,10 @@ let _respondToBash;
|
|
|
486
490
|
// ApprovalGate confirm) instead of fast-pathing it. false = unset → off.
|
|
487
491
|
let _classifyAllShell = false;
|
|
488
492
|
let _sandbox = null;
|
|
493
|
+
let _toolAdmission = null;
|
|
494
|
+
let _shellPolicyOverrides = null;
|
|
495
|
+
let _directToolExecutor = null;
|
|
496
|
+
let _unattendedActionPolicy = null;
|
|
489
497
|
// Bounded log of tool calls the agent was BLOCKED from running this session
|
|
490
498
|
// (shell-policy / ApprovalGate / settings rule / hook). Surfaced by
|
|
491
499
|
// `/permissions denials` and mirrored to `cc permissions recent`.
|
|
@@ -590,20 +598,9 @@ async function _persistAlwaysAllow(tool, args) {
|
|
|
590
598
|
* Execute a tool call — delegates to agent-core with REPL's hookDb and cwd.
|
|
591
599
|
*/
|
|
592
600
|
async function executeTool(name, args, context = {}) {
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
approvalGate: _approvalGate,
|
|
597
|
-
permissionRules: _permissionRules,
|
|
598
|
-
permissionRulesProvider: _permissionRulesProvider,
|
|
599
|
-
permissionConfirm: _permissionConfirm,
|
|
600
|
-
settingsHooks: _settingsHooks,
|
|
601
|
-
classifyAllShell: _classifyAllShell,
|
|
602
|
-
sandbox: _sandbox,
|
|
603
|
-
sessionId: context.sessionId || null,
|
|
604
|
-
sessionBudget: context.sessionBudget || null,
|
|
605
|
-
signal: context.signal || null,
|
|
606
|
-
});
|
|
601
|
+
if (!_directToolExecutor)
|
|
602
|
+
throw new Error("REPL tool executor is unavailable");
|
|
603
|
+
return _directToolExecutor(name, args, context);
|
|
607
604
|
}
|
|
608
605
|
|
|
609
606
|
/**
|
|
@@ -613,6 +610,12 @@ async function executeTool(name, args, context = {}) {
|
|
|
613
610
|
* unit-testable via the `options._coreLoop` injection seam.
|
|
614
611
|
*/
|
|
615
612
|
export async function agentLoop(messages, options) {
|
|
613
|
+
const executionPolicy = captureAgentExecutionPolicy(options);
|
|
614
|
+
options = {
|
|
615
|
+
...options,
|
|
616
|
+
...executionPolicy,
|
|
617
|
+
...resolveAgentToolSelection(executionPolicy),
|
|
618
|
+
};
|
|
616
619
|
const evolutionIngress =
|
|
617
620
|
options.evolutionIngress == null
|
|
618
621
|
? null
|
|
@@ -2931,6 +2934,11 @@ export function resolveReplPermanentMemoryStorage(
|
|
|
2931
2934
|
|
|
2932
2935
|
/** Start the agentic REPL with non-overridable production bindings. */
|
|
2933
2936
|
export async function startAgentRepl(options = {}) {
|
|
2937
|
+
const executionPolicy = captureAgentExecutionPolicy(options);
|
|
2938
|
+
options = {
|
|
2939
|
+
...options,
|
|
2940
|
+
...executionPolicy,
|
|
2941
|
+
};
|
|
2934
2942
|
const evolutionIngress =
|
|
2935
2943
|
options.evolutionIngress == null
|
|
2936
2944
|
? null
|
|
@@ -3370,6 +3378,21 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
3370
3378
|
? options.additionalDirectories
|
|
3371
3379
|
: [];
|
|
3372
3380
|
_sandbox = options.sandbox || null;
|
|
3381
|
+
_toolAdmission = options.toolAdmission;
|
|
3382
|
+
_shellPolicyOverrides = options.shellPolicyOverrides;
|
|
3383
|
+
_classifyAllShell = options.classifyAllShell === true;
|
|
3384
|
+
const toolSelection = resolveAgentToolSelection(options);
|
|
3385
|
+
_directToolExecutor = createReplToolExecutor(options, () => ({
|
|
3386
|
+
hookDb: _hookDb,
|
|
3387
|
+
cwd: process.cwd(),
|
|
3388
|
+
approvalGate: _approvalGate,
|
|
3389
|
+
permissionRules: _permissionRules,
|
|
3390
|
+
permissionRulesProvider: _permissionRulesProvider,
|
|
3391
|
+
permissionConfirm: _permissionConfirm,
|
|
3392
|
+
settingsHooks: _settingsHooks,
|
|
3393
|
+
classifyAllShell: _classifyAllShell,
|
|
3394
|
+
}));
|
|
3395
|
+
_unattendedActionPolicy = options.unattendedActionPolicy;
|
|
3373
3396
|
// Snapshot the work tree before each mutating tool (git engine) so the user
|
|
3374
3397
|
// can `cc checkpoint restore` to just before any tool call.
|
|
3375
3398
|
const autoCheckpoint = options.autoCheckpoint === true;
|
|
@@ -3728,6 +3751,7 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
3728
3751
|
});
|
|
3729
3752
|
// Claude-Code 2.1.193 autoMode.classifyAllShell (default OFF when unset).
|
|
3730
3753
|
_classifyAllShell =
|
|
3754
|
+
_classifyAllShell ||
|
|
3731
3755
|
readBooleanSetting("autoMode.classifyAllShell", {
|
|
3732
3756
|
cwd: process.cwd(),
|
|
3733
3757
|
}) === true;
|
|
@@ -9689,7 +9713,11 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
9689
9713
|
skillOutcomeIndex: options.skillOutcomeIndex,
|
|
9690
9714
|
cwd: process.cwd(),
|
|
9691
9715
|
additionalDirectories,
|
|
9716
|
+
...toolSelection,
|
|
9692
9717
|
sandbox: _sandbox,
|
|
9718
|
+
toolAdmission: _toolAdmission,
|
|
9719
|
+
shellPolicyOverrides: _shellPolicyOverrides,
|
|
9720
|
+
unattendedActionPolicy: _unattendedActionPolicy,
|
|
9693
9721
|
autoCheckpoint,
|
|
9694
9722
|
checkpointSession: sessionId,
|
|
9695
9723
|
managedCheckpoint,
|