@tangle-network/agent-runtime 0.142.3 → 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-o7JKmtxi.js → activation-DKxQsHiO.js} +3 -3
- package/dist/{activation-o7JKmtxi.js.map → activation-DKxQsHiO.js.map} +1 -1
- package/dist/agent.d.ts +2 -2
- package/dist/agent.js +3 -3
- package/dist/{analyst-loop-GcX0BY75.js → analyst-loop-B2kTHKNh.js} +2 -2
- package/dist/{analyst-loop-GcX0BY75.js.map → analyst-loop-B2kTHKNh.js.map} +1 -1
- package/dist/analyst-loop.d.ts +1 -1
- package/dist/analyst-loop.js +1 -1
- package/dist/{authoring-Bm1WlGPv.js → authoring-Tk2xFys0.js} +2 -2
- package/dist/{authoring-Bm1WlGPv.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-DXKJHyqB.js → conversation-D64WyWrK.js} +4 -4
- package/dist/{conversation-DXKJHyqB.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-BicwCDK5.d.ts → environment-provider-DJG0yIYl.d.ts} +3 -3
- package/dist/{environment-provider-DCEACNt9.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-DhrLuLOS.js → graph-M0Qr4863.js} +4 -4
- package/dist/{graph-DhrLuLOS.js.map → graph-M0Qr4863.js.map} +1 -1
- package/dist/{improvement-cycle-lcwlR6E2.js → improvement-cycle-CDxlGQGE.js} +7 -7
- package/dist/{improvement-cycle-lcwlR6E2.js.map → improvement-cycle-CDxlGQGE.js.map} +1 -1
- package/dist/{index-Bx3-tqG-.d.ts → index-BihHgUAI.d.ts} +4 -4
- package/dist/{index-D_aH0F4C.d.ts → index-Dlz7ejRx.d.ts} +342 -521
- package/dist/{index-CV1xRWy2.d.ts → index-LQfgFJoX.d.ts} +3 -3
- package/dist/index.d.ts +9 -9
- package/dist/index.js +13 -13
- package/dist/intelligence.d.ts +5 -5
- package/dist/intelligence.js +6 -6
- package/dist/kernel.d.ts +7 -7
- package/dist/kernel.js +13 -13
- package/dist/{knowledge-C9LlSJAR.js → knowledge-DM-i40b9.js} +10 -7
- package/dist/{knowledge-C9LlSJAR.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-CctBy5-X.d.ts → loop-runner-bin-D-BW51yr.d.ts} +3 -3
- package/dist/{loop-runner-bin-DFo6Ss-1.js → loop-runner-bin-pD5WJuqJ.js} +4 -4
- package/dist/{loop-runner-bin-DFo6Ss-1.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-CrdcfWXp.js → materialization-Bo6j3Hg9.js} +261 -24
- package/dist/materialization-Bo6j3Hg9.js.map +1 -0
- package/dist/mcp/bin.js +3 -3
- package/dist/mcp/index.d.ts +5 -5
- 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-CSm460sC.js → openai-tools-CWBywy-e.js} +2 -2
- package/dist/{openai-tools-CSm460sC.js.map → openai-tools-CWBywy-e.js.map} +1 -1
- package/dist/{openai-tools-t5-6h5bj.d.ts → openai-tools-z-whdYNC.d.ts} +2 -2
- 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.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-B0gDSTZO.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-htqI3fKL.d.ts → runtime-B-5dp5Iz.d.ts} +223 -11
- package/dist/{runtime-DQs5xHdt.js → runtime-RY_rvv7t.js} +93 -84
- package/dist/runtime-RY_rvv7t.js.map +1 -0
- package/dist/{sandbox-events-BK-g19wx.js → sandbox-events-DMijDq2p.js} +53 -49
- 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-Dfy12OjG.d.ts → stream-agent-turn-BGyszuPH.d.ts} +6 -3
- package/dist/{stream-agent-turn-BMHUIuQS.js → stream-agent-turn-D6HoaRPV.js} +140 -23
- package/dist/stream-agent-turn-D6HoaRPV.js.map +1 -0
- package/dist/{structural-rollout-CzZKDkmA.js → structural-rollout-P1YxFRfl.js} +11 -8
- package/dist/structural-rollout-P1YxFRfl.js.map +1 -0
- package/dist/{supervise-BEs5MB91.js → supervise-BezbzKiJ.js} +1550 -1186
- package/dist/supervise-BezbzKiJ.js.map +1 -0
- package/dist/{supervisor-B_0ISTFG.js → supervisor-DBVlPONC.js} +697 -230
- 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-_7w24mMg.d.ts → types-BPQhQRrC.d.ts} +508 -11
- package/dist/{types-DZrBoBpN.d.ts → types-DeX8ibLc.d.ts} +4 -1
- 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 +6 -6
- package/dist/environment-provider-DCEACNt9.js.map +0 -1
- package/dist/materialization-CrdcfWXp.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-DQs5xHdt.js.map +0 -1
- package/dist/sandbox-events-BK-g19wx.js.map +0 -1
- package/dist/spawn-journal-D2HKUImC.js.map +0 -1
- package/dist/stream-agent-turn-BMHUIuQS.js.map +0 -1
- package/dist/structural-rollout-CzZKDkmA.js.map +0 -1
- package/dist/supervise-BEs5MB91.js.map +0 -1
- package/dist/supervisor-B_0ISTFG.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 {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
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";
|
|
@@ -17,11 +18,13 @@ import { appendFileSync, constants, createReadStream } from "node:fs";
|
|
|
17
18
|
import { spawn } from "node:child_process";
|
|
18
19
|
import { homedir, tmpdir } from "node:os";
|
|
19
20
|
import { stripVTControlCharacters } from "node:util";
|
|
21
|
+
import { createAgentRunOutcomeTracker } from "@tangle-network/sandbox/runtime";
|
|
20
22
|
import { request } from "node:http";
|
|
21
23
|
import { request as request$1 } from "node:https";
|
|
22
24
|
import { Readable } from "node:stream";
|
|
23
25
|
import { deriveHexId, isW3CSpanId, isW3CTraceId } from "@tangle-network/agent-trace-contract";
|
|
24
26
|
import { SDKError, generateIdempotencyKey, withRetry } from "@tangle-network/agent-core";
|
|
27
|
+
import { collectAgentFinalMessageText, collectAgentResponseText } from "@tangle-network/sandbox";
|
|
25
28
|
//#region src/agent/profile-materialization.ts
|
|
26
29
|
const KNOWN_AXIS_SET = new Set(AGENT_PROFILE_MATERIALIZATION_AXES);
|
|
27
30
|
/**
|
|
@@ -216,6 +219,43 @@ function assertProfileMaterialization(options) {
|
|
|
216
219
|
if (issues.length === 0) return;
|
|
217
220
|
throw new ValidationError(renderProfileMaterializationIssues(issues, options.context));
|
|
218
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
|
+
}
|
|
219
259
|
/** Format profile-axis drop issues into a concise operator-facing error. */
|
|
220
260
|
function renderProfileMaterializationIssues(issues, context) {
|
|
221
261
|
if (issues.length === 0) return "";
|
|
@@ -1801,8 +1841,7 @@ function prepareWorktreeProfile(profile, harness) {
|
|
|
1801
1841
|
const workspaceProfile = materializationOnlyProfile(profile);
|
|
1802
1842
|
assertSupportedWorktreeProfile(profile, harness);
|
|
1803
1843
|
assertSafeProfileResourcePaths(profile);
|
|
1804
|
-
const plan =
|
|
1805
|
-
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");
|
|
1806
1845
|
assertSafeMaterializedPaths(plan);
|
|
1807
1846
|
return {
|
|
1808
1847
|
plan,
|
|
@@ -3326,12 +3365,14 @@ async function routerChatWithUsage(cfg, messages, opts) {
|
|
|
3326
3365
|
const headers = routerRequestHeaders(cfg, opts);
|
|
3327
3366
|
const temperature = opts?.temperature;
|
|
3328
3367
|
const maxTokens = opts?.maxTokens ?? cfg.maxTokens;
|
|
3368
|
+
const maxCompletionTokens = opts?.maxCompletionTokens ?? cfg.maxCompletionTokens;
|
|
3329
3369
|
const body = () => ({
|
|
3330
3370
|
...providerRequestExtras(opts?.extraBody, [
|
|
3331
3371
|
"model",
|
|
3332
3372
|
"messages",
|
|
3333
3373
|
"temperature",
|
|
3334
3374
|
"max_tokens",
|
|
3375
|
+
"max_completion_tokens",
|
|
3335
3376
|
"seed",
|
|
3336
3377
|
"reasoning_effort",
|
|
3337
3378
|
"stream",
|
|
@@ -3341,6 +3382,7 @@ async function routerChatWithUsage(cfg, messages, opts) {
|
|
|
3341
3382
|
messages,
|
|
3342
3383
|
...temperature !== void 0 ? { temperature } : {},
|
|
3343
3384
|
...maxTokens !== void 0 ? { max_tokens: maxTokens } : {},
|
|
3385
|
+
...maxCompletionTokens !== void 0 ? { max_completion_tokens: maxCompletionTokens } : {},
|
|
3344
3386
|
...opts?.seed !== void 0 ? { seed: opts.seed } : {},
|
|
3345
3387
|
...opts?.reasoningEffort ? { reasoning_effort: opts.reasoningEffort } : {}
|
|
3346
3388
|
});
|
|
@@ -3455,6 +3497,7 @@ async function routerChatWithTools(cfg, messages, tools, opts) {
|
|
|
3455
3497
|
/** The OpenAI-shape request body both tool-calling transports send. One builder so the streamed
|
|
3456
3498
|
* turn cannot drift from the buffered one on model, temperature, tool_choice, or the ceiling. */
|
|
3457
3499
|
function toolCompletionBody(cfg, messages, tools, opts) {
|
|
3500
|
+
const maxCompletionTokens = opts?.maxCompletionTokens ?? cfg.maxCompletionTokens;
|
|
3458
3501
|
return {
|
|
3459
3502
|
...providerRequestExtras(opts?.extraBody, [
|
|
3460
3503
|
"model",
|
|
@@ -3463,6 +3506,7 @@ function toolCompletionBody(cfg, messages, tools, opts) {
|
|
|
3463
3506
|
"tool_choice",
|
|
3464
3507
|
"temperature",
|
|
3465
3508
|
"max_tokens",
|
|
3509
|
+
"max_completion_tokens",
|
|
3466
3510
|
"seed",
|
|
3467
3511
|
"reasoning_effort",
|
|
3468
3512
|
"stream",
|
|
@@ -3476,6 +3520,7 @@ function toolCompletionBody(cfg, messages, tools, opts) {
|
|
|
3476
3520
|
} : {},
|
|
3477
3521
|
...opts?.temperature !== void 0 ? { temperature: opts.temperature } : {},
|
|
3478
3522
|
...opts?.maxTokens ? { max_tokens: opts.maxTokens } : {},
|
|
3523
|
+
...maxCompletionTokens !== void 0 ? { max_completion_tokens: maxCompletionTokens } : {},
|
|
3479
3524
|
...opts?.seed !== void 0 ? { seed: opts.seed } : {},
|
|
3480
3525
|
...opts?.reasoningEffort ? { reasoning_effort: opts.reasoningEffort } : {}
|
|
3481
3526
|
};
|
|
@@ -3936,7 +3981,7 @@ async function acquireSandbox(client, options, acquire = {}) {
|
|
|
3936
3981
|
while (now() < deadline) {
|
|
3937
3982
|
throwIfAborted(acquire.signal);
|
|
3938
3983
|
try {
|
|
3939
|
-
return await waitReadyOrDestroy(await client.create(createOpts), deadline, pollMs, acquire.signal, now, sleep$1);
|
|
3984
|
+
return await waitReadyOrDestroy(await client.create(createOpts, acquire.signal === void 0 ? void 0 : { signal: acquire.signal }), deadline, pollMs, acquire.signal, now, sleep$1);
|
|
3940
3985
|
} catch (err) {
|
|
3941
3986
|
throwIfAborted(acquire.signal);
|
|
3942
3987
|
if (!isRetryable(err)) throw err;
|
|
@@ -4117,14 +4162,34 @@ async function* pollPromptEvents(box, prompt, sessionId, signal, promptOptions)
|
|
|
4117
4162
|
})).sessionId;
|
|
4118
4163
|
const result = await box.session(activeSessionId).result();
|
|
4119
4164
|
if (signal.aborted) throwAbort();
|
|
4165
|
+
const resultData = {
|
|
4166
|
+
finalText: result.response ?? "",
|
|
4167
|
+
success: result.success,
|
|
4168
|
+
...result.status ? { status: result.status } : {},
|
|
4169
|
+
...result.error ? { error: result.error } : {},
|
|
4170
|
+
...result.errorCode ? { errorCode: result.errorCode } : {},
|
|
4171
|
+
...result.toolInvocations ? { toolInvocations: result.toolInvocations } : {},
|
|
4172
|
+
...result.approval ? { approval: result.approval } : {},
|
|
4173
|
+
...result.question ? { question: result.question } : {},
|
|
4174
|
+
...result.interaction ? { interaction: result.interaction } : {},
|
|
4175
|
+
...result.plan ? { plan: result.plan } : {},
|
|
4176
|
+
...result.usage ? { usage: result.usage } : {},
|
|
4177
|
+
...result.costUsd !== void 0 ? { costUsd: result.costUsd } : {}
|
|
4178
|
+
};
|
|
4120
4179
|
yield {
|
|
4121
4180
|
type: "result",
|
|
4122
4181
|
id: activeSessionId,
|
|
4182
|
+
data: resultData
|
|
4183
|
+
};
|
|
4184
|
+
yield {
|
|
4185
|
+
type: "done",
|
|
4186
|
+
id: activeSessionId,
|
|
4123
4187
|
data: {
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4188
|
+
...resultData,
|
|
4189
|
+
outcome: result.status === "awaiting_plan_decision" && result.plan ? {
|
|
4190
|
+
type: "awaiting_plan_decision",
|
|
4191
|
+
plan: result.plan
|
|
4192
|
+
} : { type: "completed" }
|
|
4128
4193
|
}
|
|
4129
4194
|
};
|
|
4130
4195
|
}
|
|
@@ -4702,14 +4767,14 @@ async function executeIteration(args) {
|
|
|
4702
4767
|
...requestedModel !== void 0 ? { model: requestedModel } : {}
|
|
4703
4768
|
};
|
|
4704
4769
|
let sawLlmCall = false;
|
|
4770
|
+
const outcomeTracker = createAgentRunOutcomeTracker();
|
|
4705
4771
|
for await (const event of stream) {
|
|
4706
4772
|
events.push(event);
|
|
4773
|
+
outcomeTracker.observe(event);
|
|
4707
4774
|
notifySandboxEventObserver(event, args.ctx.onSandboxEvent, {
|
|
4708
4775
|
iterationIndex: args.item.index,
|
|
4709
4776
|
agentRunName: slot.agentRunName
|
|
4710
4777
|
});
|
|
4711
|
-
assertSandboxEventSucceeded(event);
|
|
4712
|
-
assertSandboxServedModel(event, requested);
|
|
4713
4778
|
const llmCall = extractLlmCallEvent(event, slot.agentRunName);
|
|
4714
4779
|
if (llmCall) {
|
|
4715
4780
|
sawLlmCall = true;
|
|
@@ -4728,18 +4793,24 @@ async function executeIteration(args) {
|
|
|
4728
4793
|
});
|
|
4729
4794
|
args.ctx.runHandle?.observe(llmCall);
|
|
4730
4795
|
}
|
|
4796
|
+
assertSandboxServedModel(event, requested);
|
|
4731
4797
|
}
|
|
4798
|
+
const outcome = outcomeTracker.finish();
|
|
4799
|
+
slot.sandboxOutcome = outcome;
|
|
4732
4800
|
if (!sawLlmCall) {
|
|
4733
4801
|
slot.tokenUsage.tokensKnown = false;
|
|
4734
4802
|
slot.costUsdKnown = false;
|
|
4735
4803
|
}
|
|
4736
4804
|
slot.output = args.output.parse(events);
|
|
4737
|
-
|
|
4805
|
+
const projection = projectSandboxOutcome(outcome);
|
|
4806
|
+
if (projection.status === "failed") throw new Error(projection.reason);
|
|
4807
|
+
if (projection.status === "completed" && args.validator) slot.verdict = await args.validator.validate(slot.output, {
|
|
4738
4808
|
iteration: args.item.index,
|
|
4739
4809
|
...box ? { box } : {},
|
|
4740
4810
|
signal: args.signal,
|
|
4741
4811
|
traceEmitter: args.ctx.traceEmitter
|
|
4742
4812
|
});
|
|
4813
|
+
else if (projection.status !== "completed") slot.verdict = projection.verdict;
|
|
4743
4814
|
} catch (err) {
|
|
4744
4815
|
slot.error = err instanceof Error ? err : new Error(String(err));
|
|
4745
4816
|
} finally {
|
|
@@ -5110,6 +5181,59 @@ function hashJson(value) {
|
|
|
5110
5181
|
return (h >>> 0).toString(16).padStart(8, "0");
|
|
5111
5182
|
}
|
|
5112
5183
|
//#endregion
|
|
5184
|
+
//#region src/runtime/sandbox-executor-output.ts
|
|
5185
|
+
/** Project the complete Sandbox event stream into the standard executor result shape. */
|
|
5186
|
+
function sandboxLeafOutputFromEvents(events) {
|
|
5187
|
+
const content = collectAgentFinalMessageText(events) ?? collectAgentResponseText(events);
|
|
5188
|
+
const toolCalls = sandboxToolCalls(events);
|
|
5189
|
+
const servedBackend = lastServedBackend(events);
|
|
5190
|
+
return {
|
|
5191
|
+
events,
|
|
5192
|
+
content,
|
|
5193
|
+
output: sandboxOutputMarker(content, events.some(carriesText)),
|
|
5194
|
+
...servedBackend === void 0 ? {} : { servedBackend },
|
|
5195
|
+
...toolCalls.length === 0 ? {} : { toolCalls }
|
|
5196
|
+
};
|
|
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
|
+
}
|
|
5228
|
+
function sandboxToolCalls(events) {
|
|
5229
|
+
const state = createSandboxToolPartState();
|
|
5230
|
+
return events.flatMap((event) => mapSandboxToolEvent(event, state).flatMap((projected) => projected.type === "tool_call" ? [{
|
|
5231
|
+
...projected.toolCallId === void 0 ? {} : { id: projected.toolCallId },
|
|
5232
|
+
name: projected.toolName,
|
|
5233
|
+
arguments: projected.args ?? {}
|
|
5234
|
+
}] : []));
|
|
5235
|
+
}
|
|
5236
|
+
//#endregion
|
|
5113
5237
|
//#region src/runtime/supervise/cost-estimate.ts
|
|
5114
5238
|
/**
|
|
5115
5239
|
* Pricing for work that arrived without a provider receipt.
|
|
@@ -5132,7 +5256,8 @@ function priceUnreceiptedWork(work) {
|
|
|
5132
5256
|
const unknown = {
|
|
5133
5257
|
kind: "cost",
|
|
5134
5258
|
usd: 0,
|
|
5135
|
-
usdKnown: false
|
|
5259
|
+
usdKnown: false,
|
|
5260
|
+
provenance: "uncaptured"
|
|
5136
5261
|
};
|
|
5137
5262
|
const { inputTokens, outputTokens, model } = work;
|
|
5138
5263
|
if (model === void 0 || !isModelPriced(model)) return unknown;
|
|
@@ -5144,7 +5269,8 @@ function priceUnreceiptedWork(work) {
|
|
|
5144
5269
|
kind: "cost",
|
|
5145
5270
|
usd,
|
|
5146
5271
|
usdKnown: false,
|
|
5147
|
-
usdEstimated: usd
|
|
5272
|
+
usdEstimated: usd,
|
|
5273
|
+
provenance: "catalog-estimate"
|
|
5148
5274
|
};
|
|
5149
5275
|
}
|
|
5150
5276
|
//#endregion
|
|
@@ -5867,12 +5993,21 @@ function createSteerableSandboxSession(args) {
|
|
|
5867
5993
|
});
|
|
5868
5994
|
const state = {
|
|
5869
5995
|
turns: 0,
|
|
5870
|
-
|
|
5996
|
+
/** `undefined` until a text-bearing terminal event is observed; never seeded with `''`. */
|
|
5997
|
+
lastText: void 0,
|
|
5998
|
+
servedBackend: void 0,
|
|
5871
5999
|
seenToolCalls: /* @__PURE__ */ new Set(),
|
|
6000
|
+
toolCalls: [],
|
|
5872
6001
|
artifact: void 0,
|
|
6002
|
+
latestOutcome: void 0,
|
|
6003
|
+
/** Reads the live lineage handle once a box and session exist, for exact cancellation. */
|
|
6004
|
+
session: void 0,
|
|
5873
6005
|
teardown: void 0,
|
|
5874
6006
|
note: "starting"
|
|
5875
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. */
|
|
5876
6011
|
const recordEvent = (event) => {
|
|
5877
6012
|
const at = now();
|
|
5878
6013
|
const data = event.data;
|
|
@@ -5896,7 +6031,19 @@ function createSteerableSandboxSession(args) {
|
|
|
5896
6031
|
}
|
|
5897
6032
|
}
|
|
5898
6033
|
const text = readFinalText(event);
|
|
5899
|
-
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;
|
|
5900
6047
|
};
|
|
5901
6048
|
async function* stream(task, signal) {
|
|
5902
6049
|
const capabilities = await probeSandboxCapabilities(args.sandboxClient);
|
|
@@ -5922,6 +6069,7 @@ function createSteerableSandboxSession(args) {
|
|
|
5922
6069
|
let tokensKnown = true;
|
|
5923
6070
|
let usd = 0;
|
|
5924
6071
|
let handle;
|
|
6072
|
+
state.session = () => handle;
|
|
5925
6073
|
let nextPrompt = args.taskToPrompt(task);
|
|
5926
6074
|
try {
|
|
5927
6075
|
for (let turn = 0; maxTurns === 0 || turn < maxTurns; turn += 1) {
|
|
@@ -5958,6 +6106,7 @@ function createSteerableSandboxSession(args) {
|
|
|
5958
6106
|
};
|
|
5959
6107
|
let events;
|
|
5960
6108
|
let sawLlmCall = false;
|
|
6109
|
+
const outcomeTracker = createAgentRunOutcomeTracker();
|
|
5961
6110
|
try {
|
|
5962
6111
|
if (!handle) {
|
|
5963
6112
|
const opened = await lineage.start(spec, prompt, turnController.signal, promptOptions);
|
|
@@ -5965,36 +6114,42 @@ function createSteerableSandboxSession(args) {
|
|
|
5965
6114
|
events = opened.events;
|
|
5966
6115
|
} else events = await lineage.continue(handle, prompt, turnController.signal, promptOptions);
|
|
5967
6116
|
for await (const event of events) {
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
6117
|
+
outcomeTracker.observe(event);
|
|
6118
|
+
for (const progress of recordEvent(event)) yield {
|
|
6119
|
+
kind: "progress",
|
|
6120
|
+
progress
|
|
6121
|
+
};
|
|
5971
6122
|
const call = extractLlmCallEvent(event, spec.name ?? String(args.harness));
|
|
5972
|
-
if (
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
|
|
5995
|
-
|
|
6123
|
+
if (call) {
|
|
6124
|
+
sawLlmCall = true;
|
|
6125
|
+
const callTokensKnown = call.tokensKnown !== false && typeof call.tokensIn === "number" && typeof call.tokensOut === "number";
|
|
6126
|
+
if (!callTokensKnown) tokensKnown = false;
|
|
6127
|
+
const input = call.tokensIn ?? 0;
|
|
6128
|
+
const output = call.tokensOut ?? 0;
|
|
6129
|
+
if (input || output || !callTokensKnown) {
|
|
6130
|
+
const usage = {
|
|
6131
|
+
kind: "tokens",
|
|
6132
|
+
input,
|
|
6133
|
+
output,
|
|
6134
|
+
...callTokensKnown ? {} : { tokensKnown: false },
|
|
6135
|
+
...promptCacheTokenClasses(call.tokensIn, call.promptCache)
|
|
6136
|
+
};
|
|
6137
|
+
addTokenUsage(tokens, usage);
|
|
6138
|
+
yield usage;
|
|
6139
|
+
}
|
|
6140
|
+
if (typeof call.costUsd === "number" && call.costUsd > 0) {
|
|
6141
|
+
usd += call.costUsd;
|
|
6142
|
+
yield {
|
|
6143
|
+
kind: "cost",
|
|
6144
|
+
usd: call.costUsd,
|
|
6145
|
+
usdKnown: false,
|
|
6146
|
+
provenance: "uncaptured"
|
|
6147
|
+
};
|
|
6148
|
+
}
|
|
5996
6149
|
}
|
|
6150
|
+
assertSandboxServedModel(event, requested);
|
|
5997
6151
|
}
|
|
6152
|
+
state.latestOutcome = outcomeTracker.finish();
|
|
5998
6153
|
} catch (e) {
|
|
5999
6154
|
cleanup();
|
|
6000
6155
|
if (isInterruptAbort(e, interruptSig, signal, args.controller.signal)) {
|
|
@@ -6035,7 +6190,8 @@ function createSteerableSandboxSession(args) {
|
|
|
6035
6190
|
if (state.turns > 0) yield {
|
|
6036
6191
|
kind: "cost",
|
|
6037
6192
|
usd: 0,
|
|
6038
|
-
usdKnown: false
|
|
6193
|
+
usdKnown: false,
|
|
6194
|
+
provenance: "uncaptured"
|
|
6039
6195
|
};
|
|
6040
6196
|
const spent = {
|
|
6041
6197
|
iterations: state.turns,
|
|
@@ -6047,20 +6203,79 @@ function createSteerableSandboxSession(args) {
|
|
|
6047
6203
|
};
|
|
6048
6204
|
const out = {
|
|
6049
6205
|
content: state.lastText,
|
|
6206
|
+
output: sandboxOutputMarker(state.lastText),
|
|
6207
|
+
...state.servedBackend === void 0 ? {} : { servedBackend: state.servedBackend },
|
|
6050
6208
|
turns: state.turns,
|
|
6051
|
-
toolCalls:
|
|
6209
|
+
toolCalls: state.toolCalls,
|
|
6210
|
+
...state.latestOutcome ? { outcome: state.latestOutcome } : {}
|
|
6052
6211
|
};
|
|
6212
|
+
const verdict = state.latestOutcome ? projectSandboxOutcome(state.latestOutcome).verdict : void 0;
|
|
6053
6213
|
state.artifact = {
|
|
6054
6214
|
outRef: args.contentRef("sandbox-steerable", {
|
|
6055
6215
|
harness: args.harness,
|
|
6056
6216
|
out
|
|
6057
6217
|
}),
|
|
6058
6218
|
out,
|
|
6219
|
+
...verdict ? { verdict } : {},
|
|
6059
6220
|
spent
|
|
6060
6221
|
};
|
|
6061
6222
|
}
|
|
6062
6223
|
return {
|
|
6063
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
|
+
},
|
|
6064
6279
|
progress: () => ({
|
|
6065
6280
|
turns: state.turns,
|
|
6066
6281
|
pendingMessages: args.inbox.pending(),
|
|
@@ -6078,14 +6293,16 @@ function createSteerableSandboxSession(args) {
|
|
|
6078
6293
|
function isInterruptAbort(err, interrupt, external, owned) {
|
|
6079
6294
|
return (err instanceof DOMException && err.name === "AbortError" || typeof err === "object" && err !== null && err.name === "AbortError") && interrupt.aborted && !external.aborted && !owned.aborted;
|
|
6080
6295
|
}
|
|
6081
|
-
/** 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". */
|
|
6082
6299
|
function readFinalText(event) {
|
|
6083
6300
|
const data = event.data;
|
|
6084
6301
|
if (!data || typeof data !== "object") return void 0;
|
|
6085
6302
|
const text = data.finalText;
|
|
6086
|
-
if (typeof text === "string"
|
|
6303
|
+
if (typeof text === "string") return text;
|
|
6087
6304
|
const alt = data.text;
|
|
6088
|
-
return typeof alt === "string"
|
|
6305
|
+
return typeof alt === "string" ? alt : void 0;
|
|
6089
6306
|
}
|
|
6090
6307
|
/** Prompt options the composed loop context already carries (agent profile / cwd), forwarded so
|
|
6091
6308
|
* a steerable worker runs with the same box configuration as the single-shot path. */
|
|
@@ -6493,6 +6710,11 @@ const bridgeSeamKey = "bridge";
|
|
|
6493
6710
|
/** Internal control seam used by Runtime-owned external supervisors. A completion request stops
|
|
6494
6711
|
* the next bridge turn; it must not abort the paid request that is already streaming. */
|
|
6495
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";
|
|
6496
6718
|
const maxBridgeTimeoutMs = 2147483647;
|
|
6497
6719
|
const bridgeModelCredentialHeader = "x-cli-bridge-model-credential";
|
|
6498
6720
|
const bridgeModelBaseUrlHeader = "x-cli-bridge-model-base-url";
|
|
@@ -6631,6 +6853,19 @@ function unmeteredSpend(ms) {
|
|
|
6631
6853
|
* failures (429/5xx/Cloudflare-origin) retry with backoff before the executor
|
|
6632
6854
|
* fails the task.
|
|
6633
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
|
+
}
|
|
6634
6869
|
const routerInlineExecutor = (spec, ctx) => {
|
|
6635
6870
|
const seam = readSeam(ctx, routerSeamKey, "router/inline");
|
|
6636
6871
|
const model = exactRouterModel(spec.profile, "routerInlineExecutor");
|
|
@@ -6668,7 +6903,7 @@ const routerInlineExecutor = (spec, ctx) => {
|
|
|
6668
6903
|
...profileExecution.temperature !== void 0 ? { temperature: profileExecution.temperature } : {},
|
|
6669
6904
|
...linked ? { signal: linked } : {},
|
|
6670
6905
|
...profileExecution.toolChoice ? { toolChoice: profileExecution.toolChoice } : {},
|
|
6671
|
-
...profileExecution.
|
|
6906
|
+
...profileExecution.tokenLimits.applied,
|
|
6672
6907
|
...profileExecution.seed !== void 0 ? { seed: profileExecution.seed } : {},
|
|
6673
6908
|
...Object.keys(extraBody).length > 0 ? { extraBody } : {},
|
|
6674
6909
|
...requestIdentity
|
|
@@ -6681,7 +6916,7 @@ const routerInlineExecutor = (spec, ctx) => {
|
|
|
6681
6916
|
}, messages, {
|
|
6682
6917
|
...profileExecution.temperature !== void 0 ? { temperature: profileExecution.temperature } : {},
|
|
6683
6918
|
...linked ? { signal: linked } : {},
|
|
6684
|
-
...profileExecution.
|
|
6919
|
+
...profileExecution.tokenLimits.applied,
|
|
6685
6920
|
...profileExecution.seed !== void 0 ? { seed: profileExecution.seed } : {},
|
|
6686
6921
|
...profileExecution.reasoningEffort ? { reasoningEffort: profileExecution.reasoningEffort } : {},
|
|
6687
6922
|
...profileExecution.extraBody ? { extraBody: profileExecution.extraBody } : {},
|
|
@@ -6722,6 +6957,10 @@ const routerInlineExecutor = (spec, ctx) => {
|
|
|
6722
6957
|
};
|
|
6723
6958
|
return artifact;
|
|
6724
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
|
+
},
|
|
6725
6964
|
teardown(_grace) {
|
|
6726
6965
|
controller.abort("executor torn down");
|
|
6727
6966
|
return Promise.resolve({ destroyed: true });
|
|
@@ -6750,7 +6989,7 @@ const routerInlineExecutor = (spec, ctx) => {
|
|
|
6750
6989
|
model,
|
|
6751
6990
|
provider: spec.profile.model?.provider ?? null,
|
|
6752
6991
|
temperature: profileExecution.temperature ?? null,
|
|
6753
|
-
|
|
6992
|
+
tokenLimits: profileExecution.tokenLimits,
|
|
6754
6993
|
retry: profileExecution.retry ?? null,
|
|
6755
6994
|
seed: profileExecution.seed ?? null,
|
|
6756
6995
|
reasoningEffort: profileExecution.reasoningEffort ?? null,
|
|
@@ -6862,6 +7101,7 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
6862
7101
|
let reasoningKnown = true;
|
|
6863
7102
|
const promptCache = {};
|
|
6864
7103
|
let lastText = "";
|
|
7104
|
+
const executedToolCalls = [];
|
|
6865
7105
|
const flush = () => {
|
|
6866
7106
|
const pending = inbox.drain();
|
|
6867
7107
|
if (pending.length) messages.push({
|
|
@@ -6894,7 +7134,7 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
6894
7134
|
...profileExecution.temperature !== void 0 ? { temperature: profileExecution.temperature } : {},
|
|
6895
7135
|
signal: turnController.signal,
|
|
6896
7136
|
...profileExecution.toolChoice ? { toolChoice: profileExecution.toolChoice } : {},
|
|
6897
|
-
...profileExecution.
|
|
7137
|
+
...profileExecution.tokenLimits.applied,
|
|
6898
7138
|
...profileExecution.seed !== void 0 ? { seed: profileExecution.seed } : {},
|
|
6899
7139
|
...profileExecution.reasoningEffort ? { reasoningEffort: profileExecution.reasoningEffort } : {},
|
|
6900
7140
|
...profileExecution.extraBody ? { extraBody: profileExecution.extraBody } : {},
|
|
@@ -6960,6 +7200,11 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
6960
7200
|
const tc = toolCalls[i];
|
|
6961
7201
|
const id = tc?.id ?? `call_${i}`;
|
|
6962
7202
|
const toolName = tc?.name ?? "";
|
|
7203
|
+
executedToolCalls.push({
|
|
7204
|
+
id,
|
|
7205
|
+
name: toolName,
|
|
7206
|
+
arguments: tc?.arguments ?? ""
|
|
7207
|
+
});
|
|
6963
7208
|
if (!enabledToolNames.has(toolName)) {
|
|
6964
7209
|
messages.push({
|
|
6965
7210
|
role: "tool",
|
|
@@ -7030,7 +7275,7 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
7030
7275
|
...observedModel !== void 0 ? { model: observedModel } : {},
|
|
7031
7276
|
messages,
|
|
7032
7277
|
turns,
|
|
7033
|
-
toolCalls:
|
|
7278
|
+
toolCalls: executedToolCalls,
|
|
7034
7279
|
transportAttempts,
|
|
7035
7280
|
...estimatedUsd !== void 0 ? { estimatedCostUsd: estimatedUsd } : {},
|
|
7036
7281
|
...Object.keys(promptCache).length > 0 ? { promptCache } : {},
|
|
@@ -7046,6 +7291,10 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
7046
7291
|
};
|
|
7047
7292
|
return artifact;
|
|
7048
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
|
+
},
|
|
7049
7298
|
teardown(_grace) {
|
|
7050
7299
|
controller.abort("executor torn down");
|
|
7051
7300
|
return Promise.resolve({ destroyed: true });
|
|
@@ -7076,7 +7325,7 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
7076
7325
|
maxTurns,
|
|
7077
7326
|
tools: seam.tools,
|
|
7078
7327
|
temperature: profileExecution.temperature ?? null,
|
|
7079
|
-
|
|
7328
|
+
tokenLimits: profileExecution.tokenLimits,
|
|
7080
7329
|
retry: profileExecution.retry ?? null,
|
|
7081
7330
|
toolChoice: profileExecution.toolChoice ?? null,
|
|
7082
7331
|
extraBody: profileExecution.extraBody ?? null,
|
|
@@ -7135,6 +7384,7 @@ const sandboxExecutor = (spec, ctx) => {
|
|
|
7135
7384
|
if (!seam.sandboxClient || typeof seam.sandboxClient.create !== "function") throw new ValidationError("sandboxExecutor: SandboxSeam.sandboxClient.create required");
|
|
7136
7385
|
const maxIterations = seam.maxIterations ?? 1;
|
|
7137
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");
|
|
7138
7388
|
const traceEnv = workerTraceEnv(ctx);
|
|
7139
7389
|
const controller = new AbortController();
|
|
7140
7390
|
const abortIfSignalled = () => {
|
|
@@ -7165,7 +7415,8 @@ const sandboxExecutor = (spec, ctx) => {
|
|
|
7165
7415
|
kind: "sandbox-agent-rounds",
|
|
7166
7416
|
harness,
|
|
7167
7417
|
maxIterations,
|
|
7168
|
-
steering: seam.steering !== void 0
|
|
7418
|
+
steering: seam.steering !== void 0,
|
|
7419
|
+
tokenLimits: sandboxTokenLimits
|
|
7169
7420
|
}
|
|
7170
7421
|
};
|
|
7171
7422
|
const sandboxBinding = {
|
|
@@ -7200,6 +7451,7 @@ const sandboxExecutor = (spec, ctx) => {
|
|
|
7200
7451
|
runtime: "sandbox",
|
|
7201
7452
|
deliver: (m) => inbox.deliver(m),
|
|
7202
7453
|
progress: () => session.progress(),
|
|
7454
|
+
cancel: (request) => session.cancel(request),
|
|
7203
7455
|
traceSource: () => session.traceSource(),
|
|
7204
7456
|
execute(task, signal) {
|
|
7205
7457
|
return session.stream(task, signal);
|
|
@@ -7217,7 +7469,7 @@ const sandboxExecutor = (spec, ctx) => {
|
|
|
7217
7469
|
}, sandboxMaterialization, sandboxBinding);
|
|
7218
7470
|
}
|
|
7219
7471
|
const output = { parse(events) {
|
|
7220
|
-
return
|
|
7472
|
+
return sandboxLeafOutputFromEvents(events);
|
|
7221
7473
|
} };
|
|
7222
7474
|
const driver = singleShotDriver(maxIterations);
|
|
7223
7475
|
return attestRuntimeOwnedExecutor({
|
|
@@ -7241,6 +7493,10 @@ const sandboxExecutor = (spec, ctx) => {
|
|
|
7241
7493
|
}
|
|
7242
7494
|
});
|
|
7243
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
|
+
},
|
|
7244
7500
|
teardown(_grace) {
|
|
7245
7501
|
controller.abort();
|
|
7246
7502
|
return Promise.resolve({ destroyed: true });
|
|
@@ -7289,12 +7545,21 @@ async function* streamSandboxLeaf(args) {
|
|
|
7289
7545
|
const result = await runAgentRounds(loopOptions);
|
|
7290
7546
|
const failure = failedRound(result);
|
|
7291
7547
|
if (failure) throw failure;
|
|
7292
|
-
const
|
|
7293
|
-
const
|
|
7548
|
+
const winningIteration = result.winner ? result.iterations.find((iteration) => iteration.index === result.winner?.iterationIndex) : result.iterations.at(-1);
|
|
7549
|
+
const out = winningIteration?.output ?? sandboxLeafOutputFromEvents(winningIteration?.events ?? []);
|
|
7550
|
+
const sandboxOutcome = winningIteration?.sandboxOutcome;
|
|
7551
|
+
const outWithOutcome = {
|
|
7552
|
+
...out,
|
|
7553
|
+
...sandboxOutcome ? { outcome: sandboxOutcome } : {}
|
|
7554
|
+
};
|
|
7555
|
+
const verdict = sandboxOutcome && !sandboxOutcome.success ? {
|
|
7556
|
+
valid: false,
|
|
7557
|
+
score: 0
|
|
7558
|
+
} : result.winner?.verdict ?? leafVerdict(result);
|
|
7294
7559
|
const tokensKnown = result.tokenUsage.tokensKnown !== false;
|
|
7295
7560
|
const usdKnown = result.costUsdKnown !== false;
|
|
7296
7561
|
const outWithUsage = {
|
|
7297
|
-
...
|
|
7562
|
+
...outWithOutcome,
|
|
7298
7563
|
...result.estimatedCostUsd !== void 0 ? { estimatedCostUsd: result.estimatedCostUsd } : {},
|
|
7299
7564
|
...result.promptCache ? { promptCache: result.promptCache } : {}
|
|
7300
7565
|
};
|
|
@@ -7326,10 +7591,16 @@ async function* streamSandboxLeaf(args) {
|
|
|
7326
7591
|
...result.tokenUsage.cacheWrite !== void 0 ? { cacheWrite: result.tokenUsage.cacheWrite } : {},
|
|
7327
7592
|
...result.tokenUsage.cacheBreakdownKnown === false ? { cacheBreakdownKnown: false } : {}
|
|
7328
7593
|
};
|
|
7329
|
-
if (result.iterations.length > 0 || result.costUsd) yield {
|
|
7594
|
+
if (result.iterations.length > 0 || result.costUsd) yield usdKnown ? {
|
|
7595
|
+
kind: "cost",
|
|
7596
|
+
usdKnown: true,
|
|
7597
|
+
usd: result.costUsd,
|
|
7598
|
+
provenance: "provider-receipt"
|
|
7599
|
+
} : {
|
|
7330
7600
|
kind: "cost",
|
|
7601
|
+
usdKnown: false,
|
|
7331
7602
|
usd: result.costUsd,
|
|
7332
|
-
|
|
7603
|
+
provenance: "uncaptured"
|
|
7333
7604
|
};
|
|
7334
7605
|
} finally {
|
|
7335
7606
|
args.signal.removeEventListener("abort", cascadeExternal);
|
|
@@ -7528,18 +7799,20 @@ function bridgeProfileModel(profile, context) {
|
|
|
7528
7799
|
const bridgeExecutor = (spec, ctx) => {
|
|
7529
7800
|
const base = readSeam(ctx, bridgeSeamKey, "bridge");
|
|
7530
7801
|
const stopSignal = readOptionalAbortSignal(ctx, bridgeStopSignalKey, "bridge");
|
|
7802
|
+
const runtimeAttachments = readOptionalMcpAttachments(ctx, bridgeRuntimeAttachmentsKey, "bridge");
|
|
7531
7803
|
const modelCredential = validateBridgeModelCredential(base.modelCredential, base.bridgeUrl, "bridgeExecutor");
|
|
7532
7804
|
const effectiveProfile = agentProfileSchema.parse(spec.profile);
|
|
7533
7805
|
const model = bridgeProfileModel(effectiveProfile, "bridgeExecutor");
|
|
7534
7806
|
const harness = agentHarness(effectiveProfile.harness);
|
|
7535
7807
|
const providerModel = harness !== void 0 && model.startsWith(`${harness}/`) ? model.slice(harness.length + 1) : model;
|
|
7536
7808
|
const profileExecution = profileModelExecutionSettings(effectiveProfile, "bridgeExecutor");
|
|
7809
|
+
const bridgeTokenLimits = enforceTokenLimits(profileExecution.tokenLimits, "bridge", "bridgeExecutor");
|
|
7537
7810
|
const seam = {
|
|
7538
7811
|
...base,
|
|
7539
7812
|
...modelCredential === void 0 ? {} : { modelCredential },
|
|
7540
7813
|
model,
|
|
7541
7814
|
providerModel,
|
|
7542
|
-
...
|
|
7815
|
+
...bridgeTokenLimits.applied.maxTokens !== void 0 ? { maxTokens: bridgeTokenLimits.applied.maxTokens } : {}
|
|
7543
7816
|
};
|
|
7544
7817
|
if (!seam.bridgeUrl || !seam.bridgeBearer) throw new ValidationError("bridgeExecutor: bridgeUrl + bridgeBearer are required");
|
|
7545
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}`);
|
|
@@ -7587,7 +7860,7 @@ const bridgeExecutor = (spec, ctx) => {
|
|
|
7587
7860
|
maxReconnects,
|
|
7588
7861
|
timeoutMs: seam.timeoutMs ?? null,
|
|
7589
7862
|
streaming: true,
|
|
7590
|
-
|
|
7863
|
+
tokenLimits: bridgeTokenLimits,
|
|
7591
7864
|
terminalAcknowledgement: null
|
|
7592
7865
|
}
|
|
7593
7866
|
};
|
|
@@ -7633,11 +7906,16 @@ const bridgeExecutor = (spec, ctx) => {
|
|
|
7633
7906
|
}
|
|
7634
7907
|
},
|
|
7635
7908
|
traceSource: () => trace.source,
|
|
7909
|
+
interactive: () => Object.freeze({
|
|
7910
|
+
status: "unavailable",
|
|
7911
|
+
reason: "provider-has-no-interactive-contract"
|
|
7912
|
+
}),
|
|
7636
7913
|
execute(task, signal) {
|
|
7637
7914
|
return streamBridgeSession({
|
|
7638
7915
|
task,
|
|
7639
7916
|
signal,
|
|
7640
7917
|
...stopSignal === void 0 ? {} : { stopSignal },
|
|
7918
|
+
...runtimeAttachments === void 0 ? {} : { runtimeAttachments },
|
|
7641
7919
|
profile: effectiveProfile,
|
|
7642
7920
|
seam,
|
|
7643
7921
|
sessionId,
|
|
@@ -7674,6 +7952,41 @@ const bridgeExecutor = (spec, ctx) => {
|
|
|
7674
7952
|
}
|
|
7675
7953
|
});
|
|
7676
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
|
+
},
|
|
7677
7990
|
async teardown(grace) {
|
|
7678
7991
|
controller.abort();
|
|
7679
7992
|
const remaining = [...activeRuns.values()].filter((run) => !run.terminal);
|
|
@@ -7739,6 +8052,78 @@ function scheduleBridgeRunStateRefresh(seam, activeRuns, observation) {
|
|
|
7739
8052
|
}
|
|
7740
8053
|
})();
|
|
7741
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
|
+
}
|
|
7742
8127
|
/** `GET /v1/runs/:id` — the bridge's durable-run registry read. Resolves `undefined` for any
|
|
7743
8128
|
* non-200 or non-conforming body rather than throwing: this is only ever an observability read. */
|
|
7744
8129
|
function bridgeRunStateGet(seam, runId) {
|
|
@@ -7871,6 +8256,7 @@ async function* streamBridgeSession(args) {
|
|
|
7871
8256
|
...seam.timeoutMs !== void 0 ? { timeoutMs: seam.timeoutMs } : {}
|
|
7872
8257
|
},
|
|
7873
8258
|
agent_profile: args.profile,
|
|
8259
|
+
...args.runtimeAttachments === void 0 ? {} : { runtime_attachments: { mcp: args.runtimeAttachments } },
|
|
7874
8260
|
messages
|
|
7875
8261
|
};
|
|
7876
8262
|
let turnText = "";
|
|
@@ -7879,6 +8265,7 @@ async function* streamBridgeSession(args) {
|
|
|
7879
8265
|
let sawTurnCostStatus = false;
|
|
7880
8266
|
let turnUsdKnown = true;
|
|
7881
8267
|
let turnKnownCostSubtotal = 0;
|
|
8268
|
+
let turnCostProvenance;
|
|
7882
8269
|
let turnEstimatedCostSubtotal = 0;
|
|
7883
8270
|
let turnInputTokens = 0;
|
|
7884
8271
|
let turnOutputTokens = 0;
|
|
@@ -7901,6 +8288,7 @@ async function* streamBridgeSession(args) {
|
|
|
7901
8288
|
profile: args.profile,
|
|
7902
8289
|
sessionId: args.sessionId,
|
|
7903
8290
|
body: requestBody,
|
|
8291
|
+
requiresRuntimeAttachments: args.runtimeAttachments !== void 0,
|
|
7904
8292
|
signal: turnController.signal,
|
|
7905
8293
|
run: activeRun,
|
|
7906
8294
|
maxReconnects: args.maxReconnects,
|
|
@@ -7925,9 +8313,22 @@ async function* streamBridgeSession(args) {
|
|
|
7925
8313
|
}
|
|
7926
8314
|
observedSystemFingerprint = chunk.systemFingerprint;
|
|
7927
8315
|
}
|
|
7928
|
-
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
|
+
}
|
|
7929
8326
|
for (const step of chunk.toolCalls ?? []) {
|
|
7930
|
-
toolCalls.push(
|
|
8327
|
+
toolCalls.push({
|
|
8328
|
+
...step.callId === void 0 ? {} : { id: step.callId },
|
|
8329
|
+
name: step.toolName,
|
|
8330
|
+
arguments: step.args
|
|
8331
|
+
});
|
|
7931
8332
|
observation.activity.push({
|
|
7932
8333
|
at: Date.now(),
|
|
7933
8334
|
kind: "tool",
|
|
@@ -7935,6 +8336,15 @@ async function* streamBridgeSession(args) {
|
|
|
7935
8336
|
...describeToolArgs(step.args) ? { detail: describeToolArgs(step.args) } : {}
|
|
7936
8337
|
});
|
|
7937
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
|
+
};
|
|
7938
8348
|
}
|
|
7939
8349
|
if (chunk.usage) {
|
|
7940
8350
|
sawTurnTokenUsage = true;
|
|
@@ -7958,6 +8368,7 @@ async function* streamBridgeSession(args) {
|
|
|
7958
8368
|
if (chunk.usage.promptCache.writeInput !== void 0) promptCache.writeTokens = (promptCache.writeTokens ?? 0) + chunk.usage.promptCache.writeInput;
|
|
7959
8369
|
}
|
|
7960
8370
|
}
|
|
8371
|
+
if (chunk.costProvenance !== void 0) turnCostProvenance = chunk.costProvenance;
|
|
7961
8372
|
if (chunk.costKnown !== void 0) {
|
|
7962
8373
|
sawTurnCostStatus = true;
|
|
7963
8374
|
if (!chunk.costKnown) turnUsdKnown = false;
|
|
@@ -7971,7 +8382,9 @@ async function* streamBridgeSession(args) {
|
|
|
7971
8382
|
usd += increment;
|
|
7972
8383
|
yield {
|
|
7973
8384
|
kind: "cost",
|
|
7974
|
-
|
|
8385
|
+
usdKnown: true,
|
|
8386
|
+
usd: increment,
|
|
8387
|
+
provenance: turnCostProvenance ?? "provider-receipt"
|
|
7975
8388
|
};
|
|
7976
8389
|
}
|
|
7977
8390
|
}
|
|
@@ -8016,9 +8429,10 @@ async function* streamBridgeSession(args) {
|
|
|
8016
8429
|
}) : {
|
|
8017
8430
|
kind: "cost",
|
|
8018
8431
|
usd: 0,
|
|
8019
|
-
usdKnown: false
|
|
8432
|
+
usdKnown: false,
|
|
8433
|
+
provenance: "uncaptured"
|
|
8020
8434
|
};
|
|
8021
|
-
if (priced.usdEstimated !== void 0) estimatedUsdCharged += priced.usdEstimated;
|
|
8435
|
+
if (priced.usdKnown === false && priced.usdEstimated !== void 0) estimatedUsdCharged += priced.usdEstimated;
|
|
8022
8436
|
usd += priced.usd;
|
|
8023
8437
|
yield priced;
|
|
8024
8438
|
}
|
|
@@ -8072,7 +8486,7 @@ const BRIDGE_BRUTAL_KILL_WAIT_MS = 150;
|
|
|
8072
8486
|
* cannot prove continuity fails instead of returning a plausible partial answer.
|
|
8073
8487
|
*/
|
|
8074
8488
|
async function* streamDurableBridgeRun(args) {
|
|
8075
|
-
await assertBridgeExecutionCapabilities(args.seam, args.signal);
|
|
8489
|
+
await assertBridgeExecutionCapabilities(args.seam, args.signal, args.requiresRuntimeAttachments);
|
|
8076
8490
|
let reconnects = 0;
|
|
8077
8491
|
let pendingUpstreamError;
|
|
8078
8492
|
for (;;) {
|
|
@@ -8151,7 +8565,7 @@ async function* streamDurableBridgeRun(args) {
|
|
|
8151
8565
|
* a process may restart behind the same URL, and a remembered capability from the prior process
|
|
8152
8566
|
* is not evidence about the process that will receive the next POST. The terminal receipt remains
|
|
8153
8567
|
* mandatory because the bridge can still restart between this GET and the run request. */
|
|
8154
|
-
async function assertBridgeExecutionCapabilities(seam, signal) {
|
|
8568
|
+
async function assertBridgeExecutionCapabilities(seam, signal, requiresRuntimeAttachments) {
|
|
8155
8569
|
const target = new URL(`${seam.bridgeUrl.replace(/\/$/, "")}/`);
|
|
8156
8570
|
const requestFn = target.protocol === "https:" ? request$1 : request;
|
|
8157
8571
|
const response = await new Promise((resolve, reject) => {
|
|
@@ -8192,6 +8606,10 @@ async function assertBridgeExecutionCapabilities(seam, signal) {
|
|
|
8192
8606
|
}
|
|
8193
8607
|
if (body.capabilities?.profileMaterialization !== bridgeProfileMaterializationSchema) throw new ValidationError(`bridgeExecutor: bridge does not advertise ${bridgeProfileMaterializationSchema}`);
|
|
8194
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
|
+
}
|
|
8195
8613
|
}
|
|
8196
8614
|
/**
|
|
8197
8615
|
* POST one streamed turn to the cli-bridge over the `node:http(s)` core client
|
|
@@ -8801,6 +9219,7 @@ function applyBridgeCostReceipt(out, usage) {
|
|
|
8801
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");
|
|
8802
9220
|
out.costKnown = true;
|
|
8803
9221
|
out.cost = cost;
|
|
9222
|
+
out.costProvenance = provenance;
|
|
8804
9223
|
return;
|
|
8805
9224
|
}
|
|
8806
9225
|
if (cost !== void 0) throw new ValidationError("bridgeExecutor: unknown cost cannot carry billed cost");
|
|
@@ -9251,13 +9670,14 @@ function createExecutor(config) {
|
|
|
9251
9670
|
}
|
|
9252
9671
|
}
|
|
9253
9672
|
};
|
|
9254
|
-
|
|
9255
|
-
...
|
|
9256
|
-
|
|
9257
|
-
|
|
9258
|
-
|
|
9673
|
+
const executor = sandboxExecutor({
|
|
9674
|
+
...spec,
|
|
9675
|
+
harness
|
|
9676
|
+
}, providerCtx);
|
|
9677
|
+
return inheritRuntimeOwnedExecutorAttestation(executor, {
|
|
9678
|
+
...executor,
|
|
9259
9679
|
runtime: providerSeam.runtime ?? provider.name
|
|
9260
|
-
};
|
|
9680
|
+
});
|
|
9261
9681
|
}
|
|
9262
9682
|
const profileForCreate = providerSeam.profileForCreate;
|
|
9263
9683
|
return providerAsExecutor(provider, {
|
|
@@ -9359,6 +9779,15 @@ function readOptionalAbortSignal(ctx, key, who) {
|
|
|
9359
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`);
|
|
9360
9780
|
return value;
|
|
9361
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
|
+
}
|
|
9362
9791
|
/** A leaf task is opaque (`unknown`). A string is the prompt verbatim; an object
|
|
9363
9792
|
* with a `prompt`/`content`/`task` string field uses it; otherwise it serializes.
|
|
9364
9793
|
* Module-exported (not package surface) so sibling leaf executors read a task
|
|
@@ -9408,10 +9837,12 @@ function routerProfileExecution(profile, seam, mode) {
|
|
|
9408
9837
|
if (enabled && !suppliedNames.has(name)) throw new ValidationError(`routerInlineExecutor: AgentProfile enables tool ${JSON.stringify(name)} but the caller supplied no matching schema`);
|
|
9409
9838
|
if (!enabled && suppliedNames.has(name)) throw new ValidationError(`routerInlineExecutor: AgentProfile disables tool ${JSON.stringify(name)}`);
|
|
9410
9839
|
}
|
|
9840
|
+
const { tokenLimits, ...rest } = settings;
|
|
9411
9841
|
return {
|
|
9412
9842
|
systemPrompt: renderRouterProfilePrompt(profile),
|
|
9413
9843
|
...profileEffort ? { reasoningEffort: profileEffort } : {},
|
|
9414
|
-
...
|
|
9844
|
+
...rest,
|
|
9845
|
+
tokenLimits: enforceTokenLimits(tokenLimits, "router", "routerInlineExecutor")
|
|
9415
9846
|
};
|
|
9416
9847
|
}
|
|
9417
9848
|
/** Resolve the one model id that will cross the Router boundary from the exact profile only. */
|
|
@@ -9694,56 +10125,61 @@ function assertValidSpend(spend, label) {
|
|
|
9694
10125
|
* channels; iterations come from `'iteration'` events. Pure; `ms` stays zero (the
|
|
9695
10126
|
* pool does not read wall-clock). */
|
|
9696
10127
|
function spendFromUsageEvents(events) {
|
|
9697
|
-
const
|
|
9698
|
-
|
|
9699
|
-
|
|
9700
|
-
|
|
9701
|
-
|
|
9702
|
-
|
|
9703
|
-
for (const ev of events) if (ev.kind === "tokens") {
|
|
9704
|
-
addTokenUsage(tokens, ev);
|
|
9705
|
-
if (ev.tokensKnown === false) tokensKnown = false;
|
|
9706
|
-
} else if (ev.kind === "cost") {
|
|
9707
|
-
usd += ev.usd;
|
|
9708
|
-
usdEstimated += ev.usdEstimated ?? 0;
|
|
9709
|
-
if (ev.usdKnown === false) usdKnown = false;
|
|
9710
|
-
} 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() {
|
|
9711
10134
|
return {
|
|
9712
|
-
|
|
9713
|
-
|
|
9714
|
-
|
|
9715
|
-
|
|
9716
|
-
|
|
9717
|
-
|
|
9718
|
-
ms: 0
|
|
10135
|
+
tokens: zeroTokenUsage(),
|
|
10136
|
+
tokensKnown: true,
|
|
10137
|
+
usd: 0,
|
|
10138
|
+
usdEstimated: 0,
|
|
10139
|
+
usdKnown: true,
|
|
10140
|
+
iterations: 0
|
|
9719
10141
|
};
|
|
9720
10142
|
}
|
|
9721
|
-
|
|
9722
|
-
|
|
9723
|
-
|
|
9724
|
-
|
|
9725
|
-
|
|
9726
|
-
|
|
9727
|
-
|
|
9728
|
-
|
|
9729
|
-
|
|
9730
|
-
|
|
9731
|
-
|
|
9732
|
-
|
|
9733
|
-
usd += ev.usd;
|
|
9734
|
-
|
|
9735
|
-
|
|
9736
|
-
|
|
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) {
|
|
9737
10167
|
return {
|
|
9738
|
-
iterations,
|
|
9739
|
-
tokens,
|
|
9740
|
-
...tokensKnown ? {} : { tokensKnown: false },
|
|
9741
|
-
usd,
|
|
9742
|
-
...usdKnown ? {} : { usdKnown: false },
|
|
9743
|
-
...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 } : {},
|
|
9744
10174
|
ms: 0
|
|
9745
10175
|
};
|
|
9746
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
|
+
}
|
|
9747
10183
|
/**
|
|
9748
10184
|
* Create a conserved reservation pool from a root `Budget`. `now()` is injected so the
|
|
9749
10185
|
* deadline readout is deterministic; defaults to `Date.now` for non-test callers. The
|
|
@@ -10546,7 +10982,7 @@ function createScope(args) {
|
|
|
10546
10982
|
spec = prepared.spec;
|
|
10547
10983
|
identity = prepared.identity;
|
|
10548
10984
|
if (opts.key !== void 0 && !isCompleteIdentity(identity)) {
|
|
10549
|
-
args.pool.reconcile(reservation.ticket, zeroSpend
|
|
10985
|
+
args.pool.reconcile(reservation.ticket, zeroSpend());
|
|
10550
10986
|
permit.release();
|
|
10551
10987
|
return {
|
|
10552
10988
|
ok: false,
|
|
@@ -10557,7 +10993,7 @@ function createScope(args) {
|
|
|
10557
10993
|
if (!outcome.succeeded) throw new ValidationError(`scope.spawn: ${outcome.error}`);
|
|
10558
10994
|
resolved = outcome;
|
|
10559
10995
|
} catch (error) {
|
|
10560
|
-
args.pool.reconcile(reservation.ticket, zeroSpend
|
|
10996
|
+
args.pool.reconcile(reservation.ticket, zeroSpend());
|
|
10561
10997
|
permit.release();
|
|
10562
10998
|
throw error;
|
|
10563
10999
|
}
|
|
@@ -10622,7 +11058,7 @@ function createScope(args) {
|
|
|
10622
11058
|
label: opts.label,
|
|
10623
11059
|
...opts.assignmentId === void 0 ? {} : { assignmentId: opts.assignmentId },
|
|
10624
11060
|
...opts.key !== void 0 ? { key: opts.key } : {},
|
|
10625
|
-
spent: zeroSpend
|
|
11061
|
+
spent: zeroSpend(),
|
|
10626
11062
|
settled: void 0,
|
|
10627
11063
|
delivered: false,
|
|
10628
11064
|
executorDone: false,
|
|
@@ -10632,7 +11068,10 @@ function createScope(args) {
|
|
|
10632
11068
|
lastActivityAt: startedAt,
|
|
10633
11069
|
...executor.deliver ? { deliver: (message) => executor.deliver?.(message) !== false } : {},
|
|
10634
11070
|
...executor.progress ? { readProgress: executor.progress.bind(executor) } : {},
|
|
10635
|
-
...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)
|
|
10636
11075
|
};
|
|
10637
11076
|
children.set(id, live);
|
|
10638
11077
|
if (opts.key !== void 0) keyed.set(opts.key, {
|
|
@@ -10640,7 +11079,8 @@ function createScope(args) {
|
|
|
10640
11079
|
id,
|
|
10641
11080
|
identity
|
|
10642
11081
|
});
|
|
10643
|
-
const
|
|
11082
|
+
const profileRef = contentAddress(spec.profile);
|
|
11083
|
+
const spawnCommitted = args.blobs.put(profileRef, spec.profile).then(() => args.journal.appendEvent(args.root, {
|
|
10644
11084
|
kind: "spawned",
|
|
10645
11085
|
id,
|
|
10646
11086
|
parent: args.parentId,
|
|
@@ -10651,9 +11091,10 @@ function createScope(args) {
|
|
|
10651
11091
|
runtime: executor.runtime,
|
|
10652
11092
|
...ownedTreeRoot === void 0 ? {} : { ownedTreeRoot },
|
|
10653
11093
|
...identity ? { identity } : {},
|
|
11094
|
+
profileRef,
|
|
10654
11095
|
seq: ordinal,
|
|
10655
11096
|
at: new Date(now()).toISOString()
|
|
10656
|
-
}).then(async () => {
|
|
11097
|
+
})).then(async () => {
|
|
10657
11098
|
if (args.workerTraceUnpropagated === void 0 || workerTrace === void 0) return;
|
|
10658
11099
|
await args.journal.appendEvent(args.root, {
|
|
10659
11100
|
kind: "trace-unpropagated",
|
|
@@ -10786,7 +11227,9 @@ function createScope(args) {
|
|
|
10786
11227
|
runtime: executor.runtime,
|
|
10787
11228
|
...identity ? { identity } : {},
|
|
10788
11229
|
budget: opts.budget,
|
|
10789
|
-
depth: args.depth
|
|
11230
|
+
depth: args.depth,
|
|
11231
|
+
attemptId,
|
|
11232
|
+
startedAt
|
|
10790
11233
|
}
|
|
10791
11234
|
}, { signal: args.signal });
|
|
10792
11235
|
live.settled = runChild(live, executor, controller, task, opts, args.pool, reservation.ticket, args.blobs, now, materializationCommitted, {
|
|
@@ -10809,7 +11252,7 @@ function createScope(args) {
|
|
|
10809
11252
|
permit.release();
|
|
10810
11253
|
clearChildDeadline?.();
|
|
10811
11254
|
if (cascadeAbort) args.signal.removeEventListener("abort", cascadeAbort);
|
|
10812
|
-
args.pool.reconcile(reservation.ticket, zeroSpend
|
|
11255
|
+
args.pool.reconcile(reservation.ticket, zeroSpend());
|
|
10813
11256
|
throw err;
|
|
10814
11257
|
}
|
|
10815
11258
|
}
|
|
@@ -10903,12 +11346,13 @@ function createScope(args) {
|
|
|
10903
11346
|
id,
|
|
10904
11347
|
status: "waiting",
|
|
10905
11348
|
runtime: "wait",
|
|
11349
|
+
abortChild: (reason) => waitAbort.abort(reason),
|
|
10906
11350
|
budget: {
|
|
10907
11351
|
maxIterations: 0,
|
|
10908
11352
|
maxTokens: 0
|
|
10909
11353
|
},
|
|
10910
11354
|
label: opts.label,
|
|
10911
|
-
spent: zeroSpend
|
|
11355
|
+
spent: zeroSpend(),
|
|
10912
11356
|
settled: void 0,
|
|
10913
11357
|
delivered: false,
|
|
10914
11358
|
executorDone: false,
|
|
@@ -10981,7 +11425,7 @@ function createScope(args) {
|
|
|
10981
11425
|
kind: "done",
|
|
10982
11426
|
out: resolution.outcome,
|
|
10983
11427
|
outRef,
|
|
10984
|
-
spent: zeroSpend
|
|
11428
|
+
spent: zeroSpend(),
|
|
10985
11429
|
trace: {
|
|
10986
11430
|
status: "unavailable",
|
|
10987
11431
|
reason: "not-an-executor"
|
|
@@ -11032,6 +11476,18 @@ function createScope(args) {
|
|
|
11032
11476
|
...child.spent.usdKnown === false ? { usdKnown: false } : {}
|
|
11033
11477
|
}, fromExecutor, opts.now ?? now(), opts.stallAfterMs ?? 18e4);
|
|
11034
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
|
+
}
|
|
11035
11491
|
function traceSource(nodeId) {
|
|
11036
11492
|
const child = children.get(nodeId);
|
|
11037
11493
|
if (!child) return void 0;
|
|
@@ -11041,6 +11497,24 @@ function createScope(args) {
|
|
|
11041
11497
|
return;
|
|
11042
11498
|
}
|
|
11043
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
|
+
}
|
|
11044
11518
|
async function meterInternal(spend, detail, providerModel, accountingOnly = false) {
|
|
11045
11519
|
if (args.signal.aborted) throw new ValidationError("scope.meter: cannot record new driver work after scope abort");
|
|
11046
11520
|
const seq = meterSeq++;
|
|
@@ -11088,6 +11562,8 @@ function createScope(args) {
|
|
|
11088
11562
|
wait,
|
|
11089
11563
|
progress,
|
|
11090
11564
|
traceSource,
|
|
11565
|
+
interactive,
|
|
11566
|
+
cancel,
|
|
11091
11567
|
signal: args.signal,
|
|
11092
11568
|
meter: (spend, detail) => meterInternal(spend, detail),
|
|
11093
11569
|
...resume ? { resume } : {},
|
|
@@ -11100,7 +11576,13 @@ function createScope(args) {
|
|
|
11100
11576
|
get workerCapacity() {
|
|
11101
11577
|
return {
|
|
11102
11578
|
live: liveWorkerCapacity.live,
|
|
11103
|
-
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
|
+
})))
|
|
11104
11586
|
};
|
|
11105
11587
|
}
|
|
11106
11588
|
};
|
|
@@ -11340,7 +11822,9 @@ async function finalizeSettlement(child, settlement, seq, args, now) {
|
|
|
11340
11822
|
status: "down",
|
|
11341
11823
|
reason: settlement.reason,
|
|
11342
11824
|
infra: settlement.infra,
|
|
11343
|
-
spent: child.spent
|
|
11825
|
+
spent: child.spent,
|
|
11826
|
+
restartCount: settlement.restartCount,
|
|
11827
|
+
...settledNodeEvidence(child, settlement, settledAt)
|
|
11344
11828
|
}
|
|
11345
11829
|
}, { signal: args.signal });
|
|
11346
11830
|
return {
|
|
@@ -11393,7 +11877,8 @@ async function finalizeSettlement(child, settlement, seq, args, now) {
|
|
|
11393
11877
|
outRef: settlement.outRef,
|
|
11394
11878
|
score: settlement.verdict?.score,
|
|
11395
11879
|
valid: settlement.verdict?.valid,
|
|
11396
|
-
spent: settlement.spent
|
|
11880
|
+
spent: settlement.spent,
|
|
11881
|
+
...settledNodeEvidence(child, settlement, settledAt)
|
|
11397
11882
|
}
|
|
11398
11883
|
}, { signal: args.signal });
|
|
11399
11884
|
return {
|
|
@@ -11409,6 +11894,26 @@ async function finalizeSettlement(child, settlement, seq, args, now) {
|
|
|
11409
11894
|
seq
|
|
11410
11895
|
};
|
|
11411
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
|
+
}
|
|
11412
11917
|
/** Journal a wait-state's settlement as a `woken` event and project it onto the same `Settled`
|
|
11413
11918
|
* the driver branches on. `by` names WHY it woke — `fired` / `timeout` / `cancelled` — which is
|
|
11414
11919
|
* the fact a resumed reader needs and cannot recover from a payload it may never fetch. */
|
|
@@ -11720,30 +12225,20 @@ function freezeCorrelation(value) {
|
|
|
11720
12225
|
* now reconciles its real partial spend instead of refunding work the provider already billed.
|
|
11721
12226
|
*/
|
|
11722
12227
|
async function foldStream(stream, onProgress, signal) {
|
|
11723
|
-
const
|
|
11724
|
-
let tokensKnown = true;
|
|
11725
|
-
let usd = 0;
|
|
11726
|
-
let usdKnown = true;
|
|
11727
|
-
let iterations = 0;
|
|
12228
|
+
const totals = newUsageTotals();
|
|
11728
12229
|
const iterator = stream[Symbol.asyncIterator]();
|
|
11729
12230
|
try {
|
|
11730
12231
|
for (;;) {
|
|
11731
12232
|
const next = signal ? await awaitAbortable(Promise.resolve(iterator.next()), signal) : await iterator.next();
|
|
11732
12233
|
if (next.done) break;
|
|
11733
12234
|
const ev = next.value;
|
|
11734
|
-
|
|
11735
|
-
addTokenUsage(tokens, ev);
|
|
11736
|
-
if (ev.tokensKnown === false) tokensKnown = false;
|
|
11737
|
-
} else if (ev.kind === "cost") {
|
|
11738
|
-
usd += ev.usd;
|
|
11739
|
-
if (ev.usdKnown === false) usdKnown = false;
|
|
11740
|
-
} else iterations += 1;
|
|
12235
|
+
meterUsageEvent(totals, ev);
|
|
11741
12236
|
onProgress?.({
|
|
11742
|
-
iterations,
|
|
11743
|
-
tokens: cloneTokenUsage(tokens),
|
|
11744
|
-
...tokensKnown ? {} : { tokensKnown: false },
|
|
11745
|
-
usd,
|
|
11746
|
-
...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 },
|
|
11747
12242
|
ms: 0
|
|
11748
12243
|
});
|
|
11749
12244
|
}
|
|
@@ -11751,14 +12246,7 @@ async function foldStream(stream, onProgress, signal) {
|
|
|
11751
12246
|
Promise.resolve(iterator.return?.()).catch(() => void 0);
|
|
11752
12247
|
throw error;
|
|
11753
12248
|
}
|
|
11754
|
-
return
|
|
11755
|
-
iterations,
|
|
11756
|
-
tokens,
|
|
11757
|
-
...tokensKnown ? {} : { tokensKnown: false },
|
|
11758
|
-
usd,
|
|
11759
|
-
...usdKnown ? {} : { usdKnown: false },
|
|
11760
|
-
ms: 0
|
|
11761
|
-
};
|
|
12249
|
+
return spendFromUsageTotals(totals);
|
|
11762
12250
|
}
|
|
11763
12251
|
/** Usage events carry measured increments; the terminal artifact carries whether a provider omitted
|
|
11764
12252
|
* a whole accounting channel. Preserve those unknowns on the common streaming path. */
|
|
@@ -11819,13 +12307,12 @@ function downRecord(reason, infra, trace, metered, providerModel) {
|
|
|
11819
12307
|
...metered ? { metered } : {}
|
|
11820
12308
|
};
|
|
11821
12309
|
}
|
|
11822
|
-
|
|
11823
|
-
|
|
11824
|
-
|
|
11825
|
-
|
|
11826
|
-
|
|
11827
|
-
|
|
11828
|
-
};
|
|
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
|
+
});
|
|
11829
12316
|
}
|
|
11830
12317
|
function isAsyncIterable(value) {
|
|
11831
12318
|
return typeof value === "object" && value !== null && typeof value[Symbol.asyncIterator] === "function";
|
|
@@ -11944,7 +12431,7 @@ const driverExecutorFactory = (rawSpec, ctx) => {
|
|
|
11944
12431
|
meteredSpend = nonZeroOrUndef(sumMetered(events));
|
|
11945
12432
|
accounting = {
|
|
11946
12433
|
reported: childWork,
|
|
11947
|
-
reservation: addSpend
|
|
12434
|
+
reservation: addSpend(childWork, meteredSpend ?? zeroSpend())
|
|
11948
12435
|
};
|
|
11949
12436
|
const verdict = deriveDeliveryVerdict(settled, out);
|
|
11950
12437
|
artifact = {
|
|
@@ -12028,12 +12515,7 @@ function isSettled(ev) {
|
|
|
12028
12515
|
/** Sum the conserved spend over the nested tree's settled events — the honest per-channel
|
|
12029
12516
|
* roll-up of the whole sub-tree's child WORK. */
|
|
12030
12517
|
function sumSpend(settled) {
|
|
12031
|
-
const total =
|
|
12032
|
-
iterations: 0,
|
|
12033
|
-
tokens: zeroTokenUsage(),
|
|
12034
|
-
usd: 0,
|
|
12035
|
-
ms: 0
|
|
12036
|
-
};
|
|
12518
|
+
const total = zeroSpend();
|
|
12037
12519
|
for (const ev of settled) {
|
|
12038
12520
|
total.iterations += ev.spent.iterations;
|
|
12039
12521
|
addTokenUsage(total.tokens, ev.spent.tokens);
|
|
@@ -12048,12 +12530,7 @@ function sumSpend(settled) {
|
|
|
12048
12530
|
* own turns + any sub-driver inference already re-homed into this tree). Re-homed up to the parent
|
|
12049
12531
|
* as one `metered` event; never reconciled (already pool-debited live via `observe`). */
|
|
12050
12532
|
function sumMetered(events) {
|
|
12051
|
-
const total =
|
|
12052
|
-
iterations: 0,
|
|
12053
|
-
tokens: zeroTokenUsage(),
|
|
12054
|
-
usd: 0,
|
|
12055
|
-
ms: 0
|
|
12056
|
-
};
|
|
12533
|
+
const total = zeroSpend();
|
|
12057
12534
|
for (const ev of events) {
|
|
12058
12535
|
if (ev.kind !== "metered") continue;
|
|
12059
12536
|
total.iterations += ev.spend.iterations;
|
|
@@ -12065,28 +12542,6 @@ function sumMetered(events) {
|
|
|
12065
12542
|
}
|
|
12066
12543
|
return total;
|
|
12067
12544
|
}
|
|
12068
|
-
function zeroSpend() {
|
|
12069
|
-
return {
|
|
12070
|
-
iterations: 0,
|
|
12071
|
-
tokens: zeroTokenUsage(),
|
|
12072
|
-
usd: 0,
|
|
12073
|
-
ms: 0
|
|
12074
|
-
};
|
|
12075
|
-
}
|
|
12076
|
-
function addSpend$1(a, b) {
|
|
12077
|
-
return {
|
|
12078
|
-
iterations: a.iterations + b.iterations,
|
|
12079
|
-
tokens: (() => {
|
|
12080
|
-
const tokens = cloneTokenUsage(a.tokens);
|
|
12081
|
-
addTokenUsage(tokens, b.tokens);
|
|
12082
|
-
return tokens;
|
|
12083
|
-
})(),
|
|
12084
|
-
...a.tokensKnown === false || b.tokensKnown === false ? { tokensKnown: false } : {},
|
|
12085
|
-
usd: a.usd + b.usd,
|
|
12086
|
-
...a.usdKnown === false || b.usdKnown === false ? { usdKnown: false } : {},
|
|
12087
|
-
ms: a.ms + b.ms
|
|
12088
|
-
};
|
|
12089
|
-
}
|
|
12090
12545
|
/** An all-zero spend that carries an UNKNOWN marker counts as non-zero: a sub-driver whose turns
|
|
12091
12546
|
* went unmeasured did real work, and dropping its `metered` event here would re-hide upstream the
|
|
12092
12547
|
* very turn the driver refused to skip. */
|
|
@@ -12109,7 +12564,7 @@ async function safeRollup(journal, nestedRoot) {
|
|
|
12109
12564
|
metered,
|
|
12110
12565
|
accounting: {
|
|
12111
12566
|
reported: childWork,
|
|
12112
|
-
reservation: addSpend
|
|
12567
|
+
reservation: addSpend(childWork, metered ?? zeroSpend())
|
|
12113
12568
|
}
|
|
12114
12569
|
};
|
|
12115
12570
|
} catch {
|
|
@@ -12622,6 +13077,8 @@ function createSupervisor() {
|
|
|
12622
13077
|
ok: false,
|
|
12623
13078
|
error: new RuntimeRunStateError("supervisor: root execution did not start")
|
|
12624
13079
|
};
|
|
13080
|
+
let teardownUnconfirmed = [];
|
|
13081
|
+
let teardownSeq = 0;
|
|
12625
13082
|
let executionAborted = controller.signal.aborted;
|
|
12626
13083
|
let allChildrenDownAtSettle = false;
|
|
12627
13084
|
let downCountAtSettle = 0;
|
|
@@ -12643,7 +13100,16 @@ function createSupervisor() {
|
|
|
12643
13100
|
clearRootDeadline?.();
|
|
12644
13101
|
const settleGraceMs = actOutcome.ok === false && !controller.signal.aborted ? boundedSettleGrace(opts.childSettleGraceMs, rootDeadlineAtMs, now) : 0;
|
|
12645
13102
|
try {
|
|
12646
|
-
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
|
+
});
|
|
12647
13113
|
} catch (error) {
|
|
12648
13114
|
if (actOutcome?.ok !== false) actOutcome = {
|
|
12649
13115
|
ok: false,
|
|
@@ -12677,6 +13143,7 @@ function createSupervisor() {
|
|
|
12677
13143
|
tree,
|
|
12678
13144
|
spentTotal,
|
|
12679
13145
|
providerModel,
|
|
13146
|
+
...teardownUnconfirmed.length > 0 ? { teardownUnconfirmed } : {},
|
|
12680
13147
|
...gaps.length > 0 ? { spendGaps: gaps } : {},
|
|
12681
13148
|
...isNonEmptySpend(driverInference) ? { spentBreakdown: {
|
|
12682
13149
|
driverInference,
|
|
@@ -12695,6 +13162,7 @@ function createSupervisor() {
|
|
|
12695
13162
|
downCount: breaker.downCount(),
|
|
12696
13163
|
spentTotal,
|
|
12697
13164
|
providerModel,
|
|
13165
|
+
...teardownUnconfirmed.length > 0 ? { teardownUnconfirmed } : {},
|
|
12698
13166
|
...gaps.length > 0 ? { spendGaps: gaps } : {}
|
|
12699
13167
|
};
|
|
12700
13168
|
const lifecycle = classifyNoWinner(executionAborted, pool, opts, breaker, deadlineExceeded, allChildrenDownAtSettle, downCountAtSettle);
|
|
@@ -12839,10 +13307,7 @@ function wrapJournalForBreaker(journal, breaker) {
|
|
|
12839
13307
|
*/
|
|
12840
13308
|
async function drainLiveChildren(scope, controller, settleGraceMs = 0) {
|
|
12841
13309
|
const view = scope.view;
|
|
12842
|
-
if (!(view.inFlight > 0 || view.waiting > 0))
|
|
12843
|
-
if (scope.workerCapacity.live > 0) throw new RuntimeRunStateError(`supervisor: cleanup ended with ${scope.workerCapacity.live} executor resource(s) not confirmed destroyed`);
|
|
12844
|
-
return;
|
|
12845
|
-
}
|
|
13310
|
+
if (!(view.inFlight > 0 || view.waiting > 0)) return unconfirmedTeardowns(scope);
|
|
12846
13311
|
let graceTimer;
|
|
12847
13312
|
if (settleGraceMs > 0 && !controller.signal.aborted) {
|
|
12848
13313
|
graceTimer = setTimeout(() => controller.abort("root driver failed; child settle grace expired"), settleGraceMs);
|
|
@@ -12854,7 +13319,26 @@ async function drainLiveChildren(scope, controller, settleGraceMs = 0) {
|
|
|
12854
13319
|
if (graceTimer !== void 0) clearTimeout(graceTimer);
|
|
12855
13320
|
}
|
|
12856
13321
|
const after = scope.view;
|
|
12857
|
-
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}` : ""}`;
|
|
12858
13342
|
}
|
|
12859
13343
|
/** The settle window a failed driver's children actually get: the caller's grace, never past the
|
|
12860
13344
|
* run's own deadline. `0` (the default) keeps the historical immediate cascade. */
|
|
@@ -13019,23 +13503,6 @@ function accumulate(a, b) {
|
|
|
13019
13503
|
if (b.usdEstimated !== void 0) a.usdEstimated = (a.usdEstimated ?? 0) + b.usdEstimated;
|
|
13020
13504
|
a.ms += b.ms;
|
|
13021
13505
|
}
|
|
13022
|
-
/** Sum two conserved-spend tallies per channel — the child-work journal sum + the drivers' own
|
|
13023
|
-
* metered inference, so `spentTotal` is the true cost of the run. */
|
|
13024
|
-
function addSpend(a, b) {
|
|
13025
|
-
return {
|
|
13026
|
-
iterations: a.iterations + b.iterations,
|
|
13027
|
-
tokens: (() => {
|
|
13028
|
-
const tokens = cloneTokenUsage(a.tokens);
|
|
13029
|
-
addTokenUsage(tokens, b.tokens);
|
|
13030
|
-
return tokens;
|
|
13031
|
-
})(),
|
|
13032
|
-
...a.tokensKnown === false || b.tokensKnown === false ? { tokensKnown: false } : {},
|
|
13033
|
-
usd: a.usd + b.usd,
|
|
13034
|
-
...a.usdKnown === false || b.usdKnown === false ? { usdKnown: false } : {},
|
|
13035
|
-
...usdEstimatedOf(a, b),
|
|
13036
|
-
ms: a.ms + b.ms
|
|
13037
|
-
};
|
|
13038
|
-
}
|
|
13039
13506
|
/** True when any driver metered inference this run (so the winner carries a `spentBreakdown`).
|
|
13040
13507
|
* Checks every channel `addSpend` sums — including `ms` — so the gate stays consistent with the
|
|
13041
13508
|
* total even though the coordination driver currently stamps `ms: 0`. */
|
|
@@ -13043,6 +13510,6 @@ function isNonEmptySpend(s) {
|
|
|
13043
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;
|
|
13044
13511
|
}
|
|
13045
13512
|
//#endregion
|
|
13046
|
-
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 };
|
|
13047
13514
|
|
|
13048
|
-
//# sourceMappingURL=supervisor-
|
|
13515
|
+
//# sourceMappingURL=supervisor-DBVlPONC.js.map
|