@tangle-network/agent-runtime 0.208.0 → 0.209.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{activation-9wJniom2.js → activation-Cjhm5Tds.js} +2 -2
- package/dist/{activation-9wJniom2.js.map → activation-Cjhm5Tds.js.map} +1 -1
- package/dist/{activation-Dan50rKs.d.ts → activation-tFdeirCa.d.ts} +2 -2
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +2 -2
- package/dist/{coordination-driver-CqZGBqdt.js → coordination-driver-C-hPz1zy.js} +33 -6
- package/dist/coordination-driver-C-hPz1zy.js.map +1 -0
- package/dist/{delegate-CU7bWMuW.js → delegate-CB4CkJdV.js} +2 -2
- package/dist/{delegate-CU7bWMuW.js.map → delegate-CB4CkJdV.js.map} +1 -1
- package/dist/durable.d.ts +2 -2
- package/dist/durable.js +2 -2
- package/dist/{graph-B0cNCFmD.js → graph-Ud2-Ytos.js} +3 -3
- package/dist/{graph-B0cNCFmD.js.map → graph-Ud2-Ytos.js.map} +1 -1
- package/dist/{improvement-cycle-Bsm8TBDT.js → improvement-cycle-B7ia6rTj.js} +3 -3
- package/dist/{improvement-cycle-Bsm8TBDT.js.map → improvement-cycle-B7ia6rTj.js.map} +1 -1
- package/dist/{index-CHkf3b2C.d.ts → index-0p5DiJoy.d.ts} +3 -124
- package/dist/index.d.ts +4 -4
- package/dist/index.js +7 -7
- package/dist/intelligence.d.ts +2 -2
- package/dist/intelligence.js +3 -3
- package/dist/kernel.d.ts +3 -3
- package/dist/kernel.js +8 -8
- package/dist/{loop-runner-bin-CLxG15ta.js → loop-runner-bin-B30d3Yla.js} +3 -3
- package/dist/{loop-runner-bin-CLxG15ta.js.map → loop-runner-bin-B30d3Yla.js.map} +1 -1
- package/dist/{loop-runner-bin-BUVcdgNU.d.ts → loop-runner-bin-q-xGzEK9.d.ts} +3 -3
- package/dist/loop-runner-bin.d.ts +1 -1
- package/dist/loop-runner-bin.js +1 -1
- package/dist/mcp/bin.js +3 -3
- package/dist/mcp/index.d.ts +2 -2
- package/dist/mcp/index.js +4 -4
- package/dist/{provision-supervisor-CEMk0grI.js → provision-supervisor-C-nLaaQ_.js} +3 -3
- package/dist/{provision-supervisor-CEMk0grI.js.map → provision-supervisor-C-nLaaQ_.js.map} +1 -1
- package/dist/{redact-BMwd8IBm.js → redact-va_1mmv8.js} +290 -55
- package/dist/redact-va_1mmv8.js.map +1 -0
- package/dist/{runtime-ByeeZbA3.js → runtime-D0_b9wFH.js} +12 -8
- package/dist/{runtime-ByeeZbA3.js.map → runtime-D0_b9wFH.js.map} +1 -1
- package/dist/{server-Bl1F2Y3v.js → server-pq1x3C2i.js} +3 -3
- package/dist/{server-Bl1F2Y3v.js.map → server-pq1x3C2i.js.map} +1 -1
- package/dist/{stream-agent-turn-B3NfR48z.d.ts → stream-agent-turn-BaKYHbHg.d.ts} +161 -20
- package/dist/{structural-rollout-DsGWoyj4.js → structural-rollout-BaYBLUeI.js} +2 -2
- package/dist/{structural-rollout-DsGWoyj4.js.map → structural-rollout-BaYBLUeI.js.map} +1 -1
- package/dist/{supervise-D3r_gEyO.js → supervise-CMWpmY_1.js} +54 -16
- package/dist/supervise-CMWpmY_1.js.map +1 -0
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +12 -12
- package/dist/tui/index.d.ts +1 -1
- package/dist/tui/index.js +1 -1
- package/package.json +4 -4
- package/dist/coordination-driver-CqZGBqdt.js.map +0 -1
- package/dist/redact-BMwd8IBm.js.map +0 -1
- package/dist/supervise-D3r_gEyO.js.map +0 -1
|
@@ -4113,6 +4113,69 @@ function publicCreateOptions(create) {
|
|
|
4113
4113
|
};
|
|
4114
4114
|
}
|
|
4115
4115
|
//#endregion
|
|
4116
|
+
//#region src/runtime/supervise/resources.ts
|
|
4117
|
+
/** Validate caller-owned names and units without assigning domain meaning to them. */
|
|
4118
|
+
function assertResources(resources, kind, label) {
|
|
4119
|
+
if (resources === void 0) return;
|
|
4120
|
+
if (resources === null || typeof resources !== "object" || Array.isArray(resources)) throw new Error(`${label} must be a resource map`);
|
|
4121
|
+
for (const [name, resource] of Object.entries(resources)) {
|
|
4122
|
+
if (!name.trim() || !resource || typeof resource !== "object" || typeof resource.unit !== "string" || !resource.unit.trim()) throw new Error(`${label}: resource names and units must be non-empty strings`);
|
|
4123
|
+
const value = kind === "limit" ? "limit" in resource ? resource.limit : void 0 : "amount" in resource ? resource.amount : void 0;
|
|
4124
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) throw new Error(`${label}.${name}.${kind} must be a non-negative safe integer`);
|
|
4125
|
+
if (kind === "amount" && (!("known" in resource) || typeof resource.known !== "boolean")) throw new Error(`${label}.${name}.known must be a boolean`);
|
|
4126
|
+
}
|
|
4127
|
+
}
|
|
4128
|
+
/** Missing contributors are not usage claims; enforced omissions are marked before aggregation.
|
|
4129
|
+
* Overflow retains a safe lower bound and marks it unknown, preserving readable component receipts. */
|
|
4130
|
+
function addResourceSpend(...maps) {
|
|
4131
|
+
const totals = /* @__PURE__ */ new Map();
|
|
4132
|
+
for (const resources of maps) {
|
|
4133
|
+
assertResources(resources, "amount", "resource spend");
|
|
4134
|
+
for (const [name, resource] of Object.entries(resources ?? {})) {
|
|
4135
|
+
const prior = totals.get(name);
|
|
4136
|
+
if (prior && prior.unit !== resource.unit) throw new Error(`resource ${name}: unit mismatch`);
|
|
4137
|
+
const amount = (prior?.amount ?? 0) + resource.amount;
|
|
4138
|
+
totals.set(name, {
|
|
4139
|
+
unit: resource.unit,
|
|
4140
|
+
amount: Math.min(amount, Number.MAX_SAFE_INTEGER),
|
|
4141
|
+
known: (prior?.known ?? true) && resource.known && Number.isSafeInteger(amount)
|
|
4142
|
+
});
|
|
4143
|
+
}
|
|
4144
|
+
}
|
|
4145
|
+
return totals.size ? { resources: Object.fromEntries(totals) } : {};
|
|
4146
|
+
}
|
|
4147
|
+
/** A terminal omission under an enforced ceiling is unknown, never measured zero. */
|
|
4148
|
+
function withBudgetResources(spend, budget, notStarted = false) {
|
|
4149
|
+
const resources = new Map(Object.entries(addResourceSpend(spend.resources).resources ?? {}));
|
|
4150
|
+
for (const [name, limit] of Object.entries(budget.resources ?? {})) {
|
|
4151
|
+
const observed = resources.get(name);
|
|
4152
|
+
if (observed && observed.unit !== limit.unit) throw new Error(`resource ${name}: unit mismatch`);
|
|
4153
|
+
if (!observed) resources.set(name, {
|
|
4154
|
+
unit: limit.unit,
|
|
4155
|
+
amount: 0,
|
|
4156
|
+
known: notStarted
|
|
4157
|
+
});
|
|
4158
|
+
}
|
|
4159
|
+
return resources.size ? {
|
|
4160
|
+
...spend,
|
|
4161
|
+
resources: Object.fromEntries(resources)
|
|
4162
|
+
} : spend;
|
|
4163
|
+
}
|
|
4164
|
+
/** Stream increments and a terminal total describe the same work; never sum them twice. */
|
|
4165
|
+
function resourceTelemetry(streamed, terminal) {
|
|
4166
|
+
const resources = new Map(Object.entries(addResourceSpend(terminal.resources).resources ?? {}));
|
|
4167
|
+
for (const [name, value] of Object.entries(streamed.resources ?? {})) {
|
|
4168
|
+
const other = resources.get(name);
|
|
4169
|
+
if (other && other.unit !== value.unit) throw new Error(`resource ${name}: unit mismatch`);
|
|
4170
|
+
resources.set(name, {
|
|
4171
|
+
...value,
|
|
4172
|
+
amount: Math.max(value.amount, other?.amount ?? 0),
|
|
4173
|
+
known: value.known && (other?.known ?? true) && (other === void 0 || other.amount === value.amount)
|
|
4174
|
+
});
|
|
4175
|
+
}
|
|
4176
|
+
return addResourceSpend(Object.fromEntries(resources));
|
|
4177
|
+
}
|
|
4178
|
+
//#endregion
|
|
4116
4179
|
//#region src/sanitize.ts
|
|
4117
4180
|
/** Strip PII and large blobs from a `KnowledgeReadinessReport` for safe telemetry emission. @stable */
|
|
4118
4181
|
function sanitizeKnowledgeReadinessReport(report, options = {}) {
|
|
@@ -6150,30 +6213,23 @@ function retainedTurnMaterial(input, contextTransfer) {
|
|
|
6150
6213
|
}
|
|
6151
6214
|
//#endregion
|
|
6152
6215
|
//#region src/runtime/retained-run-start.ts
|
|
6153
|
-
const MAX_RETAINED_IDENTITY_BYTES = 128;
|
|
6154
6216
|
/**
|
|
6155
6217
|
* Mint deterministic dispatch coordinates from the two caller-supplied keys.
|
|
6156
6218
|
* The same `(idempotencyKey, turnId)` pair yields the same coordinates in
|
|
6157
6219
|
* every process, so a pre-dispatch admission record always names the exact
|
|
6158
|
-
* session and execution the dispatch will request.
|
|
6159
|
-
*
|
|
6160
|
-
* provider storage layers never receive an overlong composite identifier.
|
|
6220
|
+
* session and execution the dispatch will request. A full SHA-256 digest
|
|
6221
|
+
* keeps provider session identifiers bounded and safe for workspace paths.
|
|
6161
6222
|
*/
|
|
6162
6223
|
function mintRetainedIdentity(idempotencyKey, turnId) {
|
|
6163
|
-
const base = `${encodeURIComponent(idempotencyKey)}:${encodeURIComponent(turnId)}`;
|
|
6164
6224
|
const digest = canonicalCandidateDigest({
|
|
6165
6225
|
kind: "retained-identity.v1",
|
|
6166
|
-
base
|
|
6226
|
+
base: `${encodeURIComponent(idempotencyKey)}:${encodeURIComponent(turnId)}`
|
|
6167
6227
|
}).slice(7);
|
|
6168
6228
|
return {
|
|
6169
|
-
sessionId:
|
|
6170
|
-
executionId:
|
|
6229
|
+
sessionId: `retained-session-${digest}`,
|
|
6230
|
+
executionId: `retained-execution-${digest}`
|
|
6171
6231
|
};
|
|
6172
6232
|
}
|
|
6173
|
-
function boundedRetainedIdentity(prefix, base, digest) {
|
|
6174
|
-
const readable = `${prefix}:${base}`;
|
|
6175
|
-
return readable.length <= MAX_RETAINED_IDENTITY_BYTES ? readable : `${prefix}:${digest}`;
|
|
6176
|
-
}
|
|
6177
6233
|
/**
|
|
6178
6234
|
* Dispatch one detached, replayable run and return only after exact durable
|
|
6179
6235
|
* coordinates are confirmed by the provider and persisted by the caller.
|
|
@@ -6188,12 +6244,14 @@ function boundedRetainedIdentity(prefix, base, digest) {
|
|
|
6188
6244
|
async function startRetainedRun(options) {
|
|
6189
6245
|
assertStableText(options.environment.idempotencyKey, "environment idempotency key");
|
|
6190
6246
|
assertStableText(options.turn.turnId, "turn idempotency key");
|
|
6191
|
-
if (options.identity !== void 0) {
|
|
6192
|
-
assertStableText(options.identity.sessionId, "retained session id");
|
|
6193
|
-
assertStableText(options.identity.executionId, "retained execution id");
|
|
6194
|
-
}
|
|
6195
6247
|
if (typeof options.onAdmission !== "function") throw new Error("startRetainedRun requires an awaited onAdmission durability hook");
|
|
6196
|
-
const
|
|
6248
|
+
const { sessionId, executionId } = options.identity ?? options.intent ?? mintRetainedIdentity(options.environment.idempotencyKey, options.turn.turnId);
|
|
6249
|
+
const identity = {
|
|
6250
|
+
sessionId,
|
|
6251
|
+
executionId
|
|
6252
|
+
};
|
|
6253
|
+
assertStableText(identity.sessionId, "retained session id");
|
|
6254
|
+
assertStableText(identity.executionId, "retained execution id");
|
|
6197
6255
|
const contextTransfer = retainedContextTransfer(options.turn.contextTransfer);
|
|
6198
6256
|
if (!options.provider.get) throw new Error(`provider "${options.provider.name}" cannot reconstruct an environment by id`);
|
|
6199
6257
|
const intent = retainedRunIntent(options, identity, contextTransfer);
|
|
@@ -6422,7 +6480,9 @@ async function recoverRetainedRun(options) {
|
|
|
6422
6480
|
}
|
|
6423
6481
|
/** Check public replay material before reconnecting an already-dispatched execution. */
|
|
6424
6482
|
function assertRetainedRunReplayMaterial(provider, replay, admission) {
|
|
6425
|
-
const identity = replay.identity ??
|
|
6483
|
+
const identity = replay.identity ?? admission;
|
|
6484
|
+
assertStableText(identity.sessionId, "retained session id");
|
|
6485
|
+
assertStableText(identity.executionId, "retained execution id");
|
|
6426
6486
|
assertExactRetainedRunIntent(admission, retainedRunIntent({
|
|
6427
6487
|
...replay,
|
|
6428
6488
|
provider
|
|
@@ -6849,6 +6909,7 @@ function unmeteredSpend(ms) {
|
|
|
6849
6909
|
/** Copy a conserved spend without dropping a completeness marker or the catalog-priced part. */
|
|
6850
6910
|
function cloneSpend(spend) {
|
|
6851
6911
|
return {
|
|
6912
|
+
...addResourceSpend(spend.resources),
|
|
6852
6913
|
iterations: spend.iterations,
|
|
6853
6914
|
tokens: cloneTokenUsage(spend.tokens),
|
|
6854
6915
|
...spend.tokensKnown === false ? { tokensKnown: false } : {},
|
|
@@ -6868,6 +6929,7 @@ function addSpend(a, b) {
|
|
|
6868
6929
|
const tokens = cloneTokenUsage(a.tokens);
|
|
6869
6930
|
addTokenUsage(tokens, b.tokens);
|
|
6870
6931
|
return {
|
|
6932
|
+
...addResourceSpend(a.resources, b.resources),
|
|
6871
6933
|
iterations: a.iterations + b.iterations,
|
|
6872
6934
|
tokens,
|
|
6873
6935
|
...a.tokensKnown === false || b.tokensKnown === false ? { tokensKnown: false } : {},
|
|
@@ -9009,7 +9071,7 @@ async function routerChatWithUsage(cfg, messages, opts) {
|
|
|
9009
9071
|
}
|
|
9010
9072
|
function parseChatResult(json, model, transportAttempts) {
|
|
9011
9073
|
const data = json;
|
|
9012
|
-
const { usage, costUsd, costProvenance, billedCostUsd, cache } = meterTurn(data.usage, model);
|
|
9074
|
+
const { usage, resources, costUsd, costProvenance, billedCostUsd, cache } = meterTurn(data.usage, model, transportAttempts);
|
|
9013
9075
|
const msg = data.choices?.[0]?.message;
|
|
9014
9076
|
if (!msg) throw new ValidationError$1("router completion: no choices[0].message");
|
|
9015
9077
|
const { content, reasoning } = splitReasoning(msg?.content ?? "", msg?.reasoning ?? msg?.reasoning_content);
|
|
@@ -9019,6 +9081,7 @@ function parseChatResult(json, model, transportAttempts) {
|
|
|
9019
9081
|
...reportedModel(data.model) ? { model: reportedModel(data.model) } : {},
|
|
9020
9082
|
...reasoning ? { reasoning } : {},
|
|
9021
9083
|
...usage ? { usage } : {},
|
|
9084
|
+
...resources ? { resources } : {},
|
|
9022
9085
|
...costUsd !== void 0 ? { costUsd } : {},
|
|
9023
9086
|
...costProvenance ? { costProvenance } : {},
|
|
9024
9087
|
...billedCostUsd !== void 0 ? { billedCostUsd } : {},
|
|
@@ -9085,13 +9148,14 @@ async function routerChatWithTools(cfg, messages, tools, opts) {
|
|
|
9085
9148
|
name: tc.function?.name ?? "",
|
|
9086
9149
|
arguments: tc.function?.arguments ?? "{}"
|
|
9087
9150
|
}));
|
|
9088
|
-
const { usage, costUsd, costProvenance, billedCostUsd, cache } = meterTurn(data.usage, cfg.model);
|
|
9151
|
+
const { usage, resources, costUsd, costProvenance, billedCostUsd, cache } = meterTurn(data.usage, cfg.model, transportAttempts);
|
|
9089
9152
|
return {
|
|
9090
9153
|
content: msg?.content ?? null,
|
|
9091
9154
|
toolCalls,
|
|
9092
9155
|
transportAttempts,
|
|
9093
9156
|
...reportedModel(data.model) ? { model: reportedModel(data.model) } : {},
|
|
9094
9157
|
...usage ? { usage } : {},
|
|
9158
|
+
...resources ? { resources } : {},
|
|
9095
9159
|
...costUsd !== void 0 ? { costUsd } : {},
|
|
9096
9160
|
...costProvenance ? { costProvenance } : {},
|
|
9097
9161
|
...billedCostUsd !== void 0 ? { billedCostUsd } : {},
|
|
@@ -9141,7 +9205,12 @@ function providerRequestExtras(extraBody, reservedFields) {
|
|
|
9141
9205
|
* fabricated 0: a phantom 0 reads as a free call to the conserved budget pool, which would then
|
|
9142
9206
|
* over-spend. Shared by the buffered and streamed transports so both meter identically.
|
|
9143
9207
|
*/
|
|
9144
|
-
function meterTurn(raw, model) {
|
|
9208
|
+
function meterTurn(raw, model, transportAttempts) {
|
|
9209
|
+
let resources = addResourceSpend(raw?.resources).resources;
|
|
9210
|
+
if (transportAttempts > 1 && resources !== void 0) resources = Object.fromEntries(Object.entries(resources).map(([name, value]) => [name, {
|
|
9211
|
+
...value,
|
|
9212
|
+
known: false
|
|
9213
|
+
}]));
|
|
9145
9214
|
const reasoning = providerReasoningTokens(raw);
|
|
9146
9215
|
const usage = raw && typeof raw.prompt_tokens === "number" && typeof raw.completion_tokens === "number" ? {
|
|
9147
9216
|
input: raw.prompt_tokens,
|
|
@@ -9151,6 +9220,7 @@ function meterTurn(raw, model) {
|
|
|
9151
9220
|
const cache = readPromptCache(raw);
|
|
9152
9221
|
const billedCostUsd = providerBilledCost(raw);
|
|
9153
9222
|
if (!usage) return {
|
|
9223
|
+
...resources ? { resources } : {},
|
|
9154
9224
|
...billedCostUsd !== void 0 ? { billedCostUsd } : {},
|
|
9155
9225
|
...cache ? { cache } : {}
|
|
9156
9226
|
};
|
|
@@ -9158,6 +9228,7 @@ function meterTurn(raw, model) {
|
|
|
9158
9228
|
const costUsd = localEstimate !== void 0 && cache?.readSavingsUsd !== void 0 ? Math.max(0, localEstimate - cache.readSavingsUsd) : localEstimate;
|
|
9159
9229
|
return {
|
|
9160
9230
|
usage,
|
|
9231
|
+
...resources ? { resources } : {},
|
|
9161
9232
|
...costUsd !== void 0 ? {
|
|
9162
9233
|
costUsd,
|
|
9163
9234
|
costProvenance: "catalog-estimate"
|
|
@@ -9273,7 +9344,7 @@ async function streamRouterChatWithTools(cfg, messages, tools, opts) {
|
|
|
9273
9344
|
name: call.name ?? "",
|
|
9274
9345
|
arguments: call.arguments || "{}"
|
|
9275
9346
|
}));
|
|
9276
|
-
const { usage, costUsd, costProvenance, billedCostUsd, cache } = meterTurn(rawUsage, cfg.model);
|
|
9347
|
+
const { usage, resources, costUsd, costProvenance, billedCostUsd, cache } = meterTurn(rawUsage, cfg.model, transportAttempts);
|
|
9277
9348
|
return {
|
|
9278
9349
|
content: sawContent ? split.content : null,
|
|
9279
9350
|
toolCalls,
|
|
@@ -9282,6 +9353,7 @@ async function streamRouterChatWithTools(cfg, messages, tools, opts) {
|
|
|
9282
9353
|
...split.reasoning ? { reasoning: split.reasoning } : {},
|
|
9283
9354
|
...finishReason !== void 0 ? { finishReason } : {},
|
|
9284
9355
|
...usage ? { usage } : {},
|
|
9356
|
+
...resources ? { resources } : {},
|
|
9285
9357
|
...costUsd !== void 0 ? { costUsd } : {},
|
|
9286
9358
|
...costProvenance ? { costProvenance } : {},
|
|
9287
9359
|
...billedCostUsd !== void 0 ? { billedCostUsd } : {},
|
|
@@ -9527,6 +9599,7 @@ function routerBrain(cfg, opts = {}) {
|
|
|
9527
9599
|
content: result.content,
|
|
9528
9600
|
toolCalls: result.toolCalls,
|
|
9529
9601
|
...result.usage !== void 0 ? { usage: result.usage } : {},
|
|
9602
|
+
...addResourceSpend(result.resources),
|
|
9530
9603
|
...result.usageUnknown === true ? { usageUnknown: true } : {},
|
|
9531
9604
|
...result.model !== void 0 ? { model: result.model } : {},
|
|
9532
9605
|
...result.cache !== void 0 ? { promptCache: Object.freeze({ ...result.cache }) } : {},
|
|
@@ -10967,8 +11040,8 @@ function priceUnreceiptedWork(work) {
|
|
|
10967
11040
|
/**
|
|
10968
11041
|
*
|
|
10969
11042
|
* The conserved budget reservation pool — the invariant the whole instrument
|
|
10970
|
-
* rests on (critique M5/B3). One root `Budget` becomes a conserved pool of
|
|
10971
|
-
* quantities (tokens, usd, iterations) plus an absolute deadline. Children reserve
|
|
11043
|
+
* rests on (critique M5/B3). One root `Budget` becomes a conserved pool of standard
|
|
11044
|
+
* quantities (tokens, usd, iterations) and caller-named resources plus an absolute deadline. Children reserve
|
|
10972
11045
|
* atomically at spawn and reconcile at settle:
|
|
10973
11046
|
*
|
|
10974
11047
|
* total ≡ free + reserved + committed (for every known quantity)
|
|
@@ -10992,16 +11065,11 @@ function priceUnreceiptedWork(work) {
|
|
|
10992
11065
|
* it trusts a reported `input`: the token channel is an accounting unit, not a trust boundary
|
|
10993
11066
|
* against a provider that misreports its own usage.
|
|
10994
11067
|
*
|
|
10995
|
-
*
|
|
10996
|
-
*
|
|
10997
|
-
* The
|
|
10998
|
-
*
|
|
10999
|
-
*
|
|
11000
|
-
* lifetime it watched (`boxMinutesProvenance: 'estimated'`), not a platform receipt. Reserving
|
|
11001
|
-
* against an estimate would let a derived number refuse real work, which is the same defect as a
|
|
11002
|
-
* gate that cannot fire, inverted. When the platform reports minutes itself
|
|
11003
|
-
* (`boxMinutesProvenance: 'observed'`) and a `Budget` gains a box ceiling, the channel becomes a
|
|
11004
|
-
* conserved quantity; until both hold, it is evidence only.
|
|
11068
|
+
* Named resources require explicit units, ceilings, and complete executor measurements.
|
|
11069
|
+
* Missing or unknown enforced measurements close admission for that resource.
|
|
11070
|
+
* The pool trusts those receipts; it does not independently meter external systems.
|
|
11071
|
+
* `Spend.boxMinutes` remains evidence only and has no implicit resource ceiling.
|
|
11072
|
+
* Callers must not present estimated box lifetime as a measured resource receipt.
|
|
11005
11073
|
*
|
|
11006
11074
|
* Pure and deterministic: the run's start instant is supplied, there is no I/O, and no
|
|
11007
11075
|
* wall-clock or RNG read. A `reserve`/`reconcile` ticket is single-use (fail-loud on double or
|
|
@@ -11033,12 +11101,14 @@ function assertValidBudget(budget, label = "budget") {
|
|
|
11033
11101
|
const finiteNonNegative = (value, field) => {
|
|
11034
11102
|
if (!Number.isFinite(value) || value < 0) throw new Error(`${label}.${field} must be a non-negative finite number`);
|
|
11035
11103
|
};
|
|
11104
|
+
assertResources(budget.resources, "limit", `${label}.resources`);
|
|
11036
11105
|
safeInteger(budget.maxIterations, "maxIterations");
|
|
11037
11106
|
safeInteger(budget.maxTokens, "maxTokens");
|
|
11038
11107
|
if (budget.maxUsd !== void 0) finiteNonNegative(budget.maxUsd, "maxUsd");
|
|
11039
11108
|
if (budget.deadlineMs !== void 0) finiteNonNegative(budget.deadlineMs, "deadlineMs");
|
|
11040
11109
|
}
|
|
11041
11110
|
function assertValidSpend(spend, label) {
|
|
11111
|
+
assertResources(spend.resources, "amount", `${label}.resources`);
|
|
11042
11112
|
if (!Number.isSafeInteger(spend.iterations) || spend.iterations < 0) throw new Error(`${label}.iterations must be a non-negative safe integer`);
|
|
11043
11113
|
for (const [field, value] of [
|
|
11044
11114
|
["input", spend.tokens.input],
|
|
@@ -11090,6 +11160,14 @@ function newUsageTotals() {
|
|
|
11090
11160
|
* `iteration` advances the iteration count.
|
|
11091
11161
|
*/
|
|
11092
11162
|
function meterUsageEvent(totals, ev) {
|
|
11163
|
+
if (ev.kind === "resource") {
|
|
11164
|
+
totals.resources = addResourceSpend(totals.resources, Object.fromEntries([[ev.name, {
|
|
11165
|
+
unit: ev.unit,
|
|
11166
|
+
amount: ev.amount,
|
|
11167
|
+
known: ev.known
|
|
11168
|
+
}]])).resources;
|
|
11169
|
+
return;
|
|
11170
|
+
}
|
|
11093
11171
|
if (ev.kind === "tokens") {
|
|
11094
11172
|
addTokenUsage(totals.tokens, ev);
|
|
11095
11173
|
if (ev.tokensKnown === false) totals.tokensKnown = false;
|
|
@@ -11111,6 +11189,7 @@ function meterUsageEvent(totals, ev) {
|
|
|
11111
11189
|
* read wall-clock. */
|
|
11112
11190
|
function spendFromUsageTotals(totals) {
|
|
11113
11191
|
return {
|
|
11192
|
+
...addResourceSpend(totals.resources),
|
|
11114
11193
|
iterations: totals.iterations,
|
|
11115
11194
|
tokens: totals.tokens,
|
|
11116
11195
|
...totals.tokensKnown ? {} : { tokensKnown: false },
|
|
@@ -11153,10 +11232,56 @@ function createBudgetPool(root, runStartedAtMs, restore = {}) {
|
|
|
11153
11232
|
let reservedIterations = 0;
|
|
11154
11233
|
let committedIterations = 0;
|
|
11155
11234
|
const absoluteDeadlineMs = root.deadlineMs === void 0 ? 0 : runStartedAtMs + root.deadlineMs;
|
|
11235
|
+
const resources = new Map(Object.entries(root.resources ?? {}).map(([name, value]) => [name, {
|
|
11236
|
+
...value,
|
|
11237
|
+
remaining: value.limit,
|
|
11238
|
+
reserved: 0,
|
|
11239
|
+
committed: 0,
|
|
11240
|
+
known: true
|
|
11241
|
+
}]));
|
|
11242
|
+
function validateResourceUnits(spend) {
|
|
11243
|
+
for (const [name, value] of Object.entries(spend.resources ?? {})) {
|
|
11244
|
+
const limit = resources.get(name);
|
|
11245
|
+
if (limit && limit.unit !== value.unit) throw new Error(`resource ${name}: unit mismatch`);
|
|
11246
|
+
}
|
|
11247
|
+
}
|
|
11248
|
+
function commitResources(spend, reserved = {}, requireAll = true) {
|
|
11249
|
+
let violation;
|
|
11250
|
+
for (const [name, state] of resources) {
|
|
11251
|
+
const value = spend.resources?.[name];
|
|
11252
|
+
if (!requireAll && value === void 0) continue;
|
|
11253
|
+
const allocation = reserved?.[name]?.limit ?? 0;
|
|
11254
|
+
const amount = value?.amount ?? 0;
|
|
11255
|
+
state.reserved -= allocation;
|
|
11256
|
+
const committed = state.committed + amount;
|
|
11257
|
+
const overflow = !Number.isSafeInteger(committed);
|
|
11258
|
+
state.committed = Math.min(committed, Number.MAX_SAFE_INTEGER);
|
|
11259
|
+
state.remaining = state.limit - state.reserved - state.committed;
|
|
11260
|
+
if (value?.known !== true || overflow) {
|
|
11261
|
+
state.known = false;
|
|
11262
|
+
const retained = Math.max(0, state.remaining);
|
|
11263
|
+
state.committed += retained;
|
|
11264
|
+
state.remaining -= retained;
|
|
11265
|
+
violation ??= overflow ? `resource ${name}: amount overflow under an enforced limit` : `resource ${name}: unknown usage under an enforced limit`;
|
|
11266
|
+
} else if (reserved?.[name] && amount > allocation) violation ??= `resource ${name}: spent ${amount} > reserved ${allocation}`;
|
|
11267
|
+
else if (state.remaining < 0) violation ??= `resource ${name}: exceeded root limit ${state.limit}`;
|
|
11268
|
+
}
|
|
11269
|
+
return violation;
|
|
11270
|
+
}
|
|
11156
11271
|
let nextTicketId = 0;
|
|
11157
11272
|
const open = /* @__PURE__ */ new Set();
|
|
11158
11273
|
function reserve(b) {
|
|
11159
11274
|
assertValidBudget(b, "reservation budget");
|
|
11275
|
+
for (const [name, state] of resources) {
|
|
11276
|
+
const wanted = b.resources?.[name];
|
|
11277
|
+
if (!wanted) throw new ValidationError$1(`resource ${name}: child must declare its limit`);
|
|
11278
|
+
if (wanted.unit !== state.unit) throw new ValidationError$1(`resource ${name}: unit mismatch`);
|
|
11279
|
+
if (!state.known || wanted.limit > state.remaining) return {
|
|
11280
|
+
ok: false,
|
|
11281
|
+
reason: "budget-exhausted"
|
|
11282
|
+
};
|
|
11283
|
+
}
|
|
11284
|
+
for (const name of Object.keys(b.resources ?? {})) if (!resources.has(name)) throw new ValidationError$1(`resource ${name}: root must declare its limit`);
|
|
11160
11285
|
const wantTokens = b.maxTokens;
|
|
11161
11286
|
const wantUsd = b.maxUsd ?? 0;
|
|
11162
11287
|
const wantIterations = b.maxIterations;
|
|
@@ -11180,6 +11305,11 @@ function createBudgetPool(root, runStartedAtMs, restore = {}) {
|
|
|
11180
11305
|
ok: false,
|
|
11181
11306
|
reason: "budget-exhausted"
|
|
11182
11307
|
};
|
|
11308
|
+
for (const [name, state] of resources) {
|
|
11309
|
+
const amount = b.resources[name].limit;
|
|
11310
|
+
state.remaining -= amount;
|
|
11311
|
+
state.reserved += amount;
|
|
11312
|
+
}
|
|
11183
11313
|
freeTokens -= wantTokens;
|
|
11184
11314
|
reservedTokens += wantTokens;
|
|
11185
11315
|
freeIterations -= wantIterations;
|
|
@@ -11195,6 +11325,7 @@ function createBudgetPool(root, runStartedAtMs, restore = {}) {
|
|
|
11195
11325
|
ticket: {
|
|
11196
11326
|
id,
|
|
11197
11327
|
reserved: {
|
|
11328
|
+
...b.resources === void 0 ? {} : { resources: Object.fromEntries(Object.entries(b.resources).map(([name, value]) => [name, { ...value }])) },
|
|
11198
11329
|
tokens: wantTokens,
|
|
11199
11330
|
usd: wantUsd,
|
|
11200
11331
|
iterations: wantIterations,
|
|
@@ -11206,6 +11337,7 @@ function createBudgetPool(root, runStartedAtMs, restore = {}) {
|
|
|
11206
11337
|
function reconcile(ticket, spent) {
|
|
11207
11338
|
if (!open.has(ticket.id)) throw new Error(`budget pool: reconcile of unknown or already-settled ticket ${ticket.id}`);
|
|
11208
11339
|
assertValidSpend(spent, `budget pool ticket ${ticket.id} spend`);
|
|
11340
|
+
validateResourceUnits(spent);
|
|
11209
11341
|
const { tokens: rTokens, usd: rUsd, iterations: rIterations } = ticket.reserved;
|
|
11210
11342
|
const unknownUnderCap = usdCapped && spent.usdKnown === false;
|
|
11211
11343
|
const spentTokens = chargedTokens(spent.tokens);
|
|
@@ -11233,10 +11365,13 @@ function createBudgetPool(root, runStartedAtMs, restore = {}) {
|
|
|
11233
11365
|
freeUsd = 0;
|
|
11234
11366
|
} else freeUsd += rUsd - spent.usd;
|
|
11235
11367
|
} else committedUsd += spent.usd;
|
|
11368
|
+
const resourceViolation = commitResources(spent, ticket.reserved.resources);
|
|
11369
|
+
violation ??= resourceViolation;
|
|
11236
11370
|
if (violation !== void 0) throw new Error(`budget pool: ${violation}`);
|
|
11237
11371
|
}
|
|
11238
|
-
function observe(spend) {
|
|
11372
|
+
function observe(spend, options = {}) {
|
|
11239
11373
|
assertValidSpend(spend, "observed spend");
|
|
11374
|
+
validateResourceUnits(spend);
|
|
11240
11375
|
if (usdCapped && spend.usdKnown === false) throw new ValidationError$1("budget pool: cannot observe unknown dollar cost under a dollar-capped budget");
|
|
11241
11376
|
if (spend.tokensKnown === false) tokensTainted = true;
|
|
11242
11377
|
if (!hasCompleteCacheBreakdown(spend.tokens)) cacheBreakdownTainted = true;
|
|
@@ -11248,9 +11383,12 @@ function createBudgetPool(root, runStartedAtMs, restore = {}) {
|
|
|
11248
11383
|
committedIterations += spend.iterations;
|
|
11249
11384
|
committedUsd += spend.usd;
|
|
11250
11385
|
if (usdCapped) freeUsd -= spend.usd;
|
|
11386
|
+
const violation = commitResources(spend, {}, !options.partial);
|
|
11387
|
+
if (violation) throw new ValidationError$1(`budget pool: ${violation}`);
|
|
11251
11388
|
}
|
|
11252
11389
|
function readout() {
|
|
11253
11390
|
return {
|
|
11391
|
+
...resources.size ? { resources: Object.fromEntries([...resources].map(([name, value]) => [name, { ...value }])) } : {},
|
|
11254
11392
|
tokensLeft: freeTokens,
|
|
11255
11393
|
tokensKnown: !tokensTainted,
|
|
11256
11394
|
cacheBreakdownKnown: !cacheBreakdownTainted,
|
|
@@ -11267,6 +11405,8 @@ function createBudgetPool(root, runStartedAtMs, restore = {}) {
|
|
|
11267
11405
|
}
|
|
11268
11406
|
if (restore.committed !== void 0) {
|
|
11269
11407
|
assertValidSpend(restore.committed, "budget restore committed");
|
|
11408
|
+
validateResourceUnits(restore.committed);
|
|
11409
|
+
commitResources(restore.committed);
|
|
11270
11410
|
const committed = restore.committed;
|
|
11271
11411
|
if (committed.tokensKnown === false) tokensTainted = true;
|
|
11272
11412
|
if (!hasCompleteCacheBreakdown(committed.tokens)) cacheBreakdownTainted = true;
|
|
@@ -11288,6 +11428,12 @@ function createBudgetPool(root, runStartedAtMs, restore = {}) {
|
|
|
11288
11428
|
}
|
|
11289
11429
|
for (const [index, uncertain] of (restore.uncertainReservations ?? []).entries()) {
|
|
11290
11430
|
assertValidBudget(uncertain, `budget restore uncertainReservations[${index}]`);
|
|
11431
|
+
commitResources(withBudgetResources({
|
|
11432
|
+
iterations: 0,
|
|
11433
|
+
tokens: zeroTokenUsage(),
|
|
11434
|
+
usd: 0,
|
|
11435
|
+
ms: 0
|
|
11436
|
+
}, root));
|
|
11291
11437
|
tokensTainted = true;
|
|
11292
11438
|
usdMeasured = false;
|
|
11293
11439
|
freeTokens -= uncertain.maxTokens;
|
|
@@ -13103,6 +13249,7 @@ function readWorkerProgress(scope, executor, now, stallAfterMs = DEFAULT_STALL_A
|
|
|
13103
13249
|
const idleMs = Math.max(0, now - lastActivityAt);
|
|
13104
13250
|
const note = executor?.note;
|
|
13105
13251
|
return {
|
|
13252
|
+
...addResourceSpend(scope.resources),
|
|
13106
13253
|
id: scope.id,
|
|
13107
13254
|
status: scope.status,
|
|
13108
13255
|
live,
|
|
@@ -14270,6 +14417,7 @@ const routerInlineExecutor = (spec, ctx) => {
|
|
|
14270
14417
|
}));
|
|
14271
14418
|
if (r.model !== void 0) recordRuntimeOwnedProviderModel(executor, r.model);
|
|
14272
14419
|
const spent = {
|
|
14420
|
+
...addResourceSpend(r.resources),
|
|
14273
14421
|
iterations: 1,
|
|
14274
14422
|
tokens: r.usage ? cloneTokenUsage({
|
|
14275
14423
|
input: r.usage.input,
|
|
@@ -14420,6 +14568,7 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
14420
14568
|
let billedUsd = 0;
|
|
14421
14569
|
let usdKnown = true;
|
|
14422
14570
|
let turns = 0;
|
|
14571
|
+
let resources;
|
|
14423
14572
|
let transportAttempts = 0;
|
|
14424
14573
|
let observedModel;
|
|
14425
14574
|
let reasoningTokens = 0;
|
|
@@ -14468,6 +14617,10 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
14468
14617
|
cleanup();
|
|
14469
14618
|
if (e instanceof DOMException && e.name === "AbortError" && interruptSig.aborted && !signal.aborted && !controller.signal.aborted) {
|
|
14470
14619
|
turns += 1;
|
|
14620
|
+
resources = addResourceSpend(Object.fromEntries(Object.entries(resources ?? {}).map(([name, value]) => [name, {
|
|
14621
|
+
...value,
|
|
14622
|
+
known: false
|
|
14623
|
+
}]))).resources;
|
|
14471
14624
|
transportAttempts += routerTransportAttemptsFromError(e) ?? 1;
|
|
14472
14625
|
tokensKnown = false;
|
|
14473
14626
|
usdKnown = false;
|
|
@@ -14478,6 +14631,12 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
14478
14631
|
}
|
|
14479
14632
|
cleanup();
|
|
14480
14633
|
turns += 1;
|
|
14634
|
+
const priorResources = resources;
|
|
14635
|
+
resources = addResourceSpend(resources, res.resources).resources;
|
|
14636
|
+
resources = addResourceSpend(Object.fromEntries(Object.entries(resources ?? {}).map(([name, value]) => [name, {
|
|
14637
|
+
...value,
|
|
14638
|
+
known: value.known && res.resources?.[name] !== void 0 && (turns === 1 || priorResources?.[name] !== void 0)
|
|
14639
|
+
}]))).resources;
|
|
14481
14640
|
transportAttempts += res.transportAttempts;
|
|
14482
14641
|
if (res.model !== void 0) recordRuntimeOwnedProviderModel(executor, res.model);
|
|
14483
14642
|
assertObservedRouterModel(res.model, model, "routerToolsInlineExecutor");
|
|
@@ -14587,6 +14746,7 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
14587
14746
|
}
|
|
14588
14747
|
const estimatedUsd = isModelPriced(model) ? estimateCost(tokens.input, tokens.output, model) : void 0;
|
|
14589
14748
|
const spent = {
|
|
14749
|
+
...addResourceSpend(resources),
|
|
14590
14750
|
iterations: turns,
|
|
14591
14751
|
tokens,
|
|
14592
14752
|
...tokensKnown ? {} : { tokensKnown: false },
|
|
@@ -17913,7 +18073,12 @@ async function startRetainedInteractiveRun(options) {
|
|
|
17913
18073
|
const profile = agentProfileSchema.parse(startOptions.environment.profile);
|
|
17914
18074
|
if (profile.harness === void 0) throw new Error("retained interactive runs require AgentProfile.harness");
|
|
17915
18075
|
const requestedProfileDigest = canonicalAgentProfileDigest(profile);
|
|
17916
|
-
const identity = mintRetainedIdentity(startOptions.environment.idempotencyKey, startOptions.interactiveIdempotencyKey)
|
|
18076
|
+
const identity = startOptions.intent === void 0 ? mintRetainedIdentity(startOptions.environment.idempotencyKey, startOptions.interactiveIdempotencyKey) : {
|
|
18077
|
+
sessionId: startOptions.intent.sessionId,
|
|
18078
|
+
executionId: startOptions.intent.executionId
|
|
18079
|
+
};
|
|
18080
|
+
assertStableText(identity.sessionId, "retained session id");
|
|
18081
|
+
assertStableText(identity.executionId, "retained execution id");
|
|
17917
18082
|
const intent = interactiveIntent(startOptions, profile, identity);
|
|
17918
18083
|
if (startOptions.intent === void 0) await admitDurably(startOptions.onAdmission, intent);
|
|
17919
18084
|
else assertExactInteractiveIntent(startOptions.intent, intent);
|
|
@@ -17987,9 +18152,21 @@ function exactRecoveryRequest(admission) {
|
|
|
17987
18152
|
assertStableText(admission.interactiveIdempotencyKey, "interactive idempotency key");
|
|
17988
18153
|
const request = exactAgentInteractiveSessionStart(admission.request);
|
|
17989
18154
|
const identity = mintRetainedIdentity(admission.idempotencyKey, admission.interactiveIdempotencyKey);
|
|
17990
|
-
if (request.run.provider !== admission.provider || request.run.environmentId !== admission.environmentId || request.run.sessionId !== identity.sessionId || request.run.executionId !== identity.executionId) throw new Error("interactive admission does not match its recovery coordinates");
|
|
18155
|
+
if (request.run.provider !== admission.provider || request.run.environmentId !== admission.environmentId || (request.run.sessionId !== identity.sessionId || request.run.executionId !== identity.executionId) && !matchesHistoricalInteractiveIdentity(admission, request)) throw new Error("interactive admission does not match its recovery coordinates");
|
|
17991
18156
|
return request;
|
|
17992
18157
|
}
|
|
18158
|
+
function matchesHistoricalInteractiveIdentity(admission, request) {
|
|
18159
|
+
const base = `${encodeURIComponent(admission.idempotencyKey)}:${encodeURIComponent(admission.interactiveIdempotencyKey)}`;
|
|
18160
|
+
const digest = canonicalCandidateDigest({
|
|
18161
|
+
kind: "retained-identity.v1",
|
|
18162
|
+
base
|
|
18163
|
+
}).slice(7);
|
|
18164
|
+
const historicalId = (prefix) => {
|
|
18165
|
+
const readable = `${prefix}:${base}`;
|
|
18166
|
+
return readable.length <= 128 ? readable : `${prefix}:${digest}`;
|
|
18167
|
+
};
|
|
18168
|
+
return request.run.sessionId === historicalId("retained-session") && request.run.executionId === historicalId("retained-execution");
|
|
18169
|
+
}
|
|
17993
18170
|
/** Rebuild controls for one exact provider-owned coding-agent process. @stable */
|
|
17994
18171
|
async function reconnectRetainedInteractiveRun(options) {
|
|
17995
18172
|
options.signal?.throwIfAborted();
|
|
@@ -18758,6 +18935,8 @@ function sumSpendFromEvents(events) {
|
|
|
18758
18935
|
const rootBudget = events.find((event) => event.kind === "spawned" && event.parent === void 0)?.budget;
|
|
18759
18936
|
let remainingRootUsd = Math.max(0, (rootBudget?.maxUsd ?? 0) - totals.childWork.usd - totals.driverInference.usd);
|
|
18760
18937
|
for (const budget of uncertainSpawnBudgets(events)) {
|
|
18938
|
+
const unknown = withBudgetResources(zeroSpend(), budget);
|
|
18939
|
+
Object.assign(totals.childWork, addResourceSpend(totals.childWork.resources, unknown.resources));
|
|
18761
18940
|
totals.childWork.iterations += budget.maxIterations;
|
|
18762
18941
|
totals.childWork.tokens.input += budget.maxTokens;
|
|
18763
18942
|
totals.childWork.tokensKnown = false;
|
|
@@ -18769,10 +18948,17 @@ function sumSpendFromEvents(events) {
|
|
|
18769
18948
|
return totals;
|
|
18770
18949
|
}
|
|
18771
18950
|
function sumMeasuredSpendFromEvents(events) {
|
|
18951
|
+
const budgets = new Map(events.flatMap((event) => event.kind === "spawned" ? [[event.id, event.budget]] : []));
|
|
18772
18952
|
let childWork = zeroSpend();
|
|
18773
18953
|
let driverInference = zeroSpend();
|
|
18774
|
-
|
|
18775
|
-
|
|
18954
|
+
const owners = /* @__PURE__ */ new Map();
|
|
18955
|
+
for (const ev of events) if (ev.kind === "settled" || ev.kind === "cancelled") childWork = addSpend(childWork, withBudgetResources(ev.spent ?? {
|
|
18956
|
+
...zeroSpend(),
|
|
18957
|
+
tokensKnown: false,
|
|
18958
|
+
usdKnown: false
|
|
18959
|
+
}, budgets.get(ev.id) ?? {}));
|
|
18960
|
+
else if (ev.kind === "metered") owners.set(ev.id, addSpend(owners.get(ev.id) ?? zeroSpend(), ev.spend));
|
|
18961
|
+
for (const [id, spend] of owners) driverInference = addSpend(driverInference, withBudgetResources(spend, budgets.get(id) ?? {}));
|
|
18776
18962
|
return {
|
|
18777
18963
|
childWork,
|
|
18778
18964
|
driverInference
|
|
@@ -18783,12 +18969,14 @@ async function prepareScopeResume(opts, events, signal, now, parentId = opts.run
|
|
|
18783
18969
|
const prepared = await prepareInterruptedExecutors(opts, events, signal, now, parentId);
|
|
18784
18970
|
const prior = prepared.events;
|
|
18785
18971
|
const recovering = new Set(prepared.recoveries.map((item) => item.spawned.id));
|
|
18786
|
-
const
|
|
18972
|
+
const measuredEvents = prior.filter((event) => event.kind !== "metered" || !recovering.has(event.id));
|
|
18973
|
+
const measured = sumMeasuredSpendFromEvents(measuredEvents);
|
|
18974
|
+
const hasCommittedEvidence = measuredEvents.some((event) => event.kind === "metered" || event.kind === "settled" || event.kind === "cancelled");
|
|
18787
18975
|
const settled = await replaySpawnTree(opts.journal, opts.blobs, opts.runId);
|
|
18788
18976
|
signal.throwIfAborted();
|
|
18789
18977
|
return {
|
|
18790
18978
|
poolRestore: {
|
|
18791
|
-
committed: addSpend(measured.childWork, measured.driverInference),
|
|
18979
|
+
...hasCommittedEvidence ? { committed: addSpend(measured.childWork, measured.driverInference) } : {},
|
|
18792
18980
|
uncertainReservations: uncertainSpawnBudgets(prior, recovering)
|
|
18793
18981
|
},
|
|
18794
18982
|
resumeFrom: {
|
|
@@ -19383,7 +19571,7 @@ function createScope(args) {
|
|
|
19383
19571
|
spec = prepared.spec;
|
|
19384
19572
|
identity = prepared.identity;
|
|
19385
19573
|
if (opts.key !== void 0 && !isCompleteIdentity(identity)) {
|
|
19386
|
-
args.pool.reconcile(reservation.ticket, zeroSpend());
|
|
19574
|
+
args.pool.reconcile(reservation.ticket, withBudgetResources(zeroSpend(), opts.budget, true));
|
|
19387
19575
|
permit.release();
|
|
19388
19576
|
return {
|
|
19389
19577
|
ok: false,
|
|
@@ -19397,7 +19585,7 @@ function createScope(args) {
|
|
|
19397
19585
|
if (!outcome.succeeded) throw new ValidationError$1(`scope.spawn: ${outcome.error}`);
|
|
19398
19586
|
resolved = outcome;
|
|
19399
19587
|
} catch (error) {
|
|
19400
|
-
args.pool.reconcile(reservation.ticket, zeroSpend());
|
|
19588
|
+
args.pool.reconcile(reservation.ticket, withBudgetResources(zeroSpend(), opts.budget, true));
|
|
19401
19589
|
permit.release();
|
|
19402
19590
|
throw error;
|
|
19403
19591
|
}
|
|
@@ -19759,7 +19947,7 @@ function createScope(args) {
|
|
|
19759
19947
|
permit.release();
|
|
19760
19948
|
clearChildDeadline?.();
|
|
19761
19949
|
if (cascadeAbort) args.signal.removeEventListener("abort", cascadeAbort);
|
|
19762
|
-
args.pool.reconcile(reservation.ticket, zeroSpend());
|
|
19950
|
+
args.pool.reconcile(reservation.ticket, withBudgetResources(zeroSpend(), opts.budget, true));
|
|
19763
19951
|
throw err;
|
|
19764
19952
|
}
|
|
19765
19953
|
}
|
|
@@ -19987,6 +20175,7 @@ function createScope(args) {
|
|
|
19987
20175
|
steerable: child.deliver !== void 0 && !child.delivered,
|
|
19988
20176
|
startedAt: child.startedAt,
|
|
19989
20177
|
lastActivityAt: child.lastActivityAt,
|
|
20178
|
+
...addResourceSpend(child.spent.resources),
|
|
19990
20179
|
turns: child.spent.iterations,
|
|
19991
20180
|
tokens: child.spent.tokens,
|
|
19992
20181
|
...child.spent.tokensKnown === false ? { tokensKnown: false } : {},
|
|
@@ -20025,10 +20214,12 @@ function createScope(args) {
|
|
|
20025
20214
|
}
|
|
20026
20215
|
async function meterInternal(spend, detail, providerModel, accountingOnly = false) {
|
|
20027
20216
|
if (args.signal.aborted) throw new ValidationError$1("scope.meter: cannot record new driver work after scope abort");
|
|
20217
|
+
const partial = providerModel !== void 0 || accountingOnly;
|
|
20218
|
+
if (!partial) spend = withBudgetResources(spend, args.pool.readout());
|
|
20028
20219
|
const seq = meterSeq++;
|
|
20029
20220
|
let observeError;
|
|
20030
20221
|
try {
|
|
20031
|
-
args.pool.observe(spend);
|
|
20222
|
+
args.pool.observe(spend, { partial });
|
|
20032
20223
|
} catch (error) {
|
|
20033
20224
|
observeError = error;
|
|
20034
20225
|
}
|
|
@@ -20628,6 +20819,23 @@ async function runChild(live, executor, childAbort, task, opts, pool, ticket, bl
|
|
|
20628
20819
|
if (reconciled) return reconciliationError;
|
|
20629
20820
|
reconciled = true;
|
|
20630
20821
|
try {
|
|
20822
|
+
try {
|
|
20823
|
+
spend = withBudgetResources(spend, opts.budget, !started);
|
|
20824
|
+
live.spent = withBudgetResources(live.spent, opts.budget, !started || executor.accounting?.() !== void 0);
|
|
20825
|
+
} catch (error) {
|
|
20826
|
+
spend = withBudgetResources({
|
|
20827
|
+
...spend,
|
|
20828
|
+
resources: void 0
|
|
20829
|
+
}, opts.budget);
|
|
20830
|
+
live.spent = withBudgetResources({
|
|
20831
|
+
...live.spent,
|
|
20832
|
+
resources: void 0
|
|
20833
|
+
}, opts.budget);
|
|
20834
|
+
try {
|
|
20835
|
+
pool.reconcile(ticket, spend);
|
|
20836
|
+
} catch {}
|
|
20837
|
+
throw error;
|
|
20838
|
+
}
|
|
20631
20839
|
pool.reconcile(ticket, spend);
|
|
20632
20840
|
return;
|
|
20633
20841
|
} catch (error) {
|
|
@@ -20775,7 +20983,11 @@ async function runChild(live, executor, childAbort, task, opts, pool, ticket, bl
|
|
|
20775
20983
|
if (started && !terminalTelemetryCaptured && accounting === void 0) live.spent = {
|
|
20776
20984
|
...live.spent,
|
|
20777
20985
|
tokensKnown: false,
|
|
20778
|
-
usdKnown: false
|
|
20986
|
+
usdKnown: false,
|
|
20987
|
+
...live.spent.resources === void 0 ? {} : { resources: Object.fromEntries(Object.entries(live.spent.resources).map(([name, value]) => [name, {
|
|
20988
|
+
...value,
|
|
20989
|
+
known: false
|
|
20990
|
+
}])) }
|
|
20779
20991
|
};
|
|
20780
20992
|
const reconcileError = reconcileOnce(accounting?.reservation ?? live.spent);
|
|
20781
20993
|
return downRecord(errMessage(err), evidenceError !== void 0 || teardownError !== void 0 || reconcileError !== void 0 || aborted || isInfraError(err), trace, executor.metered?.(), providerModel);
|
|
@@ -20933,6 +21145,7 @@ async function foldStream(stream, onProgress, signal) {
|
|
|
20933
21145
|
const ev = next.value;
|
|
20934
21146
|
meterUsageEvent(totals, ev);
|
|
20935
21147
|
await onProgress?.({
|
|
21148
|
+
...addResourceSpend(totals.resources),
|
|
20936
21149
|
iterations: totals.iterations,
|
|
20937
21150
|
tokens: cloneTokenUsage(totals.tokens),
|
|
20938
21151
|
...totals.tokensKnown ? {} : { tokensKnown: false },
|
|
@@ -20954,6 +21167,7 @@ function preserveUnknownTelemetry(streamed, terminal) {
|
|
|
20954
21167
|
const terminalTokens = cloneTokenUsage(terminal.tokens);
|
|
20955
21168
|
return {
|
|
20956
21169
|
...streamed,
|
|
21170
|
+
...resourceTelemetry(streamed, terminal),
|
|
20957
21171
|
tokens: {
|
|
20958
21172
|
...streamed.tokens,
|
|
20959
21173
|
...streamed.tokens.freshInput === void 0 && terminalTokens.freshInput !== void 0 ? { freshInput: terminalTokens.freshInput } : {},
|
|
@@ -21315,7 +21529,7 @@ function sumMetered(events) {
|
|
|
21315
21529
|
* went unmeasured did real work, and dropping its `metered` event here would re-hide upstream the
|
|
21316
21530
|
* very turn the driver refused to skip. */
|
|
21317
21531
|
function isNonZeroSpend(s) {
|
|
21318
|
-
return s.iterations > 0 || s.tokens.input > 0 || s.tokens.output > 0 || s.usd > 0 || s.ms > 0 || s.tokensKnown === false || s.usdKnown === false;
|
|
21532
|
+
return s.iterations > 0 || s.tokens.input > 0 || s.tokens.output > 0 || s.usd > 0 || s.ms > 0 || s.tokensKnown === false || s.usdKnown === false || Object.keys(s.resources ?? {}).length > 0;
|
|
21319
21533
|
}
|
|
21320
21534
|
/** A spend, or `undefined` when it is all-zero — so `metered()` returns undefined for a driver
|
|
21321
21535
|
* whose sub-tree did no inference (and the parent journals no empty `metered` event). */
|
|
@@ -21396,6 +21610,15 @@ function unreportedSpend(total, prior) {
|
|
|
21396
21610
|
}
|
|
21397
21611
|
return {
|
|
21398
21612
|
...total,
|
|
21613
|
+
...addResourceSpend(total.resources === void 0 ? void 0 : Object.fromEntries(Object.entries(total.resources).map(([name, value]) => {
|
|
21614
|
+
const previous = prior.resources?.[name];
|
|
21615
|
+
if (previous && previous.unit !== value.unit) throw new ValidationError$1(`resource ${name}: unit mismatch`);
|
|
21616
|
+
return [name, {
|
|
21617
|
+
...value,
|
|
21618
|
+
amount: Math.max(0, value.amount - (previous?.amount ?? 0)),
|
|
21619
|
+
known: value.known && (previous?.known ?? true)
|
|
21620
|
+
}];
|
|
21621
|
+
}))),
|
|
21399
21622
|
iterations: Math.max(0, total.iterations - prior.iterations),
|
|
21400
21623
|
tokens,
|
|
21401
21624
|
usd: Math.max(0, total.usd - prior.usd),
|
|
@@ -22194,9 +22417,12 @@ async function terminalAccounting(journal, root, elapsedMs) {
|
|
|
22194
22417
|
* result this list rides on. */
|
|
22195
22418
|
function spendGapsFromEvents(events) {
|
|
22196
22419
|
const labels = /* @__PURE__ */ new Map();
|
|
22420
|
+
const budgets = /* @__PURE__ */ new Map();
|
|
22197
22421
|
const terminal = /* @__PURE__ */ new Set();
|
|
22198
|
-
for (const ev of events) if (ev.kind === "spawned")
|
|
22199
|
-
|
|
22422
|
+
for (const ev of events) if (ev.kind === "spawned") {
|
|
22423
|
+
labels.set(ev.id, ev.label);
|
|
22424
|
+
budgets.set(ev.id, ev.budget);
|
|
22425
|
+
} else if (closesCursorSlot(ev)) terminal.add(ev.id);
|
|
22200
22426
|
const gaps = /* @__PURE__ */ new Map();
|
|
22201
22427
|
const record = (id, kind, channels) => {
|
|
22202
22428
|
if (channels.length === 0) return;
|
|
@@ -22209,9 +22435,17 @@ function spendGapsFromEvents(events) {
|
|
|
22209
22435
|
channels: new Set(channels)
|
|
22210
22436
|
});
|
|
22211
22437
|
};
|
|
22212
|
-
for (const ev of events) if (ev.kind === "spawned" && ev.parent !== void 0 && !terminal.has(ev.id)) record(ev.id, "never-settled", [
|
|
22213
|
-
|
|
22214
|
-
|
|
22438
|
+
for (const ev of events) if (ev.kind === "spawned" && ev.parent !== void 0 && !terminal.has(ev.id)) record(ev.id, "never-settled", [
|
|
22439
|
+
"tokens",
|
|
22440
|
+
"usd",
|
|
22441
|
+
...Object.keys(ev.budget.resources ?? {}).map((name) => `resource:${name}`)
|
|
22442
|
+
]);
|
|
22443
|
+
else if (ev.kind === "cancelled" && ev.spent === void 0) record(ev.id, "unreported", [
|
|
22444
|
+
"tokens",
|
|
22445
|
+
"usd",
|
|
22446
|
+
...Object.keys(budgets.get(ev.id)?.resources ?? {}).map((name) => `resource:${name}`)
|
|
22447
|
+
]);
|
|
22448
|
+
else if (ev.kind === "settled" || ev.kind === "cancelled" && ev.spent !== void 0) record(ev.id, "unreported", unknownChannels(withBudgetResources(ev.spent, budgets.get(ev.id) ?? {})));
|
|
22215
22449
|
else if (ev.kind === "metered") record(ev.id, "unreported", unknownChannels(ev.spend));
|
|
22216
22450
|
return [...gaps.values()].map((gap) => {
|
|
22217
22451
|
const label = labels.get(gap.id);
|
|
@@ -22228,13 +22462,14 @@ function unknownChannels(spend) {
|
|
|
22228
22462
|
const channels = [];
|
|
22229
22463
|
if (spend.tokensKnown === false) channels.push("tokens");
|
|
22230
22464
|
if (spend.usdKnown === false) channels.push("usd");
|
|
22465
|
+
for (const [name, resource] of Object.entries(spend.resources ?? {})) if (!resource.known) channels.push(`resource:${name}`);
|
|
22231
22466
|
return channels;
|
|
22232
22467
|
}
|
|
22233
22468
|
/** True when any driver metered inference this run (so the winner carries a `spentBreakdown`).
|
|
22234
22469
|
* Checks every channel `addSpend` sums — including `ms` — so the gate stays consistent with the
|
|
22235
22470
|
* total even though the coordination driver currently stamps `ms: 0`. */
|
|
22236
22471
|
function isNonEmptySpend(s) {
|
|
22237
|
-
return s.iterations > 0 || s.tokens.input > 0 || s.tokens.output > 0 || s.usd > 0 || s.ms > 0 || s.tokensKnown === false || s.usdKnown === false;
|
|
22472
|
+
return s.iterations > 0 || s.tokens.input > 0 || s.tokens.output > 0 || s.usd > 0 || s.ms > 0 || s.tokensKnown === false || s.usdKnown === false || Object.values(s.resources ?? {}).some((resource) => resource.amount > 0 || !resource.known);
|
|
22238
22473
|
}
|
|
22239
22474
|
//#endregion
|
|
22240
22475
|
//#region src/redact.ts
|
|
@@ -22320,6 +22555,6 @@ function resolveRedactor(redact) {
|
|
|
22320
22555
|
return (value) => defaultRedactor(redact(value));
|
|
22321
22556
|
}
|
|
22322
22557
|
//#endregion
|
|
22323
|
-
export { bridgeAdmissionRefusal as $, buildLoopSpanNodes as $n,
|
|
22558
|
+
export { bridgeAdmissionRefusal as $, buildLoopSpanNodes as $n, inheritRuntimeOwnedExecutorAttestation as $r, spendFromUsageEvents as $t, consumeScopeRetainedOwnerResult as A, sumSandboxUsage as Ai, throwIfAborted as An, assertProfileMaterialization as Ar, peerMailTools as At, workerInteractiveBindingFile as B, startRetainedRun as Bn, renderUnsupported as Br, insideCursorNamespace as Bt, settledToIteration as C, extractLlmCallEvent as Ci, hasCompleteCacheBreakdown as Cn, DEFAULT_LOCAL_HARNESS as Cr, createInbox as Ct, timerAt as D, notifySandboxEventObserver as Di, sleep as Dn, parseCodexTokenUsage as Dr, claimsAuthority as Dt, pollFor as E, mapSandboxToolEvent as Ei, randomSuffix as En, localHarnessExecutable as Er, PEER_MAIL_WIRE_KEY as Et, interactiveAdmissionSeamKey as F, promptOptionsFromAgentTurnInput as Fi, RunCancellationReason as Fn, promptControlProfileMaterialization as Fr, taskToPrompt as Ft, destroyInteractiveEnvironment as G, harnessUsageIsEmpty as Gn, isNoEntError as Gr, WORKER_TOOL_TRACE_SCHEMA_VERSION as Gt, reconnectRetainedInteractiveRun as H, retainedCreateMaterial as Hn, unsupportedProfileDimensions as Hr, materializeTreeView as Ht, readWorkerInteractiveAdmissions as I, providerMessageText as Ii, abortError$1 as In, promptModelProfileMaterialization as Ir, FileResultBlobStore as It, queueOf as J, mergeTraceEnv as Jn, writeAllBytes as Jr, parseWorkerToolTraceArtifact as Jt, effectiveConcurrency as K, readCodexRolloutSession as Kn, parseCommittedJsonLines as Kr, captureWorkerTraceEvidence as Kt, workerInteractiveAdmissionFile as L, linkAbort as Ln, promptOnlyProfileMaterialization as Lr, FileSpawnJournal as Lt, scopeRetainedOwnerContext as M, abortError$2 as Mi, zeroSpend as Mn, defineProfileMaterializationContract as Mr, isLiveNodeStatus as Mt, scopeRetainedOwnerPriorSpend as N, awaitAbortable$1 as Ni, registerRetainedExecutorPreparation as Nn, fullProfileMaterialization as Nr, isTerminalNodeStatus as Nt, validateWaitSpec as O, sandboxEventServedBackend as Oi, stringifySafe as On, CodexExecutionDiagnosticError as Or, createPeerMailbox as Ot, scopeRetainedOwnerResult as P, promptFromAgentTurnInput as Pi, retainedExecutorSeamKey as Pn, profileMaterializationAxes$1 as Pr, createInPlaceCliExecutor as Pt, bindReusableExecutorExecutionId as Q, buildLoopOtelSpans as Qn, finalizeRuntimeOwnedPendingExecutor as Qr, createBudgetPool as Qt, attachWorker as R, reconnectRetainedRun as Rn, promptResourceProfileMaterialization as Rr, InMemoryResultBlobStore as Rt, scopeOwnerExecutorNodeContext as S, createSandboxUsageLedger as Si, deleteBoxSafe as Sn, removeWorktree as Sr, readWorkerProgress as St, isWaitOutcome as T, mapSandboxEvent as Ti, promptCacheTokenClasses as Tn, harnessSupportsReasoningEffort as Tr, DEFAULT_PEER_MAIL_LIMITS as Tt, recoverRetainedInteractiveRun as U, addHarnessUsage as Un, validateProfileMaterialization as Ur, pendingWaits as Ut, workerInteractiveBindingsDir as V, startRetainedRunInEnvironment as Vn, sandboxActProfileMaterialization as Vr, loadSpawnForest as Vt, startRetainedInteractiveRun as W, createCodexRolloutStoreReader as Wn, worktreeCliProfileMaterialization as Wr, replaySpawnTree as Wt, DEFAULT_SUCCESSFUL_SHUTDOWN_MS as X, traceContextToEnv as Xn, attestRuntimeOwnedScopeOwner as Xr, contentAddress as Xt, rollingDispatch as Y, readTraceContextFromEnv as Yn, attestRuntimeOwnedPendingExecutor as Yr, workerTraceAnalysisStore as Yt, teardownExecutor as Z, INTELLIGENCE_WIRE_VERSION as Zn, authoredProfileDigest as Zr, assertValidBudget as Zt, deriveNodeExecutionIdentity as _, projectSandboxOutcome as _i, resolveAgentEnvironmentProvider as _n, withBudgetResources as _r, createPushTraceSource as _t, createSupervisor as a, runtimeOwnedDriveHarnessProviderEvidence as ai, createSandboxLineage as an, generateSpanId as ar, cliWorktreeExecutor as at, recordScopeOwnerMaterialization as b, canonicalStreamEventFromSandboxEvent as bi, chargedTokens as bn, captureWorktreeDiff as br, DEFAULT_STALL_AFTER_MS as bt, pickBestDelivered as c, runtimeOwnedExecutorProviderEvidence as ci, assertBoxlessPromptOptions as cn, padTraceId as cr, snapshotExecutorConfig as ct, driverChild as d, unknownExecutionBindingReceipt as di, runBrainLoop as dn, createRuntimeStreamEventCollector as dr, readWorkerTraceContext as dt, knownExecutionBindingReceipt as ei, TERMINAL_DECISIONS as en, buildRuntimeEventOtelSpans as er, bridgeModelRouteRefusal as et, driverExecutorFactory as f, unknownMaterializationReceipt as fi, canonicalObservedModelParts as fn, sanitizeAgentRuntimeEvent as fr, workerTraceEnv as ft, createScope as g, detachedSnapshot as gi, providerAsSandboxClient as gn, resourceTelemetry as gr, createSteerableSandboxSession as gt, beginScopeOwnerAttempt as h, detachedFrozen as hi, providerAsExecutor as hn, addResourceSpend as hr, DEFAULT_SANDBOX_STEERING_MAX_TURNS as ht, createRootHandle as i, recordRuntimeOwnedDriveHarnessProviderEvidence as ii, runAgentRounds as in, flatOtelSpan as ir, cliInPlaceExecutor as it, prepareScopeRetainedOwnerTask as j, decodeHarnessUsage as ji, unmeteredSpend as jn, controlProfileMaterialization as jr, peerMailVerbNames as jt, waitUntil as k, sandboxProgressEvents as ki, throwAbort as kn, AGENT_PROFILE_MATERIALIZATION_AXES as kr, isPeerMailEnvelope as kt, runFinalizer as l, runtimeOwnedPendingExecutorMaterialization as li, readPromptOptions as ln, toOtelAttributes as lr, createWorktreeCliExecutor as lt, withDriverExecutor as m, executableAgentSpecSnapshot as mi, createAgentEnvironmentProviderRegistry as mn, sanitizeRuntimeStreamEvent as mr, workerTraceSeamKey as mt, defaultRedactorIdentityMaterial as n, newExecutionAttemptId as ni, defaultSelectWinner as nn, createOtelExporter as nr, bridgeStopSignalKey as nt, bestDelivered as o, runtimeOwnedExecutorExecutionBinding as oi, probeSandboxCapabilities as on, loopEventToOtelSpan as or, createExecutor as ot, isDriverSpec as p, executableAgentProfileSnapshot as pi, observedModelMatchesDeclared as pn, sanitizeKnowledgeReadinessReport as pr, workerTraceHeaders as pt, freeSlots as q, createPropagatingTraceEmitter as qn, prepareJsonlAppend as qr, isTraceAnalysisStore as qt, resolveRedactor as r, providerAttemptEvidence as ri, isTerminalDecision as rn, exportEvalRuns as rr, captureReusableExecutorConfig as rt, collectDelivered as s, runtimeOwnedExecutorMaterialization as si, acquireSandbox as sn, padSpanId as sr, createExecutorRegistry as st, defaultRedactor as t, knownMaterializationReceipt as ti, createSandboxForSpec as tn, createOpenInferenceFileExporter as tr, bridgeRuntimeAttachmentsKey as tt, runTree as u, runtimeOwnedScopeOwnerRuntime as ui, routerBrain as un, createRuntimeEventCollector as ur, WORKER_TRACE_PROPAGATION as ut, meterRuntimeOwnedAccounting as v, readSandboxOutcome as vi, sandboxClientAsProvider as vn, runSettledCommand as vr, decodeToolPart as vt, createWaitProbes as w, isSandboxTerminalEvent as wi, isAbortError$2 as wn, LOCAL_HARNESSES as wr, AUTHORITY_MARKERS as wt, restoreScopeOwnerAcceptedExecution as x, createSandboxToolPartState as xi, cloneSpend as xn, createWorktree as xr, createActivityLog as xt, meterRuntimeOwnedProviderAttempt as y, assertSandboxServedModel as yi, addSpend as yn, runWorktreeHarness as yr, sandboxSessionTraceSource as yt, readWorkerInteractiveBinding as z, recoverRetainedRun as zn, renderProfileMaterializationIssues as zr, InMemorySpawnJournal as zt };
|
|
22324
22559
|
|
|
22325
|
-
//# sourceMappingURL=redact-
|
|
22560
|
+
//# sourceMappingURL=redact-va_1mmv8.js.map
|