@rulvar/core 1.210.0 → 1.212.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 +37 -10
- package/dist/index.js +49 -13
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -382,13 +382,18 @@ type AgentError = {
|
|
|
382
382
|
retryAfterMs?: number;
|
|
383
383
|
issues?: Issue$1[];
|
|
384
384
|
/**
|
|
385
|
-
* The typed refusal marker (RV2002
|
|
386
|
-
* spawned child refused pre-wire by the
|
|
387
|
-
* no live holder left to wait out
|
|
388
|
-
* construction, so the seat is cheap to
|
|
389
|
-
* treats it as a starved seat, never a
|
|
390
|
-
|
|
391
|
-
|
|
385
|
+
* The typed refusal marker (RV2002, widened by RV2101):
|
|
386
|
+
* 'exposure-drained' names a spawned child refused pre-wire by the
|
|
387
|
+
* in-flight exposure cap with no live holder left to wait out (zero
|
|
388
|
+
* provider attempts by construction, so the seat is cheap to
|
|
389
|
+
* re-spawn; an orchestrator treats it as a starved seat, never a
|
|
390
|
+
* crashed child). 'output-floor' names a turn refused pre-wire
|
|
391
|
+
* because the remaining budget past the held reserves cannot afford
|
|
392
|
+
* the model's output floor: at the reserve line this is the
|
|
393
|
+
* boundary where the coordination loop settles partial and the
|
|
394
|
+
* synthesis promise is redeemed, never a crash.
|
|
395
|
+
*/
|
|
396
|
+
reason?: "exposure-drained" | "output-floor";
|
|
392
397
|
};
|
|
393
398
|
/**
|
|
394
399
|
* Projects an AgentError to its WireError form: code 'agent', with kind,
|
|
@@ -6513,10 +6518,17 @@ declare class RunBudget {
|
|
|
6513
6518
|
* price rows as the layer-2b clamp) right before the wire call and
|
|
6514
6519
|
* releases at the attempt's settle, so the reservation lives exactly
|
|
6515
6520
|
* as long as the exposure it covers. The admission refuses, typed
|
|
6516
|
-
* and without waiting, when spent +
|
|
6517
|
-
* synthesis money is promised elsewhere) + live reservations + this
|
|
6521
|
+
* and without waiting, when spent + live reservations + this
|
|
6518
6522
|
* estimate does not fit the cap; an exact fill admits, mirroring
|
|
6519
|
-
* admitSpawn, and a full cap refuses even a zero estimate.
|
|
6523
|
+
* admitSpawn, and a full cap refuses even a zero estimate. The tail
|
|
6524
|
+
* reserves (finalize and synthesis) stay OUT of the sum (RV2101):
|
|
6525
|
+
* the budget chain already fences them (remainingUsd subtracts the
|
|
6526
|
+
* synthesis promise, and the finalize carve-out nets out of the
|
|
6527
|
+
* orchestrator's own cap), so counting them here too made the cap
|
|
6528
|
+
* bind at cap minus reserves while the actual wire risk was far
|
|
6529
|
+
* below it: the fourth parity run's root was refused at spent
|
|
6530
|
+
* 4.71 + reserve 1.00 against 5.70 with zero live estimates, one
|
|
6531
|
+
* turn short of the synthesis the reserve existed to fund. A refusal
|
|
6520
6532
|
* is TRANSIENT (in-flight money returns at settle), so it never
|
|
6521
6533
|
* marks the run exhausted and never severs a stream. A model without
|
|
6522
6534
|
* a price row reserves zero, exactly as it debits zero (the
|
|
@@ -13290,6 +13302,21 @@ interface PreflightReport {
|
|
|
13290
13302
|
* coordination turn prices.
|
|
13291
13303
|
*/
|
|
13292
13304
|
liveRootExposureTermUsd?: number;
|
|
13305
|
+
/**
|
|
13306
|
+
* The reserve line (RV2101): the run ceiling minus the synthesis
|
|
13307
|
+
* reserve, the boundary the budget chain fences every non-tail
|
|
13308
|
+
* dispatch at while the promise is held. Present when a ceiling
|
|
13309
|
+
* and a positive synthesis reserve are both declared.
|
|
13310
|
+
*/
|
|
13311
|
+
reserveLineUsd?: number;
|
|
13312
|
+
/**
|
|
13313
|
+
* How far the admitted wave's steady state sits under the reserve
|
|
13314
|
+
* line (RV2101). Child spend past the declared estimates consumes
|
|
13315
|
+
* this headroom before the coordination loop is refused at the
|
|
13316
|
+
* line; under two coordination turn floors the projection warns
|
|
13317
|
+
* with `reserve-line-headroom`. Present beside reserveLineUsd.
|
|
13318
|
+
*/
|
|
13319
|
+
reserveLineHeadroomUsd?: number;
|
|
13293
13320
|
wave: PreflightAdmissionRow[];
|
|
13294
13321
|
admitted: number;
|
|
13295
13322
|
denied: number;
|
package/dist/index.js
CHANGED
|
@@ -10931,7 +10931,7 @@ function applyOutputBudget(req, target, budget) {
|
|
|
10931
10931
|
if (affordable === void 0) return req;
|
|
10932
10932
|
if (affordable < floor) {
|
|
10933
10933
|
const zeroInputAffordable = hook(target.resolved.ref, 0);
|
|
10934
|
-
if (zeroInputAffordable !== void 0 && zeroInputAffordable < floor) throw new BudgetExhaustedError(floor === 1 ? `the remaining budget cannot afford one output token from ${target.resolved.ref}; the turn was not dispatched` : `the remaining budget cannot afford the ${String(floor)} token output floor of ${target.resolved.ref}; the turn was not dispatched
|
|
10934
|
+
if (zeroInputAffordable !== void 0 && zeroInputAffordable < floor) throw new BudgetExhaustedError(floor === 1 ? `the remaining budget cannot afford one output token from ${target.resolved.ref}; the turn was not dispatched` : `the remaining budget cannot afford the ${String(floor)} token output floor of ${target.resolved.ref}; the turn was not dispatched`, { data: { reason: "output-floor" } });
|
|
10935
10935
|
return {
|
|
10936
10936
|
...req,
|
|
10937
10937
|
maxOutputTokens: floor
|
|
@@ -12657,10 +12657,11 @@ async function runAgent(options) {
|
|
|
12657
12657
|
} catch (thrown) {
|
|
12658
12658
|
if (!(thrown instanceof BudgetExhaustedError)) throw thrown;
|
|
12659
12659
|
status = "error";
|
|
12660
|
+
const typedReason = thrown.data?.reason;
|
|
12660
12661
|
agentError = {
|
|
12661
12662
|
kind: "budget",
|
|
12662
12663
|
retryable: false,
|
|
12663
|
-
...
|
|
12664
|
+
...typedReason === "exposure-drained" || typedReason === "output-floor" ? { reason: typedReason } : {}
|
|
12664
12665
|
};
|
|
12665
12666
|
errorMessage = thrown.message;
|
|
12666
12667
|
break;
|
|
@@ -14001,10 +14002,17 @@ var RunBudget = class {
|
|
|
14001
14002
|
* price rows as the layer-2b clamp) right before the wire call and
|
|
14002
14003
|
* releases at the attempt's settle, so the reservation lives exactly
|
|
14003
14004
|
* as long as the exposure it covers. The admission refuses, typed
|
|
14004
|
-
* and without waiting, when spent +
|
|
14005
|
-
* synthesis money is promised elsewhere) + live reservations + this
|
|
14005
|
+
* and without waiting, when spent + live reservations + this
|
|
14006
14006
|
* estimate does not fit the cap; an exact fill admits, mirroring
|
|
14007
|
-
* admitSpawn, and a full cap refuses even a zero estimate.
|
|
14007
|
+
* admitSpawn, and a full cap refuses even a zero estimate. The tail
|
|
14008
|
+
* reserves (finalize and synthesis) stay OUT of the sum (RV2101):
|
|
14009
|
+
* the budget chain already fences them (remainingUsd subtracts the
|
|
14010
|
+
* synthesis promise, and the finalize carve-out nets out of the
|
|
14011
|
+
* orchestrator's own cap), so counting them here too made the cap
|
|
14012
|
+
* bind at cap minus reserves while the actual wire risk was far
|
|
14013
|
+
* below it: the fourth parity run's root was refused at spent
|
|
14014
|
+
* 4.71 + reserve 1.00 against 5.70 with zero live estimates, one
|
|
14015
|
+
* turn short of the synthesis the reserve existed to fund. A refusal
|
|
14008
14016
|
* is TRANSIENT (in-flight money returns at settle), so it never
|
|
14009
14017
|
* marks the run exhausted and never severs a stream. A model without
|
|
14010
14018
|
* a price row reserves zero, exactly as it debits zero (the
|
|
@@ -14028,8 +14036,8 @@ var RunBudget = class {
|
|
|
14028
14036
|
});
|
|
14029
14037
|
const estimateUsd = Number.isFinite(rawEstimate) && rawEstimate > 0 ? rawEstimate : 0;
|
|
14030
14038
|
const root = this.root;
|
|
14031
|
-
const committed = root.spentUsd +
|
|
14032
|
-
if (committed >= cap || committed + estimateUsd > cap) throw new BudgetExhaustedError(`${IN_FLIGHT_EXPOSURE_REFUSAL_PREFIX}: spent ${root.spentUsd.toFixed(4)} USD plus
|
|
14039
|
+
const committed = root.spentUsd + this.inFlightExposureUsd;
|
|
14040
|
+
if (committed >= cap || committed + estimateUsd > cap) throw new BudgetExhaustedError(`${IN_FLIGHT_EXPOSURE_REFUSAL_PREFIX}: spent ${root.spentUsd.toFixed(4)} USD plus live dispatch estimates ${this.inFlightExposureUsd.toFixed(4)} USD plus this turn's estimate ${estimateUsd.toFixed(4)} USD does not fit maxInFlightExposureUsd ${cap.toFixed(4)} USD; the dispatch was refused before any provider call`, { data: {
|
|
14033
14041
|
reason: "in-flight-exposure",
|
|
14034
14042
|
capUsd: cap,
|
|
14035
14043
|
spentUsd: root.spentUsd,
|
|
@@ -18396,6 +18404,12 @@ function createCtx(internals, rootWorkflow) {
|
|
|
18396
18404
|
source: "in-flight-exposure",
|
|
18397
18405
|
reason: "in-flight-exposure"
|
|
18398
18406
|
} });
|
|
18407
|
+
if (!internals.budget.exhausted && result.error?.kind === "budget" && result.error.reason === "output-floor" && result.errorMessage !== void 0) throw new BudgetExhaustedError(result.errorMessage, { data: {
|
|
18408
|
+
scope: state.scope,
|
|
18409
|
+
entryRef: terminal.seq,
|
|
18410
|
+
source: "output-floor",
|
|
18411
|
+
reason: "output-floor"
|
|
18412
|
+
} });
|
|
18399
18413
|
const diagnostics = internals.budget.exhaustionDiagnostics(state.budgetScope ?? "run");
|
|
18400
18414
|
const crossed = diagnostics.crossed;
|
|
18401
18415
|
const rootSuffix = `run root: spent ${diagnostics.root.spentUsd.toFixed(4)}` + (diagnostics.root.ceilingUsd === void 0 ? " USD, no ceiling" : ` of ${diagnostics.root.ceilingUsd.toFixed(4)} USD`);
|
|
@@ -23884,7 +23898,8 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
23884
23898
|
try {
|
|
23885
23899
|
result = await runtime.runInScope(orchestratorState, () => ctx.agent(orchestratorPrompt(goal, opts?.maxSpawns, promptLines.length === 0 ? void 0 : promptLines), agentOpts));
|
|
23886
23900
|
} catch (thrown) {
|
|
23887
|
-
|
|
23901
|
+
const budgetReason = thrown instanceof BudgetExhaustedError ? thrown.data?.reason : void 0;
|
|
23902
|
+
if (budgetReason !== "in-flight-exposure" && budgetReason !== "output-floor") throw thrown;
|
|
23888
23903
|
const exposureKey = deriverV2.deriveKey({ kind: "orchestrator-exposure-fallback" });
|
|
23889
23904
|
if (!internals.replayer.snapshot().some((entry) => entry.kind === "decision" && entry.key === exposureKey)) await internals.replayer.appendSinglePhase({
|
|
23890
23905
|
scope: callingState.scope,
|
|
@@ -23895,7 +23910,7 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
23895
23910
|
site: "orchestrator-budget",
|
|
23896
23911
|
value: {
|
|
23897
23912
|
decisionType: "orchestrator_finalize_fallback",
|
|
23898
|
-
reason: "exposure-abort",
|
|
23913
|
+
reason: budgetReason === "output-floor" ? "budget-floor" : "exposure-abort",
|
|
23899
23914
|
turnsUsed: 0,
|
|
23900
23915
|
foldParams: {
|
|
23901
23916
|
planHash: "",
|
|
@@ -23904,12 +23919,24 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
23904
23919
|
}
|
|
23905
23920
|
});
|
|
23906
23921
|
internals.budget.markExhausted();
|
|
23907
|
-
|
|
23922
|
+
const fold = {
|
|
23908
23923
|
forcedFinishFallback: true,
|
|
23909
23924
|
completion: "partial",
|
|
23910
23925
|
planHash: "",
|
|
23911
23926
|
completed: [...byOrdinal.values()].filter((record) => record.settled !== void 0).sort((a, b) => a.spawnOrdinal - b.spawnOrdinal).map((record) => digestOf(record, record.settled))
|
|
23912
23927
|
};
|
|
23928
|
+
const synthesisReserveStillCommitted = orchestratorAccount !== void 0 && (internals.budget.accountView(orchestratorAccount)?.synthesisReserveUsd ?? 0) > 0;
|
|
23929
|
+
const anySettled = [...byOrdinal.values()].some((record) => record.settled !== void 0);
|
|
23930
|
+
if (opts?.synthesis !== void 0 && synthesisReserveStillCommitted && anySettled) try {
|
|
23931
|
+
const synthesized = await runSynthesis(void 0);
|
|
23932
|
+
return {
|
|
23933
|
+
...fold,
|
|
23934
|
+
result: synthesized
|
|
23935
|
+
};
|
|
23936
|
+
} catch {
|
|
23937
|
+
return fold;
|
|
23938
|
+
}
|
|
23939
|
+
return fold;
|
|
23913
23940
|
}
|
|
23914
23941
|
const liveTermination = extensionTermination;
|
|
23915
23942
|
if (liveTermination !== void 0) throw liveTermination;
|
|
@@ -24932,6 +24959,13 @@ function preflightEstimate(input) {
|
|
|
24932
24959
|
const admitted = wave.filter((row) => row.admitted).length;
|
|
24933
24960
|
const denied = wave.length - admitted;
|
|
24934
24961
|
const requiredMinimumCeilingUsd = wave.length === 0 ? void 0 : wave.reduce((sum, row) => sum + row.reserveUsd, 0) + reservedForFinalizationUsd + synthesisHoldUsd + liveRootExposureTermUsd;
|
|
24962
|
+
const reserveLineUsd = ceilingUsd === void 0 || synthesisHoldUsd <= 0 ? void 0 : ceilingUsd - synthesisHoldUsd;
|
|
24963
|
+
const reserveLineHeadroomUsd = reserveLineUsd === void 0 ? void 0 : reserveLineUsd - wave.filter((row) => row.admitted).reduce((sum, row) => sum + row.reserveUsd, 0);
|
|
24964
|
+
if (orchestrateWave && reserveLineUsd !== void 0 && reserveLineHeadroomUsd !== void 0 && wave.some((row) => row.admitted) && reserveLineHeadroomUsd < 2 * Math.max(liveRootExposureTermUsd, 1e-4)) say({
|
|
24965
|
+
severity: "warning",
|
|
24966
|
+
code: "reserve-line-headroom",
|
|
24967
|
+
message: `the admitted wave's steady state sits ${reserveLineHeadroomUsd.toFixed(4)} USD under the reserve line ${reserveLineUsd.toFixed(4)} USD (the ceiling minus the synthesis reserve), less than two coordination turn floors of headroom (${liveRootExposureTermUsd.toFixed(4)} USD each): child spend past the declared estimates eats that headroom, the coordination loop is then refused at the line, and the run settles partial with the synthesis redeemed from its reserve (RV2101); size the wave below the line or raise the ceiling to keep coordinating past it`
|
|
24968
|
+
});
|
|
24935
24969
|
if (wave.length > 0 && denied > 0) {
|
|
24936
24970
|
const deniedLabels = wave.filter((row) => !row.admitted).map((row) => row.label);
|
|
24937
24971
|
if (admitted === 0) say({
|
|
@@ -24996,11 +25030,11 @@ function preflightEstimate(input) {
|
|
|
24996
25030
|
code: "in-flight-exposure-cap",
|
|
24997
25031
|
message: `RunOptions.maxInFlightExposureUsd ${exposureCapUsd.toFixed(4)} USD bounds spent money plus live dispatch estimates: a dispatch whose estimate does not fit is refused typed before the provider call, so the worst concurrent overshoot past the cap is the estimate error of the in-flight turns, not one whole turn per agent`
|
|
24998
25032
|
});
|
|
24999
|
-
const requiredMinimumExposureUsd = overshootOneTurnFloorUsd
|
|
25000
|
-
if (exposureCapUsd !== void 0 &&
|
|
25033
|
+
const requiredMinimumExposureUsd = overshootOneTurnFloorUsd;
|
|
25034
|
+
if (exposureCapUsd !== void 0 && requiredMinimumExposureUsd !== void 0 && requiredMinimumExposureUsd > exposureCapUsd) say({
|
|
25001
25035
|
severity: "warning",
|
|
25002
25036
|
code: "exposure-cap-tight",
|
|
25003
|
-
message: `maxInFlightExposureUsd ${exposureCapUsd.toFixed(4)} USD sits below the declared wave's breathing floor ${requiredMinimumExposureUsd.toFixed(4)} USD (
|
|
25037
|
+
message: `maxInFlightExposureUsd ${exposureCapUsd.toFixed(4)} USD sits below the declared wave's breathing floor ${requiredMinimumExposureUsd.toFixed(4)} USD (the ${String(pricedTurns.length)} most expensive concurrent turn floors): a coordinating turn beside a full child wave will be refused pre-wire and park until a hold releases (RV1902); raise the cap to at least the floor to avoid the stall entirely`
|
|
25004
25038
|
});
|
|
25005
25039
|
const quotaConfigured = engine.quota !== void 0;
|
|
25006
25040
|
if (!quotaConfigured && maxInFlight > 1 && units.length > 0) say({
|
|
@@ -25190,6 +25224,8 @@ function preflightEstimate(input) {
|
|
|
25190
25224
|
synthesisReserveUsd: synthesisHoldUsd,
|
|
25191
25225
|
...requiredMinimumCeilingUsd === void 0 ? {} : { requiredMinimumCeilingUsd },
|
|
25192
25226
|
...liveRootExposureTermUsd > 0 ? { liveRootExposureTermUsd } : {},
|
|
25227
|
+
...reserveLineUsd === void 0 ? {} : { reserveLineUsd },
|
|
25228
|
+
...reserveLineHeadroomUsd === void 0 ? {} : { reserveLineHeadroomUsd },
|
|
25193
25229
|
wave,
|
|
25194
25230
|
admitted,
|
|
25195
25231
|
denied
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.212.0",
|
|
4
4
|
"description": "Rulvar core: L0 contracts, journal kernel, ctx primitives, agent runtime, model router, tool system, dynamic orchestrator, InMemory and JSONL stores, event stream.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|