@tangle-network/agent-runtime 0.306.1 → 0.307.2
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/dist/{activation-wZ-8vOjV.d.ts → activation-Bdugb7li.d.ts} +3 -3
- package/dist/{activation-C5wesfzd.js → activation-DNZrAzZM.js} +3 -3
- package/dist/{activation-C5wesfzd.js.map → activation-DNZrAzZM.js.map} +1 -1
- package/dist/agent.d.ts +2 -2
- package/dist/agent.js +2 -2
- package/dist/{bundle-C8EO05u3.js → bundle-E6mbRX2P.js} +2 -2
- package/dist/{bundle-C8EO05u3.js.map → bundle-E6mbRX2P.js.map} +1 -1
- package/dist/candidate-execution/index.js +5 -5
- package/dist/{coordination-driver-yj9HPXef.js → coordination-driver-DCQUXZ54.js} +3 -3
- package/dist/{coordination-driver-yj9HPXef.js.map → coordination-driver-DCQUXZ54.js.map} +1 -1
- package/dist/{delegate-KtrL9HWq.js → delegate-BcMmgX_Y.js} +2 -2
- package/dist/{delegate-KtrL9HWq.js.map → delegate-BcMmgX_Y.js.map} +1 -1
- package/dist/durable.d.ts +2 -2
- package/dist/durable.js +57 -6
- package/dist/durable.js.map +1 -1
- package/dist/{graph-DcdyHbgf.js → graph-D2yO7Epi.js} +5 -4
- package/dist/graph-D2yO7Epi.js.map +1 -0
- package/dist/{improvement-cycle-DsN-TVXR.js → improvement-cycle-C6PDngmf.js} +10 -6
- package/dist/{improvement-cycle-DsN-TVXR.js.map → improvement-cycle-C6PDngmf.js.map} +1 -1
- package/dist/{index-DflDZq_I.d.ts → index-1T1fjIUs.d.ts} +72 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +9 -9
- package/dist/intelligence.d.ts +3 -3
- package/dist/intelligence.js +7 -7
- package/dist/kernel.d.ts +4 -4
- package/dist/kernel.js +8 -8
- package/dist/{loop-runner-bin-DZfRUVWy.d.ts → loop-runner-bin-Be2jWumB.d.ts} +3 -3
- package/dist/{loop-runner-bin-rVrSX5l1.js → loop-runner-bin-Bwxtx1go.js} +3 -3
- package/dist/{loop-runner-bin-rVrSX5l1.js.map → loop-runner-bin-Bwxtx1go.js.map} +1 -1
- package/dist/loop-runner-bin.d.ts +1 -1
- package/dist/loop-runner-bin.js +1 -1
- package/dist/mcp/bin.js +3 -3
- package/dist/mcp/index.d.ts +5 -5
- package/dist/mcp/index.js +5 -5
- package/dist/{openai-tools-YO30D2s3.d.ts → openai-tools-C-lvIN3-.d.ts} +2 -2
- package/dist/{prepare--nWcazPr.js → prepare-CulUz6Wm.js} +3 -3
- package/dist/{prepare--nWcazPr.js.map → prepare-CulUz6Wm.js.map} +1 -1
- package/dist/{profile-h04LDjV6.js → profile-DY9lT3gH.js} +2 -2
- package/dist/{profile-h04LDjV6.js.map → profile-DY9lT3gH.js.map} +1 -1
- package/dist/profiles.d.ts +1 -1
- package/dist/{protected-model-port-wwalbyXM.js → protected-model-port-BT2iYAsU.js} +4 -4
- package/dist/{protected-model-port-wwalbyXM.js.map → protected-model-port-BT2iYAsU.js.map} +1 -1
- package/dist/{provision-supervisor-WxFEFQeJ.js → provision-supervisor-De_3kjM3.js} +4 -4
- package/dist/{provision-supervisor-WxFEFQeJ.js.map → provision-supervisor-De_3kjM3.js.map} +1 -1
- package/dist/{runtime-B9eBIyws.js → runtime-B3dR7tdY.js} +9 -9
- package/dist/{runtime-B9eBIyws.js.map → runtime-B3dR7tdY.js.map} +1 -1
- package/dist/{search-executor-2tWr38Qw.js → search-executor-H1IRkoRg.js} +3 -3
- package/dist/{search-executor-2tWr38Qw.js.map → search-executor-H1IRkoRg.js.map} +1 -1
- package/dist/{server-CpKcrOPj.js → server-DATtZ0Q9.js} +4 -4
- package/dist/{server-CpKcrOPj.js.map → server-DATtZ0Q9.js.map} +1 -1
- package/dist/{stream-agent-turn-B1giFgOg.d.ts → stream-agent-turn-Ch1g6gYE.d.ts} +2 -2
- package/dist/{substrate-L_sC7jCD.d.ts → substrate-Buuxd_OX.d.ts} +2 -2
- package/dist/{supervise-DllOHM4M.js → supervise-D1qqMFAu.js} +164 -191
- package/dist/supervise-D1qqMFAu.js.map +1 -0
- package/dist/{supervisor-gCfG6K1-.js → supervisor-Dz4XXtK1.js} +1734 -1114
- package/dist/supervisor-Dz4XXtK1.js.map +1 -0
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +14 -14
- package/dist/tui/index.d.ts +1 -1
- package/dist/tui/index.js +1 -1
- package/dist/{types-DeuEkBhI.d.ts → types-CBcc0_5y.d.ts} +48 -1
- package/dist/{workspace-streams-ILw0eWZ0.js → workspace-streams-DaQceg2p.js} +7 -2
- package/dist/{workspace-streams-ILw0eWZ0.js.map → workspace-streams-DaQceg2p.js.map} +1 -1
- package/package.json +3 -3
- package/skills/profile-authoring/SKILL.md +6 -0
- package/dist/graph-DcdyHbgf.js.map +0 -1
- package/dist/supervise-DllOHM4M.js.map +0 -1
- package/dist/supervisor-gCfG6K1-.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { c as RetainedInteractiveAdmissionError, d as RetainedRunDispatchBindingError, f as RuntimeRunStateError, i as ConfigError, l as RetainedInteractiveBindingError, m as ValidationError$1, r as BackendTransportError, t as AgentEvalError$1, u as RetainedRunAdmissionError } from "./errors-DodWX-cb.js";
|
|
2
|
-
import { $ as randomUuid, B as addTokenUsage, G as errorMessage, H as cloneSpend, K as fnv1a32Hex, N as deepFreezeCandidate, O as verifyWorkspaceSnapshotArtifacts, Q as randomSuffix, U as cloneTokenUsage, V as chargedTokens, W as deleteBoxSafe, X as mapWithConcurrency, Y as isAsyncIterable$1, Z as promptCacheTokenClasses, _t as armDeadlineTimer, a as verifyAgentCandidateWorkspaceArtifacts, at as unmeteredSpend, bt as singleFlightTeardown, ct as zeroTokenUsage, dt as resourceTelemetry, et as roundBoxMinutes, ft as withBudgetResources, gt as ROOT_DEADLINE_REASON, i as readAgentCandidateWorkspaceArtifactFiles, it as throwIfAborted, k as verifiedArtifactChunks, lt as addResourceSpend, mt as CHILD_DEADLINE_REASON, nt as stringifySafe, o as verifyAgentCandidateWorkspaceTree, ot as withTimeout, pt as ACCEPTED_RESULT_GRACE_MS, q as hasCompleteCacheBreakdown, rt as throwAbort, st as zeroSpend, tt as sleep, u as verifyAgentCandidateWorkspaceArchive, ut as assertResources, vt as boundedChildDeadlineAt, xt as teardownExecutor, yt as isDeadlineAbortReason, z as addSpend } from "./workspace-streams-
|
|
2
|
+
import { $ as randomUuid, B as addTokenUsage, G as errorMessage, H as cloneSpend, K as fnv1a32Hex, N as deepFreezeCandidate, O as verifyWorkspaceSnapshotArtifacts, Q as randomSuffix, St as teardownSurfaces, U as cloneTokenUsage, V as chargedTokens, W as deleteBoxSafe, X as mapWithConcurrency, Y as isAsyncIterable$1, Z as promptCacheTokenClasses, _t as armDeadlineTimer, a as verifyAgentCandidateWorkspaceArtifacts, at as unmeteredSpend, bt as singleFlightTeardown, ct as zeroTokenUsage, dt as resourceTelemetry, et as roundBoxMinutes, ft as withBudgetResources, gt as ROOT_DEADLINE_REASON, i as readAgentCandidateWorkspaceArtifactFiles, it as throwIfAborted, k as verifiedArtifactChunks, lt as addResourceSpend, mt as CHILD_DEADLINE_REASON, nt as stringifySafe, o as verifyAgentCandidateWorkspaceTree, ot as withTimeout, pt as ACCEPTED_RESULT_GRACE_MS, q as hasCompleteCacheBreakdown, rt as throwAbort, st as zeroSpend, tt as sleep, u as verifyAgentCandidateWorkspaceArchive, ut as assertResources, vt as boundedChildDeadlineAt, xt as teardownExecutor, yt as isDeadlineAbortReason, z as addSpend } from "./workspace-streams-DaQceg2p.js";
|
|
3
3
|
import { runTaskQueue } from "./task-queue.js";
|
|
4
4
|
import { _ as agentHarness, a as concreteProfileModel, c as profileModelExecutionSettings, d as assertRouterAutoDeclaration, f as assertRouterAutoResponse, g as observedModelMatchesDeclared, h as observedModelHasSnapshot, l as profileProviderModel, m as mergeObservedModelIdentity, o as enforceTokenLimits, s as profileBridgeWireModel, t as assertExecutableAgentProfile, u as resolveRouterRetryPolicy } from "./model-policy-DydyWTQg.js";
|
|
5
5
|
import { n as assertNoSymlinkDescendant, r as publishExclusiveDurableFile } from "./durable-file-DWQA4ooo.js";
|
|
@@ -380,6 +380,29 @@ const decodeCodexTurnUsage = (event) => {
|
|
|
380
380
|
...record.cacheWriteInputTokens === void 0 ? {} : { cacheWriteInput: record.cacheWriteInputTokens }
|
|
381
381
|
};
|
|
382
382
|
};
|
|
383
|
+
/** Claude's adapter forwards one delta per response snapshot, keyed and deduplicated there. */
|
|
384
|
+
const decodeClaudeAssistantUsage = (event) => {
|
|
385
|
+
if (String(event.type ?? "") !== "raw") return void 0;
|
|
386
|
+
const envelope = plainRecord$2(event.data);
|
|
387
|
+
const data = envelope?.type === "raw" && plainRecord$2(envelope.event) !== void 0 ? plainRecord$2(envelope.event) : envelope;
|
|
388
|
+
if (data?.type !== "assistant.usage") return void 0;
|
|
389
|
+
if (typeof data.message_id !== "string" || data.message_id.length === 0) throw new ValidationError$1("claude assistant.usage: missing response identity");
|
|
390
|
+
const usage = plainRecord$2(data.usage);
|
|
391
|
+
if (!usage) throw new ValidationError$1("claude assistant.usage: usage must be an object");
|
|
392
|
+
const fresh = naturalNumber$1(usage.input_tokens, "input_tokens", "claude assistant.usage");
|
|
393
|
+
const cachedInput = naturalNumber$1(usage.cache_read_input_tokens, "cache_read_input_tokens", "claude assistant.usage");
|
|
394
|
+
const cacheWriteInput = naturalNumber$1(usage.cache_creation_input_tokens, "cache_creation_input_tokens", "claude assistant.usage");
|
|
395
|
+
const output = naturalNumber$1(usage.output_tokens, "output_tokens", "claude assistant.usage");
|
|
396
|
+
const input = fresh + cachedInput + cacheWriteInput;
|
|
397
|
+
if (!Number.isSafeInteger(input)) throw new ValidationError$1("claude assistant.usage: total input tokens exceed a safe integer");
|
|
398
|
+
return {
|
|
399
|
+
harness: "claude-code",
|
|
400
|
+
input,
|
|
401
|
+
output,
|
|
402
|
+
cachedInput,
|
|
403
|
+
cacheWriteInput
|
|
404
|
+
};
|
|
405
|
+
};
|
|
383
406
|
/**
|
|
384
407
|
* The harness → usage-decoder registry. Add a harness by adding one entry.
|
|
385
408
|
*
|
|
@@ -387,7 +410,10 @@ const decodeCodexTurnUsage = (event) => {
|
|
|
387
410
|
* can produce does not compile. A harness absent from this registry reports usage through the
|
|
388
411
|
* canonical events or not at all.
|
|
389
412
|
*/
|
|
390
|
-
const harnessUsageDecoders = {
|
|
413
|
+
const harnessUsageDecoders = {
|
|
414
|
+
codex: decodeCodexTurnUsage,
|
|
415
|
+
"claude-code": decodeClaudeAssistantUsage
|
|
416
|
+
};
|
|
391
417
|
/**
|
|
392
418
|
* Decode a sandbox event with one harness's adapter, or `undefined` when the event carries no
|
|
393
419
|
* harness-native usage.
|
|
@@ -6635,6 +6661,30 @@ async function captureProviderCheckpointWorkspace(port, context, marker) {
|
|
|
6635
6661
|
clearDeadline();
|
|
6636
6662
|
}
|
|
6637
6663
|
}
|
|
6664
|
+
/** Verify a running workspace copy before treating it as retained evidence. */
|
|
6665
|
+
async function captureProviderLiveWorkspace(port, context) {
|
|
6666
|
+
assertProviderWorkspaceRetentionPort(port, "provider workspace retention");
|
|
6667
|
+
if (port.captureLive === void 0) throw new ValidationError$1("provider workspace retention: the port has no captureLive");
|
|
6668
|
+
const timeoutMs = port.liveTimeoutMs ?? port.timeoutMs;
|
|
6669
|
+
const controller = new AbortController();
|
|
6670
|
+
const clearDeadline = armDeadlineTimer(timeoutMs, () => controller.abort(/* @__PURE__ */ new Error(`live workspace capture timed out after ${timeoutMs}ms`)), true);
|
|
6671
|
+
try {
|
|
6672
|
+
return await runAbortable(() => withCaptureSlot(checkpointSlots(port), controller.signal, async () => {
|
|
6673
|
+
const tree = detachedSnapshot(await port.captureLive({
|
|
6674
|
+
...context,
|
|
6675
|
+
signal: controller.signal
|
|
6676
|
+
}), "live workspace capture tree");
|
|
6677
|
+
if (tree?.kind !== "agent-candidate-workspace-tree") throw new Error("live workspace capture returned no workspace tree");
|
|
6678
|
+
if ((await verifyAgentCandidateWorkspaceTree(tree, port.artifacts, {
|
|
6679
|
+
...port.limits === void 0 ? {} : { limits: port.limits },
|
|
6680
|
+
signal: controller.signal
|
|
6681
|
+
})).files.length !== tree.files) throw new Error("live workspace capture tree misstates its file count");
|
|
6682
|
+
return tree;
|
|
6683
|
+
}), controller.signal, `live workspace capture timed out after ${timeoutMs}ms`);
|
|
6684
|
+
} finally {
|
|
6685
|
+
clearDeadline();
|
|
6686
|
+
}
|
|
6687
|
+
}
|
|
6638
6688
|
/** Validate the executable retention port at the create boundary. */
|
|
6639
6689
|
function assertProviderWorkspaceRetentionPort(port, context) {
|
|
6640
6690
|
if (!Number.isSafeInteger(port.timeoutMs) || port.timeoutMs <= 0) throw new ValidationError$1(`${context}: workspaceRetention.timeoutMs must be a positive safe integer`);
|
|
@@ -6643,7 +6693,14 @@ function assertProviderWorkspaceRetentionPort(port, context) {
|
|
|
6643
6693
|
if (typeof port.capture !== "function") throw new ValidationError$1(`${context}: workspaceRetention.capture is required`);
|
|
6644
6694
|
if (port.captureNative !== void 0 && typeof port.captureNative !== "function") throw new ValidationError$1(`${context}: workspaceRetention.captureNative must be a function`);
|
|
6645
6695
|
if (port.captureCheckpoint !== void 0 && typeof port.captureCheckpoint !== "function") throw new ValidationError$1(`${context}: workspaceRetention.captureCheckpoint must be a function`);
|
|
6646
|
-
|
|
6696
|
+
if (port.captureLive !== void 0 && typeof port.captureLive !== "function") throw new ValidationError$1(`${context}: workspaceRetention.captureLive must be a function`);
|
|
6697
|
+
if (port.liveIntervalMs !== void 0 && port.captureLive === void 0) throw new ValidationError$1(`${context}: workspaceRetention.liveIntervalMs requires captureLive`);
|
|
6698
|
+
for (const key of [
|
|
6699
|
+
"nativeIntervalMs",
|
|
6700
|
+
"nativeTimeoutMs",
|
|
6701
|
+
"liveIntervalMs",
|
|
6702
|
+
"liveTimeoutMs"
|
|
6703
|
+
]) {
|
|
6647
6704
|
const value = port[key];
|
|
6648
6705
|
if (value !== void 0 && (!Number.isSafeInteger(value) || value <= 0)) throw new ValidationError$1(`${context}: workspaceRetention.${key} must be a positive safe integer`);
|
|
6649
6706
|
}
|
|
@@ -9694,6 +9751,9 @@ var SpawnEventIndex = class {
|
|
|
9694
9751
|
if (node?.materialized) throw new Error(`spawn journal corrupted: duplicate materialization receipt for node '${event.id}' in tree '${this.root}'`);
|
|
9695
9752
|
if (!node?.spawned) throw new Error(`spawn journal corrupted: materialization for node '${event.id}' precedes its spawn in tree '${this.root}'`);
|
|
9696
9753
|
}
|
|
9754
|
+
if (event.kind === "seat-materialized") {
|
|
9755
|
+
if (!node?.materialized || node.authoredProfileDigest === void 0 || event.receipt.status !== "known" || event.receipt.authoredProfileDigest !== node.authoredProfileDigest || !Number.isSafeInteger(event.segmentIndex) || event.segmentIndex <= node.latestSeatMaterialization) throw new Error(`spawn journal corrupted: invalid seat materialization for node '${event.id}' in tree '${this.root}'`);
|
|
9756
|
+
}
|
|
9697
9757
|
if (event.kind === "execution-bound") {
|
|
9698
9758
|
if (node?.bindings.has(event.binding.attemptId)) throw new Error(`spawn journal corrupted: duplicate execution binding for node '${event.id}' attempt '${event.binding.attemptId}' in tree '${this.root}'`);
|
|
9699
9759
|
if (!node?.materialized) throw new Error(`spawn journal corrupted: execution binding for node '${event.id}' precedes materialization in tree '${this.root}'`);
|
|
@@ -9703,29 +9763,37 @@ var SpawnEventIndex = class {
|
|
|
9703
9763
|
/** Called only after validation and, for the file writer, a successful durable append. */
|
|
9704
9764
|
add(event) {
|
|
9705
9765
|
if (!outsideCursorNamespace(event)) this.cursors.add(event.seq);
|
|
9706
|
-
if (event.kind !== "spawned" && event.kind !== "materialized" && event.kind !== "execution-bound" && event.kind !== "execution-input" && event.kind !== "execution-admitted" && event.kind !== "execution-result" && event.kind !== "environment-teardown" && !closesCursorSlot(event)) return;
|
|
9766
|
+
if (event.kind !== "spawned" && event.kind !== "materialized" && event.kind !== "seat-materialized" && event.kind !== "execution-bound" && event.kind !== "execution-input" && event.kind !== "execution-admitted" && event.kind !== "execution-result" && event.kind !== "environment-teardown" && event.kind !== "environment-terminal" && !closesCursorSlot(event)) return;
|
|
9707
9767
|
let node = this.nodes.get(event.id);
|
|
9708
9768
|
if (!node) {
|
|
9709
9769
|
node = {
|
|
9710
9770
|
spawned: false,
|
|
9711
9771
|
closed: false,
|
|
9712
9772
|
materialized: false,
|
|
9773
|
+
latestSeatMaterialization: 0,
|
|
9713
9774
|
bindings: /* @__PURE__ */ new Set(),
|
|
9714
9775
|
inputs: /* @__PURE__ */ new Set(),
|
|
9715
9776
|
input: false,
|
|
9716
9777
|
result: false,
|
|
9717
9778
|
admissions: /* @__PURE__ */ new Map(),
|
|
9718
|
-
|
|
9779
|
+
unusableEnvironments: /* @__PURE__ */ new Set()
|
|
9719
9780
|
};
|
|
9720
9781
|
this.nodes.set(event.id, node);
|
|
9721
9782
|
}
|
|
9722
9783
|
if (event.kind === "environment-teardown") {
|
|
9723
|
-
if (event.destroyed) node.
|
|
9784
|
+
if (event.destroyed) node.unusableEnvironments.add(event.environmentId);
|
|
9785
|
+
return;
|
|
9786
|
+
}
|
|
9787
|
+
if (event.kind === "environment-terminal") {
|
|
9788
|
+
node.unusableEnvironments.add(event.environmentId);
|
|
9724
9789
|
return;
|
|
9725
9790
|
}
|
|
9726
9791
|
if (event.kind === "execution-admitted" && event.admission.phase === "environment") node.lastEnvironmentId = event.admission.environmentId;
|
|
9727
9792
|
if (event.kind === "spawned") node.spawned = true;
|
|
9728
|
-
else if (event.kind === "materialized")
|
|
9793
|
+
else if (event.kind === "materialized") {
|
|
9794
|
+
node.materialized = true;
|
|
9795
|
+
node.authoredProfileDigest = event.receipt.authoredProfileDigest;
|
|
9796
|
+
} else if (event.kind === "seat-materialized") node.latestSeatMaterialization = event.segmentIndex;
|
|
9729
9797
|
else if (event.kind === "execution-bound") node.bindings.add(event.binding.attemptId);
|
|
9730
9798
|
else if (event.kind === "execution-input") {
|
|
9731
9799
|
node.inputs.add(event.seq);
|
|
@@ -9748,7 +9816,7 @@ var SpawnEventIndex = class {
|
|
|
9748
9816
|
if (node.inputs.has(event.seq)) fail("has duplicate input sequence");
|
|
9749
9817
|
const environment = node.admissions.get("environment");
|
|
9750
9818
|
const ranIn = environment?.phase === "environment" ? environment.environmentId : node.lastEnvironmentId;
|
|
9751
|
-
const abandoned = ranIn !== void 0 && node.
|
|
9819
|
+
const abandoned = ranIn !== void 0 && node.unusableEnvironments.has(ranIn);
|
|
9752
9820
|
if (node.input && !node.result && !abandoned) fail("input replaces an unfinished invocation");
|
|
9753
9821
|
return;
|
|
9754
9822
|
}
|
|
@@ -9810,6 +9878,7 @@ const outsideKinds = /* @__PURE__ */ new Set([
|
|
|
9810
9878
|
"teardown-pending",
|
|
9811
9879
|
"teardown-confirmed",
|
|
9812
9880
|
"environment-teardown",
|
|
9881
|
+
"environment-terminal",
|
|
9813
9882
|
"workspace-checkpoint-requested",
|
|
9814
9883
|
"workspace-checkpoint",
|
|
9815
9884
|
"workspace-checkpoint-fork-requested",
|
|
@@ -9819,6 +9888,9 @@ const outsideKinds = /* @__PURE__ */ new Set([
|
|
|
9819
9888
|
"workspace-restored",
|
|
9820
9889
|
"workspace-capture",
|
|
9821
9890
|
"trace-unpropagated",
|
|
9891
|
+
"seat-segment",
|
|
9892
|
+
"seat-materialized",
|
|
9893
|
+
"seat-paused",
|
|
9822
9894
|
"paused",
|
|
9823
9895
|
"driver-attempt",
|
|
9824
9896
|
"node-inputs-resolved",
|
|
@@ -9889,6 +9961,7 @@ async function replaySpawnTree(journal, blobs, root) {
|
|
|
9889
9961
|
if (ev.kind === "teardown-unconfirmed") continue;
|
|
9890
9962
|
if (ev.kind === "teardown-pending" || ev.kind === "teardown-confirmed") continue;
|
|
9891
9963
|
if (ev.kind === "environment-teardown") continue;
|
|
9964
|
+
if (ev.kind === "environment-terminal") continue;
|
|
9892
9965
|
if (ev.kind === "workspace-checkpoint-requested") continue;
|
|
9893
9966
|
if (ev.kind === "workspace-checkpoint") continue;
|
|
9894
9967
|
if (ev.kind === "workspace-checkpoint-fork-requested") continue;
|
|
@@ -9898,6 +9971,7 @@ async function replaySpawnTree(journal, blobs, root) {
|
|
|
9898
9971
|
if (ev.kind === "workspace-restored") continue;
|
|
9899
9972
|
if (ev.kind === "workspace-capture") continue;
|
|
9900
9973
|
if (ev.kind === "trace-unpropagated") continue;
|
|
9974
|
+
if (ev.kind === "seat-segment" || ev.kind === "seat-materialized" || ev.kind === "seat-paused") continue;
|
|
9901
9975
|
if (ev.kind === "paused") continue;
|
|
9902
9976
|
if (ev.kind === "driver-attempt") continue;
|
|
9903
9977
|
if (ev.kind === "node-inputs-resolved") continue;
|
|
@@ -10049,7 +10123,7 @@ function materializeTreeView(events) {
|
|
|
10049
10123
|
if (Number.isFinite(settledAt)) node.settledAt = settledAt;
|
|
10050
10124
|
}
|
|
10051
10125
|
for (const ev of events) {
|
|
10052
|
-
if (ev.kind !== "materialized") continue;
|
|
10126
|
+
if (ev.kind !== "materialized" && ev.kind !== "seat-materialized") continue;
|
|
10053
10127
|
const node = requireNode(nodes, ev.id);
|
|
10054
10128
|
node.materialization = ev.receipt;
|
|
10055
10129
|
node.runtime = ev.receipt.runtime;
|
|
@@ -10930,6 +11004,7 @@ function createProviderExecutor(provider, profile, ctx, options, placement) {
|
|
|
10930
11004
|
if (workspaceSnapshot !== void 0) return workspaceSnapshot;
|
|
10931
11005
|
if (workspaceCapturePromise === void 0) {
|
|
10932
11006
|
workspaceOutcome = outcome;
|
|
11007
|
+
stopLiveMirror();
|
|
10933
11008
|
if (nativeTimer !== void 0) clearTimeout(nativeTimer);
|
|
10934
11009
|
nativeTimer = void 0;
|
|
10935
11010
|
const captureContext = {
|
|
@@ -10945,7 +11020,7 @@ function createProviderExecutor(provider, profile, ctx, options, placement) {
|
|
|
10945
11020
|
const reportTiming = retention?.onWorkspaceCapture;
|
|
10946
11021
|
let timing;
|
|
10947
11022
|
const capturedExecutionId = workspaceExecutionId;
|
|
10948
|
-
workspaceCapturePromise = (nativeInFlight
|
|
11023
|
+
workspaceCapturePromise = Promise.all([nativeInFlight, liveInFlight]).then(() => captureProviderWorkspaceSnapshot(workspaceRetention, captureContext, "environment", reportTiming === void 0 ? void 0 : (measured) => {
|
|
10949
11024
|
timing = measured;
|
|
10950
11025
|
})).finally(async () => {
|
|
10951
11026
|
if (timing === void 0 || reportTiming === void 0) return;
|
|
@@ -10998,6 +11073,38 @@ function createProviderExecutor(provider, profile, ctx, options, placement) {
|
|
|
10998
11073
|
const nativePort = options.workspaceRetention?.captureNative === void 0 ? void 0 : options.workspaceRetention;
|
|
10999
11074
|
let nativeInFlight;
|
|
11000
11075
|
let nativeTimer;
|
|
11076
|
+
const livePort = options.workspaceRetention?.captureLive === void 0 ? void 0 : options.workspaceRetention;
|
|
11077
|
+
let liveInFlight;
|
|
11078
|
+
let liveTimer;
|
|
11079
|
+
const stopLiveMirror = () => {
|
|
11080
|
+
if (liveTimer !== void 0) clearTimeout(liveTimer);
|
|
11081
|
+
liveTimer = void 0;
|
|
11082
|
+
};
|
|
11083
|
+
const startLiveMirror = (next) => {
|
|
11084
|
+
if (livePort?.liveIntervalMs === void 0) return;
|
|
11085
|
+
stopLiveMirror();
|
|
11086
|
+
const schedule = () => {
|
|
11087
|
+
liveTimer = setTimeout(() => {
|
|
11088
|
+
if (liveInFlight === void 0 && workspaceCapturePromise === void 0) {
|
|
11089
|
+
const tracked = captureProviderLiveWorkspace(livePort, {
|
|
11090
|
+
environment: next,
|
|
11091
|
+
executionId: workspaceExecutionId,
|
|
11092
|
+
...workspaceControlRef === void 0 ? {} : { controlRef: workspaceControlRef },
|
|
11093
|
+
...node === void 0 ? {} : { node },
|
|
11094
|
+
providerSessionId,
|
|
11095
|
+
nativeSessionId: null,
|
|
11096
|
+
profile: createProfile
|
|
11097
|
+
}).then(() => void 0, () => void 0).finally(() => {
|
|
11098
|
+
if (liveInFlight === tracked) liveInFlight = void 0;
|
|
11099
|
+
});
|
|
11100
|
+
liveInFlight = tracked;
|
|
11101
|
+
}
|
|
11102
|
+
schedule();
|
|
11103
|
+
}, livePort.liveIntervalMs);
|
|
11104
|
+
liveTimer.unref?.();
|
|
11105
|
+
};
|
|
11106
|
+
schedule();
|
|
11107
|
+
};
|
|
11001
11108
|
let nativeHoldsTranscript = false;
|
|
11002
11109
|
const stopNativeMirror = async () => {
|
|
11003
11110
|
if (nativeTimer !== void 0) clearTimeout(nativeTimer);
|
|
@@ -11052,6 +11159,7 @@ function createProviderExecutor(provider, profile, ctx, options, placement) {
|
|
|
11052
11159
|
return tracked;
|
|
11053
11160
|
};
|
|
11054
11161
|
const startNativeMirror = (next) => {
|
|
11162
|
+
startLiveMirror(next);
|
|
11055
11163
|
if (nativePort === void 0) return;
|
|
11056
11164
|
if (nativeTimer !== void 0) clearTimeout(nativeTimer);
|
|
11057
11165
|
const interval = nativePort.nativeIntervalMs ?? 12e4;
|
|
@@ -11699,6 +11807,7 @@ async function* streamProviderExecutor(args) {
|
|
|
11699
11807
|
handCaptureToOwner(settledResult, outcome, true);
|
|
11700
11808
|
}
|
|
11701
11809
|
} catch (error) {
|
|
11810
|
+
yield* creditUsage(usageLedger.settleTurn(args.profile.name ?? "agent"));
|
|
11702
11811
|
failure = source.retained ? new RetainedExecutionPendingError(error) : error;
|
|
11703
11812
|
failed = true;
|
|
11704
11813
|
if (args.options.workspaceRetention !== void 0) args.onUnsettledFailure();
|
|
@@ -20886,487 +20995,1134 @@ function singleShotDriver(maxIterations) {
|
|
|
20886
20995
|
};
|
|
20887
20996
|
}
|
|
20888
20997
|
//#endregion
|
|
20889
|
-
//#region src/runtime/supervise/
|
|
20998
|
+
//#region src/runtime/supervise/continuation.ts
|
|
20890
20999
|
/**
|
|
21000
|
+
* The continuation: what a manager with a completion check is told when its turn ends and the
|
|
21001
|
+
* check is unmet, and the one rule that decides whether it is sent back.
|
|
20891
21002
|
*
|
|
20892
|
-
*
|
|
20893
|
-
*
|
|
20894
|
-
*
|
|
20895
|
-
*
|
|
20896
|
-
*
|
|
20897
|
-
*
|
|
20898
|
-
* nothing that holds N slots full, which is why a 5-worker run can peak at 2 live workers and sit
|
|
20899
|
-
* ~50% idle. This is a policy over the EXISTING `Scope.spawn` / `Scope.next` primitives: it adds
|
|
20900
|
-
* no second admission path, so the conserved budget pool stays the only fence on total work and
|
|
20901
|
-
* `width` is only a fence on simultaneous work.
|
|
20902
|
-
*
|
|
20903
|
-
* Fail-closed by construction: an admission rejection (`budget-exhausted` / `depth-exceeded`) is
|
|
20904
|
-
* recorded and STOPS further admission — the loop then drains what is already live and returns.
|
|
20905
|
-
* It never retries a rejected spawn against the same pool, and it never spawns past `width`.
|
|
20906
|
-
*
|
|
20907
|
-
* ── Concurrency ────────────────────────────────────────────────────────────────────────────────
|
|
20908
|
-
*
|
|
20909
|
-
* `width` bounds the children THIS dispatcher holds in flight. The tree-wide bound on working
|
|
20910
|
-
* agents is `SuperviseOptions.workerSlots` (`./worker-slots`): a spawn past it is queued by the
|
|
20911
|
-
* scope, not refused, so a `width` above the free slots only lengthens the allocator's queue.
|
|
20912
|
-
* `SandboxLineage`'s fork concurrency bounds boxes inside ONE leaf's fork wave, a different unit.
|
|
21003
|
+
* Measured on discovery-lab before this module (2026-09-24, 670 settled runs, 1,596 re-entries):
|
|
21004
|
+
* 1,565 re-entries followed a failed turn and resent the original task, and 31 carried note text.
|
|
21005
|
+
* The note Runtime wrote itself held seven fixed lines and no field for the check's verdict. Of 40
|
|
21006
|
+
* episodes where the director ended on its own and the outside check disagreed, 33 were told
|
|
21007
|
+
* nothing before they ended. 100 of 236 resubmits sent the identical packet. So the director
|
|
21008
|
+
* mostly graded itself, and when it was wrong it heard nothing it could use.
|
|
20913
21009
|
*
|
|
20914
|
-
*
|
|
21010
|
+
* The design (discovery `docs/38-one-loop-and-continuation.md`) makes three things single, and
|
|
21011
|
+
* this module holds the part Runtime owns:
|
|
20915
21012
|
*
|
|
20916
|
-
*
|
|
20917
|
-
*
|
|
20918
|
-
*
|
|
20919
|
-
*
|
|
20920
|
-
*
|
|
20921
|
-
*
|
|
20922
|
-
*
|
|
20923
|
-
*
|
|
20924
|
-
*
|
|
21013
|
+
* - ONE CHECK. A check reading is a {@link CheckVerdict}: pass, the items it read, the composite,
|
|
21014
|
+
* and one `FAIL <item> <where>: <reason>` line per failed item. The same check decides
|
|
21015
|
+
* `submit_result`, runs when a turn ends without an accepted result, scores the finished run,
|
|
21016
|
+
* and ranks versions. A check that could not run gives no verdict ({@link CheckUnavailableError}),
|
|
21017
|
+
* and the loop pauses instead of blaming the director.
|
|
21018
|
+
* - ONE RESEND RULE. {@link ContinuationPolicy} is required for a manager with a check. It holds a
|
|
21019
|
+
* deadline and `maxBarren`, the re-entered turns in a row that may end without progress. There
|
|
21020
|
+
* is no re-prompt count and no default: a retry default in source is a research decision.
|
|
21021
|
+
* - ONE NOTE. {@link composeContinuationNote} writes it. Runtime owns the facts and their order;
|
|
21022
|
+
* the {@link ContinuationProfile} owns every instruction word, so an optimizer can change the
|
|
21023
|
+
* words without touching code. A play may append a section, never remove or rewrite one.
|
|
20925
21024
|
*
|
|
20926
|
-
*
|
|
21025
|
+
* Evidence behind the note's shape: located errors help (given the first mistake's true location,
|
|
21026
|
+
* fix rates rose 23.5 to 43.9 points, Tyen 2023); unsupported pressure does not (threats and tips
|
|
21027
|
+
* had no significant effect, Wharton 2025; challenges without evidence flipped correct answers,
|
|
21028
|
+
* FlipFlop); repeated summaries drop detail while itemized additions do not (ACE). So the note is
|
|
21029
|
+
* a list of located facts, findings are added and marked resolved rather than rewritten, and the
|
|
21030
|
+
* profile, not this file, decides how blunt the words are.
|
|
20927
21031
|
*/
|
|
20928
21032
|
/**
|
|
20929
|
-
*
|
|
20930
|
-
*
|
|
20931
|
-
*
|
|
20932
|
-
* The loop is: fill free slots from `nextUnit` → `await scope.next()` → deliver the settlement →
|
|
20933
|
-
* refill → repeat. Because the refill happens immediately after each settlement rather than after
|
|
20934
|
-
* a whole round, a slow child never idles the other slots.
|
|
21033
|
+
* The check could not run: its box did not start, its judge's provider refused, its program
|
|
21034
|
+
* crashed. It is not a verdict on the result. Inside a run the loop pauses, as it does for an
|
|
21035
|
+
* unavailable upstream, and the refusal tells the director its result was not judged.
|
|
20935
21036
|
*/
|
|
20936
|
-
|
|
20937
|
-
|
|
20938
|
-
|
|
20939
|
-
|
|
20940
|
-
const live = /* @__PURE__ */ new Set();
|
|
20941
|
-
let admitted = 0;
|
|
20942
|
-
let peakLive = 0;
|
|
20943
|
-
let queueDry = false;
|
|
20944
|
-
let stopReason = "drained";
|
|
20945
|
-
const fill = async () => {
|
|
20946
|
-
while (live.size < opts.width) {
|
|
20947
|
-
if (queueDry) return;
|
|
20948
|
-
if (scope.signal.aborted) {
|
|
20949
|
-
stopReason = "aborted";
|
|
20950
|
-
queueDry = true;
|
|
20951
|
-
return;
|
|
20952
|
-
}
|
|
20953
|
-
if (opts.shouldStop?.() === true) {
|
|
20954
|
-
stopReason = "stopped";
|
|
20955
|
-
queueDry = true;
|
|
20956
|
-
return;
|
|
20957
|
-
}
|
|
20958
|
-
const unit = await opts.nextUnit();
|
|
20959
|
-
if (unit === void 0) {
|
|
20960
|
-
queueDry = true;
|
|
20961
|
-
return;
|
|
20962
|
-
}
|
|
20963
|
-
const res = scope.spawn(unit.agent, unit.task, unit.opts);
|
|
20964
|
-
if (!res.ok) {
|
|
20965
|
-
rejected.push(`${unit.opts.label}: ${res.reason}`);
|
|
20966
|
-
stopReason = "not-admitted";
|
|
20967
|
-
queueDry = true;
|
|
20968
|
-
return;
|
|
20969
|
-
}
|
|
20970
|
-
live.add(res.handle.id);
|
|
20971
|
-
admitted += 1;
|
|
20972
|
-
if (live.size > peakLive) peakLive = live.size;
|
|
20973
|
-
}
|
|
20974
|
-
};
|
|
20975
|
-
await fill();
|
|
20976
|
-
while (live.size > 0) {
|
|
20977
|
-
const s = await scope.next();
|
|
20978
|
-
if (s === null) break;
|
|
20979
|
-
live.delete(s.handle.id);
|
|
20980
|
-
settled.push(s);
|
|
20981
|
-
await opts.onSettled?.(s);
|
|
20982
|
-
await fill();
|
|
21037
|
+
var CheckUnavailableError = class extends Error {
|
|
21038
|
+
constructor(message, options) {
|
|
21039
|
+
super(message, options);
|
|
21040
|
+
this.name = "CheckUnavailableError";
|
|
20983
21041
|
}
|
|
20984
|
-
|
|
20985
|
-
|
|
20986
|
-
|
|
20987
|
-
|
|
20988
|
-
|
|
20989
|
-
|
|
20990
|
-
|
|
21042
|
+
};
|
|
21043
|
+
/** Read a check function's return value into a verdict. Anything but `true` or a passing verdict
|
|
21044
|
+
* is a failure: a check fails closed. */
|
|
21045
|
+
function checkVerdictOf(outcome) {
|
|
21046
|
+
if (outcome === true) return { pass: true };
|
|
21047
|
+
if (typeof outcome !== "object" || outcome === null || Array.isArray(outcome)) return { pass: false };
|
|
21048
|
+
const raw = outcome;
|
|
21049
|
+
const items = typeof raw.items === "object" && raw.items !== null && !Array.isArray(raw.items) ? Object.fromEntries(Object.entries(raw.items).filter((entry) => typeof entry[1] === "number" && Number.isFinite(entry[1]))) : void 0;
|
|
21050
|
+
const failures = Array.isArray(raw.failures) ? raw.failures.filter((line) => typeof line === "string" && line.trim() !== "") : void 0;
|
|
21051
|
+
return Object.freeze({
|
|
21052
|
+
pass: raw.pass === true,
|
|
21053
|
+
...items === void 0 ? {} : { items: Object.freeze(items) },
|
|
21054
|
+
...finite(raw.composite) ? { composite: raw.composite } : {},
|
|
21055
|
+
...finite(raw.threshold) ? { threshold: raw.threshold } : {},
|
|
21056
|
+
...failures === void 0 ? {} : { failures: Object.freeze(failures) },
|
|
21057
|
+
...typeof raw.review === "string" && raw.review.trim() !== "" ? { review: raw.review.trim() } : {}
|
|
21058
|
+
});
|
|
20991
21059
|
}
|
|
20992
21060
|
/**
|
|
20993
|
-
*
|
|
20994
|
-
*
|
|
20995
|
-
*
|
|
21061
|
+
* Read an agent-eval `JudgeScore` from a check program into a verdict.
|
|
21062
|
+
*
|
|
21063
|
+
* Each dimension is a checked item. `notes` lines that start with `FAIL ` are the failures; the
|
|
21064
|
+
* remaining lines are the check's review. The verdict passes when `composite >= threshold` and the
|
|
21065
|
+
* score is not marked `failed`; a `failed` score means the judge itself did not run, which is
|
|
21066
|
+
* {@link CheckUnavailableError}, not a verdict.
|
|
20996
21067
|
*/
|
|
20997
|
-
function
|
|
20998
|
-
if (
|
|
20999
|
-
|
|
21000
|
-
|
|
21001
|
-
|
|
21002
|
-
|
|
21003
|
-
|
|
21004
|
-
|
|
21005
|
-
|
|
21006
|
-
|
|
21007
|
-
|
|
21008
|
-
|
|
21009
|
-
return {
|
|
21010
|
-
agent: u.agent,
|
|
21011
|
-
task: u.task,
|
|
21012
|
-
opts: {
|
|
21013
|
-
budget,
|
|
21014
|
-
label: u.label
|
|
21015
|
-
}
|
|
21016
|
-
};
|
|
21017
|
-
};
|
|
21018
|
-
}
|
|
21019
|
-
//#endregion
|
|
21020
|
-
//#region src/runtime/retained-interactive-handle.ts
|
|
21021
|
-
function createRetainedInteractiveRunHandle(environment, inputRef, capabilities, requestedStart) {
|
|
21022
|
-
const ref = freezeInteractiveRef(inputRef);
|
|
21023
|
-
const source = environment.interactive(ref);
|
|
21024
|
-
if (!sameInteractiveRef(source.ref, ref)) throw new Error("provider reconstructed a different interactive process");
|
|
21025
|
-
if (!source.sendPrompt) throw new Error("provider declared interactive prompt support but exposed no prompt method");
|
|
21026
|
-
return Object.freeze({
|
|
21027
|
-
ref,
|
|
21028
|
-
capabilities,
|
|
21029
|
-
claimControl: async (request, options) => exactClaim(ref, request, await awaitAbortable$1(Promise.resolve().then(() => source.claimControl(request, options)), options?.signal)),
|
|
21030
|
-
status: async (options) => exactStatus(ref, await awaitAbortable$1(Promise.resolve().then(() => source.status(options)), options?.signal), requestedStart),
|
|
21031
|
-
attach: async (request, options) => exactTerminal(ref, request, await awaitAbortable$1(Promise.resolve().then(() => source.attach(request, options)), options?.signal)),
|
|
21032
|
-
sendPrompt: async (command, options) => exactPrompt(ref, await awaitAbortable$1(Promise.resolve().then(() => source.sendPrompt(command, options)), options?.signal), command),
|
|
21033
|
-
stop: async (command, options) => exactStop(ref, await awaitAbortable$1(Promise.resolve().then(() => source.stop(command, options)), options?.signal), command)
|
|
21068
|
+
function verdictFromJudgeScore(score, threshold) {
|
|
21069
|
+
if (score.failed === true) throw new CheckUnavailableError(`the check's judge did not run: ${score.notes}`);
|
|
21070
|
+
const lines = score.notes.split("\n").map((line) => line.trimEnd());
|
|
21071
|
+
const failures = lines.filter((line) => line.startsWith("FAIL "));
|
|
21072
|
+
const review = lines.filter((line) => !line.startsWith("FAIL ") && line.trim() !== "").join("\n");
|
|
21073
|
+
return checkVerdictOf({
|
|
21074
|
+
pass: score.composite >= threshold,
|
|
21075
|
+
items: score.dimensions,
|
|
21076
|
+
composite: score.composite,
|
|
21077
|
+
threshold,
|
|
21078
|
+
failures,
|
|
21079
|
+
...review === "" ? {} : { review }
|
|
21034
21080
|
});
|
|
21035
21081
|
}
|
|
21036
|
-
|
|
21037
|
-
|
|
21082
|
+
/** Items that fail in `verdict`: every item below 1, or the named items of its FAIL lines. */
|
|
21083
|
+
function failedItems(verdict) {
|
|
21084
|
+
if (verdict.items !== void 0) return Object.entries(verdict.items).filter(([, value]) => value < 1).map(([name]) => name);
|
|
21085
|
+
return (verdict.failures ?? []).map((line) => line.slice(5).split(/[\s:]/u)[0] ?? "");
|
|
21038
21086
|
}
|
|
21039
|
-
|
|
21040
|
-
|
|
21041
|
-
|
|
21042
|
-
if (acknowledgement.control && !agentInteractiveSessionControlClaimMatchesRef(ref, acknowledgement.control)) throw new RetainedRunProviderContractError("provider returned a control claim for another interactive process");
|
|
21043
|
-
return acknowledgement;
|
|
21087
|
+
/** Items that pass in `verdict`. */
|
|
21088
|
+
function passedItems(verdict) {
|
|
21089
|
+
return Object.entries(verdict.items ?? {}).filter(([, value]) => value >= 1).map(([name]) => name);
|
|
21044
21090
|
}
|
|
21045
|
-
|
|
21046
|
-
|
|
21047
|
-
if (
|
|
21048
|
-
|
|
21049
|
-
|
|
21050
|
-
}
|
|
21051
|
-
|
|
21052
|
-
|
|
21053
|
-
if (
|
|
21054
|
-
if (
|
|
21055
|
-
|
|
21056
|
-
|
|
21057
|
-
|
|
21058
|
-
try {
|
|
21059
|
-
return schema.parse(value);
|
|
21060
|
-
} catch {
|
|
21061
|
-
throw new RetainedRunProviderContractError(`provider returned an invalid interactive ${operation} acknowledgement`);
|
|
21091
|
+
/** Resolve and check a policy before any compute. Returns the deadline in epoch ms. */
|
|
21092
|
+
function admitContinuationPolicy(policy, context) {
|
|
21093
|
+
if (typeof policy !== "object" || policy === null) throw new ValidationError$1(`${context}: continuation must be an object`);
|
|
21094
|
+
const deadlineMs = typeof policy.deadline === "string" ? Date.parse(policy.deadline) : policy.deadline;
|
|
21095
|
+
if (typeof deadlineMs !== "number" || !Number.isFinite(deadlineMs) || deadlineMs <= 0) throw new ValidationError$1(`${context}: continuation.deadline must be a finite time (epoch ms or ISO 8601)`);
|
|
21096
|
+
if (!Number.isInteger(policy.maxBarren) || policy.maxBarren < 1) throw new ValidationError$1(`${context}: continuation.maxBarren must be an integer >= 1`);
|
|
21097
|
+
if (policy.failures !== "verbatim" && policy.failures !== "off") throw new ValidationError$1(`${context}: continuation.failures must be 'verbatim' or 'off'`);
|
|
21098
|
+
if (policy.panel !== "on" && policy.panel !== "off") throw new ValidationError$1(`${context}: continuation.panel must be 'on' or 'off'`);
|
|
21099
|
+
if (policy.bar !== "on" && policy.bar !== "off") throw new ValidationError$1(`${context}: continuation.bar must be 'on' or 'off'`);
|
|
21100
|
+
if (policy.panel === "on") {
|
|
21101
|
+
if (typeof policy.runPanel !== "function") throw new ValidationError$1(`${context}: continuation.panel 'on' needs runPanel`);
|
|
21102
|
+
const usd = policy.panelUsd;
|
|
21103
|
+
if (usd === void 0 || !finite(usd.perContinuation) || !finite(usd.perRun) || usd.perContinuation <= 0 || usd.perRun < usd.perContinuation) throw new ValidationError$1(`${context}: continuation.panel 'on' needs panelUsd with 0 < perContinuation <= perRun`);
|
|
21062
21104
|
}
|
|
21105
|
+
if (policy.append !== void 0 && typeof policy.append !== "function") throw new ValidationError$1(`${context}: continuation.append must be a function`);
|
|
21106
|
+
admitContinuationProfile(policy.profile, context);
|
|
21107
|
+
return deadlineMs;
|
|
21063
21108
|
}
|
|
21064
|
-
|
|
21065
|
-
|
|
21066
|
-
|
|
21067
|
-
|
|
21068
|
-
|
|
21069
|
-
|
|
21070
|
-
|
|
21109
|
+
/** The facts a profile template may name. */
|
|
21110
|
+
const CONTINUATION_FACTS = [
|
|
21111
|
+
"composite",
|
|
21112
|
+
"threshold",
|
|
21113
|
+
"failed",
|
|
21114
|
+
"total",
|
|
21115
|
+
"reads",
|
|
21116
|
+
"owed",
|
|
21117
|
+
"settled",
|
|
21118
|
+
"delivered",
|
|
21119
|
+
"continuation"
|
|
21120
|
+
];
|
|
21121
|
+
const factNames = new Set(CONTINUATION_FACTS);
|
|
21122
|
+
const placeholder = /\{([a-zA-Z]+)\}/gu;
|
|
21123
|
+
function admitContinuationProfile(profile, context) {
|
|
21124
|
+
if (typeof profile !== "object" || profile === null) throw new ValidationError$1(`${context}: continuation.profile must be an object`);
|
|
21125
|
+
if (typeof profile.id !== "string" || profile.id.trim() === "") throw new ValidationError$1(`${context}: continuation.profile.id must be non-empty`);
|
|
21126
|
+
const texts = [
|
|
21127
|
+
["opening", profile.opening],
|
|
21128
|
+
["plan", profile.plan],
|
|
21129
|
+
["rules", profile.rules],
|
|
21130
|
+
...Object.entries(profile.headings ?? {}).map(([key, value]) => [`headings.${key}`, value]),
|
|
21131
|
+
...profile.barRule === void 0 ? [] : [["barRule", profile.barRule]]
|
|
21132
|
+
];
|
|
21133
|
+
for (const key of [
|
|
21134
|
+
"failures",
|
|
21135
|
+
"protected",
|
|
21136
|
+
"changed",
|
|
21137
|
+
"findings",
|
|
21138
|
+
"bar",
|
|
21139
|
+
"plan",
|
|
21140
|
+
"rules"
|
|
21141
|
+
]) if (typeof profile.headings?.[key] !== "string") throw new ValidationError$1(`${context}: continuation.profile.headings.${key} must be a string`);
|
|
21142
|
+
for (const [key, text] of texts) {
|
|
21143
|
+
if (typeof text !== "string") throw new ValidationError$1(`${context}: continuation.profile.${key} must be a string`);
|
|
21144
|
+
for (const match of text.matchAll(placeholder)) if (!factNames.has(match[1] ?? "")) throw new ValidationError$1(`${context}: continuation.profile.${key} names {${match[1]}}, which is not a fact Runtime supplies (${CONTINUATION_FACTS.join(", ")})`);
|
|
21071
21145
|
}
|
|
21072
|
-
if (
|
|
21073
|
-
if (
|
|
21074
|
-
|
|
21146
|
+
if (profile.review !== void 0) {
|
|
21147
|
+
if (typeof profile.review !== "string" || profile.review.trim() === "") throw new ValidationError$1(`${context}: continuation.profile.review must be non-empty`);
|
|
21148
|
+
for (const match of profile.review.matchAll(placeholder)) if (![
|
|
21149
|
+
"version",
|
|
21150
|
+
"path",
|
|
21151
|
+
"score"
|
|
21152
|
+
].includes(match[1] ?? "")) throw new ValidationError$1(`${context}: continuation.profile.review names {${match[1]}}; it may name {version}, {path} and {score}`);
|
|
21075
21153
|
}
|
|
21076
|
-
|
|
21077
|
-
}
|
|
21078
|
-
function exactTerminal(ref, request, terminal) {
|
|
21079
|
-
const terminalRef = TerminalSessionRefSchema.parse(terminal.ref);
|
|
21080
|
-
TerminalReplayWindowSchema.parse(terminal.cursors);
|
|
21081
|
-
if (terminalRef.parentExecutionId !== ref.run.executionId) throw new Error("provider attached a terminal from another interactive run");
|
|
21082
|
-
AgentInteractiveSessionControlClaimSchema.parse(terminal.control);
|
|
21083
|
-
if (!agentInteractiveSessionControlClaimMatchesRef(ref, terminal.control)) throw new Error("provider attached a terminal with a claim for another interactive process");
|
|
21084
|
-
if (canonicalCandidateDigest(terminal.control) !== canonicalCandidateDigest(request.control)) throw new Error("provider attached a terminal with a different interactive control claim");
|
|
21085
|
-
return terminal;
|
|
21086
|
-
}
|
|
21087
|
-
function sameInteractiveRef(left, right) {
|
|
21088
|
-
return canonicalCandidateDigest(left) === canonicalCandidateDigest(right);
|
|
21154
|
+
if (profile.opening.trim() === "") throw new ValidationError$1(`${context}: continuation.profile.opening must be non-empty`);
|
|
21155
|
+
for (const [index, question] of (profile.questions ?? []).entries()) if (typeof question !== "string" || question.trim() === "") throw new ValidationError$1(`${context}: continuation.profile.questions[${index}] must be a non-empty string`);
|
|
21089
21156
|
}
|
|
21090
|
-
|
|
21091
|
-
|
|
21092
|
-
|
|
21093
|
-
|
|
21094
|
-
|
|
21095
|
-
|
|
21096
|
-
|
|
21097
|
-
|
|
21098
|
-
async function startRetainedInteractiveRun(options) {
|
|
21099
|
-
options.signal?.throwIfAborted();
|
|
21100
|
-
const startOptions = options;
|
|
21101
|
-
assertStableText(startOptions.environment.idempotencyKey, "environment idempotency key");
|
|
21102
|
-
assertStableText(startOptions.interactiveIdempotencyKey, "interactive idempotency key");
|
|
21103
|
-
if (typeof startOptions.onAdmission !== "function") throw new Error("startRetainedInteractiveRun requires an awaited onAdmission durability hook");
|
|
21104
|
-
if (!startOptions.provider.get) throw new Error(`provider "${startOptions.provider.name}" cannot reconstruct an environment by id`);
|
|
21105
|
-
const profile = agentProfileSchema.parse(startOptions.environment.profile);
|
|
21106
|
-
if (profile.harness === void 0) throw new Error("retained interactive runs require AgentProfile.harness");
|
|
21107
|
-
const requestedProfileDigest = canonicalAgentProfileDigest(profile);
|
|
21108
|
-
const identity = startOptions.intent === void 0 ? mintRetainedIdentity(startOptions.environment.idempotencyKey, startOptions.interactiveIdempotencyKey) : {
|
|
21109
|
-
sessionId: startOptions.intent.sessionId,
|
|
21110
|
-
executionId: startOptions.intent.executionId
|
|
21111
|
-
};
|
|
21112
|
-
assertStableText(identity.sessionId, "retained session id");
|
|
21113
|
-
assertStableText(identity.executionId, "retained execution id");
|
|
21114
|
-
const intent = interactiveIntent(startOptions, profile, identity);
|
|
21115
|
-
if (startOptions.intent === void 0) await admitDurably(startOptions.onAdmission, intent);
|
|
21116
|
-
else assertExactInteractiveIntent(startOptions.intent, intent);
|
|
21117
|
-
const providerCapabilities = AgentEnvironmentCapabilitiesSchema.parse(await awaitAbortable$1(Promise.resolve().then(() => startOptions.provider.capabilities()), startOptions.signal));
|
|
21118
|
-
assertInteractiveCapabilities(startOptions.provider.name, providerCapabilities);
|
|
21119
|
-
const environment = await createInteractiveEnvironment(() => startOptions.provider.create({
|
|
21120
|
-
...startOptions.environment,
|
|
21121
|
-
profile,
|
|
21122
|
-
signal: startOptions.signal,
|
|
21123
|
-
metadata: retainedEnvironmentMetadata(startOptions.environment.metadata, startOptions.environment.idempotencyKey)
|
|
21124
|
-
}), startOptions.signal);
|
|
21125
|
-
let capabilities;
|
|
21126
|
-
try {
|
|
21127
|
-
assertExactEnvironment(startOptions.provider.name, environment);
|
|
21128
|
-
startOptions.signal?.throwIfAborted();
|
|
21129
|
-
capabilities = interactiveCapabilitiesForEnvironment(startOptions.provider.name, providerCapabilities, environment);
|
|
21130
|
-
assertInteractiveMethods(startOptions.provider.name, environment);
|
|
21131
|
-
} catch (error) {
|
|
21132
|
-
await destroyUnusedEnvironment(environment, error);
|
|
21133
|
-
throw error;
|
|
21134
|
-
}
|
|
21135
|
-
const request = interactiveRequest(startOptions, environment, profile, requestedProfileDigest, identity);
|
|
21136
|
-
await admitDurably(startOptions.onAdmission, {
|
|
21137
|
-
phase: "interactive_environment",
|
|
21138
|
-
provider: startOptions.provider.name,
|
|
21139
|
-
environmentId: environment.id,
|
|
21140
|
-
idempotencyKey: startOptions.environment.idempotencyKey,
|
|
21141
|
-
interactiveIdempotencyKey: startOptions.interactiveIdempotencyKey,
|
|
21142
|
-
request
|
|
21143
|
-
});
|
|
21144
|
-
const ref = exactStartedRef(request, await startInteractiveProcess(environment, () => environment.startInteractive(request, { signal: startOptions.signal }), startOptions.signal));
|
|
21145
|
-
await admitDurably(startOptions.onAdmission, {
|
|
21146
|
-
phase: "interactive_started",
|
|
21147
|
-
idempotencyKey: startOptions.environment.idempotencyKey,
|
|
21148
|
-
interactiveIdempotencyKey: startOptions.interactiveIdempotencyKey,
|
|
21149
|
-
ref
|
|
21150
|
-
});
|
|
21151
|
-
return createRetainedInteractiveRunHandle(environment, ref, capabilities, request);
|
|
21157
|
+
/** Findings reach the note only when every citation resolves, at least two distinct spans are
|
|
21158
|
+
* cited, and the independent verifier agreed. The best method in Who&When found the failing step
|
|
21159
|
+
* 14.2% of the time, so an unverified finding is noise with a citation. */
|
|
21160
|
+
function admitFinding(finding) {
|
|
21161
|
+
if (!finding.verified) return false;
|
|
21162
|
+
if (finding.citations.length === 0) return false;
|
|
21163
|
+
if (!finding.citations.every((citation) => citation.resolved)) return false;
|
|
21164
|
+
return new Set(finding.citations.map((citation) => citation.uri)).size >= 2;
|
|
21152
21165
|
}
|
|
21166
|
+
/** About 1,500 tokens of findings. */
|
|
21167
|
+
const FINDINGS_CHAR_CAP = 6e3;
|
|
21153
21168
|
/**
|
|
21154
|
-
*
|
|
21155
|
-
*
|
|
21156
|
-
*
|
|
21157
|
-
* idempotent start request), or `null` when the provider no longer holds the
|
|
21158
|
-
* environment (not found; nothing remains to stop). @stable
|
|
21169
|
+
* Rank the admitted findings by how many failed items they explain, drop repeats, and keep them
|
|
21170
|
+
* within the note's cap. Earlier findings stay as they were written (ACE: itemized additions keep
|
|
21171
|
+
* detail that repeated rewrites lose); a finding whose items all pass now is marked resolved.
|
|
21159
21172
|
*/
|
|
21160
|
-
|
|
21161
|
-
|
|
21162
|
-
|
|
21163
|
-
const
|
|
21164
|
-
|
|
21165
|
-
|
|
21166
|
-
|
|
21167
|
-
|
|
21168
|
-
|
|
21169
|
-
|
|
21170
|
-
|
|
21171
|
-
|
|
21172
|
-
|
|
21173
|
+
function distillFindings(prior, proposed, failing, continuation) {
|
|
21174
|
+
const key = (claim) => claim.toLowerCase().replace(/\s+/gu, " ").trim();
|
|
21175
|
+
const known = new Set(prior.map((finding) => key(finding.claim)));
|
|
21176
|
+
const carried = prior.map((finding) => finding.resolvedAt === void 0 && (finding.items?.length ?? 0) > 0 && (finding.items ?? []).every((item) => !failing.has(item)) ? {
|
|
21177
|
+
...finding,
|
|
21178
|
+
resolvedAt: continuation
|
|
21179
|
+
} : finding);
|
|
21180
|
+
const fresh = proposed.filter(admitFinding).filter((finding) => {
|
|
21181
|
+
const k = key(finding.claim);
|
|
21182
|
+
if (known.has(k)) return false;
|
|
21183
|
+
known.add(k);
|
|
21184
|
+
return true;
|
|
21185
|
+
}).map((finding) => ({
|
|
21186
|
+
finding,
|
|
21187
|
+
links: (finding.items ?? []).filter((item) => failing.has(item)).length
|
|
21188
|
+
})).sort((a, b) => b.links - a.links);
|
|
21189
|
+
const out = [...carried];
|
|
21190
|
+
let used = carried.filter((finding) => finding.resolvedAt === void 0).reduce((sum, finding) => sum + finding.claim.length, 0);
|
|
21191
|
+
for (const { finding } of fresh) {
|
|
21192
|
+
if (used + finding.claim.length > FINDINGS_CHAR_CAP) break;
|
|
21193
|
+
used += finding.claim.length;
|
|
21194
|
+
out.push({
|
|
21195
|
+
...finding,
|
|
21196
|
+
admittedAt: continuation
|
|
21173
21197
|
});
|
|
21174
21198
|
}
|
|
21175
|
-
|
|
21176
|
-
const { environment, capabilities } = await reconstructEnvironment(options.provider, admission.environmentId, options.signal);
|
|
21177
|
-
if (!environment || !capabilities) return null;
|
|
21178
|
-
const ref = exactStartedRef(request, await awaitAbortable$1(Promise.resolve().then(() => environment.startInteractive(request, { signal: options.signal })), options.signal));
|
|
21179
|
-
await admitDurably(options.onAdmission, {
|
|
21180
|
-
phase: "interactive_started",
|
|
21181
|
-
idempotencyKey: admission.idempotencyKey,
|
|
21182
|
-
interactiveIdempotencyKey: admission.interactiveIdempotencyKey,
|
|
21183
|
-
ref
|
|
21184
|
-
});
|
|
21185
|
-
return createRetainedInteractiveRunHandle(environment, ref, capabilities, request);
|
|
21199
|
+
return out;
|
|
21186
21200
|
}
|
|
21187
|
-
|
|
21188
|
-
|
|
21189
|
-
|
|
21190
|
-
|
|
21191
|
-
|
|
21192
|
-
|
|
21193
|
-
|
|
21194
|
-
|
|
21201
|
+
/** Expand the profile's question templates over the failed items and the settled workers. */
|
|
21202
|
+
function expandQuestions(templates, failing, workers) {
|
|
21203
|
+
const out = [];
|
|
21204
|
+
for (const template of templates) {
|
|
21205
|
+
const hasItem = template.includes("{item}");
|
|
21206
|
+
const hasWorker = template.includes("{worker}");
|
|
21207
|
+
if (!hasItem && !hasWorker) {
|
|
21208
|
+
out.push(template);
|
|
21209
|
+
continue;
|
|
21210
|
+
}
|
|
21211
|
+
const items = hasItem ? failing : [""];
|
|
21212
|
+
const each = hasWorker ? workers.map((worker) => `${worker.id} (${worker.label})`) : [""];
|
|
21213
|
+
for (const item of items) for (const worker of each) out.push(template.replaceAll("{item}", item).replaceAll("{worker}", worker));
|
|
21214
|
+
}
|
|
21215
|
+
return out;
|
|
21195
21216
|
}
|
|
21196
|
-
|
|
21197
|
-
|
|
21198
|
-
|
|
21199
|
-
|
|
21200
|
-
|
|
21201
|
-
}
|
|
21202
|
-
const
|
|
21203
|
-
|
|
21204
|
-
|
|
21205
|
-
|
|
21206
|
-
|
|
21207
|
-
|
|
21208
|
-
|
|
21209
|
-
|
|
21210
|
-
|
|
21211
|
-
|
|
21212
|
-
|
|
21213
|
-
|
|
21214
|
-
|
|
21215
|
-
const handle = createRetainedInteractiveRunHandle(environment, ref, capabilities);
|
|
21216
|
-
await handle.status({ signal: options.signal });
|
|
21217
|
-
return handle;
|
|
21218
|
-
}
|
|
21219
|
-
function interactiveRequest(options, environment, profile, requestedProfileDigest, identity) {
|
|
21220
|
-
const start = {
|
|
21221
|
-
profile,
|
|
21222
|
-
requestedProfileDigest,
|
|
21223
|
-
...options.initialPrompt === void 0 ? {} : { initialPrompt: options.initialPrompt },
|
|
21224
|
-
...options.cwd === void 0 ? {} : { cwd: options.cwd },
|
|
21225
|
-
...options.cols === void 0 ? {} : { cols: options.cols },
|
|
21226
|
-
...options.rows === void 0 ? {} : { rows: options.rows }
|
|
21227
|
-
};
|
|
21228
|
-
return exactAgentInteractiveSessionStart({
|
|
21229
|
-
run: agentInteractiveSessionRunRef({
|
|
21230
|
-
provider: options.provider.name,
|
|
21231
|
-
environmentId: environment.id,
|
|
21232
|
-
...identity
|
|
21233
|
-
}, start),
|
|
21234
|
-
...start
|
|
21235
|
-
});
|
|
21236
|
-
}
|
|
21237
|
-
function interactiveIntent(options, profile, identity) {
|
|
21238
|
-
const requestedProfileDigest = canonicalAgentProfileDigest(profile);
|
|
21239
|
-
const requestDigest = canonicalCandidateDigest({
|
|
21240
|
-
kind: "retained-interactive-intent.v1",
|
|
21241
|
-
provider: options.provider.name,
|
|
21242
|
-
idempotencyKey: options.environment.idempotencyKey,
|
|
21243
|
-
interactiveIdempotencyKey: options.interactiveIdempotencyKey,
|
|
21244
|
-
sessionId: identity.sessionId,
|
|
21245
|
-
executionId: identity.executionId,
|
|
21246
|
-
requestedProfileDigest,
|
|
21247
|
-
create: retainedCreateMaterial(options.environment),
|
|
21248
|
-
start: sanitizedStartMaterial(options)
|
|
21249
|
-
});
|
|
21250
|
-
return {
|
|
21251
|
-
phase: "interactive_intent",
|
|
21252
|
-
provider: options.provider.name,
|
|
21253
|
-
idempotencyKey: options.environment.idempotencyKey,
|
|
21254
|
-
interactiveIdempotencyKey: options.interactiveIdempotencyKey,
|
|
21255
|
-
sessionId: identity.sessionId,
|
|
21256
|
-
executionId: identity.executionId,
|
|
21257
|
-
runId: `interactive-intent-run:${requestDigest.slice(7)}`,
|
|
21258
|
-
requestedProfileDigest,
|
|
21259
|
-
requestDigest
|
|
21217
|
+
/**
|
|
21218
|
+
* Write one continuation note, sections 1 to 8 of docs/38. Section 9, the run's state, is
|
|
21219
|
+
* `composeReentryTask`, which wraps this text. Pure: the same input writes the same note.
|
|
21220
|
+
*/
|
|
21221
|
+
function composeContinuationNote(input) {
|
|
21222
|
+
const { profile, verdict } = input;
|
|
21223
|
+
const items = verdict?.items ?? {};
|
|
21224
|
+
const total = Object.keys(items).length;
|
|
21225
|
+
const failing = verdict === void 0 ? [] : failedItems(verdict);
|
|
21226
|
+
const facts = {
|
|
21227
|
+
composite: verdict?.composite === void 0 ? "unknown" : format(verdict.composite),
|
|
21228
|
+
threshold: verdict?.threshold === void 0 ? "unknown" : format(verdict.threshold),
|
|
21229
|
+
failed: verdict === void 0 || total === 0 && (verdict.failures?.length ?? 0) === 0 ? "unknown" : String(failing.length),
|
|
21230
|
+
total: total === 0 ? "unknown" : String(total),
|
|
21231
|
+
reads: String(input.reads),
|
|
21232
|
+
owed: input.owed?.trim() || "not described",
|
|
21233
|
+
settled: String(input.progress.settledCount),
|
|
21234
|
+
delivered: String(input.progress.deliveredCount ?? 0),
|
|
21235
|
+
continuation: String(input.continuation)
|
|
21260
21236
|
};
|
|
21261
|
-
}
|
|
21262
|
-
|
|
21263
|
-
|
|
21264
|
-
|
|
21265
|
-
...
|
|
21266
|
-
...options.cols === void 0 ? {} : { cols: options.cols },
|
|
21267
|
-
...options.rows === void 0 ? {} : { rows: options.rows }
|
|
21237
|
+
const fill = (text) => text.replace(placeholder, (_, name) => facts[name] ?? `{${name}}`);
|
|
21238
|
+
const sections = [verdict === void 0 ? "No check verdict is available yet." + (input.canSubmitResult === true ? " Submit a result through submit_result to request the check." : "") : verdict.pass ? "The check passes on the current state, but no result has been accepted." + (input.canSubmitResult === true ? " Call submit_result to request acceptance." : "") : fill(profile.opening).trim()];
|
|
21239
|
+
const section = (heading, body) => {
|
|
21240
|
+
if (body.length === 0) return;
|
|
21241
|
+
sections.push([...heading.trim() === "" ? [] : [`## ${fill(heading)}`], ...body].join("\n"));
|
|
21268
21242
|
};
|
|
21269
|
-
|
|
21270
|
-
|
|
21271
|
-
|
|
21272
|
-
|
|
21273
|
-
|
|
21274
|
-
|
|
21275
|
-
|
|
21276
|
-
|
|
21277
|
-
|
|
21278
|
-
|
|
21279
|
-
|
|
21280
|
-
|
|
21281
|
-
|
|
21282
|
-
|
|
21283
|
-
|
|
21284
|
-
|
|
21285
|
-
|
|
21286
|
-
|
|
21287
|
-
|
|
21288
|
-
if (Object.keys(record).some((key) => !allowed.has(key))) throw new Error("interactive intent contains unsupported material");
|
|
21289
|
-
if (record.phase !== "interactive_intent") throw new Error("interactive intent has an invalid phase");
|
|
21290
|
-
for (const [key, value] of Object.entries(record)) {
|
|
21291
|
-
if (key === "phase") continue;
|
|
21292
|
-
if (typeof value !== "string" || value.length === 0) throw new Error(`interactive intent field "${key}" is invalid`);
|
|
21243
|
+
if (input.failures === "verbatim" && verdict !== void 0) {
|
|
21244
|
+
const lines = verdict.failures ?? [];
|
|
21245
|
+
const shown = lines.slice(0, 40);
|
|
21246
|
+
const more = lines.length - shown.length;
|
|
21247
|
+
section(profile.headings.failures, [...shown, ...more > 0 ? [input.canReadMore ? `${more} more failure lines: call read_continuation with continuation ${input.continuation}.` : `${more} more failure lines are not shown.`] : []]);
|
|
21248
|
+
const passing = passedItems(verdict);
|
|
21249
|
+
section(profile.headings.protected, passing.length === 0 ? [] : [passing.join(", ")]);
|
|
21250
|
+
if (input.previous !== void 0) {
|
|
21251
|
+
const before = new Set(failedItems(input.previous));
|
|
21252
|
+
const now = new Set(failing);
|
|
21253
|
+
const fixed = [...before].filter((item) => !now.has(item));
|
|
21254
|
+
const broke = [...now].filter((item) => !before.has(item));
|
|
21255
|
+
section(profile.headings.changed, [
|
|
21256
|
+
...fixed.length === 0 ? [] : [`Now passing: ${fixed.join(", ")}.`],
|
|
21257
|
+
...broke.length === 0 ? [] : [`Newly failing: ${broke.join(", ")}.`],
|
|
21258
|
+
...fixed.length === 0 && broke.length === 0 ? ["No item changed since the last note."] : [],
|
|
21259
|
+
...input.previous.composite !== void 0 && verdict.composite !== void 0 ? [`Composite: ${format(input.previous.composite)} then ${format(verdict.composite)}.`] : []
|
|
21260
|
+
]);
|
|
21261
|
+
}
|
|
21293
21262
|
}
|
|
21294
|
-
|
|
21295
|
-
|
|
21296
|
-
|
|
21297
|
-
}
|
|
21298
|
-
|
|
21299
|
-
if (
|
|
21263
|
+
if (input.findings !== void 0) {
|
|
21264
|
+
const open = input.findings.filter((finding) => finding.resolvedAt === void 0);
|
|
21265
|
+
const resolved = input.findings.filter((finding) => finding.resolvedAt === input.continuation);
|
|
21266
|
+
section(profile.headings.findings, [...open.map((finding) => `- [hypothesis] ${finding.claim}` + (finding.items?.length ? ` (items: ${finding.items.join(", ")})` : "") + ` Evidence: ${finding.citations.map((citation) => citation.uri).join(", ")}`), ...resolved.map((finding) => `- [resolved] ${finding.claim}`)]);
|
|
21267
|
+
}
|
|
21268
|
+
if (input.bar !== void 0 && verdict !== void 0) {
|
|
21269
|
+
const body = [];
|
|
21270
|
+
if (profile.barRule?.trim()) body.push(fill(profile.barRule).trim());
|
|
21271
|
+
for (const [item, value] of Object.entries(items)) {
|
|
21272
|
+
const best = input.bar.best?.verdict.items?.[item];
|
|
21273
|
+
body.push(`- ${item}: ${value >= 1 ? "passes" : `fails (${format(value)})`}` + (best === void 0 ? "" : ` / ${input.bar.best?.label}: ${best >= 1 ? "passes" : `fails (${format(best)})`}`));
|
|
21274
|
+
}
|
|
21275
|
+
if (input.bar.best?.verdict.composite !== void 0) body.push(`Best version ${input.bar.best.label}: composite ${format(input.bar.best.verdict.composite)}.`);
|
|
21276
|
+
if (input.bar.reference?.trim()) body.push(`Reference result: ${input.bar.reference.trim()}`);
|
|
21277
|
+
if (verdict.review?.trim()) body.push(`The check's review: ${verdict.review.trim()}`);
|
|
21278
|
+
section(profile.headings.bar, body);
|
|
21279
|
+
}
|
|
21280
|
+
section(profile.headings.plan, profile.plan.trim() === "" ? [] : [fill(profile.plan).trim()]);
|
|
21281
|
+
section(profile.headings.rules, [...profile.rules.trim() === "" ? [] : [fill(profile.rules).trim()], ...input.sealed ? ["The score comes from cases you cannot see."] : []]);
|
|
21282
|
+
for (const appended of input.appended ?? []) section(appended.heading, appended.text.trim() === "" ? [] : [appended.text.trim()]);
|
|
21283
|
+
return sections.join("\n\n");
|
|
21300
21284
|
}
|
|
21301
|
-
|
|
21302
|
-
if (
|
|
21303
|
-
const
|
|
21304
|
-
assertInteractiveCapabilities(provider.name, providerCapabilities);
|
|
21305
|
-
const environment = await awaitAbortable$1(Promise.resolve().then(() => provider.get(environmentId, { signal })), signal);
|
|
21306
|
-
if (!environment) return {
|
|
21307
|
-
environment: null,
|
|
21308
|
-
capabilities: null
|
|
21309
|
-
};
|
|
21310
|
-
assertExactEnvironment(provider.name, environment, environmentId);
|
|
21311
|
-
const capabilities = interactiveCapabilitiesForEnvironment(provider.name, providerCapabilities, environment);
|
|
21312
|
-
assertInteractiveMethods(provider.name, environment);
|
|
21285
|
+
function summarizeVerdict(verdict) {
|
|
21286
|
+
if (verdict === void 0) return null;
|
|
21287
|
+
const total = Object.keys(verdict.items ?? {}).length;
|
|
21313
21288
|
return {
|
|
21314
|
-
|
|
21315
|
-
|
|
21289
|
+
pass: verdict.pass,
|
|
21290
|
+
...verdict.composite === void 0 ? {} : { composite: verdict.composite },
|
|
21291
|
+
...total === 0 ? {} : {
|
|
21292
|
+
failed: failedItems(verdict).length,
|
|
21293
|
+
total
|
|
21294
|
+
}
|
|
21316
21295
|
};
|
|
21317
21296
|
}
|
|
21318
|
-
function
|
|
21319
|
-
|
|
21320
|
-
let ref;
|
|
21321
|
-
try {
|
|
21322
|
-
ref = AgentInteractiveSessionRefSchema.parse(value);
|
|
21323
|
-
} catch (error) {
|
|
21324
|
-
throw new RetainedInteractiveBindingError(stableRequest, {}, { cause: error });
|
|
21325
|
-
}
|
|
21326
|
-
if (!agentInteractiveSessionRefMatchesStart(request, ref)) throw new RetainedInteractiveBindingError(stableRequest, detachedSnapshot({ ref: detachedSnapshot(ref, "interactive provider start reference") }, "interactive provider start result"), { cause: /* @__PURE__ */ new Error("provider started another interactive run than requested") });
|
|
21327
|
-
return freezeInteractiveRef(ref);
|
|
21328
|
-
}
|
|
21329
|
-
function assertExactEnvironment(providerName, environment, environmentId) {
|
|
21330
|
-
if (environment.provider !== providerName || environmentId && environment.id !== environmentId) throw new Error("provider returned another interactive environment");
|
|
21331
|
-
assertStableText(environment.id, "interactive environment id");
|
|
21332
|
-
}
|
|
21333
|
-
function interactiveCapabilitiesForEnvironment(providerName, providerCapabilities, environment) {
|
|
21334
|
-
const capabilities = environment.capabilities === void 0 ? providerCapabilities : AgentEnvironmentCapabilitiesSchema.parse(environment.capabilities);
|
|
21335
|
-
assertInteractiveCapabilities(providerName, capabilities);
|
|
21336
|
-
return capabilities;
|
|
21337
|
-
}
|
|
21338
|
-
function assertInteractiveCapabilities(providerName, capabilities) {
|
|
21339
|
-
const interactive = capabilities.interactiveAgent;
|
|
21340
|
-
if (!interactive?.start || !interactive.control || !interactive.status || !interactive.attach || !interactive.reattach || !interactive.sendPrompt || !interactive.input || !interactive.resize || !interactive.stop) throw new Error(`provider "${providerName}" cannot control an exact interactive agent`);
|
|
21297
|
+
function noteDigest(note) {
|
|
21298
|
+
return `sha256:${createHash("sha256").update(note).digest("hex")}`;
|
|
21341
21299
|
}
|
|
21342
|
-
|
|
21343
|
-
|
|
21300
|
+
/** A run directory's continuation files: the root's at `<runDir>/continuations/<n>/`, a nested
|
|
21301
|
+
* manager's at `<runDir>/continuations/managers/<owner>/<n>/`. */
|
|
21302
|
+
const CONTINUATIONS_DIR = "continuations";
|
|
21303
|
+
/**
|
|
21304
|
+
* Write one continuation's files under `<dir>/<n>/`: `note.md`, `verdict.json`, and
|
|
21305
|
+
* `panel.jsonl` when the panel ran. The director reads them through `read_continuation`, because
|
|
21306
|
+
* its box cannot read the driver's run directory.
|
|
21307
|
+
*/
|
|
21308
|
+
async function writeContinuationFiles(dir, continuation, files) {
|
|
21309
|
+
const at = join(dir, String(continuation));
|
|
21310
|
+
await mkdir(at, { recursive: true });
|
|
21311
|
+
await writeFile(join(at, "note.md"), `${files.note}\n`, "utf8");
|
|
21312
|
+
await writeFile(join(at, "verdict.json"), `${JSON.stringify(files.verdict ?? null, null, 2)}\n`, "utf8");
|
|
21313
|
+
if (files.panel !== void 0) await writeFile(join(at, "panel.jsonl"), files.panel.map((line) => JSON.stringify(line)).join("\n") + (files.panel.length ? "\n" : ""), "utf8");
|
|
21344
21314
|
}
|
|
21345
|
-
|
|
21346
|
-
|
|
21347
|
-
|
|
21348
|
-
|
|
21349
|
-
|
|
21315
|
+
/** The best composite across `reads`, or `undefined` when no read scored. */
|
|
21316
|
+
function bestComposite(reads) {
|
|
21317
|
+
let best;
|
|
21318
|
+
for (const read of reads) {
|
|
21319
|
+
const value = read.verdict?.composite;
|
|
21320
|
+
if (value !== void 0 && (best === void 0 || value > best)) best = value;
|
|
21350
21321
|
}
|
|
21322
|
+
return best;
|
|
21351
21323
|
}
|
|
21352
|
-
|
|
21353
|
-
|
|
21354
|
-
const WORKER_BINDING_SCHEMA_VERSION = 1;
|
|
21355
|
-
const SPAWN_JOURNAL_FILE = "spawn-journal.jsonl";
|
|
21356
|
-
/** Directory containing exact per-worker interactive binding records. @stable */
|
|
21357
|
-
function workerInteractiveBindingsDir(eventDir) {
|
|
21358
|
-
return join(eventDir, "interactive-workers");
|
|
21324
|
+
function finite(value) {
|
|
21325
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
21359
21326
|
}
|
|
21360
|
-
|
|
21361
|
-
|
|
21362
|
-
const id = stableText$1(workerId, "worker id");
|
|
21363
|
-
const stem = createHash("sha256").update(id).digest("hex");
|
|
21364
|
-
return join(workerInteractiveBindingsDir(eventDir), `${stem}.json`);
|
|
21327
|
+
function format(value) {
|
|
21328
|
+
return Number.isInteger(value) ? String(value) : value.toFixed(3).replace(/0+$/u, "");
|
|
21365
21329
|
}
|
|
21366
|
-
/**
|
|
21367
|
-
function
|
|
21368
|
-
const
|
|
21369
|
-
const
|
|
21330
|
+
/** Build the continuation state for one manager with a check. */
|
|
21331
|
+
function createContinuationKeeper(input) {
|
|
21332
|
+
const { policy } = input;
|
|
21333
|
+
const failures = input.feedback === "pass-only" ? "off" : policy.failures;
|
|
21334
|
+
const entries = [];
|
|
21335
|
+
const notes = [];
|
|
21336
|
+
let findings = [];
|
|
21337
|
+
let panelUsd = 0;
|
|
21338
|
+
let panelUsdKnown = true;
|
|
21339
|
+
const latestVerdict = () => {
|
|
21340
|
+
const reads = input.reads();
|
|
21341
|
+
for (let i = reads.length - 1; i >= 0; i -= 1) {
|
|
21342
|
+
const read = reads[i];
|
|
21343
|
+
if (read?.verdict !== void 0) return {
|
|
21344
|
+
verdict: read.verdict,
|
|
21345
|
+
read: read.read
|
|
21346
|
+
};
|
|
21347
|
+
}
|
|
21348
|
+
return { read: 0 };
|
|
21349
|
+
};
|
|
21350
|
+
const closePrevious = () => {
|
|
21351
|
+
const last = entries.at(-1);
|
|
21352
|
+
const lastNote = notes.at(-1);
|
|
21353
|
+
if (last === void 0 || lastNote === void 0) return;
|
|
21354
|
+
const latest = latestVerdict();
|
|
21355
|
+
entries[entries.length - 1] = {
|
|
21356
|
+
...last,
|
|
21357
|
+
after: latest.read > lastNote.read ? summarizeVerdict(latest.verdict) : null
|
|
21358
|
+
};
|
|
21359
|
+
};
|
|
21360
|
+
return {
|
|
21361
|
+
async compose(context) {
|
|
21362
|
+
closePrevious();
|
|
21363
|
+
const continuation = entries.length + 1;
|
|
21364
|
+
const { verdict, read } = latestVerdict();
|
|
21365
|
+
const failing = verdict === void 0 ? [] : failedItems(verdict);
|
|
21366
|
+
let panelRecord;
|
|
21367
|
+
let panelLines;
|
|
21368
|
+
if (policy.panel === "on" && policy.runPanel !== void 0 && policy.panelUsd !== void 0) {
|
|
21369
|
+
const workers = input.workers();
|
|
21370
|
+
const questions = expandQuestions(policy.profile.questions ?? [], failing, workers);
|
|
21371
|
+
const left = policy.panelUsd.perRun - panelUsd;
|
|
21372
|
+
const usdCap = Math.min(policy.panelUsd.perContinuation, left);
|
|
21373
|
+
const asking = questions.length > 0 && usdCap > 0 && panelUsdKnown;
|
|
21374
|
+
let traces;
|
|
21375
|
+
let unavailable;
|
|
21376
|
+
if (asking) try {
|
|
21377
|
+
traces = await input.traces?.();
|
|
21378
|
+
if (traces === void 0) unavailable = "the run has recorded no trace yet";
|
|
21379
|
+
} catch (error) {
|
|
21380
|
+
unavailable = `the run's traces could not be read: ${error instanceof Error ? error.message : String(error)}`;
|
|
21381
|
+
}
|
|
21382
|
+
if (asking && traces !== void 0) {
|
|
21383
|
+
const result = await policy.runPanel({
|
|
21384
|
+
continuation,
|
|
21385
|
+
task: input.task,
|
|
21386
|
+
...verdict === void 0 ? {} : { verdict },
|
|
21387
|
+
reads: input.reads(),
|
|
21388
|
+
questions,
|
|
21389
|
+
traces,
|
|
21390
|
+
workers,
|
|
21391
|
+
...policy.best === void 0 ? {} : { bar: policy.best },
|
|
21392
|
+
...policy.reference === void 0 ? {} : { reference: policy.reference },
|
|
21393
|
+
usdCap,
|
|
21394
|
+
signal: context.signal
|
|
21395
|
+
});
|
|
21396
|
+
if (result.usd === null) panelUsdKnown = false;
|
|
21397
|
+
else panelUsd += result.usd;
|
|
21398
|
+
findings = distillFindings(findings, result.findings, new Set(failing), continuation);
|
|
21399
|
+
panelRecord = {
|
|
21400
|
+
asked: questions.length,
|
|
21401
|
+
proposed: result.findings.length,
|
|
21402
|
+
admitted: findings.filter((finding) => finding.admittedAt === continuation).length,
|
|
21403
|
+
usd: result.usd
|
|
21404
|
+
};
|
|
21405
|
+
panelLines = [...result.findings.map((finding) => ({
|
|
21406
|
+
kind: "finding",
|
|
21407
|
+
admitted: admitFinding(finding),
|
|
21408
|
+
...finding
|
|
21409
|
+
})), ...result.receipts === void 0 ? [] : [{
|
|
21410
|
+
kind: "receipts",
|
|
21411
|
+
receipts: result.receipts
|
|
21412
|
+
}]];
|
|
21413
|
+
} else panelRecord = {
|
|
21414
|
+
asked: 0,
|
|
21415
|
+
proposed: 0,
|
|
21416
|
+
admitted: 0,
|
|
21417
|
+
usd: 0,
|
|
21418
|
+
...unavailable === void 0 ? {} : { unavailable }
|
|
21419
|
+
};
|
|
21420
|
+
}
|
|
21421
|
+
const appended = policy.append ? await policy.append({
|
|
21422
|
+
continuation,
|
|
21423
|
+
...verdict === void 0 ? {} : { verdict },
|
|
21424
|
+
reads: input.reads(),
|
|
21425
|
+
signal: context.signal
|
|
21426
|
+
}) : void 0;
|
|
21427
|
+
const note = composeContinuationNote({
|
|
21428
|
+
profile: policy.profile,
|
|
21429
|
+
continuation,
|
|
21430
|
+
...verdict === void 0 ? {} : { verdict },
|
|
21431
|
+
...notes.at(-1)?.verdict === void 0 ? {} : { previous: notes.at(-1)?.verdict },
|
|
21432
|
+
reads: input.reads().length,
|
|
21433
|
+
failures,
|
|
21434
|
+
...policy.panel === "on" ? { findings } : {},
|
|
21435
|
+
...policy.bar === "on" ? { bar: {
|
|
21436
|
+
...policy.best === void 0 ? {} : { best: policy.best },
|
|
21437
|
+
...policy.reference === void 0 ? {} : { reference: policy.reference }
|
|
21438
|
+
} } : {},
|
|
21439
|
+
...appended === void 0 ? {} : { appended: [appended] },
|
|
21440
|
+
...input.owed === void 0 ? {} : { owed: input.owed },
|
|
21441
|
+
progress: context.progress,
|
|
21442
|
+
canReadMore: input.canReadMore,
|
|
21443
|
+
canSubmitResult: input.canSubmitResult === true,
|
|
21444
|
+
...input.sealed === true ? { sealed: true } : {}
|
|
21445
|
+
});
|
|
21446
|
+
notes.push({
|
|
21447
|
+
note,
|
|
21448
|
+
...verdict === void 0 ? {} : { verdict },
|
|
21449
|
+
...panelLines === void 0 ? {} : { panel: panelLines },
|
|
21450
|
+
read
|
|
21451
|
+
});
|
|
21452
|
+
entries.push({
|
|
21453
|
+
continuation,
|
|
21454
|
+
attempt: context.attempt,
|
|
21455
|
+
noteDigest: noteDigest(note),
|
|
21456
|
+
profile: policy.profile.id,
|
|
21457
|
+
switches: {
|
|
21458
|
+
failures,
|
|
21459
|
+
panel: policy.panel,
|
|
21460
|
+
bar: policy.bar
|
|
21461
|
+
},
|
|
21462
|
+
before: summarizeVerdict(verdict),
|
|
21463
|
+
after: null,
|
|
21464
|
+
...panelRecord === void 0 ? {} : { panel: panelRecord },
|
|
21465
|
+
appended: appended === void 0 ? 0 : 1
|
|
21466
|
+
});
|
|
21467
|
+
if (input.dir !== void 0) await writeContinuationFiles(input.dir, continuation, {
|
|
21468
|
+
note,
|
|
21469
|
+
...verdict === void 0 ? {} : { verdict },
|
|
21470
|
+
...panelLines === void 0 ? {} : { panel: panelLines }
|
|
21471
|
+
});
|
|
21472
|
+
return note;
|
|
21473
|
+
},
|
|
21474
|
+
read(continuation) {
|
|
21475
|
+
const index = continuation === void 0 ? notes.length - 1 : continuation - 1;
|
|
21476
|
+
const entry = notes[index];
|
|
21477
|
+
if (entry === void 0) return {
|
|
21478
|
+
found: false,
|
|
21479
|
+
reason: notes.length === 0 ? "no continuation has been sent in this run" : `continuations run from 1 to ${notes.length}`
|
|
21480
|
+
};
|
|
21481
|
+
return {
|
|
21482
|
+
found: true,
|
|
21483
|
+
continuation: index + 1,
|
|
21484
|
+
note: entry.note,
|
|
21485
|
+
verdict: failures === "off" && entry.verdict !== void 0 ? { pass: entry.verdict.pass } : entry.verdict ?? null,
|
|
21486
|
+
findings: findings.filter((finding) => finding.admittedAt <= index + 1)
|
|
21487
|
+
};
|
|
21488
|
+
},
|
|
21489
|
+
entries() {
|
|
21490
|
+
closePrevious();
|
|
21491
|
+
return entries.map((entry) => ({ ...entry }));
|
|
21492
|
+
}
|
|
21493
|
+
};
|
|
21494
|
+
}
|
|
21495
|
+
//#endregion
|
|
21496
|
+
//#region src/runtime/supervise/completion-gate.ts
|
|
21497
|
+
/**
|
|
21498
|
+
*
|
|
21499
|
+
* The completion-oracle: **settled ⟺ DELIVERED.**
|
|
21500
|
+
*
|
|
21501
|
+
* Foreman's one hard lesson (0/18 self-improvement deliverables) — "done" must mean a check
|
|
21502
|
+
* PASSED, not the agent's say-so. `gateOnDeliverable` wraps an `Executor` so its settlement
|
|
21503
|
+
* is `valid` ONLY when the deliverable check passes. The child still RUNS and settles (its
|
|
21504
|
+
* spend is conserved into the pool either way), but a child that ran WITHOUT delivering
|
|
21505
|
+
* settles `valid:false` — so a keep-best driver never counts it as done, and a gate never
|
|
21506
|
+
* inflates with self-judged wins.
|
|
21507
|
+
*
|
|
21508
|
+
* Dual-purpose by construction:
|
|
21509
|
+
* - product: the agent fleet only advances on real, checked deliverables.
|
|
21510
|
+
* - proof: the gate's `valid` is the honest settle — equal-k comparisons can't be gamed by an
|
|
21511
|
+
* arm that "ran" without producing the artifact.
|
|
21512
|
+
*
|
|
21513
|
+
* The check is a DEPLOYABLE oracle — a test command, a state verifier, the commit0 judge —
|
|
21514
|
+
* read off the child's output, never the model judging itself. A throwing check is
|
|
21515
|
+
* fail-closed (not delivered), never a crash.
|
|
21516
|
+
*
|
|
21517
|
+
* @experimental
|
|
21518
|
+
*/
|
|
21519
|
+
/**
|
|
21520
|
+
* Wrap an `Executor` so its settlement `valid` reflects the deliverable check, not the
|
|
21521
|
+
* inner verdict. Handles both `execute` shapes (one-shot `Promise<ExecutorResult>` and
|
|
21522
|
+
* streaming `AsyncIterable<UsageEvent>` + `resultArtifact()`); the check runs once the inner
|
|
21523
|
+
* executor has produced its output. The inner `score` is preserved; only `valid` is gated.
|
|
21524
|
+
*/
|
|
21525
|
+
function gateOnDeliverable(inner, deliverable) {
|
|
21526
|
+
let gated;
|
|
21527
|
+
const check = async (out, baseScore) => {
|
|
21528
|
+
let delivered;
|
|
21529
|
+
try {
|
|
21530
|
+
delivered = checkVerdictOf(await deliverable.check(out)).pass;
|
|
21531
|
+
} catch {
|
|
21532
|
+
delivered = false;
|
|
21533
|
+
}
|
|
21534
|
+
return {
|
|
21535
|
+
valid: delivered,
|
|
21536
|
+
score: baseScore ?? (delivered ? 1 : 0)
|
|
21537
|
+
};
|
|
21538
|
+
};
|
|
21539
|
+
/**
|
|
21540
|
+
* Ask the delivery question once, from whatever the inner executor managed to produce.
|
|
21541
|
+
*
|
|
21542
|
+
* Fail-closed on the artifact being unavailable: an executor that never produced one delivered
|
|
21543
|
+
* nothing, and leaving `gated` unset keeps the existing invalid-by-default reading.
|
|
21544
|
+
*/
|
|
21545
|
+
const settleVerdict = async () => {
|
|
21546
|
+
let art;
|
|
21547
|
+
try {
|
|
21548
|
+
art = inner.resultArtifact();
|
|
21549
|
+
} catch {
|
|
21550
|
+
return;
|
|
21551
|
+
}
|
|
21552
|
+
gated = await check(art.out, art.verdict?.score);
|
|
21553
|
+
};
|
|
21554
|
+
const gateExecution = (r) => {
|
|
21555
|
+
if (isAsyncIterable$1(r)) return (async function* () {
|
|
21556
|
+
try {
|
|
21557
|
+
for await (const ev of r) yield ev;
|
|
21558
|
+
} finally {
|
|
21559
|
+
await settleVerdict();
|
|
21560
|
+
}
|
|
21561
|
+
})();
|
|
21562
|
+
return (async () => {
|
|
21563
|
+
let res;
|
|
21564
|
+
try {
|
|
21565
|
+
res = await r;
|
|
21566
|
+
} catch (error) {
|
|
21567
|
+
await settleVerdict();
|
|
21568
|
+
throw error;
|
|
21569
|
+
}
|
|
21570
|
+
gated = await check(res.out, res.verdict?.score);
|
|
21571
|
+
return {
|
|
21572
|
+
...res,
|
|
21573
|
+
verdict: gated
|
|
21574
|
+
};
|
|
21575
|
+
})();
|
|
21576
|
+
};
|
|
21577
|
+
return inheritRuntimeOwnedExecutorAttestation(inner, {
|
|
21578
|
+
runtime: inner.runtime,
|
|
21579
|
+
...inner.budgetExempt !== void 0 ? { budgetExempt: inner.budgetExempt } : {},
|
|
21580
|
+
...inner.deliver ? { deliver: (m) => inner.deliver?.(m) } : {},
|
|
21581
|
+
...inner.progress ? { progress: () => inner.progress?.() } : {},
|
|
21582
|
+
...inner.traceSource ? { traceSource: () => inner.traceSource?.() } : {},
|
|
21583
|
+
...inner.metered ? { metered: () => inner.metered?.() } : {},
|
|
21584
|
+
...inner.accounting ? { accounting: () => inner.accounting?.() } : {},
|
|
21585
|
+
...inner.harnessTranscript ? { harnessTranscript: () => inner.harnessTranscript?.() } : {},
|
|
21586
|
+
...inner.harnessTranscriptSettled ? { harnessTranscriptSettled: () => inner.harnessTranscriptSettled?.() ?? Promise.resolve() } : {},
|
|
21587
|
+
execute: (task, signal) => gateExecution(inner.execute(task, signal)),
|
|
21588
|
+
...inner.recover ? { recover: (task, signal) => gateExecution(inner.recover(task, signal)) } : {},
|
|
21589
|
+
teardown: (grace) => inner.teardown(grace),
|
|
21590
|
+
...teardownSurfaces(inner),
|
|
21591
|
+
resultArtifact() {
|
|
21592
|
+
const art = inner.resultArtifact();
|
|
21593
|
+
return {
|
|
21594
|
+
...art,
|
|
21595
|
+
verdict: gated ?? art.verdict
|
|
21596
|
+
};
|
|
21597
|
+
}
|
|
21598
|
+
});
|
|
21599
|
+
}
|
|
21600
|
+
/**
|
|
21601
|
+
* Transform a Runtime executor's terminal artifact without losing its private
|
|
21602
|
+
* profile-materialization attestation or altering its measured spend. This is
|
|
21603
|
+
* the composition point for deterministic post-processing and grading; callers
|
|
21604
|
+
* must not rebuild an Executor around a model transport merely to change `out`.
|
|
21605
|
+
*/
|
|
21606
|
+
function mapExecutorResult(inner, map) {
|
|
21607
|
+
let mapped;
|
|
21608
|
+
const settle = async (result, task) => {
|
|
21609
|
+
const transformed = await map(result, task);
|
|
21610
|
+
mapped = {
|
|
21611
|
+
outRef: transformed.outRef,
|
|
21612
|
+
out: transformed.out,
|
|
21613
|
+
...transformed.verdict ? { verdict: transformed.verdict } : {},
|
|
21614
|
+
spent: result.spent
|
|
21615
|
+
};
|
|
21616
|
+
return mapped;
|
|
21617
|
+
};
|
|
21618
|
+
return inheritRuntimeOwnedExecutorAttestation(inner, {
|
|
21619
|
+
runtime: inner.runtime,
|
|
21620
|
+
...inner.budgetExempt !== void 0 ? { budgetExempt: inner.budgetExempt } : {},
|
|
21621
|
+
...inner.deliver ? { deliver: (message) => inner.deliver?.(message) } : {},
|
|
21622
|
+
...inner.progress ? { progress: () => inner.progress?.() } : {},
|
|
21623
|
+
...inner.traceSource ? { traceSource: () => inner.traceSource?.() } : {},
|
|
21624
|
+
...inner.accounting ? { accounting: () => inner.accounting?.() } : {},
|
|
21625
|
+
...inner.metered ? { metered: () => inner.metered?.() } : {},
|
|
21626
|
+
...inner.harnessTranscript ? { harnessTranscript: () => inner.harnessTranscript?.() } : {},
|
|
21627
|
+
...inner.harnessTranscriptSettled ? { harnessTranscriptSettled: () => inner.harnessTranscriptSettled?.() ?? Promise.resolve() } : {},
|
|
21628
|
+
execute(task, signal) {
|
|
21629
|
+
const execution = inner.execute(task, signal);
|
|
21630
|
+
if (isAsyncIterable$1(execution)) return (async function* () {
|
|
21631
|
+
for await (const event of execution) yield event;
|
|
21632
|
+
await settle(inner.resultArtifact(), task);
|
|
21633
|
+
})();
|
|
21634
|
+
return (async () => settle(await execution, task))();
|
|
21635
|
+
},
|
|
21636
|
+
teardown: (grace) => inner.teardown(grace),
|
|
21637
|
+
...teardownSurfaces(inner),
|
|
21638
|
+
resultArtifact() {
|
|
21639
|
+
if (!mapped) throw new Error("mapExecutorResult: resultArtifact() read before execute()");
|
|
21640
|
+
return mapped;
|
|
21641
|
+
}
|
|
21642
|
+
});
|
|
21643
|
+
}
|
|
21644
|
+
//#endregion
|
|
21645
|
+
//#region src/runtime/supervise/dispatch.ts
|
|
21646
|
+
/**
|
|
21647
|
+
*
|
|
21648
|
+
* `rollingDispatch` — the REFILLING dispatch policy over a `Scope`. It keeps `width` children in
|
|
21649
|
+
* flight and admits the next queued unit of work the instant one settles, instead of waiting for
|
|
21650
|
+
* a whole round to drain (`fanout`) or for a driver to decide again (`spawn → await → spawn`).
|
|
21651
|
+
*
|
|
21652
|
+
* The gap it closes: `fanout` opens every item at once and then drains — one round, no refill —
|
|
21653
|
+
* and a driver brain's manual loop opens one worker per model turn. Between those two there was
|
|
21654
|
+
* nothing that holds N slots full, which is why a 5-worker run can peak at 2 live workers and sit
|
|
21655
|
+
* ~50% idle. This is a policy over the EXISTING `Scope.spawn` / `Scope.next` primitives: it adds
|
|
21656
|
+
* no second admission path, so the conserved budget pool stays the only fence on total work and
|
|
21657
|
+
* `width` is only a fence on simultaneous work.
|
|
21658
|
+
*
|
|
21659
|
+
* Fail-closed by construction: an admission rejection (`budget-exhausted` / `depth-exceeded`) is
|
|
21660
|
+
* recorded and STOPS further admission — the loop then drains what is already live and returns.
|
|
21661
|
+
* It never retries a rejected spawn against the same pool, and it never spawns past `width`.
|
|
21662
|
+
*
|
|
21663
|
+
* ── Concurrency ────────────────────────────────────────────────────────────────────────────────
|
|
21664
|
+
*
|
|
21665
|
+
* `width` bounds the children THIS dispatcher holds in flight. The tree-wide bound on working
|
|
21666
|
+
* agents is `SuperviseOptions.workerSlots` (`./worker-slots`): a spawn past it is queued by the
|
|
21667
|
+
* scope, not refused, so a `width` above the free slots only lengthens the allocator's queue.
|
|
21668
|
+
* `SandboxLineage`'s fork concurrency bounds boxes inside ONE leaf's fork wave, a different unit.
|
|
21669
|
+
*
|
|
21670
|
+
* ── Why this is not a copy of the kernel's batch loop ──────────────────────────────────────────
|
|
21671
|
+
*
|
|
21672
|
+
* `runBatch` (`src/runtime/run-loop.ts`) runs the same hold-N-slots-full shape over the KERNEL's
|
|
21673
|
+
* substrate: bare promises in a `Set`, raced with `Promise.race`, bounded by `maxConcurrency`.
|
|
21674
|
+
* This one runs it over the SUPERVISOR's substrate — `Scope.spawn`'s atomic reservation against
|
|
21675
|
+
* the conserved pool, `Scope.next`'s journaled settlement cursor, and the blob store behind each
|
|
21676
|
+
* result. Neither can be expressed in the other's terms without dragging its whole substrate
|
|
21677
|
+
* along: the kernel loop has no budget to reserve and no cursor to order settlements by, and this
|
|
21678
|
+
* one cannot race raw promises because a settlement is only real once it is journaled. The shape
|
|
21679
|
+
* repeating across the two deliberate layers is resonance, not duplication — do not "unify" them
|
|
21680
|
+
* into a shared helper that would have to know about both.
|
|
21681
|
+
*
|
|
21682
|
+
* @experimental
|
|
21683
|
+
*/
|
|
21684
|
+
/**
|
|
21685
|
+
* Run the refilling dispatch loop over `scope` until the queue is dry (or a stop fires) and every
|
|
21686
|
+
* admitted child has settled. Returns the settlements in cursor order plus the admission ledger.
|
|
21687
|
+
*
|
|
21688
|
+
* The loop is: fill free slots from `nextUnit` → `await scope.next()` → deliver the settlement →
|
|
21689
|
+
* refill → repeat. Because the refill happens immediately after each settlement rather than after
|
|
21690
|
+
* a whole round, a slow child never idles the other slots.
|
|
21691
|
+
*/
|
|
21692
|
+
async function rollingDispatch(scope, opts) {
|
|
21693
|
+
if (!Number.isInteger(opts.width) || opts.width < 1) throw new ValidationError$1(`rollingDispatch: width must be a positive integer, got ${String(opts.width)}`);
|
|
21694
|
+
const settled = [];
|
|
21695
|
+
const rejected = [];
|
|
21696
|
+
const live = /* @__PURE__ */ new Set();
|
|
21697
|
+
let admitted = 0;
|
|
21698
|
+
let peakLive = 0;
|
|
21699
|
+
let queueDry = false;
|
|
21700
|
+
let stopReason = "drained";
|
|
21701
|
+
const fill = async () => {
|
|
21702
|
+
while (live.size < opts.width) {
|
|
21703
|
+
if (queueDry) return;
|
|
21704
|
+
if (scope.signal.aborted) {
|
|
21705
|
+
stopReason = "aborted";
|
|
21706
|
+
queueDry = true;
|
|
21707
|
+
return;
|
|
21708
|
+
}
|
|
21709
|
+
if (opts.shouldStop?.() === true) {
|
|
21710
|
+
stopReason = "stopped";
|
|
21711
|
+
queueDry = true;
|
|
21712
|
+
return;
|
|
21713
|
+
}
|
|
21714
|
+
const unit = await opts.nextUnit();
|
|
21715
|
+
if (unit === void 0) {
|
|
21716
|
+
queueDry = true;
|
|
21717
|
+
return;
|
|
21718
|
+
}
|
|
21719
|
+
const res = scope.spawn(unit.agent, unit.task, unit.opts);
|
|
21720
|
+
if (!res.ok) {
|
|
21721
|
+
rejected.push(`${unit.opts.label}: ${res.reason}`);
|
|
21722
|
+
stopReason = "not-admitted";
|
|
21723
|
+
queueDry = true;
|
|
21724
|
+
return;
|
|
21725
|
+
}
|
|
21726
|
+
live.add(res.handle.id);
|
|
21727
|
+
admitted += 1;
|
|
21728
|
+
if (live.size > peakLive) peakLive = live.size;
|
|
21729
|
+
}
|
|
21730
|
+
};
|
|
21731
|
+
await fill();
|
|
21732
|
+
while (live.size > 0) {
|
|
21733
|
+
const s = await scope.next();
|
|
21734
|
+
if (s === null) break;
|
|
21735
|
+
live.delete(s.handle.id);
|
|
21736
|
+
settled.push(s);
|
|
21737
|
+
await opts.onSettled?.(s);
|
|
21738
|
+
await fill();
|
|
21739
|
+
}
|
|
21740
|
+
return {
|
|
21741
|
+
settled,
|
|
21742
|
+
admitted,
|
|
21743
|
+
rejected,
|
|
21744
|
+
stopReason,
|
|
21745
|
+
peakLive
|
|
21746
|
+
};
|
|
21747
|
+
}
|
|
21748
|
+
/**
|
|
21749
|
+
* Free worker slots under a simultaneity cap: `cap - live`, floored at 0, or `null` when there is
|
|
21750
|
+
* no cap (the conserved pool is then the only fence and "free slots" is not a finite number).
|
|
21751
|
+
* The one place the answer is computed, so the driver-facing tool payload and a dispatcher agree.
|
|
21752
|
+
*/
|
|
21753
|
+
function freeSlots(liveCount, cap) {
|
|
21754
|
+
if (cap === void 0 || cap <= 0) return null;
|
|
21755
|
+
return Math.max(0, cap - liveCount);
|
|
21756
|
+
}
|
|
21757
|
+
/** Convenience: a `DispatchUnit` factory over a fixed array of tasks, for the common case where
|
|
21758
|
+
* the queue is known up front and only the refill behavior is wanted. */
|
|
21759
|
+
function queueOf(units, budget) {
|
|
21760
|
+
let i = 0;
|
|
21761
|
+
return () => {
|
|
21762
|
+
const u = units[i];
|
|
21763
|
+
if (u === void 0) return void 0;
|
|
21764
|
+
i += 1;
|
|
21765
|
+
return {
|
|
21766
|
+
agent: u.agent,
|
|
21767
|
+
task: u.task,
|
|
21768
|
+
opts: {
|
|
21769
|
+
budget,
|
|
21770
|
+
label: u.label
|
|
21771
|
+
}
|
|
21772
|
+
};
|
|
21773
|
+
};
|
|
21774
|
+
}
|
|
21775
|
+
//#endregion
|
|
21776
|
+
//#region src/runtime/retained-interactive-handle.ts
|
|
21777
|
+
function createRetainedInteractiveRunHandle(environment, inputRef, capabilities, requestedStart) {
|
|
21778
|
+
const ref = freezeInteractiveRef(inputRef);
|
|
21779
|
+
const source = environment.interactive(ref);
|
|
21780
|
+
if (!sameInteractiveRef(source.ref, ref)) throw new Error("provider reconstructed a different interactive process");
|
|
21781
|
+
if (!source.sendPrompt) throw new Error("provider declared interactive prompt support but exposed no prompt method");
|
|
21782
|
+
return Object.freeze({
|
|
21783
|
+
ref,
|
|
21784
|
+
capabilities,
|
|
21785
|
+
claimControl: async (request, options) => exactClaim(ref, request, await awaitAbortable$1(Promise.resolve().then(() => source.claimControl(request, options)), options?.signal)),
|
|
21786
|
+
status: async (options) => exactStatus(ref, await awaitAbortable$1(Promise.resolve().then(() => source.status(options)), options?.signal), requestedStart),
|
|
21787
|
+
attach: async (request, options) => exactTerminal(ref, request, await awaitAbortable$1(Promise.resolve().then(() => source.attach(request, options)), options?.signal)),
|
|
21788
|
+
sendPrompt: async (command, options) => exactPrompt(ref, await awaitAbortable$1(Promise.resolve().then(() => source.sendPrompt(command, options)), options?.signal), command),
|
|
21789
|
+
stop: async (command, options) => exactStop(ref, await awaitAbortable$1(Promise.resolve().then(() => source.stop(command, options)), options?.signal), command)
|
|
21790
|
+
});
|
|
21791
|
+
}
|
|
21792
|
+
function freezeInteractiveRef(value) {
|
|
21793
|
+
return detachedSnapshot(AgentInteractiveSessionRefSchema.parse(value), "interactive session ref");
|
|
21794
|
+
}
|
|
21795
|
+
function exactClaim(ref, request, value) {
|
|
21796
|
+
const acknowledgement = parseProviderAcknowledgement(AgentInteractiveSessionControlClaimAcknowledgementSchema, value, "control claim");
|
|
21797
|
+
if (!agentInteractiveSessionControlClaimAcknowledgementMatchesRequest(request, acknowledgement)) throw new RetainedRunProviderContractError("provider returned a control claim acknowledgement for another request");
|
|
21798
|
+
if (acknowledgement.control && !agentInteractiveSessionControlClaimMatchesRef(ref, acknowledgement.control)) throw new RetainedRunProviderContractError("provider returned a control claim for another interactive process");
|
|
21799
|
+
return acknowledgement;
|
|
21800
|
+
}
|
|
21801
|
+
function exactPrompt(ref, value, command) {
|
|
21802
|
+
const acknowledgement = parseProviderAcknowledgement(AgentInteractiveSessionPromptAcknowledgementSchema, value, "prompt");
|
|
21803
|
+
if (!agentInteractiveSessionPromptAcknowledgementMatchesCommand(command, acknowledgement)) throw new RetainedRunProviderContractError("provider returned a prompt acknowledgement for another request");
|
|
21804
|
+
if (!agentInteractiveSessionControlClaimMatchesRef(ref, acknowledgement.control)) throw new RetainedRunProviderContractError("provider returned a prompt acknowledgement for another interactive process");
|
|
21805
|
+
return acknowledgement;
|
|
21806
|
+
}
|
|
21807
|
+
function exactStop(ref, value, command) {
|
|
21808
|
+
const acknowledgement = parseProviderAcknowledgement(AgentInteractiveSessionStopAcknowledgementSchema, value, "stop");
|
|
21809
|
+
if (!agentInteractiveSessionStopAcknowledgementMatchesCommand(command, acknowledgement)) throw new RetainedRunProviderContractError("provider returned a stop acknowledgement for another request");
|
|
21810
|
+
if (!agentInteractiveSessionControlClaimMatchesRef(ref, acknowledgement.control)) throw new RetainedRunProviderContractError("provider returned a stop acknowledgement for another interactive process");
|
|
21811
|
+
return acknowledgement;
|
|
21812
|
+
}
|
|
21813
|
+
function parseProviderAcknowledgement(schema, value, operation) {
|
|
21814
|
+
try {
|
|
21815
|
+
return schema.parse(value);
|
|
21816
|
+
} catch {
|
|
21817
|
+
throw new RetainedRunProviderContractError(`provider returned an invalid interactive ${operation} acknowledgement`);
|
|
21818
|
+
}
|
|
21819
|
+
}
|
|
21820
|
+
function exactStatus(ref, value, requestedStart) {
|
|
21821
|
+
let status;
|
|
21822
|
+
try {
|
|
21823
|
+
status = AgentInteractiveSessionStatusSchema.parse(value);
|
|
21824
|
+
} catch (error) {
|
|
21825
|
+
if (requestedStart === void 0) throw error;
|
|
21826
|
+
throw new RetainedInteractiveBindingError(detachedSnapshot(requestedStart, "interactive status binding request"), {}, { cause: error });
|
|
21827
|
+
}
|
|
21828
|
+
if (!agentInteractiveSessionStatusMatchesRef(ref, status)) {
|
|
21829
|
+
if (requestedStart !== void 0) throw new RetainedInteractiveBindingError(detachedSnapshot(requestedStart, "interactive status binding request"), detachedSnapshot({ status: detachedSnapshot(status, "interactive provider status") }, "interactive provider status result"), { cause: /* @__PURE__ */ new Error("provider returned status for another interactive process") });
|
|
21830
|
+
throw new Error("provider returned status for another interactive process");
|
|
21831
|
+
}
|
|
21832
|
+
return status;
|
|
21833
|
+
}
|
|
21834
|
+
function exactTerminal(ref, request, terminal) {
|
|
21835
|
+
const terminalRef = TerminalSessionRefSchema.parse(terminal.ref);
|
|
21836
|
+
TerminalReplayWindowSchema.parse(terminal.cursors);
|
|
21837
|
+
if (terminalRef.parentExecutionId !== ref.run.executionId) throw new Error("provider attached a terminal from another interactive run");
|
|
21838
|
+
AgentInteractiveSessionControlClaimSchema.parse(terminal.control);
|
|
21839
|
+
if (!agentInteractiveSessionControlClaimMatchesRef(ref, terminal.control)) throw new Error("provider attached a terminal with a claim for another interactive process");
|
|
21840
|
+
if (canonicalCandidateDigest(terminal.control) !== canonicalCandidateDigest(request.control)) throw new Error("provider attached a terminal with a different interactive control claim");
|
|
21841
|
+
return terminal;
|
|
21842
|
+
}
|
|
21843
|
+
function sameInteractiveRef(left, right) {
|
|
21844
|
+
return canonicalCandidateDigest(left) === canonicalCandidateDigest(right);
|
|
21845
|
+
}
|
|
21846
|
+
//#endregion
|
|
21847
|
+
//#region src/runtime/retained-interactive.ts
|
|
21848
|
+
/**
|
|
21849
|
+
* Start one retry-safe native coding-agent TUI without dispatching a headless turn.
|
|
21850
|
+
* The intent admission is durable before provider.create; the environment and
|
|
21851
|
+
* process admissions follow only after their exact provider coordinates exist.
|
|
21852
|
+
* @stable
|
|
21853
|
+
*/
|
|
21854
|
+
async function startRetainedInteractiveRun(options) {
|
|
21855
|
+
options.signal?.throwIfAborted();
|
|
21856
|
+
const startOptions = options;
|
|
21857
|
+
assertStableText(startOptions.environment.idempotencyKey, "environment idempotency key");
|
|
21858
|
+
assertStableText(startOptions.interactiveIdempotencyKey, "interactive idempotency key");
|
|
21859
|
+
if (typeof startOptions.onAdmission !== "function") throw new Error("startRetainedInteractiveRun requires an awaited onAdmission durability hook");
|
|
21860
|
+
if (!startOptions.provider.get) throw new Error(`provider "${startOptions.provider.name}" cannot reconstruct an environment by id`);
|
|
21861
|
+
const profile = agentProfileSchema.parse(startOptions.environment.profile);
|
|
21862
|
+
if (profile.harness === void 0) throw new Error("retained interactive runs require AgentProfile.harness");
|
|
21863
|
+
const requestedProfileDigest = canonicalAgentProfileDigest(profile);
|
|
21864
|
+
const identity = startOptions.intent === void 0 ? mintRetainedIdentity(startOptions.environment.idempotencyKey, startOptions.interactiveIdempotencyKey) : {
|
|
21865
|
+
sessionId: startOptions.intent.sessionId,
|
|
21866
|
+
executionId: startOptions.intent.executionId
|
|
21867
|
+
};
|
|
21868
|
+
assertStableText(identity.sessionId, "retained session id");
|
|
21869
|
+
assertStableText(identity.executionId, "retained execution id");
|
|
21870
|
+
const intent = interactiveIntent(startOptions, profile, identity);
|
|
21871
|
+
if (startOptions.intent === void 0) await admitDurably(startOptions.onAdmission, intent);
|
|
21872
|
+
else assertExactInteractiveIntent(startOptions.intent, intent);
|
|
21873
|
+
const providerCapabilities = AgentEnvironmentCapabilitiesSchema.parse(await awaitAbortable$1(Promise.resolve().then(() => startOptions.provider.capabilities()), startOptions.signal));
|
|
21874
|
+
assertInteractiveCapabilities(startOptions.provider.name, providerCapabilities);
|
|
21875
|
+
const environment = await createInteractiveEnvironment(() => startOptions.provider.create({
|
|
21876
|
+
...startOptions.environment,
|
|
21877
|
+
profile,
|
|
21878
|
+
signal: startOptions.signal,
|
|
21879
|
+
metadata: retainedEnvironmentMetadata(startOptions.environment.metadata, startOptions.environment.idempotencyKey)
|
|
21880
|
+
}), startOptions.signal);
|
|
21881
|
+
let capabilities;
|
|
21882
|
+
try {
|
|
21883
|
+
assertExactEnvironment(startOptions.provider.name, environment);
|
|
21884
|
+
startOptions.signal?.throwIfAborted();
|
|
21885
|
+
capabilities = interactiveCapabilitiesForEnvironment(startOptions.provider.name, providerCapabilities, environment);
|
|
21886
|
+
assertInteractiveMethods(startOptions.provider.name, environment);
|
|
21887
|
+
} catch (error) {
|
|
21888
|
+
await destroyUnusedEnvironment(environment, error);
|
|
21889
|
+
throw error;
|
|
21890
|
+
}
|
|
21891
|
+
const request = interactiveRequest(startOptions, environment, profile, requestedProfileDigest, identity);
|
|
21892
|
+
await admitDurably(startOptions.onAdmission, {
|
|
21893
|
+
phase: "interactive_environment",
|
|
21894
|
+
provider: startOptions.provider.name,
|
|
21895
|
+
environmentId: environment.id,
|
|
21896
|
+
idempotencyKey: startOptions.environment.idempotencyKey,
|
|
21897
|
+
interactiveIdempotencyKey: startOptions.interactiveIdempotencyKey,
|
|
21898
|
+
request
|
|
21899
|
+
});
|
|
21900
|
+
const ref = exactStartedRef(request, await startInteractiveProcess(environment, () => environment.startInteractive(request, { signal: startOptions.signal }), startOptions.signal));
|
|
21901
|
+
await admitDurably(startOptions.onAdmission, {
|
|
21902
|
+
phase: "interactive_started",
|
|
21903
|
+
idempotencyKey: startOptions.environment.idempotencyKey,
|
|
21904
|
+
interactiveIdempotencyKey: startOptions.interactiveIdempotencyKey,
|
|
21905
|
+
ref
|
|
21906
|
+
});
|
|
21907
|
+
return createRetainedInteractiveRunHandle(environment, ref, capabilities, request);
|
|
21908
|
+
}
|
|
21909
|
+
/**
|
|
21910
|
+
* Retry one exact start after its provider response may have been lost.
|
|
21911
|
+
*
|
|
21912
|
+
* Resolves to the handle of the admitted process (resumed through the exact,
|
|
21913
|
+
* idempotent start request), or `null` when the provider no longer holds the
|
|
21914
|
+
* environment (not found; nothing remains to stop). @stable
|
|
21915
|
+
*/
|
|
21916
|
+
async function recoverRetainedInteractiveRun(options) {
|
|
21917
|
+
options.signal?.throwIfAborted();
|
|
21918
|
+
if (typeof options.onAdmission !== "function") throw new Error("recoverRetainedInteractiveRun requires an awaited onAdmission durability hook");
|
|
21919
|
+
const admission = options.admission;
|
|
21920
|
+
if (admission.provider !== options.provider.name) throw new Error("interactive admission belongs to another provider");
|
|
21921
|
+
if (admission.phase === "interactive_intent") {
|
|
21922
|
+
if (options.replay === void 0) throw new Error("recoverRetainedInteractiveRun requires the original start material for an interactive intent");
|
|
21923
|
+
return startRetainedInteractiveRun({
|
|
21924
|
+
provider: options.provider,
|
|
21925
|
+
...options.replay,
|
|
21926
|
+
intent: admission,
|
|
21927
|
+
onAdmission: options.onAdmission,
|
|
21928
|
+
signal: options.signal
|
|
21929
|
+
});
|
|
21930
|
+
}
|
|
21931
|
+
const request = exactRecoveryRequest(admission);
|
|
21932
|
+
const { environment, capabilities } = await reconstructEnvironment(options.provider, admission.environmentId, options.signal);
|
|
21933
|
+
if (!environment || !capabilities) return null;
|
|
21934
|
+
const ref = exactStartedRef(request, await awaitAbortable$1(Promise.resolve().then(() => environment.startInteractive(request, { signal: options.signal })), options.signal));
|
|
21935
|
+
await admitDurably(options.onAdmission, {
|
|
21936
|
+
phase: "interactive_started",
|
|
21937
|
+
idempotencyKey: admission.idempotencyKey,
|
|
21938
|
+
interactiveIdempotencyKey: admission.interactiveIdempotencyKey,
|
|
21939
|
+
ref
|
|
21940
|
+
});
|
|
21941
|
+
return createRetainedInteractiveRunHandle(environment, ref, capabilities, request);
|
|
21942
|
+
}
|
|
21943
|
+
function exactRecoveryRequest(admission) {
|
|
21944
|
+
assertStableText(admission.environmentId, "interactive environment id");
|
|
21945
|
+
assertStableText(admission.idempotencyKey, "environment idempotency key");
|
|
21946
|
+
assertStableText(admission.interactiveIdempotencyKey, "interactive idempotency key");
|
|
21947
|
+
const request = exactAgentInteractiveSessionStart(admission.request);
|
|
21948
|
+
const identity = mintRetainedIdentity(admission.idempotencyKey, admission.interactiveIdempotencyKey);
|
|
21949
|
+
if (request.run.provider !== admission.provider || request.run.environmentId !== admission.environmentId || (request.run.sessionId !== identity.sessionId || request.run.executionId !== identity.executionId) && !matchesHistoricalInteractiveIdentity(admission, request)) throw new Error("interactive admission does not match its recovery coordinates");
|
|
21950
|
+
return request;
|
|
21951
|
+
}
|
|
21952
|
+
function matchesHistoricalInteractiveIdentity(admission, request) {
|
|
21953
|
+
const base = `${encodeURIComponent(admission.idempotencyKey)}:${encodeURIComponent(admission.interactiveIdempotencyKey)}`;
|
|
21954
|
+
const digest = canonicalCandidateDigest({
|
|
21955
|
+
kind: "retained-identity.v1",
|
|
21956
|
+
base
|
|
21957
|
+
}).slice(7);
|
|
21958
|
+
const historicalId = (prefix) => {
|
|
21959
|
+
const readable = `${prefix}:${base}`;
|
|
21960
|
+
return readable.length <= 128 ? readable : `${prefix}:${digest}`;
|
|
21961
|
+
};
|
|
21962
|
+
return request.run.sessionId === historicalId("retained-session") && request.run.executionId === historicalId("retained-execution");
|
|
21963
|
+
}
|
|
21964
|
+
/** Rebuild controls for one exact provider-owned coding-agent process. @stable */
|
|
21965
|
+
async function reconnectRetainedInteractiveRun(options) {
|
|
21966
|
+
options.signal?.throwIfAborted();
|
|
21967
|
+
const ref = AgentInteractiveSessionRefSchema.parse(options.ref);
|
|
21968
|
+
if (ref.run.provider !== options.provider.name) throw new Error("interactive session reference belongs to another provider");
|
|
21969
|
+
const { environment, capabilities } = await reconstructEnvironment(options.provider, ref.run.environmentId, options.signal);
|
|
21970
|
+
if (!environment || !capabilities) return null;
|
|
21971
|
+
const handle = createRetainedInteractiveRunHandle(environment, ref, capabilities);
|
|
21972
|
+
await handle.status({ signal: options.signal });
|
|
21973
|
+
return handle;
|
|
21974
|
+
}
|
|
21975
|
+
function interactiveRequest(options, environment, profile, requestedProfileDigest, identity) {
|
|
21976
|
+
const start = {
|
|
21977
|
+
profile,
|
|
21978
|
+
requestedProfileDigest,
|
|
21979
|
+
...options.initialPrompt === void 0 ? {} : { initialPrompt: options.initialPrompt },
|
|
21980
|
+
...options.cwd === void 0 ? {} : { cwd: options.cwd },
|
|
21981
|
+
...options.cols === void 0 ? {} : { cols: options.cols },
|
|
21982
|
+
...options.rows === void 0 ? {} : { rows: options.rows }
|
|
21983
|
+
};
|
|
21984
|
+
return exactAgentInteractiveSessionStart({
|
|
21985
|
+
run: agentInteractiveSessionRunRef({
|
|
21986
|
+
provider: options.provider.name,
|
|
21987
|
+
environmentId: environment.id,
|
|
21988
|
+
...identity
|
|
21989
|
+
}, start),
|
|
21990
|
+
...start
|
|
21991
|
+
});
|
|
21992
|
+
}
|
|
21993
|
+
function interactiveIntent(options, profile, identity) {
|
|
21994
|
+
const requestedProfileDigest = canonicalAgentProfileDigest(profile);
|
|
21995
|
+
const requestDigest = canonicalCandidateDigest({
|
|
21996
|
+
kind: "retained-interactive-intent.v1",
|
|
21997
|
+
provider: options.provider.name,
|
|
21998
|
+
idempotencyKey: options.environment.idempotencyKey,
|
|
21999
|
+
interactiveIdempotencyKey: options.interactiveIdempotencyKey,
|
|
22000
|
+
sessionId: identity.sessionId,
|
|
22001
|
+
executionId: identity.executionId,
|
|
22002
|
+
requestedProfileDigest,
|
|
22003
|
+
create: retainedCreateMaterial(options.environment),
|
|
22004
|
+
start: sanitizedStartMaterial(options)
|
|
22005
|
+
});
|
|
22006
|
+
return {
|
|
22007
|
+
phase: "interactive_intent",
|
|
22008
|
+
provider: options.provider.name,
|
|
22009
|
+
idempotencyKey: options.environment.idempotencyKey,
|
|
22010
|
+
interactiveIdempotencyKey: options.interactiveIdempotencyKey,
|
|
22011
|
+
sessionId: identity.sessionId,
|
|
22012
|
+
executionId: identity.executionId,
|
|
22013
|
+
runId: `interactive-intent-run:${requestDigest.slice(7)}`,
|
|
22014
|
+
requestedProfileDigest,
|
|
22015
|
+
requestDigest
|
|
22016
|
+
};
|
|
22017
|
+
}
|
|
22018
|
+
function sanitizedStartMaterial(options) {
|
|
22019
|
+
return {
|
|
22020
|
+
...options.initialPrompt === void 0 ? {} : { initialPrompt: options.initialPrompt },
|
|
22021
|
+
...options.cwd === void 0 ? {} : { cwd: options.cwd },
|
|
22022
|
+
...options.cols === void 0 ? {} : { cols: options.cols },
|
|
22023
|
+
...options.rows === void 0 ? {} : { rows: options.rows }
|
|
22024
|
+
};
|
|
22025
|
+
}
|
|
22026
|
+
function assertExactInteractiveIntent(received, expected) {
|
|
22027
|
+
if (canonicalCandidateDigest(parseInteractiveIntent(received)) !== canonicalCandidateDigest(expected)) throw new Error("interactive intent conflicts with replay material");
|
|
22028
|
+
}
|
|
22029
|
+
function parseInteractiveIntent(value) {
|
|
22030
|
+
const stable = detachedSnapshot(value, "interactive intent");
|
|
22031
|
+
if (stable === null || typeof stable !== "object" || Array.isArray(stable)) throw new Error("interactive intent is malformed");
|
|
22032
|
+
const record = stable;
|
|
22033
|
+
const allowed = /* @__PURE__ */ new Set([
|
|
22034
|
+
"phase",
|
|
22035
|
+
"provider",
|
|
22036
|
+
"idempotencyKey",
|
|
22037
|
+
"interactiveIdempotencyKey",
|
|
22038
|
+
"sessionId",
|
|
22039
|
+
"executionId",
|
|
22040
|
+
"runId",
|
|
22041
|
+
"requestedProfileDigest",
|
|
22042
|
+
"requestDigest"
|
|
22043
|
+
]);
|
|
22044
|
+
if (Object.keys(record).some((key) => !allowed.has(key))) throw new Error("interactive intent contains unsupported material");
|
|
22045
|
+
if (record.phase !== "interactive_intent") throw new Error("interactive intent has an invalid phase");
|
|
22046
|
+
for (const [key, value] of Object.entries(record)) {
|
|
22047
|
+
if (key === "phase") continue;
|
|
22048
|
+
if (typeof value !== "string" || value.length === 0) throw new Error(`interactive intent field "${key}" is invalid`);
|
|
22049
|
+
}
|
|
22050
|
+
assertDigest$1(record.requestedProfileDigest, "interactive intent profile digest");
|
|
22051
|
+
assertDigest$1(record.requestDigest, "interactive intent request digest");
|
|
22052
|
+
return stable;
|
|
22053
|
+
}
|
|
22054
|
+
function assertDigest$1(value, label) {
|
|
22055
|
+
if (typeof value !== "string" || !/^sha256:[a-f0-9]{64}$/u.test(value)) throw new Error(`${label} is invalid`);
|
|
22056
|
+
}
|
|
22057
|
+
async function reconstructEnvironment(provider, environmentId, signal) {
|
|
22058
|
+
if (!provider.get) throw new Error(`provider "${provider.name}" cannot reconstruct an environment by id`);
|
|
22059
|
+
const providerCapabilities = AgentEnvironmentCapabilitiesSchema.parse(await awaitAbortable$1(Promise.resolve().then(() => provider.capabilities()), signal));
|
|
22060
|
+
assertInteractiveCapabilities(provider.name, providerCapabilities);
|
|
22061
|
+
const environment = await awaitAbortable$1(Promise.resolve().then(() => provider.get(environmentId, { signal })), signal);
|
|
22062
|
+
if (!environment) return {
|
|
22063
|
+
environment: null,
|
|
22064
|
+
capabilities: null
|
|
22065
|
+
};
|
|
22066
|
+
assertExactEnvironment(provider.name, environment, environmentId);
|
|
22067
|
+
const capabilities = interactiveCapabilitiesForEnvironment(provider.name, providerCapabilities, environment);
|
|
22068
|
+
assertInteractiveMethods(provider.name, environment);
|
|
22069
|
+
return {
|
|
22070
|
+
environment,
|
|
22071
|
+
capabilities
|
|
22072
|
+
};
|
|
22073
|
+
}
|
|
22074
|
+
function exactStartedRef(request, value) {
|
|
22075
|
+
const stableRequest = detachedSnapshot(request, "interactive start binding request");
|
|
22076
|
+
let ref;
|
|
22077
|
+
try {
|
|
22078
|
+
ref = AgentInteractiveSessionRefSchema.parse(value);
|
|
22079
|
+
} catch (error) {
|
|
22080
|
+
throw new RetainedInteractiveBindingError(stableRequest, {}, { cause: error });
|
|
22081
|
+
}
|
|
22082
|
+
if (!agentInteractiveSessionRefMatchesStart(request, ref)) throw new RetainedInteractiveBindingError(stableRequest, detachedSnapshot({ ref: detachedSnapshot(ref, "interactive provider start reference") }, "interactive provider start result"), { cause: /* @__PURE__ */ new Error("provider started another interactive run than requested") });
|
|
22083
|
+
return freezeInteractiveRef(ref);
|
|
22084
|
+
}
|
|
22085
|
+
function assertExactEnvironment(providerName, environment, environmentId) {
|
|
22086
|
+
if (environment.provider !== providerName || environmentId && environment.id !== environmentId) throw new Error("provider returned another interactive environment");
|
|
22087
|
+
assertStableText(environment.id, "interactive environment id");
|
|
22088
|
+
}
|
|
22089
|
+
function interactiveCapabilitiesForEnvironment(providerName, providerCapabilities, environment) {
|
|
22090
|
+
const capabilities = environment.capabilities === void 0 ? providerCapabilities : AgentEnvironmentCapabilitiesSchema.parse(environment.capabilities);
|
|
22091
|
+
assertInteractiveCapabilities(providerName, capabilities);
|
|
22092
|
+
return capabilities;
|
|
22093
|
+
}
|
|
22094
|
+
function assertInteractiveCapabilities(providerName, capabilities) {
|
|
22095
|
+
const interactive = capabilities.interactiveAgent;
|
|
22096
|
+
if (!interactive?.start || !interactive.control || !interactive.status || !interactive.attach || !interactive.reattach || !interactive.sendPrompt || !interactive.input || !interactive.resize || !interactive.stop) throw new Error(`provider "${providerName}" cannot control an exact interactive agent`);
|
|
22097
|
+
}
|
|
22098
|
+
function assertInteractiveMethods(providerName, environment) {
|
|
22099
|
+
if (!environment.startInteractive || !environment.interactive) throw new Error(`provider "${providerName}" exposes incomplete interactive agent controls`);
|
|
22100
|
+
}
|
|
22101
|
+
async function destroyUnusedEnvironment(environment, cause) {
|
|
22102
|
+
try {
|
|
22103
|
+
await destroyInteractiveEnvironment(environment);
|
|
22104
|
+
} catch (cleanupError) {
|
|
22105
|
+
throw new AggregateError([cause, cleanupError], "interactive environment was invalid and could not be destroyed");
|
|
22106
|
+
}
|
|
22107
|
+
}
|
|
22108
|
+
//#endregion
|
|
22109
|
+
//#region src/runtime/supervise/worker-interactive.ts
|
|
22110
|
+
const WORKER_BINDING_SCHEMA_VERSION = 1;
|
|
22111
|
+
const SPAWN_JOURNAL_FILE = "spawn-journal.jsonl";
|
|
22112
|
+
/** Directory containing exact per-worker interactive binding records. @stable */
|
|
22113
|
+
function workerInteractiveBindingsDir(eventDir) {
|
|
22114
|
+
return join(eventDir, "interactive-workers");
|
|
22115
|
+
}
|
|
22116
|
+
/** Exact durable binding file for one worker id. @stable */
|
|
22117
|
+
function workerInteractiveBindingFile(eventDir, workerId) {
|
|
22118
|
+
const id = stableText$1(workerId, "worker id");
|
|
22119
|
+
const stem = createHash("sha256").update(id).digest("hex");
|
|
22120
|
+
return join(workerInteractiveBindingsDir(eventDir), `${stem}.json`);
|
|
22121
|
+
}
|
|
22122
|
+
/** Read and validate one exact durable worker binding. @stable */
|
|
22123
|
+
function readWorkerInteractiveBinding(eventDir, workerId) {
|
|
22124
|
+
const id = stableText$1(workerId, "worker id");
|
|
22125
|
+
const file = workerInteractiveBindingFile(eventDir, id);
|
|
21370
22126
|
assertNoSymlinkDescendant(eventDir, file, "worker interactive");
|
|
21371
22127
|
if (!existsSync(file)) return void 0;
|
|
21372
22128
|
const binding = parseBinding(JSON.parse(readFileSync(file, "utf8")));
|
|
@@ -21798,6 +22554,25 @@ function stableText(value, label) {
|
|
|
21798
22554
|
return text;
|
|
21799
22555
|
}
|
|
21800
22556
|
//#endregion
|
|
22557
|
+
//#region src/runtime/supervise/provider-visible-profile.ts
|
|
22558
|
+
/** Runtime-owned coordination is mounted under this MCP alias. */
|
|
22559
|
+
const coordinationMcpAlias = "agent-runtime-coordination";
|
|
22560
|
+
/** A profile declares Runtime-owned tools with this provider-neutral prefix. */
|
|
22561
|
+
const coordinationProfileToolPrefix = `${coordinationMcpAlias.replaceAll("-", "_")}_`;
|
|
22562
|
+
/** Remove Runtime-only grants and seat policy from the provider-facing profile. */
|
|
22563
|
+
function providerVisibleProfile(profile) {
|
|
22564
|
+
const { seats: _seats, ...withoutSeats } = profile;
|
|
22565
|
+
if (profile.tools === void 0) return withoutSeats;
|
|
22566
|
+
const providerTools = Object.fromEntries(Object.entries(profile.tools).filter(([name]) => !name.startsWith(coordinationProfileToolPrefix)));
|
|
22567
|
+
if (Object.keys(providerTools).length === Object.keys(profile.tools).length) return withoutSeats;
|
|
22568
|
+
if (Object.keys(providerTools).length > 0) return {
|
|
22569
|
+
...withoutSeats,
|
|
22570
|
+
tools: providerTools
|
|
22571
|
+
};
|
|
22572
|
+
const { tools: _runtimeTools, ...withoutTools } = withoutSeats;
|
|
22573
|
+
return withoutTools;
|
|
22574
|
+
}
|
|
22575
|
+
//#endregion
|
|
21801
22576
|
//#region src/runtime/supervise/terminal-record.ts
|
|
21802
22577
|
/** The settlement fields every writer copies, in the terminal record's key order. The
|
|
21803
22578
|
* `reconciled` record is built from this same spread so it and the terminal record can never
|
|
@@ -21950,7 +22725,7 @@ async function healReleasedSlots(opts, signal, now) {
|
|
|
21950
22725
|
};
|
|
21951
22726
|
await opts.journal.appendEvent(tree.root, terminalDownEvent(subject, settlement, settledSeq, floor.at, "released"));
|
|
21952
22727
|
healed += 1;
|
|
21953
|
-
const materialized = owned.find((event) => event.kind === "materialized");
|
|
22728
|
+
const materialized = [...owned].reverse().find((event) => event.kind === "materialized" || event.kind === "seat-materialized");
|
|
21954
22729
|
const lastReceipt = receipts[receipts.length - 1];
|
|
21955
22730
|
notifyRuntimeHookEvent(opts.hooks, {
|
|
21956
22731
|
id: `${spawned.id}:released`,
|
|
@@ -22032,7 +22807,7 @@ async function prepareInterruptedExecutors(opts, events, signal, now, parentId =
|
|
|
22032
22807
|
});
|
|
22033
22808
|
if (!prepared) continue;
|
|
22034
22809
|
}
|
|
22035
|
-
const priorMaterialization = owned.find((event) => event.kind === "materialized")?.receipt;
|
|
22810
|
+
const priorMaterialization = [...owned].reverse().find((event) => event.kind === "materialized" || event.kind === "seat-materialized")?.receipt;
|
|
22036
22811
|
const continuation = latestInput !== void 0 && inputs.length > 1 && node.ownedTreeRoot === void 0 ? await leafContinuation(node, owned, latestInput, opts) : void 0;
|
|
22037
22812
|
recoveries.push({
|
|
22038
22813
|
...detachedSnapshot({
|
|
@@ -22100,7 +22875,7 @@ async function leafContinuation(node, owned, latestInput, opts) {
|
|
|
22100
22875
|
}
|
|
22101
22876
|
async function assertRecordedResult(node, result, events, opts) {
|
|
22102
22877
|
const before = events.slice(0, events.indexOf(result));
|
|
22103
|
-
const receipt = before.find((event) => event.kind === "materialized")?.receipt;
|
|
22878
|
+
const receipt = [...before].reverse().find((event) => event.kind === "materialized" || event.kind === "seat-materialized")?.receipt;
|
|
22104
22879
|
const binding = [...before].reverse().find((event) => event.kind === "execution-bound")?.binding;
|
|
22105
22880
|
if (receipt?.status !== "known" || binding?.status !== "known" || receipt.runtime !== node.runtime || receipt.authoredProfileDigest !== node.identity?.profileDigest || binding.materializationReceiptDigest !== canonicalCandidateDigest(receipt)) throw new RuntimeRunStateError(`retained result '${node.id}' has no matching execution evidence`);
|
|
22106
22881
|
assertValidSpend(result.spent, `retained result '${result.id}'`);
|
|
@@ -22682,6 +23457,10 @@ function registerScopeRetainedOwner(scope, args) {
|
|
|
22682
23457
|
function scopeRetainedOwnerContext(scope) {
|
|
22683
23458
|
return owners.get(scope)?.context;
|
|
22684
23459
|
}
|
|
23460
|
+
/** The journal tree that owns this manager turn, including nested driver children. */
|
|
23461
|
+
function scopeRetainedOwnerJournalRoot(scope) {
|
|
23462
|
+
return owners.get(scope)?.args.rootId;
|
|
23463
|
+
}
|
|
22685
23464
|
/**
|
|
22686
23465
|
* Bind cleanup before replay can return an already accepted owner result. `checkpointCapture` is
|
|
22687
23466
|
* where each checkpoint's files are stored before the checkpoint is deleted; without it, no
|
|
@@ -22796,6 +23575,59 @@ function noteScopeRetainedOwnerCoordination(scope) {
|
|
|
22796
23575
|
delete state.checkpointing;
|
|
22797
23576
|
});
|
|
22798
23577
|
}
|
|
23578
|
+
/** A committed turn is the seat boundary. Keep its native home for a same-harness provider
|
|
23579
|
+
* continuation; only a provider/harness change needs a new environment. */
|
|
23580
|
+
async function prepareScopeRetainedOwnerSeatSwitch(scope, mode) {
|
|
23581
|
+
const state = owners.get(scope);
|
|
23582
|
+
if (!state?.acceptedRef || !state.acceptedConsumed) throw new ValidationError$1("seat switch requires a committed owner turn");
|
|
23583
|
+
const accepted = state.acceptedRef;
|
|
23584
|
+
await scopeRetainedOwnerTurnEnded(scope);
|
|
23585
|
+
await state.checkpointing;
|
|
23586
|
+
await checkpointOwnerWorkspace(scope, state);
|
|
23587
|
+
const owned = (await state.args.journal.loadTree(state.args.rootId) ?? []).filter((event) => event.id === state.args.nodeId);
|
|
23588
|
+
const acceptedIndex = owned.findIndex((event) => event.kind === "execution-result" && event.seq === accepted.seq && event.outRef === accepted.outRef);
|
|
23589
|
+
if (acceptedIndex < 0) throw new ValidationError$1("seat switch has no committed result in its journal");
|
|
23590
|
+
const source = owned.slice(0, acceptedIndex).reverse().find((event) => event.kind === "execution-admitted" && event.admission.phase === "environment");
|
|
23591
|
+
const sourceEnvironmentId = source?.kind === "execution-admitted" && source.admission.phase === "environment" ? source.admission.environmentId : void 0;
|
|
23592
|
+
const checkpoint = sourceEnvironmentId !== void 0 ? owned.slice(acceptedIndex + 1).reverse().find((event) => event.kind === "workspace-checkpoint" && event.environmentId === sourceEnvironmentId) : void 0;
|
|
23593
|
+
if (checkpoint?.kind !== "workspace-checkpoint") throw new ValidationError$1("seat switch requires a checkpoint of the committed source environment");
|
|
23594
|
+
if (mode === "replace-environment") {
|
|
23595
|
+
await retireSeatEnvironment(scope, state);
|
|
23596
|
+
state.forceNewSession = true;
|
|
23597
|
+
}
|
|
23598
|
+
return {
|
|
23599
|
+
checkpointAt: checkpoint.at,
|
|
23600
|
+
checkpointId: checkpoint.checkpoint.checkpointId,
|
|
23601
|
+
sourceEnvironmentId: checkpoint.environmentId
|
|
23602
|
+
};
|
|
23603
|
+
}
|
|
23604
|
+
/** The next seat receives fresh create-time credentials. Release the stopped source only after
|
|
23605
|
+
* its checkpoint exists, then commit the teardown so recovery never tries its old session. */
|
|
23606
|
+
async function retireSeatEnvironment(scope, state) {
|
|
23607
|
+
const { provider, args } = state;
|
|
23608
|
+
if (!provider?.get) throw new ValidationError$1("seat switch requires a provider with exact environment lookup");
|
|
23609
|
+
const owned = (await args.journal.loadTree(args.rootId) ?? []).filter((event) => event.id === args.nodeId);
|
|
23610
|
+
const admitted = [...owned].reverse().find((event) => event.kind === "execution-admitted" && event.admission.phase === "environment");
|
|
23611
|
+
if (admitted?.kind !== "execution-admitted" || admitted.admission.phase !== "environment") throw new ValidationError$1("seat switch has no committed source environment");
|
|
23612
|
+
const environmentId = admitted.admission.environmentId;
|
|
23613
|
+
if (owned.some((event) => event.kind === "environment-teardown" && event.destroyed && event.environmentId === environmentId)) return;
|
|
23614
|
+
const signal = AbortSignal.any([scope.signal, AbortSignal.timeout(3e4)]);
|
|
23615
|
+
const environment = await runAbortable(() => provider.get(environmentId), signal, "seat switch environment lookup timed out");
|
|
23616
|
+
if (environment !== null) {
|
|
23617
|
+
if (environment.id !== environmentId || environment.provider !== provider.name || !environment.destroy) throw new ValidationError$1("seat switch cannot retire the exact source environment");
|
|
23618
|
+
await runAbortable(() => environment.destroy(), signal, "seat switch environment retirement timed out");
|
|
23619
|
+
}
|
|
23620
|
+
await args.journal.appendEvent(args.rootId, {
|
|
23621
|
+
kind: "environment-teardown",
|
|
23622
|
+
id: args.nodeId,
|
|
23623
|
+
provider: provider.name,
|
|
23624
|
+
environmentId,
|
|
23625
|
+
destroyed: true,
|
|
23626
|
+
detail: "seat changed after a committed turn",
|
|
23627
|
+
seq: state.nextSequence(),
|
|
23628
|
+
at: new Date(args.now()).toISOString()
|
|
23629
|
+
});
|
|
23630
|
+
}
|
|
22799
23631
|
async function checkpointOwnerWorkspace(scope, state) {
|
|
22800
23632
|
const { provider, args } = state;
|
|
22801
23633
|
if (provider === void 0) return;
|
|
@@ -22973,7 +23805,8 @@ async function cleanCheckpoints(state, branching, checkpoints, events, parent) {
|
|
|
22973
23805
|
for (const event of checkpoints) {
|
|
22974
23806
|
const captured = await captureBeforeCleanup(state, branching, event, events, parent);
|
|
22975
23807
|
if ("reason" in captured) {
|
|
22976
|
-
|
|
23808
|
+
state.captureRefused ??= /* @__PURE__ */ new Set();
|
|
23809
|
+
state.captureRefused.add(event.checkpoint.checkpointId);
|
|
22977
23810
|
refused.push(captured);
|
|
22978
23811
|
await state.args.journal.appendEvent(state.args.rootId, {
|
|
22979
23812
|
kind: "workspace-checkpoint-cleanup",
|
|
@@ -23193,8 +24026,8 @@ async function settleCaptureForks(state) {
|
|
|
23193
24026
|
* environment needs one; a live environment is continued, never copied.
|
|
23194
24027
|
*/
|
|
23195
24028
|
function restoreBefore(owned, inputIndex) {
|
|
23196
|
-
const
|
|
23197
|
-
return owned.slice(0, inputIndex < 0 ? owned.length : inputIndex).filter((event) => event.kind === "workspace-checkpoint" &&
|
|
24029
|
+
const unusable = unusableEnvironmentIds(owned);
|
|
24030
|
+
return owned.slice(0, inputIndex < 0 ? owned.length : inputIndex).filter((event) => event.kind === "workspace-checkpoint" && unusable.has(event.environmentId)).at(-1);
|
|
23198
24031
|
}
|
|
23199
24032
|
async function restoreCapable(provider) {
|
|
23200
24033
|
if (provider === void 0) return false;
|
|
@@ -23215,7 +24048,8 @@ async function scopeRetainedOwnerRestorePoint(scope) {
|
|
|
23215
24048
|
const latest = restoreBefore((await state.args.journal.loadTree(state.args.rootId) ?? []).filter((event) => event.id === state.args.nodeId), -1);
|
|
23216
24049
|
return latest === void 0 ? void 0 : {
|
|
23217
24050
|
checkpointId: latest.checkpoint.checkpointId,
|
|
23218
|
-
takenAt: latest.at
|
|
24051
|
+
takenAt: latest.at,
|
|
24052
|
+
sourceEnvironmentId: latest.checkpoint.source.environmentId
|
|
23219
24053
|
};
|
|
23220
24054
|
}
|
|
23221
24055
|
/** @internal Whether another owner release could still destroy what the last one left. */
|
|
@@ -23539,9 +24373,9 @@ function hasDurableWorkspaceCapture(output, snapshot, environmentId, executionId
|
|
|
23539
24373
|
const linked = agentCandidateWorkspaceSnapshotEvidenceSchema.safeParse(receipt.snapshot);
|
|
23540
24374
|
return linked.success && linked.data.digest === parsed.data.digest && JSON.stringify(linked.data.manifest) === JSON.stringify(parsed.data.manifest) && JSON.stringify(linked.data.archive) === JSON.stringify(parsed.data.archive);
|
|
23541
24375
|
}
|
|
23542
|
-
/**
|
|
23543
|
-
function
|
|
23544
|
-
return new Set(owned.flatMap((event) => event.kind === "environment-teardown" && event.destroyed ? [event.environmentId] : []));
|
|
24376
|
+
/** Environments that cannot execute another turn, whether absent or terminal at the provider. */
|
|
24377
|
+
function unusableEnvironmentIds(owned) {
|
|
24378
|
+
return new Set(owned.flatMap((event) => event.kind === "environment-terminal" || event.kind === "environment-teardown" && event.destroyed ? [event.environmentId] : []));
|
|
23545
24379
|
}
|
|
23546
24380
|
/** The environment the owner's next invocation would continue in, when there is one: the latest
|
|
23547
24381
|
* environment admission of this owner, which is either the current invocation's own (recovered
|
|
@@ -23570,8 +24404,9 @@ function continuedEnvironment(owned) {
|
|
|
23570
24404
|
* commissioned settled `done` two minutes later, unread.
|
|
23571
24405
|
*
|
|
23572
24406
|
* The reconciliation refusal protects against paying twice for an execution that may still run.
|
|
23573
|
-
* An environment the provider no longer holds
|
|
23574
|
-
*
|
|
24407
|
+
* An environment the provider no longer holds or reports terminal runs nothing. Runtime records
|
|
24408
|
+
* the provider's exact observation before the next prepare starts a new invocation. A terminal
|
|
24409
|
+
* record still requires cleanup at settlement; it is not a teardown receipt.
|
|
23575
24410
|
*/
|
|
23576
24411
|
async function reconcileScopeRetainedOwnerEnvironment(scope) {
|
|
23577
24412
|
const state = owners.get(scope);
|
|
@@ -23581,7 +24416,7 @@ async function reconcileScopeRetainedOwnerEnvironment(scope) {
|
|
|
23581
24416
|
const continued = continuedEnvironment(owned);
|
|
23582
24417
|
if (continued === void 0) return { state: "none" };
|
|
23583
24418
|
const environmentId = continued.admission.environmentId;
|
|
23584
|
-
if (
|
|
24419
|
+
if (unusableEnvironmentIds(owned).has(environmentId)) return {
|
|
23585
24420
|
state: "lost",
|
|
23586
24421
|
environmentId
|
|
23587
24422
|
};
|
|
@@ -23590,21 +24425,31 @@ async function reconcileScopeRetainedOwnerEnvironment(scope) {
|
|
|
23590
24425
|
environmentId
|
|
23591
24426
|
};
|
|
23592
24427
|
let environment;
|
|
24428
|
+
let terminalStatus;
|
|
23593
24429
|
try {
|
|
23594
24430
|
environment = await runAbortable(() => provider.get(environmentId), AbortSignal.any([scope.signal, AbortSignal.timeout(3e4)]), "retained owner environment check timed out");
|
|
24431
|
+
if (environment !== null) {
|
|
24432
|
+
const found = environment;
|
|
24433
|
+
if (found.id !== environmentId || found.provider !== provider.name) return {
|
|
24434
|
+
state: "unknown",
|
|
24435
|
+
environmentId
|
|
24436
|
+
};
|
|
24437
|
+
const status = await runAbortable(() => found.status(), AbortSignal.any([scope.signal, AbortSignal.timeout(3e4)]), "retained owner environment status timed out");
|
|
24438
|
+
if (status === "failed" || status === "expired") terminalStatus = status;
|
|
24439
|
+
}
|
|
23595
24440
|
} catch {
|
|
23596
24441
|
return {
|
|
23597
24442
|
state: "unknown",
|
|
23598
24443
|
environmentId
|
|
23599
24444
|
};
|
|
23600
24445
|
}
|
|
23601
|
-
if (environment !== null) return {
|
|
24446
|
+
if (environment !== null && terminalStatus === void 0) return {
|
|
23602
24447
|
state: "live",
|
|
23603
24448
|
environmentId,
|
|
23604
24449
|
inFlight: continued.inFlight
|
|
23605
24450
|
};
|
|
23606
24451
|
scope.signal.throwIfAborted();
|
|
23607
|
-
await args.journal.appendEvent(args.rootId, {
|
|
24452
|
+
await args.journal.appendEvent(args.rootId, terminalStatus === void 0 ? {
|
|
23608
24453
|
kind: "environment-teardown",
|
|
23609
24454
|
id: args.nodeId,
|
|
23610
24455
|
provider: provider.name,
|
|
@@ -23613,6 +24458,14 @@ async function reconcileScopeRetainedOwnerEnvironment(scope) {
|
|
|
23613
24458
|
detail: "lost: the provider no longer holds this environment, so the next invocation starts in a new one",
|
|
23614
24459
|
seq: state.nextSequence(),
|
|
23615
24460
|
at: new Date(args.now()).toISOString()
|
|
24461
|
+
} : {
|
|
24462
|
+
kind: "environment-terminal",
|
|
24463
|
+
id: args.nodeId,
|
|
24464
|
+
provider: provider.name,
|
|
24465
|
+
environmentId,
|
|
24466
|
+
status: terminalStatus,
|
|
24467
|
+
seq: state.nextSequence(),
|
|
24468
|
+
at: new Date(args.now()).toISOString()
|
|
23616
24469
|
});
|
|
23617
24470
|
return {
|
|
23618
24471
|
state: "lost",
|
|
@@ -23635,9 +24488,9 @@ async function prepareScopeRetainedOwnerTask(scope, task) {
|
|
|
23635
24488
|
const accepted = [...attempt].reverse().find((event) => event.kind === "execution-result");
|
|
23636
24489
|
if (accepted?.kind === "execution-result") state.acceptedRef = accepted;
|
|
23637
24490
|
}
|
|
23638
|
-
const
|
|
24491
|
+
const unusable = unusableEnvironmentIds(owned);
|
|
23639
24492
|
const inFlight = continuedEnvironment(owned);
|
|
23640
|
-
if (inFlight?.inFlight &&
|
|
24493
|
+
if (inFlight?.inFlight && unusable.has(inFlight.admission.environmentId)) {
|
|
23641
24494
|
delete state.inputSequence;
|
|
23642
24495
|
delete state.taskRef;
|
|
23643
24496
|
state.admissions.length = 0;
|
|
@@ -23653,7 +24506,15 @@ async function prepareScopeRetainedOwnerTask(scope, task) {
|
|
|
23653
24506
|
state.admissions.length = 0;
|
|
23654
24507
|
delete state.acceptedConsumed;
|
|
23655
24508
|
}
|
|
23656
|
-
if (state.priorSession !== void 0 &&
|
|
24509
|
+
if (state.priorSession !== void 0 && unusable.has(state.priorSession.environmentId)) delete state.priorSession;
|
|
24510
|
+
const segmentStarts = owned.filter((event) => event.kind === "seat-segment" && event.phase === "started");
|
|
24511
|
+
const latestSeat = segmentStarts.at(-1);
|
|
24512
|
+
const previousSeat = segmentStarts.at(-2);
|
|
24513
|
+
if (latestSeat && previousSeat && latestSeat.provider !== previousSeat.provider && owned.indexOf(latestSeat) > owned.indexOf(latestInput)) state.forceNewSession = true;
|
|
24514
|
+
if (state.forceNewSession) {
|
|
24515
|
+
delete state.priorSession;
|
|
24516
|
+
delete state.forceNewSession;
|
|
24517
|
+
}
|
|
23657
24518
|
state.prepared = true;
|
|
23658
24519
|
const capable = await restoreCapable(state.provider);
|
|
23659
24520
|
const restoreFor = (inputIndex) => {
|
|
@@ -23702,26 +24563,247 @@ async function scopeRetainedOwnerResult(scope) {
|
|
|
23702
24563
|
if (out === void 0 || contentAddress(out) !== event.outRef) throw new ValidationError$1("retained owner result is missing or corrupt");
|
|
23703
24564
|
assertValidSpend(event.spent, "replayed retained owner result");
|
|
23704
24565
|
return {
|
|
23705
|
-
outRef: event.outRef,
|
|
23706
|
-
out,
|
|
23707
|
-
spent: event.spent,
|
|
23708
|
-
...event.verdict ? { verdict: event.verdict } : {},
|
|
23709
|
-
...event.outcome ? { outcome: event.outcome } : {}
|
|
24566
|
+
outRef: event.outRef,
|
|
24567
|
+
out,
|
|
24568
|
+
spent: event.spent,
|
|
24569
|
+
...event.verdict ? { verdict: event.verdict } : {},
|
|
24570
|
+
...event.outcome ? { outcome: event.outcome } : {}
|
|
24571
|
+
};
|
|
24572
|
+
}
|
|
24573
|
+
async function scopeRetainedOwnerPriorSpend(scope) {
|
|
24574
|
+
const state = owners.get(scope);
|
|
24575
|
+
if (!state) return zeroSpend();
|
|
24576
|
+
const events = (await state.args.journal.loadTree(state.args.rootId) ?? []).filter((event) => event.id === state.args.nodeId);
|
|
24577
|
+
const input = [...events].reverse().find((event) => event.kind === "execution-input");
|
|
24578
|
+
if (!input) return zeroSpend();
|
|
24579
|
+
return events.slice(events.indexOf(input)).reduce((total, event) => event.kind === "metered" ? addSpend(total, event.spend) : total, zeroSpend());
|
|
24580
|
+
}
|
|
24581
|
+
/** Called only after the scope verifies the accepted invocation's materialization. */
|
|
24582
|
+
function consumeScopeRetainedOwnerResult(scope) {
|
|
24583
|
+
const state = owners.get(scope);
|
|
24584
|
+
if (!state?.acceptedRef) throw new ValidationError$1("retained owner has no accepted result");
|
|
24585
|
+
state.acceptedConsumed = true;
|
|
24586
|
+
}
|
|
24587
|
+
//#endregion
|
|
24588
|
+
//#region src/runtime/supervise/seat-chain.ts
|
|
24589
|
+
var SeatChainExhaustedError = class extends Error {
|
|
24590
|
+
resumeAt;
|
|
24591
|
+
constructor(resumeAt) {
|
|
24592
|
+
super(`authored subscription seat chain exhausted; resume at ${resumeAt}`);
|
|
24593
|
+
this.name = "SeatChainExhaustedError";
|
|
24594
|
+
this.resumeAt = resumeAt;
|
|
24595
|
+
}
|
|
24596
|
+
};
|
|
24597
|
+
/** One logical node's durable chain. The spawn journal is the sole transition authority. */
|
|
24598
|
+
var SeatChain = class {
|
|
24599
|
+
profile;
|
|
24600
|
+
nodeId;
|
|
24601
|
+
rootId;
|
|
24602
|
+
journal;
|
|
24603
|
+
select;
|
|
24604
|
+
now;
|
|
24605
|
+
onSegment;
|
|
24606
|
+
beforeStart;
|
|
24607
|
+
observedThrough = -1;
|
|
24608
|
+
constructor(profile, nodeId, rootId, journal, select, now = Date.now, onSegment, beforeStart) {
|
|
24609
|
+
this.profile = profile;
|
|
24610
|
+
this.nodeId = nodeId;
|
|
24611
|
+
this.rootId = rootId;
|
|
24612
|
+
this.journal = journal;
|
|
24613
|
+
this.select = select;
|
|
24614
|
+
this.now = now;
|
|
24615
|
+
this.onSegment = onSegment;
|
|
24616
|
+
this.beforeStart = beforeStart;
|
|
24617
|
+
}
|
|
24618
|
+
async next(afterUsageLimit = false, afterRecheck = false) {
|
|
24619
|
+
const stages = authoredSeatStages(this.profile);
|
|
24620
|
+
if (!stages) throw new ValidationError$1("SeatChain requires authored AgentProfile.seats");
|
|
24621
|
+
const allEvents = await this.journal.loadTree(this.rootId) ?? [];
|
|
24622
|
+
const events = allEvents.filter((event) => event.kind === "seat-segment" && event.id === this.nodeId);
|
|
24623
|
+
const destroyed = new Set(allEvents.filter((event) => event.kind === "environment-teardown" && event.id === this.nodeId && event.destroyed).map((event) => event.environmentId));
|
|
24624
|
+
let admittedEnvironmentId;
|
|
24625
|
+
for (const event of allEvents) if (event.kind === "execution-admitted" && event.id === this.nodeId && event.admission.phase === "environment") admittedEnvironmentId = event.admission.environmentId;
|
|
24626
|
+
const retainedEnvironmentId = admittedEnvironmentId !== void 0 && !destroyed.has(admittedEnvironmentId) ? admittedEnvironmentId : void 0;
|
|
24627
|
+
await this.reconcile(events);
|
|
24628
|
+
const starts = events.filter((event) => event.phase === "started");
|
|
24629
|
+
const last = starts.at(-1);
|
|
24630
|
+
const closed = last && events.some((event) => event.phase === "ended" && event.segmentIndex === last.segmentIndex);
|
|
24631
|
+
if (last && !closed && afterUsageLimit) await this.end(last, "usage-limit");
|
|
24632
|
+
const resume = last && !closed && !afterUsageLimit;
|
|
24633
|
+
const segmentIndex = resume ? last.segmentIndex : (last?.segmentIndex ?? -1) + 1;
|
|
24634
|
+
const firstStageIndex = afterRecheck ? 0 : last?.stageIndex ?? 0;
|
|
24635
|
+
let earliestReset;
|
|
24636
|
+
for (let stageIndex = firstStageIndex; stageIndex < stages.length; stageIndex += 1) {
|
|
24637
|
+
const stage = stages[stageIndex];
|
|
24638
|
+
const excludedSeatIds = (afterRecheck ? [] : starts).filter((event) => event.stageIndex === stageIndex && (!resume || event.seat !== last.seat)).map((event) => event.seat);
|
|
24639
|
+
const prior = last === void 0 ? void 0 : {
|
|
24640
|
+
seat: last.seat,
|
|
24641
|
+
harness: last.harness,
|
|
24642
|
+
provider: last.provider,
|
|
24643
|
+
model: last.model
|
|
24644
|
+
};
|
|
24645
|
+
const preceding = resume ? starts.at(-2) : last;
|
|
24646
|
+
const requiresNativeTurnGrant = Boolean(preceding && preceding.provider === stage.provider && preceding.harness === stage.harness && (!resume || preceding.seat !== last.seat));
|
|
24647
|
+
const selection = checkedSeatSelection(stage, await this.select({
|
|
24648
|
+
profile: this.profile,
|
|
24649
|
+
nodeId: this.nodeId,
|
|
24650
|
+
stage,
|
|
24651
|
+
stageIndex,
|
|
24652
|
+
segmentIndex,
|
|
24653
|
+
excludedSeatIds,
|
|
24654
|
+
requiresNativeTurnGrant,
|
|
24655
|
+
...retainedEnvironmentId === void 0 ? {} : { retainedEnvironmentId },
|
|
24656
|
+
...prior === void 0 ? {} : { previous: prior },
|
|
24657
|
+
...resume ? { resumeSeatId: last.seat } : {}
|
|
24658
|
+
}));
|
|
24659
|
+
if ("resumeAt" in selection) {
|
|
24660
|
+
const reset = Date.parse(selection.resumeAt);
|
|
24661
|
+
earliestReset = earliestReset === void 0 ? reset : Math.min(earliestReset, reset);
|
|
24662
|
+
if (resume) break;
|
|
24663
|
+
continue;
|
|
24664
|
+
}
|
|
24665
|
+
if (resume && selection.seat !== last.seat) throw new ValidationError$1("selectSeat: resume changed the committed seat");
|
|
24666
|
+
if (excludedSeatIds.includes(selection.seat)) throw new ValidationError$1("selectSeat: selected an exhausted seat");
|
|
24667
|
+
if (preceding && preceding.seat !== selection.seat && preceding.provider === stage.provider && preceding.harness === stage.harness && selection.nativeTurnGrant !== true) throw new ValidationError$1("selectSeat: same-environment seat requires a verified native turn grant");
|
|
24668
|
+
const active = {
|
|
24669
|
+
seat: selection.seat,
|
|
24670
|
+
stageIndex,
|
|
24671
|
+
segmentIndex,
|
|
24672
|
+
stage,
|
|
24673
|
+
backend: selection.backend,
|
|
24674
|
+
...selection.nativeTurnGrant === true ? { nativeTurnGrant: true } : {},
|
|
24675
|
+
...preceding === void 0 ? {} : { previous: {
|
|
24676
|
+
seat: preceding.seat,
|
|
24677
|
+
harness: preceding.harness,
|
|
24678
|
+
provider: preceding.provider,
|
|
24679
|
+
model: preceding.model
|
|
24680
|
+
} }
|
|
24681
|
+
};
|
|
24682
|
+
if (!resume) {
|
|
24683
|
+
await this.beforeStart?.(active, prior);
|
|
24684
|
+
const at = new Date(this.now()).toISOString();
|
|
24685
|
+
await this.journal.appendEvent(this.rootId, {
|
|
24686
|
+
kind: "seat-segment",
|
|
24687
|
+
id: this.nodeId,
|
|
24688
|
+
segmentIndex,
|
|
24689
|
+
stageIndex,
|
|
24690
|
+
phase: "started",
|
|
24691
|
+
seat: selection.seat,
|
|
24692
|
+
harness: stage.harness,
|
|
24693
|
+
provider: stage.provider,
|
|
24694
|
+
model: stage.model,
|
|
24695
|
+
seq: segmentIndex,
|
|
24696
|
+
at
|
|
24697
|
+
});
|
|
24698
|
+
await this.onSegment?.({
|
|
24699
|
+
seat: selection.seat,
|
|
24700
|
+
harness: stage.harness,
|
|
24701
|
+
provider: stage.provider,
|
|
24702
|
+
model: stage.model,
|
|
24703
|
+
startedAt: at
|
|
24704
|
+
}, "started");
|
|
24705
|
+
this.observedThrough = events.length;
|
|
24706
|
+
return active;
|
|
24707
|
+
}
|
|
24708
|
+
return active;
|
|
24709
|
+
}
|
|
24710
|
+
const recheckAt = Math.max(earliestReset ?? 0, this.now() + 12e4);
|
|
24711
|
+
throw new SeatChainExhaustedError(new Date(recheckAt).toISOString());
|
|
24712
|
+
}
|
|
24713
|
+
async close(reason) {
|
|
24714
|
+
const events = (await this.journal.loadTree(this.rootId) ?? []).filter((event) => event.kind === "seat-segment" && event.id === this.nodeId);
|
|
24715
|
+
await this.reconcile(events);
|
|
24716
|
+
const last = events.filter((event) => event.phase === "started").at(-1);
|
|
24717
|
+
if (last && !events.some((event) => event.phase === "ended" && event.segmentIndex === last.segmentIndex)) await this.end(last, reason);
|
|
24718
|
+
}
|
|
24719
|
+
async end(start, reason) {
|
|
24720
|
+
const at = new Date(this.now()).toISOString();
|
|
24721
|
+
await this.journal.appendEvent(this.rootId, {
|
|
24722
|
+
...start,
|
|
24723
|
+
phase: "ended",
|
|
24724
|
+
reason,
|
|
24725
|
+
at
|
|
24726
|
+
});
|
|
24727
|
+
await this.onSegment?.({
|
|
24728
|
+
seat: start.seat,
|
|
24729
|
+
harness: start.harness,
|
|
24730
|
+
provider: start.provider,
|
|
24731
|
+
model: start.model,
|
|
24732
|
+
startedAt: start.at,
|
|
24733
|
+
endedAt: at,
|
|
24734
|
+
reason
|
|
24735
|
+
}, "ended");
|
|
24736
|
+
this.observedThrough += 1;
|
|
24737
|
+
}
|
|
24738
|
+
/** A crash may land between the authoritative journal append and observer delivery. On
|
|
24739
|
+
* reconstruction, deliver every unobserved boundary again; the observer projection folds
|
|
24740
|
+
* repeated boundaries by seat and start time, so a callback never decides execution identity. */
|
|
24741
|
+
async reconcile(events) {
|
|
24742
|
+
const starts = /* @__PURE__ */ new Map();
|
|
24743
|
+
for (let index = 0; index < events.length; index += 1) {
|
|
24744
|
+
const event = events[index];
|
|
24745
|
+
if (event.phase === "started") starts.set(event.segmentIndex, event);
|
|
24746
|
+
if (index <= this.observedThrough) continue;
|
|
24747
|
+
const start = event.phase === "started" ? event : starts.get(event.segmentIndex);
|
|
24748
|
+
if (!start) throw new ValidationError$1("seat segment ended without a committed start");
|
|
24749
|
+
await this.onSegment?.({
|
|
24750
|
+
seat: start.seat,
|
|
24751
|
+
harness: start.harness,
|
|
24752
|
+
provider: start.provider,
|
|
24753
|
+
model: start.model,
|
|
24754
|
+
startedAt: start.at,
|
|
24755
|
+
...event.phase === "ended" ? {
|
|
24756
|
+
endedAt: event.at,
|
|
24757
|
+
reason: event.reason
|
|
24758
|
+
} : {}
|
|
24759
|
+
}, event.phase);
|
|
24760
|
+
this.observedThrough = index;
|
|
24761
|
+
}
|
|
24762
|
+
}
|
|
24763
|
+
};
|
|
24764
|
+
/** Preserve the authored profile for identity; only the provider-facing copy changes stages. */
|
|
24765
|
+
function seatExecutionProfile(profile, stage) {
|
|
24766
|
+
const { seats: _seats, ...withoutSeats } = profile;
|
|
24767
|
+
return {
|
|
24768
|
+
...withoutSeats,
|
|
24769
|
+
harness: stage.harness,
|
|
24770
|
+
...stage.tools === void 0 ? {} : { tools: stage.tools },
|
|
24771
|
+
...stage.permissions === void 0 ? {} : { permissions: stage.permissions },
|
|
24772
|
+
model: {
|
|
24773
|
+
...profile.model,
|
|
24774
|
+
default: stage.model,
|
|
24775
|
+
provider: stage.provider
|
|
24776
|
+
}
|
|
23710
24777
|
};
|
|
23711
24778
|
}
|
|
23712
|
-
|
|
23713
|
-
const
|
|
23714
|
-
if (
|
|
23715
|
-
|
|
23716
|
-
|
|
23717
|
-
if (!input) return zeroSpend();
|
|
23718
|
-
return events.slice(events.indexOf(input)).reduce((total, event) => event.kind === "metered" ? addSpend(total, event.spend) : total, zeroSpend());
|
|
24779
|
+
function authoredSeatStages(profile) {
|
|
24780
|
+
const seats = profile.seats;
|
|
24781
|
+
if (seats === void 0) return void 0;
|
|
24782
|
+
if (!Array.isArray(seats) || seats.length === 0) throw new ValidationError$1("AgentProfile.seats must be a nonempty ordered chain");
|
|
24783
|
+
return seats;
|
|
23719
24784
|
}
|
|
23720
|
-
|
|
23721
|
-
|
|
23722
|
-
|
|
23723
|
-
|
|
23724
|
-
|
|
24785
|
+
const USAGE_LIMIT_CODES = /* @__PURE__ */ new Set([
|
|
24786
|
+
"subscription_usage_limit",
|
|
24787
|
+
"usage_limit_reached",
|
|
24788
|
+
"usage_limit_exceeded",
|
|
24789
|
+
"weekly_limit_reached",
|
|
24790
|
+
"session_limit_reached"
|
|
24791
|
+
]);
|
|
24792
|
+
/** Normalize a native harness refusal into a typed limit. A plain HTTP 429 is insufficient. */
|
|
24793
|
+
function subscriptionUsageLimitSignal(failure) {
|
|
24794
|
+
if (failure.errorCode && USAGE_LIMIT_CODES.has(failure.errorCode.toLowerCase())) return "subscription-usage-limit";
|
|
24795
|
+
if (/\bYou've hit your (?:usage|weekly|session) limit\b/iu.test(failure.error)) return "subscription-usage-limit";
|
|
24796
|
+
}
|
|
24797
|
+
/** An ineligible or misconfigured account must never turn an authored stage into another model. */
|
|
24798
|
+
function checkedSeatSelection(stage, selected) {
|
|
24799
|
+
if ("resumeAt" in selected) {
|
|
24800
|
+
if (!Number.isFinite(Date.parse(selected.resumeAt))) throw new ValidationError$1("selectSeat: resumeAt must be an ISO timestamp");
|
|
24801
|
+
return selected;
|
|
24802
|
+
}
|
|
24803
|
+
if (!selected.seat.trim()) throw new ValidationError$1("selectSeat: seat must be nonempty");
|
|
24804
|
+
if (stage.selector.kind === "seat" && stage.selector.id !== selected.seat) throw new ValidationError$1("selectSeat: selection does not match the authored seat");
|
|
24805
|
+
if (selected.backend.backend !== "provider") throw new ValidationError$1("selectSeat: selection must use a provider backend");
|
|
24806
|
+
return selected;
|
|
23725
24807
|
}
|
|
23726
24808
|
//#endregion
|
|
23727
24809
|
//#region src/runtime/supervise/scope.ts
|
|
@@ -25139,7 +26221,23 @@ async function publishOwnerMaterialization(state, runtime, declaration, bindingI
|
|
|
25139
26221
|
await rejectOwnerMaterialization(state);
|
|
25140
26222
|
throw new ValidationError$1("scope owner returned invalid materialization evidence", { cause: error });
|
|
25141
26223
|
}
|
|
25142
|
-
|
|
26224
|
+
const committed = state.receipt ?? state.prior;
|
|
26225
|
+
if (committed?.status === "known" && canonicalCandidateDigest(committed) !== canonicalCandidateDigest(receipt)) {
|
|
26226
|
+
const events = await state.journal.loadTree(state.retainedRoot) ?? [];
|
|
26227
|
+
const started = [...events].reverse().find((event) => event.id === state.nodeId && event.kind === "seat-segment" && event.phase === "started");
|
|
26228
|
+
const latestMaterialization = [...events].reverse().find((event) => event.id === state.nodeId && (event.kind === "materialized" || event.kind === "seat-materialized"));
|
|
26229
|
+
const lastSegmentIndex = latestMaterialization?.kind === "seat-materialized" ? latestMaterialization.segmentIndex : 0;
|
|
26230
|
+
const authored = agentProfileSchema.safeParse(state.authoredProfile);
|
|
26231
|
+
const authoredProfile = authored.success ? authored.data : void 0;
|
|
26232
|
+
const stage = authoredProfile && started?.kind === "seat-segment" ? authoredSeatStages(authoredProfile)?.[started.stageIndex] : void 0;
|
|
26233
|
+
if (authoredProfile && stage && started?.kind === "seat-segment" && started.segmentIndex > lastSegmentIndex && started.harness === stage.harness && started.provider === stage.provider && started.model === stage.model && receipt.status === "known" && receipt.effectiveProfileDigest === canonicalAgentProfileDigest(providerVisibleProfile(seatExecutionProfile(authoredProfile, stage))) && receipt.model.status === "known" && receipt.model.id === stage.model) {
|
|
26234
|
+
await appendOwnerSeatMaterialization(state, started.segmentIndex, receipt, binding);
|
|
26235
|
+
state.onReceipt?.(receipt, binding);
|
|
26236
|
+
state.publishedThisProcess = true;
|
|
26237
|
+
return;
|
|
26238
|
+
}
|
|
26239
|
+
}
|
|
26240
|
+
if (state.prior !== void 0 && state.receipt === void 0) {
|
|
25143
26241
|
if (canonicalCandidateDigest(state.prior) !== canonicalCandidateDigest(receipt)) {
|
|
25144
26242
|
await rejectOwnerMaterialization(state);
|
|
25145
26243
|
throw new ValidationError$1("scope owner materialization changed across resume; backend, model, execution identity, and plan must match");
|
|
@@ -25221,12 +26319,12 @@ async function restoreScopeOwnerAcceptedExecution(scope) {
|
|
|
25221
26319
|
const resultIndex = latestResult === void 0 ? -1 : owned.indexOf(latestResult);
|
|
25222
26320
|
const result = owned[resultIndex];
|
|
25223
26321
|
if (inputIndex < 0 || resultIndex <= inputIndex || result?.kind !== "execution-result") throw new ValidationError$1("scope owner has no accepted retained invocation");
|
|
25224
|
-
const receiptEvent = owned.slice(0, resultIndex).reverse().find((event) => event.kind === "materialized");
|
|
26322
|
+
const receiptEvent = owned.slice(0, resultIndex).reverse().find((event) => event.kind === "materialized" || event.kind === "seat-materialized");
|
|
25225
26323
|
const bindingEvent = owned.slice(inputIndex, resultIndex).reverse().find((event) => event.kind === "execution-bound");
|
|
25226
|
-
if (receiptEvent?.kind !== "materialized" || bindingEvent?.kind !== "execution-bound") throw new ValidationError$1("accepted scope owner result has no preceding materialization evidence");
|
|
26324
|
+
if (receiptEvent?.kind !== "materialized" && receiptEvent?.kind !== "seat-materialized" || bindingEvent?.kind !== "execution-bound") throw new ValidationError$1("accepted scope owner result has no preceding materialization evidence");
|
|
25227
26325
|
const { receipt } = receiptEvent;
|
|
25228
26326
|
const { binding } = bindingEvent;
|
|
25229
|
-
if (receipt.status !== "known" || binding.status !== "known" || receipt.runtime !== state.runtime || receipt.authoredProfileDigest !== state.authoredProfileDigest || binding.materializationReceiptDigest !== canonicalCandidateDigest(receipt) || state.prior !== void 0 && canonicalCandidateDigest(state.prior) !== canonicalCandidateDigest(receipt)) throw new ValidationError$1("accepted scope owner materialization does not match the resumed owner");
|
|
26327
|
+
if (receipt.status !== "known" || binding.status !== "known" || receipt.runtime !== state.runtime || receipt.authoredProfileDigest !== state.authoredProfileDigest || binding.materializationReceiptDigest !== canonicalCandidateDigest(receipt) || (state.receipt ?? state.prior) !== void 0 && canonicalCandidateDigest(state.receipt ?? state.prior) !== canonicalCandidateDigest(receipt)) throw new ValidationError$1("accepted scope owner materialization does not match the resumed owner");
|
|
25230
26328
|
assertValidSpend(result.spent, "accepted scope owner result");
|
|
25231
26329
|
const output = await state.blobs.get(result.outRef);
|
|
25232
26330
|
if (output === void 0 || contentAddress(output) !== result.outRef) throw new ValidationError$1("accepted scope owner output is missing or corrupt");
|
|
@@ -25318,6 +26416,18 @@ async function appendOwnerMaterialization(state, receipt, binding) {
|
|
|
25318
26416
|
state.receipt = receipt;
|
|
25319
26417
|
await appendOwnerBinding(state, binding);
|
|
25320
26418
|
}
|
|
26419
|
+
async function appendOwnerSeatMaterialization(state, segmentIndex, receipt, binding) {
|
|
26420
|
+
await appendOwnerEvidence(state, {
|
|
26421
|
+
kind: "seat-materialized",
|
|
26422
|
+
id: state.nodeId,
|
|
26423
|
+
segmentIndex,
|
|
26424
|
+
receipt,
|
|
26425
|
+
seq: segmentIndex,
|
|
26426
|
+
at: new Date(state.now()).toISOString()
|
|
26427
|
+
});
|
|
26428
|
+
state.receipt = receipt;
|
|
26429
|
+
await appendOwnerBinding(state, binding);
|
|
26430
|
+
}
|
|
25321
26431
|
async function appendOwnerBinding(state, binding) {
|
|
25322
26432
|
await appendOwnerEvidence(state, {
|
|
25323
26433
|
kind: "execution-bound",
|
|
@@ -25332,10 +26442,10 @@ async function appendOwnerEvidence(state, event) {
|
|
|
25332
26442
|
for (const root of /* @__PURE__ */ new Set([state.root, state.retainedRoot])) await appendExactMaterializationEvent(state.journal, root, event);
|
|
25333
26443
|
}
|
|
25334
26444
|
async function appendExactMaterializationEvent(journal, root, event) {
|
|
25335
|
-
const prior = (await journal.loadTree(root))?.find((item) => item.id === event.id && (event.kind === "materialized" ? item.kind === "materialized" : item.kind === "execution-bound" && item.binding.attemptId === event.binding.attemptId));
|
|
25336
|
-
if (prior?.kind === "materialized" || prior?.kind === "execution-bound") {
|
|
25337
|
-
const previous = prior.kind === "
|
|
25338
|
-
const next = event.kind === "
|
|
26445
|
+
const prior = (await journal.loadTree(root))?.find((item) => item.id === event.id && (event.kind === "materialized" ? item.kind === "materialized" : event.kind === "seat-materialized" ? item.kind === "seat-materialized" && item.segmentIndex === event.segmentIndex : item.kind === "execution-bound" && item.binding.attemptId === event.binding.attemptId));
|
|
26446
|
+
if (prior?.kind === "materialized" || prior?.kind === "seat-materialized" || prior?.kind === "execution-bound") {
|
|
26447
|
+
const previous = prior.kind === "execution-bound" ? prior.binding : prior.receipt;
|
|
26448
|
+
const next = event.kind === "execution-bound" ? event.binding : event.receipt;
|
|
25339
26449
|
if (canonicalCandidateDigest(previous) !== canonicalCandidateDigest(next)) throw new ValidationError$1("scope execution evidence conflicts with its committed record");
|
|
25340
26450
|
return;
|
|
25341
26451
|
}
|
|
@@ -26213,7 +27323,7 @@ function isInfraError(err) {
|
|
|
26213
27323
|
* journal so the executor can run its `act` inside a nested scope. `act` fails loud if
|
|
26214
27324
|
* called directly — a driver child runs THROUGH its nested-scope executor, never as a root.
|
|
26215
27325
|
*/
|
|
26216
|
-
function driverChild(profile, driver, journal, execution, acceptedSubmission, recoverExecutor, unassessedOutput) {
|
|
27326
|
+
function driverChild(profile, driver, journal, execution, acceptedSubmission, recoverExecutor, unassessedOutput, leafDeliverable) {
|
|
26217
27327
|
const name = profile.name ?? driver.name;
|
|
26218
27328
|
const traceSource = driver.traceSource;
|
|
26219
27329
|
const progress = driver.progress;
|
|
@@ -26228,6 +27338,7 @@ function driverChild(profile, driver, journal, execution, acceptedSubmission, re
|
|
|
26228
27338
|
journal,
|
|
26229
27339
|
...acceptedSubmission ? { acceptedSubmission } : {},
|
|
26230
27340
|
...unassessedOutput ? { unassessedOutput } : {},
|
|
27341
|
+
...leafDeliverable ? { leafDeliverable } : {},
|
|
26231
27342
|
...recoverExecutor ? { recoverExecutor } : {},
|
|
26232
27343
|
...traceSource ? { traceSource } : {},
|
|
26233
27344
|
...progress ? { progress } : {},
|
|
@@ -26435,642 +27546,144 @@ function withDriverExecutor(base) {
|
|
|
26435
27546
|
const spec = executableAgentSpecSnapshot(rawSpec, "driver executor registry");
|
|
26436
27547
|
if (spec.driverRuntime === "driver" && !spec.executor) return {
|
|
26437
27548
|
succeeded: true,
|
|
26438
|
-
value: ((_ignored, context) => driverExecutorFactory(spec, context))
|
|
27549
|
+
value: ((_ignored, context) => isDriverSpec(spec) && spec.leafDeliverable ? attestNestedDriverTreeOwner(gateOnDeliverable(driverExecutorFactory(spec, context), spec.leafDeliverable)) : driverExecutorFactory(spec, context))
|
|
26439
27550
|
};
|
|
26440
27551
|
const resolved = base.resolve(spec);
|
|
26441
27552
|
if (!resolved.succeeded) return resolved;
|
|
26442
27553
|
return {
|
|
26443
|
-
succeeded: true,
|
|
26444
|
-
value: (_ignored, context) => resolved.value(spec, context)
|
|
26445
|
-
};
|
|
26446
|
-
}
|
|
26447
|
-
};
|
|
26448
|
-
}
|
|
26449
|
-
async function closeNestedScope(scope, controller, reason) {
|
|
26450
|
-
if (!controller.signal.aborted) controller.abort(reason);
|
|
26451
|
-
for (;;) if (await scope.next() === null) break;
|
|
26452
|
-
const view = scope.view;
|
|
26453
|
-
if (view.inFlight > 0) throw new ValidationError$1(`driverExecutor: nested cleanup left ${view.inFlight} running nodes`);
|
|
26454
|
-
}
|
|
26455
|
-
/** The nested tree's full event list — the one evidence the spend, verdict, AND driver-inference
|
|
26456
|
-
* roll-ups read off the same journal the supervisor sums. */
|
|
26457
|
-
async function loadTreeEvents(journal, nestedRoot) {
|
|
26458
|
-
const events = await journal.loadTree(nestedRoot);
|
|
26459
|
-
if (events === void 0) throw new ValidationError$1(`driverExecutor: nested tree '${nestedRoot}' missing from the journal after run (corrupted log)`);
|
|
26460
|
-
return events;
|
|
26461
|
-
}
|
|
26462
|
-
function isSettled(ev) {
|
|
26463
|
-
return ev.kind === "settled" || ev.kind === "cancelled" && ev.spent !== void 0;
|
|
26464
|
-
}
|
|
26465
|
-
/** Sum the conserved spend over the nested tree's settled events — the honest per-channel
|
|
26466
|
-
* roll-up of the whole sub-tree's child WORK. */
|
|
26467
|
-
function sumSpend(settled) {
|
|
26468
|
-
return settled.reduce((total, ev) => addSpend(total, ev.spent), zeroSpend());
|
|
26469
|
-
}
|
|
26470
|
-
/** Sum the nested tree's `metered` events — the sub-tree's whole driver INFERENCE (this driver's
|
|
26471
|
-
* own turns + any sub-driver inference already re-homed into this tree). Re-homed up to the parent
|
|
26472
|
-
* as one `metered` event; never reconciled (already pool-debited live via `observe`). */
|
|
26473
|
-
function sumMetered(events) {
|
|
26474
|
-
return events.reduce((total, ev) => ev.kind === "metered" ? addSpend(total, ev.spend) : total, zeroSpend());
|
|
26475
|
-
}
|
|
26476
|
-
/** An all-zero spend that carries an UNKNOWN marker counts as non-zero: a sub-driver whose turns
|
|
26477
|
-
* went unmeasured did real work, and dropping its `metered` event here would re-hide upstream the
|
|
26478
|
-
* very turn the driver refused to skip. */
|
|
26479
|
-
function isNonZeroSpend(s) {
|
|
26480
|
-
return s.iterations > 0 || s.tokens.input > 0 || s.tokens.output > 0 || s.usd > 0 || s.ms > 0 || s.tokensKnown === false || s.usdKnown === false || Object.keys(s.resources ?? {}).length > 0;
|
|
26481
|
-
}
|
|
26482
|
-
/** A spend, or `undefined` when it is all-zero — so `metered()` returns undefined for a driver
|
|
26483
|
-
* whose sub-tree did no inference (and the parent journals no empty `metered` event). */
|
|
26484
|
-
function nonZeroOrUndef(s) {
|
|
26485
|
-
return isNonZeroSpend(s) ? s : void 0;
|
|
26486
|
-
}
|
|
26487
|
-
/** Sum the nested tree's metered events, tolerating a missing tree (a crash before `beginTree`
|
|
26488
|
-
* landed) — never throw here, or it would mask the original `act` error on the crash path. */
|
|
26489
|
-
async function safeRollup(journal, nestedRoot) {
|
|
26490
|
-
try {
|
|
26491
|
-
const events = await loadTreeEvents(journal, nestedRoot);
|
|
26492
|
-
const childWork = sumSpend(events.filter(isSettled));
|
|
26493
|
-
const metered = nonZeroOrUndef(sumMetered(events));
|
|
26494
|
-
return {
|
|
26495
|
-
metered,
|
|
26496
|
-
accounting: {
|
|
26497
|
-
reported: childWork,
|
|
26498
|
-
reservation: addSpend(childWork, metered ?? zeroSpend())
|
|
26499
|
-
}
|
|
26500
|
-
};
|
|
26501
|
-
} catch {
|
|
26502
|
-
return;
|
|
26503
|
-
}
|
|
26504
|
-
}
|
|
26505
|
-
/** Derive the driver child's delivery verdict from an accepted direct submission, or from its
|
|
26506
|
-
* DIRECT children's settlements and the manager's actual finalized output: `valid` iff the
|
|
26507
|
-
* manager's own assignment check accepted a submission, or a direct child delivered AND the
|
|
26508
|
-
* finalizer returned a defined output;
|
|
26509
|
-
* `score` = the best delivered score. Returns `undefined` when no child settled at all (the
|
|
26510
|
-
* driver itself produced nothing to bubble a verdict from). Fail-closed: a child whose verdict
|
|
26511
|
-
* carried no `valid` counts as not-delivered. */
|
|
26512
|
-
function deriveDeliveryVerdict(settled, finalizedOutput, acceptedSubmission) {
|
|
26513
|
-
if (acceptedSubmission) return {
|
|
26514
|
-
valid: true,
|
|
26515
|
-
score: 1
|
|
26516
|
-
};
|
|
26517
|
-
let sawChild = false;
|
|
26518
|
-
let anyValid = false;
|
|
26519
|
-
let bestValidScore;
|
|
26520
|
-
let bestDoneScore;
|
|
26521
|
-
for (const ev of settled) {
|
|
26522
|
-
sawChild = true;
|
|
26523
|
-
if (ev.status !== "done") continue;
|
|
26524
|
-
const score = ev.verdict?.score;
|
|
26525
|
-
if (score !== void 0 && (bestDoneScore === void 0 || score > bestDoneScore)) bestDoneScore = score;
|
|
26526
|
-
if (ev.verdict?.valid === true) {
|
|
26527
|
-
anyValid = true;
|
|
26528
|
-
if (score !== void 0 && (bestValidScore === void 0 || score > bestValidScore)) bestValidScore = score;
|
|
26529
|
-
}
|
|
26530
|
-
}
|
|
26531
|
-
if (!sawChild) return void 0;
|
|
26532
|
-
const accepted = anyValid && finalizedOutput !== void 0;
|
|
26533
|
-
return {
|
|
26534
|
-
valid: accepted,
|
|
26535
|
-
score: accepted ? bestValidScore ?? 1 : bestDoneScore ?? 0
|
|
26536
|
-
};
|
|
26537
|
-
}
|
|
26538
|
-
function readNestedScopeSeam(ctx) {
|
|
26539
|
-
const seam = ctx.seams[nestedScopeSeamKey];
|
|
26540
|
-
if (!seam || typeof seam.mount !== "function") throw new ValidationError$1(`driverExecutor: missing required seam "${nestedScopeSeamKey}" — a driver child must be spawned through a Scope that seeds it (the keystone scope does)`);
|
|
26541
|
-
return seam;
|
|
26542
|
-
}
|
|
26543
|
-
function isAgent(value) {
|
|
26544
|
-
return typeof value === "object" && value !== null && typeof value.act === "function" && typeof value.name === "string";
|
|
26545
|
-
}
|
|
26546
|
-
/** Parent journals may already contain an interrupted driver's inference prefix. */
|
|
26547
|
-
function unreportedSpend(total, prior) {
|
|
26548
|
-
const tokens = { ...total.tokens };
|
|
26549
|
-
for (const key of [
|
|
26550
|
-
"input",
|
|
26551
|
-
"output",
|
|
26552
|
-
"freshInput",
|
|
26553
|
-
"cacheRead",
|
|
26554
|
-
"cacheWrite"
|
|
26555
|
-
]) {
|
|
26556
|
-
const value = total.tokens[key];
|
|
26557
|
-
if (value !== void 0) tokens[key] = Math.max(0, value - (prior.tokens[key] ?? 0));
|
|
26558
|
-
}
|
|
26559
|
-
return {
|
|
26560
|
-
...total,
|
|
26561
|
-
...addResourceSpend(total.resources === void 0 ? void 0 : Object.fromEntries(Object.entries(total.resources).map(([name, value]) => {
|
|
26562
|
-
const previous = prior.resources?.[name];
|
|
26563
|
-
if (previous && previous.unit !== value.unit) throw new ValidationError$1(`resource ${name}: unit mismatch`);
|
|
26564
|
-
return [name, {
|
|
26565
|
-
...value,
|
|
26566
|
-
amount: Math.max(0, value.amount - (previous?.amount ?? 0)),
|
|
26567
|
-
known: value.known && (previous?.known ?? true)
|
|
26568
|
-
}];
|
|
26569
|
-
}))),
|
|
26570
|
-
iterations: Math.max(0, total.iterations - prior.iterations),
|
|
26571
|
-
tokens,
|
|
26572
|
-
usd: Math.max(0, total.usd - prior.usd),
|
|
26573
|
-
ms: Math.max(0, total.ms - prior.ms),
|
|
26574
|
-
...total.usdEstimated === void 0 ? {} : { usdEstimated: Math.max(0, total.usdEstimated - (prior.usdEstimated ?? 0)) },
|
|
26575
|
-
...total.boxMinutes === void 0 ? {} : { boxMinutes: Math.max(0, total.boxMinutes - (prior.boxMinutes ?? 0)) }
|
|
26576
|
-
};
|
|
26577
|
-
}
|
|
26578
|
-
//#endregion
|
|
26579
|
-
//#region src/runtime/supervise/continuation.ts
|
|
26580
|
-
/**
|
|
26581
|
-
* The continuation: what a manager with a completion check is told when its turn ends and the
|
|
26582
|
-
* check is unmet, and the one rule that decides whether it is sent back.
|
|
26583
|
-
*
|
|
26584
|
-
* Measured on discovery-lab before this module (2026-09-24, 670 settled runs, 1,596 re-entries):
|
|
26585
|
-
* 1,565 re-entries followed a failed turn and resent the original task, and 31 carried note text.
|
|
26586
|
-
* The note Runtime wrote itself held seven fixed lines and no field for the check's verdict. Of 40
|
|
26587
|
-
* episodes where the director ended on its own and the outside check disagreed, 33 were told
|
|
26588
|
-
* nothing before they ended. 100 of 236 resubmits sent the identical packet. So the director
|
|
26589
|
-
* mostly graded itself, and when it was wrong it heard nothing it could use.
|
|
26590
|
-
*
|
|
26591
|
-
* The design (discovery `docs/38-one-loop-and-continuation.md`) makes three things single, and
|
|
26592
|
-
* this module holds the part Runtime owns:
|
|
26593
|
-
*
|
|
26594
|
-
* - ONE CHECK. A check reading is a {@link CheckVerdict}: pass, the items it read, the composite,
|
|
26595
|
-
* and one `FAIL <item> <where>: <reason>` line per failed item. The same check decides
|
|
26596
|
-
* `submit_result`, runs when a turn ends without an accepted result, scores the finished run,
|
|
26597
|
-
* and ranks versions. A check that could not run gives no verdict ({@link CheckUnavailableError}),
|
|
26598
|
-
* and the loop pauses instead of blaming the director.
|
|
26599
|
-
* - ONE RESEND RULE. {@link ContinuationPolicy} is required for a manager with a check. It holds a
|
|
26600
|
-
* deadline and `maxBarren`, the re-entered turns in a row that may end without progress. There
|
|
26601
|
-
* is no re-prompt count and no default: a retry default in source is a research decision.
|
|
26602
|
-
* - ONE NOTE. {@link composeContinuationNote} writes it. Runtime owns the facts and their order;
|
|
26603
|
-
* the {@link ContinuationProfile} owns every instruction word, so an optimizer can change the
|
|
26604
|
-
* words without touching code. A play may append a section, never remove or rewrite one.
|
|
26605
|
-
*
|
|
26606
|
-
* Evidence behind the note's shape: located errors help (given the first mistake's true location,
|
|
26607
|
-
* fix rates rose 23.5 to 43.9 points, Tyen 2023); unsupported pressure does not (threats and tips
|
|
26608
|
-
* had no significant effect, Wharton 2025; challenges without evidence flipped correct answers,
|
|
26609
|
-
* FlipFlop); repeated summaries drop detail while itemized additions do not (ACE). So the note is
|
|
26610
|
-
* a list of located facts, findings are added and marked resolved rather than rewritten, and the
|
|
26611
|
-
* profile, not this file, decides how blunt the words are.
|
|
26612
|
-
*/
|
|
26613
|
-
/**
|
|
26614
|
-
* The check could not run: its box did not start, its judge's provider refused, its program
|
|
26615
|
-
* crashed. It is not a verdict on the result. Inside a run the loop pauses, as it does for an
|
|
26616
|
-
* unavailable upstream, and the refusal tells the director its result was not judged.
|
|
26617
|
-
*/
|
|
26618
|
-
var CheckUnavailableError = class extends Error {
|
|
26619
|
-
constructor(message, options) {
|
|
26620
|
-
super(message, options);
|
|
26621
|
-
this.name = "CheckUnavailableError";
|
|
26622
|
-
}
|
|
26623
|
-
};
|
|
26624
|
-
/** Read a check function's return value into a verdict. Anything but `true` or a passing verdict
|
|
26625
|
-
* is a failure: a check fails closed. */
|
|
26626
|
-
function checkVerdictOf(outcome) {
|
|
26627
|
-
if (outcome === true) return { pass: true };
|
|
26628
|
-
if (typeof outcome !== "object" || outcome === null || Array.isArray(outcome)) return { pass: false };
|
|
26629
|
-
const raw = outcome;
|
|
26630
|
-
const items = typeof raw.items === "object" && raw.items !== null && !Array.isArray(raw.items) ? Object.fromEntries(Object.entries(raw.items).filter((entry) => typeof entry[1] === "number" && Number.isFinite(entry[1]))) : void 0;
|
|
26631
|
-
const failures = Array.isArray(raw.failures) ? raw.failures.filter((line) => typeof line === "string" && line.trim() !== "") : void 0;
|
|
26632
|
-
return Object.freeze({
|
|
26633
|
-
pass: raw.pass === true,
|
|
26634
|
-
...items === void 0 ? {} : { items: Object.freeze(items) },
|
|
26635
|
-
...finite(raw.composite) ? { composite: raw.composite } : {},
|
|
26636
|
-
...finite(raw.threshold) ? { threshold: raw.threshold } : {},
|
|
26637
|
-
...failures === void 0 ? {} : { failures: Object.freeze(failures) },
|
|
26638
|
-
...typeof raw.review === "string" && raw.review.trim() !== "" ? { review: raw.review.trim() } : {}
|
|
26639
|
-
});
|
|
26640
|
-
}
|
|
26641
|
-
/**
|
|
26642
|
-
* Read an agent-eval `JudgeScore` from a check program into a verdict.
|
|
26643
|
-
*
|
|
26644
|
-
* Each dimension is a checked item. `notes` lines that start with `FAIL ` are the failures; the
|
|
26645
|
-
* remaining lines are the check's review. The verdict passes when `composite >= threshold` and the
|
|
26646
|
-
* score is not marked `failed`; a `failed` score means the judge itself did not run, which is
|
|
26647
|
-
* {@link CheckUnavailableError}, not a verdict.
|
|
26648
|
-
*/
|
|
26649
|
-
function verdictFromJudgeScore(score, threshold) {
|
|
26650
|
-
if (score.failed === true) throw new CheckUnavailableError(`the check's judge did not run: ${score.notes}`);
|
|
26651
|
-
const lines = score.notes.split("\n").map((line) => line.trimEnd());
|
|
26652
|
-
const failures = lines.filter((line) => line.startsWith("FAIL "));
|
|
26653
|
-
const review = lines.filter((line) => !line.startsWith("FAIL ") && line.trim() !== "").join("\n");
|
|
26654
|
-
return checkVerdictOf({
|
|
26655
|
-
pass: score.composite >= threshold,
|
|
26656
|
-
items: score.dimensions,
|
|
26657
|
-
composite: score.composite,
|
|
26658
|
-
threshold,
|
|
26659
|
-
failures,
|
|
26660
|
-
...review === "" ? {} : { review }
|
|
26661
|
-
});
|
|
27554
|
+
succeeded: true,
|
|
27555
|
+
value: (_ignored, context) => resolved.value(spec, context)
|
|
27556
|
+
};
|
|
27557
|
+
}
|
|
27558
|
+
};
|
|
26662
27559
|
}
|
|
26663
|
-
|
|
26664
|
-
|
|
26665
|
-
|
|
26666
|
-
|
|
27560
|
+
async function closeNestedScope(scope, controller, reason) {
|
|
27561
|
+
if (!controller.signal.aborted) controller.abort(reason);
|
|
27562
|
+
for (;;) if (await scope.next() === null) break;
|
|
27563
|
+
const view = scope.view;
|
|
27564
|
+
if (view.inFlight > 0) throw new ValidationError$1(`driverExecutor: nested cleanup left ${view.inFlight} running nodes`);
|
|
26667
27565
|
}
|
|
26668
|
-
/**
|
|
26669
|
-
|
|
26670
|
-
|
|
27566
|
+
/** The nested tree's full event list — the one evidence the spend, verdict, AND driver-inference
|
|
27567
|
+
* roll-ups read off the same journal the supervisor sums. */
|
|
27568
|
+
async function loadTreeEvents(journal, nestedRoot) {
|
|
27569
|
+
const events = await journal.loadTree(nestedRoot);
|
|
27570
|
+
if (events === void 0) throw new ValidationError$1(`driverExecutor: nested tree '${nestedRoot}' missing from the journal after run (corrupted log)`);
|
|
27571
|
+
return events;
|
|
26671
27572
|
}
|
|
26672
|
-
|
|
26673
|
-
|
|
26674
|
-
if (typeof policy !== "object" || policy === null) throw new ValidationError$1(`${context}: continuation must be an object`);
|
|
26675
|
-
const deadlineMs = typeof policy.deadline === "string" ? Date.parse(policy.deadline) : policy.deadline;
|
|
26676
|
-
if (typeof deadlineMs !== "number" || !Number.isFinite(deadlineMs) || deadlineMs <= 0) throw new ValidationError$1(`${context}: continuation.deadline must be a finite time (epoch ms or ISO 8601)`);
|
|
26677
|
-
if (!Number.isInteger(policy.maxBarren) || policy.maxBarren < 1) throw new ValidationError$1(`${context}: continuation.maxBarren must be an integer >= 1`);
|
|
26678
|
-
if (policy.failures !== "verbatim" && policy.failures !== "off") throw new ValidationError$1(`${context}: continuation.failures must be 'verbatim' or 'off'`);
|
|
26679
|
-
if (policy.panel !== "on" && policy.panel !== "off") throw new ValidationError$1(`${context}: continuation.panel must be 'on' or 'off'`);
|
|
26680
|
-
if (policy.bar !== "on" && policy.bar !== "off") throw new ValidationError$1(`${context}: continuation.bar must be 'on' or 'off'`);
|
|
26681
|
-
if (policy.panel === "on") {
|
|
26682
|
-
if (typeof policy.runPanel !== "function") throw new ValidationError$1(`${context}: continuation.panel 'on' needs runPanel`);
|
|
26683
|
-
const usd = policy.panelUsd;
|
|
26684
|
-
if (usd === void 0 || !finite(usd.perContinuation) || !finite(usd.perRun) || usd.perContinuation <= 0 || usd.perRun < usd.perContinuation) throw new ValidationError$1(`${context}: continuation.panel 'on' needs panelUsd with 0 < perContinuation <= perRun`);
|
|
26685
|
-
}
|
|
26686
|
-
if (policy.append !== void 0 && typeof policy.append !== "function") throw new ValidationError$1(`${context}: continuation.append must be a function`);
|
|
26687
|
-
admitContinuationProfile(policy.profile, context);
|
|
26688
|
-
return deadlineMs;
|
|
27573
|
+
function isSettled(ev) {
|
|
27574
|
+
return ev.kind === "settled" || ev.kind === "cancelled" && ev.spent !== void 0;
|
|
26689
27575
|
}
|
|
26690
|
-
/**
|
|
26691
|
-
|
|
26692
|
-
|
|
26693
|
-
|
|
26694
|
-
"failed",
|
|
26695
|
-
"total",
|
|
26696
|
-
"reads",
|
|
26697
|
-
"owed",
|
|
26698
|
-
"settled",
|
|
26699
|
-
"delivered",
|
|
26700
|
-
"continuation"
|
|
26701
|
-
];
|
|
26702
|
-
const factNames = new Set(CONTINUATION_FACTS);
|
|
26703
|
-
const placeholder = /\{([a-zA-Z]+)\}/gu;
|
|
26704
|
-
function admitContinuationProfile(profile, context) {
|
|
26705
|
-
if (typeof profile !== "object" || profile === null) throw new ValidationError$1(`${context}: continuation.profile must be an object`);
|
|
26706
|
-
if (typeof profile.id !== "string" || profile.id.trim() === "") throw new ValidationError$1(`${context}: continuation.profile.id must be non-empty`);
|
|
26707
|
-
const texts = [
|
|
26708
|
-
["opening", profile.opening],
|
|
26709
|
-
["plan", profile.plan],
|
|
26710
|
-
["rules", profile.rules],
|
|
26711
|
-
...Object.entries(profile.headings ?? {}).map(([key, value]) => [`headings.${key}`, value]),
|
|
26712
|
-
...profile.barRule === void 0 ? [] : [["barRule", profile.barRule]]
|
|
26713
|
-
];
|
|
26714
|
-
for (const key of [
|
|
26715
|
-
"failures",
|
|
26716
|
-
"protected",
|
|
26717
|
-
"changed",
|
|
26718
|
-
"findings",
|
|
26719
|
-
"bar",
|
|
26720
|
-
"plan",
|
|
26721
|
-
"rules"
|
|
26722
|
-
]) if (typeof profile.headings?.[key] !== "string") throw new ValidationError$1(`${context}: continuation.profile.headings.${key} must be a string`);
|
|
26723
|
-
for (const [key, text] of texts) {
|
|
26724
|
-
if (typeof text !== "string") throw new ValidationError$1(`${context}: continuation.profile.${key} must be a string`);
|
|
26725
|
-
for (const match of text.matchAll(placeholder)) if (!factNames.has(match[1] ?? "")) throw new ValidationError$1(`${context}: continuation.profile.${key} names {${match[1]}}, which is not a fact Runtime supplies (${CONTINUATION_FACTS.join(", ")})`);
|
|
26726
|
-
}
|
|
26727
|
-
if (profile.review !== void 0) {
|
|
26728
|
-
if (typeof profile.review !== "string" || profile.review.trim() === "") throw new ValidationError$1(`${context}: continuation.profile.review must be non-empty`);
|
|
26729
|
-
for (const match of profile.review.matchAll(placeholder)) if (![
|
|
26730
|
-
"version",
|
|
26731
|
-
"path",
|
|
26732
|
-
"score"
|
|
26733
|
-
].includes(match[1] ?? "")) throw new ValidationError$1(`${context}: continuation.profile.review names {${match[1]}}; it may name {version}, {path} and {score}`);
|
|
26734
|
-
}
|
|
26735
|
-
if (profile.opening.trim() === "") throw new ValidationError$1(`${context}: continuation.profile.opening must be non-empty`);
|
|
26736
|
-
for (const [index, question] of (profile.questions ?? []).entries()) if (typeof question !== "string" || question.trim() === "") throw new ValidationError$1(`${context}: continuation.profile.questions[${index}] must be a non-empty string`);
|
|
27576
|
+
/** Sum the conserved spend over the nested tree's settled events — the honest per-channel
|
|
27577
|
+
* roll-up of the whole sub-tree's child WORK. */
|
|
27578
|
+
function sumSpend(settled) {
|
|
27579
|
+
return settled.reduce((total, ev) => addSpend(total, ev.spent), zeroSpend());
|
|
26737
27580
|
}
|
|
26738
|
-
/**
|
|
26739
|
-
*
|
|
26740
|
-
*
|
|
26741
|
-
function
|
|
26742
|
-
|
|
26743
|
-
if (finding.citations.length === 0) return false;
|
|
26744
|
-
if (!finding.citations.every((citation) => citation.resolved)) return false;
|
|
26745
|
-
return new Set(finding.citations.map((citation) => citation.uri)).size >= 2;
|
|
27581
|
+
/** Sum the nested tree's `metered` events — the sub-tree's whole driver INFERENCE (this driver's
|
|
27582
|
+
* own turns + any sub-driver inference already re-homed into this tree). Re-homed up to the parent
|
|
27583
|
+
* as one `metered` event; never reconciled (already pool-debited live via `observe`). */
|
|
27584
|
+
function sumMetered(events) {
|
|
27585
|
+
return events.reduce((total, ev) => ev.kind === "metered" ? addSpend(total, ev.spend) : total, zeroSpend());
|
|
26746
27586
|
}
|
|
26747
|
-
/**
|
|
26748
|
-
|
|
26749
|
-
|
|
26750
|
-
|
|
26751
|
-
|
|
26752
|
-
* detail that repeated rewrites lose); a finding whose items all pass now is marked resolved.
|
|
26753
|
-
*/
|
|
26754
|
-
function distillFindings(prior, proposed, failing, continuation) {
|
|
26755
|
-
const key = (claim) => claim.toLowerCase().replace(/\s+/gu, " ").trim();
|
|
26756
|
-
const known = new Set(prior.map((finding) => key(finding.claim)));
|
|
26757
|
-
const carried = prior.map((finding) => finding.resolvedAt === void 0 && (finding.items?.length ?? 0) > 0 && (finding.items ?? []).every((item) => !failing.has(item)) ? {
|
|
26758
|
-
...finding,
|
|
26759
|
-
resolvedAt: continuation
|
|
26760
|
-
} : finding);
|
|
26761
|
-
const fresh = proposed.filter(admitFinding).filter((finding) => {
|
|
26762
|
-
const k = key(finding.claim);
|
|
26763
|
-
if (known.has(k)) return false;
|
|
26764
|
-
known.add(k);
|
|
26765
|
-
return true;
|
|
26766
|
-
}).map((finding) => ({
|
|
26767
|
-
finding,
|
|
26768
|
-
links: (finding.items ?? []).filter((item) => failing.has(item)).length
|
|
26769
|
-
})).sort((a, b) => b.links - a.links);
|
|
26770
|
-
const out = [...carried];
|
|
26771
|
-
let used = carried.filter((finding) => finding.resolvedAt === void 0).reduce((sum, finding) => sum + finding.claim.length, 0);
|
|
26772
|
-
for (const { finding } of fresh) {
|
|
26773
|
-
if (used + finding.claim.length > FINDINGS_CHAR_CAP) break;
|
|
26774
|
-
used += finding.claim.length;
|
|
26775
|
-
out.push({
|
|
26776
|
-
...finding,
|
|
26777
|
-
admittedAt: continuation
|
|
26778
|
-
});
|
|
26779
|
-
}
|
|
26780
|
-
return out;
|
|
27587
|
+
/** An all-zero spend that carries an UNKNOWN marker counts as non-zero: a sub-driver whose turns
|
|
27588
|
+
* went unmeasured did real work, and dropping its `metered` event here would re-hide upstream the
|
|
27589
|
+
* very turn the driver refused to skip. */
|
|
27590
|
+
function isNonZeroSpend(s) {
|
|
27591
|
+
return s.iterations > 0 || s.tokens.input > 0 || s.tokens.output > 0 || s.usd > 0 || s.ms > 0 || s.tokensKnown === false || s.usdKnown === false || Object.keys(s.resources ?? {}).length > 0;
|
|
26781
27592
|
}
|
|
26782
|
-
/**
|
|
26783
|
-
|
|
26784
|
-
|
|
26785
|
-
|
|
26786
|
-
|
|
26787
|
-
|
|
26788
|
-
|
|
26789
|
-
|
|
26790
|
-
|
|
26791
|
-
|
|
26792
|
-
const
|
|
26793
|
-
const
|
|
26794
|
-
|
|
27593
|
+
/** A spend, or `undefined` when it is all-zero — so `metered()` returns undefined for a driver
|
|
27594
|
+
* whose sub-tree did no inference (and the parent journals no empty `metered` event). */
|
|
27595
|
+
function nonZeroOrUndef(s) {
|
|
27596
|
+
return isNonZeroSpend(s) ? s : void 0;
|
|
27597
|
+
}
|
|
27598
|
+
/** Sum the nested tree's metered events, tolerating a missing tree (a crash before `beginTree`
|
|
27599
|
+
* landed) — never throw here, or it would mask the original `act` error on the crash path. */
|
|
27600
|
+
async function safeRollup(journal, nestedRoot) {
|
|
27601
|
+
try {
|
|
27602
|
+
const events = await loadTreeEvents(journal, nestedRoot);
|
|
27603
|
+
const childWork = sumSpend(events.filter(isSettled));
|
|
27604
|
+
const metered = nonZeroOrUndef(sumMetered(events));
|
|
27605
|
+
return {
|
|
27606
|
+
metered,
|
|
27607
|
+
accounting: {
|
|
27608
|
+
reported: childWork,
|
|
27609
|
+
reservation: addSpend(childWork, metered ?? zeroSpend())
|
|
27610
|
+
}
|
|
27611
|
+
};
|
|
27612
|
+
} catch {
|
|
27613
|
+
return;
|
|
26795
27614
|
}
|
|
26796
|
-
return out;
|
|
26797
27615
|
}
|
|
26798
|
-
/**
|
|
26799
|
-
*
|
|
26800
|
-
*
|
|
26801
|
-
|
|
26802
|
-
|
|
26803
|
-
|
|
26804
|
-
|
|
26805
|
-
|
|
26806
|
-
|
|
26807
|
-
|
|
26808
|
-
|
|
26809
|
-
threshold: verdict?.threshold === void 0 ? "unknown" : format(verdict.threshold),
|
|
26810
|
-
failed: verdict === void 0 || total === 0 && (verdict.failures?.length ?? 0) === 0 ? "unknown" : String(failing.length),
|
|
26811
|
-
total: total === 0 ? "unknown" : String(total),
|
|
26812
|
-
reads: String(input.reads),
|
|
26813
|
-
owed: input.owed?.trim() || "not described",
|
|
26814
|
-
settled: String(input.progress.settledCount),
|
|
26815
|
-
delivered: String(input.progress.deliveredCount ?? 0),
|
|
26816
|
-
continuation: String(input.continuation)
|
|
26817
|
-
};
|
|
26818
|
-
const fill = (text) => text.replace(placeholder, (_, name) => facts[name] ?? `{${name}}`);
|
|
26819
|
-
const sections = [verdict === void 0 ? "No check verdict is available yet." + (input.canSubmitResult === true ? " Submit a result through submit_result to request the check." : "") : verdict.pass ? "The check passes on the current state, but no result has been accepted." + (input.canSubmitResult === true ? " Call submit_result to request acceptance." : "") : fill(profile.opening).trim()];
|
|
26820
|
-
const section = (heading, body) => {
|
|
26821
|
-
if (body.length === 0) return;
|
|
26822
|
-
sections.push([...heading.trim() === "" ? [] : [`## ${fill(heading)}`], ...body].join("\n"));
|
|
27616
|
+
/** Derive the driver child's delivery verdict from an accepted direct submission, or from its
|
|
27617
|
+
* DIRECT children's settlements and the manager's actual finalized output: `valid` iff the
|
|
27618
|
+
* manager's own assignment check accepted a submission, or a direct child delivered AND the
|
|
27619
|
+
* finalizer returned a defined output;
|
|
27620
|
+
* `score` = the best delivered score. Returns `undefined` when no child settled at all (the
|
|
27621
|
+
* driver itself produced nothing to bubble a verdict from). Fail-closed: a child whose verdict
|
|
27622
|
+
* carried no `valid` counts as not-delivered. */
|
|
27623
|
+
function deriveDeliveryVerdict(settled, finalizedOutput, acceptedSubmission) {
|
|
27624
|
+
if (acceptedSubmission) return {
|
|
27625
|
+
valid: true,
|
|
27626
|
+
score: 1
|
|
26823
27627
|
};
|
|
26824
|
-
|
|
26825
|
-
|
|
26826
|
-
|
|
26827
|
-
|
|
26828
|
-
|
|
26829
|
-
|
|
26830
|
-
|
|
26831
|
-
|
|
26832
|
-
|
|
26833
|
-
|
|
26834
|
-
|
|
26835
|
-
|
|
26836
|
-
section(profile.headings.changed, [
|
|
26837
|
-
...fixed.length === 0 ? [] : [`Now passing: ${fixed.join(", ")}.`],
|
|
26838
|
-
...broke.length === 0 ? [] : [`Newly failing: ${broke.join(", ")}.`],
|
|
26839
|
-
...fixed.length === 0 && broke.length === 0 ? ["No item changed since the last note."] : [],
|
|
26840
|
-
...input.previous.composite !== void 0 && verdict.composite !== void 0 ? [`Composite: ${format(input.previous.composite)} then ${format(verdict.composite)}.`] : []
|
|
26841
|
-
]);
|
|
26842
|
-
}
|
|
26843
|
-
}
|
|
26844
|
-
if (input.findings !== void 0) {
|
|
26845
|
-
const open = input.findings.filter((finding) => finding.resolvedAt === void 0);
|
|
26846
|
-
const resolved = input.findings.filter((finding) => finding.resolvedAt === input.continuation);
|
|
26847
|
-
section(profile.headings.findings, [...open.map((finding) => `- [hypothesis] ${finding.claim}` + (finding.items?.length ? ` (items: ${finding.items.join(", ")})` : "") + ` Evidence: ${finding.citations.map((citation) => citation.uri).join(", ")}`), ...resolved.map((finding) => `- [resolved] ${finding.claim}`)]);
|
|
26848
|
-
}
|
|
26849
|
-
if (input.bar !== void 0 && verdict !== void 0) {
|
|
26850
|
-
const body = [];
|
|
26851
|
-
if (profile.barRule?.trim()) body.push(fill(profile.barRule).trim());
|
|
26852
|
-
for (const [item, value] of Object.entries(items)) {
|
|
26853
|
-
const best = input.bar.best?.verdict.items?.[item];
|
|
26854
|
-
body.push(`- ${item}: ${value >= 1 ? "passes" : `fails (${format(value)})`}` + (best === void 0 ? "" : ` / ${input.bar.best?.label}: ${best >= 1 ? "passes" : `fails (${format(best)})`}`));
|
|
27628
|
+
let sawChild = false;
|
|
27629
|
+
let anyValid = false;
|
|
27630
|
+
let bestValidScore;
|
|
27631
|
+
let bestDoneScore;
|
|
27632
|
+
for (const ev of settled) {
|
|
27633
|
+
sawChild = true;
|
|
27634
|
+
if (ev.status !== "done") continue;
|
|
27635
|
+
const score = ev.verdict?.score;
|
|
27636
|
+
if (score !== void 0 && (bestDoneScore === void 0 || score > bestDoneScore)) bestDoneScore = score;
|
|
27637
|
+
if (ev.verdict?.valid === true) {
|
|
27638
|
+
anyValid = true;
|
|
27639
|
+
if (score !== void 0 && (bestValidScore === void 0 || score > bestValidScore)) bestValidScore = score;
|
|
26855
27640
|
}
|
|
26856
|
-
if (input.bar.best?.verdict.composite !== void 0) body.push(`Best version ${input.bar.best.label}: composite ${format(input.bar.best.verdict.composite)}.`);
|
|
26857
|
-
if (input.bar.reference?.trim()) body.push(`Reference result: ${input.bar.reference.trim()}`);
|
|
26858
|
-
if (verdict.review?.trim()) body.push(`The check's review: ${verdict.review.trim()}`);
|
|
26859
|
-
section(profile.headings.bar, body);
|
|
26860
27641
|
}
|
|
26861
|
-
|
|
26862
|
-
|
|
26863
|
-
for (const appended of input.appended ?? []) section(appended.heading, appended.text.trim() === "" ? [] : [appended.text.trim()]);
|
|
26864
|
-
return sections.join("\n\n");
|
|
26865
|
-
}
|
|
26866
|
-
function summarizeVerdict(verdict) {
|
|
26867
|
-
if (verdict === void 0) return null;
|
|
26868
|
-
const total = Object.keys(verdict.items ?? {}).length;
|
|
27642
|
+
if (!sawChild) return void 0;
|
|
27643
|
+
const accepted = anyValid && finalizedOutput !== void 0;
|
|
26869
27644
|
return {
|
|
26870
|
-
|
|
26871
|
-
|
|
26872
|
-
...total === 0 ? {} : {
|
|
26873
|
-
failed: failedItems(verdict).length,
|
|
26874
|
-
total
|
|
26875
|
-
}
|
|
27645
|
+
valid: accepted,
|
|
27646
|
+
score: accepted ? bestValidScore ?? 1 : bestDoneScore ?? 0
|
|
26876
27647
|
};
|
|
26877
27648
|
}
|
|
26878
|
-
function
|
|
26879
|
-
|
|
27649
|
+
function readNestedScopeSeam(ctx) {
|
|
27650
|
+
const seam = ctx.seams[nestedScopeSeamKey];
|
|
27651
|
+
if (!seam || typeof seam.mount !== "function") throw new ValidationError$1(`driverExecutor: missing required seam "${nestedScopeSeamKey}" — a driver child must be spawned through a Scope that seeds it (the keystone scope does)`);
|
|
27652
|
+
return seam;
|
|
26880
27653
|
}
|
|
26881
|
-
|
|
26882
|
-
|
|
26883
|
-
const CONTINUATIONS_DIR = "continuations";
|
|
26884
|
-
/**
|
|
26885
|
-
* Write one continuation's files under `<dir>/<n>/`: `note.md`, `verdict.json`, and
|
|
26886
|
-
* `panel.jsonl` when the panel ran. The director reads them through `read_continuation`, because
|
|
26887
|
-
* its box cannot read the driver's run directory.
|
|
26888
|
-
*/
|
|
26889
|
-
async function writeContinuationFiles(dir, continuation, files) {
|
|
26890
|
-
const at = join(dir, String(continuation));
|
|
26891
|
-
await mkdir(at, { recursive: true });
|
|
26892
|
-
await writeFile(join(at, "note.md"), `${files.note}\n`, "utf8");
|
|
26893
|
-
await writeFile(join(at, "verdict.json"), `${JSON.stringify(files.verdict ?? null, null, 2)}\n`, "utf8");
|
|
26894
|
-
if (files.panel !== void 0) await writeFile(join(at, "panel.jsonl"), files.panel.map((line) => JSON.stringify(line)).join("\n") + (files.panel.length ? "\n" : ""), "utf8");
|
|
27654
|
+
function isAgent(value) {
|
|
27655
|
+
return typeof value === "object" && value !== null && typeof value.act === "function" && typeof value.name === "string";
|
|
26895
27656
|
}
|
|
26896
|
-
/**
|
|
26897
|
-
function
|
|
26898
|
-
|
|
26899
|
-
for (const
|
|
26900
|
-
|
|
26901
|
-
|
|
27657
|
+
/** Parent journals may already contain an interrupted driver's inference prefix. */
|
|
27658
|
+
function unreportedSpend(total, prior) {
|
|
27659
|
+
const tokens = { ...total.tokens };
|
|
27660
|
+
for (const key of [
|
|
27661
|
+
"input",
|
|
27662
|
+
"output",
|
|
27663
|
+
"freshInput",
|
|
27664
|
+
"cacheRead",
|
|
27665
|
+
"cacheWrite"
|
|
27666
|
+
]) {
|
|
27667
|
+
const value = total.tokens[key];
|
|
27668
|
+
if (value !== void 0) tokens[key] = Math.max(0, value - (prior.tokens[key] ?? 0));
|
|
26902
27669
|
}
|
|
26903
|
-
return best;
|
|
26904
|
-
}
|
|
26905
|
-
function finite(value) {
|
|
26906
|
-
return typeof value === "number" && Number.isFinite(value);
|
|
26907
|
-
}
|
|
26908
|
-
function format(value) {
|
|
26909
|
-
return Number.isInteger(value) ? String(value) : value.toFixed(3).replace(/0+$/u, "");
|
|
26910
|
-
}
|
|
26911
|
-
/** Build the continuation state for one manager with a check. */
|
|
26912
|
-
function createContinuationKeeper(input) {
|
|
26913
|
-
const { policy } = input;
|
|
26914
|
-
const failures = input.feedback === "pass-only" ? "off" : policy.failures;
|
|
26915
|
-
const entries = [];
|
|
26916
|
-
const notes = [];
|
|
26917
|
-
let findings = [];
|
|
26918
|
-
let panelUsd = 0;
|
|
26919
|
-
let panelUsdKnown = true;
|
|
26920
|
-
const latestVerdict = () => {
|
|
26921
|
-
const reads = input.reads();
|
|
26922
|
-
for (let i = reads.length - 1; i >= 0; i -= 1) {
|
|
26923
|
-
const read = reads[i];
|
|
26924
|
-
if (read?.verdict !== void 0) return {
|
|
26925
|
-
verdict: read.verdict,
|
|
26926
|
-
read: read.read
|
|
26927
|
-
};
|
|
26928
|
-
}
|
|
26929
|
-
return { read: 0 };
|
|
26930
|
-
};
|
|
26931
|
-
const closePrevious = () => {
|
|
26932
|
-
const last = entries.at(-1);
|
|
26933
|
-
const lastNote = notes.at(-1);
|
|
26934
|
-
if (last === void 0 || lastNote === void 0) return;
|
|
26935
|
-
const latest = latestVerdict();
|
|
26936
|
-
entries[entries.length - 1] = {
|
|
26937
|
-
...last,
|
|
26938
|
-
after: latest.read > lastNote.read ? summarizeVerdict(latest.verdict) : null
|
|
26939
|
-
};
|
|
26940
|
-
};
|
|
26941
27670
|
return {
|
|
26942
|
-
|
|
26943
|
-
|
|
26944
|
-
const
|
|
26945
|
-
|
|
26946
|
-
|
|
26947
|
-
|
|
26948
|
-
|
|
26949
|
-
|
|
26950
|
-
|
|
26951
|
-
|
|
26952
|
-
|
|
26953
|
-
|
|
26954
|
-
|
|
26955
|
-
|
|
26956
|
-
|
|
26957
|
-
|
|
26958
|
-
traces = await input.traces?.();
|
|
26959
|
-
if (traces === void 0) unavailable = "the run has recorded no trace yet";
|
|
26960
|
-
} catch (error) {
|
|
26961
|
-
unavailable = `the run's traces could not be read: ${error instanceof Error ? error.message : String(error)}`;
|
|
26962
|
-
}
|
|
26963
|
-
if (asking && traces !== void 0) {
|
|
26964
|
-
const result = await policy.runPanel({
|
|
26965
|
-
continuation,
|
|
26966
|
-
task: input.task,
|
|
26967
|
-
...verdict === void 0 ? {} : { verdict },
|
|
26968
|
-
reads: input.reads(),
|
|
26969
|
-
questions,
|
|
26970
|
-
traces,
|
|
26971
|
-
workers,
|
|
26972
|
-
...policy.best === void 0 ? {} : { bar: policy.best },
|
|
26973
|
-
...policy.reference === void 0 ? {} : { reference: policy.reference },
|
|
26974
|
-
usdCap,
|
|
26975
|
-
signal: context.signal
|
|
26976
|
-
});
|
|
26977
|
-
if (result.usd === null) panelUsdKnown = false;
|
|
26978
|
-
else panelUsd += result.usd;
|
|
26979
|
-
findings = distillFindings(findings, result.findings, new Set(failing), continuation);
|
|
26980
|
-
panelRecord = {
|
|
26981
|
-
asked: questions.length,
|
|
26982
|
-
proposed: result.findings.length,
|
|
26983
|
-
admitted: findings.filter((finding) => finding.admittedAt === continuation).length,
|
|
26984
|
-
usd: result.usd
|
|
26985
|
-
};
|
|
26986
|
-
panelLines = [...result.findings.map((finding) => ({
|
|
26987
|
-
kind: "finding",
|
|
26988
|
-
admitted: admitFinding(finding),
|
|
26989
|
-
...finding
|
|
26990
|
-
})), ...result.receipts === void 0 ? [] : [{
|
|
26991
|
-
kind: "receipts",
|
|
26992
|
-
receipts: result.receipts
|
|
26993
|
-
}]];
|
|
26994
|
-
} else panelRecord = {
|
|
26995
|
-
asked: 0,
|
|
26996
|
-
proposed: 0,
|
|
26997
|
-
admitted: 0,
|
|
26998
|
-
usd: 0,
|
|
26999
|
-
...unavailable === void 0 ? {} : { unavailable }
|
|
27000
|
-
};
|
|
27001
|
-
}
|
|
27002
|
-
const appended = policy.append ? await policy.append({
|
|
27003
|
-
continuation,
|
|
27004
|
-
...verdict === void 0 ? {} : { verdict },
|
|
27005
|
-
reads: input.reads(),
|
|
27006
|
-
signal: context.signal
|
|
27007
|
-
}) : void 0;
|
|
27008
|
-
const note = composeContinuationNote({
|
|
27009
|
-
profile: policy.profile,
|
|
27010
|
-
continuation,
|
|
27011
|
-
...verdict === void 0 ? {} : { verdict },
|
|
27012
|
-
...notes.at(-1)?.verdict === void 0 ? {} : { previous: notes.at(-1)?.verdict },
|
|
27013
|
-
reads: input.reads().length,
|
|
27014
|
-
failures,
|
|
27015
|
-
...policy.panel === "on" ? { findings } : {},
|
|
27016
|
-
...policy.bar === "on" ? { bar: {
|
|
27017
|
-
...policy.best === void 0 ? {} : { best: policy.best },
|
|
27018
|
-
...policy.reference === void 0 ? {} : { reference: policy.reference }
|
|
27019
|
-
} } : {},
|
|
27020
|
-
...appended === void 0 ? {} : { appended: [appended] },
|
|
27021
|
-
...input.owed === void 0 ? {} : { owed: input.owed },
|
|
27022
|
-
progress: context.progress,
|
|
27023
|
-
canReadMore: input.canReadMore,
|
|
27024
|
-
canSubmitResult: input.canSubmitResult === true,
|
|
27025
|
-
...input.sealed === true ? { sealed: true } : {}
|
|
27026
|
-
});
|
|
27027
|
-
notes.push({
|
|
27028
|
-
note,
|
|
27029
|
-
...verdict === void 0 ? {} : { verdict },
|
|
27030
|
-
...panelLines === void 0 ? {} : { panel: panelLines },
|
|
27031
|
-
read
|
|
27032
|
-
});
|
|
27033
|
-
entries.push({
|
|
27034
|
-
continuation,
|
|
27035
|
-
attempt: context.attempt,
|
|
27036
|
-
noteDigest: noteDigest(note),
|
|
27037
|
-
profile: policy.profile.id,
|
|
27038
|
-
switches: {
|
|
27039
|
-
failures,
|
|
27040
|
-
panel: policy.panel,
|
|
27041
|
-
bar: policy.bar
|
|
27042
|
-
},
|
|
27043
|
-
before: summarizeVerdict(verdict),
|
|
27044
|
-
after: null,
|
|
27045
|
-
...panelRecord === void 0 ? {} : { panel: panelRecord },
|
|
27046
|
-
appended: appended === void 0 ? 0 : 1
|
|
27047
|
-
});
|
|
27048
|
-
if (input.dir !== void 0) await writeContinuationFiles(input.dir, continuation, {
|
|
27049
|
-
note,
|
|
27050
|
-
...verdict === void 0 ? {} : { verdict },
|
|
27051
|
-
...panelLines === void 0 ? {} : { panel: panelLines }
|
|
27052
|
-
});
|
|
27053
|
-
return note;
|
|
27054
|
-
},
|
|
27055
|
-
read(continuation) {
|
|
27056
|
-
const index = continuation === void 0 ? notes.length - 1 : continuation - 1;
|
|
27057
|
-
const entry = notes[index];
|
|
27058
|
-
if (entry === void 0) return {
|
|
27059
|
-
found: false,
|
|
27060
|
-
reason: notes.length === 0 ? "no continuation has been sent in this run" : `continuations run from 1 to ${notes.length}`
|
|
27061
|
-
};
|
|
27062
|
-
return {
|
|
27063
|
-
found: true,
|
|
27064
|
-
continuation: index + 1,
|
|
27065
|
-
note: entry.note,
|
|
27066
|
-
verdict: failures === "off" && entry.verdict !== void 0 ? { pass: entry.verdict.pass } : entry.verdict ?? null,
|
|
27067
|
-
findings: findings.filter((finding) => finding.admittedAt <= index + 1)
|
|
27068
|
-
};
|
|
27069
|
-
},
|
|
27070
|
-
entries() {
|
|
27071
|
-
closePrevious();
|
|
27072
|
-
return entries.map((entry) => ({ ...entry }));
|
|
27073
|
-
}
|
|
27671
|
+
...total,
|
|
27672
|
+
...addResourceSpend(total.resources === void 0 ? void 0 : Object.fromEntries(Object.entries(total.resources).map(([name, value]) => {
|
|
27673
|
+
const previous = prior.resources?.[name];
|
|
27674
|
+
if (previous && previous.unit !== value.unit) throw new ValidationError$1(`resource ${name}: unit mismatch`);
|
|
27675
|
+
return [name, {
|
|
27676
|
+
...value,
|
|
27677
|
+
amount: Math.max(0, value.amount - (previous?.amount ?? 0)),
|
|
27678
|
+
known: value.known && (previous?.known ?? true)
|
|
27679
|
+
}];
|
|
27680
|
+
}))),
|
|
27681
|
+
iterations: Math.max(0, total.iterations - prior.iterations),
|
|
27682
|
+
tokens,
|
|
27683
|
+
usd: Math.max(0, total.usd - prior.usd),
|
|
27684
|
+
ms: Math.max(0, total.ms - prior.ms),
|
|
27685
|
+
...total.usdEstimated === void 0 ? {} : { usdEstimated: Math.max(0, total.usdEstimated - (prior.usdEstimated ?? 0)) },
|
|
27686
|
+
...total.boxMinutes === void 0 ? {} : { boxMinutes: Math.max(0, total.boxMinutes - (prior.boxMinutes ?? 0)) }
|
|
27074
27687
|
};
|
|
27075
27688
|
}
|
|
27076
27689
|
//#endregion
|
|
@@ -27229,11 +27842,18 @@ function upstreamUnavailableSignal(error) {
|
|
|
27229
27842
|
if (!(error instanceof Error)) return void 0;
|
|
27230
27843
|
if (isProviderSchemaRejection(error)) return void 0;
|
|
27231
27844
|
if (error instanceof CheckUnavailableError) return "check-unavailable";
|
|
27232
|
-
if (error instanceof HarnessTurnFailedError)
|
|
27233
|
-
|
|
27234
|
-
|
|
27235
|
-
|
|
27236
|
-
|
|
27845
|
+
if (error instanceof HarnessTurnFailedError) {
|
|
27846
|
+
const usageLimit = subscriptionUsageLimitSignal({
|
|
27847
|
+
error: error.message,
|
|
27848
|
+
...error.errorCode === void 0 ? {} : { errorCode: error.errorCode }
|
|
27849
|
+
});
|
|
27850
|
+
if (usageLimit !== void 0) return usageLimit;
|
|
27851
|
+
return unavailableSignalOfFailure({
|
|
27852
|
+
error: error.message,
|
|
27853
|
+
...error.errorCode === void 0 ? {} : { errorCode: error.errorCode },
|
|
27854
|
+
...error.statusCode === void 0 ? {} : { statusCode: error.statusCode }
|
|
27855
|
+
});
|
|
27856
|
+
}
|
|
27237
27857
|
if (error instanceof BackendTransportError) {
|
|
27238
27858
|
const code = error.upstreamCode?.toLowerCase();
|
|
27239
27859
|
if (code !== void 0 && UNAVAILABLE_CODES.has(code)) return code;
|
|
@@ -28778,6 +29398,6 @@ function isNonEmptySpend(s) {
|
|
|
28778
29398
|
return s.iterations > 0 || s.tokens.input > 0 || s.tokens.output > 0 || s.usd > 0 || s.ms > 0 || s.tokensKnown === false || s.usdKnown === false || Object.values(s.resources ?? {}).some((resource) => resource.amount > 0 || !resource.known);
|
|
28779
29399
|
}
|
|
28780
29400
|
//#endregion
|
|
28781
|
-
export {
|
|
29401
|
+
export { hostDirectoryReader as $, readSandboxOutcome as $i, workerTraceAnalysisStore as $n, sanitizeKnowledgeReadinessReport as $r, claimsAuthority as $t, scopeOwnerExecutorNodeContext as A, attestRuntimeOwnedPendingExecutor as Ai, unavailablePauseMs as An, retainHarnessTranscript as Ar, cliInPlaceExecutor as At, noteScopeRetainedOwnerCoordination as B, runtimeOwnedDriveHarnessProviderEvidence as Bi, InMemorySpawnJournal as Bn, buildLoopSpanNodes as Br, WORKER_TRACE_PROPAGATION as Bt, deriveNodeExecutionIdentity as C, promptResourceProfileMaterialization as Ci, routerBrain as Cn, linkAbort as Cr, distillFindings as Ct, recordScopeOwnerMaterialization as D, unsupportedProfileDimensions as Di, providerAsExecutor as Dn, persistHarnessTranscript as Dr, verdictFromJudgeScore as Dt, recordScopeOwnerDriverAttempt as E, sandboxActProfileMaterialization as Ei, createAgentEnvironmentProviderRegistry as En, harnessTranscriptArtifact as Er, passedItems as Et, seatExecutionProfile as F, knownExecutionBindingReceipt as Fi, registerRetainedExecutorPreparation as Fn, traceContextToEnv as Fr, createWorktreeCliExecutor as Ft, scopeRetainedOwnerJournalRoot as G, runtimeOwnedScopeOwnerRuntime as Gi, isNoEntError as Gn, generateSpanId as Gr, taskToPrompt as Gt, prepareScopeRetainedOwnerTask as H, runtimeOwnedExecutorMaterialization as Hi, loadSpawnForest as Hn, createOpenInferenceFileExporter as Hr, workerTraceEnv as Ht, beginScopeRetainedOwnerDrive as I, knownMaterializationReceipt as Ii, retainedExecutorSeamKey as In, defaultRedactor as Ir, DEFAULT_SANDBOX_STEERING_MAX_TURNS as It, scopeRetainedOwnerRestorePoint as J, executableAgentProfileSnapshot as Ji, writeAllBytes as Jn, padTraceId as Jr, readWorkerProgress as Jt, scopeRetainedOwnerPriorSpend as K, unknownExecutionBindingReceipt as Ki, prepareJsonlAppend as Kn, loopEventToOtelSpan as Kr, DEFAULT_STALL_AFTER_MS as Kt, bindScopeRetainedOwnerEnvironmentId as L, newExecutionAttemptId as Li, FileResultBlobStore as Ln, defaultRedactorIdentityMaterial as Lr, createSteerableSandboxSession as Lt, SeatChain as M, authoredProfileDigest as Mi, createPushTraceSource as Mn, createPropagatingTraceEmitter as Mr, createExecutor as Mt, SeatChainExhaustedError as N, finalizeRuntimeOwnedPendingExecutor as Ni, decodeToolPart as Nn, mergeTraceEnv as Nr, createExecutorRegistry as Nt, recordScopeOwnerPause as O, validateProfileMaterialization as Oi, providerAsSandboxClient as On, readHarnessTranscript as Or, bindReusableExecutorExecutionId as Ot, authoredSeatStages as P, inheritRuntimeOwnedExecutorAttestation as Pi, sandboxSessionTraceSource as Pn, readTraceContextFromEnv as Pr, snapshotExecutorConfig as Pt, environmentReader as Q, projectSandboxOutcome as Qi, parseWorkerToolTraceArtifact as Qn, sanitizeAgentRuntimeEvent as Qr, PEER_MAIL_WIRE_KEY as Qt, bindScopeRetainedOwnerProvider as R, providerAttemptEvidence as Ri, FileSpawnJournal as Rn, resolveRedactor as Rr, createRouterTranscript as Rt, createScope as S, promptOnlyProfileMaterialization as Si, readPromptOptions as Sn, abortError as Sr, createContinuationKeeper as St, meterRuntimeOwnedProviderAttempt as T, renderUnsupported as Ti, LEAF_CONTINUATION_TASK as Tn, captureHarnessTranscript as Tr, failedItems as Tt, reconcileScopeRetainedOwnerEnvironment as U, runtimeOwnedExecutorProviderEvidence as Ui, materializeTreeView as Un, createOtelExporter as Ur, workerTraceHeaders as Ut, prepareScopeRetainedOwnerSeatSwitch as V, runtimeOwnedExecutorExecutionBinding as Vi, insideCursorNamespace as Vn, buildRuntimeEventOtelSpans as Vr, readWorkerTraceContext as Vt, scopeRetainedOwnerContext as W, runtimeOwnedPendingExecutorMaterialization as Wi, replaySpawnTree as Wn, flatOtelSpan as Wr, workerTraceSeamKey as Wt, scopeRetainedOwnerTurnEnded as X, detachedFrozen as Xi, captureWorkerTraceEvidence as Xn, createRuntimeEventCollector as Xr, AUTHORITY_MARKERS as Xt, scopeRetainedOwnerResult as Y, executableAgentSpecSnapshot as Yi, WORKER_TOOL_TRACE_SCHEMA_VERSION as Yn, toOtelAttributes as Yr, createInbox as Yt, SPAWN_RESOURCE_PATH_MAX_BYTES as Z, detachedSnapshot as Zi, isTraceAnalysisStore as Zn, createRuntimeStreamEventCollector as Zr, DEFAULT_PEER_MAIL_LIMITS as Zt, isDriverSpec as _, providerMessageText as _a, defineProfileMaterializationContract as _i, createSandboxLineage as _n, destroyInteractiveEnvironment as _r, CheckUnavailableError as _t, collectDelivered as a, isSandboxTerminalEvent as aa, removeWorktree as ai, isTerminalNodeStatus as an, meterUsageEvent as ar, attachWorker as at, assertRecursiveReservationPolicy as b, promptControlProfileMaterialization as bi, captureBeforeDestroy as bn, openSlotGroup as br, bestComposite as bt, runTree as c, notifySandboxEventObserver as ca, harnessInvocation as ci, addHarnessUsage as cn, spendFromUsageTotals as cr, recoverRetainedInteractiveRun as ct, classifyDriverFailure as d, sumSandboxUsage as da, parseCodexTokenUsage as di, readCodexRolloutSession as dn, errMessage as dr, queueOf as dt, assertSandboxServedModel as ea, sanitizeRuntimeStreamEvent as ei, createPeerMailbox as en, executorFailure as er, resolveSpawnResourcePaths as et, runDriverWithRetry as f, decodeHarnessUsage as fa, CodexExecutionDiagnosticError as fi, TERMINAL_DECISIONS as fn, reconnectRetainedRun as fr, rollingDispatch as ft, driverExecutorFactory as g, promptOptionsFromAgentTurnInput as ga, controlProfileMaterialization as gi, runAgentRounds as gn, retainedCreateMaterial as gr, CONTINUATION_FACTS as gt, driverChild as h, promptFromAgentTurnInput as ha, assertProfileMaterialization as hi, isTerminalDecision as hn, startRetainedRunInEnvironment as hr, CONTINUATIONS_DIR as ht, bestDelivered as i, extractLlmCallEvent as ia, createWorktree as ii, isLiveNodeStatus as in, createBudgetPool as ir, interactiveAdmissionSeamKey as it, settledToIteration as j, attestRuntimeOwnedScopeOwner as ji, unavailableSignalOfFailure as jn, contentAddress as jr, cliWorktreeExecutor as jt, restoreScopeOwnerAcceptedExecution as k, worktreeCliProfileMaterialization as ki, resolveAgentEnvironmentProvider as kn, resolveHarnessTranscriptCapture as kr, captureReusableExecutorConfig as kt, DriverAttemptsExhaustedError as l, sandboxEventServedBackend as la, harnessSupportsReasoningEffort as li, createCodexRolloutStoreReader as ln, bridgeRuntimeAttachmentsKey as lr, startRetainedInteractiveRun as lt, upstreamUnavailableSignal as m, awaitAbortable$1 as ma, AGENT_PROFILE_MATERIALIZATION_AXES as mi, defaultSelectWinner as mn, startRetainedRun as mr, mapExecutorResult as mt, createRootHandle as n, createSandboxToolPartState as na, runWorktreeHarness as ni, peerMailTools as nn, ReservationWaitRefused as nr, coordinationProfileToolPrefix as nt, pickBestDelivered as o, mapSandboxEvent as oa, DEFAULT_LOCAL_HARNESS as oi, bridgeAdmissionRefusal as on, newUsageTotals as or, readWorkerInteractiveBinding as ot, summarizeDriverAttempts as p, abortError$1 as pa, terminateProcessTreeAndConfirm as pi, createSandboxForSpec as pn, recoverRetainedRun as pr, gateOnDeliverable as pt, scopeRetainedOwnerResourceReader as q, unknownMaterializationReceipt as qi, readCommittedJsonLines as qn, padSpanId as qr, createActivityLog as qt, createSupervisor as r, createSandboxUsageLedger as ra, captureWorktreeDiff as ri, peerMailVerbNames as rn, assertValidBudget as rr, providerVisibleProfile as rt, runFinalizer as s, mapSandboxToolEvent as sa, LOCAL_HARNESSES as si, bridgeModelRouteRefusal as sn, spendFromUsageEvents as sr, reconnectRetainedInteractiveRun as st, DEFAULT_MAX_DEPTH as t, canonicalStreamEventFromSandboxEvent as ta, runSettledCommand as ti, isPeerMailEnvelope as tn, BudgetReconcileFault as tr, coordinationMcpAlias as tt, HarnessTurnFailedError as u, sandboxProgressEvents as ua, localHarnessExecutable as ui, harnessUsageIsEmpty as un, bridgeStopSignalKey as ur, freeSlots as ut, withDriverExecutor as v, fullProfileMaterialization as vi, acquireSandbox as vn, environmentGone as vr, admitContinuationPolicy as vt, meterRuntimeOwnedAccounting as w, renderProfileMaterializationIssues as wi, runBrainLoop as wn, runAbortable as wr, expandQuestions as wt, beginScopeOwnerAttempt as x, promptModelProfileMaterialization as xi, assertBoxlessPromptOptions as xn, RunCancellationReason as xr, checkVerdictOf as xt, SUBTREE_RESULT_LIMIT as y, profileMaterializationAxes$1 as yi, SandboxEvidenceRetentionError as yn, createWorkerSlots as yr, admitFinding as yt, consumeScopeRetainedOwnerResult as z, recordRuntimeOwnedDriveHarnessProviderEvidence as zi, InMemoryResultBlobStore as zn, buildLoopOtelSpans as zr, createInPlaceCliExecutor as zt };
|
|
28782
29402
|
|
|
28783
|
-
//# sourceMappingURL=supervisor-
|
|
29403
|
+
//# sourceMappingURL=supervisor-Dz4XXtK1.js.map
|