@sema-agent/core 5.13.0 → 5.14.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 +296 -0
- package/dist/agents/send-message-tool.js +1 -0
- package/dist/agents/subagent.d.ts +4 -0
- package/dist/agents/subagent.js +133 -41
- package/dist/brain/anthropic.js +33 -10
- package/dist/brain/context-overflow.d.ts +20 -0
- package/dist/brain/context-overflow.js +58 -0
- package/dist/brain/open-responses.js +24 -10
- package/dist/brain/openai.js +29 -11
- package/dist/brain/request-params.d.ts +2 -0
- package/dist/brain/request-params.js +16 -0
- package/dist/brain/stream-engine.d.ts +9 -1
- package/dist/brain/stream-engine.js +256 -27
- package/dist/brain/timeout.d.ts +1 -0
- package/dist/brain/timeout.js +1 -0
- package/dist/core/a2a.d.ts +2 -2
- package/dist/core/a2a.js +3 -3
- package/dist/core/ask-question.d.ts +47 -2
- package/dist/core/ask-question.js +209 -28
- package/dist/core/background-agent-store.d.ts +2 -0
- package/dist/core/checkpoint-store.d.ts +41 -17
- package/dist/core/checkpoint-store.js +114 -3
- package/dist/core/hooks.d.ts +24 -2
- package/dist/core/hooks.js +97 -10
- package/dist/core/human-input-projection.d.ts +12 -0
- package/dist/core/human-input-projection.js +27 -0
- package/dist/core/mcp.d.ts +7 -2
- package/dist/core/mcp.js +7 -7
- package/dist/core/memory-admission.d.ts +4 -0
- package/dist/core/memory-admission.js +3 -0
- package/dist/core/runner/assemble-result.d.ts +1 -0
- package/dist/core/runner/assemble-result.js +1 -1
- package/dist/core/runner/prepare-task.d.ts +16 -6
- package/dist/core/runner/prepare-task.js +301 -24
- package/dist/core/runner/runtask.d.ts +3 -6
- package/dist/core/runner/runtask.js +186 -36
- package/dist/core/runner/tool-output-projection.js +1 -0
- package/dist/core/session-store.d.ts +3 -0
- package/dist/core/session-store.js +4 -0
- package/dist/core/session.d.ts +1 -0
- package/dist/core/store-contracts/background-agent-store-contract.js +19 -0
- package/dist/core/store-contracts/checkpoint-store-contract.js +62 -3
- package/dist/core/task-notification.d.ts +2 -0
- package/dist/core/task-notification.js +5 -3
- package/dist/core/task-registry-agent.d.ts +1 -0
- package/dist/core/task-registry-agent.js +6 -0
- package/dist/core/task-registry.d.ts +1 -0
- package/dist/core/task-registry.js +4 -1
- package/dist/core/tool-policy.d.ts +5 -0
- package/dist/core/tool-policy.js +2 -1
- package/dist/core/types.d.ts +32 -1
- package/dist/core/wiring-manifest.d.ts +97 -0
- package/dist/core/wiring-manifest.js +186 -0
- package/dist/engine/compaction/compaction.js +2 -2
- package/dist/engine/harness/agent-harness.d.ts +2 -1
- package/dist/engine/harness/agent-harness.js +8 -1
- package/dist/engine/harness/types.d.ts +3 -1
- package/dist/engine/llm/types.d.ts +7 -0
- package/dist/engine/llm/types.js +8 -1
- package/dist/engine/session/import-validate.d.ts +6 -1
- package/dist/engine/session/import-validate.js +29 -6
- package/dist/engine/session/memory-repo.d.ts +3 -1
- package/dist/engine/session/memory-repo.js +2 -2
- package/dist/index.d.ts +7 -4
- package/dist/index.js +7 -4
- package/dist/internal/harness-types.d.ts +1 -1
- package/dist/internal/llm.d.ts +2 -2
- package/dist/internal/llm.js +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +4 -0
- package/dist/orchestration/run-workflow-tool.js +3 -0
- package/dist/orchestration/workflow-types.d.ts +8 -0
- package/dist/orchestration/workflow-types.js +14 -0
- package/dist/orchestration/workflow.d.ts +4 -0
- package/dist/orchestration/workflow.js +134 -5
- package/dist/prompts/default.js +1 -1
- package/dist/stores/file/checkpoint-store.d.ts +3 -5
- package/dist/stores/file/checkpoint-store.js +31 -2
- package/dist/stores/file/index.js +1 -1
- package/dist/stores/file/session-store.d.ts +3 -1
- package/dist/stores/file/session-store.js +2 -2
- package/dist/stores/file/shared-ledger.js +8 -1
- package/dist/tools/fs/bash-readonly-classifier.d.ts +3 -0
- package/dist/tools/fs/bash-readonly-classifier.js +94 -0
- package/dist/tools/fs/fs-bash.js +31 -12
- package/dist/tools/fs/safety.js +34 -10
- package/package.json +1 -1
|
@@ -12,6 +12,8 @@ import { primaryActivityArg } from "../arg-summary.js";
|
|
|
12
12
|
import { materializeMcpTools } from "../mcp.js";
|
|
13
13
|
import { materializeA2aTools } from "../a2a.js";
|
|
14
14
|
import { Type } from "typebox";
|
|
15
|
+
import { Value } from "typebox/value";
|
|
16
|
+
import { uuidv7 } from "../../engine/session/uuid.js";
|
|
15
17
|
import { brainToRuntime } from "../runtime.js";
|
|
16
18
|
import { StoredSession, isSessionConflict, hasSessionFork } from "../session.js";
|
|
17
19
|
import { createSubagentWorktreeHelper, forkGovernanceDenial } from "../../agents/subagent.js";
|
|
@@ -24,7 +26,7 @@ import { CHANGED_FILES_MTIME_EPS_MS, fenceMcpServerInstructions, renderAgentList
|
|
|
24
26
|
import { inlineUntrusted } from "../untrusted-text.js";
|
|
25
27
|
import { emitTrace } from "../trace.js";
|
|
26
28
|
import { createSessionRulePolicy } from "./session-rule-policy.js";
|
|
27
|
-
import { cloneObserverInput, formatHookFeedback, runToolGate } from "../hooks.js";
|
|
29
|
+
import { cloneObserverInput, createHookEnvCapabilities, formatHookFeedback, runToolGate } from "../hooks.js";
|
|
28
30
|
import { reconcileInterruptedSession } from "../session-reconcile.js";
|
|
29
31
|
import { CacheBreakDetector, toolsToFingerprintInputs } from "../cache-break-detector.js";
|
|
30
32
|
import { reservedCollisions, reservedFor } from "../../brain/request-params.js";
|
|
@@ -64,7 +66,7 @@ import { createMonitorTool } from "../../tools/monitor.js";
|
|
|
64
66
|
import { createWorktreeTools } from "../../tools/worktree.js";
|
|
65
67
|
import { applyCompactionToReadFileState, bashReversibilityProbe, createHandsToolkit, isReadDedupStubResult, seedReadFileStateFromContext, seedReadFileStateFromTranscript, HAND_TOOL_EFFECTS, pdfModelCapabilitiesOf } from "../../tools/fs/index.js";
|
|
66
68
|
import { decodeTextBytes } from "../../tools/fs/encoding.js";
|
|
67
|
-
import { ASK_USER_QUESTION_TOOL_NAME, createAskUserQuestionTool } from "../ask-question.js";
|
|
69
|
+
import { ASK_USER_QUESTION_TOOL_NAME, createAskUserQuestionTool, classifyQuestionOutcome, isLiveQuestionFace, validateAskQuestions, } from "../ask-question.js";
|
|
68
70
|
import { createSchedulerTools } from "../../tools/scheduler-tools.js";
|
|
69
71
|
import { createPresentPlanTool, createEnterPlanModeTool, PRESENT_PLAN_TOOL_NAME, ENTER_PLAN_MODE_TOOL_NAME } from "../present-plan-tool.js";
|
|
70
72
|
import { isSelfOrchestrationActive, selfOrchestrationFailClosedReason } from "../../orchestration/workflow-script-runner.js";
|
|
@@ -73,8 +75,9 @@ import { resolveWorkflowSizeGuideline } from "../../orchestration/workflow-size-
|
|
|
73
75
|
import { createLspTool, gitCheckIgnoreFilter, resolveLspPath } from "../lsp.js";
|
|
74
76
|
import { resolveKey } from "../../tools/fs/safety.js";
|
|
75
77
|
import { wholeFileRecordsFromTranscript } from "./session-file-state-replay.js";
|
|
76
|
-
import { BINDING_CHECKPOINT_VERSION, mintCheckpointToken, ORG_ADMISSION_CHECKPOINT_VERSION, RESOURCE_CHECKPOINT_VERSION, TOKEN_CHECKPOINT_VERSION, buildRiskDescriptor, debitLedger, remainingBudgetMicroUsd, } from "../checkpoint-store.js";
|
|
78
|
+
import { BINDING_CHECKPOINT_VERSION, mintCheckpointToken, ORG_ADMISSION_CHECKPOINT_VERSION, RESOURCE_CHECKPOINT_VERSION, TOKEN_CHECKPOINT_VERSION, buildRiskDescriptor, debitLedger, remainingBudgetMicroUsd, resolveCheckpointStore, } from "../checkpoint-store.js";
|
|
77
79
|
import { boundInputHashOf } from "../canonical-json.js";
|
|
80
|
+
import { countElicitOptIns, deriveAskEffective, deriveWiringManifest, resolveAskSeamForm, resolveDeclaredDurability, resolveElicitSeam, resolveQuestionSeam } from "../wiring-manifest.js";
|
|
78
81
|
import { GLOBAL_USAGE_KEY, resolveUsageWindows, usageRetryAfterMs } from "../usage-window-store.js";
|
|
79
82
|
const RECONCILE_MAX_RETRIES = 3;
|
|
80
83
|
const DEFAULT_MAX_SUSPENDS = 5;
|
|
@@ -177,11 +180,7 @@ export const DEFAULT_IRREVERSIBLE_SCOPE = "irreversible";
|
|
|
177
180
|
export function checkpointScopeOf(spec) {
|
|
178
181
|
return spec.durableApproval?.scope || spec.principal || DEFAULT_IRREVERSIBLE_SCOPE;
|
|
179
182
|
}
|
|
180
|
-
export
|
|
181
|
-
if (spec.checkpointStore === null)
|
|
182
|
-
return undefined;
|
|
183
|
-
return spec.checkpointStore ?? deps.checkpointStore;
|
|
184
|
-
}
|
|
183
|
+
export { resolveCheckpointStore } from "../checkpoint-store.js";
|
|
185
184
|
export function isFableFamilyModelId(id) {
|
|
186
185
|
const tail = id.toLowerCase().split("/").pop() ?? "";
|
|
187
186
|
return /^claude-fable-\d/.test(tail) || /^claude-mythos-5(?!\d)/.test(tail);
|
|
@@ -351,6 +350,54 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
351
350
|
{ name: "toolResultStore", store: deps.toolResultStore },
|
|
352
351
|
],
|
|
353
352
|
});
|
|
353
|
+
const resolvedInteractionPosture = spec.interactionPosture ?? internals?.parentInteractionPosture ?? deps.interactionPosture;
|
|
354
|
+
{
|
|
355
|
+
const interactionPosture = resolvedInteractionPosture;
|
|
356
|
+
const discloseInteractionPostureRefusal = (err) => {
|
|
357
|
+
try {
|
|
358
|
+
deps.onError?.(err, { phase: "config", sessionId: spec.sessionId ?? "(pre-session)", classification: "interaction-posture-refused" });
|
|
359
|
+
}
|
|
360
|
+
catch {
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
if (interactionPosture !== undefined && interactionPosture !== "interactive" && interactionPosture !== "headless") {
|
|
364
|
+
const e = new Error(`interactionPosture ${JSON.stringify(interactionPosture)} is not a recognized posture ("interactive" | "headless") — ` +
|
|
365
|
+
`an unevaluable declaration is refused loudly, never folded to either posture.`);
|
|
366
|
+
e.code = "config.interaction_posture";
|
|
367
|
+
discloseInteractionPostureRefusal(e);
|
|
368
|
+
throw e;
|
|
369
|
+
}
|
|
370
|
+
if (interactionPosture === "interactive") {
|
|
371
|
+
const askDoor = resolveAskSeamForm(spec, deps);
|
|
372
|
+
const humanReachable = deriveAskEffective(askDoor.form, "unresolved") === "human_reachable";
|
|
373
|
+
const questionDoor = resolveQuestionSeam(spec, deps);
|
|
374
|
+
const strippedByEngine = internals?.questionFaceStripped === true;
|
|
375
|
+
if (spec.interactiveTools === false) {
|
|
376
|
+
const e = new Error(`interaction posture "interactive" declared together with interactiveTools: false — the hard-headless ` +
|
|
377
|
+
`clamp removes the AskUserQuestion mount, so no content question can ever reach the human this posture ` +
|
|
378
|
+
`promises. Drop one of the two declarations.`);
|
|
379
|
+
e.code = "config.interaction_posture";
|
|
380
|
+
discloseInteractionPostureRefusal(e);
|
|
381
|
+
throw e;
|
|
382
|
+
}
|
|
383
|
+
if (!humanReachable || !(questionDoor.wired || strippedByEngine)) {
|
|
384
|
+
const missing = [];
|
|
385
|
+
if (!humanReachable) {
|
|
386
|
+
missing.push(askDoor.form === "absent"
|
|
387
|
+
? "no onAsk approver is wired (spec.onAsk ?? deps.onAsk is absent — asks would auto-deny or park)"
|
|
388
|
+
: `the resolved onAsk seat is the blanket policy "${askDoor.form}" (${askDoor.provenance ?? "?"}) — a policy setting is not a reachable human`);
|
|
389
|
+
}
|
|
390
|
+
if (!questionDoor.wired && !strippedByEngine) {
|
|
391
|
+
missing.push("no content-question channel (spec.onQuestion ?? deps.onQuestion is absent, and this leg is not an engine-stripped background lane)");
|
|
392
|
+
}
|
|
393
|
+
const e = new Error(`interaction posture "interactive" declared, but this assembly cannot reach a human: ${missing.join("; ")}. ` +
|
|
394
|
+
`Wire the missing seam(s), or drop the posture declaration (absent = no check).`);
|
|
395
|
+
e.code = "config.interaction_posture";
|
|
396
|
+
discloseInteractionPostureRefusal(e);
|
|
397
|
+
throw e;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
354
401
|
resolveTaskLimits(spec.limits);
|
|
355
402
|
if (spec.resourceSuspend !== undefined) {
|
|
356
403
|
const rsus = spec.resourceSuspend;
|
|
@@ -392,6 +439,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
392
439
|
const egressTools = new Set();
|
|
393
440
|
const irreversibleTools = new Set();
|
|
394
441
|
const irreversibilityTier = new Map();
|
|
442
|
+
const axisExplicitNegatives = new Map();
|
|
395
443
|
const reversibilityProbes = new Map();
|
|
396
444
|
let shellGatedBash = false;
|
|
397
445
|
let shellGatedMonitor = false;
|
|
@@ -958,9 +1006,20 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
958
1006
|
const seedAdmittedOrg = seedInheritedGate?.admittedOrgScopes;
|
|
959
1007
|
const inheritedAdmittedOrgScopes = liveAdmittedOrg === undefined ? seedAdmittedOrg : seedAdmittedOrg === undefined ? liveAdmittedOrg : liveAdmittedOrg.filter((s) => seedAdmittedOrg.includes(s));
|
|
960
1008
|
const inheritedOrgGoverned = liveInheritedGate?.orgAdmissionGoverned === true || seedInheritedGate?.orgAdmissionGoverned === true;
|
|
961
|
-
const
|
|
1009
|
+
const checkpointOwnOrgVerdict = resume?.seed.inheritedGate?.ownAdmittedOrgScopes !== undefined
|
|
962
1010
|
? { scopes: resume.seed.inheritedGate.ownAdmittedOrgScopes, writeScope: resume.seed.inheritedGate.ownAdmittedOrgWriteScope ?? null }
|
|
963
1011
|
: undefined;
|
|
1012
|
+
const refOwnOrgVerdict = internals?.ownOrgAdmissionRef?.current;
|
|
1013
|
+
const priorOwnOrgVerdict = checkpointOwnOrgVerdict === undefined
|
|
1014
|
+
? refOwnOrgVerdict
|
|
1015
|
+
: refOwnOrgVerdict === undefined
|
|
1016
|
+
? checkpointOwnOrgVerdict
|
|
1017
|
+
: {
|
|
1018
|
+
scopes: checkpointOwnOrgVerdict.scopes.filter((sc) => refOwnOrgVerdict.scopes.includes(sc)),
|
|
1019
|
+
writeScope: checkpointOwnOrgVerdict.writeScope !== null && checkpointOwnOrgVerdict.writeScope === refOwnOrgVerdict.writeScope
|
|
1020
|
+
? checkpointOwnOrgVerdict.writeScope
|
|
1021
|
+
: null,
|
|
1022
|
+
};
|
|
964
1023
|
const orgGovernedProvenance = deps.memoryScopeAdmission !== undefined ||
|
|
965
1024
|
(deps.deploymentMemoryScopes !== undefined && deps.deploymentMemoryScopes.length > 0) ||
|
|
966
1025
|
deps.compliancePostureResolver !== undefined ||
|
|
@@ -1055,6 +1114,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1055
1114
|
: {}),
|
|
1056
1115
|
sessionId,
|
|
1057
1116
|
...(spec.backgroundScope !== undefined ? { backgroundScope: spec.backgroundScope } : {}),
|
|
1117
|
+
...(resolvedInteractionPosture !== undefined ? { interactionPosture: resolvedInteractionPosture } : {}),
|
|
1058
1118
|
...(deps.onBackgroundChildEvent ? { onBackgroundChildEvent: deps.onBackgroundChildEvent } : {}),
|
|
1059
1119
|
...(internals?.onTaskNotification ? { onTaskNotification: internals.onTaskNotification } : {}),
|
|
1060
1120
|
...(forwardEvent ? { forwardEvent } : {}),
|
|
@@ -1208,6 +1268,8 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1208
1268
|
...(spec.getApiKeyAndHeaders !== undefined ? { parentGetApiKeyAndHeaders: spec.getApiKeyAndHeaders } : {}),
|
|
1209
1269
|
principal: spec.principal,
|
|
1210
1270
|
oneShot: spec.oneShot,
|
|
1271
|
+
...(resolvedInteractionPosture !== undefined ? { parentInteractionPosture: resolvedInteractionPosture } : {}),
|
|
1272
|
+
autoModeReview: () => (autoModeDecider !== undefined ? { decider: autoModeDecider } : undefined),
|
|
1211
1273
|
workflowDepth: internals?.workflowDepth,
|
|
1212
1274
|
parentCwd: taskRootPath,
|
|
1213
1275
|
parentThinking: () => harnessRef.current?.getThinkingLevel() ?? thinking,
|
|
@@ -1380,6 +1442,12 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1380
1442
|
irreversibilityTier.set(axis.name, "always");
|
|
1381
1443
|
irreversibleTools.add(axis.name);
|
|
1382
1444
|
}
|
|
1445
|
+
if (axis.irreversibility === "never") {
|
|
1446
|
+
axisExplicitNegatives.set(axis.name, { ...axisExplicitNegatives.get(axis.name), irreversible: false });
|
|
1447
|
+
}
|
|
1448
|
+
if (axis.egress === false) {
|
|
1449
|
+
axisExplicitNegatives.set(axis.name, { ...axisExplicitNegatives.get(axis.name), egress: false });
|
|
1450
|
+
}
|
|
1383
1451
|
if (axis.egress) {
|
|
1384
1452
|
if (axis.effect !== undefined && axis.effect !== "write") {
|
|
1385
1453
|
const e = new Error(`${protocolLabel} tool "${axis.name}" resolves to egress:true with effect:"${axis.effect}" — an egress tool (external write) must have effect:"write". Clear egress (toolAxes egress:false) if it is a pure read, or set effect:"write".`);
|
|
@@ -1535,6 +1603,11 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1535
1603
|
}
|
|
1536
1604
|
tools.push(...band.map((t) => firstPartyOffload(t)));
|
|
1537
1605
|
const shellGate = effectiveShellGate;
|
|
1606
|
+
if (shellGate === "off" && !(executionEnv instanceof StubExecutionEnv) && spec.handsReadOnly !== true) {
|
|
1607
|
+
deps.onError?.(new Error(`shell gate doctrine is "off" while a real writable shell (Bash) is mounted — no shell safety-axis ` +
|
|
1608
|
+
`fold applies to this run (commands are adjudicated by the ordinary policy/hook chain only). ` +
|
|
1609
|
+
`Set spec.shellGate to "classify" or "always" if this deployment expects doctrine-gated shell behavior.`), { phase: "config", sessionId, classification: "shell-gate-off" });
|
|
1610
|
+
}
|
|
1538
1611
|
if (shellGate !== "off" && !(executionEnv instanceof StubExecutionEnv) && spec.handsReadOnly !== true) {
|
|
1539
1612
|
shellGatedBash = !egressTools.has("Bash") && !irreversibilityTier.has("Bash");
|
|
1540
1613
|
irreversibilityTier.set("Bash", shellGate === "always" ? "always" : "maybe");
|
|
@@ -1655,10 +1728,79 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1655
1728
|
if (offloadStore)
|
|
1656
1729
|
tools.push(createReadToolResultTool(offloadStore));
|
|
1657
1730
|
const onQuestion = frozenOnQuestion;
|
|
1731
|
+
const liveQuestionFace = isLiveQuestionFace(onQuestion) ? onQuestion : undefined;
|
|
1732
|
+
const contentAskBindings = new Map();
|
|
1733
|
+
const CONTENT_ASK_BINDING_CAP = 32;
|
|
1734
|
+
const contentAskRoutable = (toolCallId) => liveQuestionFace !== undefined &&
|
|
1735
|
+
mountedQuestionTool !== undefined &&
|
|
1736
|
+
tools.includes(mountedQuestionTool) &&
|
|
1737
|
+
runtimeCaps?.forceDurableGate !== true &&
|
|
1738
|
+
!inheritedUnavailableAsks.has(toolCallId);
|
|
1739
|
+
const lateStrandedAnswers = [];
|
|
1740
|
+
const discloseStrandedAnswers = (records, why) => {
|
|
1741
|
+
if (records.length === 0)
|
|
1742
|
+
return;
|
|
1743
|
+
try {
|
|
1744
|
+
deps.onError?.(new Error(`AskUserQuestion: ${records.length} question(s) were answered by a person but the call never ` +
|
|
1745
|
+
`executed to collect the answer (${records.map((r) => `${r.toolCallId} [delivery ${r.deliveryId}]`).join(", ")}) — ${why}. The answer(s) were NOT ` +
|
|
1746
|
+
`delivered to the model and are gone with this leg; re-ask if the decision is still needed.`), { phase: "degraded", sessionId, classification: "unconsumed-human-answer" });
|
|
1747
|
+
}
|
|
1748
|
+
catch {
|
|
1749
|
+
}
|
|
1750
|
+
};
|
|
1751
|
+
const settleContentAskBindings = () => {
|
|
1752
|
+
const stranded = [];
|
|
1753
|
+
for (const [callId, bound] of contentAskBindings) {
|
|
1754
|
+
if (bound.kind === "answered")
|
|
1755
|
+
stranded.push({ deliveryId: bound.deliveryId, toolCallId: callId });
|
|
1756
|
+
}
|
|
1757
|
+
contentAskBindings.clear();
|
|
1758
|
+
discloseStrandedAnswers(stranded, "the leg ended first (abort, batch teardown, or a loop failure)");
|
|
1759
|
+
const byDelivery = new Map();
|
|
1760
|
+
for (const r of [...stranded, ...lateStrandedAnswers])
|
|
1761
|
+
byDelivery.set(r.deliveryId, r);
|
|
1762
|
+
return [...byDelivery.values()];
|
|
1763
|
+
};
|
|
1658
1764
|
const durableQuestionFace = resolveCheckpointStore(spec, deps) !== undefined &&
|
|
1659
1765
|
(spec.durableApproval !== undefined || runtimeCaps?.forceDurableGate === true);
|
|
1660
|
-
|
|
1661
|
-
|
|
1766
|
+
const mountedQuestionFace = liveQuestionFace !== undefined
|
|
1767
|
+
? async (req, signal) => {
|
|
1768
|
+
const bound = contentAskBindings.get(req.toolCallId);
|
|
1769
|
+
if (bound !== undefined) {
|
|
1770
|
+
if (bound.questionsHash === boundInputHashOf(req.questions)) {
|
|
1771
|
+
contentAskBindings.delete(req.toolCallId);
|
|
1772
|
+
if (bound.kind === "answered")
|
|
1773
|
+
return bound.answer;
|
|
1774
|
+
throw bound.error;
|
|
1775
|
+
}
|
|
1776
|
+
contentAskBindings.delete(req.toolCallId);
|
|
1777
|
+
}
|
|
1778
|
+
return liveQuestionFace(req, signal);
|
|
1779
|
+
}
|
|
1780
|
+
: onQuestion;
|
|
1781
|
+
const questionToolMounted = spec.interactiveTools === true || (spec.interactiveTools !== false && (onQuestion !== undefined || durableQuestionFace));
|
|
1782
|
+
let mountedQuestionTool;
|
|
1783
|
+
if (questionToolMounted)
|
|
1784
|
+
tools.push((mountedQuestionTool =
|
|
1785
|
+
createAskUserQuestionTool(mountedQuestionFace, { principal: spec.principal, sourceTaskId: sessionId }, {
|
|
1786
|
+
...(resume?.redeemedContentAskCallId !== undefined
|
|
1787
|
+
? {
|
|
1788
|
+
redeemedApprovalCallId: resume.redeemedContentAskCallId,
|
|
1789
|
+
...(resume.redeemedContentAskQuestionsHash !== undefined ? { redeemedApprovalQuestionsHash: resume.redeemedContentAskQuestionsHash } : {}),
|
|
1790
|
+
}
|
|
1791
|
+
: {}),
|
|
1792
|
+
...(resolvedInteractionPosture !== undefined ? { posture: resolvedInteractionPosture } : {}),
|
|
1793
|
+
...(spec.interactiveQuestionFallback === true ? { interactiveFallback: true } : {}),
|
|
1794
|
+
onSyntheticContinuation: ({ questionId, reason }) => {
|
|
1795
|
+
deps.onError?.(new Error(`AskUserQuestion ${questionId}: no human answer was obtainable (` +
|
|
1796
|
+
(reason === "seam_absent"
|
|
1797
|
+
? "no onQuestion seam is wired"
|
|
1798
|
+
: reason === "declined_unavailable"
|
|
1799
|
+
? "the wired question channel reported nobody was reachable"
|
|
1800
|
+
: "the wired question channel failed") +
|
|
1801
|
+
`) — the model was instructed to self-answer and the run CONTINUES (warning, not a failure).`), { phase: "degraded", sessionId, classification: "no-human-autoanswered" });
|
|
1802
|
+
},
|
|
1803
|
+
})));
|
|
1662
1804
|
if (spec.handsReadOnly !== true) {
|
|
1663
1805
|
const sessionScope = sessionId ?? spec.principal ?? spec.taskId ?? "default";
|
|
1664
1806
|
tools.push(...createSchedulerTools(executionEnv, {
|
|
@@ -1721,6 +1863,9 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1721
1863
|
});
|
|
1722
1864
|
memoryAdmittedOrgScopesRef.current = memoryAdmittedOrgScopes;
|
|
1723
1865
|
ownOrgVerdictRef.current = memoryOwnOrgVerdict ?? priorOwnOrgVerdict;
|
|
1866
|
+
if (internals?.ownOrgAdmissionRef !== undefined && ownOrgVerdictRef.current !== undefined) {
|
|
1867
|
+
internals.ownOrgAdmissionRef.current = ownOrgVerdictRef.current;
|
|
1868
|
+
}
|
|
1724
1869
|
let memoryBlock = memoryBlockFromEngine;
|
|
1725
1870
|
if (memorySeedFiles?.length && seedContextFiles) {
|
|
1726
1871
|
try {
|
|
@@ -2117,6 +2262,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2117
2262
|
model,
|
|
2118
2263
|
deferNames: (toolFaceSnapshot.defer ?? []).filter((n) => tools.some((t) => t.name === n)),
|
|
2119
2264
|
alwaysLoadNames: [
|
|
2265
|
+
ASK_USER_QUESTION_TOOL_NAME,
|
|
2120
2266
|
...(toolFaceSnapshot.alwaysLoad ?? []),
|
|
2121
2267
|
...mcp.tools
|
|
2122
2268
|
.filter((t) => t.mcpAlwaysLoad === true && !(toolFaceSnapshot.defer ?? []).includes(t.name))
|
|
@@ -2598,6 +2744,15 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2598
2744
|
? { sourceAgentName: internals?.explicitAgentName ?? internals?.agentName }
|
|
2599
2745
|
: {}),
|
|
2600
2746
|
});
|
|
2747
|
+
const riskAxesOf = (toolName) => {
|
|
2748
|
+
const tier = irreversibilityTier.get(toolName);
|
|
2749
|
+
const negatives = axisExplicitNegatives.get(toolName);
|
|
2750
|
+
const irreversible = tier === "always" || tier === "maybe" ? true : tier === "never" ? false : negatives?.irreversible;
|
|
2751
|
+
const egress = egressTools.has(toolName) ? true : negatives?.egress;
|
|
2752
|
+
if (irreversible === undefined && egress === undefined)
|
|
2753
|
+
return {};
|
|
2754
|
+
return { riskAxes: { ...(irreversible !== undefined ? { irreversible } : {}), ...(egress !== undefined ? { egress } : {}) } };
|
|
2755
|
+
};
|
|
2601
2756
|
const recheckApprovedEdit = async (pol, onAskOf, creq, edit, csignal) => {
|
|
2602
2757
|
let editArgs = edit;
|
|
2603
2758
|
for (let round = 0;; round++) {
|
|
@@ -2630,6 +2785,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2630
2785
|
args: editArgs,
|
|
2631
2786
|
message: re.message ?? `approval required for "${creq.toolName}" (inherited parent policy)`,
|
|
2632
2787
|
...askSourceIdentity(),
|
|
2788
|
+
...riskAxesOf(creq.toolName),
|
|
2633
2789
|
...(re.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
|
|
2634
2790
|
}, onAskOf, csignal ?? abortController.signal);
|
|
2635
2791
|
if (rr.action !== "allow")
|
|
@@ -2654,8 +2810,9 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2654
2810
|
return first;
|
|
2655
2811
|
if (first.action === "allow")
|
|
2656
2812
|
return { action: "allow" };
|
|
2657
|
-
if (creq.toolName === ASK_USER_QUESTION_TOOL_NAME)
|
|
2813
|
+
if (creq.toolName === ASK_USER_QUESTION_TOOL_NAME && (pc.durableMandate !== true || markInheritedUnavailable(creq.toolCallId))) {
|
|
2658
2814
|
return first;
|
|
2815
|
+
}
|
|
2659
2816
|
if (pc.durableMandate === true) {
|
|
2660
2817
|
if (resolveCheckpointStore(spec, deps) !== undefined &&
|
|
2661
2818
|
(spec.durableApproval !== undefined || runtimeCaps?.forceDurableGate === true) &&
|
|
@@ -2676,6 +2833,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2676
2833
|
args: presentedArgs,
|
|
2677
2834
|
message: first.message ?? `approval required for "${creq.toolName}" (inherited parent policy)`,
|
|
2678
2835
|
...askSourceIdentity(),
|
|
2836
|
+
...riskAxesOf(creq.toolName),
|
|
2679
2837
|
...(first.action === "ask" && first.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
|
|
2680
2838
|
}, pc.onAsk, csignal ?? abortController.signal);
|
|
2681
2839
|
const askWaitMs = Math.max(0, now() - askT0);
|
|
@@ -2710,8 +2868,9 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2710
2868
|
}
|
|
2711
2869
|
if (decision.action !== "ask")
|
|
2712
2870
|
return decision;
|
|
2713
|
-
if (creq.toolName === ASK_USER_QUESTION_TOOL_NAME)
|
|
2871
|
+
if (creq.toolName === ASK_USER_QUESTION_TOOL_NAME && (pc.durableMandate !== true || markInheritedUnavailable(creq.toolCallId))) {
|
|
2714
2872
|
return decision;
|
|
2873
|
+
}
|
|
2715
2874
|
if (pc.durableMandate === true) {
|
|
2716
2875
|
if (resolveCheckpointStore(spec, deps) !== undefined &&
|
|
2717
2876
|
(spec.durableApproval !== undefined || runtimeCaps?.forceDurableGate === true) &&
|
|
@@ -2732,6 +2891,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2732
2891
|
args: presentedArgs,
|
|
2733
2892
|
message: decision.message ?? `approval required for "${creq.toolName}" (inherited parent policy)`,
|
|
2734
2893
|
...askSourceIdentity(),
|
|
2894
|
+
...riskAxesOf(creq.toolName),
|
|
2735
2895
|
...(decision.action === "ask" && decision.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
|
|
2736
2896
|
}, pc.onAsk, csignal ?? abortController.signal);
|
|
2737
2897
|
const askWaitMs = Math.max(0, now() - askT0);
|
|
@@ -2917,6 +3077,42 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2917
3077
|
};
|
|
2918
3078
|
})();
|
|
2919
3079
|
const platformSuspendArmed = durableSuspendInfraReady && (envLifetimeSuspendAt !== undefined || usageGovernance !== undefined);
|
|
3080
|
+
const checkpointStore = resolveCheckpointStore(spec, deps);
|
|
3081
|
+
const durableApproval = spec.durableApproval ??
|
|
3082
|
+
(runtimeCaps?.forceDurableGate ? { scope: spec.principal || DEFAULT_IRREVERSIBLE_SCOPE } : undefined);
|
|
3083
|
+
const wiringQuestionSeam = resolveQuestionSeam(spec, deps);
|
|
3084
|
+
const wiringQuestionStripped = internals?.questionFaceStripped === true;
|
|
3085
|
+
const wiringAskSeam = resolveAskSeamForm(spec, deps);
|
|
3086
|
+
const wiringManifest = deriveWiringManifest({
|
|
3087
|
+
half: "effective",
|
|
3088
|
+
leg: resume !== undefined ? "resume" : internals?.isDelegatedChild === true ? "child" : "root",
|
|
3089
|
+
askForm: wiringAskSeam.form,
|
|
3090
|
+
...(wiringAskSeam.provenance !== undefined ? { askProvenance: wiringAskSeam.provenance } : {}),
|
|
3091
|
+
questionWired: wiringQuestionSeam.wired,
|
|
3092
|
+
...(wiringQuestionSeam.provenance !== undefined ? { questionProvenance: wiringQuestionSeam.provenance } : {}),
|
|
3093
|
+
...(wiringQuestionStripped ? { questionStrippedByEngine: true } : {}),
|
|
3094
|
+
...(resolvedInteractionPosture !== undefined ? { interactionPosture: resolvedInteractionPosture } : {}),
|
|
3095
|
+
...(spec.interactiveTools === true && !wiringQuestionSeam.wired && !durableQuestionFace && !wiringQuestionStripped
|
|
3096
|
+
? { interactiveToolsWithoutDeliveryFace: true }
|
|
3097
|
+
: {}),
|
|
3098
|
+
elicitSeamWired: resolveElicitSeam(deps),
|
|
3099
|
+
elicitServersOptedIn: countElicitOptIns(spec),
|
|
3100
|
+
parkCapable: checkpointStore !== undefined,
|
|
3101
|
+
parkDurableApprovalOptIn: spec.durableApproval !== undefined,
|
|
3102
|
+
parkForceDurableGate: runtimeCaps?.forceDurableGate === true,
|
|
3103
|
+
parkSafetyVocabularyArmed: irreversibleTools.size > 0 || egressTools.size > 0,
|
|
3104
|
+
...(checkpointStore !== undefined ? { checkpointDurability: resolveDeclaredDurability(checkpointStore, "checkpointStore") } : {}),
|
|
3105
|
+
sessionDurability: resolveDeclaredDurability(sessions, "sessionStore"),
|
|
3106
|
+
backgroundAgentStoreWired: deps.backgroundAgentStore !== undefined,
|
|
3107
|
+
hostChildEventSinkWired: deps.onBackgroundChildEvent !== undefined,
|
|
3108
|
+
lockedConfigWired: deps.lockedConfig !== undefined,
|
|
3109
|
+
complianceWired: deps.compliancePostureResolver !== undefined,
|
|
3110
|
+
memoryAdmissionWired: deps.memoryScopeAdmission !== undefined,
|
|
3111
|
+
retentionPolicyWired: deps.retentionPolicy !== undefined,
|
|
3112
|
+
});
|
|
3113
|
+
const parkLaneArmed = wiringManifest.parkLane.effective === true;
|
|
3114
|
+
const hookContextConsumerWired = hooks?.preToolUse !== undefined || hooks?.postToolUse !== undefined || hooks?.postToolUseFailure !== undefined;
|
|
3115
|
+
const hookEnvFace = hookContextConsumerWired && (ownedEnv ?? deps.executionEnv) != null ? createHookEnvCapabilities(executionEnv) : undefined;
|
|
2920
3116
|
if (effectivePolicy || hooks?.preToolUse || egressTools.size > 0 || irreversibleTools.size > 0 || resourceSuspendEligible || platformSuspendArmed || spec.enablePlanMode === true) {
|
|
2921
3117
|
const adjudicate = effectivePolicy
|
|
2922
3118
|
? (req) => raceAbort(Promise.resolve(effectivePolicy.check({ ...req, budget: budgetSnapshot }, abortController.signal)), abortController.signal, () => ({
|
|
@@ -2998,6 +3194,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2998
3194
|
})(),
|
|
2999
3195
|
message: decision.message ?? `approval required for "${req.toolName}"`,
|
|
3000
3196
|
...askSourceIdentity(),
|
|
3197
|
+
...riskAxesOf(req.toolName),
|
|
3001
3198
|
...(decision.action === "ask" && decision.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
|
|
3002
3199
|
}, onAsk, abortController.signal);
|
|
3003
3200
|
const waitMs = Math.max(0, now() - t0);
|
|
@@ -3037,9 +3234,6 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3037
3234
|
catch {
|
|
3038
3235
|
}
|
|
3039
3236
|
};
|
|
3040
|
-
const checkpointStore = resolveCheckpointStore(spec, deps);
|
|
3041
|
-
const durableApproval = spec.durableApproval ??
|
|
3042
|
-
(runtimeCaps?.forceDurableGate ? { scope: spec.principal || DEFAULT_IRREVERSIBLE_SCOPE } : undefined);
|
|
3043
3237
|
const inFlightSpendMicroUsd = () => {
|
|
3044
3238
|
const own = liveSpendRef.get?.().costMicroUsd ?? 0;
|
|
3045
3239
|
const seededNested = resume?.seed.nestedStats.costMicroUsd;
|
|
@@ -3078,6 +3272,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3078
3272
|
return live.length > 0 ? live : undefined;
|
|
3079
3273
|
})(),
|
|
3080
3274
|
pendingSteer: undefined,
|
|
3275
|
+
pendingSteerQueue: undefined,
|
|
3081
3276
|
inheritedGate: (() => {
|
|
3082
3277
|
const requiresParentConstraint = (inheritedParentConstraints?.length ?? 0) > 0 || seedInheritedGate?.requiresParentConstraint === true;
|
|
3083
3278
|
const parentConstraintCount = (inheritedParentConstraints?.length ?? 0) > 0 ? inheritedParentConstraints.length : seedInheritedGate?.parentConstraintCount;
|
|
@@ -3325,12 +3520,92 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3325
3520
|
return true;
|
|
3326
3521
|
}
|
|
3327
3522
|
: undefined;
|
|
3328
|
-
const
|
|
3329
|
-
|
|
3330
|
-
|
|
3523
|
+
const resolveContentAsk = async (req) => {
|
|
3524
|
+
if (!contentAskRoutable(req.toolCallId) || liveQuestionFace === undefined || mountedQuestionTool === undefined) {
|
|
3525
|
+
return { kind: "unavailable", parkDeclined: false };
|
|
3526
|
+
}
|
|
3527
|
+
const deliveryId = uuidv7();
|
|
3528
|
+
const bindOutcome = (entry, questionsHash) => {
|
|
3529
|
+
if (contentAskBindings.size >= CONTENT_ASK_BINDING_CAP && !contentAskBindings.has(req.toolCallId))
|
|
3530
|
+
return;
|
|
3531
|
+
contentAskBindings.set(req.toolCallId, { ...entry, questionsHash, deliveryId });
|
|
3532
|
+
};
|
|
3533
|
+
const refuseBeforeDelivery = (code, presentedInput) => ({
|
|
3534
|
+
kind: "delivery_failure",
|
|
3535
|
+
code,
|
|
3536
|
+
...(presentedInput !== undefined ? { presentedInput } : {}),
|
|
3537
|
+
});
|
|
3538
|
+
let retained;
|
|
3539
|
+
let presented;
|
|
3540
|
+
try {
|
|
3541
|
+
retained = structuredClone(req.args);
|
|
3542
|
+
presented = structuredClone(retained.questions);
|
|
3543
|
+
}
|
|
3544
|
+
catch {
|
|
3545
|
+
return refuseBeforeDelivery("question.malformed_request");
|
|
3546
|
+
}
|
|
3547
|
+
const retainedQuestionsHash = boundInputHashOf(retained.questions);
|
|
3548
|
+
if (!Value.Check(mountedQuestionTool.parameters, retained) || validateAskQuestions(presented) !== undefined) {
|
|
3549
|
+
return refuseBeforeDelivery("question.malformed_request", retained);
|
|
3550
|
+
}
|
|
3551
|
+
if (contentAskBindings.size >= CONTENT_ASK_BINDING_CAP && !contentAskBindings.has(req.toolCallId)) {
|
|
3552
|
+
return { kind: "unavailable", parkDeclined: true };
|
|
3553
|
+
}
|
|
3554
|
+
if (abortController.signal.aborted) {
|
|
3555
|
+
return { kind: "delivery_failure", code: "question.aborted", presentedInput: retained };
|
|
3556
|
+
}
|
|
3557
|
+
try {
|
|
3558
|
+
const facePromise = (async () => liveQuestionFace({
|
|
3559
|
+
toolCallId: req.toolCallId,
|
|
3560
|
+
questions: presented,
|
|
3561
|
+
...(spec.principal !== undefined ? { principal: spec.principal } : {}),
|
|
3562
|
+
sourceTaskId: sessionId,
|
|
3563
|
+
boundInputHash: boundInputHashOf(retained),
|
|
3564
|
+
deliveryId,
|
|
3565
|
+
}, abortController.signal))();
|
|
3566
|
+
const settlement = await raceAbort(facePromise.then((outcome) => ({ tag: "outcome", outcome }), (error) => ({ tag: "threw", error })), abortController.signal, () => ({ tag: "aborted" }));
|
|
3567
|
+
if (settlement.tag === "aborted") {
|
|
3568
|
+
void facePromise.then((late) => {
|
|
3569
|
+
if (classifyQuestionOutcome(late).shape !== "answered")
|
|
3570
|
+
return;
|
|
3571
|
+
lateStrandedAnswers.push({ deliveryId, toolCallId: req.toolCallId });
|
|
3572
|
+
discloseStrandedAnswers([{ deliveryId, toolCallId: req.toolCallId }], "the task had already ended when the answer arrived");
|
|
3573
|
+
}, () => undefined).catch(() => undefined);
|
|
3574
|
+
}
|
|
3575
|
+
if (settlement.tag === "outcome") {
|
|
3576
|
+
const outcome = settlement.outcome;
|
|
3577
|
+
const reading = classifyQuestionOutcome(outcome);
|
|
3578
|
+
if (reading.shape === "contradictory") {
|
|
3579
|
+
bindOutcome({ kind: "failed", error: new Error("the question channel returned a contradictory outcome (an unavailable answer)") }, retainedQuestionsHash);
|
|
3580
|
+
return { kind: "delivery_failure", code: "question.human_channel_failed", presentedInput: retained };
|
|
3581
|
+
}
|
|
3582
|
+
if (reading.shape === "unavailable")
|
|
3583
|
+
return { kind: "unavailable", parkDeclined: true, presentedInput: retained };
|
|
3584
|
+
const answerSnapshot = reading.answer;
|
|
3585
|
+
bindOutcome({ kind: "answered", answer: answerSnapshot }, retainedQuestionsHash);
|
|
3586
|
+
return { kind: "answered", presentedInput: retained };
|
|
3587
|
+
}
|
|
3588
|
+
const error = settlement.tag === "threw"
|
|
3589
|
+
? settlement.error
|
|
3590
|
+
: Object.assign(new Error("the task ended while this question was still out"), { name: "AbortError" });
|
|
3591
|
+
bindOutcome({ kind: "failed", error }, retainedQuestionsHash);
|
|
3592
|
+
return {
|
|
3593
|
+
kind: "delivery_failure",
|
|
3594
|
+
code: settlement.tag === "aborted" || abortController.signal.aborted ? "question.aborted" : "question.human_channel_failed",
|
|
3595
|
+
presentedInput: retained,
|
|
3596
|
+
};
|
|
3597
|
+
}
|
|
3598
|
+
catch (err) {
|
|
3599
|
+
bindOutcome({ kind: "failed", error: err }, retainedQuestionsHash);
|
|
3600
|
+
return { kind: "delivery_failure", code: "question.human_channel_failed", presentedInput: retained };
|
|
3601
|
+
}
|
|
3602
|
+
};
|
|
3603
|
+
const suspendAsk = parkLaneArmed && checkpointStore !== undefined
|
|
3604
|
+
? async (req, postHookArgs, safety, liveFaceUnavailable) => {
|
|
3605
|
+
const syncFirstEligible = req.toolName === ASK_USER_QUESTION_TOOL_NAME ? contentAskRoutable(req.toolCallId) : onAsk !== undefined;
|
|
3606
|
+
if (syncFirstEligible &&
|
|
3331
3607
|
runtimeCaps?.forceDurableGate !== true &&
|
|
3332
|
-
|
|
3333
|
-
req.toolName !== ASK_USER_QUESTION_TOOL_NAME &&
|
|
3608
|
+
liveFaceUnavailable !== true &&
|
|
3334
3609
|
!inheritedUnavailableAsks.has(req.toolCallId)) {
|
|
3335
3610
|
return undefined;
|
|
3336
3611
|
}
|
|
@@ -3519,9 +3794,11 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3519
3794
|
onNotifyError: (f) => emitTrace(deps.tracer, () => ({ kind: "observer.notify_failed", version: 1, taskId: spec.taskId ?? sessionId, site: f.site, message: f.error.message, ts: Date.now() })),
|
|
3520
3795
|
event: e,
|
|
3521
3796
|
preToolUse: hooks?.preToolUse,
|
|
3797
|
+
...(hookEnvFace !== undefined ? { hookEnv: hookEnvFace } : {}),
|
|
3522
3798
|
adjudicate,
|
|
3523
3799
|
resolveAsk: resolveAskBound,
|
|
3524
3800
|
suspendAsk,
|
|
3801
|
+
resolveContentAsk,
|
|
3525
3802
|
egress: egressTools.has(e.toolName),
|
|
3526
3803
|
irreversibility: irreversibilityTier.get(e.toolName),
|
|
3527
3804
|
reversibilityProbe: reversibilityProbes.get(e.toolName),
|
|
@@ -3574,7 +3851,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3574
3851
|
isInterrupt: abortController.signal.aborted || spec.signal?.aborted === true,
|
|
3575
3852
|
content: e.content.map((c) => ({ ...c })),
|
|
3576
3853
|
details: clonedDetails,
|
|
3577
|
-
}, { toolCallId: e.toolCallId, toolName: e.toolName });
|
|
3854
|
+
}, { toolCallId: e.toolCallId, toolName: e.toolName, ...(hookEnvFace !== undefined ? { env: hookEnvFace } : {}) });
|
|
3578
3855
|
if (patch?.additionalContext) {
|
|
3579
3856
|
content = [...content, { type: "text", text: formatHookFeedback(patch.additionalContext) }];
|
|
3580
3857
|
changed = true;
|
|
@@ -3582,7 +3859,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3582
3859
|
}
|
|
3583
3860
|
}
|
|
3584
3861
|
else if (hooks?.postToolUse) {
|
|
3585
|
-
const patch = await hooks.postToolUse(e.toolName, e.input, { content: e.content, details: e.details, isError: e.isError }, { toolCallId: e.toolCallId, toolName: e.toolName });
|
|
3862
|
+
const patch = await hooks.postToolUse(e.toolName, e.input, { content: e.content, details: e.details, isError: e.isError }, { toolCallId: e.toolCallId, toolName: e.toolName, ...(hookEnvFace !== undefined ? { env: hookEnvFace } : {}) });
|
|
3586
3863
|
if (patch?.updatedOutput) {
|
|
3587
3864
|
content = patch.updatedOutput;
|
|
3588
3865
|
changed = true;
|
|
@@ -3831,7 +4108,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3831
4108
|
: undefined;
|
|
3832
4109
|
overheadState.promptChars = systemPrompt.length;
|
|
3833
4110
|
const preparedHolder = {};
|
|
3834
|
-
const buildPrepared = () => ({ harness, session, sessionId, taskRootPath, model, thinking, compModel, mcp: mcp, ...(a2a !== undefined && a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), cwdRef: handsCwdRef, ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), denyNarrowingPolicy, ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), releaseSignal, cacheBreakDetector, cacheFingerprint, promptManifest, epochDeclaredSections, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, ownedEnv, suspendRef, suspendProgressRef, reviewRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, brainCallGuardrailRef, suspendForReview, resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, readTaskFile, recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent } } : {}), planModeRef, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, listBackgroundTasks, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}) });
|
|
4111
|
+
const buildPrepared = () => ({ harness, session, sessionId, taskRootPath, model, thinking, compModel, mcp: mcp, ...(a2a !== undefined && a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), cwdRef: handsCwdRef, ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), denyNarrowingPolicy, ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), releaseSignal, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, epochDeclaredSections, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, ownedEnv, suspendRef, suspendProgressRef, reviewRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, brainCallGuardrailRef, suspendForReview, resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, readTaskFile, recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent } } : {}), planModeRef, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, listBackgroundTasks, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}) });
|
|
3835
4112
|
const prepared = buildPrepared();
|
|
3836
4113
|
preparedHolder.current = prepared;
|
|
3837
4114
|
return prepared;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import { type Checkpoint, type CheckpointToken, type ReopenReason, type ResumeOutcome } from "../checkpoint-store.js";
|
|
1
|
+
import { type Model } from "../../internal/llm.js";
|
|
2
|
+
import { type Checkpoint, type CheckpointToken, type PendingSteerEntry, type ReopenReason, type ResumeOutcome } from "../checkpoint-store.js";
|
|
3
3
|
import type { RunInternals } from "./prepare-task.js";
|
|
4
4
|
import { type TaskOutcome } from "../task-outcome.js";
|
|
5
5
|
import { type SideQuerySpec, type SideQueryResult } from "../side-query.js";
|
|
@@ -13,10 +13,7 @@ interface ResumeRun {
|
|
|
13
13
|
outcome: Extract<ResumeOutcome, {
|
|
14
14
|
gate: "policy_ask" | "resource_limit" | "dry_run_review" | "plan_review" | "wake";
|
|
15
15
|
}>;
|
|
16
|
-
wakeMessage?:
|
|
17
|
-
text: string;
|
|
18
|
-
trusted: boolean;
|
|
19
|
-
};
|
|
16
|
+
wakeMessage?: Omit<PendingSteerEntry, "seq">;
|
|
20
17
|
onEnvRestoreFailed?: (reason: ReopenReason) => Promise<void>;
|
|
21
18
|
decisionDelivered?: boolean;
|
|
22
19
|
}
|