@rulvar/core 1.229.0 → 1.231.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/index.d.ts +185 -8
- package/dist/index.js +1121 -938
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -8708,6 +8708,12 @@ function assertFencedWrites(stores) {
|
|
|
8708
8708
|
//#region src/stores/reconcile.ts
|
|
8709
8709
|
/** The decisionType of the journaled run settle entry. */
|
|
8710
8710
|
const RUN_SETTLE_DECISION_TYPE = "run_settle";
|
|
8711
|
+
/**
|
|
8712
|
+
* The decisionType of the journaled spawn admission (RV2702): the
|
|
8713
|
+
* entry that names every child an orchestration judged, which is what
|
|
8714
|
+
* makes an offline roster a read rather than a guess.
|
|
8715
|
+
*/
|
|
8716
|
+
const SPAWN_ADMISSION_DECISION_TYPE = "spawn-admission";
|
|
8711
8717
|
const RUN_STATUSES = /* @__PURE__ */ new Set([
|
|
8712
8718
|
"ok",
|
|
8713
8719
|
"error",
|
|
@@ -8788,13 +8794,25 @@ function readRejectedFinishCandidates(raw) {
|
|
|
8788
8794
|
*
|
|
8789
8795
|
* The twenty-fifth comparison run was killed and resumed, and its two
|
|
8790
8796
|
* terminals mixed both kinds with nothing marking which was which: the
|
|
8791
|
-
* money was cumulative, the
|
|
8797
|
+
* money was cumulative, the live-only counters were not,
|
|
8792
8798
|
* and reconciling them into one honest account of the logical run was
|
|
8793
8799
|
* hand work over a joined journal. Keys are field paths as a consumer
|
|
8794
|
-
* reads them off `RunOutcome` (`cost.orchestrator.wakes`)
|
|
8795
|
-
*
|
|
8796
|
-
*
|
|
8797
|
-
*
|
|
8800
|
+
* reads them off `RunOutcome` (`cost.orchestrator.wakes`): the type
|
|
8801
|
+
* requires every field of the outcome, and the `satisfies` below
|
|
8802
|
+
* requires every counted leaf under `cost` (RV2801), because an index
|
|
8803
|
+
* signature admits nested paths and demands none, so the five that were
|
|
8804
|
+
* declared were declared by hand and by luck while four
|
|
8805
|
+
* (`cost.usageApprox`, `cost.abandoned.usd`, `cost.abandoned.usageApprox`,
|
|
8806
|
+
* `cost.orchestrator.share`) were simply missing. That is the RV2701
|
|
8807
|
+
* blindness one level down: a gate whose subject is nested figures
|
|
8808
|
+
* cannot stop at the top level.
|
|
8809
|
+
*
|
|
8810
|
+
* What neither can decide is whether a declared scope is TRUE, and a
|
|
8811
|
+
* wrong scope is worse than a missing one: a missing one is noticed, a
|
|
8812
|
+
* wrong one is believed. The doctrine test suspends a real run, resumes
|
|
8813
|
+
* it, and holds every declared figure against its own claim (RV2801),
|
|
8814
|
+
* which is how three `cost.orchestrator.*` paths were found calling
|
|
8815
|
+
* themselves `'segment'` while the terminal folded them cumulatively.
|
|
8798
8816
|
*/
|
|
8799
8817
|
const TERMINAL_TELEMETRY_SCOPE = Object.freeze({
|
|
8800
8818
|
status: "terminal",
|
|
@@ -8808,6 +8826,7 @@ const TERMINAL_TELEMETRY_SCOPE = Object.freeze({
|
|
|
8808
8826
|
salvagedTerminalOutputChildren: "cumulative",
|
|
8809
8827
|
belowFloorOkChildren: "cumulative",
|
|
8810
8828
|
acceptanceChildren: "cumulative",
|
|
8829
|
+
childrenAtFailure: "cumulative",
|
|
8811
8830
|
semanticPasses: "terminal",
|
|
8812
8831
|
claimConsistencyMeta: "terminal",
|
|
8813
8832
|
synthesisSkipped: "terminal",
|
|
@@ -8822,10 +8841,14 @@ const TERMINAL_TELEMETRY_SCOPE = Object.freeze({
|
|
|
8822
8841
|
"cost.totalUsd": "cumulative",
|
|
8823
8842
|
"cost.grossUsd": "cumulative",
|
|
8824
8843
|
"cost.wireRequests": "cumulative",
|
|
8844
|
+
"cost.usageApprox": "cumulative",
|
|
8845
|
+
"cost.abandoned.usd": "cumulative",
|
|
8846
|
+
"cost.abandoned.usageApprox": "cumulative",
|
|
8825
8847
|
"cost.orchestrator.spentUsd": "cumulative",
|
|
8826
|
-
"cost.orchestrator.
|
|
8827
|
-
"cost.orchestrator.
|
|
8828
|
-
"cost.orchestrator.
|
|
8848
|
+
"cost.orchestrator.share": "cumulative",
|
|
8849
|
+
"cost.orchestrator.wakes": "cumulative",
|
|
8850
|
+
"cost.orchestrator.forcedFinish": "cumulative",
|
|
8851
|
+
"cost.orchestrator.reserveUsedUsd": "cumulative",
|
|
8829
8852
|
transportRetries: "segment",
|
|
8830
8853
|
schemaRejectedFinishExchanges: "segment",
|
|
8831
8854
|
schemaRecoveredFinishExchanges: "segment"
|
|
@@ -8869,6 +8892,91 @@ function logicalRunTelemetry(entries) {
|
|
|
8869
8892
|
entriesAfterLastSettle: sinceLastSettle
|
|
8870
8893
|
};
|
|
8871
8894
|
}
|
|
8895
|
+
/**
|
|
8896
|
+
* Every orchestration's children, folded from a run's journal (RV2702).
|
|
8897
|
+
*
|
|
8898
|
+
* `childrenAtFailure` (RV2602) answers this for a LIVE consumer, and it
|
|
8899
|
+
* dies with the process that held it: the settle persists the
|
|
8900
|
+
* completion lift and nothing else, so a post-mortem over a journal,
|
|
8901
|
+
* which is all a paid run leaves behind, had no way to ask what the
|
|
8902
|
+
* children produced. Every ingredient was already written down. This
|
|
8903
|
+
* is the fold.
|
|
8904
|
+
*
|
|
8905
|
+
* It reads what resume reads. A `spawn-admission` decision names every
|
|
8906
|
+
* child the controller judged, with its ordinal, its profile, its
|
|
8907
|
+
* verdict, and the scope its dispatch pins to; the dispatch and
|
|
8908
|
+
* terminal `agent` entries under that scope are the child itself, and
|
|
8909
|
+
* the RV806 evidence verdict rides the terminal. Nothing is
|
|
8910
|
+
* re-derived and no validator runs again, so a journal written by any
|
|
8911
|
+
* prior version reads exactly as well as today's, which is the point:
|
|
8912
|
+
* the runs worth a post-mortem are the ones already in the archive.
|
|
8913
|
+
*
|
|
8914
|
+
* Two things it deliberately does NOT claim. It is not the live
|
|
8915
|
+
* roster: this reading happens after the RV1903 exit barrier settled
|
|
8916
|
+
* the stragglers, so a child the live field would have called
|
|
8917
|
+
* unsettled usually has a terminal here, and `status` is absent only
|
|
8918
|
+
* where the journal truly ends mid-flight. And it names children by
|
|
8919
|
+
* their dispatch seq rather than by nodeId, because the seq is the
|
|
8920
|
+
* handle the orchestrator's own turns used and the one a reader can
|
|
8921
|
+
* follow into the transcript.
|
|
8922
|
+
*/
|
|
8923
|
+
function childRostersFromJournal(entries) {
|
|
8924
|
+
const rosters = /* @__PURE__ */ new Map();
|
|
8925
|
+
const ordered = [...entries].sort((a, b) => a.seq - b.seq);
|
|
8926
|
+
const abandoned = buildAbandonFold(ordered);
|
|
8927
|
+
const dispatchesByScope = /* @__PURE__ */ new Map();
|
|
8928
|
+
const terminalsByScopeKey = /* @__PURE__ */ new Map();
|
|
8929
|
+
for (const entry of ordered) {
|
|
8930
|
+
if (entry.kind !== "agent") continue;
|
|
8931
|
+
if (entry.status === "running") {
|
|
8932
|
+
const rows = dispatchesByScope.get(entry.scope);
|
|
8933
|
+
if (rows === void 0) dispatchesByScope.set(entry.scope, [entry]);
|
|
8934
|
+
else rows.push(entry);
|
|
8935
|
+
continue;
|
|
8936
|
+
}
|
|
8937
|
+
const key = JSON.stringify([entry.scope, entry.key]);
|
|
8938
|
+
const rows = terminalsByScopeKey.get(key);
|
|
8939
|
+
if (rows === void 0) terminalsByScopeKey.set(key, [entry]);
|
|
8940
|
+
else rows.push(entry);
|
|
8941
|
+
}
|
|
8942
|
+
const cursors = /* @__PURE__ */ new Map();
|
|
8943
|
+
for (const entry of ordered) {
|
|
8944
|
+
if (entry.kind !== "decision") continue;
|
|
8945
|
+
const value = entry.value;
|
|
8946
|
+
if (value?.decisionType !== "spawn-admission" || value.origin !== "spawn_agent" && value.origin !== "parallel_agents") continue;
|
|
8947
|
+
const childScope = typeof value.childScope === "string" ? value.childScope : entry.scope;
|
|
8948
|
+
let roster = rosters.get(childScope);
|
|
8949
|
+
if (roster === void 0) {
|
|
8950
|
+
roster = {
|
|
8951
|
+
childScope,
|
|
8952
|
+
admitted: 0,
|
|
8953
|
+
rejected: 0,
|
|
8954
|
+
children: []
|
|
8955
|
+
};
|
|
8956
|
+
rosters.set(childScope, roster);
|
|
8957
|
+
}
|
|
8958
|
+
if (value.decision?.verdict?.kind !== "admit") {
|
|
8959
|
+
roster.rejected += 1;
|
|
8960
|
+
continue;
|
|
8961
|
+
}
|
|
8962
|
+
roster.admitted += 1;
|
|
8963
|
+
const rows = dispatchesByScope.get(childScope) ?? [];
|
|
8964
|
+
let cursor = cursors.get(childScope) ?? 0;
|
|
8965
|
+
while (cursor < rows.length && (rows[cursor]?.seq ?? 0) <= entry.seq) cursor += 1;
|
|
8966
|
+
const dispatch = rows[cursor];
|
|
8967
|
+
cursors.set(childScope, cursor + 1);
|
|
8968
|
+
if (dispatch === void 0) continue;
|
|
8969
|
+
const terminal = terminalsByScopeKey.get(JSON.stringify([childScope, dispatch.key]))?.find((candidate) => candidate.seq > dispatch.seq);
|
|
8970
|
+
roster.children.push({
|
|
8971
|
+
handle: dispatch.seq,
|
|
8972
|
+
...abandoned.isAbandoned(dispatch.seq) ? { abandoned: true } : {},
|
|
8973
|
+
...terminal?.costAttribution?.agentType === void 0 ? {} : { agentType: terminal.costAttribution.agentType },
|
|
8974
|
+
...terminal === void 0 ? {} : { status: terminal.status },
|
|
8975
|
+
...terminal?.evidence === void 0 ? {} : { evidence: { ...terminal.evidence } }
|
|
8976
|
+
});
|
|
8977
|
+
}
|
|
8978
|
+
return [...rosters.values()];
|
|
8979
|
+
}
|
|
8872
8980
|
function structure(entries) {
|
|
8873
8981
|
const referenced = /* @__PURE__ */ new Set();
|
|
8874
8982
|
for (const entry of entries) if (entry.ref !== void 0) referenced.add(entry.ref);
|
|
@@ -8983,472 +9091,834 @@ async function reconcileRunMeta(store, runId, opts) {
|
|
|
8983
9091
|
};
|
|
8984
9092
|
}
|
|
8985
9093
|
//#endregion
|
|
8986
|
-
//#region src/
|
|
8987
|
-
|
|
8988
|
-
|
|
8989
|
-
|
|
8990
|
-
|
|
8991
|
-
|
|
8992
|
-
|
|
8993
|
-
* Contract (DEF-4 tightening):
|
|
8994
|
-
* - A1 atomicity: a torn trailing line (crash mid-append) is never
|
|
8995
|
-
* visible in load; the incomplete fragment is dropped and overwritten
|
|
8996
|
-
* by the next append. Whole records on that line are data, never
|
|
8997
|
-
* fragment (RV701): a crash that persisted every JSON byte but not
|
|
8998
|
-
* the '\n' leaves a parseable tail that load serves and append
|
|
8999
|
-
* terminates before writing, and repair salvages complete records a
|
|
9000
|
-
* glued line carries instead of discarding the line, so an entry a
|
|
9001
|
-
* load has served can never be un-served by a later repair.
|
|
9002
|
-
* - A2 total per-run order: load returns append order, stable across
|
|
9003
|
-
* calls (the kernel's per-run queue serializes appends).
|
|
9004
|
-
* - A3 read-your-writes: append resolves after the line is written.
|
|
9005
|
-
* - A4 opaque payload: entries round-trip byte-for-byte as JSON; unknown
|
|
9006
|
-
* kinds and fields pass through untouched.
|
|
9007
|
-
*
|
|
9008
|
-
* Leasing is NOT implemented here: LeasableStore ships with
|
|
9009
|
-
* @rulvar/store-sqlite (M5); JsonlFileStore is single-writer by
|
|
9010
|
-
* convention.
|
|
9011
|
-
*/
|
|
9012
|
-
const JOURNAL_SUFFIX = ".jsonl";
|
|
9013
|
-
const META_SUFFIX = ".meta.json";
|
|
9014
|
-
function safeName(runId) {
|
|
9015
|
-
if (!/^[A-Za-z0-9._-]+$/.test(runId)) throw new JournalOrderViolation(`JsonlFileStore: runId '${runId}' is not filesystem-safe ([A-Za-z0-9._-] only)`);
|
|
9016
|
-
return runId;
|
|
9017
|
-
}
|
|
9094
|
+
//#region src/l0/telemetry-reduce.ts
|
|
9095
|
+
const ZERO = {
|
|
9096
|
+
inputTokens: 0,
|
|
9097
|
+
outputTokens: 0,
|
|
9098
|
+
cacheReadTokens: 0,
|
|
9099
|
+
cacheWriteTokens: 0
|
|
9100
|
+
};
|
|
9018
9101
|
/**
|
|
9019
|
-
*
|
|
9020
|
-
*
|
|
9021
|
-
*
|
|
9022
|
-
* clean concatenation from its first byte salvages its whole prefix
|
|
9023
|
-
* values and returns everything after them as the torn fragment, so the
|
|
9024
|
-
* caller keeps accepted records and drops exactly the unacknowledged
|
|
9025
|
-
* tail a crash tore.
|
|
9102
|
+
* Reduces one run's event stream (or any slice of it) to the invocation
|
|
9103
|
+
* table. Feed it the events in emission order; both a live stream and a
|
|
9104
|
+
* replayed one produce the same usage and cost columns.
|
|
9026
9105
|
*/
|
|
9027
|
-
function
|
|
9028
|
-
const
|
|
9029
|
-
|
|
9030
|
-
|
|
9031
|
-
|
|
9032
|
-
let
|
|
9033
|
-
|
|
9034
|
-
|
|
9035
|
-
if (
|
|
9036
|
-
|
|
9037
|
-
|
|
9038
|
-
|
|
9039
|
-
|
|
9040
|
-
|
|
9041
|
-
|
|
9042
|
-
|
|
9043
|
-
|
|
9106
|
+
function reduceInvocationTable(events) {
|
|
9107
|
+
const rows = /* @__PURE__ */ new Map();
|
|
9108
|
+
const order = [];
|
|
9109
|
+
const openPhases = /* @__PURE__ */ new Map();
|
|
9110
|
+
const byRole = {};
|
|
9111
|
+
let totalCostUsd = 0;
|
|
9112
|
+
const rowFor = (event) => {
|
|
9113
|
+
let row = rows.get(event.spanId);
|
|
9114
|
+
if (row === void 0) {
|
|
9115
|
+
row = {
|
|
9116
|
+
spanId: event.spanId,
|
|
9117
|
+
agentType: event.agentType,
|
|
9118
|
+
...event.label === void 0 ? {} : { label: event.label },
|
|
9119
|
+
usage: ZERO,
|
|
9120
|
+
costUsd: 0,
|
|
9121
|
+
costBasis: "aggregate-estimate",
|
|
9122
|
+
usageApprox: false,
|
|
9123
|
+
retryCount: 0,
|
|
9124
|
+
replayed: event.replayed === true,
|
|
9125
|
+
open: true,
|
|
9126
|
+
phases: []
|
|
9127
|
+
};
|
|
9128
|
+
rows.set(event.spanId, row);
|
|
9129
|
+
order.push(row);
|
|
9044
9130
|
}
|
|
9045
|
-
|
|
9046
|
-
|
|
9047
|
-
|
|
9131
|
+
return row;
|
|
9132
|
+
};
|
|
9133
|
+
for (const event of events) switch (event.type) {
|
|
9134
|
+
case "agent:start": {
|
|
9135
|
+
const row = rowFor(event);
|
|
9136
|
+
row.role = event.role;
|
|
9137
|
+
break;
|
|
9048
9138
|
}
|
|
9049
|
-
|
|
9050
|
-
|
|
9051
|
-
|
|
9052
|
-
|
|
9053
|
-
|
|
9139
|
+
case "agent:phase:start": {
|
|
9140
|
+
const row = rowFor(event);
|
|
9141
|
+
const phase = {
|
|
9142
|
+
invocation: event.invocation,
|
|
9143
|
+
role: event.role,
|
|
9144
|
+
model: event.model,
|
|
9145
|
+
durationMs: 0,
|
|
9146
|
+
usage: ZERO,
|
|
9147
|
+
costUsd: 0,
|
|
9148
|
+
costBasis: "aggregate-estimate",
|
|
9149
|
+
retries: 0,
|
|
9150
|
+
replayed: event.replayed === true,
|
|
9151
|
+
open: true
|
|
9054
9152
|
};
|
|
9055
|
-
|
|
9056
|
-
|
|
9057
|
-
|
|
9058
|
-
|
|
9059
|
-
|
|
9060
|
-
|
|
9061
|
-
|
|
9062
|
-
|
|
9063
|
-
|
|
9064
|
-
|
|
9065
|
-
|
|
9153
|
+
row.phases.push(phase);
|
|
9154
|
+
openPhases.set(`${event.spanId}#${event.invocation}`, phase);
|
|
9155
|
+
break;
|
|
9156
|
+
}
|
|
9157
|
+
case "agent:phase:end": {
|
|
9158
|
+
const key = `${event.spanId}#${event.invocation}`;
|
|
9159
|
+
let phase = openPhases.get(key);
|
|
9160
|
+
if (phase === void 0) {
|
|
9161
|
+
phase = {
|
|
9162
|
+
invocation: event.invocation,
|
|
9163
|
+
role: event.role,
|
|
9164
|
+
model: event.model,
|
|
9165
|
+
durationMs: 0,
|
|
9166
|
+
usage: ZERO,
|
|
9167
|
+
costUsd: 0,
|
|
9168
|
+
costBasis: "aggregate-estimate",
|
|
9169
|
+
retries: 0,
|
|
9170
|
+
replayed: event.replayed === true,
|
|
9171
|
+
open: true
|
|
9172
|
+
};
|
|
9173
|
+
rowFor(event).phases.push(phase);
|
|
9066
9174
|
}
|
|
9175
|
+
openPhases.delete(key);
|
|
9176
|
+
phase.open = false;
|
|
9177
|
+
phase.role = event.role;
|
|
9178
|
+
phase.model = event.model;
|
|
9179
|
+
phase.durationMs = event.durationMs;
|
|
9180
|
+
phase.usage = event.usage;
|
|
9181
|
+
phase.costUsd = event.costUsd;
|
|
9182
|
+
phase.costBasis = event.costBasis ?? "aggregate-estimate";
|
|
9183
|
+
phase.outcome = event.outcome;
|
|
9184
|
+
phase.retries = event.retries ?? 0;
|
|
9185
|
+
const bucket = byRole[event.role] ??= {
|
|
9186
|
+
usage: ZERO,
|
|
9187
|
+
costUsd: 0,
|
|
9188
|
+
costBasis: "per-call"
|
|
9189
|
+
};
|
|
9190
|
+
bucket.usage = sumUsage(bucket.usage, event.usage);
|
|
9191
|
+
bucket.costUsd += event.costUsd;
|
|
9192
|
+
if (phase.costBasis === "aggregate-estimate") bucket.costBasis = "aggregate-estimate";
|
|
9193
|
+
break;
|
|
9194
|
+
}
|
|
9195
|
+
case "agent:end": {
|
|
9196
|
+
const row = rowFor(event);
|
|
9197
|
+
row.open = false;
|
|
9198
|
+
row.status = event.status;
|
|
9199
|
+
row.usage = event.usage;
|
|
9200
|
+
row.costUsd = event.costUsd;
|
|
9201
|
+
row.costBasis = event.costBasis ?? "aggregate-estimate";
|
|
9202
|
+
row.usageApprox = event.usageApprox === true;
|
|
9203
|
+
row.retryCount = event.retryCount ?? 0;
|
|
9204
|
+
if (event.toolBudget !== void 0) row.toolBudget = event.toolBudget;
|
|
9205
|
+
totalCostUsd += event.costUsd;
|
|
9206
|
+
break;
|
|
9067
9207
|
}
|
|
9208
|
+
default: break;
|
|
9068
9209
|
}
|
|
9069
9210
|
return {
|
|
9070
|
-
|
|
9071
|
-
|
|
9211
|
+
agents: order,
|
|
9212
|
+
byRole,
|
|
9213
|
+
totalCostUsd
|
|
9072
9214
|
};
|
|
9073
9215
|
}
|
|
9074
|
-
|
|
9075
|
-
|
|
9076
|
-
|
|
9077
|
-
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
|
|
9081
|
-
|
|
9082
|
-
|
|
9083
|
-
|
|
9084
|
-
|
|
9085
|
-
|
|
9086
|
-
|
|
9087
|
-
|
|
9088
|
-
|
|
9089
|
-
|
|
9090
|
-
|
|
9091
|
-
|
|
9092
|
-
|
|
9093
|
-
|
|
9094
|
-
|
|
9095
|
-
|
|
9096
|
-
|
|
9097
|
-
|
|
9098
|
-
|
|
9099
|
-
|
|
9100
|
-
|
|
9101
|
-
|
|
9102
|
-
|
|
9103
|
-
|
|
9104
|
-
|
|
9105
|
-
|
|
9106
|
-
|
|
9107
|
-
|
|
9108
|
-
|
|
9109
|
-
|
|
9110
|
-
|
|
9111
|
-
|
|
9112
|
-
|
|
9113
|
-
|
|
9114
|
-
|
|
9115
|
-
|
|
9116
|
-
|
|
9117
|
-
|
|
9118
|
-
|
|
9119
|
-
|
|
9120
|
-
|
|
9121
|
-
|
|
9122
|
-
|
|
9123
|
-
|
|
9124
|
-
|
|
9125
|
-
|
|
9126
|
-
|
|
9127
|
-
|
|
9128
|
-
|
|
9129
|
-
|
|
9130
|
-
|
|
9131
|
-
|
|
9132
|
-
|
|
9133
|
-
|
|
9134
|
-
|
|
9135
|
-
|
|
9136
|
-
|
|
9216
|
+
/**
|
|
9217
|
+
* The label the claim-consistency judge invocation dispatches under
|
|
9218
|
+
* (RV1502; named here since RV1604 so the critical-path reducer and the
|
|
9219
|
+
* orchestrator share one constant): the judge rides role 'synthesize',
|
|
9220
|
+
* and this label is what tells its wall apart from a real final
|
|
9221
|
+
* composition in {@link reduceCriticalPath}.
|
|
9222
|
+
*/
|
|
9223
|
+
const CLAIM_JUDGE_LABEL = "claim-consistency-judge";
|
|
9224
|
+
/** Total length of the union of possibly overlapping intervals. */
|
|
9225
|
+
function unionLength(intervals) {
|
|
9226
|
+
const positive = intervals.filter((interval) => interval.to > interval.from);
|
|
9227
|
+
if (positive.length === 0) return 0;
|
|
9228
|
+
const sorted = [...positive].sort((a, b) => a.from - b.from);
|
|
9229
|
+
let total = 0;
|
|
9230
|
+
let from = sorted[0]?.from ?? 0;
|
|
9231
|
+
let to = sorted[0]?.to ?? 0;
|
|
9232
|
+
for (const interval of sorted.slice(1)) if (interval.from > to) {
|
|
9233
|
+
total += to - from;
|
|
9234
|
+
from = interval.from;
|
|
9235
|
+
to = interval.to;
|
|
9236
|
+
} else if (interval.to > to) to = interval.to;
|
|
9237
|
+
return total + (to - from);
|
|
9238
|
+
}
|
|
9239
|
+
function reduceCriticalPath(events) {
|
|
9240
|
+
let runStart;
|
|
9241
|
+
let runEnd;
|
|
9242
|
+
const startBySpan = /* @__PURE__ */ new Map();
|
|
9243
|
+
let lastWorkerEnd;
|
|
9244
|
+
let workerSpans = 0;
|
|
9245
|
+
let synthesisMs = 0;
|
|
9246
|
+
let finalCompositionMs = 0;
|
|
9247
|
+
let semanticJudgeMs = 0;
|
|
9248
|
+
const coordinationModel = [];
|
|
9249
|
+
const coordinationTools = [];
|
|
9250
|
+
const synthesisSpans = [];
|
|
9251
|
+
const spanOf = (durationMs) => Number.isFinite(durationMs) && durationMs > 0 ? durationMs : 0;
|
|
9252
|
+
for (const event of events) {
|
|
9253
|
+
const at = Date.parse(event.ts);
|
|
9254
|
+
if (!Number.isFinite(at)) continue;
|
|
9255
|
+
switch (event.type) {
|
|
9256
|
+
case "run:start":
|
|
9257
|
+
runStart ??= at;
|
|
9258
|
+
break;
|
|
9259
|
+
case "run:end":
|
|
9260
|
+
runEnd = at;
|
|
9261
|
+
break;
|
|
9262
|
+
case "agent:start":
|
|
9263
|
+
startBySpan.set(event.spanId, {
|
|
9264
|
+
role: event.role,
|
|
9265
|
+
at,
|
|
9266
|
+
...event.label === void 0 ? {} : { label: event.label }
|
|
9267
|
+
});
|
|
9268
|
+
break;
|
|
9269
|
+
case "agent:phase:end":
|
|
9270
|
+
if (startBySpan.get(event.spanId)?.role === "orchestrate") coordinationModel.push({
|
|
9271
|
+
phase: event.role,
|
|
9272
|
+
from: at - spanOf(event.durationMs),
|
|
9273
|
+
to: at
|
|
9274
|
+
});
|
|
9275
|
+
break;
|
|
9276
|
+
case "tool:end":
|
|
9277
|
+
if (startBySpan.get(event.spanId)?.role === "orchestrate") coordinationTools.push({
|
|
9278
|
+
name: event.toolName,
|
|
9279
|
+
from: at - spanOf(event.durationMs),
|
|
9280
|
+
to: at
|
|
9281
|
+
});
|
|
9282
|
+
break;
|
|
9283
|
+
case "agent:end": {
|
|
9284
|
+
const started = startBySpan.get(event.spanId);
|
|
9285
|
+
if (started === void 0) break;
|
|
9286
|
+
if (started.role === "synthesize") {
|
|
9287
|
+
const wall = Math.max(0, at - started.at);
|
|
9288
|
+
const judge = started.label === CLAIM_JUDGE_LABEL;
|
|
9289
|
+
synthesisMs += wall;
|
|
9290
|
+
if (judge) semanticJudgeMs += wall;
|
|
9291
|
+
else finalCompositionMs += wall;
|
|
9292
|
+
synthesisSpans.push({
|
|
9293
|
+
from: started.at,
|
|
9294
|
+
to: at,
|
|
9295
|
+
judge
|
|
9296
|
+
});
|
|
9297
|
+
} else if (started.role !== "orchestrate") {
|
|
9298
|
+
workerSpans += 1;
|
|
9299
|
+
lastWorkerEnd = lastWorkerEnd === void 0 ? at : Math.max(lastWorkerEnd, at);
|
|
9137
9300
|
}
|
|
9138
|
-
|
|
9301
|
+
break;
|
|
9139
9302
|
}
|
|
9303
|
+
default: break;
|
|
9140
9304
|
}
|
|
9141
|
-
return entries;
|
|
9142
9305
|
}
|
|
9143
|
-
|
|
9144
|
-
|
|
9145
|
-
|
|
9146
|
-
|
|
9147
|
-
|
|
9148
|
-
|
|
9149
|
-
|
|
9150
|
-
|
|
9151
|
-
|
|
9152
|
-
|
|
9153
|
-
|
|
9154
|
-
|
|
9155
|
-
if (
|
|
9156
|
-
|
|
9157
|
-
|
|
9158
|
-
|
|
9159
|
-
|
|
9160
|
-
|
|
9161
|
-
|
|
9162
|
-
|
|
9163
|
-
|
|
9164
|
-
|
|
9165
|
-
|
|
9166
|
-
|
|
9167
|
-
|
|
9306
|
+
const path = {
|
|
9307
|
+
synthesisMs,
|
|
9308
|
+
finalCompositionMs,
|
|
9309
|
+
semanticJudgeMs,
|
|
9310
|
+
workerSpans
|
|
9311
|
+
};
|
|
9312
|
+
if (runStart !== void 0 && runEnd !== void 0) path.runWallMs = Math.max(0, runEnd - runStart);
|
|
9313
|
+
if (runEnd !== void 0 && lastWorkerEnd !== void 0) {
|
|
9314
|
+
path.postFanInMs = Math.max(0, runEnd - lastWorkerEnd);
|
|
9315
|
+
const windowFrom = Math.min(lastWorkerEnd, runEnd);
|
|
9316
|
+
const windowTo = runEnd;
|
|
9317
|
+
const clip = (interval) => {
|
|
9318
|
+
if (interval.to < windowFrom || interval.from > windowTo) return;
|
|
9319
|
+
return {
|
|
9320
|
+
from: Math.max(interval.from, windowFrom),
|
|
9321
|
+
to: Math.min(interval.to, windowTo)
|
|
9322
|
+
};
|
|
9323
|
+
};
|
|
9324
|
+
const byPhase = {};
|
|
9325
|
+
const modelClipped = [];
|
|
9326
|
+
for (const interval of coordinationModel) {
|
|
9327
|
+
const clipped = clip(interval);
|
|
9328
|
+
if (clipped === void 0) continue;
|
|
9329
|
+
byPhase[interval.phase] = (byPhase[interval.phase] ?? 0) + (clipped.to - clipped.from);
|
|
9330
|
+
modelClipped.push(clipped);
|
|
9168
9331
|
}
|
|
9169
|
-
|
|
9170
|
-
|
|
9171
|
-
|
|
9172
|
-
const
|
|
9173
|
-
|
|
9174
|
-
|
|
9175
|
-
|
|
9176
|
-
|
|
9177
|
-
|
|
9178
|
-
const path = this.metaPath(m.runId);
|
|
9179
|
-
const temp = `${path}.tmp`;
|
|
9180
|
-
writeFileSync(temp, JSON.stringify(m, null, 2), "utf8");
|
|
9181
|
-
renameSync(temp, path);
|
|
9182
|
-
}
|
|
9183
|
-
async getMeta(runId) {
|
|
9184
|
-
try {
|
|
9185
|
-
return JSON.parse(readFileSync(this.metaPath(runId), "utf8"));
|
|
9186
|
-
} catch {
|
|
9187
|
-
return;
|
|
9332
|
+
const synthesisClipped = [];
|
|
9333
|
+
let judgeClippedMs = 0;
|
|
9334
|
+
let compositionClippedMs = 0;
|
|
9335
|
+
for (const span of synthesisSpans) {
|
|
9336
|
+
const clipped = clip(span);
|
|
9337
|
+
if (clipped === void 0) continue;
|
|
9338
|
+
synthesisClipped.push(clipped);
|
|
9339
|
+
if (span.judge) judgeClippedMs += clipped.to - clipped.from;
|
|
9340
|
+
else compositionClippedMs += clipped.to - clipped.from;
|
|
9188
9341
|
}
|
|
9189
|
-
|
|
9190
|
-
|
|
9191
|
-
const
|
|
9192
|
-
for (const
|
|
9193
|
-
|
|
9194
|
-
|
|
9195
|
-
|
|
9196
|
-
|
|
9342
|
+
const byName = {};
|
|
9343
|
+
const callsByName = {};
|
|
9344
|
+
const toolsClipped = [];
|
|
9345
|
+
for (const interval of coordinationTools) {
|
|
9346
|
+
const clipped = clip(interval);
|
|
9347
|
+
if (clipped === void 0) continue;
|
|
9348
|
+
byName[interval.name] = (byName[interval.name] ?? 0) + (clipped.to - clipped.from);
|
|
9349
|
+
callsByName[interval.name] = (callsByName[interval.name] ?? 0) + 1;
|
|
9350
|
+
toolsClipped.push(clipped);
|
|
9197
9351
|
}
|
|
9198
|
-
|
|
9352
|
+
const lengthOf = (intervals) => intervals.reduce((sum, interval) => sum + (interval.to - interval.from), 0);
|
|
9353
|
+
const coveredMs = unionLength([
|
|
9354
|
+
...modelClipped,
|
|
9355
|
+
...toolsClipped,
|
|
9356
|
+
...synthesisClipped
|
|
9357
|
+
]);
|
|
9358
|
+
const modelOnlyMs = unionLength([...modelClipped, ...toolsClipped]) - unionLength(toolsClipped);
|
|
9359
|
+
const breakdown = {
|
|
9360
|
+
coordinationModelMs: lengthOf(modelClipped),
|
|
9361
|
+
coordinationModelMsByPhase: byPhase,
|
|
9362
|
+
coordinationModelOnlyMs: modelOnlyMs,
|
|
9363
|
+
coordinationToolMs: lengthOf(toolsClipped),
|
|
9364
|
+
coordinationToolMsByName: byName,
|
|
9365
|
+
coordinationToolCallsByName: callsByName,
|
|
9366
|
+
synthesisMs: lengthOf(synthesisClipped),
|
|
9367
|
+
finalCompositionMs: compositionClippedMs,
|
|
9368
|
+
semanticJudgeMs: judgeClippedMs,
|
|
9369
|
+
coveredMs,
|
|
9370
|
+
residueMs: Math.max(0, path.postFanInMs - coveredMs)
|
|
9371
|
+
};
|
|
9372
|
+
if (path.postFanInMs > 0) breakdown.residueShare = breakdown.residueMs / path.postFanInMs;
|
|
9373
|
+
path.postFanIn = breakdown;
|
|
9199
9374
|
}
|
|
9200
|
-
|
|
9201
|
-
|
|
9202
|
-
|
|
9203
|
-
this.lastSeq.delete(runId);
|
|
9375
|
+
if (path.runWallMs !== void 0 && path.runWallMs > 0) {
|
|
9376
|
+
if (path.postFanInMs !== void 0) path.postFanInShare = path.postFanInMs / path.runWallMs;
|
|
9377
|
+
path.synthesisShare = synthesisMs / path.runWallMs;
|
|
9204
9378
|
}
|
|
9379
|
+
return path;
|
|
9380
|
+
}
|
|
9381
|
+
//#endregion
|
|
9382
|
+
//#region src/stores/critical-path.ts
|
|
9383
|
+
const parse = (at) => {
|
|
9384
|
+
if (at === void 0) return;
|
|
9385
|
+
const ms = Date.parse(at);
|
|
9386
|
+
return Number.isFinite(ms) ? ms : void 0;
|
|
9205
9387
|
};
|
|
9206
|
-
const TRANSCRIPT_SUFFIX = ".bin";
|
|
9207
9388
|
/**
|
|
9208
|
-
*
|
|
9209
|
-
* persisted CompiledWorkflow sources) as one file per ref under `dir`,
|
|
9210
|
-
* so compiled runs resume across processes. Refs follow the
|
|
9211
|
-
* `<runId>/<name>` convention; nested segments become directories.
|
|
9389
|
+
* Fold a run's critical path out of its journal.
|
|
9212
9390
|
*
|
|
9213
|
-
*
|
|
9214
|
-
* segment must match `[A-Za-z0-9._-]` and be neither empty, '.', nor
|
|
9215
|
-
* '..', and the resolved path must stay under the resolved root. A '..'
|
|
9216
|
-
* segment used to pass the per-segment alphabet (dots are in it) and, via
|
|
9217
|
-
* `join`, escape the root; a caller passing an untrusted ref (or an
|
|
9218
|
-
* untrusted runId, which prefixes checkpoint and workflow-source refs)
|
|
9219
|
-
* could read, write, or delete `.bin` files outside `dir`.
|
|
9391
|
+
* @param entries the journal of one run, in any order
|
|
9220
9392
|
*/
|
|
9221
|
-
|
|
9222
|
-
|
|
9223
|
-
|
|
9224
|
-
|
|
9225
|
-
|
|
9226
|
-
|
|
9227
|
-
|
|
9228
|
-
|
|
9229
|
-
|
|
9230
|
-
|
|
9231
|
-
|
|
9232
|
-
|
|
9233
|
-
|
|
9234
|
-
|
|
9235
|
-
|
|
9236
|
-
|
|
9237
|
-
|
|
9238
|
-
|
|
9239
|
-
|
|
9240
|
-
const
|
|
9241
|
-
|
|
9242
|
-
|
|
9243
|
-
|
|
9244
|
-
async get(ref) {
|
|
9245
|
-
try {
|
|
9246
|
-
return new Uint8Array(readFileSync(this.blobPath(ref)));
|
|
9247
|
-
} catch (error) {
|
|
9248
|
-
if (error.code === "ENOENT") return null;
|
|
9249
|
-
throw error;
|
|
9250
|
-
}
|
|
9251
|
-
}
|
|
9252
|
-
async list(runId) {
|
|
9253
|
-
if (runId === "." || runId === "..") throw new JournalOrderViolation(`FileTranscriptStore: runId '${runId}' is not filesystem-safe`);
|
|
9254
|
-
const root = join(this.dir, safeName(runId));
|
|
9255
|
-
const refs = [];
|
|
9256
|
-
const walk = (dir, prefix) => {
|
|
9257
|
-
let names;
|
|
9258
|
-
try {
|
|
9259
|
-
names = readdirSync(dir);
|
|
9260
|
-
} catch {
|
|
9261
|
-
return;
|
|
9262
|
-
}
|
|
9263
|
-
for (const name of names) {
|
|
9264
|
-
const path = join(dir, name);
|
|
9265
|
-
if (statSync(path).isDirectory()) walk(path, `${prefix}${name}/`);
|
|
9266
|
-
else if (name.endsWith(TRANSCRIPT_SUFFIX)) refs.push(`${prefix}${name.slice(0, -4)}`);
|
|
9267
|
-
}
|
|
9268
|
-
};
|
|
9269
|
-
walk(root, `${runId}/`);
|
|
9270
|
-
return refs.sort();
|
|
9271
|
-
}
|
|
9272
|
-
async delete(ref) {
|
|
9273
|
-
try {
|
|
9274
|
-
rmSync(this.blobPath(ref));
|
|
9275
|
-
} catch (error) {
|
|
9276
|
-
if (error.code !== "ENOENT") throw error;
|
|
9393
|
+
function criticalPathFromJournal(entries) {
|
|
9394
|
+
const ordered = [...entries].sort((a, b) => a.seq - b.seq);
|
|
9395
|
+
let runStart;
|
|
9396
|
+
let runEnd;
|
|
9397
|
+
let lastWorkerEnd;
|
|
9398
|
+
let workerSpans = 0;
|
|
9399
|
+
let unclassifiedSpans = 0;
|
|
9400
|
+
let synthesisMs = 0;
|
|
9401
|
+
let finalCompositionMs = 0;
|
|
9402
|
+
let semanticJudgeMs = 0;
|
|
9403
|
+
let labelledSynthesis = false;
|
|
9404
|
+
let unlabelledSynthesis = false;
|
|
9405
|
+
for (const entry of ordered) {
|
|
9406
|
+
const startedAt = parse(entry.startedAt);
|
|
9407
|
+
const endedAt = parse(entry.endedAt);
|
|
9408
|
+
if (startedAt !== void 0) runStart = runStart === void 0 ? startedAt : Math.min(runStart, startedAt);
|
|
9409
|
+
const last = endedAt ?? startedAt;
|
|
9410
|
+
if (last !== void 0) runEnd = runEnd === void 0 ? last : Math.max(runEnd, last);
|
|
9411
|
+
if (entry.kind !== "agent" || entry.status === "running" || entry.status === "suspended") continue;
|
|
9412
|
+
const role = entry.costAttribution?.role;
|
|
9413
|
+
if (role === void 0) {
|
|
9414
|
+
unclassifiedSpans += 1;
|
|
9415
|
+
continue;
|
|
9277
9416
|
}
|
|
9278
|
-
|
|
9279
|
-
|
|
9280
|
-
|
|
9281
|
-
|
|
9282
|
-
|
|
9283
|
-
* Resolves the pricing for a model: the versioned table wins; the
|
|
9284
|
-
* adapter-reported caps.pricing is the fallback; undefined means
|
|
9285
|
-
* unpriced (the CostReport surfaces it, never a silent zero).
|
|
9286
|
-
*/
|
|
9287
|
-
function resolvePricing(ref, table, capsPricing) {
|
|
9288
|
-
return table?.models[ref] ?? capsPricing;
|
|
9289
|
-
}
|
|
9290
|
-
/** The tier a full prompt lands in: the highest threshold strictly below it. */
|
|
9291
|
-
function tierFor(pricing, inputTokens) {
|
|
9292
|
-
let tier;
|
|
9293
|
-
for (const candidate of pricing.tiers ?? []) if (inputTokens > candidate.aboveInputTokens && (tier === void 0 || candidate.aboveInputTokens > tier.aboveInputTokens)) tier = candidate;
|
|
9294
|
-
return tier;
|
|
9295
|
-
}
|
|
9296
|
-
/**
|
|
9297
|
-
* Decomposes one usage against one pricing row into the four billing
|
|
9298
|
-
* components. Under the Usage invariant inputTokens is the FULL prompt
|
|
9299
|
-
* including cache reads and writes, so the input rate bills only the
|
|
9300
|
-
* uncached remainder and cache tokens bill at their own rates, never
|
|
9301
|
-
* twice; a row that omits a cache rate bills those tokens at the plain
|
|
9302
|
-
* input rate rather than silently for free. A row may carry
|
|
9303
|
-
* long-context tiers: the highest threshold strictly below the full
|
|
9304
|
-
* prompt re-prices the ENTIRE request (input-side rates scale by
|
|
9305
|
-
* inputMultiplier, the output rate by outputMultiplier). Cache writes
|
|
9306
|
-
* price at the 5m premium rate by default; when the usage carries the
|
|
9307
|
-
* TTL split (RV810: `cacheWrite5mTokens` and `cacheWrite1hTokens`,
|
|
9308
|
-
* filled by adapters whose provider distinguishes write TTLs), the 1h
|
|
9309
|
-
* share prices at `cacheWrite1hUsdPerMTok` (falling back to the plain
|
|
9310
|
-
* write rate when the row lacks it) and everything the 1h share does
|
|
9311
|
-
* not claim, the 5m share plus any unattributed remainder an upstream
|
|
9312
|
-
* invariant violation left, bills at the write rate, never silently
|
|
9313
|
-
* for free. The component's `tokens` stays the WHOLE
|
|
9314
|
-
* `cacheWriteTokens` either way, so statement reconciliation keys are
|
|
9315
|
-
* unchanged.
|
|
9316
|
-
*/
|
|
9317
|
-
function priceComponentsOf(pricing, usage) {
|
|
9318
|
-
const tier = tierFor(pricing, usage.inputTokens);
|
|
9319
|
-
const inputMul = tier?.inputMultiplier ?? 1;
|
|
9320
|
-
const outputMul = tier?.outputMultiplier ?? 1;
|
|
9321
|
-
const uncachedInputTokens = Math.max(0, usage.inputTokens - usage.cacheReadTokens - usage.cacheWriteTokens);
|
|
9322
|
-
const writeRate = pricing.cacheWriteUsdPerMTok ?? pricing.inputUsdPerMTok;
|
|
9323
|
-
const write1hRate = pricing.cacheWrite1hUsdPerMTok ?? writeRate;
|
|
9324
|
-
const write1hTokens = usage.cacheWrite5mTokens !== void 0 || usage.cacheWrite1hTokens !== void 0 ? usage.cacheWrite1hTokens ?? 0 : 0;
|
|
9325
|
-
const writeDefaultTokens = Math.max(0, usage.cacheWriteTokens - write1hTokens);
|
|
9326
|
-
return {
|
|
9327
|
-
input: {
|
|
9328
|
-
tokens: uncachedInputTokens,
|
|
9329
|
-
usd: uncachedInputTokens / 1e6 * pricing.inputUsdPerMTok * inputMul
|
|
9330
|
-
},
|
|
9331
|
-
output: {
|
|
9332
|
-
tokens: usage.outputTokens,
|
|
9333
|
-
usd: usage.outputTokens / 1e6 * pricing.outputUsdPerMTok * outputMul
|
|
9334
|
-
},
|
|
9335
|
-
cachedInput: {
|
|
9336
|
-
tokens: usage.cacheReadTokens,
|
|
9337
|
-
usd: usage.cacheReadTokens / 1e6 * (pricing.cacheReadUsdPerMTok ?? pricing.inputUsdPerMTok) * inputMul
|
|
9338
|
-
},
|
|
9339
|
-
cacheWrite: {
|
|
9340
|
-
tokens: usage.cacheWriteTokens,
|
|
9341
|
-
usd: (writeDefaultTokens / 1e6 * writeRate + write1hTokens / 1e6 * write1hRate) * inputMul
|
|
9417
|
+
if (role === "orchestrate") continue;
|
|
9418
|
+
if (role !== "synthesize") {
|
|
9419
|
+
workerSpans += 1;
|
|
9420
|
+
if (endedAt !== void 0) lastWorkerEnd = lastWorkerEnd === void 0 ? endedAt : Math.max(lastWorkerEnd, endedAt);
|
|
9421
|
+
continue;
|
|
9342
9422
|
}
|
|
9343
|
-
|
|
9344
|
-
|
|
9345
|
-
|
|
9346
|
-
|
|
9347
|
-
|
|
9348
|
-
|
|
9349
|
-
* cache writes).
|
|
9350
|
-
*/
|
|
9351
|
-
function priceUsdOf(pricing, usage) {
|
|
9352
|
-
const parts = priceComponentsOf(pricing, usage);
|
|
9353
|
-
return parts.input.usd + parts.output.usd + parts.cachedInput.usd + parts.cacheWrite.usd;
|
|
9354
|
-
}
|
|
9355
|
-
/**
|
|
9356
|
-
* The output tokens `remainingUsd` still buys from one pricing row after
|
|
9357
|
-
* paying for an estimated prompt of `estimatedInputTokens`, priced with
|
|
9358
|
-
* the same tier rules as settlement (the tier is selected by the
|
|
9359
|
-
* estimated prompt). Floored to whole tokens; zero or negative means not
|
|
9360
|
-
* even one output token fits, so the turn must not be dispatched.
|
|
9361
|
-
* Undefined when the row prices output at zero (a free model needs no
|
|
9362
|
-
* output bound).
|
|
9363
|
-
*/
|
|
9364
|
-
function affordableOutputTokens(pricing, remainingUsd, estimatedInputTokens) {
|
|
9365
|
-
const tier = tierFor(pricing, estimatedInputTokens);
|
|
9366
|
-
const outputRate = pricing.outputUsdPerMTok * (tier?.outputMultiplier ?? 1);
|
|
9367
|
-
if (outputRate <= 0) return;
|
|
9368
|
-
const inputUsd = priceUsdOf(pricing, {
|
|
9369
|
-
inputTokens: estimatedInputTokens,
|
|
9370
|
-
outputTokens: 0,
|
|
9371
|
-
cacheReadTokens: 0,
|
|
9372
|
-
cacheWriteTokens: 0
|
|
9373
|
-
});
|
|
9374
|
-
return Math.floor((remainingUsd - inputUsd) / outputRate * 1e6);
|
|
9375
|
-
}
|
|
9376
|
-
const RATE_FIELDS = [
|
|
9377
|
-
"inputUsdPerMTok",
|
|
9378
|
-
"outputUsdPerMTok",
|
|
9379
|
-
"cacheReadUsdPerMTok",
|
|
9380
|
-
"cacheWriteUsdPerMTok",
|
|
9381
|
-
"cacheWrite1hUsdPerMTok"
|
|
9382
|
-
];
|
|
9383
|
-
const TIER_FIELDS = [
|
|
9384
|
-
"aboveInputTokens",
|
|
9385
|
-
"inputMultiplier",
|
|
9386
|
-
"outputMultiplier"
|
|
9387
|
-
];
|
|
9388
|
-
/**
|
|
9389
|
-
* Compares a pricing seed against rates extracted from the provider's
|
|
9390
|
-
* documented pricing page, in BOTH directions (RV902): a seed rate the
|
|
9391
|
-
* page moved or dropped is a finding, and so is a documented billable
|
|
9392
|
-
* rate the seed never declared, because a billable column missing from
|
|
9393
|
-
* the seed is a silent underpricing channel (the 1h cache-write premium
|
|
9394
|
-
* hid exactly there). Declared long-context tiers compare field by
|
|
9395
|
-
* field. Returns human-readable findings, empty when the sides agree;
|
|
9396
|
-
* the weekly rates audit (scripts/rates-audit.mjs) runs this exact
|
|
9397
|
-
* comparator over the live pages, and the fault-injection kit drives it
|
|
9398
|
-
* as a permanent gate (RV909). It verifies DOCUMENTATION, not billing:
|
|
9399
|
-
* only a statement reconciliation over saved exports settles what the
|
|
9400
|
-
* provider's meter actually charges.
|
|
9401
|
-
*/
|
|
9402
|
-
function compareRates(seed, page) {
|
|
9403
|
-
const findings = [];
|
|
9404
|
-
for (const field of RATE_FIELDS) {
|
|
9405
|
-
const seedValue = seed[field];
|
|
9406
|
-
const pageValue = page[field];
|
|
9407
|
-
if (seedValue === void 0) {
|
|
9408
|
-
if (pageValue !== void 0) findings.push(`${field}: the page shows ${String(pageValue)} but the seed declares no such rate`);
|
|
9423
|
+
if (startedAt === void 0 || endedAt === void 0) continue;
|
|
9424
|
+
const wall = Math.max(0, endedAt - startedAt);
|
|
9425
|
+
synthesisMs += wall;
|
|
9426
|
+
const label = entry.costAttribution?.label;
|
|
9427
|
+
if (label === void 0) {
|
|
9428
|
+
unlabelledSynthesis = true;
|
|
9409
9429
|
continue;
|
|
9410
9430
|
}
|
|
9411
|
-
|
|
9412
|
-
|
|
9431
|
+
labelledSynthesis = true;
|
|
9432
|
+
if (label === "claim-consistency-judge" || label.startsWith(`claim-consistency-judge-`)) semanticJudgeMs += wall;
|
|
9433
|
+
else finalCompositionMs += wall;
|
|
9413
9434
|
}
|
|
9414
|
-
const
|
|
9415
|
-
const
|
|
9416
|
-
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
|
|
9420
|
-
|
|
9421
|
-
|
|
9422
|
-
|
|
9435
|
+
const segments = logicalRunTelemetry(ordered).segments;
|
|
9436
|
+
const path = {
|
|
9437
|
+
workerSpans,
|
|
9438
|
+
synthesisMs,
|
|
9439
|
+
unclassifiedSpans,
|
|
9440
|
+
segments
|
|
9441
|
+
};
|
|
9442
|
+
if (labelledSynthesis && !unlabelledSynthesis) {
|
|
9443
|
+
path.finalCompositionMs = finalCompositionMs;
|
|
9444
|
+
path.semanticJudgeMs = semanticJudgeMs;
|
|
9445
|
+
}
|
|
9446
|
+
if (segments > 1 || runStart === void 0 || runEnd === void 0) return path;
|
|
9447
|
+
path.runWallMs = Math.max(0, runEnd - runStart);
|
|
9448
|
+
if (lastWorkerEnd !== void 0) path.postFanInMs = Math.max(0, runEnd - lastWorkerEnd);
|
|
9449
|
+
if (path.runWallMs > 0) {
|
|
9450
|
+
if (path.postFanInMs !== void 0) path.postFanInShare = path.postFanInMs / path.runWallMs;
|
|
9451
|
+
path.synthesisShare = synthesisMs / path.runWallMs;
|
|
9423
9452
|
}
|
|
9424
|
-
return
|
|
9453
|
+
return path;
|
|
9425
9454
|
}
|
|
9426
9455
|
//#endregion
|
|
9427
|
-
//#region src/
|
|
9456
|
+
//#region src/stores/jsonl.ts
|
|
9428
9457
|
/**
|
|
9429
|
-
*
|
|
9430
|
-
*
|
|
9431
|
-
*
|
|
9432
|
-
*
|
|
9433
|
-
* epoch, admission at reservation time, reconciliation to actual
|
|
9434
|
-
* usage inside the same window. The hard guarantee is on
|
|
9435
|
-
* `requestsPerMinute` (every wire attempt is exactly one request);
|
|
9436
|
-
* `tokensPerMinute` admits on the heuristic estimate and settles to
|
|
9437
|
-
* actual usage, so token windows are approximate at admission and
|
|
9438
|
-
* exact at settlement.
|
|
9458
|
+
* JsonlFileStore (M2-T01): the durable file store. One JSON entry per
|
|
9459
|
+
* line per run; the journal doubles as an event log. Meta records live
|
|
9460
|
+
* beside the journal and are replaced atomically, so listRuns never
|
|
9461
|
+
* parses payloads.
|
|
9439
9462
|
*
|
|
9440
|
-
*
|
|
9463
|
+
* Contract (DEF-4 tightening):
|
|
9464
|
+
* - A1 atomicity: a torn trailing line (crash mid-append) is never
|
|
9465
|
+
* visible in load; the incomplete fragment is dropped and overwritten
|
|
9466
|
+
* by the next append. Whole records on that line are data, never
|
|
9467
|
+
* fragment (RV701): a crash that persisted every JSON byte but not
|
|
9468
|
+
* the '\n' leaves a parseable tail that load serves and append
|
|
9469
|
+
* terminates before writing, and repair salvages complete records a
|
|
9470
|
+
* glued line carries instead of discarding the line, so an entry a
|
|
9471
|
+
* load has served can never be un-served by a later repair.
|
|
9472
|
+
* - A2 total per-run order: load returns append order, stable across
|
|
9473
|
+
* calls (the kernel's per-run queue serializes appends).
|
|
9474
|
+
* - A3 read-your-writes: append resolves after the line is written.
|
|
9475
|
+
* - A4 opaque payload: entries round-trip byte-for-byte as JSON; unknown
|
|
9476
|
+
* kinds and fields pass through untouched.
|
|
9477
|
+
*
|
|
9478
|
+
* Leasing is NOT implemented here: LeasableStore ships with
|
|
9479
|
+
* @rulvar/store-sqlite (M5); JsonlFileStore is single-writer by
|
|
9480
|
+
* convention.
|
|
9441
9481
|
*/
|
|
9482
|
+
const JOURNAL_SUFFIX = ".jsonl";
|
|
9483
|
+
const META_SUFFIX = ".meta.json";
|
|
9484
|
+
function safeName(runId) {
|
|
9485
|
+
if (!/^[A-Za-z0-9._-]+$/.test(runId)) throw new JournalOrderViolation(`JsonlFileStore: runId '${runId}' is not filesystem-safe ([A-Za-z0-9._-] only)`);
|
|
9486
|
+
return runId;
|
|
9487
|
+
}
|
|
9442
9488
|
/**
|
|
9443
|
-
*
|
|
9444
|
-
*
|
|
9445
|
-
*
|
|
9446
|
-
*
|
|
9489
|
+
* Whole JSON values glued on one line, split apart without parser
|
|
9490
|
+
* ambiguity (RV701): depth is tracked outside string literals only, and
|
|
9491
|
+
* every candidate must still round-trip JSON.parse. A line that is not a
|
|
9492
|
+
* clean concatenation from its first byte salvages its whole prefix
|
|
9493
|
+
* values and returns everything after them as the torn fragment, so the
|
|
9494
|
+
* caller keeps accepted records and drops exactly the unacknowledged
|
|
9495
|
+
* tail a crash tore.
|
|
9447
9496
|
*/
|
|
9448
|
-
|
|
9449
|
-
|
|
9450
|
-
|
|
9451
|
-
|
|
9497
|
+
function splitConcatenatedJson(line) {
|
|
9498
|
+
const whole = [];
|
|
9499
|
+
let start = 0;
|
|
9500
|
+
let depth = 0;
|
|
9501
|
+
let inString = false;
|
|
9502
|
+
let escaped = false;
|
|
9503
|
+
for (let i = 0; i < line.length; i += 1) {
|
|
9504
|
+
const ch = line[i];
|
|
9505
|
+
if (inString) {
|
|
9506
|
+
if (escaped) escaped = false;
|
|
9507
|
+
else if (ch === "\\") escaped = true;
|
|
9508
|
+
else if (ch === "\"") inString = false;
|
|
9509
|
+
continue;
|
|
9510
|
+
}
|
|
9511
|
+
if (ch === "\"") {
|
|
9512
|
+
inString = true;
|
|
9513
|
+
continue;
|
|
9514
|
+
}
|
|
9515
|
+
if (ch === "{" || ch === "[") {
|
|
9516
|
+
depth += 1;
|
|
9517
|
+
continue;
|
|
9518
|
+
}
|
|
9519
|
+
if (ch === "}" || ch === "]") {
|
|
9520
|
+
depth -= 1;
|
|
9521
|
+
if (depth < 0) return {
|
|
9522
|
+
whole,
|
|
9523
|
+
fragment: line.slice(start)
|
|
9524
|
+
};
|
|
9525
|
+
if (depth === 0) {
|
|
9526
|
+
const candidate = line.slice(start, i + 1);
|
|
9527
|
+
try {
|
|
9528
|
+
whole.push(JSON.parse(candidate));
|
|
9529
|
+
} catch {
|
|
9530
|
+
return {
|
|
9531
|
+
whole,
|
|
9532
|
+
fragment: line.slice(start)
|
|
9533
|
+
};
|
|
9534
|
+
}
|
|
9535
|
+
start = i + 1;
|
|
9536
|
+
}
|
|
9537
|
+
}
|
|
9538
|
+
}
|
|
9539
|
+
return {
|
|
9540
|
+
whole,
|
|
9541
|
+
fragment: line.slice(start)
|
|
9542
|
+
};
|
|
9543
|
+
}
|
|
9544
|
+
var JsonlFileStore = class {
|
|
9545
|
+
dir;
|
|
9546
|
+
/**
|
|
9547
|
+
* The stored tail seq per run, lazily initialized from the file on the
|
|
9548
|
+
* first append this instance performs (obligation A5). Per instance by
|
|
9549
|
+
* design: cross-process writers are the lease seam's job.
|
|
9550
|
+
*/
|
|
9551
|
+
lastSeq = /* @__PURE__ */ new Map();
|
|
9552
|
+
/**
|
|
9553
|
+
* The verify-only load switch (RV1512): with `repairOnLoad: false`,
|
|
9554
|
+
* `load` serves the salvageable records WITHOUT rewriting the file,
|
|
9555
|
+
* so an auditor's "verification" read never destroys the evidence
|
|
9556
|
+
* of a tear it found. The default keeps the owner semantics byte
|
|
9557
|
+
* for byte: a torn tail repairs on load exactly as documented in
|
|
9558
|
+
* the A1 model above. Mutations (`append`, `putMeta`, `delete`)
|
|
9559
|
+
* are unaffected by the flag; an auditor that must not write simply
|
|
9560
|
+
* does not call them.
|
|
9561
|
+
*/
|
|
9562
|
+
repairOnLoad;
|
|
9563
|
+
constructor(options) {
|
|
9564
|
+
this.dir = options.dir;
|
|
9565
|
+
this.repairOnLoad = options.repairOnLoad !== false;
|
|
9566
|
+
mkdirSync(this.dir, { recursive: true });
|
|
9567
|
+
}
|
|
9568
|
+
journalPath(runId) {
|
|
9569
|
+
return join(this.dir, `${safeName(runId)}${JOURNAL_SUFFIX}`);
|
|
9570
|
+
}
|
|
9571
|
+
metaPath(runId) {
|
|
9572
|
+
return join(this.dir, `${safeName(runId)}${META_SUFFIX}`);
|
|
9573
|
+
}
|
|
9574
|
+
async append(runId, e) {
|
|
9575
|
+
let tail = this.lastSeq.get(runId);
|
|
9576
|
+
if (tail === void 0) {
|
|
9577
|
+
const existing = await this.load(runId);
|
|
9578
|
+
this.terminateUnterminatedTail(runId);
|
|
9579
|
+
const last = existing[existing.length - 1];
|
|
9580
|
+
tail = last !== void 0 && Number.isFinite(last.seq) ? last.seq : Number.NEGATIVE_INFINITY;
|
|
9581
|
+
this.lastSeq.set(runId, tail);
|
|
9582
|
+
}
|
|
9583
|
+
if (Number.isFinite(e.seq) && e.seq <= tail) throw new JournalOrderViolation(`JsonlFileStore: append of seq ${e.seq} to run '${runId}' is not after the stored tail seq ${tail}; a concurrent writer raced this journal from a stale tail`);
|
|
9584
|
+
appendFileSync(this.journalPath(runId), `${JSON.stringify(e)}\n`, "utf8");
|
|
9585
|
+
if (Number.isFinite(e.seq)) this.lastSeq.set(runId, e.seq);
|
|
9586
|
+
}
|
|
9587
|
+
async load(runId) {
|
|
9588
|
+
let raw;
|
|
9589
|
+
try {
|
|
9590
|
+
raw = readFileSync(this.journalPath(runId), "utf8");
|
|
9591
|
+
} catch (thrown) {
|
|
9592
|
+
if (thrown.code === "ENOENT") return [];
|
|
9593
|
+
throw thrown;
|
|
9594
|
+
}
|
|
9595
|
+
const lines = raw.split("\n");
|
|
9596
|
+
const entries = [];
|
|
9597
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
9598
|
+
const line = lines[i] ?? "";
|
|
9599
|
+
if (line === "") continue;
|
|
9600
|
+
try {
|
|
9601
|
+
entries.push(JSON.parse(line));
|
|
9602
|
+
} catch (thrown) {
|
|
9603
|
+
if (lines.slice(i + 1).every((rest) => rest === "")) {
|
|
9604
|
+
for (const value of splitConcatenatedJson(line).whole) entries.push(value);
|
|
9605
|
+
if (this.repairOnLoad) this.repairTornTail(runId, entries);
|
|
9606
|
+
break;
|
|
9607
|
+
}
|
|
9608
|
+
throw new JournalOrderViolation(`JsonlFileStore: corrupt journal line ${i + 1} of run '${runId}' (not the trailing line, so this is not a torn append)`, { cause: thrown });
|
|
9609
|
+
}
|
|
9610
|
+
}
|
|
9611
|
+
return entries;
|
|
9612
|
+
}
|
|
9613
|
+
/**
|
|
9614
|
+
* Restores the trailing '\n' of a parseable-but-unterminated tail
|
|
9615
|
+
* (RV701). One byte appended in place terminates the record exactly
|
|
9616
|
+
* where the crash left it; the file's bytes before it stay untouched.
|
|
9617
|
+
* No-op on a missing, empty, or already-terminated journal.
|
|
9618
|
+
*/
|
|
9619
|
+
terminateUnterminatedTail(runId) {
|
|
9620
|
+
const path = this.journalPath(runId);
|
|
9621
|
+
let fd;
|
|
9622
|
+
try {
|
|
9623
|
+
fd = openSync(path, "r");
|
|
9624
|
+
} catch (thrown) {
|
|
9625
|
+
if (thrown.code === "ENOENT") return;
|
|
9626
|
+
throw thrown;
|
|
9627
|
+
}
|
|
9628
|
+
let needsNewline = false;
|
|
9629
|
+
try {
|
|
9630
|
+
const size = fstatSync(fd).size;
|
|
9631
|
+
if (size > 0) {
|
|
9632
|
+
const lastByte = /* @__PURE__ */ new Uint8Array(1);
|
|
9633
|
+
readSync(fd, lastByte, 0, 1, size - 1);
|
|
9634
|
+
needsNewline = lastByte[0] !== 10;
|
|
9635
|
+
}
|
|
9636
|
+
} finally {
|
|
9637
|
+
closeSync(fd);
|
|
9638
|
+
}
|
|
9639
|
+
if (needsNewline) appendFileSync(path, "\n", "utf8");
|
|
9640
|
+
}
|
|
9641
|
+
repairTornTail(runId, whole) {
|
|
9642
|
+
const path = this.journalPath(runId);
|
|
9643
|
+
const temp = `${path}.tmp`;
|
|
9644
|
+
writeFileSync(temp, whole.map((entry) => JSON.stringify(entry)).join("\n") + (whole.length > 0 ? "\n" : ""), "utf8");
|
|
9645
|
+
renameSync(temp, path);
|
|
9646
|
+
}
|
|
9647
|
+
async putMeta(m) {
|
|
9648
|
+
const path = this.metaPath(m.runId);
|
|
9649
|
+
const temp = `${path}.tmp`;
|
|
9650
|
+
writeFileSync(temp, JSON.stringify(m, null, 2), "utf8");
|
|
9651
|
+
renameSync(temp, path);
|
|
9652
|
+
}
|
|
9653
|
+
async getMeta(runId) {
|
|
9654
|
+
try {
|
|
9655
|
+
return JSON.parse(readFileSync(this.metaPath(runId), "utf8"));
|
|
9656
|
+
} catch {
|
|
9657
|
+
return;
|
|
9658
|
+
}
|
|
9659
|
+
}
|
|
9660
|
+
async listRuns(f) {
|
|
9661
|
+
const metas = [];
|
|
9662
|
+
for (const file of readdirSync(this.dir)) {
|
|
9663
|
+
if (!file.endsWith(META_SUFFIX)) continue;
|
|
9664
|
+
try {
|
|
9665
|
+
metas.push(JSON.parse(readFileSync(join(this.dir, file), "utf8")));
|
|
9666
|
+
} catch {}
|
|
9667
|
+
}
|
|
9668
|
+
return metas.filter((meta) => metaMatchesFilter(meta, f));
|
|
9669
|
+
}
|
|
9670
|
+
async delete(runId) {
|
|
9671
|
+
rmSync(this.journalPath(runId), { force: true });
|
|
9672
|
+
rmSync(this.metaPath(runId), { force: true });
|
|
9673
|
+
this.lastSeq.delete(runId);
|
|
9674
|
+
}
|
|
9675
|
+
};
|
|
9676
|
+
const TRANSCRIPT_SUFFIX = ".bin";
|
|
9677
|
+
/**
|
|
9678
|
+
* File-backed TranscriptStore (M6-T02): blobs (transcripts, checkpoints,
|
|
9679
|
+
* persisted CompiledWorkflow sources) as one file per ref under `dir`,
|
|
9680
|
+
* so compiled runs resume across processes. Refs follow the
|
|
9681
|
+
* `<runId>/<name>` convention; nested segments become directories.
|
|
9682
|
+
*
|
|
9683
|
+
* Every ref is contained under `dir` (v1.36.0 review SEC-P1): each
|
|
9684
|
+
* segment must match `[A-Za-z0-9._-]` and be neither empty, '.', nor
|
|
9685
|
+
* '..', and the resolved path must stay under the resolved root. A '..'
|
|
9686
|
+
* segment used to pass the per-segment alphabet (dots are in it) and, via
|
|
9687
|
+
* `join`, escape the root; a caller passing an untrusted ref (or an
|
|
9688
|
+
* untrusted runId, which prefixes checkpoint and workflow-source refs)
|
|
9689
|
+
* could read, write, or delete `.bin` files outside `dir`.
|
|
9690
|
+
*/
|
|
9691
|
+
var FileTranscriptStore = class {
|
|
9692
|
+
dir;
|
|
9693
|
+
constructor(options) {
|
|
9694
|
+
this.dir = options.dir;
|
|
9695
|
+
mkdirSync(this.dir, { recursive: true });
|
|
9696
|
+
}
|
|
9697
|
+
blobPath(ref) {
|
|
9698
|
+
const segments = ref.split("/");
|
|
9699
|
+
for (const segment of segments) if (segment === "" || segment === "." || segment === ".." || !/^[A-Za-z0-9._-]+$/.test(segment)) throw new JournalOrderViolation(`FileTranscriptStore: ref segment '${segment}' is not filesystem-safe`);
|
|
9700
|
+
const name = segments.pop() ?? "";
|
|
9701
|
+
const path = join(this.dir, ...segments, `${name}${TRANSCRIPT_SUFFIX}`);
|
|
9702
|
+
const root = resolve(this.dir);
|
|
9703
|
+
const resolved = resolve(path);
|
|
9704
|
+
if (resolved !== root && !resolved.startsWith(`${root}${sep}`)) throw new JournalOrderViolation(`FileTranscriptStore: ref '${ref}' resolves outside the configured root`);
|
|
9705
|
+
return path;
|
|
9706
|
+
}
|
|
9707
|
+
async put(ref, blob) {
|
|
9708
|
+
const path = this.blobPath(ref);
|
|
9709
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
9710
|
+
const temp = `${path}.tmp`;
|
|
9711
|
+
writeFileSync(temp, blob);
|
|
9712
|
+
renameSync(temp, path);
|
|
9713
|
+
}
|
|
9714
|
+
async get(ref) {
|
|
9715
|
+
try {
|
|
9716
|
+
return new Uint8Array(readFileSync(this.blobPath(ref)));
|
|
9717
|
+
} catch (error) {
|
|
9718
|
+
if (error.code === "ENOENT") return null;
|
|
9719
|
+
throw error;
|
|
9720
|
+
}
|
|
9721
|
+
}
|
|
9722
|
+
async list(runId) {
|
|
9723
|
+
if (runId === "." || runId === "..") throw new JournalOrderViolation(`FileTranscriptStore: runId '${runId}' is not filesystem-safe`);
|
|
9724
|
+
const root = join(this.dir, safeName(runId));
|
|
9725
|
+
const refs = [];
|
|
9726
|
+
const walk = (dir, prefix) => {
|
|
9727
|
+
let names;
|
|
9728
|
+
try {
|
|
9729
|
+
names = readdirSync(dir);
|
|
9730
|
+
} catch {
|
|
9731
|
+
return;
|
|
9732
|
+
}
|
|
9733
|
+
for (const name of names) {
|
|
9734
|
+
const path = join(dir, name);
|
|
9735
|
+
if (statSync(path).isDirectory()) walk(path, `${prefix}${name}/`);
|
|
9736
|
+
else if (name.endsWith(TRANSCRIPT_SUFFIX)) refs.push(`${prefix}${name.slice(0, -4)}`);
|
|
9737
|
+
}
|
|
9738
|
+
};
|
|
9739
|
+
walk(root, `${runId}/`);
|
|
9740
|
+
return refs.sort();
|
|
9741
|
+
}
|
|
9742
|
+
async delete(ref) {
|
|
9743
|
+
try {
|
|
9744
|
+
rmSync(this.blobPath(ref));
|
|
9745
|
+
} catch (error) {
|
|
9746
|
+
if (error.code !== "ENOENT") throw error;
|
|
9747
|
+
}
|
|
9748
|
+
}
|
|
9749
|
+
};
|
|
9750
|
+
//#endregion
|
|
9751
|
+
//#region src/model/pricing.ts
|
|
9752
|
+
/**
|
|
9753
|
+
* Resolves the pricing for a model: the versioned table wins; the
|
|
9754
|
+
* adapter-reported caps.pricing is the fallback; undefined means
|
|
9755
|
+
* unpriced (the CostReport surfaces it, never a silent zero).
|
|
9756
|
+
*/
|
|
9757
|
+
function resolvePricing(ref, table, capsPricing) {
|
|
9758
|
+
return table?.models[ref] ?? capsPricing;
|
|
9759
|
+
}
|
|
9760
|
+
/** The tier a full prompt lands in: the highest threshold strictly below it. */
|
|
9761
|
+
function tierFor(pricing, inputTokens) {
|
|
9762
|
+
let tier;
|
|
9763
|
+
for (const candidate of pricing.tiers ?? []) if (inputTokens > candidate.aboveInputTokens && (tier === void 0 || candidate.aboveInputTokens > tier.aboveInputTokens)) tier = candidate;
|
|
9764
|
+
return tier;
|
|
9765
|
+
}
|
|
9766
|
+
/**
|
|
9767
|
+
* Decomposes one usage against one pricing row into the four billing
|
|
9768
|
+
* components. Under the Usage invariant inputTokens is the FULL prompt
|
|
9769
|
+
* including cache reads and writes, so the input rate bills only the
|
|
9770
|
+
* uncached remainder and cache tokens bill at their own rates, never
|
|
9771
|
+
* twice; a row that omits a cache rate bills those tokens at the plain
|
|
9772
|
+
* input rate rather than silently for free. A row may carry
|
|
9773
|
+
* long-context tiers: the highest threshold strictly below the full
|
|
9774
|
+
* prompt re-prices the ENTIRE request (input-side rates scale by
|
|
9775
|
+
* inputMultiplier, the output rate by outputMultiplier). Cache writes
|
|
9776
|
+
* price at the 5m premium rate by default; when the usage carries the
|
|
9777
|
+
* TTL split (RV810: `cacheWrite5mTokens` and `cacheWrite1hTokens`,
|
|
9778
|
+
* filled by adapters whose provider distinguishes write TTLs), the 1h
|
|
9779
|
+
* share prices at `cacheWrite1hUsdPerMTok` (falling back to the plain
|
|
9780
|
+
* write rate when the row lacks it) and everything the 1h share does
|
|
9781
|
+
* not claim, the 5m share plus any unattributed remainder an upstream
|
|
9782
|
+
* invariant violation left, bills at the write rate, never silently
|
|
9783
|
+
* for free. The component's `tokens` stays the WHOLE
|
|
9784
|
+
* `cacheWriteTokens` either way, so statement reconciliation keys are
|
|
9785
|
+
* unchanged.
|
|
9786
|
+
*/
|
|
9787
|
+
function priceComponentsOf(pricing, usage) {
|
|
9788
|
+
const tier = tierFor(pricing, usage.inputTokens);
|
|
9789
|
+
const inputMul = tier?.inputMultiplier ?? 1;
|
|
9790
|
+
const outputMul = tier?.outputMultiplier ?? 1;
|
|
9791
|
+
const uncachedInputTokens = Math.max(0, usage.inputTokens - usage.cacheReadTokens - usage.cacheWriteTokens);
|
|
9792
|
+
const writeRate = pricing.cacheWriteUsdPerMTok ?? pricing.inputUsdPerMTok;
|
|
9793
|
+
const write1hRate = pricing.cacheWrite1hUsdPerMTok ?? writeRate;
|
|
9794
|
+
const write1hTokens = usage.cacheWrite5mTokens !== void 0 || usage.cacheWrite1hTokens !== void 0 ? usage.cacheWrite1hTokens ?? 0 : 0;
|
|
9795
|
+
const writeDefaultTokens = Math.max(0, usage.cacheWriteTokens - write1hTokens);
|
|
9796
|
+
return {
|
|
9797
|
+
input: {
|
|
9798
|
+
tokens: uncachedInputTokens,
|
|
9799
|
+
usd: uncachedInputTokens / 1e6 * pricing.inputUsdPerMTok * inputMul
|
|
9800
|
+
},
|
|
9801
|
+
output: {
|
|
9802
|
+
tokens: usage.outputTokens,
|
|
9803
|
+
usd: usage.outputTokens / 1e6 * pricing.outputUsdPerMTok * outputMul
|
|
9804
|
+
},
|
|
9805
|
+
cachedInput: {
|
|
9806
|
+
tokens: usage.cacheReadTokens,
|
|
9807
|
+
usd: usage.cacheReadTokens / 1e6 * (pricing.cacheReadUsdPerMTok ?? pricing.inputUsdPerMTok) * inputMul
|
|
9808
|
+
},
|
|
9809
|
+
cacheWrite: {
|
|
9810
|
+
tokens: usage.cacheWriteTokens,
|
|
9811
|
+
usd: (writeDefaultTokens / 1e6 * writeRate + write1hTokens / 1e6 * write1hRate) * inputMul
|
|
9812
|
+
}
|
|
9813
|
+
};
|
|
9814
|
+
}
|
|
9815
|
+
/**
|
|
9816
|
+
* Dollars from normalized usage against one pricing row: the sum of the
|
|
9817
|
+
* {@link priceComponentsOf} terms in their declared order, byte for
|
|
9818
|
+
* byte the historical expression (uncached input, output, cached input,
|
|
9819
|
+
* cache writes).
|
|
9820
|
+
*/
|
|
9821
|
+
function priceUsdOf(pricing, usage) {
|
|
9822
|
+
const parts = priceComponentsOf(pricing, usage);
|
|
9823
|
+
return parts.input.usd + parts.output.usd + parts.cachedInput.usd + parts.cacheWrite.usd;
|
|
9824
|
+
}
|
|
9825
|
+
/**
|
|
9826
|
+
* The output tokens `remainingUsd` still buys from one pricing row after
|
|
9827
|
+
* paying for an estimated prompt of `estimatedInputTokens`, priced with
|
|
9828
|
+
* the same tier rules as settlement (the tier is selected by the
|
|
9829
|
+
* estimated prompt). Floored to whole tokens; zero or negative means not
|
|
9830
|
+
* even one output token fits, so the turn must not be dispatched.
|
|
9831
|
+
* Undefined when the row prices output at zero (a free model needs no
|
|
9832
|
+
* output bound).
|
|
9833
|
+
*/
|
|
9834
|
+
function affordableOutputTokens(pricing, remainingUsd, estimatedInputTokens) {
|
|
9835
|
+
const tier = tierFor(pricing, estimatedInputTokens);
|
|
9836
|
+
const outputRate = pricing.outputUsdPerMTok * (tier?.outputMultiplier ?? 1);
|
|
9837
|
+
if (outputRate <= 0) return;
|
|
9838
|
+
const inputUsd = priceUsdOf(pricing, {
|
|
9839
|
+
inputTokens: estimatedInputTokens,
|
|
9840
|
+
outputTokens: 0,
|
|
9841
|
+
cacheReadTokens: 0,
|
|
9842
|
+
cacheWriteTokens: 0
|
|
9843
|
+
});
|
|
9844
|
+
return Math.floor((remainingUsd - inputUsd) / outputRate * 1e6);
|
|
9845
|
+
}
|
|
9846
|
+
const RATE_FIELDS = [
|
|
9847
|
+
"inputUsdPerMTok",
|
|
9848
|
+
"outputUsdPerMTok",
|
|
9849
|
+
"cacheReadUsdPerMTok",
|
|
9850
|
+
"cacheWriteUsdPerMTok",
|
|
9851
|
+
"cacheWrite1hUsdPerMTok"
|
|
9852
|
+
];
|
|
9853
|
+
const TIER_FIELDS = [
|
|
9854
|
+
"aboveInputTokens",
|
|
9855
|
+
"inputMultiplier",
|
|
9856
|
+
"outputMultiplier"
|
|
9857
|
+
];
|
|
9858
|
+
/**
|
|
9859
|
+
* Compares a pricing seed against rates extracted from the provider's
|
|
9860
|
+
* documented pricing page, in BOTH directions (RV902): a seed rate the
|
|
9861
|
+
* page moved or dropped is a finding, and so is a documented billable
|
|
9862
|
+
* rate the seed never declared, because a billable column missing from
|
|
9863
|
+
* the seed is a silent underpricing channel (the 1h cache-write premium
|
|
9864
|
+
* hid exactly there). Declared long-context tiers compare field by
|
|
9865
|
+
* field. Returns human-readable findings, empty when the sides agree;
|
|
9866
|
+
* the weekly rates audit (scripts/rates-audit.mjs) runs this exact
|
|
9867
|
+
* comparator over the live pages, and the fault-injection kit drives it
|
|
9868
|
+
* as a permanent gate (RV909). It verifies DOCUMENTATION, not billing:
|
|
9869
|
+
* only a statement reconciliation over saved exports settles what the
|
|
9870
|
+
* provider's meter actually charges.
|
|
9871
|
+
*/
|
|
9872
|
+
function compareRates(seed, page) {
|
|
9873
|
+
const findings = [];
|
|
9874
|
+
for (const field of RATE_FIELDS) {
|
|
9875
|
+
const seedValue = seed[field];
|
|
9876
|
+
const pageValue = page[field];
|
|
9877
|
+
if (seedValue === void 0) {
|
|
9878
|
+
if (pageValue !== void 0) findings.push(`${field}: the page shows ${String(pageValue)} but the seed declares no such rate`);
|
|
9879
|
+
continue;
|
|
9880
|
+
}
|
|
9881
|
+
if (pageValue === void 0) findings.push(`${field}: seed ${String(seedValue)} but the page shows no such rate`);
|
|
9882
|
+
else if (!(Math.abs(seedValue - pageValue) <= 1e-9)) findings.push(`${field}: seed ${String(seedValue)} vs page ${String(pageValue)}`);
|
|
9883
|
+
}
|
|
9884
|
+
const seedTiers = seed.tiers;
|
|
9885
|
+
const pageTiers = page.tiers;
|
|
9886
|
+
if (!Array.isArray(seedTiers)) {
|
|
9887
|
+
if (Array.isArray(pageTiers) && pageTiers.length > 0) findings.push(`tiers: the page shows ${String(pageTiers.length)} but the seed declares none`);
|
|
9888
|
+
} else if (!Array.isArray(pageTiers) || pageTiers.length !== seedTiers.length) findings.push(`tiers: seed declares ${String(seedTiers.length)}, page shows ${Array.isArray(pageTiers) ? String(pageTiers.length) : "none"}`);
|
|
9889
|
+
else for (let i = 0; i < seedTiers.length; i += 1) for (const field of TIER_FIELDS) {
|
|
9890
|
+
const seedValue = seedTiers[i]?.[field] ?? NaN;
|
|
9891
|
+
const pageValue = pageTiers[i]?.[field] ?? NaN;
|
|
9892
|
+
if (!(Math.abs(seedValue - pageValue) <= 1e-9)) findings.push(`tiers[${String(i)}].${field}: seed ${String(seedValue)} vs page ${String(pageValue)}`);
|
|
9893
|
+
}
|
|
9894
|
+
return findings;
|
|
9895
|
+
}
|
|
9896
|
+
//#endregion
|
|
9897
|
+
//#region src/model/quota.ts
|
|
9898
|
+
/**
|
|
9899
|
+
* Quota rules and the in-process reference QuotaLimiter (RV-215).
|
|
9900
|
+
* The rule model is shared by every reference implementation
|
|
9901
|
+
* (memoryQuotaLimiter here, SqliteQuotaLimiter in
|
|
9902
|
+
* @rulvar/store-sqlite): fixed one-minute windows aligned to the
|
|
9903
|
+
* epoch, admission at reservation time, reconciliation to actual
|
|
9904
|
+
* usage inside the same window. The hard guarantee is on
|
|
9905
|
+
* `requestsPerMinute` (every wire attempt is exactly one request);
|
|
9906
|
+
* `tokensPerMinute` admits on the heuristic estimate and settles to
|
|
9907
|
+
* actual usage, so token windows are approximate at admission and
|
|
9908
|
+
* exact at settlement.
|
|
9909
|
+
*
|
|
9910
|
+
* Docs: https://docs.rulvar.com/guide/model-routing
|
|
9911
|
+
*/
|
|
9912
|
+
/**
|
|
9913
|
+
* Captured at module load, before the InProcessRunner's
|
|
9914
|
+
* nondeterminism guard can patch the global: the limiter's clock is
|
|
9915
|
+
* engine infrastructure on the live-only dispatch path and must never
|
|
9916
|
+
* be blamed on workflow code.
|
|
9917
|
+
*/
|
|
9918
|
+
const nativeNow = Date.now;
|
|
9919
|
+
/** The fixed accounting window every PerMinute cap counts over. */
|
|
9920
|
+
const QUOTA_WINDOW_MS = 6e4;
|
|
9921
|
+
/**
|
|
9452
9922
|
* Validates a quota rule set as a typed ConfigError before any
|
|
9453
9923
|
* limiter can admit under it: a non-array or empty set, a rule
|
|
9454
9924
|
* without a cap, a malformed dimension, or a malformed cap all fail
|
|
@@ -16364,520 +16834,232 @@ var AdmissionController = class {
|
|
|
16364
16834
|
this.lineageIndex?.noteAdmitted(logicalTaskId);
|
|
16365
16835
|
}
|
|
16366
16836
|
/**
|
|
16367
|
-
* Evaluates one spawn live, strictly BEFORE its decision entry is
|
|
16368
|
-
* appended. On admit the reserve is committed on the whole ancestor
|
|
16369
|
-
* account chain atomically with the evaluation; the caller journals the
|
|
16370
|
-
* returned decision and only then produces effects (child account,
|
|
16371
|
-
* dispatch). On reject nothing is committed and the reject verdict is
|
|
16372
|
-
* journaled by the caller so replay re-delivers it without
|
|
16373
|
-
* re-evaluation.
|
|
16374
|
-
*/
|
|
16375
|
-
/**
|
|
16376
|
-
* The reserve the DISPATCH layer will actually commit for this spec:
|
|
16377
|
-
* the estimate (or the flat default) clamped by the explicit child
|
|
16378
|
-
* budget when one exists, because only an explicit budget opens a
|
|
16379
|
-
* child-allowance account at dispatch; the childBudgetFraction cap
|
|
16380
|
-
* never materializes as an account and must not shrink the
|
|
16381
|
-
* projection. The token-count-priced estimate of ctx.agent is
|
|
16382
|
-
* unreachable here (async); a divergence there lands as a journaled
|
|
16383
|
-
* dispatch rejection instead of a strand. Delegates to the exported
|
|
16384
|
-
* {@link dispatchProjectionReserveUsd} so the live gate and
|
|
16385
|
-
* preflightEstimate share ONE formula (the 1.63.0 experiment review,
|
|
16386
|
-
* P0.3).
|
|
16387
|
-
*/
|
|
16388
|
-
projectedDispatchReserveUsd(spec) {
|
|
16389
|
-
return dispatchProjectionReserveUsd(spec, this.flatReserveUsd);
|
|
16390
|
-
}
|
|
16391
|
-
admit(spec, options) {
|
|
16392
|
-
const commitReserve = options?.commitReserve ?? true;
|
|
16393
|
-
const nodeKey = spec.nodeKey ?? spec.parentAccountScope;
|
|
16394
|
-
const depth = spawnDepthOf(spec.childScope);
|
|
16395
|
-
const childrenBefore = this.childrenOf.get(nodeKey) ?? 0;
|
|
16396
|
-
const evaluated = this.evaluateLineage(spec);
|
|
16397
|
-
const statsBefore = {
|
|
16398
|
-
spawnsBefore: this.budget.spent().agentsSpawned,
|
|
16399
|
-
childrenOfParentBefore: childrenBefore,
|
|
16400
|
-
depth,
|
|
16401
|
-
...evaluated.statsBefore === void 0 ? {} : { lineage: evaluated.statsBefore }
|
|
16402
|
-
};
|
|
16403
|
-
if (evaluated.decision.kind === "reject") return {
|
|
16404
|
-
verdict: {
|
|
16405
|
-
kind: "reject",
|
|
16406
|
-
reason: evaluated.decision.reason
|
|
16407
|
-
},
|
|
16408
|
-
statsBefore
|
|
16409
|
-
};
|
|
16410
|
-
if (this.terminationAccount !== void 0) {
|
|
16411
|
-
if ((spec.ladderLength ?? 1) > this.terminationAccount.limits.kMax) return {
|
|
16412
|
-
verdict: {
|
|
16413
|
-
kind: "reject",
|
|
16414
|
-
reason: { code: "ladder_exceeds_frozen" }
|
|
16415
|
-
},
|
|
16416
|
-
statsBefore
|
|
16417
|
-
};
|
|
16418
|
-
if (this.terminationAccount.spawnUnitsExhausted) return {
|
|
16419
|
-
verdict: {
|
|
16420
|
-
kind: "reject",
|
|
16421
|
-
reason: { code: "termination_exhausted" }
|
|
16422
|
-
},
|
|
16423
|
-
statsBefore
|
|
16424
|
-
};
|
|
16425
|
-
}
|
|
16426
|
-
if (depth > this.maxDepth) return {
|
|
16427
|
-
verdict: {
|
|
16428
|
-
kind: "reject",
|
|
16429
|
-
reason: { code: "depth" }
|
|
16430
|
-
},
|
|
16431
|
-
statsBefore
|
|
16432
|
-
};
|
|
16433
|
-
if (childrenBefore >= this.maxChildrenPerNode) return {
|
|
16434
|
-
verdict: {
|
|
16435
|
-
kind: "reject",
|
|
16436
|
-
reason: { code: "quota" }
|
|
16437
|
-
},
|
|
16438
|
-
statsBefore
|
|
16439
|
-
};
|
|
16440
|
-
if (this.maxTotalSpawns !== void 0 && this.admittedTotal >= this.maxTotalSpawns) return {
|
|
16441
|
-
verdict: {
|
|
16442
|
-
kind: "reject",
|
|
16443
|
-
reason: { code: "lifetime" }
|
|
16444
|
-
},
|
|
16445
|
-
statsBefore
|
|
16446
|
-
};
|
|
16447
|
-
if (spec.roster !== void 0) {
|
|
16448
|
-
const seatsRemaining = spec.roster.floor - spec.roster.admittedChildren;
|
|
16449
|
-
if (seatsRemaining > 0) {
|
|
16450
|
-
const perSeatProjectionUsd = this.projectedDispatchReserveUsd(spec);
|
|
16451
|
-
const remainder = this.budget.remainderOf(spec.parentAccountScope);
|
|
16452
|
-
if (remainder !== void 0 && remainder < seatsRemaining * perSeatProjectionUsd + spec.roster.liveExposureUsd) return {
|
|
16453
|
-
verdict: {
|
|
16454
|
-
kind: "reject",
|
|
16455
|
-
reason: {
|
|
16456
|
-
code: "roster_floor",
|
|
16457
|
-
floor: spec.roster.floor,
|
|
16458
|
-
admittedChildren: spec.roster.admittedChildren,
|
|
16459
|
-
seatsRemaining,
|
|
16460
|
-
perSeatProjectionUsd,
|
|
16461
|
-
liveExposureUsd: spec.roster.liveExposureUsd,
|
|
16462
|
-
remainderUsd: remainder
|
|
16463
|
-
}
|
|
16464
|
-
},
|
|
16465
|
-
statsBefore
|
|
16466
|
-
};
|
|
16467
|
-
}
|
|
16468
|
-
}
|
|
16469
|
-
const spawnToolOrigin = spec.origin === "spawn_agent" || spec.origin === "parallel_agents";
|
|
16470
|
-
let childCeilingUsd;
|
|
16471
|
-
const parentRemainder = this.budget.remainderOf(spec.parentAccountScope);
|
|
16472
|
-
if (spawnToolOrigin) {
|
|
16473
|
-
if (spec.budgetUsd !== void 0) childCeilingUsd = spec.budgetUsd;
|
|
16474
|
-
} else if (parentRemainder !== void 0) {
|
|
16475
|
-
const fractionCap = this.childBudgetFraction * parentRemainder;
|
|
16476
|
-
childCeilingUsd = spec.budgetUsd === void 0 ? fractionCap : Math.min(spec.budgetUsd, fractionCap);
|
|
16477
|
-
} else if (spec.budgetUsd !== void 0) childCeilingUsd = spec.budgetUsd;
|
|
16478
|
-
let reserveUsd = spec.estCostUsd ?? this.flatReserveUsd;
|
|
16479
|
-
const source = spec.estCostUsd === void 0 ? "default" : "estCost";
|
|
16480
|
-
let clampedBy;
|
|
16481
|
-
if (childCeilingUsd !== void 0 && reserveUsd > childCeilingUsd) {
|
|
16482
|
-
clampedBy = spec.budgetUsd !== void 0 && childCeilingUsd === spec.budgetUsd ? "explicit-budget" : "fraction-ceiling";
|
|
16483
|
-
reserveUsd = childCeilingUsd;
|
|
16484
|
-
}
|
|
16485
|
-
const reserve = {
|
|
16486
|
-
reserveUsd,
|
|
16487
|
-
source
|
|
16488
|
-
};
|
|
16489
|
-
if (clampedBy !== void 0) reserve.clampedBy = clampedBy;
|
|
16490
|
-
if (childCeilingUsd !== void 0) reserve.childCeilingUsd = childCeilingUsd;
|
|
16491
|
-
if (this.budget.spawnHeadroom <= 0) return {
|
|
16492
|
-
verdict: {
|
|
16493
|
-
kind: "reject",
|
|
16494
|
-
reason: { code: "lifetime" }
|
|
16495
|
-
},
|
|
16496
|
-
statsBefore
|
|
16497
|
-
};
|
|
16498
|
-
if (commitReserve) try {
|
|
16499
|
-
this.budget.admitSpawn(reserveUsd, spec.parentAccountScope);
|
|
16500
|
-
} catch {
|
|
16501
|
-
return {
|
|
16502
|
-
verdict: {
|
|
16503
|
-
kind: "reject",
|
|
16504
|
-
reason: { code: "budget" }
|
|
16505
|
-
},
|
|
16506
|
-
statsBefore
|
|
16507
|
-
};
|
|
16508
|
-
}
|
|
16509
|
-
else {
|
|
16510
|
-
const remainder = this.budget.remainderOf(spec.parentAccountScope);
|
|
16511
|
-
const projection = this.projectedDispatchReserveUsd(spec);
|
|
16512
|
-
if (remainder !== void 0 && (remainder <= 0 || remainder < projection + (spec.pendingReserveUsd ?? 0))) return {
|
|
16513
|
-
verdict: {
|
|
16514
|
-
kind: "reject",
|
|
16515
|
-
reason: { code: "budget" }
|
|
16516
|
-
},
|
|
16517
|
-
statsBefore
|
|
16518
|
-
};
|
|
16519
|
-
}
|
|
16520
|
-
this.childrenOf.set(nodeKey, childrenBefore + 1);
|
|
16521
|
-
this.admittedTotal += 1;
|
|
16522
|
-
const lineage = evaluated.decision.lineage;
|
|
16523
|
-
this.registerLineageAdmit(lineage.logicalTaskId);
|
|
16524
|
-
let spawnUnitsAfter = this.budget.spawnHeadroom;
|
|
16525
|
-
if (this.terminationAccount !== void 0) {
|
|
16526
|
-
const debited = this.terminationAccount.debitSpawn({
|
|
16527
|
-
logicalTaskId: lineage.logicalTaskId,
|
|
16528
|
-
isNew: spec.lineage === void 0,
|
|
16529
|
-
ladderLength: spec.ladderLength ?? 1
|
|
16530
|
-
});
|
|
16531
|
-
if (!debited.ok) return {
|
|
16532
|
-
verdict: {
|
|
16533
|
-
kind: "reject",
|
|
16534
|
-
reason: { code: "termination_exhausted" }
|
|
16535
|
-
},
|
|
16536
|
-
statsBefore
|
|
16537
|
-
};
|
|
16538
|
-
spawnUnitsAfter = debited.spawnUnitsAfter;
|
|
16539
|
-
}
|
|
16540
|
-
return {
|
|
16541
|
-
verdict: {
|
|
16542
|
-
kind: "admit",
|
|
16543
|
-
reserve,
|
|
16544
|
-
spawnUnitsAfter,
|
|
16545
|
-
lineage: {
|
|
16546
|
-
logicalTaskId: lineage.logicalTaskId,
|
|
16547
|
-
isNew: spec.lineage === void 0,
|
|
16548
|
-
depth
|
|
16549
|
-
}
|
|
16550
|
-
},
|
|
16551
|
-
statsBefore,
|
|
16552
|
-
nodeId: this.mintId(),
|
|
16553
|
-
lineage,
|
|
16554
|
-
...this.terminationAccount === void 0 ? {} : { ladderLength: spec.ladderLength ?? 1 }
|
|
16555
|
-
};
|
|
16556
|
-
}
|
|
16557
|
-
/**
|
|
16558
|
-
* Resume roll-forward for an orchestrator child (M6-T07): restores the
|
|
16559
|
-
* children-quota counter only. The budget seed already counts settled
|
|
16560
|
-
* agent dispatches, and an in-flight child re-commits its reserve
|
|
16561
|
-
* through the ctx.agent dispatch path.
|
|
16562
|
-
*/
|
|
16563
|
-
recoverChild(nodeKey) {
|
|
16564
|
-
this.childrenOf.set(nodeKey, (this.childrenOf.get(nodeKey) ?? 0) + 1);
|
|
16565
|
-
this.admittedTotal += 1;
|
|
16566
|
-
}
|
|
16567
|
-
/**
|
|
16568
|
-
* Resume roll-forward for a child that already SETTLED before the
|
|
16569
|
-
* resume: re-registers the counters (maxChildrenPerNode, the lifetime
|
|
16570
|
-
* cap, statsBefore fidelity) without committing any reserve; the spend
|
|
16571
|
-
* itself sits in the root ledger seed.
|
|
16837
|
+
* Evaluates one spawn live, strictly BEFORE its decision entry is
|
|
16838
|
+
* appended. On admit the reserve is committed on the whole ancestor
|
|
16839
|
+
* account chain atomically with the evaluation; the caller journals the
|
|
16840
|
+
* returned decision and only then produces effects (child account,
|
|
16841
|
+
* dispatch). On reject nothing is committed and the reject verdict is
|
|
16842
|
+
* journaled by the caller so replay re-delivers it without
|
|
16843
|
+
* re-evaluation.
|
|
16572
16844
|
*/
|
|
16573
|
-
recoverSettled(parentAccountScope) {
|
|
16574
|
-
this.budget.admitRecovered(0, parentAccountScope);
|
|
16575
|
-
this.childrenOf.set(parentAccountScope, (this.childrenOf.get(parentAccountScope) ?? 0) + 1);
|
|
16576
|
-
this.admittedTotal += 1;
|
|
16577
|
-
}
|
|
16578
16845
|
/**
|
|
16579
|
-
*
|
|
16580
|
-
*
|
|
16581
|
-
*
|
|
16582
|
-
*
|
|
16583
|
-
*
|
|
16846
|
+
* The reserve the DISPATCH layer will actually commit for this spec:
|
|
16847
|
+
* the estimate (or the flat default) clamped by the explicit child
|
|
16848
|
+
* budget when one exists, because only an explicit budget opens a
|
|
16849
|
+
* child-allowance account at dispatch; the childBudgetFraction cap
|
|
16850
|
+
* never materializes as an account and must not shrink the
|
|
16851
|
+
* projection. The token-count-priced estimate of ctx.agent is
|
|
16852
|
+
* unreachable here (async); a divergence there lands as a journaled
|
|
16853
|
+
* dispatch rejection instead of a strand. Delegates to the exported
|
|
16854
|
+
* {@link dispatchProjectionReserveUsd} so the live gate and
|
|
16855
|
+
* preflightEstimate share ONE formula (the 1.63.0 experiment review,
|
|
16856
|
+
* P0.3).
|
|
16584
16857
|
*/
|
|
16585
|
-
|
|
16586
|
-
|
|
16587
|
-
const reserveUsd = verdict.kind === "reuse_full" ? 0 : verdict.reserve.reserveUsd;
|
|
16588
|
-
this.budget.admitRecovered(reserveUsd, parentAccountScope);
|
|
16589
|
-
this.childrenOf.set(parentAccountScope, (this.childrenOf.get(parentAccountScope) ?? 0) + 1);
|
|
16590
|
-
this.admittedTotal += 1;
|
|
16591
|
-
}
|
|
16592
|
-
};
|
|
16593
|
-
//#endregion
|
|
16594
|
-
//#region src/l0/telemetry-reduce.ts
|
|
16595
|
-
const ZERO = {
|
|
16596
|
-
inputTokens: 0,
|
|
16597
|
-
outputTokens: 0,
|
|
16598
|
-
cacheReadTokens: 0,
|
|
16599
|
-
cacheWriteTokens: 0
|
|
16600
|
-
};
|
|
16601
|
-
/**
|
|
16602
|
-
* Reduces one run's event stream (or any slice of it) to the invocation
|
|
16603
|
-
* table. Feed it the events in emission order; both a live stream and a
|
|
16604
|
-
* replayed one produce the same usage and cost columns.
|
|
16605
|
-
*/
|
|
16606
|
-
function reduceInvocationTable(events) {
|
|
16607
|
-
const rows = /* @__PURE__ */ new Map();
|
|
16608
|
-
const order = [];
|
|
16609
|
-
const openPhases = /* @__PURE__ */ new Map();
|
|
16610
|
-
const byRole = {};
|
|
16611
|
-
let totalCostUsd = 0;
|
|
16612
|
-
const rowFor = (event) => {
|
|
16613
|
-
let row = rows.get(event.spanId);
|
|
16614
|
-
if (row === void 0) {
|
|
16615
|
-
row = {
|
|
16616
|
-
spanId: event.spanId,
|
|
16617
|
-
agentType: event.agentType,
|
|
16618
|
-
...event.label === void 0 ? {} : { label: event.label },
|
|
16619
|
-
usage: ZERO,
|
|
16620
|
-
costUsd: 0,
|
|
16621
|
-
costBasis: "aggregate-estimate",
|
|
16622
|
-
usageApprox: false,
|
|
16623
|
-
retryCount: 0,
|
|
16624
|
-
replayed: event.replayed === true,
|
|
16625
|
-
open: true,
|
|
16626
|
-
phases: []
|
|
16627
|
-
};
|
|
16628
|
-
rows.set(event.spanId, row);
|
|
16629
|
-
order.push(row);
|
|
16630
|
-
}
|
|
16631
|
-
return row;
|
|
16632
|
-
};
|
|
16633
|
-
for (const event of events) switch (event.type) {
|
|
16634
|
-
case "agent:start": {
|
|
16635
|
-
const row = rowFor(event);
|
|
16636
|
-
row.role = event.role;
|
|
16637
|
-
break;
|
|
16638
|
-
}
|
|
16639
|
-
case "agent:phase:start": {
|
|
16640
|
-
const row = rowFor(event);
|
|
16641
|
-
const phase = {
|
|
16642
|
-
invocation: event.invocation,
|
|
16643
|
-
role: event.role,
|
|
16644
|
-
model: event.model,
|
|
16645
|
-
durationMs: 0,
|
|
16646
|
-
usage: ZERO,
|
|
16647
|
-
costUsd: 0,
|
|
16648
|
-
costBasis: "aggregate-estimate",
|
|
16649
|
-
retries: 0,
|
|
16650
|
-
replayed: event.replayed === true,
|
|
16651
|
-
open: true
|
|
16652
|
-
};
|
|
16653
|
-
row.phases.push(phase);
|
|
16654
|
-
openPhases.set(`${event.spanId}#${event.invocation}`, phase);
|
|
16655
|
-
break;
|
|
16656
|
-
}
|
|
16657
|
-
case "agent:phase:end": {
|
|
16658
|
-
const key = `${event.spanId}#${event.invocation}`;
|
|
16659
|
-
let phase = openPhases.get(key);
|
|
16660
|
-
if (phase === void 0) {
|
|
16661
|
-
phase = {
|
|
16662
|
-
invocation: event.invocation,
|
|
16663
|
-
role: event.role,
|
|
16664
|
-
model: event.model,
|
|
16665
|
-
durationMs: 0,
|
|
16666
|
-
usage: ZERO,
|
|
16667
|
-
costUsd: 0,
|
|
16668
|
-
costBasis: "aggregate-estimate",
|
|
16669
|
-
retries: 0,
|
|
16670
|
-
replayed: event.replayed === true,
|
|
16671
|
-
open: true
|
|
16672
|
-
};
|
|
16673
|
-
rowFor(event).phases.push(phase);
|
|
16674
|
-
}
|
|
16675
|
-
openPhases.delete(key);
|
|
16676
|
-
phase.open = false;
|
|
16677
|
-
phase.role = event.role;
|
|
16678
|
-
phase.model = event.model;
|
|
16679
|
-
phase.durationMs = event.durationMs;
|
|
16680
|
-
phase.usage = event.usage;
|
|
16681
|
-
phase.costUsd = event.costUsd;
|
|
16682
|
-
phase.costBasis = event.costBasis ?? "aggregate-estimate";
|
|
16683
|
-
phase.outcome = event.outcome;
|
|
16684
|
-
phase.retries = event.retries ?? 0;
|
|
16685
|
-
const bucket = byRole[event.role] ??= {
|
|
16686
|
-
usage: ZERO,
|
|
16687
|
-
costUsd: 0,
|
|
16688
|
-
costBasis: "per-call"
|
|
16689
|
-
};
|
|
16690
|
-
bucket.usage = sumUsage(bucket.usage, event.usage);
|
|
16691
|
-
bucket.costUsd += event.costUsd;
|
|
16692
|
-
if (phase.costBasis === "aggregate-estimate") bucket.costBasis = "aggregate-estimate";
|
|
16693
|
-
break;
|
|
16694
|
-
}
|
|
16695
|
-
case "agent:end": {
|
|
16696
|
-
const row = rowFor(event);
|
|
16697
|
-
row.open = false;
|
|
16698
|
-
row.status = event.status;
|
|
16699
|
-
row.usage = event.usage;
|
|
16700
|
-
row.costUsd = event.costUsd;
|
|
16701
|
-
row.costBasis = event.costBasis ?? "aggregate-estimate";
|
|
16702
|
-
row.usageApprox = event.usageApprox === true;
|
|
16703
|
-
row.retryCount = event.retryCount ?? 0;
|
|
16704
|
-
if (event.toolBudget !== void 0) row.toolBudget = event.toolBudget;
|
|
16705
|
-
totalCostUsd += event.costUsd;
|
|
16706
|
-
break;
|
|
16707
|
-
}
|
|
16708
|
-
default: break;
|
|
16858
|
+
projectedDispatchReserveUsd(spec) {
|
|
16859
|
+
return dispatchProjectionReserveUsd(spec, this.flatReserveUsd);
|
|
16709
16860
|
}
|
|
16710
|
-
|
|
16711
|
-
|
|
16712
|
-
|
|
16713
|
-
|
|
16714
|
-
|
|
16715
|
-
|
|
16716
|
-
|
|
16717
|
-
|
|
16718
|
-
|
|
16719
|
-
|
|
16720
|
-
|
|
16721
|
-
|
|
16722
|
-
|
|
16723
|
-
|
|
16724
|
-
|
|
16725
|
-
|
|
16726
|
-
|
|
16727
|
-
|
|
16728
|
-
|
|
16729
|
-
|
|
16730
|
-
|
|
16731
|
-
|
|
16732
|
-
|
|
16733
|
-
|
|
16734
|
-
|
|
16735
|
-
|
|
16736
|
-
|
|
16737
|
-
|
|
16738
|
-
|
|
16739
|
-
|
|
16740
|
-
|
|
16741
|
-
|
|
16742
|
-
|
|
16743
|
-
|
|
16744
|
-
|
|
16745
|
-
|
|
16746
|
-
|
|
16747
|
-
|
|
16748
|
-
|
|
16749
|
-
|
|
16750
|
-
|
|
16751
|
-
|
|
16752
|
-
|
|
16753
|
-
|
|
16754
|
-
|
|
16755
|
-
|
|
16756
|
-
|
|
16757
|
-
|
|
16758
|
-
|
|
16759
|
-
|
|
16760
|
-
|
|
16761
|
-
|
|
16762
|
-
|
|
16763
|
-
|
|
16764
|
-
|
|
16765
|
-
|
|
16766
|
-
|
|
16767
|
-
|
|
16768
|
-
|
|
16769
|
-
|
|
16770
|
-
|
|
16771
|
-
|
|
16772
|
-
|
|
16773
|
-
|
|
16774
|
-
|
|
16775
|
-
|
|
16776
|
-
|
|
16777
|
-
|
|
16778
|
-
|
|
16779
|
-
|
|
16780
|
-
|
|
16781
|
-
|
|
16782
|
-
|
|
16783
|
-
|
|
16784
|
-
|
|
16785
|
-
|
|
16786
|
-
if (started.role === "synthesize") {
|
|
16787
|
-
const wall = Math.max(0, at - started.at);
|
|
16788
|
-
const judge = started.label === CLAIM_JUDGE_LABEL;
|
|
16789
|
-
synthesisMs += wall;
|
|
16790
|
-
if (judge) semanticJudgeMs += wall;
|
|
16791
|
-
else finalCompositionMs += wall;
|
|
16792
|
-
synthesisSpans.push({
|
|
16793
|
-
from: started.at,
|
|
16794
|
-
to: at,
|
|
16795
|
-
judge
|
|
16796
|
-
});
|
|
16797
|
-
} else if (started.role !== "orchestrate") {
|
|
16798
|
-
workerSpans += 1;
|
|
16799
|
-
lastWorkerEnd = lastWorkerEnd === void 0 ? at : Math.max(lastWorkerEnd, at);
|
|
16800
|
-
}
|
|
16801
|
-
break;
|
|
16861
|
+
admit(spec, options) {
|
|
16862
|
+
const commitReserve = options?.commitReserve ?? true;
|
|
16863
|
+
const nodeKey = spec.nodeKey ?? spec.parentAccountScope;
|
|
16864
|
+
const depth = spawnDepthOf(spec.childScope);
|
|
16865
|
+
const childrenBefore = this.childrenOf.get(nodeKey) ?? 0;
|
|
16866
|
+
const evaluated = this.evaluateLineage(spec);
|
|
16867
|
+
const statsBefore = {
|
|
16868
|
+
spawnsBefore: this.budget.spent().agentsSpawned,
|
|
16869
|
+
childrenOfParentBefore: childrenBefore,
|
|
16870
|
+
depth,
|
|
16871
|
+
...evaluated.statsBefore === void 0 ? {} : { lineage: evaluated.statsBefore }
|
|
16872
|
+
};
|
|
16873
|
+
if (evaluated.decision.kind === "reject") return {
|
|
16874
|
+
verdict: {
|
|
16875
|
+
kind: "reject",
|
|
16876
|
+
reason: evaluated.decision.reason
|
|
16877
|
+
},
|
|
16878
|
+
statsBefore
|
|
16879
|
+
};
|
|
16880
|
+
if (this.terminationAccount !== void 0) {
|
|
16881
|
+
if ((spec.ladderLength ?? 1) > this.terminationAccount.limits.kMax) return {
|
|
16882
|
+
verdict: {
|
|
16883
|
+
kind: "reject",
|
|
16884
|
+
reason: { code: "ladder_exceeds_frozen" }
|
|
16885
|
+
},
|
|
16886
|
+
statsBefore
|
|
16887
|
+
};
|
|
16888
|
+
if (this.terminationAccount.spawnUnitsExhausted) return {
|
|
16889
|
+
verdict: {
|
|
16890
|
+
kind: "reject",
|
|
16891
|
+
reason: { code: "termination_exhausted" }
|
|
16892
|
+
},
|
|
16893
|
+
statsBefore
|
|
16894
|
+
};
|
|
16895
|
+
}
|
|
16896
|
+
if (depth > this.maxDepth) return {
|
|
16897
|
+
verdict: {
|
|
16898
|
+
kind: "reject",
|
|
16899
|
+
reason: { code: "depth" }
|
|
16900
|
+
},
|
|
16901
|
+
statsBefore
|
|
16902
|
+
};
|
|
16903
|
+
if (childrenBefore >= this.maxChildrenPerNode) return {
|
|
16904
|
+
verdict: {
|
|
16905
|
+
kind: "reject",
|
|
16906
|
+
reason: { code: "quota" }
|
|
16907
|
+
},
|
|
16908
|
+
statsBefore
|
|
16909
|
+
};
|
|
16910
|
+
if (this.maxTotalSpawns !== void 0 && this.admittedTotal >= this.maxTotalSpawns) return {
|
|
16911
|
+
verdict: {
|
|
16912
|
+
kind: "reject",
|
|
16913
|
+
reason: { code: "lifetime" }
|
|
16914
|
+
},
|
|
16915
|
+
statsBefore
|
|
16916
|
+
};
|
|
16917
|
+
if (spec.roster !== void 0) {
|
|
16918
|
+
const seatsRemaining = spec.roster.floor - spec.roster.admittedChildren;
|
|
16919
|
+
if (seatsRemaining > 0) {
|
|
16920
|
+
const perSeatProjectionUsd = this.projectedDispatchReserveUsd(spec);
|
|
16921
|
+
const remainder = this.budget.remainderOf(spec.parentAccountScope);
|
|
16922
|
+
if (remainder !== void 0 && remainder < seatsRemaining * perSeatProjectionUsd + spec.roster.liveExposureUsd) return {
|
|
16923
|
+
verdict: {
|
|
16924
|
+
kind: "reject",
|
|
16925
|
+
reason: {
|
|
16926
|
+
code: "roster_floor",
|
|
16927
|
+
floor: spec.roster.floor,
|
|
16928
|
+
admittedChildren: spec.roster.admittedChildren,
|
|
16929
|
+
seatsRemaining,
|
|
16930
|
+
perSeatProjectionUsd,
|
|
16931
|
+
liveExposureUsd: spec.roster.liveExposureUsd,
|
|
16932
|
+
remainderUsd: remainder
|
|
16933
|
+
}
|
|
16934
|
+
},
|
|
16935
|
+
statsBefore
|
|
16936
|
+
};
|
|
16802
16937
|
}
|
|
16803
|
-
default: break;
|
|
16804
16938
|
}
|
|
16805
|
-
|
|
16806
|
-
|
|
16807
|
-
|
|
16808
|
-
|
|
16809
|
-
|
|
16810
|
-
|
|
16811
|
-
|
|
16812
|
-
|
|
16813
|
-
|
|
16814
|
-
|
|
16815
|
-
const
|
|
16816
|
-
|
|
16817
|
-
|
|
16818
|
-
|
|
16939
|
+
const spawnToolOrigin = spec.origin === "spawn_agent" || spec.origin === "parallel_agents";
|
|
16940
|
+
let childCeilingUsd;
|
|
16941
|
+
const parentRemainder = this.budget.remainderOf(spec.parentAccountScope);
|
|
16942
|
+
if (spawnToolOrigin) {
|
|
16943
|
+
if (spec.budgetUsd !== void 0) childCeilingUsd = spec.budgetUsd;
|
|
16944
|
+
} else if (parentRemainder !== void 0) {
|
|
16945
|
+
const fractionCap = this.childBudgetFraction * parentRemainder;
|
|
16946
|
+
childCeilingUsd = spec.budgetUsd === void 0 ? fractionCap : Math.min(spec.budgetUsd, fractionCap);
|
|
16947
|
+
} else if (spec.budgetUsd !== void 0) childCeilingUsd = spec.budgetUsd;
|
|
16948
|
+
let reserveUsd = spec.estCostUsd ?? this.flatReserveUsd;
|
|
16949
|
+
const source = spec.estCostUsd === void 0 ? "default" : "estCost";
|
|
16950
|
+
let clampedBy;
|
|
16951
|
+
if (childCeilingUsd !== void 0 && reserveUsd > childCeilingUsd) {
|
|
16952
|
+
clampedBy = spec.budgetUsd !== void 0 && childCeilingUsd === spec.budgetUsd ? "explicit-budget" : "fraction-ceiling";
|
|
16953
|
+
reserveUsd = childCeilingUsd;
|
|
16954
|
+
}
|
|
16955
|
+
const reserve = {
|
|
16956
|
+
reserveUsd,
|
|
16957
|
+
source
|
|
16958
|
+
};
|
|
16959
|
+
if (clampedBy !== void 0) reserve.clampedBy = clampedBy;
|
|
16960
|
+
if (childCeilingUsd !== void 0) reserve.childCeilingUsd = childCeilingUsd;
|
|
16961
|
+
if (this.budget.spawnHeadroom <= 0) return {
|
|
16962
|
+
verdict: {
|
|
16963
|
+
kind: "reject",
|
|
16964
|
+
reason: { code: "lifetime" }
|
|
16965
|
+
},
|
|
16966
|
+
statsBefore
|
|
16967
|
+
};
|
|
16968
|
+
if (commitReserve) try {
|
|
16969
|
+
this.budget.admitSpawn(reserveUsd, spec.parentAccountScope);
|
|
16970
|
+
} catch {
|
|
16819
16971
|
return {
|
|
16820
|
-
|
|
16821
|
-
|
|
16972
|
+
verdict: {
|
|
16973
|
+
kind: "reject",
|
|
16974
|
+
reason: { code: "budget" }
|
|
16975
|
+
},
|
|
16976
|
+
statsBefore
|
|
16822
16977
|
};
|
|
16823
|
-
};
|
|
16824
|
-
const byPhase = {};
|
|
16825
|
-
const modelClipped = [];
|
|
16826
|
-
for (const interval of coordinationModel) {
|
|
16827
|
-
const clipped = clip(interval);
|
|
16828
|
-
if (clipped === void 0) continue;
|
|
16829
|
-
byPhase[interval.phase] = (byPhase[interval.phase] ?? 0) + (clipped.to - clipped.from);
|
|
16830
|
-
modelClipped.push(clipped);
|
|
16831
16978
|
}
|
|
16832
|
-
|
|
16833
|
-
|
|
16834
|
-
|
|
16835
|
-
|
|
16836
|
-
|
|
16837
|
-
|
|
16838
|
-
|
|
16839
|
-
|
|
16840
|
-
|
|
16979
|
+
else {
|
|
16980
|
+
const remainder = this.budget.remainderOf(spec.parentAccountScope);
|
|
16981
|
+
const projection = this.projectedDispatchReserveUsd(spec);
|
|
16982
|
+
if (remainder !== void 0 && (remainder <= 0 || remainder < projection + (spec.pendingReserveUsd ?? 0))) return {
|
|
16983
|
+
verdict: {
|
|
16984
|
+
kind: "reject",
|
|
16985
|
+
reason: { code: "budget" }
|
|
16986
|
+
},
|
|
16987
|
+
statsBefore
|
|
16988
|
+
};
|
|
16841
16989
|
}
|
|
16842
|
-
|
|
16843
|
-
|
|
16844
|
-
const
|
|
16845
|
-
|
|
16846
|
-
|
|
16847
|
-
|
|
16848
|
-
|
|
16849
|
-
|
|
16850
|
-
|
|
16990
|
+
this.childrenOf.set(nodeKey, childrenBefore + 1);
|
|
16991
|
+
this.admittedTotal += 1;
|
|
16992
|
+
const lineage = evaluated.decision.lineage;
|
|
16993
|
+
this.registerLineageAdmit(lineage.logicalTaskId);
|
|
16994
|
+
let spawnUnitsAfter = this.budget.spawnHeadroom;
|
|
16995
|
+
if (this.terminationAccount !== void 0) {
|
|
16996
|
+
const debited = this.terminationAccount.debitSpawn({
|
|
16997
|
+
logicalTaskId: lineage.logicalTaskId,
|
|
16998
|
+
isNew: spec.lineage === void 0,
|
|
16999
|
+
ladderLength: spec.ladderLength ?? 1
|
|
17000
|
+
});
|
|
17001
|
+
if (!debited.ok) return {
|
|
17002
|
+
verdict: {
|
|
17003
|
+
kind: "reject",
|
|
17004
|
+
reason: { code: "termination_exhausted" }
|
|
17005
|
+
},
|
|
17006
|
+
statsBefore
|
|
17007
|
+
};
|
|
17008
|
+
spawnUnitsAfter = debited.spawnUnitsAfter;
|
|
16851
17009
|
}
|
|
16852
|
-
|
|
16853
|
-
|
|
16854
|
-
|
|
16855
|
-
|
|
16856
|
-
|
|
16857
|
-
|
|
16858
|
-
|
|
16859
|
-
|
|
16860
|
-
|
|
16861
|
-
|
|
16862
|
-
|
|
16863
|
-
|
|
16864
|
-
|
|
16865
|
-
|
|
16866
|
-
|
|
16867
|
-
finalCompositionMs: compositionClippedMs,
|
|
16868
|
-
semanticJudgeMs: judgeClippedMs,
|
|
16869
|
-
coveredMs,
|
|
16870
|
-
residueMs: Math.max(0, path.postFanInMs - coveredMs)
|
|
17010
|
+
return {
|
|
17011
|
+
verdict: {
|
|
17012
|
+
kind: "admit",
|
|
17013
|
+
reserve,
|
|
17014
|
+
spawnUnitsAfter,
|
|
17015
|
+
lineage: {
|
|
17016
|
+
logicalTaskId: lineage.logicalTaskId,
|
|
17017
|
+
isNew: spec.lineage === void 0,
|
|
17018
|
+
depth
|
|
17019
|
+
}
|
|
17020
|
+
},
|
|
17021
|
+
statsBefore,
|
|
17022
|
+
nodeId: this.mintId(),
|
|
17023
|
+
lineage,
|
|
17024
|
+
...this.terminationAccount === void 0 ? {} : { ladderLength: spec.ladderLength ?? 1 }
|
|
16871
17025
|
};
|
|
16872
|
-
if (path.postFanInMs > 0) breakdown.residueShare = breakdown.residueMs / path.postFanInMs;
|
|
16873
|
-
path.postFanIn = breakdown;
|
|
16874
17026
|
}
|
|
16875
|
-
|
|
16876
|
-
|
|
16877
|
-
|
|
17027
|
+
/**
|
|
17028
|
+
* Resume roll-forward for an orchestrator child (M6-T07): restores the
|
|
17029
|
+
* children-quota counter only. The budget seed already counts settled
|
|
17030
|
+
* agent dispatches, and an in-flight child re-commits its reserve
|
|
17031
|
+
* through the ctx.agent dispatch path.
|
|
17032
|
+
*/
|
|
17033
|
+
recoverChild(nodeKey) {
|
|
17034
|
+
this.childrenOf.set(nodeKey, (this.childrenOf.get(nodeKey) ?? 0) + 1);
|
|
17035
|
+
this.admittedTotal += 1;
|
|
16878
17036
|
}
|
|
16879
|
-
|
|
16880
|
-
|
|
17037
|
+
/**
|
|
17038
|
+
* Resume roll-forward for a child that already SETTLED before the
|
|
17039
|
+
* resume: re-registers the counters (maxChildrenPerNode, the lifetime
|
|
17040
|
+
* cap, statsBefore fidelity) without committing any reserve; the spend
|
|
17041
|
+
* itself sits in the root ledger seed.
|
|
17042
|
+
*/
|
|
17043
|
+
recoverSettled(parentAccountScope) {
|
|
17044
|
+
this.budget.admitRecovered(0, parentAccountScope);
|
|
17045
|
+
this.childrenOf.set(parentAccountScope, (this.childrenOf.get(parentAccountScope) ?? 0) + 1);
|
|
17046
|
+
this.admittedTotal += 1;
|
|
17047
|
+
}
|
|
17048
|
+
/**
|
|
17049
|
+
* Resume roll-forward for an admission whose decision entry exists but
|
|
17050
|
+
* whose child has NOT settled: re-applies the recorded reserve and
|
|
17051
|
+
* counters without re-evaluating any limit (replay never
|
|
17052
|
+
* re-evaluates admission; reserves are recovered, never
|
|
17053
|
+
* re-estimated).
|
|
17054
|
+
*/
|
|
17055
|
+
recoverInFlight(parentAccountScope, verdict) {
|
|
17056
|
+
if (verdict.kind === "reject") return;
|
|
17057
|
+
const reserveUsd = verdict.kind === "reuse_full" ? 0 : verdict.reserve.reserveUsd;
|
|
17058
|
+
this.budget.admitRecovered(reserveUsd, parentAccountScope);
|
|
17059
|
+
this.childrenOf.set(parentAccountScope, (this.childrenOf.get(parentAccountScope) ?? 0) + 1);
|
|
17060
|
+
this.admittedTotal += 1;
|
|
17061
|
+
}
|
|
17062
|
+
};
|
|
16881
17063
|
//#endregion
|
|
16882
17064
|
//#region src/model/profile-card.ts
|
|
16883
17065
|
function toolNamesOf(profile) {
|
|
@@ -18620,6 +18802,7 @@ function createCtx(internals, rootWorkflow) {
|
|
|
18620
18802
|
agentType,
|
|
18621
18803
|
role: primaryRole,
|
|
18622
18804
|
budgetAccount: state.budgetScope ?? "run",
|
|
18805
|
+
...opts.label === void 0 ? {} : { label: opts.label },
|
|
18623
18806
|
...opts[kFinalizeReserve] === true ? { finalizeReserve: true } : {}
|
|
18624
18807
|
},
|
|
18625
18808
|
transcriptRef: result.transcriptRef
|
|
@@ -28228,4 +28411,4 @@ function createSandboxBridge(ctx, options) {
|
|
|
28228
28411
|
};
|
|
28229
28412
|
}
|
|
28230
28413
|
//#endregion
|
|
28231
|
-
export { AWAIT_SCHEMA, AdmissionController, AdmissionRejectedError, AgentCallError, BUDGET_ABORT_REASON, BudgetExhaustedError, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_JUDGE_LABEL, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, ConfigError, DECISION_CHAIN_KINDS, DEFAULT_ANCHOR_PATTERN, DEFAULT_ARTIFACT_PATTERN, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_CHILD_RESULT_PAGE_CHARS, DEFAULT_CITATION_PATTERN, DEFAULT_CITATION_SAMPLE, DEFAULT_CLAIM_JUDGE_MAX_TURNS, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, DEFAULT_EVIDENCE_CALLS_PER_ENTRY, DEFAULT_EVIDENCE_GRADE_PHRASES, DEFAULT_EVIDENCE_MIN_SHARE, DEFAULT_EVIDENCE_OVERHEAD_CALLS, DEFAULT_FINISH_MAX_REPAIRS, DEFAULT_FLAT_RESERVE_USD, DEFAULT_MAX_CHILDREN_PER_NODE, DEFAULT_MAX_CLAIM_PAIRS, DEFAULT_MAX_CONTRADICTIONS, DEFAULT_MAX_DEPTH, DEFAULT_MAX_EXCERPT_CHARS, DEFAULT_MAX_OSCILLATIONS_PER_KEY, DEFAULT_MAX_PAIR_EXCERPT_CHARS, DEFAULT_MAX_PINNED_WORKTREES, DEFAULT_MAX_POOL_PER_PAIR, DEFAULT_MAX_QUOTA_DENIALS, DEFAULT_MAX_REVISIONS_PER_RUN, DEFAULT_MAX_RUN_FACT_PAIRS, DEFAULT_MAX_TOTAL_SPAWNS, DEFAULT_MAX_TURNS, DEFAULT_MODEL_RETRY_ATTEMPTS, DEFAULT_NO_PROGRESS_TURNS, DEFAULT_PER_RUN_CONCURRENCY, DEFAULT_RETRY_POLICY, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DEFAULT_SYNTHESIS_MAX_TURNS, DEFAULT_SYNTHESIS_NOTE_MAX_TURNS, DedupIndex, DeterminismError, EMIT_RESULT_TOOL, EMPTY_AUTHORITY_HASH, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EVENT_SEGMENT_STRIDE, EXPOSURE_WAIT_SWEEP_MS, EscalationDecisionAbortedError, EventBus, ExternalRegistry, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_SECTIONAL_SCHEMA, FINISH_TOOL_NAME, FUTURE_RATES_TOLERANCE_MS, FailRunError, FileModelKnowledgeStore, FileTranscriptStore, GET_CHILD_RESULT_SCHEMA, GET_CHILD_RESULT_TOOL_NAME, GET_SETTLED_CHILD_RESULTS_SCHEMA, GET_SETTLED_CHILD_RESULTS_TOOL_NAME, GitWorktreeProvider, IMPLEMENTATION_PROFILE_LIMITS, INBOX_PROPOSAL_TTL_DAYS, IN_FLIGHT_EXPOSURE_REFUSAL_PREFIX, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, InvalidResolutionError, JOURNAL_ENVELOPE_MARKER, JournalCompatibilityError, JournalMatcher, JournalMissError, JournalOrderViolation, JournalSealedError, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, KeyedLimiter, KnowledgeCasError, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LeaseHeldError, LineageIndex, MASKED_SECRET, MAX_CHILD_RESULT_PAGE_CHARS, MAX_CRITICAL_UNCOVERED, MAX_DEPTH_CEILING, MAX_RUN_FACTS_SHEET_CHARS, MAX_RUN_ID_LENGTH, MAX_TIMER_DELAY_MS, ModelRetry, NoProgressDetector, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OrchestratorCapConfigError, PARALLEL_AGENTS_SCHEMA, PROGRESS_REPORT_TOOL_NAME, ParallelSiteCounter, PlanInvariantError, QUOTA_WINDOW_MS, READ_CHILD_ARTIFACT_SCHEMA, READ_CHILD_ARTIFACT_TOOL_NAME, RESEARCH_PROFILE_LIMITS, REVIEW_PROFILE_LIMITS, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_FACTS_ANCHOR, RUN_PROFILES, RUN_SETTLE_DECISION_TYPE, ReplayPlanHashMismatch, Replayer, ResolutionArbiter, ResolutionFold, RulvarError, RunBudget, SANDBOX_AGENT_OPT_KEYS, SPAWN_AGENT_SCHEMA, SandboxError, ScriptRejected, Semaphore, SettlementError, SpanRegistry, SupersededError, TERMINAL_TELEMETRY_SCOPE, TOOL_NAME_PATTERN, TerminationAccount, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, accountSpendFromJournal, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentResultWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, assertFencedWrites, assertSafeRunId, atCompactionThreshold, attestToolset, auditRun, auditRuns, buildAbandonFold, buildAdapterRegistry, buildCostReport, buildDeriverRegistry, buildOrchestratorTools, buildTerminationInitValue, buildToolContext, canRideLoopTurn, canonicalIsolationTag, canonicalizeLadder, canonicalizeSchema, capIssues, capsHashOf, checkFloors, checkpointRefFor, childCoveragePrefix, citationTargetsValidator, citedValueValidator, claimCoverageOf, claimExpired, claimExpiry, claimIssues, claimOpIssues, classifyAgentError, classifyAttemptOutcome, collectDeclaredLadders, compactMessages, compareRates, compilePermissionChain, compilePermissionPreset, compileSecretMasker, compileVerifiedLayer, constantTimeEqual, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createEnvelopeEncryption, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, dedupeRepeatedClaims, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispatchProjectionReserveUsd, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, enforceToolsetAttestation, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, evidenceGradeValidator, evidencePreservedValidator, executeWorkflow, executionFactsOf, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, findContradictions, finishContract, foldLedger, foldTermination, formatCharacterValidator, formatRePrompt, formatScopePath, hasFencedWrites, hasMetaLookup, hashRunArgs, hashRunOutput, hashWorkflowBody, hashWorkflowSource, headingStructureValidator, identityJcs, implementationAgentProfile, invoiceFromJournal, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, journalPricingSnapshot, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lastRunSettle, latestProgressReport, lexShellCommand, liftRetainedParts, lineageWeightOf, localKeyProvider, logicalRunTelemetry, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, memoryQuotaLimiter, mergeQuotaDenial, mergeUsageLimits, metaMatchesFilter, minMatchesValidator, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, orchestratorAdmissionEstCostUsd, pairDraftClaims, pairRunFactClaims, parallelScope, parseModelRef, parseScopePath, persistedTerminalEnvelope, phiInitialOf, pilotAgentProfile, pipelineScope, planNodeScope, preflightEstimate, priceComponentsOf, priceEntryBilling, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, progressReportTool, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, quotaActualRequestsDelta, quotaActualTokens, quotaEstimateTokens, quotaRuleAdmission, quotaRuleKey, quotaRuleMatches, readRunMeta, readTerminationInit, reconcileRunMeta, reconcileStatement, reduceAuditTrail, reduceCriticalPath, reduceDecisionChain, reduceInvocationTable, registryKeyRing, remeasureQueue, replayDisposition, repositoryResearchToolset, requiredFieldsValidator, requiredSectionsValidator, researchAgentProfile, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, reviewAgentProfile, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, sanitizeTerminalText, sanitizeTokenCount, sanitizeUsage, sanitizeUsageDelta, scanJournalCompatibility, schemaHash, schemaHashOfSpec, sectionCitationsValidator, sectionPatternCountValidator, selectStructuredOutputTier, selfTestFinishValidation, shouldCompact, snapshotQuotaRules, snapshotUsage, spawnDepthOf, spliceSections, statementFromRows, stripFencedBlocks, sumUsage, summarizeInstruction, summarizeOutput, terminalEnvelopeOf, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolAuthority, toolContract, toolContractHash, toolsetAuthorityHash, toolsetHash, ttlState, usageViolations, validateDetachedResolution, validateEditorialCommit, validateEngineQuotaConfig, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateQuotaRules, validateRetryPolicy, validateSchemaSpec, validateTerminationLimits, validateToolsetAttestation, validateUsageLimits, wordCountValidator, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
|
|
28414
|
+
export { AWAIT_SCHEMA, AdmissionController, AdmissionRejectedError, AgentCallError, BUDGET_ABORT_REASON, BudgetExhaustedError, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_JUDGE_LABEL, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, ConfigError, DECISION_CHAIN_KINDS, DEFAULT_ANCHOR_PATTERN, DEFAULT_ARTIFACT_PATTERN, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_CHILD_RESULT_PAGE_CHARS, DEFAULT_CITATION_PATTERN, DEFAULT_CITATION_SAMPLE, DEFAULT_CLAIM_JUDGE_MAX_TURNS, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, DEFAULT_EVIDENCE_CALLS_PER_ENTRY, DEFAULT_EVIDENCE_GRADE_PHRASES, DEFAULT_EVIDENCE_MIN_SHARE, DEFAULT_EVIDENCE_OVERHEAD_CALLS, DEFAULT_FINISH_MAX_REPAIRS, DEFAULT_FLAT_RESERVE_USD, DEFAULT_MAX_CHILDREN_PER_NODE, DEFAULT_MAX_CLAIM_PAIRS, DEFAULT_MAX_CONTRADICTIONS, DEFAULT_MAX_DEPTH, DEFAULT_MAX_EXCERPT_CHARS, DEFAULT_MAX_OSCILLATIONS_PER_KEY, DEFAULT_MAX_PAIR_EXCERPT_CHARS, DEFAULT_MAX_PINNED_WORKTREES, DEFAULT_MAX_POOL_PER_PAIR, DEFAULT_MAX_QUOTA_DENIALS, DEFAULT_MAX_REVISIONS_PER_RUN, DEFAULT_MAX_RUN_FACT_PAIRS, DEFAULT_MAX_TOTAL_SPAWNS, DEFAULT_MAX_TURNS, DEFAULT_MODEL_RETRY_ATTEMPTS, DEFAULT_NO_PROGRESS_TURNS, DEFAULT_PER_RUN_CONCURRENCY, DEFAULT_RETRY_POLICY, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DEFAULT_SYNTHESIS_MAX_TURNS, DEFAULT_SYNTHESIS_NOTE_MAX_TURNS, DedupIndex, DeterminismError, EMIT_RESULT_TOOL, EMPTY_AUTHORITY_HASH, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EVENT_SEGMENT_STRIDE, EXPOSURE_WAIT_SWEEP_MS, EscalationDecisionAbortedError, EventBus, ExternalRegistry, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_SECTIONAL_SCHEMA, FINISH_TOOL_NAME, FUTURE_RATES_TOLERANCE_MS, FailRunError, FileModelKnowledgeStore, FileTranscriptStore, GET_CHILD_RESULT_SCHEMA, GET_CHILD_RESULT_TOOL_NAME, GET_SETTLED_CHILD_RESULTS_SCHEMA, GET_SETTLED_CHILD_RESULTS_TOOL_NAME, GitWorktreeProvider, IMPLEMENTATION_PROFILE_LIMITS, INBOX_PROPOSAL_TTL_DAYS, IN_FLIGHT_EXPOSURE_REFUSAL_PREFIX, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, InvalidResolutionError, JOURNAL_ENVELOPE_MARKER, JournalCompatibilityError, JournalMatcher, JournalMissError, JournalOrderViolation, JournalSealedError, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, KeyedLimiter, KnowledgeCasError, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LeaseHeldError, LineageIndex, MASKED_SECRET, MAX_CHILD_RESULT_PAGE_CHARS, MAX_CRITICAL_UNCOVERED, MAX_DEPTH_CEILING, MAX_RUN_FACTS_SHEET_CHARS, MAX_RUN_ID_LENGTH, MAX_TIMER_DELAY_MS, ModelRetry, NoProgressDetector, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OrchestratorCapConfigError, PARALLEL_AGENTS_SCHEMA, PROGRESS_REPORT_TOOL_NAME, ParallelSiteCounter, PlanInvariantError, QUOTA_WINDOW_MS, READ_CHILD_ARTIFACT_SCHEMA, READ_CHILD_ARTIFACT_TOOL_NAME, RESEARCH_PROFILE_LIMITS, REVIEW_PROFILE_LIMITS, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_FACTS_ANCHOR, RUN_PROFILES, RUN_SETTLE_DECISION_TYPE, ReplayPlanHashMismatch, Replayer, ResolutionArbiter, ResolutionFold, RulvarError, RunBudget, SANDBOX_AGENT_OPT_KEYS, SPAWN_ADMISSION_DECISION_TYPE, SPAWN_AGENT_SCHEMA, SandboxError, ScriptRejected, Semaphore, SettlementError, SpanRegistry, SupersededError, TERMINAL_TELEMETRY_SCOPE, TOOL_NAME_PATTERN, TerminationAccount, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, accountSpendFromJournal, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentResultWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, assertFencedWrites, assertSafeRunId, atCompactionThreshold, attestToolset, auditRun, auditRuns, buildAbandonFold, buildAdapterRegistry, buildCostReport, buildDeriverRegistry, buildOrchestratorTools, buildTerminationInitValue, buildToolContext, canRideLoopTurn, canonicalIsolationTag, canonicalizeLadder, canonicalizeSchema, capIssues, capsHashOf, checkFloors, checkpointRefFor, childCoveragePrefix, childRostersFromJournal, citationTargetsValidator, citedValueValidator, claimCoverageOf, claimExpired, claimExpiry, claimIssues, claimOpIssues, classifyAgentError, classifyAttemptOutcome, collectDeclaredLadders, compactMessages, compareRates, compilePermissionChain, compilePermissionPreset, compileSecretMasker, compileVerifiedLayer, constantTimeEqual, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createEnvelopeEncryption, createSandboxBridge, criticalPathFromJournal, currentOnlyKeyRing, decodeCheckpoint, dedupeRepeatedClaims, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispatchProjectionReserveUsd, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, enforceToolsetAttestation, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, evidenceGradeValidator, evidencePreservedValidator, executeWorkflow, executionFactsOf, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, findContradictions, finishContract, foldLedger, foldTermination, formatCharacterValidator, formatRePrompt, formatScopePath, hasFencedWrites, hasMetaLookup, hashRunArgs, hashRunOutput, hashWorkflowBody, hashWorkflowSource, headingStructureValidator, identityJcs, implementationAgentProfile, invoiceFromJournal, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, journalPricingSnapshot, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lastRunSettle, latestProgressReport, lexShellCommand, liftRetainedParts, lineageWeightOf, localKeyProvider, logicalRunTelemetry, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, memoryQuotaLimiter, mergeQuotaDenial, mergeUsageLimits, metaMatchesFilter, minMatchesValidator, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, orchestratorAdmissionEstCostUsd, pairDraftClaims, pairRunFactClaims, parallelScope, parseModelRef, parseScopePath, persistedTerminalEnvelope, phiInitialOf, pilotAgentProfile, pipelineScope, planNodeScope, preflightEstimate, priceComponentsOf, priceEntryBilling, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, progressReportTool, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, quotaActualRequestsDelta, quotaActualTokens, quotaEstimateTokens, quotaRuleAdmission, quotaRuleKey, quotaRuleMatches, readRunMeta, readTerminationInit, reconcileRunMeta, reconcileStatement, reduceAuditTrail, reduceCriticalPath, reduceDecisionChain, reduceInvocationTable, registryKeyRing, remeasureQueue, replayDisposition, repositoryResearchToolset, requiredFieldsValidator, requiredSectionsValidator, researchAgentProfile, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, reviewAgentProfile, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, sanitizeTerminalText, sanitizeTokenCount, sanitizeUsage, sanitizeUsageDelta, scanJournalCompatibility, schemaHash, schemaHashOfSpec, sectionCitationsValidator, sectionPatternCountValidator, selectStructuredOutputTier, selfTestFinishValidation, shouldCompact, snapshotQuotaRules, snapshotUsage, spawnDepthOf, spliceSections, statementFromRows, stripFencedBlocks, sumUsage, summarizeInstruction, summarizeOutput, terminalEnvelopeOf, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolAuthority, toolContract, toolContractHash, toolsetAuthorityHash, toolsetHash, ttlState, usageViolations, validateDetachedResolution, validateEditorialCommit, validateEngineQuotaConfig, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateQuotaRules, validateRetryPolicy, validateSchemaSpec, validateTerminationLimits, validateToolsetAttestation, validateUsageLimits, wordCountValidator, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
|