@tangle-network/agent-runtime 0.143.0 → 0.153.1
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/README.md +32 -0
- package/dist/{activation-mi8TgSLM.js → activation-DKxQsHiO.js} +3 -3
- package/dist/{activation-mi8TgSLM.js.map → activation-DKxQsHiO.js.map} +1 -1
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +3 -3
- package/dist/{analyst-loop-CvkmfhUB.js → analyst-loop-B2kTHKNh.js} +2 -2
- package/dist/{analyst-loop-CvkmfhUB.js.map → analyst-loop-B2kTHKNh.js.map} +1 -1
- package/dist/analyst-loop.js +1 -1
- package/dist/{authoring-DuyShLdw.js → authoring-Tk2xFys0.js} +2 -2
- package/dist/{authoring-DuyShLdw.js.map → authoring-Tk2xFys0.js.map} +1 -1
- package/dist/candidate-execution/index.js +4 -4
- package/dist/{candidate-execution-CD5PoNmC.js → candidate-execution-CB9RJbbJ.js} +4 -4
- package/dist/{candidate-execution-CD5PoNmC.js.map → candidate-execution-CB9RJbbJ.js.map} +1 -1
- package/dist/{conversation-1hNtDeMM.js → conversation-D64WyWrK.js} +4 -4
- package/dist/{conversation-1hNtDeMM.js.map → conversation-D64WyWrK.js.map} +1 -1
- package/dist/conversation.d.ts +1 -1
- package/dist/conversation.js +1 -1
- package/dist/durable.d.ts +102 -4
- package/dist/durable.js +259 -10
- package/dist/durable.js.map +1 -1
- package/dist/{environment-provider-B8eZ85Ga.d.ts → environment-provider-DJG0yIYl.d.ts} +2 -2
- package/dist/{environment-provider-DCBJ13VP.js → environment-provider-D_MXw3jK.js} +88 -9
- package/dist/environment-provider-D_MXw3jK.js.map +1 -0
- package/dist/environment-provider.d.ts +1 -1
- package/dist/environment-provider.js +1 -1
- package/dist/executable-spec-BUcUcEPk.js +73 -0
- package/dist/executable-spec-BUcUcEPk.js.map +1 -0
- package/dist/{graph-De_XEsfH.js → graph-M0Qr4863.js} +4 -4
- package/dist/{graph-De_XEsfH.js.map → graph-M0Qr4863.js.map} +1 -1
- package/dist/{improvement-cycle-Bi-Tf4QF.js → improvement-cycle-CDxlGQGE.js} +7 -7
- package/dist/{improvement-cycle-Bi-Tf4QF.js.map → improvement-cycle-CDxlGQGE.js.map} +1 -1
- package/dist/{index-B8rKtH3U.d.ts → index-BihHgUAI.d.ts} +4 -4
- package/dist/{index-C2caGomG.d.ts → index-Dlz7ejRx.d.ts} +339 -503
- package/dist/{index-D4sLkOPY.d.ts → index-LQfgFJoX.d.ts} +2 -2
- package/dist/index.d.ts +7 -7
- package/dist/index.js +13 -13
- package/dist/intelligence.d.ts +4 -4
- package/dist/intelligence.js +6 -6
- package/dist/kernel.d.ts +6 -6
- package/dist/kernel.js +13 -13
- package/dist/{knowledge-CVE6Wk1i.js → knowledge-DM-i40b9.js} +10 -7
- package/dist/{knowledge-CVE6Wk1i.js.map → knowledge-DM-i40b9.js.map} +1 -1
- package/dist/knowledge.d.ts +1 -1
- package/dist/knowledge.js +1 -1
- package/dist/{loop-runner-bin-BoHdQqLm.d.ts → loop-runner-bin-D-BW51yr.d.ts} +3 -3
- package/dist/{loop-runner-bin-DdaI1nLL.js → loop-runner-bin-pD5WJuqJ.js} +4 -4
- package/dist/{loop-runner-bin-DdaI1nLL.js.map → loop-runner-bin-pD5WJuqJ.js.map} +1 -1
- package/dist/loop-runner-bin.d.ts +1 -1
- package/dist/loop-runner-bin.js +1 -1
- package/dist/{materialization-P86EciBw.js → materialization-Bo6j3Hg9.js} +257 -61
- package/dist/materialization-Bo6j3Hg9.js.map +1 -0
- package/dist/mcp/bin.js +3 -3
- package/dist/mcp/index.d.ts +3 -3
- package/dist/mcp/index.js +6 -6
- package/dist/{model-policy-DgRJIJse.js → model-policy-Sw4ywhtL.js} +68 -6
- package/dist/model-policy-Sw4ywhtL.js.map +1 -0
- package/dist/{openai-tools-BiAWKjh6.js → openai-tools-CWBywy-e.js} +2 -2
- package/dist/{openai-tools-BiAWKjh6.js.map → openai-tools-CWBywy-e.js.map} +1 -1
- package/dist/{prepare-D3n7cA39.js → prepare-C3eFd3UA.js} +2 -2
- package/dist/{prepare-D3n7cA39.js.map → prepare-C3eFd3UA.js.map} +1 -1
- package/dist/primeintellect/index.d.ts +1 -1
- package/dist/profiles.js +1 -1
- package/dist/{protected-model-port-bq6bD9YX.js → protected-model-port-Dn2b6peS.js} +2 -2
- package/dist/{protected-model-port-bq6bD9YX.js.map → protected-model-port-Dn2b6peS.js.map} +1 -1
- package/dist/{redact-DexTuAiX.d.ts → redact-NAptmqKw.d.ts} +3 -3
- package/dist/{researcher-CiSY6Wzb.js → researcher-BMFFPwKb.js} +2 -2
- package/dist/{researcher-CiSY6Wzb.js.map → researcher-BMFFPwKb.js.map} +1 -1
- package/dist/{run-layout-Be_Z0dF8.js → run-layout-C2jgwsCq.js} +111 -6
- package/dist/run-layout-C2jgwsCq.js.map +1 -0
- package/dist/{runtime-J6Toky8K.d.ts → runtime-B-5dp5Iz.d.ts} +214 -14
- package/dist/{runtime-BnqjbOGX.js → runtime-RY_rvv7t.js} +85 -82
- package/dist/runtime-RY_rvv7t.js.map +1 -0
- package/dist/{sandbox-events-COwCWUVB.js → sandbox-events-DMijDq2p.js} +49 -2
- package/dist/sandbox-events-DMijDq2p.js.map +1 -0
- package/dist/{spawn-journal-D2HKUImC.js → spawn-journal-CLguaA2A.js} +8 -43
- package/dist/spawn-journal-CLguaA2A.js.map +1 -0
- package/dist/{stream-agent-turn-C1Vs_3B9.d.ts → stream-agent-turn-BGyszuPH.d.ts} +2 -2
- package/dist/{stream-agent-turn-CXRugSGO.js → stream-agent-turn-D6HoaRPV.js} +90 -14
- package/dist/stream-agent-turn-D6HoaRPV.js.map +1 -0
- package/dist/{structural-rollout-CJgj9YXH.js → structural-rollout-P1YxFRfl.js} +11 -8
- package/dist/structural-rollout-P1YxFRfl.js.map +1 -0
- package/dist/{supervise-hCgG6ROJ.js → supervise-BezbzKiJ.js} +1550 -1186
- package/dist/supervise-BezbzKiJ.js.map +1 -0
- package/dist/{supervisor-s8SfZYbW.js → supervisor-DBVlPONC.js} +597 -194
- package/dist/supervisor-DBVlPONC.js.map +1 -0
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +12 -12
- package/dist/{top-app-BMOSKK06.js → top-app-tKo9OrON.js} +189 -86
- package/dist/top-app-tKo9OrON.js.map +1 -0
- package/dist/tui/bin.js +1 -1
- package/dist/tui/index.d.ts +32 -4
- package/dist/tui/index.js +1 -1
- package/dist/{types-Df9vulGc.d.ts → types-BPQhQRrC.d.ts} +507 -10
- package/dist/{util-C1bv6yog.js → util-Bncw0o_F.js} +41 -2
- package/dist/util-Bncw0o_F.js.map +1 -0
- package/dist/{workspace-archive-C52LjkeN.js → workspace-archive-Dm73lTfB.js} +2 -2
- package/dist/{workspace-archive-C52LjkeN.js.map → workspace-archive-Dm73lTfB.js.map} +1 -1
- package/package.json +4 -4
- package/dist/environment-provider-DCBJ13VP.js.map +0 -1
- package/dist/materialization-P86EciBw.js.map +0 -1
- package/dist/model-policy-DgRJIJse.js.map +0 -1
- package/dist/retained-run-binding-Dp2e8xne.js +0 -268
- package/dist/retained-run-binding-Dp2e8xne.js.map +0 -1
- package/dist/run-layout-Be_Z0dF8.js.map +0 -1
- package/dist/runtime-BnqjbOGX.js.map +0 -1
- package/dist/sandbox-events-COwCWUVB.js.map +0 -1
- package/dist/spawn-journal-D2HKUImC.js.map +0 -1
- package/dist/stream-agent-turn-CXRugSGO.js.map +0 -1
- package/dist/structural-rollout-CJgj9YXH.js.map +0 -1
- package/dist/supervise-hCgG6ROJ.js.map +0 -1
- package/dist/supervisor-s8SfZYbW.js.map +0 -1
- package/dist/top-app-BMOSKK06.js.map +0 -1
- package/dist/util-C1bv6yog.js.map +0 -1
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import { C as unknownExecutionBindingReceipt, S as runtimeOwnedScopeOwnerRuntime, a as authoredProfileDigest, b as runtimeOwnedExecutorProviderEvidence, c as knownExecutionBindingReceipt, f as recordRuntimeOwnedProviderAttemptStart, g as runtimeOwnedDeferredExecutorRuntime, h as recordRuntimeOwnedProviderModel, l as knownMaterializationReceipt, m as recordRuntimeOwnedProviderIdentityConflict, n as attestRuntimeOwnedExecutor, o as finalizeRuntimeOwnedPendingExecutor, p as recordRuntimeOwnedProviderDispatchNotStarted, r as attestRuntimeOwnedPendingExecutor, s as inheritRuntimeOwnedExecutorAttestation, t as attestRuntimeOwnedDeferredExecutor, u as newExecutionAttemptId, v as runtimeOwnedExecutorExecutionBinding, w as unknownMaterializationReceipt, x as runtimeOwnedPendingExecutorMaterialization, y as runtimeOwnedExecutorMaterialization } from "./materialization-Bo6j3Hg9.js";
|
|
1
2
|
import { f as RuntimeRunStateError, m as ValidationError, r as BackendTransportError } from "./errors-CDZ8XsVj.js";
|
|
2
3
|
import { t as detachedSnapshot } from "./snapshot-cK9K420n.js";
|
|
3
|
-
import { S as contentAddress, a as aggregateProviderModelEvidence, c as pendingWaits, g as runtimeOwnedNestedDriverTreeRoot, h as nestedDriverTreeRoot, l as replaySpawnTree, m as driverRuntime, o as loadSpawnForest, p as attestNestedDriverTreeOwner, s as materializeTreeView, v as captureWorkerTraceEvidence } from "./spawn-journal-
|
|
4
|
-
import { _ as
|
|
5
|
-
import { i as extractLlmCallEvent, o as mapSandboxToolEvent, r as createSandboxToolPartState, s as notifySandboxEventObserver, t as assertSandboxServedModel } from "./sandbox-events-
|
|
6
|
-
import {
|
|
7
|
-
import { a as concreteProfileModel,
|
|
8
|
-
import { i as resolveAgentEnvironmentProvider, n as providerAsExecutor, r as providerAsSandboxClient } from "./environment-provider-
|
|
4
|
+
import { S as contentAddress, a as aggregateProviderModelEvidence, c as pendingWaits, g as runtimeOwnedNestedDriverTreeRoot, h as nestedDriverTreeRoot, l as replaySpawnTree, m as driverRuntime, o as loadSpawnForest, p as attestNestedDriverTreeOwner, s as materializeTreeView, v as captureWorkerTraceEvidence } from "./spawn-journal-CLguaA2A.js";
|
|
5
|
+
import { _ as withTimeout, a as cloneTokenUsage, d as randomSuffix, f as randomUuid, g as throwIfAborted, h as throwAbort, l as mapWithConcurrency, m as stringifySafe, n as addTokenUsage, o as deleteBoxSafe, p as sleep, r as chargedTokens, s as hasCompleteCacheBreakdown, t as addSpend, u as promptCacheTokenClasses, v as zeroSpend, y as zeroTokenUsage } from "./util-Bncw0o_F.js";
|
|
6
|
+
import { c as sandboxEventServedBackend, i as extractLlmCallEvent, l as sandboxProgressEvents, o as mapSandboxToolEvent, r as createSandboxToolPartState, s as notifySandboxEventObserver, t as assertSandboxServedModel } from "./sandbox-events-DMijDq2p.js";
|
|
7
|
+
import { n as executableAgentSpecSnapshot, r as projectSandboxOutcome, t as executableAgentProfileSnapshot } from "./executable-spec-BUcUcEPk.js";
|
|
8
|
+
import { a as concreteProfileModel, c as profileModelExecutionSettings, d as agentHarness, o as enforceTokenLimits, s as profileBridgeWireModel, t as assertExecutableAgentProfile, u as resolveRouterRetryPolicy } from "./model-policy-Sw4ywhtL.js";
|
|
9
|
+
import { i as resolveAgentEnvironmentProvider, n as providerAsExecutor, r as providerAsSandboxClient } from "./environment-provider-D_MXw3jK.js";
|
|
9
10
|
import { i as notifyRuntimeHookEvent } from "./runtime-hooks-tXpAarhW.js";
|
|
10
11
|
import { AGENT_PROFILE_MATERIALIZATION_AXES, AgentTurnInputSchema, REASONING_EFFORTS, agentProfileSchema, canonicalAgentProfileDigest, canonicalCandidateDigest, profileMaterializationAxes, profileMaterializationAxes as profileMaterializationAxes$1, renderInputPartsAsText, sha256DigestSchema } from "@tangle-network/agent-interface";
|
|
11
12
|
import { estimateCost, isModelPriced } from "@tangle-network/agent-eval";
|
|
@@ -218,6 +219,43 @@ function assertProfileMaterialization(options) {
|
|
|
218
219
|
if (issues.length === 0) return;
|
|
219
220
|
throw new ValidationError(renderProfileMaterializationIssues(issues, options.context));
|
|
220
221
|
}
|
|
222
|
+
/**
|
|
223
|
+
* Throw when the CHOSEN HARNESS has no control for a dimension the profile asks for.
|
|
224
|
+
*
|
|
225
|
+
* The contract above answers which axes a run path carries; this answers whether the harness can
|
|
226
|
+
* execute them. `materializeProfile` is pure, so the verdict costs no process and no IO.
|
|
227
|
+
*
|
|
228
|
+
* `skip` must mirror what the EXECUTING caller skips, or this refuses a profile that would have
|
|
229
|
+
* run: a dimension handled by the executor's own native control is not unsupported, it is simply
|
|
230
|
+
* not the plan's to lower.
|
|
231
|
+
*/
|
|
232
|
+
function assertProfileMaterializes(profile, harness, context, skip) {
|
|
233
|
+
const plan = materializeProfile(profile, harness, skip ? { skip: [...skip] } : void 0);
|
|
234
|
+
if (plan.unsupported.length > 0) throw new ValidationError(`${context}: ${harness} cannot materialize the profile: ${renderUnsupported(plan.unsupported)}`);
|
|
235
|
+
return plan;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Ask the materializer which of `dimensions` this harness has no control for, without executing
|
|
239
|
+
* the profile's own `resources.failOnError` policy.
|
|
240
|
+
*
|
|
241
|
+
* A caller that gates only SOME dimensions needs the verdict as data, not as a throw: the
|
|
242
|
+
* materializer throws while planning when `failOnError` is set (its strict default), which hides
|
|
243
|
+
* the dimension list and would conflate a gated dimension with an ungated one. The query copy sets
|
|
244
|
+
* `failOnError: false` so every dimension comes back on `plan.unsupported` and the caller decides.
|
|
245
|
+
*/
|
|
246
|
+
function unsupportedProfileDimensions(profile, harness, dimensions, skip) {
|
|
247
|
+
return materializeProfile({
|
|
248
|
+
...profile,
|
|
249
|
+
resources: {
|
|
250
|
+
...profile.resources,
|
|
251
|
+
failOnError: false
|
|
252
|
+
}
|
|
253
|
+
}, harness, skip ? { skip: [...skip] } : void 0).unsupported.filter((entry) => dimensions.includes(entry.dimension));
|
|
254
|
+
}
|
|
255
|
+
/** One clause per dimension the harness cannot execute, carrying the materializer's own reason. */
|
|
256
|
+
function renderUnsupported(unsupported) {
|
|
257
|
+
return unsupported.map(({ dimension, reason }) => `${dimension}: ${reason}`).join("; ");
|
|
258
|
+
}
|
|
221
259
|
/** Format profile-axis drop issues into a concise operator-facing error. */
|
|
222
260
|
function renderProfileMaterializationIssues(issues, context) {
|
|
223
261
|
if (issues.length === 0) return "";
|
|
@@ -1803,8 +1841,7 @@ function prepareWorktreeProfile(profile, harness) {
|
|
|
1803
1841
|
const workspaceProfile = materializationOnlyProfile(profile);
|
|
1804
1842
|
assertSupportedWorktreeProfile(profile, harness);
|
|
1805
1843
|
assertSafeProfileResourcePaths(profile);
|
|
1806
|
-
const plan =
|
|
1807
|
-
if (plan.unsupported.length > 0) throw new Error(`runWorktreeHarness: profile cannot be materialized for ${harness}: ${plan.unsupported.map(({ dimension, reason }) => `${dimension}: ${reason}`).join("; ")}`);
|
|
1844
|
+
const plan = assertProfileMaterializes(workspaceProfile, harness, "runWorktreeHarness");
|
|
1808
1845
|
assertSafeMaterializedPaths(plan);
|
|
1809
1846
|
return {
|
|
1810
1847
|
plan,
|
|
@@ -3328,12 +3365,14 @@ async function routerChatWithUsage(cfg, messages, opts) {
|
|
|
3328
3365
|
const headers = routerRequestHeaders(cfg, opts);
|
|
3329
3366
|
const temperature = opts?.temperature;
|
|
3330
3367
|
const maxTokens = opts?.maxTokens ?? cfg.maxTokens;
|
|
3368
|
+
const maxCompletionTokens = opts?.maxCompletionTokens ?? cfg.maxCompletionTokens;
|
|
3331
3369
|
const body = () => ({
|
|
3332
3370
|
...providerRequestExtras(opts?.extraBody, [
|
|
3333
3371
|
"model",
|
|
3334
3372
|
"messages",
|
|
3335
3373
|
"temperature",
|
|
3336
3374
|
"max_tokens",
|
|
3375
|
+
"max_completion_tokens",
|
|
3337
3376
|
"seed",
|
|
3338
3377
|
"reasoning_effort",
|
|
3339
3378
|
"stream",
|
|
@@ -3343,6 +3382,7 @@ async function routerChatWithUsage(cfg, messages, opts) {
|
|
|
3343
3382
|
messages,
|
|
3344
3383
|
...temperature !== void 0 ? { temperature } : {},
|
|
3345
3384
|
...maxTokens !== void 0 ? { max_tokens: maxTokens } : {},
|
|
3385
|
+
...maxCompletionTokens !== void 0 ? { max_completion_tokens: maxCompletionTokens } : {},
|
|
3346
3386
|
...opts?.seed !== void 0 ? { seed: opts.seed } : {},
|
|
3347
3387
|
...opts?.reasoningEffort ? { reasoning_effort: opts.reasoningEffort } : {}
|
|
3348
3388
|
});
|
|
@@ -3457,6 +3497,7 @@ async function routerChatWithTools(cfg, messages, tools, opts) {
|
|
|
3457
3497
|
/** The OpenAI-shape request body both tool-calling transports send. One builder so the streamed
|
|
3458
3498
|
* turn cannot drift from the buffered one on model, temperature, tool_choice, or the ceiling. */
|
|
3459
3499
|
function toolCompletionBody(cfg, messages, tools, opts) {
|
|
3500
|
+
const maxCompletionTokens = opts?.maxCompletionTokens ?? cfg.maxCompletionTokens;
|
|
3460
3501
|
return {
|
|
3461
3502
|
...providerRequestExtras(opts?.extraBody, [
|
|
3462
3503
|
"model",
|
|
@@ -3465,6 +3506,7 @@ function toolCompletionBody(cfg, messages, tools, opts) {
|
|
|
3465
3506
|
"tool_choice",
|
|
3466
3507
|
"temperature",
|
|
3467
3508
|
"max_tokens",
|
|
3509
|
+
"max_completion_tokens",
|
|
3468
3510
|
"seed",
|
|
3469
3511
|
"reasoning_effort",
|
|
3470
3512
|
"stream",
|
|
@@ -3478,6 +3520,7 @@ function toolCompletionBody(cfg, messages, tools, opts) {
|
|
|
3478
3520
|
} : {},
|
|
3479
3521
|
...opts?.temperature !== void 0 ? { temperature: opts.temperature } : {},
|
|
3480
3522
|
...opts?.maxTokens ? { max_tokens: opts.maxTokens } : {},
|
|
3523
|
+
...maxCompletionTokens !== void 0 ? { max_completion_tokens: maxCompletionTokens } : {},
|
|
3481
3524
|
...opts?.seed !== void 0 ? { seed: opts.seed } : {},
|
|
3482
3525
|
...opts?.reasoningEffort ? { reasoning_effort: opts.reasoningEffort } : {}
|
|
3483
3526
|
};
|
|
@@ -5141,14 +5184,47 @@ function hashJson(value) {
|
|
|
5141
5184
|
//#region src/runtime/sandbox-executor-output.ts
|
|
5142
5185
|
/** Project the complete Sandbox event stream into the standard executor result shape. */
|
|
5143
5186
|
function sandboxLeafOutputFromEvents(events) {
|
|
5144
|
-
const content = collectAgentFinalMessageText(events) ?? collectAgentResponseText(events)
|
|
5187
|
+
const content = collectAgentFinalMessageText(events) ?? collectAgentResponseText(events);
|
|
5145
5188
|
const toolCalls = sandboxToolCalls(events);
|
|
5189
|
+
const servedBackend = lastServedBackend(events);
|
|
5146
5190
|
return {
|
|
5147
5191
|
events,
|
|
5148
5192
|
content,
|
|
5193
|
+
output: sandboxOutputMarker(content, events.some(carriesText)),
|
|
5194
|
+
...servedBackend === void 0 ? {} : { servedBackend },
|
|
5149
5195
|
...toolCalls.length === 0 ? {} : { toolCalls }
|
|
5150
5196
|
};
|
|
5151
5197
|
}
|
|
5198
|
+
/**
|
|
5199
|
+
* Classify observed text into the explicit output marker. `sawTextEvent` says whether the stream
|
|
5200
|
+
* carried a text-bearing event at all, which is what separates a box that answered nothing from a
|
|
5201
|
+
* box whose answer was never observed.
|
|
5202
|
+
*/
|
|
5203
|
+
function sandboxOutputMarker(content, sawTextEvent = content !== void 0) {
|
|
5204
|
+
if (content !== void 0 && content.length > 0) return {
|
|
5205
|
+
kind: "text",
|
|
5206
|
+
bytes: Buffer.byteLength(content, "utf8")
|
|
5207
|
+
};
|
|
5208
|
+
return sawTextEvent ? { kind: "empty" } : { kind: "absent" };
|
|
5209
|
+
}
|
|
5210
|
+
/** True when the event carries a text field a turn's answer could come from, empty or not. */
|
|
5211
|
+
function carriesText(event) {
|
|
5212
|
+
if (!event || typeof event !== "object") return false;
|
|
5213
|
+
const data = event.data && typeof event.data === "object" ? event.data : {};
|
|
5214
|
+
if (typeof data.finalText === "string" || typeof data.text === "string") return true;
|
|
5215
|
+
if (typeof data.delta === "string") return true;
|
|
5216
|
+
const part = data.part && typeof data.part === "object" ? data.part : void 0;
|
|
5217
|
+
return part !== void 0 && part.type === "text" && typeof part.text === "string";
|
|
5218
|
+
}
|
|
5219
|
+
/** The last served identity the platform reported across a turn's events, or `undefined`. */
|
|
5220
|
+
function lastServedBackend(events) {
|
|
5221
|
+
let served;
|
|
5222
|
+
for (const event of events) {
|
|
5223
|
+
const next = sandboxEventServedBackend(event);
|
|
5224
|
+
if (next !== void 0) served = next;
|
|
5225
|
+
}
|
|
5226
|
+
return served;
|
|
5227
|
+
}
|
|
5152
5228
|
function sandboxToolCalls(events) {
|
|
5153
5229
|
const state = createSandboxToolPartState();
|
|
5154
5230
|
return events.flatMap((event) => mapSandboxToolEvent(event, state).flatMap((projected) => projected.type === "tool_call" ? [{
|
|
@@ -5180,7 +5256,8 @@ function priceUnreceiptedWork(work) {
|
|
|
5180
5256
|
const unknown = {
|
|
5181
5257
|
kind: "cost",
|
|
5182
5258
|
usd: 0,
|
|
5183
|
-
usdKnown: false
|
|
5259
|
+
usdKnown: false,
|
|
5260
|
+
provenance: "uncaptured"
|
|
5184
5261
|
};
|
|
5185
5262
|
const { inputTokens, outputTokens, model } = work;
|
|
5186
5263
|
if (model === void 0 || !isModelPriced(model)) return unknown;
|
|
@@ -5192,7 +5269,8 @@ function priceUnreceiptedWork(work) {
|
|
|
5192
5269
|
kind: "cost",
|
|
5193
5270
|
usd,
|
|
5194
5271
|
usdKnown: false,
|
|
5195
|
-
usdEstimated: usd
|
|
5272
|
+
usdEstimated: usd,
|
|
5273
|
+
provenance: "catalog-estimate"
|
|
5196
5274
|
};
|
|
5197
5275
|
}
|
|
5198
5276
|
//#endregion
|
|
@@ -5915,13 +5993,21 @@ function createSteerableSandboxSession(args) {
|
|
|
5915
5993
|
});
|
|
5916
5994
|
const state = {
|
|
5917
5995
|
turns: 0,
|
|
5918
|
-
|
|
5996
|
+
/** `undefined` until a text-bearing terminal event is observed; never seeded with `''`. */
|
|
5997
|
+
lastText: void 0,
|
|
5998
|
+
servedBackend: void 0,
|
|
5919
5999
|
seenToolCalls: /* @__PURE__ */ new Set(),
|
|
6000
|
+
toolCalls: [],
|
|
5920
6001
|
artifact: void 0,
|
|
5921
6002
|
latestOutcome: void 0,
|
|
6003
|
+
/** Reads the live lineage handle once a box and session exist, for exact cancellation. */
|
|
6004
|
+
session: void 0,
|
|
5922
6005
|
teardown: void 0,
|
|
5923
6006
|
note: "starting"
|
|
5924
6007
|
};
|
|
6008
|
+
const toolParts = createSandboxToolPartState();
|
|
6009
|
+
/** Record one box event for the trace and the activity window, and return the live output it
|
|
6010
|
+
* carries so the caller can publish it to the turn stream. */
|
|
5925
6011
|
const recordEvent = (event) => {
|
|
5926
6012
|
const at = now();
|
|
5927
6013
|
const data = event.data;
|
|
@@ -5945,7 +6031,19 @@ function createSteerableSandboxSession(args) {
|
|
|
5945
6031
|
}
|
|
5946
6032
|
}
|
|
5947
6033
|
const text = readFinalText(event);
|
|
5948
|
-
if (text) state.lastText = text;
|
|
6034
|
+
if (text !== void 0) state.lastText = text;
|
|
6035
|
+
const served = sandboxEventServedBackend(event);
|
|
6036
|
+
if (served !== void 0) state.servedBackend = served;
|
|
6037
|
+
const progress = sandboxProgressEvents(event, toolParts);
|
|
6038
|
+
for (const item of progress) {
|
|
6039
|
+
if (item.kind !== "tool_call") continue;
|
|
6040
|
+
state.toolCalls.push({
|
|
6041
|
+
...item.toolCallId === void 0 ? {} : { id: item.toolCallId },
|
|
6042
|
+
name: item.toolName,
|
|
6043
|
+
arguments: item.args ?? {}
|
|
6044
|
+
});
|
|
6045
|
+
}
|
|
6046
|
+
return progress;
|
|
5949
6047
|
};
|
|
5950
6048
|
async function* stream(task, signal) {
|
|
5951
6049
|
const capabilities = await probeSandboxCapabilities(args.sandboxClient);
|
|
@@ -5971,6 +6069,7 @@ function createSteerableSandboxSession(args) {
|
|
|
5971
6069
|
let tokensKnown = true;
|
|
5972
6070
|
let usd = 0;
|
|
5973
6071
|
let handle;
|
|
6072
|
+
state.session = () => handle;
|
|
5974
6073
|
let nextPrompt = args.taskToPrompt(task);
|
|
5975
6074
|
try {
|
|
5976
6075
|
for (let turn = 0; maxTurns === 0 || turn < maxTurns; turn += 1) {
|
|
@@ -6016,7 +6115,10 @@ function createSteerableSandboxSession(args) {
|
|
|
6016
6115
|
} else events = await lineage.continue(handle, prompt, turnController.signal, promptOptions);
|
|
6017
6116
|
for await (const event of events) {
|
|
6018
6117
|
outcomeTracker.observe(event);
|
|
6019
|
-
recordEvent(event)
|
|
6118
|
+
for (const progress of recordEvent(event)) yield {
|
|
6119
|
+
kind: "progress",
|
|
6120
|
+
progress
|
|
6121
|
+
};
|
|
6020
6122
|
const call = extractLlmCallEvent(event, spec.name ?? String(args.harness));
|
|
6021
6123
|
if (call) {
|
|
6022
6124
|
sawLlmCall = true;
|
|
@@ -6040,7 +6142,8 @@ function createSteerableSandboxSession(args) {
|
|
|
6040
6142
|
yield {
|
|
6041
6143
|
kind: "cost",
|
|
6042
6144
|
usd: call.costUsd,
|
|
6043
|
-
usdKnown: false
|
|
6145
|
+
usdKnown: false,
|
|
6146
|
+
provenance: "uncaptured"
|
|
6044
6147
|
};
|
|
6045
6148
|
}
|
|
6046
6149
|
}
|
|
@@ -6087,7 +6190,8 @@ function createSteerableSandboxSession(args) {
|
|
|
6087
6190
|
if (state.turns > 0) yield {
|
|
6088
6191
|
kind: "cost",
|
|
6089
6192
|
usd: 0,
|
|
6090
|
-
usdKnown: false
|
|
6193
|
+
usdKnown: false,
|
|
6194
|
+
provenance: "uncaptured"
|
|
6091
6195
|
};
|
|
6092
6196
|
const spent = {
|
|
6093
6197
|
iterations: state.turns,
|
|
@@ -6099,8 +6203,10 @@ function createSteerableSandboxSession(args) {
|
|
|
6099
6203
|
};
|
|
6100
6204
|
const out = {
|
|
6101
6205
|
content: state.lastText,
|
|
6206
|
+
output: sandboxOutputMarker(state.lastText),
|
|
6207
|
+
...state.servedBackend === void 0 ? {} : { servedBackend: state.servedBackend },
|
|
6102
6208
|
turns: state.turns,
|
|
6103
|
-
toolCalls:
|
|
6209
|
+
toolCalls: state.toolCalls,
|
|
6104
6210
|
...state.latestOutcome ? { outcome: state.latestOutcome } : {}
|
|
6105
6211
|
};
|
|
6106
6212
|
const verdict = state.latestOutcome ? projectSandboxOutcome(state.latestOutcome).verdict : void 0;
|
|
@@ -6116,6 +6222,60 @@ function createSteerableSandboxSession(args) {
|
|
|
6116
6222
|
}
|
|
6117
6223
|
return {
|
|
6118
6224
|
stream,
|
|
6225
|
+
async cancel(request) {
|
|
6226
|
+
const live = state.session?.();
|
|
6227
|
+
const observedAt = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
6228
|
+
if (!live) return {
|
|
6229
|
+
status: "unknown",
|
|
6230
|
+
effect: "cancel_requested",
|
|
6231
|
+
observedAt: observedAt(),
|
|
6232
|
+
detail: "no box session exists yet for this worker; nothing remote could be asked"
|
|
6233
|
+
};
|
|
6234
|
+
const session = live.box.session?.(live.sessionId);
|
|
6235
|
+
if (!session || typeof session.interrupt !== "function") return {
|
|
6236
|
+
status: "unknown",
|
|
6237
|
+
effect: "cancel_requested",
|
|
6238
|
+
observedAt: observedAt(),
|
|
6239
|
+
detail: "the sandbox client exposes no session interrupt operation",
|
|
6240
|
+
evidence: { sessionId: live.sessionId }
|
|
6241
|
+
};
|
|
6242
|
+
try {
|
|
6243
|
+
const result = await session.interrupt();
|
|
6244
|
+
const evidence = {
|
|
6245
|
+
sessionId: live.sessionId,
|
|
6246
|
+
operationId: request.operationId,
|
|
6247
|
+
result
|
|
6248
|
+
};
|
|
6249
|
+
if (result?.cancelled === true) {
|
|
6250
|
+
args.controller.abort("executor cancelled");
|
|
6251
|
+
return {
|
|
6252
|
+
status: "accepted",
|
|
6253
|
+
effect: "cancelled",
|
|
6254
|
+
observedAt: observedAt(),
|
|
6255
|
+
detail: "the box reported the running execution cancelled",
|
|
6256
|
+
evidence
|
|
6257
|
+
};
|
|
6258
|
+
}
|
|
6259
|
+
return {
|
|
6260
|
+
status: "already-terminal",
|
|
6261
|
+
effect: "not_live",
|
|
6262
|
+
observedAt: observedAt(),
|
|
6263
|
+
detail: "the box reported no running execution on this session",
|
|
6264
|
+
evidence
|
|
6265
|
+
};
|
|
6266
|
+
} catch (error) {
|
|
6267
|
+
return {
|
|
6268
|
+
status: "unknown",
|
|
6269
|
+
effect: "cancel_requested",
|
|
6270
|
+
observedAt: observedAt(),
|
|
6271
|
+
detail: `the box interrupt failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
6272
|
+
evidence: {
|
|
6273
|
+
sessionId: live.sessionId,
|
|
6274
|
+
operationId: request.operationId
|
|
6275
|
+
}
|
|
6276
|
+
};
|
|
6277
|
+
}
|
|
6278
|
+
},
|
|
6119
6279
|
progress: () => ({
|
|
6120
6280
|
turns: state.turns,
|
|
6121
6281
|
pendingMessages: args.inbox.pending(),
|
|
@@ -6133,14 +6293,16 @@ function createSteerableSandboxSession(args) {
|
|
|
6133
6293
|
function isInterruptAbort(err, interrupt, external, owned) {
|
|
6134
6294
|
return (err instanceof DOMException && err.name === "AbortError" || typeof err === "object" && err !== null && err.name === "AbortError") && interrupt.aborted && !external.aborted && !owned.aborted;
|
|
6135
6295
|
}
|
|
6136
|
-
/** The terminal text a sandbox `result` event carries, when it carries one.
|
|
6296
|
+
/** The terminal text a sandbox `result` event carries, when it carries one. An observed empty
|
|
6297
|
+
* string is returned as `''`, because "the box answered nothing" is not "the box never
|
|
6298
|
+
* answered". */
|
|
6137
6299
|
function readFinalText(event) {
|
|
6138
6300
|
const data = event.data;
|
|
6139
6301
|
if (!data || typeof data !== "object") return void 0;
|
|
6140
6302
|
const text = data.finalText;
|
|
6141
|
-
if (typeof text === "string"
|
|
6303
|
+
if (typeof text === "string") return text;
|
|
6142
6304
|
const alt = data.text;
|
|
6143
|
-
return typeof alt === "string"
|
|
6305
|
+
return typeof alt === "string" ? alt : void 0;
|
|
6144
6306
|
}
|
|
6145
6307
|
/** Prompt options the composed loop context already carries (agent profile / cwd), forwarded so
|
|
6146
6308
|
* a steerable worker runs with the same box configuration as the single-shot path. */
|
|
@@ -6548,6 +6710,11 @@ const bridgeSeamKey = "bridge";
|
|
|
6548
6710
|
/** Internal control seam used by Runtime-owned external supervisors. A completion request stops
|
|
6549
6711
|
* the next bridge turn; it must not abort the paid request that is already streaming. */
|
|
6550
6712
|
const bridgeStopSignalKey = "__bridge_stop_signal";
|
|
6713
|
+
/** Internal attachment seam used by Runtime-owned external supervisors. The named MCP servers ride
|
|
6714
|
+
* beside the AgentProfile as `runtime_attachments`, so the bridge mounts them for the run and keeps
|
|
6715
|
+
* them out of its session profile binding. A rebound coordination port therefore cannot move the
|
|
6716
|
+
* authored profile digest that binds a durable session. */
|
|
6717
|
+
const bridgeRuntimeAttachmentsKey = "__bridge_runtime_attachments";
|
|
6551
6718
|
const maxBridgeTimeoutMs = 2147483647;
|
|
6552
6719
|
const bridgeModelCredentialHeader = "x-cli-bridge-model-credential";
|
|
6553
6720
|
const bridgeModelBaseUrlHeader = "x-cli-bridge-model-base-url";
|
|
@@ -6686,6 +6853,19 @@ function unmeteredSpend(ms) {
|
|
|
6686
6853
|
* failures (429/5xx/Cloudflare-origin) retry with backoff before the executor
|
|
6687
6854
|
* fails the task.
|
|
6688
6855
|
*/
|
|
6856
|
+
/**
|
|
6857
|
+
* The honest answer for a backend with no cancel operation: the local request stopped, and
|
|
6858
|
+
* nothing about the remote run is known. Never `accepted` — a client that advertises provider
|
|
6859
|
+
* cancellation from this would claim more than Runtime observed.
|
|
6860
|
+
*/
|
|
6861
|
+
function localAbortCancellation(detail) {
|
|
6862
|
+
return {
|
|
6863
|
+
status: "unknown",
|
|
6864
|
+
effect: "cancel_requested",
|
|
6865
|
+
observedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6866
|
+
detail
|
|
6867
|
+
};
|
|
6868
|
+
}
|
|
6689
6869
|
const routerInlineExecutor = (spec, ctx) => {
|
|
6690
6870
|
const seam = readSeam(ctx, routerSeamKey, "router/inline");
|
|
6691
6871
|
const model = exactRouterModel(spec.profile, "routerInlineExecutor");
|
|
@@ -6723,7 +6903,7 @@ const routerInlineExecutor = (spec, ctx) => {
|
|
|
6723
6903
|
...profileExecution.temperature !== void 0 ? { temperature: profileExecution.temperature } : {},
|
|
6724
6904
|
...linked ? { signal: linked } : {},
|
|
6725
6905
|
...profileExecution.toolChoice ? { toolChoice: profileExecution.toolChoice } : {},
|
|
6726
|
-
...profileExecution.
|
|
6906
|
+
...profileExecution.tokenLimits.applied,
|
|
6727
6907
|
...profileExecution.seed !== void 0 ? { seed: profileExecution.seed } : {},
|
|
6728
6908
|
...Object.keys(extraBody).length > 0 ? { extraBody } : {},
|
|
6729
6909
|
...requestIdentity
|
|
@@ -6736,7 +6916,7 @@ const routerInlineExecutor = (spec, ctx) => {
|
|
|
6736
6916
|
}, messages, {
|
|
6737
6917
|
...profileExecution.temperature !== void 0 ? { temperature: profileExecution.temperature } : {},
|
|
6738
6918
|
...linked ? { signal: linked } : {},
|
|
6739
|
-
...profileExecution.
|
|
6919
|
+
...profileExecution.tokenLimits.applied,
|
|
6740
6920
|
...profileExecution.seed !== void 0 ? { seed: profileExecution.seed } : {},
|
|
6741
6921
|
...profileExecution.reasoningEffort ? { reasoningEffort: profileExecution.reasoningEffort } : {},
|
|
6742
6922
|
...profileExecution.extraBody ? { extraBody: profileExecution.extraBody } : {},
|
|
@@ -6777,6 +6957,10 @@ const routerInlineExecutor = (spec, ctx) => {
|
|
|
6777
6957
|
};
|
|
6778
6958
|
return artifact;
|
|
6779
6959
|
},
|
|
6960
|
+
cancel(_request) {
|
|
6961
|
+
controller.abort("executor cancelled");
|
|
6962
|
+
return Promise.resolve(localAbortCancellation("the Router chat-completions API exposes no cancel operation; the local request was aborted and the provider may still bill the completion"));
|
|
6963
|
+
},
|
|
6780
6964
|
teardown(_grace) {
|
|
6781
6965
|
controller.abort("executor torn down");
|
|
6782
6966
|
return Promise.resolve({ destroyed: true });
|
|
@@ -6805,7 +6989,7 @@ const routerInlineExecutor = (spec, ctx) => {
|
|
|
6805
6989
|
model,
|
|
6806
6990
|
provider: spec.profile.model?.provider ?? null,
|
|
6807
6991
|
temperature: profileExecution.temperature ?? null,
|
|
6808
|
-
|
|
6992
|
+
tokenLimits: profileExecution.tokenLimits,
|
|
6809
6993
|
retry: profileExecution.retry ?? null,
|
|
6810
6994
|
seed: profileExecution.seed ?? null,
|
|
6811
6995
|
reasoningEffort: profileExecution.reasoningEffort ?? null,
|
|
@@ -6917,6 +7101,7 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
6917
7101
|
let reasoningKnown = true;
|
|
6918
7102
|
const promptCache = {};
|
|
6919
7103
|
let lastText = "";
|
|
7104
|
+
const executedToolCalls = [];
|
|
6920
7105
|
const flush = () => {
|
|
6921
7106
|
const pending = inbox.drain();
|
|
6922
7107
|
if (pending.length) messages.push({
|
|
@@ -6949,7 +7134,7 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
6949
7134
|
...profileExecution.temperature !== void 0 ? { temperature: profileExecution.temperature } : {},
|
|
6950
7135
|
signal: turnController.signal,
|
|
6951
7136
|
...profileExecution.toolChoice ? { toolChoice: profileExecution.toolChoice } : {},
|
|
6952
|
-
...profileExecution.
|
|
7137
|
+
...profileExecution.tokenLimits.applied,
|
|
6953
7138
|
...profileExecution.seed !== void 0 ? { seed: profileExecution.seed } : {},
|
|
6954
7139
|
...profileExecution.reasoningEffort ? { reasoningEffort: profileExecution.reasoningEffort } : {},
|
|
6955
7140
|
...profileExecution.extraBody ? { extraBody: profileExecution.extraBody } : {},
|
|
@@ -7015,6 +7200,11 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
7015
7200
|
const tc = toolCalls[i];
|
|
7016
7201
|
const id = tc?.id ?? `call_${i}`;
|
|
7017
7202
|
const toolName = tc?.name ?? "";
|
|
7203
|
+
executedToolCalls.push({
|
|
7204
|
+
id,
|
|
7205
|
+
name: toolName,
|
|
7206
|
+
arguments: tc?.arguments ?? ""
|
|
7207
|
+
});
|
|
7018
7208
|
if (!enabledToolNames.has(toolName)) {
|
|
7019
7209
|
messages.push({
|
|
7020
7210
|
role: "tool",
|
|
@@ -7085,7 +7275,7 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
7085
7275
|
...observedModel !== void 0 ? { model: observedModel } : {},
|
|
7086
7276
|
messages,
|
|
7087
7277
|
turns,
|
|
7088
|
-
toolCalls:
|
|
7278
|
+
toolCalls: executedToolCalls,
|
|
7089
7279
|
transportAttempts,
|
|
7090
7280
|
...estimatedUsd !== void 0 ? { estimatedCostUsd: estimatedUsd } : {},
|
|
7091
7281
|
...Object.keys(promptCache).length > 0 ? { promptCache } : {},
|
|
@@ -7101,6 +7291,10 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
7101
7291
|
};
|
|
7102
7292
|
return artifact;
|
|
7103
7293
|
},
|
|
7294
|
+
cancel(_request) {
|
|
7295
|
+
controller.abort("executor cancelled");
|
|
7296
|
+
return Promise.resolve(localAbortCancellation("the Router chat-completions API exposes no cancel operation; the in-flight turn was aborted and the provider may still bill it"));
|
|
7297
|
+
},
|
|
7104
7298
|
teardown(_grace) {
|
|
7105
7299
|
controller.abort("executor torn down");
|
|
7106
7300
|
return Promise.resolve({ destroyed: true });
|
|
@@ -7131,7 +7325,7 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
7131
7325
|
maxTurns,
|
|
7132
7326
|
tools: seam.tools,
|
|
7133
7327
|
temperature: profileExecution.temperature ?? null,
|
|
7134
|
-
|
|
7328
|
+
tokenLimits: profileExecution.tokenLimits,
|
|
7135
7329
|
retry: profileExecution.retry ?? null,
|
|
7136
7330
|
toolChoice: profileExecution.toolChoice ?? null,
|
|
7137
7331
|
extraBody: profileExecution.extraBody ?? null,
|
|
@@ -7190,6 +7384,7 @@ const sandboxExecutor = (spec, ctx) => {
|
|
|
7190
7384
|
if (!seam.sandboxClient || typeof seam.sandboxClient.create !== "function") throw new ValidationError("sandboxExecutor: SandboxSeam.sandboxClient.create required");
|
|
7191
7385
|
const maxIterations = seam.maxIterations ?? 1;
|
|
7192
7386
|
if (!Number.isFinite(maxIterations) || maxIterations <= 0) throw new ValidationError("sandboxExecutor: maxIterations must be > 0");
|
|
7387
|
+
const sandboxTokenLimits = enforceTokenLimits(profileModelExecutionSettings(spec.profile, "sandboxExecutor").tokenLimits, "sandbox", "sandboxExecutor");
|
|
7193
7388
|
const traceEnv = workerTraceEnv(ctx);
|
|
7194
7389
|
const controller = new AbortController();
|
|
7195
7390
|
const abortIfSignalled = () => {
|
|
@@ -7220,7 +7415,8 @@ const sandboxExecutor = (spec, ctx) => {
|
|
|
7220
7415
|
kind: "sandbox-agent-rounds",
|
|
7221
7416
|
harness,
|
|
7222
7417
|
maxIterations,
|
|
7223
|
-
steering: seam.steering !== void 0
|
|
7418
|
+
steering: seam.steering !== void 0,
|
|
7419
|
+
tokenLimits: sandboxTokenLimits
|
|
7224
7420
|
}
|
|
7225
7421
|
};
|
|
7226
7422
|
const sandboxBinding = {
|
|
@@ -7255,6 +7451,7 @@ const sandboxExecutor = (spec, ctx) => {
|
|
|
7255
7451
|
runtime: "sandbox",
|
|
7256
7452
|
deliver: (m) => inbox.deliver(m),
|
|
7257
7453
|
progress: () => session.progress(),
|
|
7454
|
+
cancel: (request) => session.cancel(request),
|
|
7258
7455
|
traceSource: () => session.traceSource(),
|
|
7259
7456
|
execute(task, signal) {
|
|
7260
7457
|
return session.stream(task, signal);
|
|
@@ -7296,6 +7493,10 @@ const sandboxExecutor = (spec, ctx) => {
|
|
|
7296
7493
|
}
|
|
7297
7494
|
});
|
|
7298
7495
|
},
|
|
7496
|
+
cancel(_request) {
|
|
7497
|
+
controller.abort("executor cancelled");
|
|
7498
|
+
return Promise.resolve(localAbortCancellation("the composed sandbox run owns its boxes, so this executor retains no exact session control reference to cancel against"));
|
|
7499
|
+
},
|
|
7299
7500
|
teardown(_grace) {
|
|
7300
7501
|
controller.abort();
|
|
7301
7502
|
return Promise.resolve({ destroyed: true });
|
|
@@ -7390,10 +7591,16 @@ async function* streamSandboxLeaf(args) {
|
|
|
7390
7591
|
...result.tokenUsage.cacheWrite !== void 0 ? { cacheWrite: result.tokenUsage.cacheWrite } : {},
|
|
7391
7592
|
...result.tokenUsage.cacheBreakdownKnown === false ? { cacheBreakdownKnown: false } : {}
|
|
7392
7593
|
};
|
|
7393
|
-
if (result.iterations.length > 0 || result.costUsd) yield {
|
|
7594
|
+
if (result.iterations.length > 0 || result.costUsd) yield usdKnown ? {
|
|
7394
7595
|
kind: "cost",
|
|
7596
|
+
usdKnown: true,
|
|
7395
7597
|
usd: result.costUsd,
|
|
7396
|
-
|
|
7598
|
+
provenance: "provider-receipt"
|
|
7599
|
+
} : {
|
|
7600
|
+
kind: "cost",
|
|
7601
|
+
usdKnown: false,
|
|
7602
|
+
usd: result.costUsd,
|
|
7603
|
+
provenance: "uncaptured"
|
|
7397
7604
|
};
|
|
7398
7605
|
} finally {
|
|
7399
7606
|
args.signal.removeEventListener("abort", cascadeExternal);
|
|
@@ -7592,18 +7799,20 @@ function bridgeProfileModel(profile, context) {
|
|
|
7592
7799
|
const bridgeExecutor = (spec, ctx) => {
|
|
7593
7800
|
const base = readSeam(ctx, bridgeSeamKey, "bridge");
|
|
7594
7801
|
const stopSignal = readOptionalAbortSignal(ctx, bridgeStopSignalKey, "bridge");
|
|
7802
|
+
const runtimeAttachments = readOptionalMcpAttachments(ctx, bridgeRuntimeAttachmentsKey, "bridge");
|
|
7595
7803
|
const modelCredential = validateBridgeModelCredential(base.modelCredential, base.bridgeUrl, "bridgeExecutor");
|
|
7596
7804
|
const effectiveProfile = agentProfileSchema.parse(spec.profile);
|
|
7597
7805
|
const model = bridgeProfileModel(effectiveProfile, "bridgeExecutor");
|
|
7598
7806
|
const harness = agentHarness(effectiveProfile.harness);
|
|
7599
7807
|
const providerModel = harness !== void 0 && model.startsWith(`${harness}/`) ? model.slice(harness.length + 1) : model;
|
|
7600
7808
|
const profileExecution = profileModelExecutionSettings(effectiveProfile, "bridgeExecutor");
|
|
7809
|
+
const bridgeTokenLimits = enforceTokenLimits(profileExecution.tokenLimits, "bridge", "bridgeExecutor");
|
|
7601
7810
|
const seam = {
|
|
7602
7811
|
...base,
|
|
7603
7812
|
...modelCredential === void 0 ? {} : { modelCredential },
|
|
7604
7813
|
model,
|
|
7605
7814
|
providerModel,
|
|
7606
|
-
...
|
|
7815
|
+
...bridgeTokenLimits.applied.maxTokens !== void 0 ? { maxTokens: bridgeTokenLimits.applied.maxTokens } : {}
|
|
7607
7816
|
};
|
|
7608
7817
|
if (!seam.bridgeUrl || !seam.bridgeBearer) throw new ValidationError("bridgeExecutor: bridgeUrl + bridgeBearer are required");
|
|
7609
7818
|
if (seam.timeoutMs !== void 0 && (!Number.isSafeInteger(seam.timeoutMs) || seam.timeoutMs < 1 || seam.timeoutMs > maxBridgeTimeoutMs)) throw new ValidationError(`bridgeExecutor: timeoutMs must be an integer from 1 to ${maxBridgeTimeoutMs}`);
|
|
@@ -7651,7 +7860,7 @@ const bridgeExecutor = (spec, ctx) => {
|
|
|
7651
7860
|
maxReconnects,
|
|
7652
7861
|
timeoutMs: seam.timeoutMs ?? null,
|
|
7653
7862
|
streaming: true,
|
|
7654
|
-
|
|
7863
|
+
tokenLimits: bridgeTokenLimits,
|
|
7655
7864
|
terminalAcknowledgement: null
|
|
7656
7865
|
}
|
|
7657
7866
|
};
|
|
@@ -7697,11 +7906,16 @@ const bridgeExecutor = (spec, ctx) => {
|
|
|
7697
7906
|
}
|
|
7698
7907
|
},
|
|
7699
7908
|
traceSource: () => trace.source,
|
|
7909
|
+
interactive: () => Object.freeze({
|
|
7910
|
+
status: "unavailable",
|
|
7911
|
+
reason: "provider-has-no-interactive-contract"
|
|
7912
|
+
}),
|
|
7700
7913
|
execute(task, signal) {
|
|
7701
7914
|
return streamBridgeSession({
|
|
7702
7915
|
task,
|
|
7703
7916
|
signal,
|
|
7704
7917
|
...stopSignal === void 0 ? {} : { stopSignal },
|
|
7918
|
+
...runtimeAttachments === void 0 ? {} : { runtimeAttachments },
|
|
7705
7919
|
profile: effectiveProfile,
|
|
7706
7920
|
seam,
|
|
7707
7921
|
sessionId,
|
|
@@ -7738,6 +7952,41 @@ const bridgeExecutor = (spec, ctx) => {
|
|
|
7738
7952
|
}
|
|
7739
7953
|
});
|
|
7740
7954
|
},
|
|
7955
|
+
async cancel(request) {
|
|
7956
|
+
const live = [...activeRuns.values()].filter((run) => !run.terminal);
|
|
7957
|
+
const observedAt = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
7958
|
+
if (live.length === 0) return {
|
|
7959
|
+
status: "already-terminal",
|
|
7960
|
+
effect: "not_live",
|
|
7961
|
+
observedAt: observedAt(),
|
|
7962
|
+
detail: "every bridge run for this session was already terminal",
|
|
7963
|
+
evidence: { runs: [...activeRuns.keys()] }
|
|
7964
|
+
};
|
|
7965
|
+
controller.abort("executor cancelled");
|
|
7966
|
+
const grace = request.signal === void 0 ? "infinity" : BRIDGE_CANCEL_LONG_POLL_MS;
|
|
7967
|
+
const terminal = await Promise.all(live.map((run) => cancelBridgeRunToTerminal(seam, run, grace, request.signal)));
|
|
7968
|
+
const evidence = {
|
|
7969
|
+
operationId: request.operationId,
|
|
7970
|
+
runs: live.map((run, index) => ({
|
|
7971
|
+
id: run.id,
|
|
7972
|
+
terminal: terminal[index] === true
|
|
7973
|
+
}))
|
|
7974
|
+
};
|
|
7975
|
+
if (terminal.every(Boolean)) return {
|
|
7976
|
+
status: "accepted",
|
|
7977
|
+
effect: "cancelled",
|
|
7978
|
+
observedAt: observedAt(),
|
|
7979
|
+
detail: "the bridge reported every run terminal after the cancel operation",
|
|
7980
|
+
evidence
|
|
7981
|
+
};
|
|
7982
|
+
return {
|
|
7983
|
+
status: "unknown",
|
|
7984
|
+
effect: "cancel_requested",
|
|
7985
|
+
observedAt: observedAt(),
|
|
7986
|
+
detail: "the bridge accepted the cancel operation but a run had not reached terminal state within the deadline",
|
|
7987
|
+
evidence
|
|
7988
|
+
};
|
|
7989
|
+
},
|
|
7741
7990
|
async teardown(grace) {
|
|
7742
7991
|
controller.abort();
|
|
7743
7992
|
const remaining = [...activeRuns.values()].filter((run) => !run.terminal);
|
|
@@ -7803,6 +8052,78 @@ function scheduleBridgeRunStateRefresh(seam, activeRuns, observation) {
|
|
|
7803
8052
|
}
|
|
7804
8053
|
})();
|
|
7805
8054
|
}
|
|
8055
|
+
/** One bridge GET over the `node:http(s)` core client — the same transport every other bridge
|
|
8056
|
+
* read uses, so a computed provider endpoint never reaches global `fetch`. Resolves the status
|
|
8057
|
+
* and the body text; a transport failure rejects. */
|
|
8058
|
+
function bridgeGet(seam, path, timeoutMs) {
|
|
8059
|
+
const target = new URL(`${seam.bridgeUrl.replace(/\/$/, "")}${path}`);
|
|
8060
|
+
const requestFn = target.protocol === "https:" ? request$1 : request;
|
|
8061
|
+
return new Promise((resolve, reject) => {
|
|
8062
|
+
const req = requestFn(target, {
|
|
8063
|
+
method: "GET",
|
|
8064
|
+
headers: { authorization: `Bearer ${seam.bridgeBearer}` },
|
|
8065
|
+
timeout: timeoutMs
|
|
8066
|
+
}, (res) => {
|
|
8067
|
+
(async () => {
|
|
8068
|
+
const chunks = [];
|
|
8069
|
+
for await (const chunk of res) chunks.push(Buffer.from(chunk));
|
|
8070
|
+
resolve({
|
|
8071
|
+
status: res.statusCode ?? 0,
|
|
8072
|
+
body: Buffer.concat(chunks).toString("utf8")
|
|
8073
|
+
});
|
|
8074
|
+
})().catch(reject);
|
|
8075
|
+
});
|
|
8076
|
+
req.on("timeout", () => req.destroy(/* @__PURE__ */ new Error(`bridge GET ${path} timed out`)));
|
|
8077
|
+
req.on("error", reject);
|
|
8078
|
+
req.end();
|
|
8079
|
+
});
|
|
8080
|
+
}
|
|
8081
|
+
/**
|
|
8082
|
+
* `GET /v1/capabilities?model=<wire id>` — does this bridge route this model AT ALL.
|
|
8083
|
+
*
|
|
8084
|
+
* The bridge answers exactly this question and 404s `no backend matches model "…"`, which is the
|
|
8085
|
+
* error a child would otherwise discover after it was spawned and metered. Returns `undefined`
|
|
8086
|
+
* when the route resolves; otherwise the operator-facing reason it did not. FAIL CLOSED: a
|
|
8087
|
+
* transport error and an unexpected status are both reasons, never a silent pass.
|
|
8088
|
+
*/
|
|
8089
|
+
async function bridgeModelRouteRefusal(seam, wireModel) {
|
|
8090
|
+
const base = seam.bridgeUrl.replace(/\/$/, "");
|
|
8091
|
+
let answer;
|
|
8092
|
+
try {
|
|
8093
|
+
answer = await bridgeGet(seam, `/v1/capabilities?model=${encodeURIComponent(wireModel)}`, BRIDGE_RUN_STATE_TIMEOUT_MS);
|
|
8094
|
+
} catch (error) {
|
|
8095
|
+
return `bridge ${base} did not answer for model ${JSON.stringify(wireModel)}: ${error instanceof Error ? error.message : String(error)}`;
|
|
8096
|
+
}
|
|
8097
|
+
if (answer.status === 200) return void 0;
|
|
8098
|
+
return answer.status === 404 ? `bridge ${base} routes no backend for model ${JSON.stringify(wireModel)}` : `bridge ${base} answered ${answer.status} for model ${JSON.stringify(wireModel)}`;
|
|
8099
|
+
}
|
|
8100
|
+
/**
|
|
8101
|
+
* `GET /health` → `admission.{active,maxActive}`, or `undefined` when the bridge does not report
|
|
8102
|
+
* them. ADVISORY by nature — admission fills and drains — so an unanswered or admission-less
|
|
8103
|
+
* `/health` is not evidence about capacity and must not be read as one.
|
|
8104
|
+
*/
|
|
8105
|
+
async function bridgeAdmissionRead(seam) {
|
|
8106
|
+
let answer;
|
|
8107
|
+
try {
|
|
8108
|
+
answer = await bridgeGet(seam, "/health", BRIDGE_RUN_STATE_TIMEOUT_MS);
|
|
8109
|
+
} catch {
|
|
8110
|
+
return;
|
|
8111
|
+
}
|
|
8112
|
+
let parsed;
|
|
8113
|
+
try {
|
|
8114
|
+
parsed = JSON.parse(answer.body);
|
|
8115
|
+
} catch {
|
|
8116
|
+
return;
|
|
8117
|
+
}
|
|
8118
|
+
const admission = parsed?.admission;
|
|
8119
|
+
const active = admission?.active;
|
|
8120
|
+
const maxActive = admission?.maxActive;
|
|
8121
|
+
if (typeof active !== "number" || typeof maxActive !== "number" || maxActive <= 0) return;
|
|
8122
|
+
return {
|
|
8123
|
+
active,
|
|
8124
|
+
maxActive
|
|
8125
|
+
};
|
|
8126
|
+
}
|
|
7806
8127
|
/** `GET /v1/runs/:id` — the bridge's durable-run registry read. Resolves `undefined` for any
|
|
7807
8128
|
* non-200 or non-conforming body rather than throwing: this is only ever an observability read. */
|
|
7808
8129
|
function bridgeRunStateGet(seam, runId) {
|
|
@@ -7935,6 +8256,7 @@ async function* streamBridgeSession(args) {
|
|
|
7935
8256
|
...seam.timeoutMs !== void 0 ? { timeoutMs: seam.timeoutMs } : {}
|
|
7936
8257
|
},
|
|
7937
8258
|
agent_profile: args.profile,
|
|
8259
|
+
...args.runtimeAttachments === void 0 ? {} : { runtime_attachments: { mcp: args.runtimeAttachments } },
|
|
7938
8260
|
messages
|
|
7939
8261
|
};
|
|
7940
8262
|
let turnText = "";
|
|
@@ -7943,6 +8265,7 @@ async function* streamBridgeSession(args) {
|
|
|
7943
8265
|
let sawTurnCostStatus = false;
|
|
7944
8266
|
let turnUsdKnown = true;
|
|
7945
8267
|
let turnKnownCostSubtotal = 0;
|
|
8268
|
+
let turnCostProvenance;
|
|
7946
8269
|
let turnEstimatedCostSubtotal = 0;
|
|
7947
8270
|
let turnInputTokens = 0;
|
|
7948
8271
|
let turnOutputTokens = 0;
|
|
@@ -7965,6 +8288,7 @@ async function* streamBridgeSession(args) {
|
|
|
7965
8288
|
profile: args.profile,
|
|
7966
8289
|
sessionId: args.sessionId,
|
|
7967
8290
|
body: requestBody,
|
|
8291
|
+
requiresRuntimeAttachments: args.runtimeAttachments !== void 0,
|
|
7968
8292
|
signal: turnController.signal,
|
|
7969
8293
|
run: activeRun,
|
|
7970
8294
|
maxReconnects: args.maxReconnects,
|
|
@@ -7989,9 +8313,22 @@ async function* streamBridgeSession(args) {
|
|
|
7989
8313
|
}
|
|
7990
8314
|
observedSystemFingerprint = chunk.systemFingerprint;
|
|
7991
8315
|
}
|
|
7992
|
-
if (chunk.content)
|
|
8316
|
+
if (chunk.content) {
|
|
8317
|
+
turnText += chunk.content;
|
|
8318
|
+
yield {
|
|
8319
|
+
kind: "progress",
|
|
8320
|
+
progress: {
|
|
8321
|
+
kind: "text_delta",
|
|
8322
|
+
text: chunk.content
|
|
8323
|
+
}
|
|
8324
|
+
};
|
|
8325
|
+
}
|
|
7993
8326
|
for (const step of chunk.toolCalls ?? []) {
|
|
7994
|
-
toolCalls.push(
|
|
8327
|
+
toolCalls.push({
|
|
8328
|
+
...step.callId === void 0 ? {} : { id: step.callId },
|
|
8329
|
+
name: step.toolName,
|
|
8330
|
+
arguments: step.args
|
|
8331
|
+
});
|
|
7995
8332
|
observation.activity.push({
|
|
7996
8333
|
at: Date.now(),
|
|
7997
8334
|
kind: "tool",
|
|
@@ -7999,6 +8336,15 @@ async function* streamBridgeSession(args) {
|
|
|
7999
8336
|
...describeToolArgs(step.args) ? { detail: describeToolArgs(step.args) } : {}
|
|
8000
8337
|
});
|
|
8001
8338
|
args.record(step);
|
|
8339
|
+
yield {
|
|
8340
|
+
kind: "progress",
|
|
8341
|
+
progress: {
|
|
8342
|
+
kind: "tool_call",
|
|
8343
|
+
toolName: step.toolName,
|
|
8344
|
+
...step.callId === void 0 ? {} : { toolCallId: step.callId },
|
|
8345
|
+
args: step.args
|
|
8346
|
+
}
|
|
8347
|
+
};
|
|
8002
8348
|
}
|
|
8003
8349
|
if (chunk.usage) {
|
|
8004
8350
|
sawTurnTokenUsage = true;
|
|
@@ -8022,6 +8368,7 @@ async function* streamBridgeSession(args) {
|
|
|
8022
8368
|
if (chunk.usage.promptCache.writeInput !== void 0) promptCache.writeTokens = (promptCache.writeTokens ?? 0) + chunk.usage.promptCache.writeInput;
|
|
8023
8369
|
}
|
|
8024
8370
|
}
|
|
8371
|
+
if (chunk.costProvenance !== void 0) turnCostProvenance = chunk.costProvenance;
|
|
8025
8372
|
if (chunk.costKnown !== void 0) {
|
|
8026
8373
|
sawTurnCostStatus = true;
|
|
8027
8374
|
if (!chunk.costKnown) turnUsdKnown = false;
|
|
@@ -8035,7 +8382,9 @@ async function* streamBridgeSession(args) {
|
|
|
8035
8382
|
usd += increment;
|
|
8036
8383
|
yield {
|
|
8037
8384
|
kind: "cost",
|
|
8038
|
-
|
|
8385
|
+
usdKnown: true,
|
|
8386
|
+
usd: increment,
|
|
8387
|
+
provenance: turnCostProvenance ?? "provider-receipt"
|
|
8039
8388
|
};
|
|
8040
8389
|
}
|
|
8041
8390
|
}
|
|
@@ -8080,9 +8429,10 @@ async function* streamBridgeSession(args) {
|
|
|
8080
8429
|
}) : {
|
|
8081
8430
|
kind: "cost",
|
|
8082
8431
|
usd: 0,
|
|
8083
|
-
usdKnown: false
|
|
8432
|
+
usdKnown: false,
|
|
8433
|
+
provenance: "uncaptured"
|
|
8084
8434
|
};
|
|
8085
|
-
if (priced.usdEstimated !== void 0) estimatedUsdCharged += priced.usdEstimated;
|
|
8435
|
+
if (priced.usdKnown === false && priced.usdEstimated !== void 0) estimatedUsdCharged += priced.usdEstimated;
|
|
8086
8436
|
usd += priced.usd;
|
|
8087
8437
|
yield priced;
|
|
8088
8438
|
}
|
|
@@ -8136,7 +8486,7 @@ const BRIDGE_BRUTAL_KILL_WAIT_MS = 150;
|
|
|
8136
8486
|
* cannot prove continuity fails instead of returning a plausible partial answer.
|
|
8137
8487
|
*/
|
|
8138
8488
|
async function* streamDurableBridgeRun(args) {
|
|
8139
|
-
await assertBridgeExecutionCapabilities(args.seam, args.signal);
|
|
8489
|
+
await assertBridgeExecutionCapabilities(args.seam, args.signal, args.requiresRuntimeAttachments);
|
|
8140
8490
|
let reconnects = 0;
|
|
8141
8491
|
let pendingUpstreamError;
|
|
8142
8492
|
for (;;) {
|
|
@@ -8215,7 +8565,7 @@ async function* streamDurableBridgeRun(args) {
|
|
|
8215
8565
|
* a process may restart behind the same URL, and a remembered capability from the prior process
|
|
8216
8566
|
* is not evidence about the process that will receive the next POST. The terminal receipt remains
|
|
8217
8567
|
* mandatory because the bridge can still restart between this GET and the run request. */
|
|
8218
|
-
async function assertBridgeExecutionCapabilities(seam, signal) {
|
|
8568
|
+
async function assertBridgeExecutionCapabilities(seam, signal, requiresRuntimeAttachments) {
|
|
8219
8569
|
const target = new URL(`${seam.bridgeUrl.replace(/\/$/, "")}/`);
|
|
8220
8570
|
const requestFn = target.protocol === "https:" ? request$1 : request;
|
|
8221
8571
|
const response = await new Promise((resolve, reject) => {
|
|
@@ -8256,6 +8606,10 @@ async function assertBridgeExecutionCapabilities(seam, signal) {
|
|
|
8256
8606
|
}
|
|
8257
8607
|
if (body.capabilities?.profileMaterialization !== bridgeProfileMaterializationSchema) throw new ValidationError(`bridgeExecutor: bridge does not advertise ${bridgeProfileMaterializationSchema}`);
|
|
8258
8608
|
if (body.capabilities?.usageCostProvenance !== bridgeUsageCostSchema) throw new ValidationError(`bridgeExecutor: bridge does not advertise ${bridgeUsageCostSchema}`);
|
|
8609
|
+
if (requiresRuntimeAttachments) {
|
|
8610
|
+
const attachments = body.capabilities?.runtimeAttachments;
|
|
8611
|
+
if (attachments === null || typeof attachments !== "object" || attachments.mcp !== true) throw new ValidationError(`bridgeExecutor: bridge at ${seam.bridgeUrl} does not advertise capabilities.runtimeAttachments.mcp; upgrade cli-bridge to a version that carries Runtime MCP attachments outside the bound AgentProfile`);
|
|
8612
|
+
}
|
|
8259
8613
|
}
|
|
8260
8614
|
/**
|
|
8261
8615
|
* POST one streamed turn to the cli-bridge over the `node:http(s)` core client
|
|
@@ -8865,6 +9219,7 @@ function applyBridgeCostReceipt(out, usage) {
|
|
|
8865
9219
|
if (cost === void 0 || provenance !== "provider-receipt" && provenance !== "billing-receipt" || estimatedCost !== void 0) throw new ValidationError("bridgeExecutor: known cost requires cost plus provider-receipt or billing-receipt provenance");
|
|
8866
9220
|
out.costKnown = true;
|
|
8867
9221
|
out.cost = cost;
|
|
9222
|
+
out.costProvenance = provenance;
|
|
8868
9223
|
return;
|
|
8869
9224
|
}
|
|
8870
9225
|
if (cost !== void 0) throw new ValidationError("bridgeExecutor: unknown cost cannot carry billed cost");
|
|
@@ -9315,13 +9670,14 @@ function createExecutor(config) {
|
|
|
9315
9670
|
}
|
|
9316
9671
|
}
|
|
9317
9672
|
};
|
|
9318
|
-
|
|
9319
|
-
...
|
|
9320
|
-
|
|
9321
|
-
|
|
9322
|
-
|
|
9673
|
+
const executor = sandboxExecutor({
|
|
9674
|
+
...spec,
|
|
9675
|
+
harness
|
|
9676
|
+
}, providerCtx);
|
|
9677
|
+
return inheritRuntimeOwnedExecutorAttestation(executor, {
|
|
9678
|
+
...executor,
|
|
9323
9679
|
runtime: providerSeam.runtime ?? provider.name
|
|
9324
|
-
};
|
|
9680
|
+
});
|
|
9325
9681
|
}
|
|
9326
9682
|
const profileForCreate = providerSeam.profileForCreate;
|
|
9327
9683
|
return providerAsExecutor(provider, {
|
|
@@ -9423,6 +9779,15 @@ function readOptionalAbortSignal(ctx, key, who) {
|
|
|
9423
9779
|
if (value === null || typeof value !== "object" || typeof value.aborted !== "boolean" || typeof value.addEventListener !== "function") throw new ValidationError(`${who} executor: seam "${key}" must be an AbortSignal`);
|
|
9424
9780
|
return value;
|
|
9425
9781
|
}
|
|
9782
|
+
/** Narrow the Runtime-owned MCP attachment seam. Absent means the run mounts nothing; a present
|
|
9783
|
+
* value must be a named map of MCP servers, never an empty one that would silently mount nothing. */
|
|
9784
|
+
function readOptionalMcpAttachments(ctx, key, who) {
|
|
9785
|
+
const value = ctx.seams[key];
|
|
9786
|
+
if (value === void 0) return void 0;
|
|
9787
|
+
const entries = value !== null && typeof value === "object" && !Array.isArray(value) ? Object.entries(value) : void 0;
|
|
9788
|
+
if (entries === void 0 || entries.length === 0 || entries.some(([, server]) => server === null || typeof server !== "object")) throw new ValidationError(`${who} executor: seam ${JSON.stringify(key)} must be a non-empty map of MCP servers`);
|
|
9789
|
+
return value;
|
|
9790
|
+
}
|
|
9426
9791
|
/** A leaf task is opaque (`unknown`). A string is the prompt verbatim; an object
|
|
9427
9792
|
* with a `prompt`/`content`/`task` string field uses it; otherwise it serializes.
|
|
9428
9793
|
* Module-exported (not package surface) so sibling leaf executors read a task
|
|
@@ -9472,10 +9837,12 @@ function routerProfileExecution(profile, seam, mode) {
|
|
|
9472
9837
|
if (enabled && !suppliedNames.has(name)) throw new ValidationError(`routerInlineExecutor: AgentProfile enables tool ${JSON.stringify(name)} but the caller supplied no matching schema`);
|
|
9473
9838
|
if (!enabled && suppliedNames.has(name)) throw new ValidationError(`routerInlineExecutor: AgentProfile disables tool ${JSON.stringify(name)}`);
|
|
9474
9839
|
}
|
|
9840
|
+
const { tokenLimits, ...rest } = settings;
|
|
9475
9841
|
return {
|
|
9476
9842
|
systemPrompt: renderRouterProfilePrompt(profile),
|
|
9477
9843
|
...profileEffort ? { reasoningEffort: profileEffort } : {},
|
|
9478
|
-
...
|
|
9844
|
+
...rest,
|
|
9845
|
+
tokenLimits: enforceTokenLimits(tokenLimits, "router", "routerInlineExecutor")
|
|
9479
9846
|
};
|
|
9480
9847
|
}
|
|
9481
9848
|
/** Resolve the one model id that will cross the Router boundary from the exact profile only. */
|
|
@@ -9758,56 +10125,61 @@ function assertValidSpend(spend, label) {
|
|
|
9758
10125
|
* channels; iterations come from `'iteration'` events. Pure; `ms` stays zero (the
|
|
9759
10126
|
* pool does not read wall-clock). */
|
|
9760
10127
|
function spendFromUsageEvents(events) {
|
|
9761
|
-
const
|
|
9762
|
-
|
|
9763
|
-
|
|
9764
|
-
|
|
9765
|
-
|
|
9766
|
-
|
|
9767
|
-
for (const ev of events) if (ev.kind === "tokens") {
|
|
9768
|
-
addTokenUsage(tokens, ev);
|
|
9769
|
-
if (ev.tokensKnown === false) tokensKnown = false;
|
|
9770
|
-
} else if (ev.kind === "cost") {
|
|
9771
|
-
usd += ev.usd;
|
|
9772
|
-
usdEstimated += ev.usdEstimated ?? 0;
|
|
9773
|
-
if (ev.usdKnown === false) usdKnown = false;
|
|
9774
|
-
} else iterations += 1;
|
|
10128
|
+
const totals = newUsageTotals();
|
|
10129
|
+
for (const ev of events) meterUsageEvent(totals, ev);
|
|
10130
|
+
return spendFromUsageTotals(totals);
|
|
10131
|
+
}
|
|
10132
|
+
/** Fresh zeroed {@link UsageTotals}. */
|
|
10133
|
+
function newUsageTotals() {
|
|
9775
10134
|
return {
|
|
9776
|
-
|
|
9777
|
-
|
|
9778
|
-
|
|
9779
|
-
|
|
9780
|
-
|
|
9781
|
-
|
|
9782
|
-
ms: 0
|
|
10135
|
+
tokens: zeroTokenUsage(),
|
|
10136
|
+
tokensKnown: true,
|
|
10137
|
+
usd: 0,
|
|
10138
|
+
usdEstimated: 0,
|
|
10139
|
+
usdKnown: true,
|
|
10140
|
+
iterations: 0
|
|
9783
10141
|
};
|
|
9784
10142
|
}
|
|
9785
|
-
|
|
9786
|
-
|
|
9787
|
-
|
|
9788
|
-
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
9792
|
-
|
|
9793
|
-
|
|
9794
|
-
|
|
9795
|
-
|
|
9796
|
-
|
|
9797
|
-
usd += ev.usd;
|
|
9798
|
-
|
|
9799
|
-
|
|
9800
|
-
|
|
10143
|
+
/**
|
|
10144
|
+
* Fold ONE usage event into running totals — the single place that decides which event kinds
|
|
10145
|
+
* meter. `progress` carries observed output rather than accounting, so it meters nothing; only
|
|
10146
|
+
* `iteration` advances the iteration count.
|
|
10147
|
+
*/
|
|
10148
|
+
function meterUsageEvent(totals, ev) {
|
|
10149
|
+
if (ev.kind === "tokens") {
|
|
10150
|
+
addTokenUsage(totals.tokens, ev);
|
|
10151
|
+
if (ev.tokensKnown === false) totals.tokensKnown = false;
|
|
10152
|
+
return;
|
|
10153
|
+
}
|
|
10154
|
+
if (ev.kind === "cost") {
|
|
10155
|
+
totals.usd += ev.usd;
|
|
10156
|
+
if (ev.usdKnown === false) {
|
|
10157
|
+
totals.usdEstimated += ev.usdEstimated ?? 0;
|
|
10158
|
+
totals.usdKnown = false;
|
|
10159
|
+
}
|
|
10160
|
+
return;
|
|
10161
|
+
}
|
|
10162
|
+
if (ev.kind === "iteration") totals.iterations += 1;
|
|
10163
|
+
}
|
|
10164
|
+
/** Project folded totals onto the conserved-pool `Spend`. `ms` stays zero — the pool does not
|
|
10165
|
+
* read wall-clock. */
|
|
10166
|
+
function spendFromUsageTotals(totals) {
|
|
9801
10167
|
return {
|
|
9802
|
-
iterations,
|
|
9803
|
-
tokens,
|
|
9804
|
-
...tokensKnown ? {} : { tokensKnown: false },
|
|
9805
|
-
usd,
|
|
9806
|
-
...usdKnown ? {} : { usdKnown: false },
|
|
9807
|
-
...usdEstimated > 0 ? { usdEstimated } : {},
|
|
10168
|
+
iterations: totals.iterations,
|
|
10169
|
+
tokens: totals.tokens,
|
|
10170
|
+
...totals.tokensKnown ? {} : { tokensKnown: false },
|
|
10171
|
+
usd: totals.usd,
|
|
10172
|
+
...totals.usdKnown ? {} : { usdKnown: false },
|
|
10173
|
+
...totals.usdEstimated > 0 ? { usdEstimated: totals.usdEstimated } : {},
|
|
9808
10174
|
ms: 0
|
|
9809
10175
|
};
|
|
9810
10176
|
}
|
|
10177
|
+
async function foldUsage(events) {
|
|
10178
|
+
if (Array.isArray(events)) return spendFromUsageEvents(events);
|
|
10179
|
+
const totals = newUsageTotals();
|
|
10180
|
+
for await (const ev of events) meterUsageEvent(totals, ev);
|
|
10181
|
+
return spendFromUsageTotals(totals);
|
|
10182
|
+
}
|
|
9811
10183
|
/**
|
|
9812
10184
|
* Create a conserved reservation pool from a root `Budget`. `now()` is injected so the
|
|
9813
10185
|
* deadline readout is deterministic; defaults to `Date.now` for non-test callers. The
|
|
@@ -10610,7 +10982,7 @@ function createScope(args) {
|
|
|
10610
10982
|
spec = prepared.spec;
|
|
10611
10983
|
identity = prepared.identity;
|
|
10612
10984
|
if (opts.key !== void 0 && !isCompleteIdentity(identity)) {
|
|
10613
|
-
args.pool.reconcile(reservation.ticket, zeroSpend
|
|
10985
|
+
args.pool.reconcile(reservation.ticket, zeroSpend());
|
|
10614
10986
|
permit.release();
|
|
10615
10987
|
return {
|
|
10616
10988
|
ok: false,
|
|
@@ -10621,7 +10993,7 @@ function createScope(args) {
|
|
|
10621
10993
|
if (!outcome.succeeded) throw new ValidationError(`scope.spawn: ${outcome.error}`);
|
|
10622
10994
|
resolved = outcome;
|
|
10623
10995
|
} catch (error) {
|
|
10624
|
-
args.pool.reconcile(reservation.ticket, zeroSpend
|
|
10996
|
+
args.pool.reconcile(reservation.ticket, zeroSpend());
|
|
10625
10997
|
permit.release();
|
|
10626
10998
|
throw error;
|
|
10627
10999
|
}
|
|
@@ -10686,7 +11058,7 @@ function createScope(args) {
|
|
|
10686
11058
|
label: opts.label,
|
|
10687
11059
|
...opts.assignmentId === void 0 ? {} : { assignmentId: opts.assignmentId },
|
|
10688
11060
|
...opts.key !== void 0 ? { key: opts.key } : {},
|
|
10689
|
-
spent: zeroSpend
|
|
11061
|
+
spent: zeroSpend(),
|
|
10690
11062
|
settled: void 0,
|
|
10691
11063
|
delivered: false,
|
|
10692
11064
|
executorDone: false,
|
|
@@ -10696,7 +11068,10 @@ function createScope(args) {
|
|
|
10696
11068
|
lastActivityAt: startedAt,
|
|
10697
11069
|
...executor.deliver ? { deliver: (message) => executor.deliver?.(message) !== false } : {},
|
|
10698
11070
|
...executor.progress ? { readProgress: executor.progress.bind(executor) } : {},
|
|
10699
|
-
...executor.traceSource ? { readTraceSource: executor.traceSource.bind(executor) } : {}
|
|
11071
|
+
...executor.traceSource ? { readTraceSource: executor.traceSource.bind(executor) } : {},
|
|
11072
|
+
...executor.interactive ? { readInteractive: executor.interactive.bind(executor) } : {},
|
|
11073
|
+
...executor.cancel ? { requestCancel: executor.cancel.bind(executor) } : {},
|
|
11074
|
+
abortChild: (reason) => controller.abort(reason)
|
|
10700
11075
|
};
|
|
10701
11076
|
children.set(id, live);
|
|
10702
11077
|
if (opts.key !== void 0) keyed.set(opts.key, {
|
|
@@ -10704,7 +11079,8 @@ function createScope(args) {
|
|
|
10704
11079
|
id,
|
|
10705
11080
|
identity
|
|
10706
11081
|
});
|
|
10707
|
-
const
|
|
11082
|
+
const profileRef = contentAddress(spec.profile);
|
|
11083
|
+
const spawnCommitted = args.blobs.put(profileRef, spec.profile).then(() => args.journal.appendEvent(args.root, {
|
|
10708
11084
|
kind: "spawned",
|
|
10709
11085
|
id,
|
|
10710
11086
|
parent: args.parentId,
|
|
@@ -10715,9 +11091,10 @@ function createScope(args) {
|
|
|
10715
11091
|
runtime: executor.runtime,
|
|
10716
11092
|
...ownedTreeRoot === void 0 ? {} : { ownedTreeRoot },
|
|
10717
11093
|
...identity ? { identity } : {},
|
|
11094
|
+
profileRef,
|
|
10718
11095
|
seq: ordinal,
|
|
10719
11096
|
at: new Date(now()).toISOString()
|
|
10720
|
-
}).then(async () => {
|
|
11097
|
+
})).then(async () => {
|
|
10721
11098
|
if (args.workerTraceUnpropagated === void 0 || workerTrace === void 0) return;
|
|
10722
11099
|
await args.journal.appendEvent(args.root, {
|
|
10723
11100
|
kind: "trace-unpropagated",
|
|
@@ -10850,7 +11227,9 @@ function createScope(args) {
|
|
|
10850
11227
|
runtime: executor.runtime,
|
|
10851
11228
|
...identity ? { identity } : {},
|
|
10852
11229
|
budget: opts.budget,
|
|
10853
|
-
depth: args.depth
|
|
11230
|
+
depth: args.depth,
|
|
11231
|
+
attemptId,
|
|
11232
|
+
startedAt
|
|
10854
11233
|
}
|
|
10855
11234
|
}, { signal: args.signal });
|
|
10856
11235
|
live.settled = runChild(live, executor, controller, task, opts, args.pool, reservation.ticket, args.blobs, now, materializationCommitted, {
|
|
@@ -10873,7 +11252,7 @@ function createScope(args) {
|
|
|
10873
11252
|
permit.release();
|
|
10874
11253
|
clearChildDeadline?.();
|
|
10875
11254
|
if (cascadeAbort) args.signal.removeEventListener("abort", cascadeAbort);
|
|
10876
|
-
args.pool.reconcile(reservation.ticket, zeroSpend
|
|
11255
|
+
args.pool.reconcile(reservation.ticket, zeroSpend());
|
|
10877
11256
|
throw err;
|
|
10878
11257
|
}
|
|
10879
11258
|
}
|
|
@@ -10967,12 +11346,13 @@ function createScope(args) {
|
|
|
10967
11346
|
id,
|
|
10968
11347
|
status: "waiting",
|
|
10969
11348
|
runtime: "wait",
|
|
11349
|
+
abortChild: (reason) => waitAbort.abort(reason),
|
|
10970
11350
|
budget: {
|
|
10971
11351
|
maxIterations: 0,
|
|
10972
11352
|
maxTokens: 0
|
|
10973
11353
|
},
|
|
10974
11354
|
label: opts.label,
|
|
10975
|
-
spent: zeroSpend
|
|
11355
|
+
spent: zeroSpend(),
|
|
10976
11356
|
settled: void 0,
|
|
10977
11357
|
delivered: false,
|
|
10978
11358
|
executorDone: false,
|
|
@@ -11045,7 +11425,7 @@ function createScope(args) {
|
|
|
11045
11425
|
kind: "done",
|
|
11046
11426
|
out: resolution.outcome,
|
|
11047
11427
|
outRef,
|
|
11048
|
-
spent: zeroSpend
|
|
11428
|
+
spent: zeroSpend(),
|
|
11049
11429
|
trace: {
|
|
11050
11430
|
status: "unavailable",
|
|
11051
11431
|
reason: "not-an-executor"
|
|
@@ -11096,6 +11476,18 @@ function createScope(args) {
|
|
|
11096
11476
|
...child.spent.usdKnown === false ? { usdKnown: false } : {}
|
|
11097
11477
|
}, fromExecutor, opts.now ?? now(), opts.stallAfterMs ?? 18e4);
|
|
11098
11478
|
}
|
|
11479
|
+
async function cancel(nodeId, request) {
|
|
11480
|
+
const child = children.get(nodeId);
|
|
11481
|
+
if (!child) throw new ValidationError(`scope.cancel: unknown node ${JSON.stringify(nodeId)}`);
|
|
11482
|
+
if (child.requestCancel) return await child.requestCancel(request);
|
|
11483
|
+
child.abortChild("cancelled");
|
|
11484
|
+
return {
|
|
11485
|
+
status: "unknown",
|
|
11486
|
+
effect: "cancel_requested",
|
|
11487
|
+
observedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11488
|
+
detail: `executor runtime ${JSON.stringify(child.runtime ?? "unknown")} exposes no cancellation operation; the child was aborted locally`
|
|
11489
|
+
};
|
|
11490
|
+
}
|
|
11099
11491
|
function traceSource(nodeId) {
|
|
11100
11492
|
const child = children.get(nodeId);
|
|
11101
11493
|
if (!child) return void 0;
|
|
@@ -11105,6 +11497,24 @@ function createScope(args) {
|
|
|
11105
11497
|
return;
|
|
11106
11498
|
}
|
|
11107
11499
|
}
|
|
11500
|
+
function terminalNodeStatus(status) {
|
|
11501
|
+
return status === "done" || status === "failed" || status === "cancelled";
|
|
11502
|
+
}
|
|
11503
|
+
function interactive(nodeId) {
|
|
11504
|
+
const child = children.get(nodeId);
|
|
11505
|
+
if (!child) return noInteractiveSession("unknown-node");
|
|
11506
|
+
if (child.wait || child.executorDone || terminalNodeStatus(child.status)) return noInteractiveSession("not-live");
|
|
11507
|
+
if (!child.readInteractive) return noInteractiveSession("executor-exposes-no-interactive-session");
|
|
11508
|
+
let reported;
|
|
11509
|
+
try {
|
|
11510
|
+
reported = child.readInteractive();
|
|
11511
|
+
} catch {
|
|
11512
|
+
return noInteractiveSession("executor-exposes-no-interactive-session");
|
|
11513
|
+
}
|
|
11514
|
+
if (reported?.status === "unavailable" && reported.reason) return reported;
|
|
11515
|
+
if (reported?.status === "available" && reported.handle) return reported;
|
|
11516
|
+
return noInteractiveSession("executor-exposes-no-interactive-session");
|
|
11517
|
+
}
|
|
11108
11518
|
async function meterInternal(spend, detail, providerModel, accountingOnly = false) {
|
|
11109
11519
|
if (args.signal.aborted) throw new ValidationError("scope.meter: cannot record new driver work after scope abort");
|
|
11110
11520
|
const seq = meterSeq++;
|
|
@@ -11152,6 +11562,8 @@ function createScope(args) {
|
|
|
11152
11562
|
wait,
|
|
11153
11563
|
progress,
|
|
11154
11564
|
traceSource,
|
|
11565
|
+
interactive,
|
|
11566
|
+
cancel,
|
|
11155
11567
|
signal: args.signal,
|
|
11156
11568
|
meter: (spend, detail) => meterInternal(spend, detail),
|
|
11157
11569
|
...resume ? { resume } : {},
|
|
@@ -11164,7 +11576,13 @@ function createScope(args) {
|
|
|
11164
11576
|
get workerCapacity() {
|
|
11165
11577
|
return {
|
|
11166
11578
|
live: liveWorkerCapacity.live,
|
|
11167
|
-
freeSlots: freeSlots(liveWorkerCapacity.live, liveWorkerCapacity.max)
|
|
11579
|
+
freeSlots: freeSlots(liveWorkerCapacity.live, liveWorkerCapacity.max),
|
|
11580
|
+
unconfirmed: Object.freeze([...children.values()].filter((child) => (child.status === "done" || child.status === "failed" || child.status === "cancelled") && !child.cleanupConfirmed).map((child) => Object.freeze({
|
|
11581
|
+
id: child.id,
|
|
11582
|
+
label: child.label,
|
|
11583
|
+
runtime: child.runtime,
|
|
11584
|
+
status: child.status
|
|
11585
|
+
})))
|
|
11168
11586
|
};
|
|
11169
11587
|
}
|
|
11170
11588
|
};
|
|
@@ -11404,7 +11822,9 @@ async function finalizeSettlement(child, settlement, seq, args, now) {
|
|
|
11404
11822
|
status: "down",
|
|
11405
11823
|
reason: settlement.reason,
|
|
11406
11824
|
infra: settlement.infra,
|
|
11407
|
-
spent: child.spent
|
|
11825
|
+
spent: child.spent,
|
|
11826
|
+
restartCount: settlement.restartCount,
|
|
11827
|
+
...settledNodeEvidence(child, settlement, settledAt)
|
|
11408
11828
|
}
|
|
11409
11829
|
}, { signal: args.signal });
|
|
11410
11830
|
return {
|
|
@@ -11457,7 +11877,8 @@ async function finalizeSettlement(child, settlement, seq, args, now) {
|
|
|
11457
11877
|
outRef: settlement.outRef,
|
|
11458
11878
|
score: settlement.verdict?.score,
|
|
11459
11879
|
valid: settlement.verdict?.valid,
|
|
11460
|
-
spent: settlement.spent
|
|
11880
|
+
spent: settlement.spent,
|
|
11881
|
+
...settledNodeEvidence(child, settlement, settledAt)
|
|
11461
11882
|
}
|
|
11462
11883
|
}, { signal: args.signal });
|
|
11463
11884
|
return {
|
|
@@ -11473,6 +11894,26 @@ async function finalizeSettlement(child, settlement, seq, args, now) {
|
|
|
11473
11894
|
seq
|
|
11474
11895
|
};
|
|
11475
11896
|
}
|
|
11897
|
+
/**
|
|
11898
|
+
* The evidence a settled node carries beyond its status: the receipts that name what actually
|
|
11899
|
+
* ran, the own-inference spend the parent tree re-homes as a `metered` event, and the wall-clock
|
|
11900
|
+
* window. One builder feeds BOTH terminal paths, so an observer never sees a `down` node
|
|
11901
|
+
* described in different terms from a `done` one. Every field is omitted when the fact is
|
|
11902
|
+
* absent — an unreported receipt must not read as an empty one. Snapshots are detached because
|
|
11903
|
+
* an observer may serialize them after the live child has moved on.
|
|
11904
|
+
*/
|
|
11905
|
+
function settledNodeEvidence(child, settlement, settledAt) {
|
|
11906
|
+
return {
|
|
11907
|
+
runtime: child.runtime,
|
|
11908
|
+
startedAt: child.startedAt,
|
|
11909
|
+
settledAt,
|
|
11910
|
+
...settlement.metered ? { metered: detachedSnapshot(settlement.metered, "metered") } : {},
|
|
11911
|
+
...child.providerModel ? { providerModel: detachedSnapshot(child.providerModel, "provider model evidence") } : {},
|
|
11912
|
+
...child.materialization ? { materialization: detachedSnapshot(child.materialization, "materialization receipt") } : {},
|
|
11913
|
+
...child.executionBindings.length > 0 ? { executionBindings: detachedSnapshot([...child.executionBindings], "execution binding receipts") } : {},
|
|
11914
|
+
trace: detachedSnapshot(settlement.trace, "worker trace evidence")
|
|
11915
|
+
};
|
|
11916
|
+
}
|
|
11476
11917
|
/** Journal a wait-state's settlement as a `woken` event and project it onto the same `Settled`
|
|
11477
11918
|
* the driver branches on. `by` names WHY it woke — `fired` / `timeout` / `cancelled` — which is
|
|
11478
11919
|
* the fact a resumed reader needs and cannot recover from a payload it may never fetch. */
|
|
@@ -11784,30 +12225,20 @@ function freezeCorrelation(value) {
|
|
|
11784
12225
|
* now reconciles its real partial spend instead of refunding work the provider already billed.
|
|
11785
12226
|
*/
|
|
11786
12227
|
async function foldStream(stream, onProgress, signal) {
|
|
11787
|
-
const
|
|
11788
|
-
let tokensKnown = true;
|
|
11789
|
-
let usd = 0;
|
|
11790
|
-
let usdKnown = true;
|
|
11791
|
-
let iterations = 0;
|
|
12228
|
+
const totals = newUsageTotals();
|
|
11792
12229
|
const iterator = stream[Symbol.asyncIterator]();
|
|
11793
12230
|
try {
|
|
11794
12231
|
for (;;) {
|
|
11795
12232
|
const next = signal ? await awaitAbortable(Promise.resolve(iterator.next()), signal) : await iterator.next();
|
|
11796
12233
|
if (next.done) break;
|
|
11797
12234
|
const ev = next.value;
|
|
11798
|
-
|
|
11799
|
-
addTokenUsage(tokens, ev);
|
|
11800
|
-
if (ev.tokensKnown === false) tokensKnown = false;
|
|
11801
|
-
} else if (ev.kind === "cost") {
|
|
11802
|
-
usd += ev.usd;
|
|
11803
|
-
if (ev.usdKnown === false) usdKnown = false;
|
|
11804
|
-
} else iterations += 1;
|
|
12235
|
+
meterUsageEvent(totals, ev);
|
|
11805
12236
|
onProgress?.({
|
|
11806
|
-
iterations,
|
|
11807
|
-
tokens: cloneTokenUsage(tokens),
|
|
11808
|
-
...tokensKnown ? {} : { tokensKnown: false },
|
|
11809
|
-
usd,
|
|
11810
|
-
...usdKnown ? {} : { usdKnown: false },
|
|
12237
|
+
iterations: totals.iterations,
|
|
12238
|
+
tokens: cloneTokenUsage(totals.tokens),
|
|
12239
|
+
...totals.tokensKnown ? {} : { tokensKnown: false },
|
|
12240
|
+
usd: totals.usd,
|
|
12241
|
+
...totals.usdKnown ? {} : { usdKnown: false },
|
|
11811
12242
|
ms: 0
|
|
11812
12243
|
});
|
|
11813
12244
|
}
|
|
@@ -11815,14 +12246,7 @@ async function foldStream(stream, onProgress, signal) {
|
|
|
11815
12246
|
Promise.resolve(iterator.return?.()).catch(() => void 0);
|
|
11816
12247
|
throw error;
|
|
11817
12248
|
}
|
|
11818
|
-
return
|
|
11819
|
-
iterations,
|
|
11820
|
-
tokens,
|
|
11821
|
-
...tokensKnown ? {} : { tokensKnown: false },
|
|
11822
|
-
usd,
|
|
11823
|
-
...usdKnown ? {} : { usdKnown: false },
|
|
11824
|
-
ms: 0
|
|
11825
|
-
};
|
|
12249
|
+
return spendFromUsageTotals(totals);
|
|
11826
12250
|
}
|
|
11827
12251
|
/** Usage events carry measured increments; the terminal artifact carries whether a provider omitted
|
|
11828
12252
|
* a whole accounting channel. Preserve those unknowns on the common streaming path. */
|
|
@@ -11883,13 +12307,12 @@ function downRecord(reason, infra, trace, metered, providerModel) {
|
|
|
11883
12307
|
...metered ? { metered } : {}
|
|
11884
12308
|
};
|
|
11885
12309
|
}
|
|
11886
|
-
|
|
11887
|
-
|
|
11888
|
-
|
|
11889
|
-
|
|
11890
|
-
|
|
11891
|
-
|
|
11892
|
-
};
|
|
12310
|
+
/** The one place an absent interactive process is spelled, so every refusal reads the same. */
|
|
12311
|
+
function noInteractiveSession(reason) {
|
|
12312
|
+
return Object.freeze({
|
|
12313
|
+
status: "unavailable",
|
|
12314
|
+
reason
|
|
12315
|
+
});
|
|
11893
12316
|
}
|
|
11894
12317
|
function isAsyncIterable(value) {
|
|
11895
12318
|
return typeof value === "object" && value !== null && typeof value[Symbol.asyncIterator] === "function";
|
|
@@ -12008,7 +12431,7 @@ const driverExecutorFactory = (rawSpec, ctx) => {
|
|
|
12008
12431
|
meteredSpend = nonZeroOrUndef(sumMetered(events));
|
|
12009
12432
|
accounting = {
|
|
12010
12433
|
reported: childWork,
|
|
12011
|
-
reservation: addSpend
|
|
12434
|
+
reservation: addSpend(childWork, meteredSpend ?? zeroSpend())
|
|
12012
12435
|
};
|
|
12013
12436
|
const verdict = deriveDeliveryVerdict(settled, out);
|
|
12014
12437
|
artifact = {
|
|
@@ -12092,12 +12515,7 @@ function isSettled(ev) {
|
|
|
12092
12515
|
/** Sum the conserved spend over the nested tree's settled events — the honest per-channel
|
|
12093
12516
|
* roll-up of the whole sub-tree's child WORK. */
|
|
12094
12517
|
function sumSpend(settled) {
|
|
12095
|
-
const total =
|
|
12096
|
-
iterations: 0,
|
|
12097
|
-
tokens: zeroTokenUsage(),
|
|
12098
|
-
usd: 0,
|
|
12099
|
-
ms: 0
|
|
12100
|
-
};
|
|
12518
|
+
const total = zeroSpend();
|
|
12101
12519
|
for (const ev of settled) {
|
|
12102
12520
|
total.iterations += ev.spent.iterations;
|
|
12103
12521
|
addTokenUsage(total.tokens, ev.spent.tokens);
|
|
@@ -12112,12 +12530,7 @@ function sumSpend(settled) {
|
|
|
12112
12530
|
* own turns + any sub-driver inference already re-homed into this tree). Re-homed up to the parent
|
|
12113
12531
|
* as one `metered` event; never reconciled (already pool-debited live via `observe`). */
|
|
12114
12532
|
function sumMetered(events) {
|
|
12115
|
-
const total =
|
|
12116
|
-
iterations: 0,
|
|
12117
|
-
tokens: zeroTokenUsage(),
|
|
12118
|
-
usd: 0,
|
|
12119
|
-
ms: 0
|
|
12120
|
-
};
|
|
12533
|
+
const total = zeroSpend();
|
|
12121
12534
|
for (const ev of events) {
|
|
12122
12535
|
if (ev.kind !== "metered") continue;
|
|
12123
12536
|
total.iterations += ev.spend.iterations;
|
|
@@ -12129,28 +12542,6 @@ function sumMetered(events) {
|
|
|
12129
12542
|
}
|
|
12130
12543
|
return total;
|
|
12131
12544
|
}
|
|
12132
|
-
function zeroSpend() {
|
|
12133
|
-
return {
|
|
12134
|
-
iterations: 0,
|
|
12135
|
-
tokens: zeroTokenUsage(),
|
|
12136
|
-
usd: 0,
|
|
12137
|
-
ms: 0
|
|
12138
|
-
};
|
|
12139
|
-
}
|
|
12140
|
-
function addSpend$1(a, b) {
|
|
12141
|
-
return {
|
|
12142
|
-
iterations: a.iterations + b.iterations,
|
|
12143
|
-
tokens: (() => {
|
|
12144
|
-
const tokens = cloneTokenUsage(a.tokens);
|
|
12145
|
-
addTokenUsage(tokens, b.tokens);
|
|
12146
|
-
return tokens;
|
|
12147
|
-
})(),
|
|
12148
|
-
...a.tokensKnown === false || b.tokensKnown === false ? { tokensKnown: false } : {},
|
|
12149
|
-
usd: a.usd + b.usd,
|
|
12150
|
-
...a.usdKnown === false || b.usdKnown === false ? { usdKnown: false } : {},
|
|
12151
|
-
ms: a.ms + b.ms
|
|
12152
|
-
};
|
|
12153
|
-
}
|
|
12154
12545
|
/** An all-zero spend that carries an UNKNOWN marker counts as non-zero: a sub-driver whose turns
|
|
12155
12546
|
* went unmeasured did real work, and dropping its `metered` event here would re-hide upstream the
|
|
12156
12547
|
* very turn the driver refused to skip. */
|
|
@@ -12173,7 +12564,7 @@ async function safeRollup(journal, nestedRoot) {
|
|
|
12173
12564
|
metered,
|
|
12174
12565
|
accounting: {
|
|
12175
12566
|
reported: childWork,
|
|
12176
|
-
reservation: addSpend
|
|
12567
|
+
reservation: addSpend(childWork, metered ?? zeroSpend())
|
|
12177
12568
|
}
|
|
12178
12569
|
};
|
|
12179
12570
|
} catch {
|
|
@@ -12686,6 +13077,8 @@ function createSupervisor() {
|
|
|
12686
13077
|
ok: false,
|
|
12687
13078
|
error: new RuntimeRunStateError("supervisor: root execution did not start")
|
|
12688
13079
|
};
|
|
13080
|
+
let teardownUnconfirmed = [];
|
|
13081
|
+
let teardownSeq = 0;
|
|
12689
13082
|
let executionAborted = controller.signal.aborted;
|
|
12690
13083
|
let allChildrenDownAtSettle = false;
|
|
12691
13084
|
let downCountAtSettle = 0;
|
|
@@ -12707,7 +13100,16 @@ function createSupervisor() {
|
|
|
12707
13100
|
clearRootDeadline?.();
|
|
12708
13101
|
const settleGraceMs = actOutcome.ok === false && !controller.signal.aborted ? boundedSettleGrace(opts.childSettleGraceMs, rootDeadlineAtMs, now) : 0;
|
|
12709
13102
|
try {
|
|
12710
|
-
await drainLiveChildren(openScope, controller, settleGraceMs);
|
|
13103
|
+
teardownUnconfirmed = await drainLiveChildren(openScope, controller, settleGraceMs);
|
|
13104
|
+
for (const node of teardownUnconfirmed) await opts.journal.appendEvent(opts.runId, {
|
|
13105
|
+
kind: "teardown-unconfirmed",
|
|
13106
|
+
id: node.id,
|
|
13107
|
+
label: node.label,
|
|
13108
|
+
runtime: node.runtime,
|
|
13109
|
+
status: node.status,
|
|
13110
|
+
seq: teardownSeq++,
|
|
13111
|
+
at: new Date(now()).toISOString()
|
|
13112
|
+
});
|
|
12711
13113
|
} catch (error) {
|
|
12712
13114
|
if (actOutcome?.ok !== false) actOutcome = {
|
|
12713
13115
|
ok: false,
|
|
@@ -12741,6 +13143,7 @@ function createSupervisor() {
|
|
|
12741
13143
|
tree,
|
|
12742
13144
|
spentTotal,
|
|
12743
13145
|
providerModel,
|
|
13146
|
+
...teardownUnconfirmed.length > 0 ? { teardownUnconfirmed } : {},
|
|
12744
13147
|
...gaps.length > 0 ? { spendGaps: gaps } : {},
|
|
12745
13148
|
...isNonEmptySpend(driverInference) ? { spentBreakdown: {
|
|
12746
13149
|
driverInference,
|
|
@@ -12759,6 +13162,7 @@ function createSupervisor() {
|
|
|
12759
13162
|
downCount: breaker.downCount(),
|
|
12760
13163
|
spentTotal,
|
|
12761
13164
|
providerModel,
|
|
13165
|
+
...teardownUnconfirmed.length > 0 ? { teardownUnconfirmed } : {},
|
|
12762
13166
|
...gaps.length > 0 ? { spendGaps: gaps } : {}
|
|
12763
13167
|
};
|
|
12764
13168
|
const lifecycle = classifyNoWinner(executionAborted, pool, opts, breaker, deadlineExceeded, allChildrenDownAtSettle, downCountAtSettle);
|
|
@@ -12903,10 +13307,7 @@ function wrapJournalForBreaker(journal, breaker) {
|
|
|
12903
13307
|
*/
|
|
12904
13308
|
async function drainLiveChildren(scope, controller, settleGraceMs = 0) {
|
|
12905
13309
|
const view = scope.view;
|
|
12906
|
-
if (!(view.inFlight > 0 || view.waiting > 0))
|
|
12907
|
-
if (scope.workerCapacity.live > 0) throw new RuntimeRunStateError(`supervisor: cleanup ended with ${scope.workerCapacity.live} executor resource(s) not confirmed destroyed`);
|
|
12908
|
-
return;
|
|
12909
|
-
}
|
|
13310
|
+
if (!(view.inFlight > 0 || view.waiting > 0)) return unconfirmedTeardowns(scope);
|
|
12910
13311
|
let graceTimer;
|
|
12911
13312
|
if (settleGraceMs > 0 && !controller.signal.aborted) {
|
|
12912
13313
|
graceTimer = setTimeout(() => controller.abort("root driver failed; child settle grace expired"), settleGraceMs);
|
|
@@ -12918,7 +13319,26 @@ async function drainLiveChildren(scope, controller, settleGraceMs = 0) {
|
|
|
12918
13319
|
if (graceTimer !== void 0) clearTimeout(graceTimer);
|
|
12919
13320
|
}
|
|
12920
13321
|
const after = scope.view;
|
|
12921
|
-
if (after.inFlight > 0 || after.waiting > 0
|
|
13322
|
+
if (after.inFlight > 0 || after.waiting > 0) throw new RuntimeRunStateError(`supervisor: cleanup ended with ${after.inFlight} running, ${after.waiting} waiting, and ` + describeUnconfirmed(scope));
|
|
13323
|
+
return unconfirmedTeardowns(scope);
|
|
13324
|
+
}
|
|
13325
|
+
/**
|
|
13326
|
+
* The settled children whose executor teardown was never acknowledged.
|
|
13327
|
+
*
|
|
13328
|
+
* They still hold their capacity slot — the ledger stays poisoned, so replacement work can never
|
|
13329
|
+
* exceed the physical live count — but every one of them has already reached a terminal state and
|
|
13330
|
+
* journaled its work. That is evidence about an EXECUTOR, not a cause of run failure, so the
|
|
13331
|
+
* barrier NAMES them and lets the run reach its real terminal state. Live work after the drain is
|
|
13332
|
+
* a different fault and still fails loud.
|
|
13333
|
+
*/
|
|
13334
|
+
function unconfirmedTeardowns(scope) {
|
|
13335
|
+
return scope.workerCapacity.unconfirmed;
|
|
13336
|
+
}
|
|
13337
|
+
/** The unconfirmed set as one error clause: the count plus the node ids behind it. One integer is
|
|
13338
|
+
* not actionable after a six-hour run. */
|
|
13339
|
+
function describeUnconfirmed(scope) {
|
|
13340
|
+
const named = scope.workerCapacity.unconfirmed.map((node) => `${node.id} (${node.label}, ${node.runtime}, ${node.status})`).join(", ");
|
|
13341
|
+
return `${scope.workerCapacity.live} executor resource(s) not confirmed destroyed${named.length > 0 ? `: ${named}` : ""}`;
|
|
12922
13342
|
}
|
|
12923
13343
|
/** The settle window a failed driver's children actually get: the caller's grace, never past the
|
|
12924
13344
|
* run's own deadline. `0` (the default) keeps the historical immediate cascade. */
|
|
@@ -13083,23 +13503,6 @@ function accumulate(a, b) {
|
|
|
13083
13503
|
if (b.usdEstimated !== void 0) a.usdEstimated = (a.usdEstimated ?? 0) + b.usdEstimated;
|
|
13084
13504
|
a.ms += b.ms;
|
|
13085
13505
|
}
|
|
13086
|
-
/** Sum two conserved-spend tallies per channel — the child-work journal sum + the drivers' own
|
|
13087
|
-
* metered inference, so `spentTotal` is the true cost of the run. */
|
|
13088
|
-
function addSpend(a, b) {
|
|
13089
|
-
return {
|
|
13090
|
-
iterations: a.iterations + b.iterations,
|
|
13091
|
-
tokens: (() => {
|
|
13092
|
-
const tokens = cloneTokenUsage(a.tokens);
|
|
13093
|
-
addTokenUsage(tokens, b.tokens);
|
|
13094
|
-
return tokens;
|
|
13095
|
-
})(),
|
|
13096
|
-
...a.tokensKnown === false || b.tokensKnown === false ? { tokensKnown: false } : {},
|
|
13097
|
-
usd: a.usd + b.usd,
|
|
13098
|
-
...a.usdKnown === false || b.usdKnown === false ? { usdKnown: false } : {},
|
|
13099
|
-
...usdEstimatedOf(a, b),
|
|
13100
|
-
ms: a.ms + b.ms
|
|
13101
|
-
};
|
|
13102
|
-
}
|
|
13103
13506
|
/** True when any driver metered inference this run (so the winner carries a `spentBreakdown`).
|
|
13104
13507
|
* Checks every channel `addSpend` sums — including `ms` — so the gate stays consistent with the
|
|
13105
13508
|
* total even though the coordination driver currently stamps `ms: 0`. */
|
|
@@ -13107,6 +13510,6 @@ function isNonEmptySpend(s) {
|
|
|
13107
13510
|
return s.iterations > 0 || s.tokens.input > 0 || s.tokens.output > 0 || s.usd > 0 || s.ms > 0 || s.tokensKnown === false || s.usdKnown === false;
|
|
13108
13511
|
}
|
|
13109
13512
|
//#endregion
|
|
13110
|
-
export {
|
|
13513
|
+
export { DEFAULT_STALL_AFTER_MS as $, localHarnessExecutable as $t, createBudgetPool as A, buildRuntimeEventOtelSpans as At, createExecutorRegistry as B, createRuntimeEventCollector as Bt, effectiveConcurrency as C, createPropagatingTraceEmitter as Ct, DEFAULT_SUCCESSFUL_SHUTDOWN_MS as D, INTELLIGENCE_WIRE_VERSION as Dt, rollingDispatch as E, traceContextToEnv as Et, bridgeRuntimeAttachmentsKey as F, generateSpanId as Ft, workerTraceEnv as G, runSettledCommand as Gt, createWorktreeCliExecutor as H, sanitizeAgentRuntimeEvent as Ht, bridgeStopSignalKey as I, loopEventToOtelSpan as It, DEFAULT_SANDBOX_STEERING_MAX_TURNS as J, createWorktree as Jt, workerTraceHeaders as K, runWorktreeHarness as Kt, captureReusableExecutorConfig as L, padSpanId as Lt, bindReusableExecutorExecutionId as M, createOtelExporter as Mt, bridgeAdmissionRead as N, exportEvalRuns as Nt, teardownExecutor as O, buildLoopOtelSpans as Ot, bridgeModelRouteRefusal as P, flatOtelSpan as Pt, sandboxSessionTraceSource as Q, harnessSupportsReasoningEffort as Qt, cliWorktreeExecutor as R, padTraceId as Rt, waitUntil as S, observedModelMatchesDeclared as St, queueOf as T, readTraceContextFromEnv as Tt, WORKER_TRACE_PROPAGATION as U, sanitizeKnowledgeReadinessReport as Ut, snapshotExecutorConfig as V, createRuntimeStreamEventCollector as Vt, readWorkerTraceContext as W, sanitizeRuntimeStreamEvent as Wt, createPushTraceSource as X, DEFAULT_LOCAL_HARNESS as Xt, createSteerableSandboxSession as Y, removeWorktree as Yt, decodeToolPart as Z, LOCAL_HARNESSES as Zt, createWaitProbes as _, worktreeCliProfileMaterialization as _n, probeSandboxCapabilities as _t, pickBestDelivered as a, defineProfileMaterializationContract as an, PEER_MAIL_WIRE_KEY as at, timerAt as b, runBrainLoop as bt, driverChild as c, promptControlProfileMaterialization as cn, isPeerMailEnvelope as ct, deriveNodeExecutionIdentity as d, promptResourceProfileMaterialization as dn, TERMINAL_DECISIONS as dt, parseCodexTokenUsage as en, createActivityLog as et, meterRuntimeOwnedAccounting as f, renderProfileMaterializationIssues as fn, createSandboxForSpec as ft, settledToIteration as g, validateProfileMaterialization as gn, createSandboxLineage as gt, scopeOwnerExecutorNodeContext as h, unsupportedProfileDimensions as hn, runAgentRounds as ht, collectDelivered as i, controlProfileMaterialization as in, DEFAULT_PEER_MAIL_LIMITS as it, spendFromUsageEvents as j, createOpenInferenceFileExporter as jt, assertValidBudget as k, buildLoopSpanNodes as kt, withDriverExecutor as l, promptModelProfileMaterialization as ln, peerMailTools as lt, recordScopeOwnerMaterialization as m, sandboxActProfileMaterialization as mn, isTerminalDecision as mt, createSupervisor as n, AGENT_PROFILE_MATERIALIZATION_AXES as nn, createInbox as nt, runFinalizer as o, fullProfileMaterialization as on, claimsAuthority as ot, meterRuntimeOwnedProviderAttempt as p, renderUnsupported as pn, defaultSelectWinner as pt, workerTraceSeamKey as q, captureWorktreeDiff as qt, bestDelivered as r, assertProfileMaterialization as rn, AUTHORITY_MARKERS as rt, runTree as s, profileMaterializationAxes$1 as sn, createPeerMailbox as st, createRootHandle as t, CodexExecutionDiagnosticError as tn, readWorkerProgress as tt, createScope as u, promptOnlyProfileMaterialization as un, peerMailVerbNames as ut, isWaitOutcome as v, acquireSandbox as vt, freeSlots as w, mergeTraceEnv as wt, validateWaitSpec as x, canonicalObservedModel as xt, pollFor as y, routerBrain as yt, createExecutor as z, toOtelAttributes as zt };
|
|
13111
13514
|
|
|
13112
|
-
//# sourceMappingURL=supervisor-
|
|
13515
|
+
//# sourceMappingURL=supervisor-DBVlPONC.js.map
|