@tangle-network/agent-runtime 0.342.1 → 0.343.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-DOH7Fnyp.js → activation-BMjalBNv.js} +4 -4
- package/dist/{activation-DOH7Fnyp.js.map → activation-BMjalBNv.js.map} +1 -1
- package/dist/{activation-CXqtijue.d.ts → activation-NJiV0MHb.d.ts} +2 -2
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +3 -3
- package/dist/{bundle-Cwpit6Tg.js → bundle-DKQtOO9d.js} +2 -2
- package/dist/{bundle-Cwpit6Tg.js.map → bundle-DKQtOO9d.js.map} +1 -1
- package/dist/candidate-execution/index.js +4 -4
- package/dist/{coordination-manager-HQE0bIav.js → coordination-manager-DIC19cgD.js} +22 -314
- package/dist/coordination-manager-DIC19cgD.js.map +1 -0
- package/dist/{delegate-DmShSdjy.js → delegate-BWXq1BeR.js} +2 -2
- package/dist/{delegate-DmShSdjy.js.map → delegate-BWXq1BeR.js.map} +1 -1
- package/dist/{durable-file-gNI9ILAn.js → durable-file-CA0kr1Pi.js} +8 -3
- package/dist/durable-file-CA0kr1Pi.js.map +1 -0
- package/dist/durable.d.ts +2 -2
- package/dist/durable.js +153 -16
- package/dist/durable.js.map +1 -1
- package/dist/{graph-BCghJFlS.js → graph-B89lApkU.js} +4 -4
- package/dist/{graph-BCghJFlS.js.map → graph-B89lApkU.js.map} +1 -1
- package/dist/{improve-Dga6OYt-.js → improve-CII-AhGN.js} +7 -8
- package/dist/{improve-Dga6OYt-.js.map → improve-CII-AhGN.js.map} +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +9 -9
- package/dist/intelligence.d.ts +2 -2
- package/dist/intelligence.js +6 -6
- package/dist/kernel.d.ts +1 -1
- package/dist/kernel.js +10 -11
- package/dist/{loop-runner-CW87Vqoj.js → loop-runner-Bbk9It72.js} +2 -2
- package/dist/{loop-runner-CW87Vqoj.js.map → loop-runner-Bbk9It72.js.map} +1 -1
- package/dist/{loop-runner-CuhbgVGo.d.ts → loop-runner-D56Rpd2z.d.ts} +2 -2
- 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 +1 -1
- package/dist/mcp/index.js +6 -6
- package/dist/mcp/index.js.map +1 -1
- package/dist/platform.js +1 -1
- package/dist/platform.js.map +1 -1
- package/dist/{prepare-C-cWCyt3.js → prepare-TEEHSJwq.js} +3 -3
- package/dist/{prepare-C-cWCyt3.js.map → prepare-TEEHSJwq.js.map} +1 -1
- package/dist/{profile-CbMw5hAn.js → profile-6OLpbjvV.js} +2 -2
- package/dist/{profile-CbMw5hAn.js.map → profile-6OLpbjvV.js.map} +1 -1
- package/dist/profiles.d.ts +1 -1
- package/dist/profiles.js +1 -1
- package/dist/profiles.js.map +1 -1
- package/dist/{provision-supervisor-BWR_TJFg.js → provision-supervisor-it-VCGyZ.js} +6 -6
- package/dist/{provision-supervisor-BWR_TJFg.js.map → provision-supervisor-it-VCGyZ.js.map} +1 -1
- package/dist/{run-cancellation-C9oL62sW.js → run-cancellation-DSpwvFmQ.js} +8 -4
- package/dist/{run-cancellation-C9oL62sW.js.map → run-cancellation-DSpwvFmQ.js.map} +1 -1
- package/dist/{runtime-CuRTZFe6.js → runtime-fKVK1rVb.js} +15 -17
- package/dist/{runtime-CuRTZFe6.js.map → runtime-fKVK1rVb.js.map} +1 -1
- package/dist/{sandbox-profile-compat-FN2kab2-.js → sandbox-profile-compat-_fEtHPCj.js} +2 -2
- package/dist/sandbox-profile-compat-_fEtHPCj.js.map +1 -0
- package/dist/{search-executor-0-SjHAao.js → search-executor-Ymr-tAKJ.js} +3 -3
- package/dist/{search-executor-0-SjHAao.js.map → search-executor-Ymr-tAKJ.js.map} +1 -1
- package/dist/{server-DTUK2wW1.js → server-BngfDubR.js} +4 -4
- package/dist/{server-DTUK2wW1.js.map → server-BngfDubR.js.map} +1 -1
- package/dist/{structural-rollout-kfaZgAkd.js → structural-rollout-BmKAIWWR.js} +3 -3
- package/dist/{structural-rollout-kfaZgAkd.js.map → structural-rollout-BmKAIWWR.js.map} +1 -1
- package/dist/{supervise-C_GAgiJU.js → supervise-DyCUu8Io.js} +415 -107
- package/dist/supervise-DyCUu8Io.js.map +1 -0
- package/dist/{supervisor-C_03z693.js → supervisor-gDn4C1o5.js} +627 -27
- package/dist/supervisor-gDn4C1o5.js.map +1 -0
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +13 -13
- package/dist/{top-snapshot-CbZE1JsU.js → top-snapshot-OjHdhai1.js} +2 -2
- package/dist/{top-snapshot-CbZE1JsU.js.map → top-snapshot-OjHdhai1.js.map} +1 -1
- package/dist/tui/bin.js +5 -3
- package/dist/tui/bin.js.map +1 -1
- package/dist/tui/index.d.ts +1 -1
- package/dist/tui/index.js +2 -2
- package/dist/{types-Cgs89PQd.d.ts → types-D0ZRqIJh.d.ts} +131 -17
- package/package.json +6 -6
- package/dist/content-digest-sBTLujlK.js +0 -9
- package/dist/content-digest-sBTLujlK.js.map +0 -1
- package/dist/coordination-manager-HQE0bIav.js.map +0 -1
- package/dist/durable-file-gNI9ILAn.js.map +0 -1
- package/dist/graph-registry-BnO64cn8.js +0 -197
- package/dist/graph-registry-BnO64cn8.js.map +0 -1
- package/dist/jsonl-file-C9Kde_0Z.js +0 -206
- package/dist/jsonl-file-C9Kde_0Z.js.map +0 -1
- package/dist/record-value-B6bwJxLa.js +0 -12
- package/dist/record-value-B6bwJxLa.js.map +0 -1
- package/dist/sandbox-profile-compat-FN2kab2-.js.map +0 -1
- package/dist/supervise-C_GAgiJU.js.map +0 -1
- package/dist/supervisor-C_03z693.js.map +0 -1
|
@@ -1,93 +1,23 @@
|
|
|
1
|
-
import { n as assertNoSymlinkDescendant } from "./durable-file-
|
|
2
|
-
import { $ as
|
|
1
|
+
import { c as __exportAll, n as assertNoSymlinkDescendant, o as writeAtomicDurableFile, s as sha256 } from "./durable-file-CA0kr1Pi.js";
|
|
2
|
+
import { $ as beginScopeRetainedOwnerDrive, $n as upstreamUnavailableSignal, A as coordinationProfileToolPrefix, An as createInbox, Ar as bridgeStopSignalKey, B as meterRuntimeOwnedProviderAttempt, Bi as assertValidBudget, Br as fullProfileMaterialization, Bt as toolResultText, Ci as cappedDoublingMs, Ct as captureReusableExecutorConfig, D as restoreScopeOwnerAcceptedExecution, Dr as runAbortable, E as recordScopeOwnerMaterialization, Ei as unavailableResumeAt, Er as linkAbort, F as deriveNodeExecutionIdentity, G as scopeRetainedOwnerResourceReader, Gn as isTerminalNodeStatus, H as recordScopeOwnerDriverAttempt, Hn as createActivityLog, Hr as promptControlProfileMaterialization, Ht as routerBrain, Ii as meterUsageEvent, Ir as assertProfileMaterialization, It as codeModeArguments, J as abandonScopeRetainedOwnerInvocation, Jn as abandonablePending, Jr as worktreeCliProfileMaterialization, Kn as DriverAttemptsExhaustedError, Kr as sandboxProfileMaterialization, Li as newUsageTotals, Ln as isPeerMailEnvelope, Lt as codeModeModelOutput, M as runtimeGraphMetadataKey, Mi as contentAddress, Ni as executorFailure, O as scopeOwnerExecutorNodeContext, P as assertRecursiveReservationPolicy, Pi as errMessage, Pn as PEER_MAIL_WIRE_KEY, Q as scopeRetainedOwnerResult, Qn as undispatchedCredentialExit, Rr as controlProfileMaterialization, Rt as createCodeModeTools, Si as retainedExecutorSeamKey, St as bindReusableExecutorExecutionId, T as noteScopeOwnerPlannedExecution, Ti as unavailablePauseMs, Tr as RunCancellationReason, Tt as snapshotExecutorConfig, U as recordScopeOwnerPause, Ur as promptModelProfileMaterialization, V as recordScopeOwnerBarrenPause, Vr as profileMaterializationAxes$1, Vt as createRouterTranscript, W as prepareScopeRetainedOwnerSeatSwitch, Wn as isLiveNodeStatus, Wr as renderUnsupported, Wt as resolveAgentEnvironmentProvider, X as prepareScopeRetainedOwnerTask, Xn as classifyDriverFailure, Xr as attestRuntimeOwnedScopeOwner, Y as consumeScopeRetainedOwnerResult, Yn as causedByPartialFailure, Z as scopeRetainedOwnerPriorSpend, Zn as summarizeDriverAttempts, Zr as authoredAgentIdentity, _r as bridgeModelRouteRefusal, _t as readCommittedJsonLines, a as runFinalizer, ai as recordRuntimeOwnedDriveHarnessProviderEvidence, ar as CheckUnavailableError, at as bindScopeRetainedOwnerProvider, bi as RetainedExecutionPendingError, bn as generateSpanId, c as driverChild, ci as runtimeOwnedExecutorMaterialization, di as runtimeOwnedScopeOwnerRuntime, dn as WORKER_TRACE_PROPAGATION, dr as bestComposite, ei as inheritRuntimeOwnedExecutorAttestation, er as SeatChain, et as scopeRetainedOwnerTurnEnded, fr as checkVerdictOf, gr as bridgeAdmissionRefusal, gt as readCommittedJsonFile, h as parseWorkerToolTraceArtifact, ht as prepareJsonlAppend, i as bestDelivered, ii as providerAttemptEvidence, in as readHarnessTranscript, it as bindScopeRetainedOwnerEnvironmentId, j as providerVisibleProfile, ji as detachedSnapshot, k as coordinationMcpAlias, kn as INBOX_RECEIPT_KEY, kr as bridgeRuntimeAttachmentsKey, l as driverExecutorFactory, li as runtimeOwnedExecutorProviderEvidence, lr as CONTINUATIONS_DIR, mt as isNoEntError, n as createSupervisor, nr as authoredSeatStages, nt as scopeRetainedOwnerRestorePoint, o as runTree, oi as runtimeOwnedDriveHarnessProviderEvidence, or as gateOnDeliverable, ot as scopeRetainedOwnerContext, pr as createContinuationKeeper, qn as HarnessTurnFailedError, qr as unsupportedProfileDimensions, rn as persistHarnessTranscript, rr as seatExecutionProfile, rt as noteScopeRetainedOwnerCoordination, s as createRootHandle, si as runtimeOwnedExecutorExecutionBinding, st as scopeRetainedOwnerJournalRoot, tr as SeatChainExhaustedError, tt as reconcileScopeRetainedOwnerEnvironment, u as isDriverSpec, ui as runtimeOwnedPendingExecutorMaterialization, ur as admitContinuationPolicy, vn as createOtelExporter, vt as upsertCommittedJsonLine, w as beginScopeOwnerAttempt, wi as jitteredMs, wn as toOtelAttributes, wt as createExecutor, xi as registerRetainedExecutorPreparation, yt as withJsonlFileLock, z as meterRuntimeOwnedAccounting, zi as spendFromUsageTotals, zr as defineProfileMaterializationContract } from "./supervisor-gDn4C1o5.js";
|
|
3
3
|
import { f as RuntimeRunStateError, i as ConfigError, m as ValidationError } from "./errors-DodWX-cb.js";
|
|
4
|
-
import {
|
|
5
|
-
import { Et as isDeadlineAbortReason, K as chargedTokens, Ot as teardownExecutor, W as addSpend, X as errorMessage, _t as withBudgetResources, dt as withTimeout, et as isAsyncIterable, ft as zeroSpend, gt as resourceTelemetry, kt as teardownSurfaces, mt as addResourceSpend, nt as promptCacheTokenClasses, ot as sleep, ut as unmeteredSpend, xt as DEFAULT_SUCCESSFUL_SHUTDOWN_MS } from "./sandbox-profile-compat-FN2kab2-.js";
|
|
4
|
+
import { Et as isDeadlineAbortReason, K as chargedTokens, Ot as teardownExecutor, W as addSpend, X as errorMessage, _t as withBudgetResources, dt as withTimeout, et as isAsyncIterable, ft as zeroSpend, gt as resourceTelemetry, kt as teardownSurfaces, mt as addResourceSpend, nt as promptCacheTokenClasses, ot as sleep, ut as unmeteredSpend, xt as DEFAULT_SUCCESSFUL_SHUTDOWN_MS } from "./sandbox-profile-compat-_fEtHPCj.js";
|
|
6
5
|
import { _ as agentHarness, a as concreteProfileModel, c as profileModelExecutionSettings, l as profileProviderModel, n as assertModelAllowed, o as enforceTokenLimits, r as assertProfileModelsAllowed, s as profileBridgeWireModel, t as assertExecutableAgentProfile, v as harnessRunsAgent } from "./model-policy-CyCUwHed.js";
|
|
7
6
|
import { t as composeRuntimeHooks } from "./runtime-hooks-tXpAarhW.js";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { a as watchRunCancellation, i as readRunCancellation, o as writeRunCancellation, r as readRunCancelRequest, t as applyRunCancellation } from "./run-cancellation-C9oL62sW.js";
|
|
7
|
+
import { c as budgetOverspendText, d as safeJsonText, f as createFileRunContext, l as normalizeAnalyzeOnSettle, m as withRunContext, n as createCoordinationToolsForManager, o as createCancelAcknowledger, p as createInMemoryRunContext, s as createSteerAcknowledger, t as createCoordinationTools, u as coordinationVerbNames } from "./coordination-manager-DIC19cgD.js";
|
|
8
|
+
import { c as writeRunCancellation, i as readRunCancellation, r as readRunCancelRequest, s as watchRunCancellation, t as applyRunCancellation } from "./run-cancellation-DSpwvFmQ.js";
|
|
11
9
|
import { n as createStdioToolServer, t as PROTOCOL_VERSION } from "./tool-server-XV4aJwoQ.js";
|
|
12
|
-
import { c as loadGraph, i as graphRegistry } from "./graph-registry-BnO64cn8.js";
|
|
13
10
|
import { agentProfileSchema, canonicalAgentProfileDigest, canonicalCandidateDigest, canonicalCandidateJson, validateAgentProfileSecurity } from "@tangle-network/agent-interface";
|
|
14
11
|
import { toolSpansToTraceAnalysisStore } from "@tangle-network/agent-eval";
|
|
12
|
+
import { isRecord } from "@tangle-network/agent-core";
|
|
15
13
|
import { createHash, createHmac, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
|
|
16
14
|
import { closeSync, constants, fsyncSync, openSync, writeSync } from "node:fs";
|
|
17
|
-
import { dirname, resolve } from "node:path";
|
|
18
|
-
import { mkdir } from "node:fs/promises";
|
|
15
|
+
import { dirname, join, resolve } from "node:path";
|
|
16
|
+
import { mkdir, readFile, readdir } from "node:fs/promises";
|
|
19
17
|
import { isMaterializerHarness } from "@tangle-network/agent-profile-materialize";
|
|
20
18
|
import { createServer } from "node:http";
|
|
21
19
|
import { ATTR, agentIdentityAttributes } from "@tangle-network/agent-trace-contract";
|
|
22
20
|
import { withProfileKb } from "@tangle-network/agent-interface/profile-kb";
|
|
23
|
-
//#region src/runtime/supervise/retained-owner-resource-reader.ts
|
|
24
|
-
/**
|
|
25
|
-
* The owner's environment as a source of by-path spawn resources.
|
|
26
|
-
*
|
|
27
|
-
* Built once per scope, before the environment exists: the coordination tools are created ahead
|
|
28
|
-
* of the owner's first turn, and the environment is admitted during it. So the reader resolves
|
|
29
|
-
* its target on every read — the latest environment admission on this node, reconstructed through
|
|
30
|
-
* the bound provider the same way cleanup reconstructs it, with the same identity check. A manager
|
|
31
|
-
* that has not yet been admitted, or whose provider was never bound, gets a refusal that names the
|
|
32
|
-
* missing piece rather than a read from nowhere.
|
|
33
|
-
*
|
|
34
|
-
* The environment's `read()` serves the sandbox's own workspace; containment against that
|
|
35
|
-
* workspace is the provider's. The relative-path and `..` rules are the reader's, in
|
|
36
|
-
* `environmentReader`, so a manager is refused for the rule it broke.
|
|
37
|
-
*/
|
|
38
|
-
function scopeRetainedOwnerResourceReader(scope) {
|
|
39
|
-
const state = owners.get(scope);
|
|
40
|
-
if (state === void 0) return void 0;
|
|
41
|
-
const latestEnvironmentId = () => state.liveEnvironmentId?.() ?? [...state.admissions].reverse().flatMap((admission) => admission.phase === "environment" ? [admission.environmentId] : [])[0];
|
|
42
|
-
return {
|
|
43
|
-
get describe() {
|
|
44
|
-
return `environment ${latestEnvironmentId() ?? "<not yet admitted>"}`;
|
|
45
|
-
},
|
|
46
|
-
async read(path) {
|
|
47
|
-
const provider = state.provider;
|
|
48
|
-
if (provider === void 0) return {
|
|
49
|
-
ok: false,
|
|
50
|
-
reason: "the manager’s environment provider is not bound yet"
|
|
51
|
-
};
|
|
52
|
-
const environmentId = latestEnvironmentId();
|
|
53
|
-
if (environmentId === void 0) return {
|
|
54
|
-
ok: false,
|
|
55
|
-
reason: "the manager’s environment has not been admitted yet"
|
|
56
|
-
};
|
|
57
|
-
if (!provider.get) return {
|
|
58
|
-
ok: false,
|
|
59
|
-
reason: `provider ${provider.name} cannot reconstruct the manager’s environment`
|
|
60
|
-
};
|
|
61
|
-
let environment;
|
|
62
|
-
try {
|
|
63
|
-
environment = await provider.get(environmentId);
|
|
64
|
-
} catch (error) {
|
|
65
|
-
return {
|
|
66
|
-
ok: false,
|
|
67
|
-
reason: `environment ${environmentId}: ${error instanceof Error ? error.message : String(error)}`
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
if (environment === null) return {
|
|
71
|
-
ok: false,
|
|
72
|
-
reason: `environment ${environmentId} is gone`
|
|
73
|
-
};
|
|
74
|
-
if (environment.id !== environmentId || environment.provider !== provider.name) return {
|
|
75
|
-
ok: false,
|
|
76
|
-
reason: `provider returned another environment for ${environmentId}`
|
|
77
|
-
};
|
|
78
|
-
if (typeof environment.read !== "function") return {
|
|
79
|
-
ok: false,
|
|
80
|
-
reason: `environment ${environmentId} does not expose read; its provider cannot serve a resource by path`
|
|
81
|
-
};
|
|
82
|
-
const read = environment.read.bind(environment);
|
|
83
|
-
return environmentReader({
|
|
84
|
-
id: environment.id,
|
|
85
|
-
read
|
|
86
|
-
}).read(path);
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
//#endregion
|
|
91
21
|
//#region src/runtime/supervise/supervise-identity.ts
|
|
92
22
|
function externalExecutionId(kind, identity) {
|
|
93
23
|
return `${kind}-${canonicalCandidateDigest({
|
|
@@ -5127,6 +5057,16 @@ const DEFAULT_MAX_BACKOFF_MS$1 = 3e4;
|
|
|
5127
5057
|
const DEFAULT_TRANSIENT_OUTAGE_MS = 9e5;
|
|
5128
5058
|
const BARREN_PAUSE_FIRST_MS = 5 * 6e4;
|
|
5129
5059
|
const BARREN_PAUSE_MAX_MS = 60 * 6e4;
|
|
5060
|
+
/** The stops an opted-in root pauses on (`DriverRetryRun.stopPause`). `completed`, `aborted` and a
|
|
5061
|
+
* declared `deadline` end the run; `supervise()` refuses `driverRetry.pauseRootStops` beside `retry-disabled`. */
|
|
5062
|
+
const PAUSED_STOPS = /* @__PURE__ */ new Set([
|
|
5063
|
+
"terminal-error",
|
|
5064
|
+
"no-progress",
|
|
5065
|
+
"max-attempts",
|
|
5066
|
+
"repeated-failure",
|
|
5067
|
+
"pending-unresolved",
|
|
5068
|
+
"budget-exhausted"
|
|
5069
|
+
]);
|
|
5130
5070
|
/**
|
|
5131
5071
|
* The pause before a continuation once `streak` re-entered drives in a row have completed without
|
|
5132
5072
|
* progress: 5 minutes at `maxBarren`, doubling per further barren drive, 60 minutes at most.
|
|
@@ -5175,6 +5115,10 @@ function budgetStop(budget, atMs) {
|
|
|
5175
5115
|
if (budget.usdCapped && budget.usdKnown === false) return "budget-exhausted";
|
|
5176
5116
|
if (Object.values(budget.resources ?? {}).some((resource) => !resource.known || resource.remaining <= 0)) return "budget-exhausted";
|
|
5177
5117
|
}
|
|
5118
|
+
/** The cause an admission or continuation refusal carries: it has no failure of its own. */
|
|
5119
|
+
function admissionError(stop) {
|
|
5120
|
+
return new ValidationError(`driver admission: ${stop}`);
|
|
5121
|
+
}
|
|
5178
5122
|
function contractOf(mark) {
|
|
5179
5123
|
return mark.contract ?? "none";
|
|
5180
5124
|
}
|
|
@@ -5227,6 +5171,7 @@ var DriverRetryLoop = class {
|
|
|
5227
5171
|
sameFailure;
|
|
5228
5172
|
samePartial;
|
|
5229
5173
|
abandonments = 0;
|
|
5174
|
+
stopPauses = 0;
|
|
5230
5175
|
pauses = 0;
|
|
5231
5176
|
continuations = 0;
|
|
5232
5177
|
wakes = 0;
|
|
@@ -5250,13 +5195,100 @@ var DriverRetryLoop = class {
|
|
|
5250
5195
|
this.attempts.push(stamped);
|
|
5251
5196
|
await this.run.onAttempt?.(stamped);
|
|
5252
5197
|
}
|
|
5253
|
-
/**
|
|
5254
|
-
|
|
5198
|
+
/**
|
|
5199
|
+
* Whether the next attempt may run: `undefined` admits it, `'refused'` returns before it, and a
|
|
5200
|
+
* stop is one an opted-in root pauses on before asking again. Throws when no attempt ever
|
|
5201
|
+
* completed. Synchronous, so nothing separates an admitted attempt from its dispatch.
|
|
5202
|
+
*/
|
|
5203
|
+
admission() {
|
|
5255
5204
|
const { run } = this;
|
|
5256
5205
|
const admissionStop = run.signal.aborted ? abortStop(run.signal) : budgetStop(run.budget(), this.limits.now());
|
|
5257
|
-
if (admissionStop === void 0) return
|
|
5258
|
-
if (this.
|
|
5259
|
-
|
|
5206
|
+
if (admissionStop === void 0) return void 0;
|
|
5207
|
+
if (this.pausesStop(admissionStop)) return admissionStop;
|
|
5208
|
+
if (this.attempts.length > 0) return "refused";
|
|
5209
|
+
throw new DriverAttemptsExhaustedError(run.signal.aborted ? run.signal.reason : admissionError(admissionStop), this.attempts, admissionStop);
|
|
5210
|
+
}
|
|
5211
|
+
/** Pause an opted-in root where admission would have stopped it; the re-entry is kept. */
|
|
5212
|
+
async pauseAdmission(stop, attempt) {
|
|
5213
|
+
await this.stopPause(admissionError(stop), stop, {
|
|
5214
|
+
attempt,
|
|
5215
|
+
durationMs: 0,
|
|
5216
|
+
madeProgress: false
|
|
5217
|
+
});
|
|
5218
|
+
}
|
|
5219
|
+
/** True when `stop` becomes a pause: the caller opted in, the stop is one the header names, and
|
|
5220
|
+
* neither the run nor the manager's own stop has fired. */
|
|
5221
|
+
pausesStop(stop) {
|
|
5222
|
+
const { run } = this;
|
|
5223
|
+
return run.stopPause !== void 0 && PAUSED_STOPS.has(stop) && !run.signal.aborted && run.stopSignal?.aborted !== true;
|
|
5224
|
+
}
|
|
5225
|
+
/** End the loop on `stop` with `record` (when the stop has one), or pause an opted-in root. */
|
|
5226
|
+
async stopOrPause(error, stop, record) {
|
|
5227
|
+
if (!this.pausesStop(stop)) {
|
|
5228
|
+
await this.emit({
|
|
5229
|
+
...record,
|
|
5230
|
+
stop
|
|
5231
|
+
});
|
|
5232
|
+
throw new DriverAttemptsExhaustedError(error, this.attempts, stop);
|
|
5233
|
+
}
|
|
5234
|
+
await this.stopPause(error, stop, record);
|
|
5235
|
+
}
|
|
5236
|
+
/** The earlier of the continuation deadline and the budget's deadline; infinite when neither is set. */
|
|
5237
|
+
deadlineAt() {
|
|
5238
|
+
const budgetDeadline = this.run.budget().deadlineMs;
|
|
5239
|
+
return Math.min(this.run.continuation?.deadlineMs ?? Number.POSITIVE_INFINITY, budgetDeadline > 0 ? budgetDeadline : Number.POSITIVE_INFINITY);
|
|
5240
|
+
}
|
|
5241
|
+
/**
|
|
5242
|
+
* The wait an opted-in root takes where it would stop (STOP-PAUSE in `./driver-retry.ts`). Emits
|
|
5243
|
+
* one record carrying `replacesStop`, sleeps until the ladder ends, a cancel or a root steer, and
|
|
5244
|
+
* resets the per-window counters. A cancel during the pause emits one `aborted` record and
|
|
5245
|
+
* throws; so does a declared deadline the pause reached. A failure re-enters as `driver-failure`.
|
|
5246
|
+
*/
|
|
5247
|
+
async stopPause(error, stop, record) {
|
|
5248
|
+
const { run, limits } = this;
|
|
5249
|
+
const steering = run.stopPause;
|
|
5250
|
+
if (steering === void 0) throw new DriverAttemptsExhaustedError(error, this.attempts, stop);
|
|
5251
|
+
this.stopPauses += 1;
|
|
5252
|
+
const pausedAt = limits.now();
|
|
5253
|
+
const pauseMs = Math.max(0, Math.min(cappedDoublingMs(this.stopPauses, BARREN_PAUSE_FIRST_MS, BARREN_PAUSE_MAX_MS), this.deadlineAt() - pausedAt));
|
|
5254
|
+
await this.emit({
|
|
5255
|
+
...record,
|
|
5256
|
+
replacesStop: stop,
|
|
5257
|
+
stopPauseStreak: this.stopPauses,
|
|
5258
|
+
retryInMs: pauseMs,
|
|
5259
|
+
resumeAt: new Date(pausedAt + pauseMs).toISOString()
|
|
5260
|
+
});
|
|
5261
|
+
const steered = new AbortController();
|
|
5262
|
+
const wait = AbortSignal.any([run.signal, steered.signal]);
|
|
5263
|
+
steering.steered(wait).then(() => steered.abort());
|
|
5264
|
+
try {
|
|
5265
|
+
await limits.sleep(pauseMs, wait);
|
|
5266
|
+
} finally {
|
|
5267
|
+
steered.abort();
|
|
5268
|
+
}
|
|
5269
|
+
const ended = run.signal.aborted ? abortStop(run.signal) : limits.now() >= this.deadlineAt() ? "deadline" : void 0;
|
|
5270
|
+
if (ended !== void 0) {
|
|
5271
|
+
await this.emit({
|
|
5272
|
+
attempt: record.attempt,
|
|
5273
|
+
durationMs: 0,
|
|
5274
|
+
madeProgress: false,
|
|
5275
|
+
stop: ended
|
|
5276
|
+
});
|
|
5277
|
+
throw new DriverAttemptsExhaustedError(error, this.attempts, ended);
|
|
5278
|
+
}
|
|
5279
|
+
this.chargedFailures = 0;
|
|
5280
|
+
this.consecutiveBarren = 0;
|
|
5281
|
+
this.sameFailure = void 0;
|
|
5282
|
+
this.samePartial = void 0;
|
|
5283
|
+
this.samePending = void 0;
|
|
5284
|
+
this.abandonments = 0;
|
|
5285
|
+
this.outageSince = void 0;
|
|
5286
|
+
if (record.error !== void 0) this.reentry = {
|
|
5287
|
+
reason: "driver-failure",
|
|
5288
|
+
failure: errMessage(error),
|
|
5289
|
+
retry: this.failures,
|
|
5290
|
+
pausedMs: pauseMs
|
|
5291
|
+
};
|
|
5260
5292
|
}
|
|
5261
5293
|
failureRecord(failure) {
|
|
5262
5294
|
return {
|
|
@@ -5271,16 +5303,17 @@ var DriverRetryLoop = class {
|
|
|
5271
5303
|
const { run } = this;
|
|
5272
5304
|
if (run.signal.aborted) throw new DriverAttemptsExhaustedError(error, this.attempts, abortStop(run.signal));
|
|
5273
5305
|
const afterWait = budgetStop(run.budget(), this.limits.now());
|
|
5274
|
-
if (afterWait) throw new DriverAttemptsExhaustedError(error, this.attempts, afterWait);
|
|
5306
|
+
if (afterWait && !this.pausesStop(afterWait)) throw new DriverAttemptsExhaustedError(error, this.attempts, afterWait);
|
|
5275
5307
|
}
|
|
5276
5308
|
/** Read a failed drive, then pause or retry it, or throw the stop that ends the loop. */
|
|
5277
5309
|
async afterFailure(error, attempt, before, startedAt) {
|
|
5278
5310
|
const durationMs = this.limits.now() - startedAt;
|
|
5279
|
-
const classification = classifyDriverFailure(error, this.run.signal);
|
|
5311
|
+
const classification = classifyDriverFailure(error, this.run.signal, this.run.stopSignal);
|
|
5280
5312
|
const after = this.run.progress();
|
|
5281
5313
|
const progressed = madeProgress(before, after);
|
|
5282
5314
|
if (progressed) {
|
|
5283
5315
|
this.abandonments = 0;
|
|
5316
|
+
this.stopPauses = 0;
|
|
5284
5317
|
this.lastProgressAt = this.limits.now();
|
|
5285
5318
|
}
|
|
5286
5319
|
const pending = abandonablePending(error);
|
|
@@ -5313,12 +5346,11 @@ var DriverRetryLoop = class {
|
|
|
5313
5346
|
})();
|
|
5314
5347
|
const unavailableSignal = upstreamUnavailableSignal(error) ?? "unavailable";
|
|
5315
5348
|
if (stop !== void 0) {
|
|
5316
|
-
await this.
|
|
5349
|
+
await this.stopOrPause(error, stop, {
|
|
5317
5350
|
...this.failureRecord(failure),
|
|
5318
|
-
unavailableSignal
|
|
5319
|
-
stop
|
|
5351
|
+
unavailableSignal
|
|
5320
5352
|
});
|
|
5321
|
-
|
|
5353
|
+
return;
|
|
5322
5354
|
}
|
|
5323
5355
|
this.pauses += 1;
|
|
5324
5356
|
this.consecutivePauses = progressed ? 1 : this.consecutivePauses + 1;
|
|
@@ -5357,12 +5389,11 @@ var DriverRetryLoop = class {
|
|
|
5357
5389
|
const retryStop = abandoned ? void 0 : unresolved ? "pending-unresolved" : stop;
|
|
5358
5390
|
if (progressed) this.barrenReentries = 0;
|
|
5359
5391
|
if (retryStop !== void 0) {
|
|
5360
|
-
await this.
|
|
5392
|
+
await this.stopOrPause(error, retryStop, {
|
|
5361
5393
|
...this.failureRecord(failure),
|
|
5362
|
-
stop: retryStop,
|
|
5363
5394
|
...retainedFailure === void 0 ? {} : { pendingCause: retainedFailure.pendingCause }
|
|
5364
5395
|
});
|
|
5365
|
-
|
|
5396
|
+
return;
|
|
5366
5397
|
}
|
|
5367
5398
|
if (!abandoned) this.consecutiveBarren = progressed ? 0 : this.consecutiveBarren + 1;
|
|
5368
5399
|
const backoff = jitteredMs(cappedDoublingMs(this.consecutiveBarren, limits.initialBackoff, limits.maxBackoff), limits.random);
|
|
@@ -5476,9 +5507,7 @@ var DriverRetryLoop = class {
|
|
|
5476
5507
|
if (this.barrenReentries < policy.maxBarren) return void 0;
|
|
5477
5508
|
const { run } = this;
|
|
5478
5509
|
const pausedAt = this.limits.now();
|
|
5479
|
-
const
|
|
5480
|
-
const until = Math.min(policy.deadlineMs ?? Number.POSITIVE_INFINITY, budgetDeadline > 0 ? budgetDeadline : Number.POSITIVE_INFINITY);
|
|
5481
|
-
const pauseMs = Math.max(0, Math.min(barrenPauseMs(this.barrenReentries, policy.maxBarren), until - pausedAt));
|
|
5510
|
+
const pauseMs = Math.max(0, Math.min(barrenPauseMs(this.barrenReentries, policy.maxBarren), this.deadlineAt() - pausedAt));
|
|
5482
5511
|
const pause = {
|
|
5483
5512
|
attempt,
|
|
5484
5513
|
streak: this.barrenReentries,
|
|
@@ -5516,11 +5545,21 @@ var DriverRetryLoop = class {
|
|
|
5516
5545
|
};
|
|
5517
5546
|
if (progressed) {
|
|
5518
5547
|
this.barrenReentries = 0;
|
|
5548
|
+
this.stopPauses = 0;
|
|
5519
5549
|
this.lastProgressAt = this.limits.now();
|
|
5520
5550
|
} else if (!this.beforeModelEvent && this.reentry !== void 0 && this.reentry.reason !== "wake" && contract === "unmet") this.barrenReentries += 1;
|
|
5521
5551
|
if (run.wait !== void 0 && contract !== "met" && await this.wake(attempt, completed)) return true;
|
|
5522
5552
|
if (contract === "unmet" && continuation !== void 0) {
|
|
5523
|
-
|
|
5553
|
+
let decision = await this.decideContinuation(continuation, attempt, after);
|
|
5554
|
+
while ("refusedBy" in decision && decision.refusedBy === "budget-exhausted") {
|
|
5555
|
+
if (!this.pausesStop("budget-exhausted")) break;
|
|
5556
|
+
await this.stopPause(admissionError("budget-exhausted"), "budget-exhausted", {
|
|
5557
|
+
attempt,
|
|
5558
|
+
durationMs,
|
|
5559
|
+
madeProgress: false
|
|
5560
|
+
});
|
|
5561
|
+
decision = await this.decideContinuation(continuation, attempt, after);
|
|
5562
|
+
}
|
|
5524
5563
|
if ("steer" in decision) {
|
|
5525
5564
|
this.continuations += 1;
|
|
5526
5565
|
await this.emit({
|
|
@@ -5582,10 +5621,12 @@ var DriverRetryLoop = class {
|
|
|
5582
5621
|
* backend reattaches the harness session because the execution id is bound durably per node.
|
|
5583
5622
|
*
|
|
5584
5623
|
* Failure classes (all conservative):
|
|
5585
|
-
* - TERMINAL: Runtime's own refusals (`ValidationError`/`ConfigError`, exhausted budget,
|
|
5586
|
-
* client-side transport status such as 401/404/422). Retrying re-runs a decision.
|
|
5624
|
+
* - TERMINAL: Runtime's own refusals (`ValidationError`/`ConfigError`, exhausted budget, the run's
|
|
5625
|
+
* own abort, a client-side transport status such as 401/404/422). Retrying re-runs a decision.
|
|
5626
|
+
* Fails at once.
|
|
5587
5627
|
* - TRANSIENT: everything foreign (harness exit without a reason, a stream cut mid-turn, a 5xx, a
|
|
5588
|
-
* socket reset
|
|
5628
|
+
* socket reset, an `AbortError` that neither the run's signal nor the manager's own stop
|
|
5629
|
+
* issued). A harness turn that RETURNED a failed outcome is the same accident reported as
|
|
5589
5630
|
* a value, so the drive raises {@link HarnessTurnFailedError} and it is classified like any other.
|
|
5590
5631
|
* - UNAVAILABLE: the upstream said "not now" (429, 503, 529, or the router's own codes: quota,
|
|
5591
5632
|
* rate limit, overload). The driver PAUSES and re-enters; a pause consumes neither `maxAttempts`
|
|
@@ -5648,6 +5689,21 @@ var DriverRetryLoop = class {
|
|
|
5648
5689
|
*
|
|
5649
5690
|
* Every wait, a failure backoff or a pause, is jittered over its upper half so drivers that one
|
|
5650
5691
|
* outage cut off together do not re-enter together.
|
|
5692
|
+
*
|
|
5693
|
+
* STOP-PAUSE. A run started with `driverRetry.pauseRootStops` hands its ROOT a `stopPause`;
|
|
5694
|
+
* no other manager gets one. It turns every stop except `completed`, `aborted` and a declared `deadline` into a wait that alarms:
|
|
5695
|
+
* `terminal-error`, `no-progress`, `max-attempts`, `repeated-failure`, `pending-unresolved` and
|
|
5696
|
+
* `budget-exhausted` each emit one record with `replacesStop` and pause 5 minutes, doubling per
|
|
5697
|
+
* stop-pause in a row up to 60, never past a declared deadline and not jittered. An attempt that
|
|
5698
|
+
* made progress resets the streak. A cancel ends the pause and settles the run; a root steer ends
|
|
5699
|
+
* any pause at once, a budget pause included, because a steer is how an operator changes a live
|
|
5700
|
+
* run. Ending a pause admits nothing by itself: the next admission reads the pool again, a pool
|
|
5701
|
+
* still spent pauses again with its own row, and the steer stays queued until a turn reads it.
|
|
5702
|
+
* After the pause the per-window counters start over and the driver is re-entered: after
|
|
5703
|
+
* a failure as `driver-failure` with `pausedMs`, after an admission or continuation refusal as the
|
|
5704
|
+
* re-entry it was about to use. Drew, 2026-10-21: "why do these runs keep failing early its
|
|
5705
|
+
* unacceptable!" Measured 2026-10-21 over 259 runs since 10-14: 8 of the 10 stops settled runs that
|
|
5706
|
+
* nobody solved or stopped, including 17 roots whose harness never streamed.
|
|
5651
5707
|
*/
|
|
5652
5708
|
function assertContinuationPolicy(continuation) {
|
|
5653
5709
|
if (continuation === void 0) return;
|
|
@@ -5664,7 +5720,8 @@ function assertContinuationPolicy(continuation) {
|
|
|
5664
5720
|
* `deadline` when a deadline cut it and `aborted` otherwise, never `terminal-error`. Throws
|
|
5665
5721
|
* `DriverAttemptsExhaustedError` (cause = the last real failure) when a FAILURE ends the loop; a
|
|
5666
5722
|
* completed drive returns, met contract or not, because deciding what an undelivered run is worth
|
|
5667
|
-
* belongs to the finalizer, not to this loop.
|
|
5723
|
+
* belongs to the finalizer, not to this loop. With `stopPause`, every stop but `completed`,
|
|
5724
|
+
* `aborted` and a declared `deadline` pauses instead (STOP-PAUSE in the header).
|
|
5668
5725
|
*/
|
|
5669
5726
|
async function runDriverWithRetry(run) {
|
|
5670
5727
|
const limits = driverRetryLimits(run);
|
|
@@ -5674,7 +5731,13 @@ async function runDriverWithRetry(run) {
|
|
|
5674
5731
|
const before = run.progress();
|
|
5675
5732
|
const startedAt = limits.now();
|
|
5676
5733
|
loop.beforeModelEvent = run.reentered !== void 0 && run.reentered.modelEvents() === 0;
|
|
5677
|
-
|
|
5734
|
+
const admission = loop.admission();
|
|
5735
|
+
if (admission === "refused") return;
|
|
5736
|
+
if (admission !== void 0) {
|
|
5737
|
+
await loop.pauseAdmission(admission, attempt);
|
|
5738
|
+
attempt -= 1;
|
|
5739
|
+
continue;
|
|
5740
|
+
}
|
|
5678
5741
|
try {
|
|
5679
5742
|
await run.drive(attempt, loop.reentry);
|
|
5680
5743
|
} catch (error) {
|
|
@@ -5996,7 +6059,8 @@ async function driveManagerTurns(inputs) {
|
|
|
5996
6059
|
workspaceRestores: 0,
|
|
5997
6060
|
describe: deps.deliverable?.describe,
|
|
5998
6061
|
continuationSession: deps.continuation?.session,
|
|
5999
|
-
modelEvents: 0
|
|
6062
|
+
modelEvents: 0,
|
|
6063
|
+
reported: false
|
|
6000
6064
|
};
|
|
6001
6065
|
const { mcp } = session;
|
|
6002
6066
|
const keeper = session.state.keeper;
|
|
@@ -6016,6 +6080,8 @@ async function driveManagerTurns(inputs) {
|
|
|
6016
6080
|
progress: () => readManagerProgress(loop),
|
|
6017
6081
|
budget: () => scope.budget,
|
|
6018
6082
|
signal: scope.signal,
|
|
6083
|
+
stopSignal: session.state.stopController.signal,
|
|
6084
|
+
...rootStopPause(config, session),
|
|
6019
6085
|
resolvePending: (failure, failures) => abandonScopeRetainedOwnerInvocation(scope, failure, failures),
|
|
6020
6086
|
wait: {
|
|
6021
6087
|
open: () => !mcp.submittedResult() && !mcp.isStopped() && session.state.progressStopReason === void 0 && (session.controls.hasOpenWork() || session.state.nextTurnInbox.pendingAuthority() > 0),
|
|
@@ -6034,10 +6100,49 @@ async function driveManagerTurns(inputs) {
|
|
|
6034
6100
|
driverFailed = false;
|
|
6035
6101
|
} finally {
|
|
6036
6102
|
await driveHarness.closeSeatSegment?.(scope.signal.aborted ? "cancelled" : driverFailed ? "failed" : "completed");
|
|
6037
|
-
reportManagerLoop(loop);
|
|
6103
|
+
if (!loop.reported) reportManagerLoop(loop);
|
|
6038
6104
|
}
|
|
6039
6105
|
return loop.candidate;
|
|
6040
6106
|
}
|
|
6107
|
+
/**
|
|
6108
|
+
* The stop-pause of an opted-in ROOT (`SupervisorAgentDeps.pauseRootStops`, which `supervise()`
|
|
6109
|
+
* sets on the root's deps alone); a nested manager keeps its stops and settles `down` for its
|
|
6110
|
+
* parent. A root steer between turns reaches the coordinator as a lead message, and one an ended
|
|
6111
|
+
* invocation still held waits in `nextTurnInbox`. Either ends a pause once and stays queued for
|
|
6112
|
+
* the next turn: a steer that turn never read, or a pool still spent, would otherwise end every
|
|
6113
|
+
* later pause at once.
|
|
6114
|
+
*/
|
|
6115
|
+
function rootStopPause(config, session) {
|
|
6116
|
+
if (config.deps.pauseRootStops !== true) return {};
|
|
6117
|
+
const { controls } = session;
|
|
6118
|
+
const { nextTurnInbox } = session.state;
|
|
6119
|
+
let answeredLead = /* @__PURE__ */ new Set();
|
|
6120
|
+
let answeredInbox = 0;
|
|
6121
|
+
const unanswered = () => controls.queuedLeadMessages().some((seq) => !answeredLead.has(seq)) || nextTurnInbox.pendingAuthority() > answeredInbox;
|
|
6122
|
+
return { stopPause: { steered: async (signal) => {
|
|
6123
|
+
answeredInbox = Math.min(answeredInbox, nextTurnInbox.pendingAuthority());
|
|
6124
|
+
if (!unanswered()) {
|
|
6125
|
+
const listening = new AbortController();
|
|
6126
|
+
const until = AbortSignal.any([signal, listening.signal]);
|
|
6127
|
+
try {
|
|
6128
|
+
await Promise.race([controls.awaitLeadMessage(until), (async () => {
|
|
6129
|
+
while (!until.aborted && !unanswered()) await Promise.race([nextTurnInbox.nextDelivery(), abortedSignal(until)]);
|
|
6130
|
+
})()]);
|
|
6131
|
+
} finally {
|
|
6132
|
+
listening.abort();
|
|
6133
|
+
}
|
|
6134
|
+
}
|
|
6135
|
+
if (signal.aborted || !unanswered()) return;
|
|
6136
|
+
answeredLead = new Set(controls.queuedLeadMessages());
|
|
6137
|
+
answeredInbox = nextTurnInbox.pendingAuthority();
|
|
6138
|
+
} } };
|
|
6139
|
+
}
|
|
6140
|
+
function abortedSignal(signal) {
|
|
6141
|
+
return new Promise((resolve) => {
|
|
6142
|
+
if (signal.aborted) resolve();
|
|
6143
|
+
else signal.addEventListener("abort", () => resolve(), { once: true });
|
|
6144
|
+
});
|
|
6145
|
+
}
|
|
6041
6146
|
function createManagerKeeper(config, session, deliverable, continuation) {
|
|
6042
6147
|
const { deps, runtimeToolNames } = config;
|
|
6043
6148
|
const { mcp, controls } = session;
|
|
@@ -6116,6 +6221,7 @@ async function readCheckAtTurnEnd(loop, attempt) {
|
|
|
6116
6221
|
if (last?.unavailable !== void 0) throw new CheckUnavailableError(`the completion check could not run: ${last.unavailable}`);
|
|
6117
6222
|
}
|
|
6118
6223
|
function reportManagerLoop(loop) {
|
|
6224
|
+
loop.reported = true;
|
|
6119
6225
|
const { mcp, controls, state } = loop.session;
|
|
6120
6226
|
const stopReason = controls.stopReason() ?? state.progressStopReason;
|
|
6121
6227
|
const closedBy = mcp.submittedResult() ? "result-accepted" : mcp.isStopped() ? "stop" : state.progressStopReason !== void 0 ? "stop-rule" : void 0;
|
|
@@ -6275,8 +6381,20 @@ async function wakeManager(loop, nextAttempt) {
|
|
|
6275
6381
|
async function recordManagerAttempt(loop, record) {
|
|
6276
6382
|
const { scope } = loop.session.state;
|
|
6277
6383
|
loop.records.push(record);
|
|
6384
|
+
if (record.stop !== void 0) reportManagerLoop(loop);
|
|
6278
6385
|
await recordScopeOwnerDriverAttempt(scope, record);
|
|
6279
|
-
if (record.
|
|
6386
|
+
if (record.replacesStop !== void 0 && record.retryInMs !== void 0 && record.stopPauseStreak !== void 0 && record.resumeAt !== void 0) await recordScopeOwnerPause(scope, {
|
|
6387
|
+
attempt: record.attempt,
|
|
6388
|
+
signal: record.replacesStop,
|
|
6389
|
+
cause: record.error ?? record.replacesStop,
|
|
6390
|
+
attemptMs: record.durationMs,
|
|
6391
|
+
pauseMs: record.retryInMs,
|
|
6392
|
+
madeProgress: record.madeProgress,
|
|
6393
|
+
replacesStop: record.replacesStop,
|
|
6394
|
+
streak: record.stopPauseStreak,
|
|
6395
|
+
resumeAt: record.resumeAt
|
|
6396
|
+
});
|
|
6397
|
+
else if (record.classification === "unavailable" && record.retryInMs !== void 0) await recordScopeOwnerPause(scope, {
|
|
6280
6398
|
attempt: record.attempt,
|
|
6281
6399
|
signal: record.unavailableSignal ?? "unavailable",
|
|
6282
6400
|
cause: record.error ?? "",
|
|
@@ -7217,6 +7335,194 @@ function admitSpawn(env, seat, authoredProfile, spawnContext, recovering) {
|
|
|
7217
7335
|
};
|
|
7218
7336
|
}
|
|
7219
7337
|
//#endregion
|
|
7338
|
+
//#region src/runtime/supervise/graph-registry.ts
|
|
7339
|
+
/**
|
|
7340
|
+
* `graph-registry` — the designer's memory: graphs and their outcomes as files.
|
|
7341
|
+
*
|
|
7342
|
+
* The AgentGraph algebra makes a graph PLAIN DATA (nodes with pinned profiles,
|
|
7343
|
+
* edges with registry-versioned directives, a budget, a deliverable
|
|
7344
|
+
* description), which is the property that lets a graph be stored, replayed
|
|
7345
|
+
* byte-identical, and mutated like code. This module is the thin durable layer
|
|
7346
|
+
* on top: one JSONL record per run, the exact graph content-addressed beside
|
|
7347
|
+
* it. The natural home is a SANDBOX WORKSPACE — the platform's snapshot story
|
|
7348
|
+
* (Firecracker restore, warm leases, `continuity: 'resume'`) then makes the
|
|
7349
|
+
* registry the agent's compounding execution memory across runs: a rerun over
|
|
7350
|
+
* the same sandbox finds every graph the designer ever ran, what each cost,
|
|
7351
|
+
* and whether it delivered.
|
|
7352
|
+
*
|
|
7353
|
+
* ORACLES STAY ENVIRONMENT-OWNED. `DeliverableSpec.check` is a function and is
|
|
7354
|
+
* deliberately NOT stored: a stored graph keeps the deliverable's `describe`
|
|
7355
|
+
* and an optional `checkRef`, and replay re-binds the check from the caller's
|
|
7356
|
+
* environment. This is the graph contract's own doctrine — graders are
|
|
7357
|
+
* environment, never workers — applied to persistence.
|
|
7358
|
+
*
|
|
7359
|
+
* Scoring is a documented heuristic, not a learned model: delivered beats
|
|
7360
|
+
* failed, then cheaper (tokens, then iterations), then most recent. A designer
|
|
7361
|
+
* that needs better selection replaces `pickBest`, not the records.
|
|
7362
|
+
*/
|
|
7363
|
+
var graph_registry_exports = /* @__PURE__ */ __exportAll({
|
|
7364
|
+
digestOfGraph: () => digestOfGraph,
|
|
7365
|
+
graphDigest: () => graphDigest,
|
|
7366
|
+
graphFromStored: () => graphFromStored,
|
|
7367
|
+
graphRegistry: () => graphRegistry,
|
|
7368
|
+
graphRunsFor: () => graphRunsFor,
|
|
7369
|
+
listGraphRuns: () => listGraphRuns,
|
|
7370
|
+
loadGraph: () => loadGraph,
|
|
7371
|
+
lookupGraph: () => lookupGraph,
|
|
7372
|
+
pickBestGraph: () => pickBestGraph,
|
|
7373
|
+
recordGraphRun: () => recordGraphRun,
|
|
7374
|
+
storedGraphDigests: () => storedGraphDigests,
|
|
7375
|
+
taskShapeDigest: () => taskShapeDigest
|
|
7376
|
+
});
|
|
7377
|
+
const RECORDS_FILE = "records.jsonl";
|
|
7378
|
+
const GRAPHS_DIR = "graphs";
|
|
7379
|
+
/** Canonical serialization for content-addressing: stable key order, sorted. */
|
|
7380
|
+
function canonicalJson$1(value) {
|
|
7381
|
+
if (Array.isArray(value)) return `[${value.map(canonicalJson$1).join(",")}]`;
|
|
7382
|
+
if (value && typeof value === "object") return `{${Object.entries(value).filter(([, v]) => v !== void 0).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([k, v]) => `${JSON.stringify(k)}:${canonicalJson$1(v)}`).join(",")}}`;
|
|
7383
|
+
return JSON.stringify(value);
|
|
7384
|
+
}
|
|
7385
|
+
/** Digest of the exact graph (nodes + edges + budget + deliverable describe, and a flow graph's
|
|
7386
|
+
* entry and gates). An absent key is not serialized, so a graph without `entry` keeps the digest
|
|
7387
|
+
* it had before flow graphs were stored. */
|
|
7388
|
+
function graphDigest(graph) {
|
|
7389
|
+
return sha256(canonicalJson$1(graph));
|
|
7390
|
+
}
|
|
7391
|
+
/** Digest of the normalized task shape a designer looks records up by. */
|
|
7392
|
+
function taskShapeDigest(taskShape) {
|
|
7393
|
+
return sha256(canonicalJson$1(taskShape));
|
|
7394
|
+
}
|
|
7395
|
+
/** Digest of a runnable graph exactly as the registry stores it — the value
|
|
7396
|
+
* `recordGraphRun` demands. Callers recording real runs hash through this,
|
|
7397
|
+
* never hand-rolled, so a record always matches its graph. */
|
|
7398
|
+
function digestOfGraph(graph) {
|
|
7399
|
+
return storeGraph(graph).digest;
|
|
7400
|
+
}
|
|
7401
|
+
function storeGraph(graph) {
|
|
7402
|
+
const content = {
|
|
7403
|
+
nodes: graph.nodes,
|
|
7404
|
+
edges: graph.edges,
|
|
7405
|
+
budget: graph.budget,
|
|
7406
|
+
deliverable: { ...graph.deliverable.describe ? { describe: graph.deliverable.describe } : {} },
|
|
7407
|
+
...graph.entry === void 0 ? {} : { entry: graph.entry },
|
|
7408
|
+
...graph.gates === void 0 ? {} : { gates: graph.gates }
|
|
7409
|
+
};
|
|
7410
|
+
return {
|
|
7411
|
+
digest: graphDigest(content),
|
|
7412
|
+
...content
|
|
7413
|
+
};
|
|
7414
|
+
}
|
|
7415
|
+
function assertRecord(record) {
|
|
7416
|
+
if (typeof record.graphDigest !== "string" || record.graphDigest.length === 0) throw new ValidationError("graph-registry: record.graphDigest is required");
|
|
7417
|
+
if (typeof record.taskDigest !== "string" || record.taskDigest.length === 0) throw new ValidationError("graph-registry: record.taskDigest is required");
|
|
7418
|
+
if (record.outcome.kind !== "delivered" && record.outcome.kind !== "no-winner") throw new ValidationError("graph-registry: record.outcome.kind must be 'delivered' | 'no-winner'");
|
|
7419
|
+
}
|
|
7420
|
+
function recordKey(record) {
|
|
7421
|
+
assertRecord(record);
|
|
7422
|
+
return JSON.stringify([
|
|
7423
|
+
record.taskDigest,
|
|
7424
|
+
record.graphDigest,
|
|
7425
|
+
record.startedAt
|
|
7426
|
+
]);
|
|
7427
|
+
}
|
|
7428
|
+
/** Open (or lazily create) a registry rooted at a workspace directory. The
|
|
7429
|
+
* directory is the sandbox workspace; snapshots carry it across runs. */
|
|
7430
|
+
function graphRegistry(root) {
|
|
7431
|
+
if (!root || root.trim().length === 0) throw new ValidationError("graphRegistry: root directory is required");
|
|
7432
|
+
return { root };
|
|
7433
|
+
}
|
|
7434
|
+
/** Append one run record; the exact graph is content-addressed beside it.
|
|
7435
|
+
* Idempotent per (taskDigest, graphDigest, startedAt): a replayed append with
|
|
7436
|
+
* the same key replaces the prior row rather than duplicating it. */
|
|
7437
|
+
async function recordGraphRun(reg, graph, record) {
|
|
7438
|
+
assertRecord(record);
|
|
7439
|
+
const stored = storeGraph(graph);
|
|
7440
|
+
if (stored.digest !== record.graphDigest) throw new ValidationError(`graph-registry: record.graphDigest ${record.graphDigest} does not match the supplied graph (${stored.digest}) — record the graph that actually ran`);
|
|
7441
|
+
await mkdir(join(reg.root, GRAPHS_DIR), { recursive: true });
|
|
7442
|
+
return withJsonlFileLock(join(reg.root, RECORDS_FILE), async (canonicalPath) => {
|
|
7443
|
+
writeAtomicDurableFile(join(reg.root, GRAPHS_DIR, `${stored.digest}.json`), JSON.stringify(stored), { preserveMode: true });
|
|
7444
|
+
await upsertCommittedJsonLine(canonicalPath, record, recordKey);
|
|
7445
|
+
return stored;
|
|
7446
|
+
});
|
|
7447
|
+
}
|
|
7448
|
+
/** All records, newest last. */
|
|
7449
|
+
async function listGraphRuns(reg) {
|
|
7450
|
+
return readCommittedJsonFile(join(reg.root, RECORDS_FILE));
|
|
7451
|
+
}
|
|
7452
|
+
/** Records for one task shape, newest last. */
|
|
7453
|
+
async function graphRunsFor(reg, taskDigest) {
|
|
7454
|
+
return (await listGraphRuns(reg)).filter((row) => row.taskDigest === taskDigest);
|
|
7455
|
+
}
|
|
7456
|
+
/** The documented heuristic: delivered beats failed; among delivered, cheaper
|
|
7457
|
+
* (tokens, then iterations) wins; ties go to the most recent. */
|
|
7458
|
+
function pickBestGraph(records) {
|
|
7459
|
+
const delivered = records.filter((row) => row.outcome.kind === "delivered");
|
|
7460
|
+
if (delivered.length === 0) return void 0;
|
|
7461
|
+
const better = (a, b) => {
|
|
7462
|
+
const aTokens = a.cost.tokens ?? Number.POSITIVE_INFINITY;
|
|
7463
|
+
const bTokens = b.cost.tokens ?? Number.POSITIVE_INFINITY;
|
|
7464
|
+
if (aTokens !== bTokens) return aTokens < bTokens ? a : b;
|
|
7465
|
+
const aIter = a.cost.iterations ?? Number.POSITIVE_INFINITY;
|
|
7466
|
+
const bIter = b.cost.iterations ?? Number.POSITIVE_INFINITY;
|
|
7467
|
+
if (aIter !== bIter) return aIter < bIter ? a : b;
|
|
7468
|
+
return a.finishedAt >= b.finishedAt ? a : b;
|
|
7469
|
+
};
|
|
7470
|
+
return delivered.reduce((best, row) => better(best, row) === best ? best : row);
|
|
7471
|
+
}
|
|
7472
|
+
/** Load a stored graph by digest. */
|
|
7473
|
+
async function loadGraph(reg, digest) {
|
|
7474
|
+
try {
|
|
7475
|
+
return JSON.parse(await readFile(join(reg.root, GRAPHS_DIR, `${digest}.json`), "utf8"));
|
|
7476
|
+
} catch {
|
|
7477
|
+
return;
|
|
7478
|
+
}
|
|
7479
|
+
}
|
|
7480
|
+
/** The designer's lookup: replay the known-good graph for this task shape, or
|
|
7481
|
+
* author a new one — with the reason stated either way (the decision is data). */
|
|
7482
|
+
async function lookupGraph(reg, taskDigest) {
|
|
7483
|
+
const records = await graphRunsFor(reg, taskDigest);
|
|
7484
|
+
const best = pickBestGraph(records);
|
|
7485
|
+
if (best) {
|
|
7486
|
+
const graph = await loadGraph(reg, best.graphDigest);
|
|
7487
|
+
if (graph) return {
|
|
7488
|
+
kind: "replay",
|
|
7489
|
+
graph,
|
|
7490
|
+
record: best
|
|
7491
|
+
};
|
|
7492
|
+
return {
|
|
7493
|
+
kind: "author",
|
|
7494
|
+
reason: `best record's graph ${best.graphDigest.slice(0, 12)} is missing from the registry`
|
|
7495
|
+
};
|
|
7496
|
+
}
|
|
7497
|
+
return {
|
|
7498
|
+
kind: "author",
|
|
7499
|
+
reason: records.length === 0 ? "first run for this task shape" : "no graph delivered for this task shape yet"
|
|
7500
|
+
};
|
|
7501
|
+
}
|
|
7502
|
+
/** Rehydrate a stored graph into a runnable one. The check comes from the
|
|
7503
|
+
* CALLER's environment (oracles are environment, never stored). */
|
|
7504
|
+
function graphFromStored(stored, check) {
|
|
7505
|
+
return {
|
|
7506
|
+
nodes: stored.nodes,
|
|
7507
|
+
edges: stored.edges,
|
|
7508
|
+
budget: stored.budget,
|
|
7509
|
+
deliverable: {
|
|
7510
|
+
check,
|
|
7511
|
+
...stored.deliverable.describe ? { describe: stored.deliverable.describe } : {}
|
|
7512
|
+
},
|
|
7513
|
+
...stored.entry === void 0 ? {} : { entry: stored.entry },
|
|
7514
|
+
...stored.gates === void 0 ? {} : { gates: stored.gates }
|
|
7515
|
+
};
|
|
7516
|
+
}
|
|
7517
|
+
/** Digests present on disk (integrity probe for tests and audits). */
|
|
7518
|
+
async function storedGraphDigests(reg) {
|
|
7519
|
+
try {
|
|
7520
|
+
return (await readdir(join(reg.root, GRAPHS_DIR))).filter((name) => name.endsWith(".json")).map((name) => name.slice(0, -5)).sort();
|
|
7521
|
+
} catch {
|
|
7522
|
+
return [];
|
|
7523
|
+
}
|
|
7524
|
+
}
|
|
7525
|
+
//#endregion
|
|
7220
7526
|
//#region src/runtime/supervise/supervise-graph-subtasks.ts
|
|
7221
7527
|
/** A stored graph's topology, from the registry `SuperviseOptions.graphRegistry` names. */
|
|
7222
7528
|
async function storedGraphTopology(dir, digest) {
|
|
@@ -9180,7 +9486,7 @@ function superviseInternal(profile, task, opts, testBrain) {
|
|
|
9180
9486
|
const workers = createSuperviseWorkers(setup, (reason, request) => cancelDurableRun(reason, request));
|
|
9181
9487
|
const durableCancellation = new AbortController();
|
|
9182
9488
|
const cancelDurableRun = (reason, request) => {
|
|
9183
|
-
durableCancellation.abort(request === void 0 ? new Error(reason) : new RunCancellationReason(request.source, reason, request.operationId));
|
|
9489
|
+
durableCancellation.abort(request === void 0 ? new Error(reason) : new RunCancellationReason(request.source, reason, request.operationId, request.operator));
|
|
9184
9490
|
};
|
|
9185
9491
|
return startSupervisedRun({
|
|
9186
9492
|
setup,
|
|
@@ -9279,6 +9585,7 @@ function rootSupervisorAgent(run, priorCoordination, runDir) {
|
|
|
9279
9585
|
...options.decideGate ? { decideGate: options.decideGate } : {},
|
|
9280
9586
|
...options.continuityByProfile ? { continuityByProfile: options.continuityByProfile } : {},
|
|
9281
9587
|
...supervisorTurnOptions(options),
|
|
9588
|
+
...options.driverRetry?.pauseRootStops === true ? { pauseRootStops: true } : {},
|
|
9282
9589
|
...deliverable && options.continuation && setup.externalRoot ? {
|
|
9283
9590
|
continuation: options.continuation,
|
|
9284
9591
|
...runDir === void 0 ? {} : {
|
|
@@ -9418,6 +9725,7 @@ function superviseWithTestBrain(profile, task, opts) {
|
|
|
9418
9725
|
return superviseWithContext(profile, task, runtimeOptions, brain);
|
|
9419
9726
|
}
|
|
9420
9727
|
function superviseWithContext(profile, task, opts, brain) {
|
|
9728
|
+
if (opts.driverRetry?.pauseRootStops === true && opts.driverRetry.enabled === false) throw new ValidationError("supervise: driverRetry.pauseRootStops pauses where a retry would stop; it cannot be combined with driverRetry.enabled: false");
|
|
9421
9729
|
if (opts.runContext?.acquire === void 0) return superviseInternal(profile, task, opts, brain);
|
|
9422
9730
|
const options = captureSuperviseOptions(opts);
|
|
9423
9731
|
const capturedProfile = freezeDetached(profile);
|
|
@@ -9429,6 +9737,6 @@ function superviseWithContext(profile, task, opts, brain) {
|
|
|
9429
9737
|
}, brain));
|
|
9430
9738
|
}
|
|
9431
9739
|
//#endregion
|
|
9432
|
-
export {
|
|
9740
|
+
export { noProgressFor as $, runBrainLoop as A, graphRootProfile as B, workerFromBackend as C, composeReentryTask as D, UNPROVEN_CONTINUITY as E, flowRootProfile as F, dumbContinuationFailPrompt as G, analyzesFindingsReportPrompt as H, journaledGateDecider as I, kernelPromptRegistry as J, dumbContinuationPassPrompt as K, routeFlowOf as L, createGraphOverlay as M, GraphRouteError as N, serveCoordinationMcp as O, createFlowRun as P, anyOf as Q, validateFlowGraph as R, taskShapeDigest as S, supervisorAgentWithTestBrain as T, createPromptRegistry as U, validateGraphTopology as V, delegatesWorkerBriefPrompt as W, promptHandle as X, naiveContinuationPrompt as Y, allWorkersStalled as Z, loadGraph as _, superviseRootProfile as a, renderAnytimeTable as at, recordGraphRun as b, retryPreSpawnRefusals as c, createSupervisorSpanRecorder as ct, graphDigest as d, plateau as et, graphFromStored as f, listGraphRuns as g, graph_registry_exports as h, profileGuidanceComposer as i, plateauLength as it, runtimeFlowBrain as j, driverAgent as k, withWorkerSpawnRetry as l, graphRunsFor as m, superviseFleetCapabilities as n, areaUnderCurve as nt, isPreSpawnExecutorFailure as o, readRootStream as ot, graphRegistry as p, formatPromptHandle as q, superviseWithTestBrain as r, bestSoFar as rt, resolveWorkerSpawnRetry as s, readRootStreamReceipt as st, supervise as t, anytimeReport as tt, digestOfGraph as u, lookupGraph as v, supervisorAgent as w, storedGraphDigests as x, pickBestGraph as y, defaultEdgeTraversalCap as z };
|
|
9433
9741
|
|
|
9434
|
-
//# sourceMappingURL=supervise-
|
|
9742
|
+
//# sourceMappingURL=supervise-DyCUu8Io.js.map
|