@sema-agent/core 5.21.0 → 5.22.0
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/CHANGELOG.md +66 -0
- package/dist/agents/send-message-tool.js +6 -3
- package/dist/agents/subagent.d.ts +6 -0
- package/dist/agents/subagent.js +45 -4
- package/dist/brain/errors.d.ts +20 -0
- package/dist/brain/errors.js +40 -0
- package/dist/brain/retry.d.ts +16 -2
- package/dist/brain/retry.js +3 -2
- package/dist/brain/status-sink.d.ts +9 -2
- package/dist/brain/stream-engine.d.ts +22 -0
- package/dist/brain/stream-engine.js +41 -10
- package/dist/core/ask-class.d.ts +48 -0
- package/dist/core/ask-class.js +33 -0
- package/dist/core/checkpoint-store.d.ts +103 -10
- package/dist/core/checkpoint-store.js +3 -1
- package/dist/core/governance-codes.d.ts +38 -0
- package/dist/core/governance-codes.js +11 -0
- package/dist/core/hooks.d.ts +39 -0
- package/dist/core/hooks.js +26 -2
- package/dist/core/locked-config.d.ts +7 -1
- package/dist/core/locked-config.js +2 -1
- package/dist/core/memory-engine/delegation-provenance.d.ts +62 -0
- package/dist/core/memory-engine/delegation-provenance.js +26 -0
- package/dist/core/memory-engine/engine.d.ts +67 -1
- package/dist/core/memory-engine/engine.js +270 -12
- package/dist/core/memory-engine/header-hints.d.ts +30 -0
- package/dist/core/memory-engine/header-hints.js +41 -0
- package/dist/core/memory-engine/index.d.ts +3 -2
- package/dist/core/memory-engine/index.js +3 -2
- package/dist/core/memory-engine/layout.d.ts +166 -0
- package/dist/core/memory-engine/layout.js +399 -0
- package/dist/core/memory-engine/tools.d.ts +30 -0
- package/dist/core/memory-engine/tools.js +108 -17
- package/dist/core/permission-rule-consent.d.ts +25 -9
- package/dist/core/permission-rule-consent.js +91 -20
- package/dist/core/permission-rule-model.d.ts +9 -1
- package/dist/core/permission-rule-model.js +2 -2
- package/dist/core/permission-rule-org.d.ts +161 -0
- package/dist/core/permission-rule-org.js +211 -0
- package/dist/core/permission-rule-store.d.ts +249 -6
- package/dist/core/permission-rule-store.js +313 -3
- package/dist/core/permission-rule-sync.d.ts +131 -0
- package/dist/core/permission-rule-sync.js +314 -0
- package/dist/core/runner/prepare-memory.js +35 -8
- package/dist/core/runner/prepare-task.d.ts +54 -1
- package/dist/core/runner/prepare-task.js +246 -27
- package/dist/core/runner/runtask.js +147 -6
- package/dist/core/shared-memory/contract.js +19 -4
- package/dist/core/shared-memory/normalize.d.ts +3 -1
- package/dist/core/shared-memory/tools.js +73 -17
- package/dist/core/shared-memory/types.d.ts +27 -1
- package/dist/core/store-contracts/permission-rule-sync-contract.d.ts +33 -0
- package/dist/core/store-contracts/permission-rule-sync-contract.js +186 -0
- package/dist/core/task-notification.d.ts +5 -2
- package/dist/core/task-registry-agent.d.ts +1 -1
- package/dist/core/task-registry-agent.js +6 -2
- package/dist/core/task-registry-shared.d.ts +9 -2
- package/dist/core/task-registry.d.ts +9 -3
- package/dist/core/task-registry.js +2 -0
- package/dist/core/tool-policy.d.ts +120 -2
- package/dist/core/tool-policy.js +116 -6
- package/dist/core/trace.d.ts +32 -1
- package/dist/core/types.d.ts +56 -3
- package/dist/index.d.ts +12 -7
- package/dist/index.js +10 -5
- package/dist/stores/file/checkpoint-store.d.ts +4 -0
- package/dist/stores/file/checkpoint-store.js +1 -0
- package/dist/stores/file/permission-rule-adopt.d.ts +62 -0
- package/dist/stores/file/permission-rule-adopt.js +95 -0
- package/dist/stores/file/permission-rule-store.d.ts +80 -2
- package/dist/stores/file/permission-rule-store.js +189 -46
- package/dist/tools/fs/fs-search-tools.js +0 -1
- package/package.json +1 -1
|
@@ -20,12 +20,13 @@ import { createSubagentWorktreeHelper, forkGovernanceDenial } from "../../agents
|
|
|
20
20
|
import { createAgentTranscriptTool, AGENT_TRANSCRIPT_TOOL_NAME } from "../../agents/agent-transcript-tool.js";
|
|
21
21
|
import { createSendMessageTool, SEND_MESSAGE_TOOL_NAME } from "../../agents/send-message-tool.js";
|
|
22
22
|
import { SubagentRetainLedger } from "../../agents/retain-ledger.js";
|
|
23
|
-
import { askApproverIdentity, combinePolicies, isApprovalSettledBy, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, describeThrown, refuseOutOfContractDecision, resolveAsk, toolPolicyNameSets, tryCloneArgs } from "../tool-policy.js";
|
|
23
|
+
import { askApproverIdentity, checkToolPolicyProjection, combinePolicies, constraintChainDigest, constraintChainEntryOf, isApprovalSettledBy, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, describeThrown, refuseOutOfContractDecision, resolveAsk, toolPolicyNameSets, tryCloneArgs } from "../tool-policy.js";
|
|
24
24
|
const PERSISTED_RULE_TOOL = "Bash";
|
|
25
25
|
import { findAdmittingRule, suggestRulesForCommand } from "../permission-rule-model.js";
|
|
26
26
|
import { ActiveSkillScope, createActiveSkillScopePolicy } from "./active-skill-scope.js";
|
|
27
27
|
import { CHANGED_FILES_MTIME_EPS_MS, fenceMcpServerInstructions, renderAgentListingDelta } from "./turn-attachments.js";
|
|
28
28
|
import { inlineUntrusted } from "../untrusted-text.js";
|
|
29
|
+
import { policyAskClassOf } from "../ask-class.js";
|
|
29
30
|
import { emitTrace } from "../trace.js";
|
|
30
31
|
import { createSessionRulePolicy } from "./session-rule-policy.js";
|
|
31
32
|
import { cloneObserverInput, createHookEnvCapabilities, createPreToolUseConstraintPolicy, formatHookFeedback, runToolGate } from "../hooks.js";
|
|
@@ -46,6 +47,7 @@ import { SHARED_MEMORY_TOOL_NAMES } from "../shared-memory/types.js";
|
|
|
46
47
|
import { MEMORY_ENGINE_TOOL_NAMES } from "../memory-engine/tools.js";
|
|
47
48
|
import { MEMORY_RECALL_DISCIPLINE } from "../memory-engine/engine.js";
|
|
48
49
|
import { classifyToolContentOrigin, contentOriginPollutes, delegationCallIsExternal } from "../memory-engine/content-origin.js";
|
|
50
|
+
import { narrowContentSafety, readCardAttestation } from "../memory-engine/delegation-provenance.js";
|
|
49
51
|
import { composeMemoryBlock } from "../memory.js";
|
|
50
52
|
import { preflightLockedConfig } from "../locked-config.js";
|
|
51
53
|
import { COMPLIANCE_CAPABILITIES, WEB_FETCH_TOOL_NAME, complianceCallDenial, resolveComplianceDenies } from "../compliance.js";
|
|
@@ -82,7 +84,7 @@ import { resolveWorkflowSizeGuideline } from "../../orchestration/workflow-size-
|
|
|
82
84
|
import { createLspTool, gitCheckIgnoreFilter, resolveLspPath } from "../lsp.js";
|
|
83
85
|
import { resolveKey } from "../../tools/fs/safety.js";
|
|
84
86
|
import { wholeFileRecordsFromTranscript } from "./session-file-state-replay.js";
|
|
85
|
-
import { BINDING_CHECKPOINT_VERSION, mintCheckpointToken, ORG_ADMISSION_CHECKPOINT_VERSION, RESOURCE_CHECKPOINT_VERSION, TOKEN_CHECKPOINT_VERSION, buildRiskDescriptor, debitLedger, encodeAtFidelity, remainingBudgetMicroUsd, resolveCheckpointStore, resolveDeclaredFidelity, samePlainValue, } from "../checkpoint-store.js";
|
|
87
|
+
import { BINDING_CHECKPOINT_VERSION, mintCheckpointToken, ORG_ADMISSION_CHECKPOINT_VERSION, F012_CHECKPOINT_VERSION, RESOURCE_CHECKPOINT_VERSION, TOKEN_CHECKPOINT_VERSION, buildRiskDescriptor, debitLedger, encodeAtFidelity, remainingBudgetMicroUsd, resolveCheckpointStore, resolveDeclaredFidelity, samePlainValue, } from "../checkpoint-store.js";
|
|
86
88
|
import { boundInputHashOf } from "../canonical-json.js";
|
|
87
89
|
import { countElicitOptIns, deriveAskEffective, deriveWiringManifest, resolveAskSeamForm, resolveDeclaredDurability, resolveElicitSeam, resolveQuestionSeam } from "../wiring-manifest.js";
|
|
88
90
|
import { GLOBAL_USAGE_KEY, resolveUsageWindows, usageRetryAfterMs } from "../usage-window-store.js";
|
|
@@ -1057,6 +1059,9 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1057
1059
|
const memoryAdmittedOrgScopesRef = { current: [] };
|
|
1058
1060
|
const ownOrgVerdictRef = { current: undefined };
|
|
1059
1061
|
const orgAdmissionCheckpointState = () => inheritedAdmittedOrgScopes !== undefined || ownOrgVerdictRef.current !== undefined || orgGovernedProvenance;
|
|
1062
|
+
const f012CheckpointState = () => (inheritedParentConstraints?.length ?? 0) > 0 ||
|
|
1063
|
+
seedInheritedGate?.constraintChain !== undefined ||
|
|
1064
|
+
internals?.delegationProvenance !== undefined;
|
|
1060
1065
|
const frozenOnAsk = spec.onAsk ?? deps.onAsk;
|
|
1061
1066
|
const hookEnvSource = (ownedEnv ?? deps.executionEnv) != null ? executionEnv : undefined;
|
|
1062
1067
|
const notifyOwnHookCrash = (err) => {
|
|
@@ -1067,6 +1072,8 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1067
1072
|
}
|
|
1068
1073
|
};
|
|
1069
1074
|
const frozenOnQuestion = spec.onQuestion ?? deps.onQuestion;
|
|
1075
|
+
const provenanceForChildrenRef = {};
|
|
1076
|
+
const delegationProvenanceForChildren = () => provenanceForChildrenRef.current;
|
|
1070
1077
|
const inheritedGateForChildren = () => {
|
|
1071
1078
|
const ancestorRules = [
|
|
1072
1079
|
...(inheritedAncestorRules ?? []),
|
|
@@ -1075,12 +1082,16 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1075
1082
|
const ownCallerPolicy = lockedPreflight.toolPolicy;
|
|
1076
1083
|
const durableMandate = runtimeCaps?.forceDurableGate === true ||
|
|
1077
1084
|
(spec.durableApproval !== undefined && !isLiveApproverSeat(frozenOnAsk));
|
|
1085
|
+
const contentMandate = runtimeCaps?.forceDurableGate === true ||
|
|
1086
|
+
(spec.durableApproval !== undefined && !isLiveQuestionFace(frozenOnQuestion));
|
|
1078
1087
|
const ownPreToolUse = preToolUseObservational ? undefined : hooks?.preToolUse;
|
|
1079
1088
|
const hookConstraint = ownPreToolUse !== undefined &&
|
|
1080
1089
|
!(inheritedParentConstraints ?? []).some((pc) => pc.preToolUse === ownPreToolUse &&
|
|
1081
1090
|
askApproverIdentity(pc.onAsk) === askApproverIdentity(frozenOnAsk) &&
|
|
1082
1091
|
(pc.durableMandate === true) === durableMandate &&
|
|
1083
|
-
pc.
|
|
1092
|
+
(pc.contentMandate === true) === contentMandate &&
|
|
1093
|
+
pc.hookEnv === hookEnvSource &&
|
|
1094
|
+
pc.autoMode?.decider === autoModeDecider)
|
|
1084
1095
|
? [
|
|
1085
1096
|
{
|
|
1086
1097
|
policy: createPreToolUseConstraintPolicy(ownPreToolUse, hookEnvFace, notifyOwnHookCrash),
|
|
@@ -1088,6 +1099,8 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1088
1099
|
...(hookEnvSource !== undefined ? { hookEnv: hookEnvSource } : {}),
|
|
1089
1100
|
...(frozenOnAsk !== undefined ? { onAsk: frozenOnAsk } : {}),
|
|
1090
1101
|
...(durableMandate ? { durableMandate: true } : {}),
|
|
1102
|
+
...(contentMandate ? { contentMandate: true } : {}),
|
|
1103
|
+
...(autoModeDecider !== undefined ? { autoMode: { decider: autoModeDecider } } : {}),
|
|
1091
1104
|
},
|
|
1092
1105
|
]
|
|
1093
1106
|
: [];
|
|
@@ -1100,6 +1113,8 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1100
1113
|
policy: ownCallerPolicy,
|
|
1101
1114
|
...(frozenOnAsk !== undefined ? { onAsk: frozenOnAsk } : {}),
|
|
1102
1115
|
...(durableMandate ? { durableMandate: true } : {}),
|
|
1116
|
+
...(contentMandate ? { contentMandate: true } : {}),
|
|
1117
|
+
...(autoModeDecider !== undefined ? { autoMode: { decider: autoModeDecider } } : {}),
|
|
1103
1118
|
},
|
|
1104
1119
|
]
|
|
1105
1120
|
: []),
|
|
@@ -1140,6 +1155,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1140
1155
|
...(centerAdoption?.sourceRevision !== undefined ? { centerSourceRevision: centerAdoption.sourceRevision } : {}),
|
|
1141
1156
|
activeSkillScope: () => skillScope.active(),
|
|
1142
1157
|
inheritedGateForChildren,
|
|
1158
|
+
delegationProvenanceForChildren,
|
|
1143
1159
|
...(autoModeDecider ? { autoModeReview: { decider: autoModeDecider } } : {}),
|
|
1144
1160
|
...(spec.durableApproval !== undefined ? { durableApprovalForChildren: { ...spec.durableApproval } } : {}),
|
|
1145
1161
|
...(spec.checkpointStore === null ? { checkpointStoreDisabledForChildren: true } : {}),
|
|
@@ -1939,6 +1955,19 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1939
1955
|
if (internals?.ownOrgAdmissionRef !== undefined && ownOrgVerdictRef.current !== undefined) {
|
|
1940
1956
|
internals.ownOrgAdmissionRef.current = ownOrgVerdictRef.current;
|
|
1941
1957
|
}
|
|
1958
|
+
if (internals?.delegationProvenance !== undefined && resume !== undefined) {
|
|
1959
|
+
const live = internals.delegationProvenance.ref.current;
|
|
1960
|
+
const seed = resume.seed.delegationProvenance;
|
|
1961
|
+
if (seed === undefined || seed.version !== 1 || seed.coverageStartTurn !== 0) {
|
|
1962
|
+
live.incomplete = true;
|
|
1963
|
+
}
|
|
1964
|
+
else {
|
|
1965
|
+
if (seed.sawExternal)
|
|
1966
|
+
live.sawExternal = true;
|
|
1967
|
+
if (seed.incomplete)
|
|
1968
|
+
live.incomplete = true;
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1942
1971
|
let memoryBlock = memoryBlockFromEngine;
|
|
1943
1972
|
if (memorySeedFiles?.length && seedContextFiles) {
|
|
1944
1973
|
try {
|
|
@@ -2312,15 +2341,28 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2312
2341
|
else {
|
|
2313
2342
|
deferred = classifyDeferredOverFace(tools, []);
|
|
2314
2343
|
}
|
|
2315
|
-
|
|
2316
|
-
|
|
2344
|
+
const delegationProvenanceChannel = internals?.delegationProvenance;
|
|
2345
|
+
if (memoryEngineSession !== undefined || delegationProvenanceChannel !== undefined) {
|
|
2346
|
+
const pollution = memoryEngineSession?.pollution;
|
|
2347
|
+
const effectiveSafety = narrowContentSafety(delegationProvenanceChannel?.contentSafety, memoryEngineSession?.contentSafety);
|
|
2348
|
+
const trustedTools = effectiveSafety.trustedTools;
|
|
2349
|
+
const execIsExternalContent = effectiveSafety.execIsExternalContent;
|
|
2350
|
+
provenanceForChildrenRef.current = { trustedTools: [...trustedTools], execIsExternalContent };
|
|
2351
|
+
const recordExternal = () => {
|
|
2352
|
+
if (delegationProvenanceChannel !== undefined)
|
|
2353
|
+
delegationProvenanceChannel.ref.current.sawExternal = true;
|
|
2354
|
+
};
|
|
2355
|
+
const recordIncomplete = () => {
|
|
2356
|
+
if (delegationProvenanceChannel !== undefined)
|
|
2357
|
+
delegationProvenanceChannel.ref.current.incomplete = true;
|
|
2358
|
+
};
|
|
2317
2359
|
const callerToolNames = new Set((spec.tools ?? []).map((t) => t.name));
|
|
2318
2360
|
const contentOriginWrapped = new WeakSet();
|
|
2319
2361
|
const classOf = (t) => classifyToolContentOrigin({
|
|
2320
2362
|
declared: t.contentOrigin,
|
|
2321
2363
|
isProtocolTool: protocolOf(t.name) !== undefined,
|
|
2322
2364
|
isCallerTool: callerToolNames.has(t.name),
|
|
2323
|
-
trusted:
|
|
2365
|
+
trusted: trustedTools.has(t.name),
|
|
2324
2366
|
});
|
|
2325
2367
|
const delegationByName = new Map();
|
|
2326
2368
|
for (const t of spec.tools ?? []) {
|
|
@@ -2333,8 +2375,8 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2333
2375
|
declared: t.contentOrigin,
|
|
2334
2376
|
isProtocolTool: protocolOf(t.name) !== undefined,
|
|
2335
2377
|
isCallerTool: true,
|
|
2336
|
-
trusted:
|
|
2337
|
-
}),
|
|
2378
|
+
trusted: trustedTools.has(t.name),
|
|
2379
|
+
}), execIsExternalContent);
|
|
2338
2380
|
contentOriginWrapRef.current = () => {
|
|
2339
2381
|
for (let i = 0; i < tools.length; i++) {
|
|
2340
2382
|
const t = tools[i];
|
|
@@ -2343,7 +2385,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2343
2385
|
const origin = classOf(t);
|
|
2344
2386
|
const delegation = delegationByName.get(t.name);
|
|
2345
2387
|
const isDelegation = delegation !== undefined;
|
|
2346
|
-
const pollutes = contentOriginPollutes(origin,
|
|
2388
|
+
const pollutes = contentOriginPollutes(origin, execIsExternalContent);
|
|
2347
2389
|
if (!pollutes && !isDelegation) {
|
|
2348
2390
|
contentOriginWrapped.add(t);
|
|
2349
2391
|
continue;
|
|
@@ -2351,7 +2393,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2351
2393
|
const inner = t.execute.bind(t);
|
|
2352
2394
|
const mark = (reason) => {
|
|
2353
2395
|
try {
|
|
2354
|
-
pollution
|
|
2396
|
+
pollution?.markPolluted(reason);
|
|
2355
2397
|
}
|
|
2356
2398
|
catch {
|
|
2357
2399
|
}
|
|
@@ -2359,8 +2401,10 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2359
2401
|
const wrapped = {
|
|
2360
2402
|
...t,
|
|
2361
2403
|
execute: async (toolCallId, params, signal, onUpdate) => {
|
|
2362
|
-
if (pollutes)
|
|
2404
|
+
if (pollutes) {
|
|
2363
2405
|
mark(`tool "${t.name}" (${origin} content class) was invoked in this session`);
|
|
2406
|
+
recordExternal();
|
|
2407
|
+
}
|
|
2364
2408
|
if (!isDelegation)
|
|
2365
2409
|
return inner(toolCallId, params, signal, onUpdate);
|
|
2366
2410
|
const requested = params?.subagent_type;
|
|
@@ -2371,9 +2415,18 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2371
2415
|
isPolluting: poolToolPollutes,
|
|
2372
2416
|
});
|
|
2373
2417
|
const result = await inner(toolCallId, params, signal, onUpdate);
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2418
|
+
const att = readCardAttestation(result?.details);
|
|
2419
|
+
if (att === "external") {
|
|
2420
|
+
mark(`tool "${t.name}" returned the output of a delegated agent that invoked an external-content-class tool at runtime` +
|
|
2421
|
+
(typeof requested === "string" ? ` (subagent_type "${requested}")` : ""));
|
|
2422
|
+
recordExternal();
|
|
2423
|
+
}
|
|
2424
|
+
else if (att !== "clean") {
|
|
2425
|
+
if (external) {
|
|
2426
|
+
mark(`tool "${t.name}" returned the output of a delegated agent whose tool face can reach external content` +
|
|
2427
|
+
(typeof requested === "string" ? ` (subagent_type "${requested}")` : " (no subagent_type named — classified fail-closed)"));
|
|
2428
|
+
}
|
|
2429
|
+
recordIncomplete();
|
|
2377
2430
|
}
|
|
2378
2431
|
return result;
|
|
2379
2432
|
},
|
|
@@ -2941,11 +2994,16 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2941
2994
|
toolEffects,
|
|
2942
2995
|
})
|
|
2943
2996
|
: undefined;
|
|
2944
|
-
const
|
|
2997
|
+
const frozenConstraintLayers = (seedInheritedGate?.constraintChain ?? [])
|
|
2998
|
+
.filter((e) => !("opaque" in e))
|
|
2999
|
+
.map((entry) => ({
|
|
3000
|
+
check: (creq) => checkToolPolicyProjection(entry, creq) ?? { action: "allow" },
|
|
3001
|
+
}));
|
|
3002
|
+
const narrowingLayers = [sessionRulePolicy, ...ancestorRulePolicies, ...frozenConstraintLayers, skillScopePolicy].filter((p) => p !== undefined);
|
|
2945
3003
|
for (const layer of narrowingLayers)
|
|
2946
3004
|
auditPolicyNames(layer);
|
|
2947
3005
|
const denyNarrowingPolicy = narrowingLayers.length === 0 ? undefined : narrowingLayers.length === 1 ? narrowingLayers[0] : combinePolicies(...narrowingLayers);
|
|
2948
|
-
const basePolicyForResumeEdit = lockedPreflight.toolPolicy;
|
|
3006
|
+
const basePolicyForResumeEdit = lockedPreflight.basePolicyForResumeEdit ?? lockedPreflight.toolPolicy;
|
|
2949
3007
|
const hooks = spec.hooks ?? deps.hooks;
|
|
2950
3008
|
const preToolUseObservational = hooks?.preToolUse !== undefined && hooks.preToolUseObservational === true;
|
|
2951
3009
|
const ownGatePreToolUse = !preToolUseObservational
|
|
@@ -2997,6 +3055,62 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2997
3055
|
return;
|
|
2998
3056
|
inheritedAskGrants.set(toolCallId, { approver, argsJson, presented, waitMs });
|
|
2999
3057
|
};
|
|
3058
|
+
const sandboxDeclared = isIsolated(executionEnv);
|
|
3059
|
+
const sandboxAdmissionArmed = (() => {
|
|
3060
|
+
if (!sandboxDeclared)
|
|
3061
|
+
return false;
|
|
3062
|
+
const store = resolveCheckpointStore(spec, deps);
|
|
3063
|
+
const missing = [];
|
|
3064
|
+
if (store === undefined)
|
|
3065
|
+
missing.push("a wired CheckpointStore");
|
|
3066
|
+
else if (store.redecision?.reopen !== true)
|
|
3067
|
+
missing.push("a CheckpointStore that DECLARES redecision.reopen (declaration, never duck-typing)");
|
|
3068
|
+
if (spec.durableApproval === undefined && runtimeCaps?.forceDurableGate !== true)
|
|
3069
|
+
missing.push("a durable park (spec.durableApproval, or the forceDurableGate entitlement)");
|
|
3070
|
+
if (missing.length === 0)
|
|
3071
|
+
return true;
|
|
3072
|
+
try {
|
|
3073
|
+
const e = new Error(`sandbox admission mode NOT armed: the execution env declares an isolated sandbox (capabilities.isolation), but the mode's ` +
|
|
3074
|
+
`park prerequisites are missing — ${missing.join("; ")}. Asks keep the conservative default chain (no auto-admission, no boundary park).`);
|
|
3075
|
+
e.code = "config.sandbox_admission_unavailable";
|
|
3076
|
+
deps.onError?.(e, { phase: "config", sessionId, classification: "sandbox-admission-unavailable" });
|
|
3077
|
+
}
|
|
3078
|
+
catch {
|
|
3079
|
+
}
|
|
3080
|
+
return false;
|
|
3081
|
+
})();
|
|
3082
|
+
const foldAskClasses = new Map();
|
|
3083
|
+
const FOLD_ASK_CLASSES_CAP = 256;
|
|
3084
|
+
const recordFoldAskClass = (toolCallId, cls, layer) => {
|
|
3085
|
+
if (!foldAskClasses.has(toolCallId) && foldAskClasses.size >= FOLD_ASK_CLASSES_CAP)
|
|
3086
|
+
return;
|
|
3087
|
+
const list = foldAskClasses.get(toolCallId) ?? [];
|
|
3088
|
+
list.push({ cls, layer });
|
|
3089
|
+
foldAskClasses.set(toolCallId, list);
|
|
3090
|
+
};
|
|
3091
|
+
const sandboxBoundaryCapable = (toolName) => egressTools.has(toolName) || toolName.includes("__") || ownToolNames.has(toolName);
|
|
3092
|
+
const emitSandboxAdmitted = (info) => {
|
|
3093
|
+
emitTrace(deps.tracer, () => ({
|
|
3094
|
+
kind: "permission.sandbox_admitted",
|
|
3095
|
+
version: 1,
|
|
3096
|
+
taskId: spec.taskId ?? sessionId,
|
|
3097
|
+
toolCallId: info.toolCallId,
|
|
3098
|
+
toolName: info.toolName,
|
|
3099
|
+
askClasses: info.askClasses.map((a) => a.cls),
|
|
3100
|
+
sourceLayers: info.askClasses.map((a) => a.layer),
|
|
3101
|
+
boundary: info.boundary,
|
|
3102
|
+
ts: Date.now(),
|
|
3103
|
+
}));
|
|
3104
|
+
};
|
|
3105
|
+
const ancestorSandboxAdmissions = new Map();
|
|
3106
|
+
const recordAncestorSandboxAdmission = (toolCallId, toolName) => {
|
|
3107
|
+
const list = ancestorSandboxAdmissions.get(toolCallId);
|
|
3108
|
+
if (list !== undefined)
|
|
3109
|
+
list.push({ cls: "sandbox_local", layer: "ancestor_constraint" });
|
|
3110
|
+
else
|
|
3111
|
+
ancestorSandboxAdmissions.set(toolCallId, [{ cls: "sandbox_local", layer: "ancestor_constraint" }]);
|
|
3112
|
+
void toolName;
|
|
3113
|
+
};
|
|
3000
3114
|
const callerPolicyLayer = policy !== undefined && sameInstanceAncestorCount > 0
|
|
3001
3115
|
? {
|
|
3002
3116
|
check: async (creq, csignal) => {
|
|
@@ -3069,7 +3183,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3069
3183
|
const suggestions = suggestRulesForCommand(command);
|
|
3070
3184
|
return suggestions.length > 0 ? { ruleSuggestions: suggestions } : {};
|
|
3071
3185
|
};
|
|
3072
|
-
const recheckApprovedEdit = async (pol, onAskOf, creq, edit, csignal) => {
|
|
3186
|
+
const recheckApprovedEdit = async (pol, onAskOf, creq, edit, csignal, ancestorDecider) => {
|
|
3073
3187
|
let editArgs = edit;
|
|
3074
3188
|
for (let round = 0;; round++) {
|
|
3075
3189
|
if (round >= 3) {
|
|
@@ -3095,6 +3209,22 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3095
3209
|
}
|
|
3096
3210
|
if (re.updatedInput !== undefined)
|
|
3097
3211
|
editArgs = re.updatedInput;
|
|
3212
|
+
if (ancestorDecider !== undefined) {
|
|
3213
|
+
const verdict = await ancestorDecider
|
|
3214
|
+
.decide({ req: { ...creq, args: editArgs }, ...(re.message !== undefined ? { askMessage: re.message } : {}) }, csignal ?? abortController.signal)
|
|
3215
|
+
.catch(() => ({ kind: "unavailable", cause: "error" }));
|
|
3216
|
+
if (verdict.kind === "allow")
|
|
3217
|
+
return { action: "allow", updatedInput: editArgs };
|
|
3218
|
+
if (verdict.kind === "block") {
|
|
3219
|
+
const reason = verdict.reason ? inlineUntrusted(verdict.reason) : "";
|
|
3220
|
+
const category = verdict.category ? inlineUntrusted(verdict.category) : "";
|
|
3221
|
+
return {
|
|
3222
|
+
action: "deny",
|
|
3223
|
+
message: `auto-mode classifier blocked the approved edit at an inherited ancestor layer${reason ? `: ${reason}` : category ? `: [${category}]` : ""}`,
|
|
3224
|
+
decisionReason: "classifier",
|
|
3225
|
+
};
|
|
3226
|
+
}
|
|
3227
|
+
}
|
|
3098
3228
|
const rr = await resolveAsk({
|
|
3099
3229
|
toolName: creq.toolName,
|
|
3100
3230
|
toolCallId: creq.toolCallId,
|
|
@@ -3116,8 +3246,10 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3116
3246
|
pc.preToolUse === hooks?.preToolUse &&
|
|
3117
3247
|
!preToolUseObservational &&
|
|
3118
3248
|
pc.durableMandate !== true &&
|
|
3249
|
+
pc.contentMandate !== true &&
|
|
3119
3250
|
askApproverIdentity(pc.onAsk) === askApproverIdentity(frozenOnAsk) &&
|
|
3120
|
-
pc.hookEnv === hookEnvSource
|
|
3251
|
+
pc.hookEnv === hookEnvSource &&
|
|
3252
|
+
pc.autoMode?.decider === autoModeDecider
|
|
3121
3253
|
? { check: () => ({ action: "allow" }) }
|
|
3122
3254
|
: policy !== undefined && pc.policy === policy
|
|
3123
3255
|
? {
|
|
@@ -3134,8 +3266,14 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3134
3266
|
return first;
|
|
3135
3267
|
if (first.action === "allow")
|
|
3136
3268
|
return { action: "allow" };
|
|
3137
|
-
if (creq.toolName === ASK_USER_QUESTION_TOOL_NAME
|
|
3138
|
-
|
|
3269
|
+
if (creq.toolName === ASK_USER_QUESTION_TOOL_NAME) {
|
|
3270
|
+
if (pc.contentMandate !== true || markInheritedUnavailable(creq.toolCallId))
|
|
3271
|
+
return first;
|
|
3272
|
+
return {
|
|
3273
|
+
action: "deny",
|
|
3274
|
+
message: `inherited parent policy requires durable handling of the question raised for "${creq.toolName}" and the marker channel is at capacity — ` +
|
|
3275
|
+
`denied fail-closed (tighten-only)`,
|
|
3276
|
+
};
|
|
3139
3277
|
}
|
|
3140
3278
|
if (pc.durableMandate === true) {
|
|
3141
3279
|
if (resolveCheckpointStore(spec, deps) !== undefined &&
|
|
@@ -3149,6 +3287,26 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3149
3287
|
`ask cannot be reconstructed in a delegated child; denied fail-closed (tighten-only)`,
|
|
3150
3288
|
};
|
|
3151
3289
|
}
|
|
3290
|
+
if (pc.autoMode !== undefined) {
|
|
3291
|
+
const verdict = await pc.autoMode.decider
|
|
3292
|
+
.decide({ req: creq, ...(first.message !== undefined ? { askMessage: first.message } : {}) }, csignal ?? abortController.signal)
|
|
3293
|
+
.catch(() => ({ kind: "unavailable", cause: "error" }));
|
|
3294
|
+
if (verdict.kind === "allow")
|
|
3295
|
+
return { action: "allow" };
|
|
3296
|
+
if (verdict.kind === "block") {
|
|
3297
|
+
const reason = verdict.reason ? inlineUntrusted(verdict.reason) : "";
|
|
3298
|
+
const category = verdict.category ? inlineUntrusted(verdict.category) : "";
|
|
3299
|
+
return {
|
|
3300
|
+
action: "deny",
|
|
3301
|
+
message: `auto-mode classifier blocked this call at an inherited ancestor layer${reason ? `: ${reason}` : category ? `: [${category}]` : ""}`,
|
|
3302
|
+
decisionReason: "classifier",
|
|
3303
|
+
};
|
|
3304
|
+
}
|
|
3305
|
+
}
|
|
3306
|
+
if (sandboxAdmissionArmed && policyAskClassOf(pc.policy) === "sandbox_local" && !sandboxBoundaryCapable(creq.toolName)) {
|
|
3307
|
+
recordAncestorSandboxAdmission(creq.toolCallId, creq.toolName);
|
|
3308
|
+
return { action: "allow" };
|
|
3309
|
+
}
|
|
3152
3310
|
const presentedArgs = creq.args;
|
|
3153
3311
|
const askT0 = now();
|
|
3154
3312
|
const resolved = await resolveAsk({
|
|
@@ -3173,7 +3331,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3173
3331
|
if (resolved.action !== "allow")
|
|
3174
3332
|
return resolved;
|
|
3175
3333
|
if (resolved.updatedInput !== undefined) {
|
|
3176
|
-
return recheckApprovedEdit(pc.policy, pc.onAsk, creq, resolved.updatedInput, csignal);
|
|
3334
|
+
return recheckApprovedEdit(pc.policy, pc.onAsk, creq, resolved.updatedInput, csignal, pc.autoMode?.decider);
|
|
3177
3335
|
}
|
|
3178
3336
|
recordInheritedAskGrant(creq.toolCallId, pc.onAsk, resolved.presentedInput, askWaitMs);
|
|
3179
3337
|
return { action: "allow" };
|
|
@@ -3193,8 +3351,14 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3193
3351
|
}
|
|
3194
3352
|
if (decision.action !== "ask")
|
|
3195
3353
|
return decision;
|
|
3196
|
-
if (creq.toolName === ASK_USER_QUESTION_TOOL_NAME
|
|
3197
|
-
|
|
3354
|
+
if (creq.toolName === ASK_USER_QUESTION_TOOL_NAME) {
|
|
3355
|
+
if (pc.contentMandate !== true || markInheritedUnavailable(creq.toolCallId))
|
|
3356
|
+
return decision;
|
|
3357
|
+
return {
|
|
3358
|
+
action: "deny",
|
|
3359
|
+
message: `inherited parent policy requires durable handling of the question raised for "${creq.toolName}" and the marker channel is at capacity — ` +
|
|
3360
|
+
`denied fail-closed (tighten-only)`,
|
|
3361
|
+
};
|
|
3198
3362
|
}
|
|
3199
3363
|
if (pc.durableMandate === true) {
|
|
3200
3364
|
if (resolveCheckpointStore(spec, deps) !== undefined &&
|
|
@@ -3209,6 +3373,27 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3209
3373
|
};
|
|
3210
3374
|
}
|
|
3211
3375
|
const presentedArgs = decision.updatedInput !== undefined ? decision.updatedInput : creq.args;
|
|
3376
|
+
if (pc.autoMode !== undefined) {
|
|
3377
|
+
const verdict = await pc.autoMode.decider
|
|
3378
|
+
.decide({ req: { ...creq, args: presentedArgs }, ...(decision.message !== undefined ? { askMessage: decision.message } : {}) }, csignal ?? abortController.signal)
|
|
3379
|
+
.catch(() => ({ kind: "unavailable", cause: "error" }));
|
|
3380
|
+
if (verdict.kind === "allow") {
|
|
3381
|
+
return decision.updatedInput !== undefined ? { action: "allow", updatedInput: decision.updatedInput } : { action: "allow" };
|
|
3382
|
+
}
|
|
3383
|
+
if (verdict.kind === "block") {
|
|
3384
|
+
const reason = verdict.reason ? inlineUntrusted(verdict.reason) : "";
|
|
3385
|
+
const category = verdict.category ? inlineUntrusted(verdict.category) : "";
|
|
3386
|
+
return {
|
|
3387
|
+
action: "deny",
|
|
3388
|
+
message: `auto-mode classifier blocked this call at an inherited ancestor layer${reason ? `: ${reason}` : category ? `: [${category}]` : ""}`,
|
|
3389
|
+
decisionReason: "classifier",
|
|
3390
|
+
};
|
|
3391
|
+
}
|
|
3392
|
+
}
|
|
3393
|
+
if (sandboxAdmissionArmed && policyAskClassOf(pc.policy) === "sandbox_local" && !sandboxBoundaryCapable(creq.toolName)) {
|
|
3394
|
+
recordAncestorSandboxAdmission(creq.toolCallId, creq.toolName);
|
|
3395
|
+
return decision.updatedInput !== undefined ? { action: "allow", updatedInput: decision.updatedInput } : { action: "allow" };
|
|
3396
|
+
}
|
|
3212
3397
|
const askT0 = now();
|
|
3213
3398
|
const resolved = await resolveAsk({
|
|
3214
3399
|
toolName: creq.toolName,
|
|
@@ -3232,7 +3417,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3232
3417
|
if (resolved.action !== "allow")
|
|
3233
3418
|
return resolved;
|
|
3234
3419
|
if (resolved.updatedInput !== undefined) {
|
|
3235
|
-
return recheckApprovedEdit(pc.policy, pc.onAsk, creq, resolved.updatedInput, csignal);
|
|
3420
|
+
return recheckApprovedEdit(pc.policy, pc.onAsk, creq, resolved.updatedInput, csignal, pc.autoMode?.decider);
|
|
3236
3421
|
}
|
|
3237
3422
|
if (pc.preToolUse === undefined) {
|
|
3238
3423
|
recordInheritedAskGrant(creq.toolCallId, pc.onAsk, resolved.presentedInput, askWaitMs);
|
|
@@ -3257,6 +3442,9 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3257
3442
|
const d = await layer.check(creq, csignal);
|
|
3258
3443
|
if (d.updatedInput !== undefined)
|
|
3259
3444
|
rewriteEmitterIndex.set(creq.toolCallId, idx);
|
|
3445
|
+
if (d.action === "ask") {
|
|
3446
|
+
recordFoldAskClass(creq.toolCallId, idx < callerSlotOffset ? policyAskClassOf(policy) : "mandate", idx < callerSlotOffset ? "caller_policy" : "ancestor_constraint");
|
|
3447
|
+
}
|
|
3260
3448
|
return d;
|
|
3261
3449
|
},
|
|
3262
3450
|
}));
|
|
@@ -3607,6 +3795,12 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3607
3795
|
inheritedGate: (() => {
|
|
3608
3796
|
const requiresParentConstraint = (inheritedParentConstraints?.length ?? 0) > 0 || seedInheritedGate?.requiresParentConstraint === true;
|
|
3609
3797
|
const parentConstraintCount = (inheritedParentConstraints?.length ?? 0) > 0 ? inheritedParentConstraints.length : seedInheritedGate?.parentConstraintCount;
|
|
3798
|
+
const constraintChain = (inheritedParentConstraints?.length ?? 0) > 0
|
|
3799
|
+
? inheritedParentConstraints.map((pc) => constraintChainEntryOf(pc.policy, { ...(pc.autoMode !== undefined ? { autoModeArmed: true } : {}), ...(pc.durableMandate === true ? { durableMandate: true } : {}), ...(pc.contentMandate === true ? { contentMandate: true } : {}) }))
|
|
3800
|
+
: seedInheritedGate?.constraintChain;
|
|
3801
|
+
const constraintDigest = (inheritedParentConstraints?.length ?? 0) > 0
|
|
3802
|
+
? constraintChainDigest(constraintChain)
|
|
3803
|
+
: seedInheritedGate?.constraintDigest;
|
|
3610
3804
|
return inheritedAncestorRules !== undefined ||
|
|
3611
3805
|
inheritedShellGate !== undefined ||
|
|
3612
3806
|
inheritedAdmittedOrgScopes !== undefined ||
|
|
@@ -3623,6 +3817,9 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3623
3817
|
...(orgGovernedProvenance ? { orgAdmissionGoverned: true } : {}),
|
|
3624
3818
|
requiresParentConstraint,
|
|
3625
3819
|
...(requiresParentConstraint && parentConstraintCount !== undefined ? { parentConstraintCount } : {}),
|
|
3820
|
+
...(requiresParentConstraint && constraintChain !== undefined
|
|
3821
|
+
? { constraintChain: structuredClone(constraintChain), ...(constraintDigest !== undefined ? { constraintDigest } : {}) }
|
|
3822
|
+
: {}),
|
|
3626
3823
|
}
|
|
3627
3824
|
: undefined;
|
|
3628
3825
|
})(),
|
|
@@ -3633,6 +3830,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3633
3830
|
...(announcedListingsRef.models !== undefined ? { models: [...announcedListingsRef.models] } : {}),
|
|
3634
3831
|
}
|
|
3635
3832
|
: undefined,
|
|
3833
|
+
delegationProvenance: internals?.delegationProvenance !== undefined ? { ...internals.delegationProvenance.ref.current } : undefined,
|
|
3636
3834
|
});
|
|
3637
3835
|
const commitSuspendSaga = async (token, cp, remoteEnv, remoteHandle) => {
|
|
3638
3836
|
if (!checkpointStore)
|
|
@@ -3752,7 +3950,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3752
3950
|
const mintedAt = Date.now();
|
|
3753
3951
|
const cp = {
|
|
3754
3952
|
token,
|
|
3755
|
-
version: orgAdmissionCheckpointState() ? ORG_ADMISSION_CHECKPOINT_VERSION : resourceLedgerOut.totalTokens !== undefined ? TOKEN_CHECKPOINT_VERSION : RESOURCE_CHECKPOINT_VERSION,
|
|
3953
|
+
version: f012CheckpointState() ? F012_CHECKPOINT_VERSION : orgAdmissionCheckpointState() ? ORG_ADMISSION_CHECKPOINT_VERSION : resourceLedgerOut.totalTokens !== undefined ? TOKEN_CHECKPOINT_VERSION : RESOURCE_CHECKPOINT_VERSION,
|
|
3756
3954
|
scope,
|
|
3757
3955
|
sessionId,
|
|
3758
3956
|
leafId,
|
|
@@ -3834,7 +4032,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3834
4032
|
const mintedAt = Date.now();
|
|
3835
4033
|
const cp = {
|
|
3836
4034
|
token,
|
|
3837
|
-
version: orgAdmissionCheckpointState() ? ORG_ADMISSION_CHECKPOINT_VERSION : reviewLedger.totalTokens !== undefined ? TOKEN_CHECKPOINT_VERSION : BINDING_CHECKPOINT_VERSION,
|
|
4035
|
+
version: f012CheckpointState() ? F012_CHECKPOINT_VERSION : orgAdmissionCheckpointState() ? ORG_ADMISSION_CHECKPOINT_VERSION : reviewLedger.totalTokens !== undefined ? TOKEN_CHECKPOINT_VERSION : BINDING_CHECKPOINT_VERSION,
|
|
3838
4036
|
scope,
|
|
3839
4037
|
sessionId,
|
|
3840
4038
|
leafId,
|
|
@@ -3983,6 +4181,10 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3983
4181
|
}
|
|
3984
4182
|
const parkedArgs = captured.value;
|
|
3985
4183
|
const projectionMovedArgs = backendFidelity !== "structured-clone" && !samePlainValue(parked.value, parkedArgs);
|
|
4184
|
+
if (projectionMovedArgs && basePolicyForResumeEdit === undefined) {
|
|
4185
|
+
throw new ParkRefusal(`the arguments of "${req.toolName}" change shape when stored by this checkpoint backend, and no policy is wired to re-adjudicate the stored shape ` +
|
|
4186
|
+
`(no basePolicyForResumeEdit override and no caller toolPolicy) — refusing to file a row whose executable form nothing adjudicated`);
|
|
4187
|
+
}
|
|
3986
4188
|
if (projectionMovedArgs && basePolicyForResumeEdit !== undefined) {
|
|
3987
4189
|
const presented = encodeAtFidelity(backendFidelity, parkedArgs);
|
|
3988
4190
|
if (!presented.ok) {
|
|
@@ -3992,6 +4194,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3992
4194
|
toolName: req.toolName,
|
|
3993
4195
|
args: presented.value,
|
|
3994
4196
|
toolCallId: req.toolCallId,
|
|
4197
|
+
budget: budgetSnapshot,
|
|
3995
4198
|
...(handsCwdRef !== undefined ? { cwd: handsCwdRef.current } : {}),
|
|
3996
4199
|
}, abortController.signal));
|
|
3997
4200
|
const demanded = reprojected.updatedInput !== undefined ? tryCloneArgs(reprojected.updatedInput) : undefined;
|
|
@@ -4081,7 +4284,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
4081
4284
|
const mintedAt = Date.now();
|
|
4082
4285
|
cp = {
|
|
4083
4286
|
token,
|
|
4084
|
-
version: orgAdmissionCheckpointState() ? ORG_ADMISSION_CHECKPOINT_VERSION : approvalLedger.totalTokens !== undefined ? TOKEN_CHECKPOINT_VERSION : BINDING_CHECKPOINT_VERSION,
|
|
4287
|
+
version: f012CheckpointState() ? F012_CHECKPOINT_VERSION : orgAdmissionCheckpointState() ? ORG_ADMISSION_CHECKPOINT_VERSION : approvalLedger.totalTokens !== undefined ? TOKEN_CHECKPOINT_VERSION : BINDING_CHECKPOINT_VERSION,
|
|
4085
4288
|
scope,
|
|
4086
4289
|
sessionId,
|
|
4087
4290
|
leafId,
|
|
@@ -4220,11 +4423,27 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
4220
4423
|
}
|
|
4221
4424
|
: {}),
|
|
4222
4425
|
isMarkedUnresolvable: (toolCallId) => inheritedUnavailableAsks.has(toolCallId),
|
|
4426
|
+
...(sandboxAdmissionArmed
|
|
4427
|
+
? {
|
|
4428
|
+
sandboxAdmission: {
|
|
4429
|
+
askClassesOf: (toolCallId) => foldAskClasses.get(toolCallId),
|
|
4430
|
+
boundaryCapable: sandboxBoundaryCapable(e.toolName),
|
|
4431
|
+
onAdmitted: emitSandboxAdmitted,
|
|
4432
|
+
},
|
|
4433
|
+
}
|
|
4434
|
+
: {}),
|
|
4223
4435
|
});
|
|
4224
4436
|
}
|
|
4225
4437
|
finally {
|
|
4226
4438
|
inheritedUnavailableAsks.delete(e.toolCallId);
|
|
4227
4439
|
inheritedAskGrants.delete(e.toolCallId);
|
|
4440
|
+
foldAskClasses.delete(e.toolCallId);
|
|
4441
|
+
}
|
|
4442
|
+
const ancestorAdmitted = ancestorSandboxAdmissions.get(e.toolCallId);
|
|
4443
|
+
ancestorSandboxAdmissions.delete(e.toolCallId);
|
|
4444
|
+
if (ancestorAdmitted !== undefined && !result.block && !result.suspend) {
|
|
4445
|
+
emitSandboxAdmitted({ toolCallId: e.toolCallId, toolName: e.toolName, askClasses: ancestorAdmitted, boundary: "sandbox_internal" });
|
|
4446
|
+
result.preToolContext.push(`permission.sandbox_admitted: this call's inherited pending approval was auto-admitted because the deployment declares an isolated sandbox execution env and the request stays inside it. Recorded for audit.`);
|
|
4228
4447
|
}
|
|
4229
4448
|
if (!result.block && !result.suspend && result.preToolContext.length > 0) {
|
|
4230
4449
|
preToolContexts.set(e.toolCallId, result.preToolContext);
|