@rulvar/core 1.192.0 → 1.194.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 +81 -2
- package/dist/index.js +149 -12
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -2389,6 +2389,16 @@ type AgentEvents = {
|
|
|
2389
2389
|
reason?: string;
|
|
2390
2390
|
retryAfterMs?: number;
|
|
2391
2391
|
willRetry: true;
|
|
2392
|
+
} | {
|
|
2393
|
+
type: "budget:exposure-wait";
|
|
2394
|
+
agentType: string;
|
|
2395
|
+
label?: string; /** The refused model ref. */
|
|
2396
|
+
model?: string; /** The refusal arithmetic, verbatim from the typed refusal. */
|
|
2397
|
+
capUsd?: number;
|
|
2398
|
+
spentUsd?: number;
|
|
2399
|
+
inFlightUsd?: number;
|
|
2400
|
+
estimateUsd?: number;
|
|
2401
|
+
willWait: boolean;
|
|
2392
2402
|
} | {
|
|
2393
2403
|
type: "agent:schema-retry";
|
|
2394
2404
|
agentType: string;
|
|
@@ -5107,6 +5117,16 @@ interface BudgetHooks {
|
|
|
5107
5117
|
*/
|
|
5108
5118
|
assertPricedDispatch?: (servedBy: ModelRef) => void;
|
|
5109
5119
|
admitTurnExposure?: (servedBy: ModelRef, estimatedInputTokens: number, plannedOutputTokens: number) => (() => void) | undefined;
|
|
5120
|
+
/**
|
|
5121
|
+
* Parks until the next in-flight exposure hold releases (RV1902):
|
|
5122
|
+
* 'released' on that wake, 'drained' immediately when no hold is
|
|
5123
|
+
* live, 'aborted' when the signal fires first. Wired beside
|
|
5124
|
+
* admitTurnExposure when the cap is configured; consumed only by
|
|
5125
|
+
* invocations that opted into the exposure wait.
|
|
5126
|
+
*/
|
|
5127
|
+
awaitExposureRelease?: (signal?: AbortSignal) => Promise<"released" | "drained" | "aborted">;
|
|
5128
|
+
/** Live in-flight exposure currently held by open dispatches (RV1902). */
|
|
5129
|
+
liveExposureUsd?: () => number;
|
|
5110
5130
|
/** Live usage accounting; layer 3 may respond by aborting `signal`. */
|
|
5111
5131
|
onUsage(usage: Usage, servedBy: ModelRef): void;
|
|
5112
5132
|
/**
|
|
@@ -5391,6 +5411,15 @@ interface RunAgentOptions<S extends SchemaSpec = JsonSchema> {
|
|
|
5391
5411
|
/** Host or sibling cancellation. */
|
|
5392
5412
|
signal?: AbortSignal;
|
|
5393
5413
|
budget?: BudgetHooks;
|
|
5414
|
+
/**
|
|
5415
|
+
* The exposure-wait posture (RV1902): an in-flight exposure refusal
|
|
5416
|
+
* on this invocation parks until a live hold releases and retries
|
|
5417
|
+
* pre-wire, instead of settling a budget error. Set only by the
|
|
5418
|
+
* orchestrate-owned root dispatches (the coordination loop, the
|
|
5419
|
+
* synthesis invocation, the forced-finish wake), whose settle would
|
|
5420
|
+
* tear down the run its own admitted children are still funding.
|
|
5421
|
+
*/
|
|
5422
|
+
exposureWait?: boolean;
|
|
5394
5423
|
events?: RuntimeEventSink;
|
|
5395
5424
|
transcript?: {
|
|
5396
5425
|
mintRef(): string;
|
|
@@ -6094,6 +6123,13 @@ declare class RunBudget {
|
|
|
6094
6123
|
private exhaustedInternal;
|
|
6095
6124
|
/** Live dispatch estimates held by reserveTurnExposure (RV711). */
|
|
6096
6125
|
private inFlightExposureUsd;
|
|
6126
|
+
/**
|
|
6127
|
+
* Waiters parked on the next exposure release (RV1902): the
|
|
6128
|
+
* orchestrate root's dispatch waits out a transient refusal here
|
|
6129
|
+
* instead of settling a budget error. Notified (and self-removed)
|
|
6130
|
+
* on every hold release; never on spend, which only grows.
|
|
6131
|
+
*/
|
|
6132
|
+
private readonly exposureWaiters;
|
|
6097
6133
|
/** Models already warned about; the warning fires once per model per run. */
|
|
6098
6134
|
private readonly unpricedWarned;
|
|
6099
6135
|
/** Models whose price function already returned an invalid USD once. */
|
|
@@ -6308,6 +6344,19 @@ declare class RunBudget {
|
|
|
6308
6344
|
* lifetime reserve and its own turn exposure would double-count.
|
|
6309
6345
|
*/
|
|
6310
6346
|
reserveTurnExposure(servedBy: ModelRef, estimatedInputTokens: number, plannedOutputTokens: number): (() => void) | undefined;
|
|
6347
|
+
/** Live in-flight exposure currently held by open dispatches (RV1902). */
|
|
6348
|
+
get liveExposureUsd(): number;
|
|
6349
|
+
/**
|
|
6350
|
+
* Parks until the NEXT in-flight exposure hold releases (RV1902):
|
|
6351
|
+
* resolves 'released' on that wake, 'drained' immediately when no
|
|
6352
|
+
* hold is live (there is nothing to wait out, so the caller's refusal
|
|
6353
|
+
* is terminal for its turn), and 'aborted' when the signal fires
|
|
6354
|
+
* first. The waiter registers BEFORE any check, so a release racing
|
|
6355
|
+
* the caller's refusal is never lost; spend never shrinks, so
|
|
6356
|
+
* releases are the only wake source that can turn a refusal into a
|
|
6357
|
+
* fit.
|
|
6358
|
+
*/
|
|
6359
|
+
awaitExposureRelease(signal?: AbortSignal): Promise<"released" | "drained" | "aborted">;
|
|
6311
6360
|
/** Layer 2: the per-turn guard. A turn that would cross any ceiling in the chain is not dispatched. */
|
|
6312
6361
|
beforeTurn(accountScope?: string): void;
|
|
6313
6362
|
/**
|
|
@@ -7241,8 +7290,12 @@ interface RunOptions {
|
|
|
7241
7290
|
* settles, and the dispatch whose estimate does not fit
|
|
7242
7291
|
* spent + finalize/synthesis reserves + live estimates is refused
|
|
7243
7292
|
* with a typed BudgetExhaustedError (data.reason
|
|
7244
|
-
* 'in-flight-exposure')
|
|
7245
|
-
*
|
|
7293
|
+
* 'in-flight-exposure'). A plain agent settles the refusal as a
|
|
7294
|
+
* budget error; an orchestrate-owned root dispatch waits it out
|
|
7295
|
+
* (RV1902): it parks until a live hold releases, retries pre-wire,
|
|
7296
|
+
* and emits budget:exposure-wait, while a drained refusal settles
|
|
7297
|
+
* the documented forced-finish partial instead of tearing the run
|
|
7298
|
+
* down. Worst concurrent overshoot past the cap
|
|
7246
7299
|
* is thereby the estimate error of the in-flight turns, not one
|
|
7247
7300
|
* whole turn per agent. Absent by default: wire traffic, journals,
|
|
7248
7301
|
* and hooks stay byte-identical. Recorded in RunMeta at genesis
|
|
@@ -12553,6 +12606,14 @@ interface PreflightOrchestratorSpec {
|
|
|
12553
12606
|
};
|
|
12554
12607
|
acceptPartialChildren?: boolean;
|
|
12555
12608
|
acceptValidatedTerminalOutputOnLimit?: boolean;
|
|
12609
|
+
/**
|
|
12610
|
+
* Mirrors OrchestrateAcceptance.minSpawnedChildren (RV1901, the
|
|
12611
|
+
* four-role benchmark's primary defect): declaring it lets the
|
|
12612
|
+
* admission projection judge whether the declared wave can seat
|
|
12613
|
+
* the roster the acceptance policy demands, instead of green-
|
|
12614
|
+
* lighting a wave the settle verdict is bound to reject.
|
|
12615
|
+
*/
|
|
12616
|
+
minSpawnedChildren?: number;
|
|
12556
12617
|
};
|
|
12557
12618
|
/**
|
|
12558
12619
|
* The separate synthesis invocation (RV-211), when the orchestration
|
|
@@ -12714,6 +12775,15 @@ interface PreflightAdmissionRow {
|
|
|
12714
12775
|
reserveUsd: number;
|
|
12715
12776
|
admitted: boolean;
|
|
12716
12777
|
deniedBy?: "budget" | "spawn-cap" | "orchestrator-max-spawns";
|
|
12778
|
+
/**
|
|
12779
|
+
* The run-root money already held when this row was evaluated:
|
|
12780
|
+
* committed reserves of the earlier rows plus the finalization and
|
|
12781
|
+
* synthesis carve-outs (RV1901). The row admits iff held + reserveUsd
|
|
12782
|
+
* fits the ceiling (children strictly below it at exact fill), so a
|
|
12783
|
+
* denied row's arithmetic is auditable term by term. Present only
|
|
12784
|
+
* under a USD ceiling.
|
|
12785
|
+
*/
|
|
12786
|
+
heldAtEvaluationUsd?: number;
|
|
12717
12787
|
}
|
|
12718
12788
|
/** The machine-readable preflight report; JSON-serializable throughout. */
|
|
12719
12789
|
interface PreflightReport {
|
|
@@ -12756,6 +12826,15 @@ interface PreflightReport {
|
|
|
12756
12826
|
admission: {
|
|
12757
12827
|
ceilingUsd?: number;
|
|
12758
12828
|
reservedForFinalizationUsd: number;
|
|
12829
|
+
/**
|
|
12830
|
+
* The synthesis payload carve-out the projection holds against the
|
|
12831
|
+
* run root, exactly the live commitSynthesisReserve mirror (RV1901):
|
|
12832
|
+
* a capped orchestrator with budget.synthesisReserveUsd registers it
|
|
12833
|
+
* on the root before any spawn admits, so the wave arithmetic must
|
|
12834
|
+
* hold it too. Zero when the orchestrator is uncapped or declares no
|
|
12835
|
+
* synthesis reserve, matching the runtime that then commits none.
|
|
12836
|
+
*/
|
|
12837
|
+
synthesisReserveUsd: number;
|
|
12759
12838
|
wave: PreflightAdmissionRow[];
|
|
12760
12839
|
admitted: number;
|
|
12761
12840
|
denied: number;
|
package/dist/index.js
CHANGED
|
@@ -12308,10 +12308,33 @@ async function runAgent(options) {
|
|
|
12308
12308
|
return dispatchWithQuota(options.quota);
|
|
12309
12309
|
};
|
|
12310
12310
|
let outcome;
|
|
12311
|
-
|
|
12312
|
-
|
|
12313
|
-
|
|
12314
|
-
|
|
12311
|
+
for (;;) {
|
|
12312
|
+
try {
|
|
12313
|
+
outcome = await (options.providerSlot === void 0 ? dispatch() : options.providerSlot(target.adapter.id, dispatch, options.signal));
|
|
12314
|
+
} catch (thrown) {
|
|
12315
|
+
const refusalData = thrown instanceof BudgetExhaustedError ? thrown.data : void 0;
|
|
12316
|
+
const awaitRelease = options.budget?.awaitExposureRelease;
|
|
12317
|
+
if (options.exposureWait !== true || refusalData?.reason !== "in-flight-exposure" || awaitRelease === void 0) throw thrown;
|
|
12318
|
+
const willWait = (options.budget?.liveExposureUsd?.() ?? 0) > 0;
|
|
12319
|
+
events?.emit({
|
|
12320
|
+
type: "budget:exposure-wait",
|
|
12321
|
+
agentType,
|
|
12322
|
+
label: options.label,
|
|
12323
|
+
model: target.resolved.ref,
|
|
12324
|
+
...typeof refusalData.capUsd === "number" ? { capUsd: refusalData.capUsd } : {},
|
|
12325
|
+
...typeof refusalData.spentUsd === "number" ? { spentUsd: refusalData.spentUsd } : {},
|
|
12326
|
+
...typeof refusalData.inFlightUsd === "number" ? { inFlightUsd: refusalData.inFlightUsd } : {},
|
|
12327
|
+
...typeof refusalData.estimateUsd === "number" ? { estimateUsd: refusalData.estimateUsd } : {},
|
|
12328
|
+
willWait
|
|
12329
|
+
});
|
|
12330
|
+
if (!willWait) throw thrown;
|
|
12331
|
+
const waitSignals = [options.signal, options.budget?.signal].filter((candidate) => candidate !== void 0);
|
|
12332
|
+
await awaitRelease(waitSignals.length === 0 ? void 0 : AbortSignal.any(waitSignals));
|
|
12333
|
+
continue;
|
|
12334
|
+
} finally {
|
|
12335
|
+
releaseExposure?.();
|
|
12336
|
+
}
|
|
12337
|
+
break;
|
|
12315
12338
|
}
|
|
12316
12339
|
if (reservationId !== void 0 && options.quota !== void 0) {
|
|
12317
12340
|
const rawWireCount = (outcome.providerMetadata?.[target.adapter.id])?.wireRequests?.count;
|
|
@@ -13445,6 +13468,13 @@ var RunBudget = class {
|
|
|
13445
13468
|
exhaustedInternal = false;
|
|
13446
13469
|
/** Live dispatch estimates held by reserveTurnExposure (RV711). */
|
|
13447
13470
|
inFlightExposureUsd = 0;
|
|
13471
|
+
/**
|
|
13472
|
+
* Waiters parked on the next exposure release (RV1902): the
|
|
13473
|
+
* orchestrate root's dispatch waits out a transient refusal here
|
|
13474
|
+
* instead of settling a budget error. Notified (and self-removed)
|
|
13475
|
+
* on every hold release; never on spend, which only grows.
|
|
13476
|
+
*/
|
|
13477
|
+
exposureWaiters = /* @__PURE__ */ new Set();
|
|
13448
13478
|
/** Models already warned about; the warning fires once per model per run. */
|
|
13449
13479
|
unpricedWarned = /* @__PURE__ */ new Set();
|
|
13450
13480
|
/** Models whose price function already returned an invalid USD once. */
|
|
@@ -13862,8 +13892,42 @@ var RunBudget = class {
|
|
|
13862
13892
|
if (released) return;
|
|
13863
13893
|
released = true;
|
|
13864
13894
|
this.inFlightExposureUsd = Math.max(0, this.inFlightExposureUsd - estimateUsd);
|
|
13895
|
+
for (const waiter of [...this.exposureWaiters]) waiter();
|
|
13865
13896
|
};
|
|
13866
13897
|
}
|
|
13898
|
+
/** Live in-flight exposure currently held by open dispatches (RV1902). */
|
|
13899
|
+
get liveExposureUsd() {
|
|
13900
|
+
return this.inFlightExposureUsd;
|
|
13901
|
+
}
|
|
13902
|
+
/**
|
|
13903
|
+
* Parks until the NEXT in-flight exposure hold releases (RV1902):
|
|
13904
|
+
* resolves 'released' on that wake, 'drained' immediately when no
|
|
13905
|
+
* hold is live (there is nothing to wait out, so the caller's refusal
|
|
13906
|
+
* is terminal for its turn), and 'aborted' when the signal fires
|
|
13907
|
+
* first. The waiter registers BEFORE any check, so a release racing
|
|
13908
|
+
* the caller's refusal is never lost; spend never shrinks, so
|
|
13909
|
+
* releases are the only wake source that can turn a refusal into a
|
|
13910
|
+
* fit.
|
|
13911
|
+
*/
|
|
13912
|
+
awaitExposureRelease(signal) {
|
|
13913
|
+
if (signal?.aborted === true) return Promise.resolve("aborted");
|
|
13914
|
+
if (this.inFlightExposureUsd <= 0) return Promise.resolve("drained");
|
|
13915
|
+
return new Promise((resolve) => {
|
|
13916
|
+
const settle = (outcome) => {
|
|
13917
|
+
this.exposureWaiters.delete(waiter);
|
|
13918
|
+
signal?.removeEventListener("abort", onAbort);
|
|
13919
|
+
resolve(outcome);
|
|
13920
|
+
};
|
|
13921
|
+
const waiter = () => {
|
|
13922
|
+
settle("released");
|
|
13923
|
+
};
|
|
13924
|
+
const onAbort = () => {
|
|
13925
|
+
settle("aborted");
|
|
13926
|
+
};
|
|
13927
|
+
this.exposureWaiters.add(waiter);
|
|
13928
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
13929
|
+
});
|
|
13930
|
+
}
|
|
13867
13931
|
/** Layer 2: the per-turn guard. A turn that would cross any ceiling in the chain is not dispatched. */
|
|
13868
13932
|
beforeTurn(accountScope = "run") {
|
|
13869
13933
|
for (const account of this.chainOf(accountScope)) if (account.ceilingUsd !== void 0 && account.spentUsd >= account.ceilingUsd) {
|
|
@@ -16270,6 +16334,19 @@ const kBootCheckpoint = Symbol("rulvar.bootCheckpoint");
|
|
|
16270
16334
|
* attribution so the journal fold reproduces reserveUsedUsd.
|
|
16271
16335
|
*/
|
|
16272
16336
|
const kFinalizeReserve = Symbol("rulvar.finalizeReserve");
|
|
16337
|
+
/**
|
|
16338
|
+
* Internal AgentOpts channel (RV1902): marks an orchestrate-owned root
|
|
16339
|
+
* dispatch (the coordination loop, the synthesis invocation, the
|
|
16340
|
+
* forced-finish wake) as one that WAITS OUT a transient in-flight
|
|
16341
|
+
* exposure refusal instead of settling a budget error. The four-role
|
|
16342
|
+
* benchmark's recovery arm died exactly there: the refusal is transient
|
|
16343
|
+
* by contract (budgets guide), but the refused agent was the workflow's
|
|
16344
|
+
* coordinating root, so its settle tore down the whole run while four
|
|
16345
|
+
* admitted children were still finalizing. Never part of the public
|
|
16346
|
+
* AgentOpts surface; plain agents keep the documented settle-as-budget-
|
|
16347
|
+
* error behavior, because their caller can catch and decide.
|
|
16348
|
+
*/
|
|
16349
|
+
const kExposureWait = Symbol("rulvar.exposureWait");
|
|
16273
16350
|
/** Typed accessor used by the in-package consumers. */
|
|
16274
16351
|
function runtimeOf(ctx) {
|
|
16275
16352
|
const runtime = ctxRuntimes.get(ctx);
|
|
@@ -17607,7 +17684,11 @@ function createCtx(internals, rootWorkflow) {
|
|
|
17607
17684
|
maxAffordableOutputTokens: (servedBy, estimatedInputTokens) => internals.budget.maxAffordableOutputTokens(servedBy, estimatedInputTokens, budgetAccount),
|
|
17608
17685
|
remainingUsd: () => internals.budget.remainingUsd(budgetAccount),
|
|
17609
17686
|
...internals.budget.strictPricing === void 0 ? {} : { assertPricedDispatch: (servedBy) => internals.budget.assertPricedDispatch(servedBy) },
|
|
17610
|
-
...internals.budget.maxInFlightExposureUsd === void 0 ? {} : {
|
|
17687
|
+
...internals.budget.maxInFlightExposureUsd === void 0 ? {} : {
|
|
17688
|
+
admitTurnExposure: (servedBy, estimatedInputTokens, plannedOutputTokens) => internals.budget.reserveTurnExposure(servedBy, estimatedInputTokens, plannedOutputTokens),
|
|
17689
|
+
awaitExposureRelease: (signal) => internals.budget.awaitExposureRelease(signal),
|
|
17690
|
+
liveExposureUsd: () => internals.budget.liveExposureUsd
|
|
17691
|
+
},
|
|
17611
17692
|
onUsage: (usage, servedBy) => internals.budget.onUsage(usage, servedBy, budgetAccount),
|
|
17612
17693
|
openCallMeter: (servedBy) => internals.budget.openCallMeter(servedBy, budgetAccount),
|
|
17613
17694
|
signal: budgetAccount === "run" ? internals.budget.signal : AbortSignal.any([internals.budget.signal, internals.budget.signalOf(budgetAccount)].filter((signal) => signal !== void 0))
|
|
@@ -17621,6 +17702,7 @@ function createCtx(internals, rootWorkflow) {
|
|
|
17621
17702
|
if (escalation !== void 0) runAgentOptions.escalation = { minSpendUsd: escalation.minSpendUsd ?? 0 };
|
|
17622
17703
|
const terminalTool = opts[kTerminalTool];
|
|
17623
17704
|
if (terminalTool !== void 0) runAgentOptions.terminalTool = terminalTool;
|
|
17705
|
+
if (opts[kExposureWait] === true) runAgentOptions.exposureWait = true;
|
|
17624
17706
|
runAgentOptions.checkpoint = checkpointPlumbing;
|
|
17625
17707
|
if (opts.schema !== void 0) runAgentOptions.schema = opts.schema;
|
|
17626
17708
|
if (canonicalSchema !== void 0) runAgentOptions.canonicalSchema = canonicalSchema;
|
|
@@ -22235,6 +22317,7 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
22235
22317
|
role: "orchestrate",
|
|
22236
22318
|
result: "full",
|
|
22237
22319
|
tools,
|
|
22320
|
+
[kExposureWait]: true,
|
|
22238
22321
|
...capState === void 0 ? {} : { estCost: orchestratorAdmissionEstCostUsd(capState.effectiveCapUsd, orchestratorAccount === void 0 ? 0 : (internals.budget.accountView(orchestratorAccount)?.finalizeReserveUsd ?? 0) + (internals.budget.accountView(orchestratorAccount)?.synthesisReserveUsd ?? 0)) },
|
|
22239
22322
|
...opts?.model === void 0 ? {} : { model: opts.model },
|
|
22240
22323
|
...opts?.limits === void 0 ? {} : { limits: opts.limits },
|
|
@@ -22293,11 +22376,13 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
22293
22376
|
const fallbackKey = deriverV2.deriveKey({ kind: "orchestrator-finalize-fallback" });
|
|
22294
22377
|
const priorFallback = internals.replayer.snapshot().find((entry) => entry.kind === "decision" && entry.key === fallbackKey);
|
|
22295
22378
|
const priorFinalize = internals.replayer.snapshot().filter((entry) => entry.kind === "agent" && entry.scope === callingState.scope && entry.seq > (capDecisionRef ?? -1) && entry.status !== "running" && entry.costAttribution?.finalizeReserve === true).at(-1);
|
|
22379
|
+
const finalizeTurns = capState?.finalizeTurns ?? 2;
|
|
22296
22380
|
const finalOpts = {
|
|
22297
22381
|
role: "orchestrate",
|
|
22298
22382
|
result: "full",
|
|
22299
22383
|
tools: finishOnly,
|
|
22300
|
-
|
|
22384
|
+
[kExposureWait]: true,
|
|
22385
|
+
limits: { maxTurns: finalizeTurns },
|
|
22301
22386
|
...capState === void 0 ? {} : { estCost: capState.finalizeReserveUsd },
|
|
22302
22387
|
...opts?.model === void 0 ? {} : { model: opts.model },
|
|
22303
22388
|
[kTerminalTool]: {
|
|
@@ -23202,6 +23287,7 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
23202
23287
|
role: "synthesize",
|
|
23203
23288
|
result: "full",
|
|
23204
23289
|
tools: synthesisTools,
|
|
23290
|
+
[kExposureWait]: true,
|
|
23205
23291
|
limits: spec.limits ?? { maxTurns: 4 },
|
|
23206
23292
|
...spec.model === void 0 ? {} : { model: spec.model },
|
|
23207
23293
|
...spec.effort === void 0 ? {} : { effort: spec.effort },
|
|
@@ -23340,7 +23426,37 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
23340
23426
|
...finishValidationPromptLines(validationSpec, coordSectionalFinish ? "rejected-attempt" : void 0),
|
|
23341
23427
|
...acceptancePromptLines(opts?.acceptance)
|
|
23342
23428
|
];
|
|
23343
|
-
|
|
23429
|
+
let result;
|
|
23430
|
+
try {
|
|
23431
|
+
result = await runtime.runInScope(orchestratorState, () => ctx.agent(orchestratorPrompt(goal, opts?.maxSpawns, promptLines.length === 0 ? void 0 : promptLines), agentOpts));
|
|
23432
|
+
} catch (thrown) {
|
|
23433
|
+
if (!(thrown instanceof BudgetExhaustedError) || thrown.data?.reason !== "in-flight-exposure") throw thrown;
|
|
23434
|
+
const exposureKey = deriverV2.deriveKey({ kind: "orchestrator-exposure-fallback" });
|
|
23435
|
+
if (!internals.replayer.snapshot().some((entry) => entry.kind === "decision" && entry.key === exposureKey)) await internals.replayer.appendSinglePhase({
|
|
23436
|
+
scope: callingState.scope,
|
|
23437
|
+
key: exposureKey,
|
|
23438
|
+
kind: "decision",
|
|
23439
|
+
status: "ok",
|
|
23440
|
+
spanId: internals.spans.mint(callingState.spanId),
|
|
23441
|
+
site: "orchestrator-budget",
|
|
23442
|
+
value: {
|
|
23443
|
+
decisionType: "orchestrator_finalize_fallback",
|
|
23444
|
+
reason: "exposure-abort",
|
|
23445
|
+
turnsUsed: 0,
|
|
23446
|
+
foldParams: {
|
|
23447
|
+
planHash: "",
|
|
23448
|
+
digestOrdinalMax: wakeOrdinal
|
|
23449
|
+
}
|
|
23450
|
+
}
|
|
23451
|
+
});
|
|
23452
|
+
internals.budget.markExhausted();
|
|
23453
|
+
return {
|
|
23454
|
+
forcedFinishFallback: true,
|
|
23455
|
+
completion: "partial",
|
|
23456
|
+
planHash: "",
|
|
23457
|
+
completed: [...byOrdinal.values()].filter((record) => record.settled !== void 0).sort((a, b) => a.spawnOrdinal - b.spawnOrdinal).map((record) => digestOf(record, record.settled))
|
|
23458
|
+
};
|
|
23459
|
+
}
|
|
23344
23460
|
const liveTermination = extensionTermination;
|
|
23345
23461
|
if (liveTermination !== void 0) throw liveTermination;
|
|
23346
23462
|
if (capDecisionRef !== void 0) return await settleCapOutcome();
|
|
@@ -23784,9 +23900,11 @@ function preflightEstimate(input) {
|
|
|
23784
23900
|
const coordinationRepairReserve = input.orchestrator?.synthesis === void 0 ? finishRepairReserve : 0;
|
|
23785
23901
|
let orchestratorEcho;
|
|
23786
23902
|
let reservedForFinalizationUsd = 0;
|
|
23903
|
+
let synthesisHoldUsd = 0;
|
|
23787
23904
|
let effectiveCapUsd;
|
|
23788
23905
|
if (input.orchestrator !== void 0) {
|
|
23789
23906
|
if (input.orchestrator.estInputTokens !== void 0) requireNonNegativeInteger(input.orchestrator.estInputTokens, "preflight.orchestrator.estInputTokens");
|
|
23907
|
+
if (input.orchestrator.acceptance?.minSpawnedChildren !== void 0) requirePositiveInteger$2(input.orchestrator.acceptance.minSpawnedChildren, "preflight.orchestrator.acceptance.minSpawnedChildren");
|
|
23790
23908
|
const spec = input.orchestrator.budget;
|
|
23791
23909
|
const fraction = spec?.capFraction ?? .2;
|
|
23792
23910
|
const fromFraction = ceilingUsd === void 0 ? void 0 : fraction * ceilingUsd;
|
|
@@ -23796,6 +23914,7 @@ function preflightEstimate(input) {
|
|
|
23796
23914
|
const finalizeReserveUsd = spec?.finalizeReserveUsd ?? finalizeTurns * flatReserveUsd;
|
|
23797
23915
|
const reserveCommitted = input.orchestrator.extension === true;
|
|
23798
23916
|
if (reserveCommitted) reservedForFinalizationUsd = finalizeReserveUsd;
|
|
23917
|
+
if (effectiveCapUsd !== void 0) synthesisHoldUsd = Math.max(0, spec?.synthesisReserveUsd ?? 0);
|
|
23799
23918
|
const echoLimits = mergeUsageLimits(input.orchestrator.limits, void 0, defaults.limits);
|
|
23800
23919
|
orchestratorEcho = {
|
|
23801
23920
|
...effectiveCapUsd === void 0 ? {} : { effectiveCapUsd },
|
|
@@ -24208,9 +24327,11 @@ function preflightEstimate(input) {
|
|
|
24208
24327
|
let committed = 0;
|
|
24209
24328
|
let spawned = 0;
|
|
24210
24329
|
let children = 0;
|
|
24330
|
+
let childrenDeniedByBudget = 0;
|
|
24331
|
+
const heldAgainstRoot = () => committed + reservedForFinalizationUsd + synthesisHoldUsd;
|
|
24211
24332
|
const admitAgainstRoot = (reserveUsd, strictAtFill = false) => {
|
|
24212
24333
|
if (ceilingUsd === void 0) return true;
|
|
24213
|
-
const held =
|
|
24334
|
+
const held = heldAgainstRoot();
|
|
24214
24335
|
if (held >= ceilingUsd) return false;
|
|
24215
24336
|
const fill = held + reserveUsd;
|
|
24216
24337
|
return strictAtFill ? fill < ceilingUsd : fill <= ceilingUsd;
|
|
@@ -24224,7 +24345,8 @@ function preflightEstimate(input) {
|
|
|
24224
24345
|
label: "orchestrator",
|
|
24225
24346
|
reserveUsd,
|
|
24226
24347
|
admitted: deniedBy === void 0,
|
|
24227
|
-
...deniedBy === void 0 ? {} : { deniedBy }
|
|
24348
|
+
...deniedBy === void 0 ? {} : { deniedBy },
|
|
24349
|
+
...ceilingUsd === void 0 ? {} : { heldAtEvaluationUsd: heldAgainstRoot() }
|
|
24228
24350
|
});
|
|
24229
24351
|
if (deniedBy === void 0) {
|
|
24230
24352
|
committed += reserveUsd;
|
|
@@ -24243,7 +24365,7 @@ function preflightEstimate(input) {
|
|
|
24243
24365
|
else if (maxSpawns !== void 0 && children >= maxSpawns) deniedBy = "orchestrator-max-spawns";
|
|
24244
24366
|
else {
|
|
24245
24367
|
if (orchestrateWave && ceilingUsd !== void 0) {
|
|
24246
|
-
const remainder = ceilingUsd -
|
|
24368
|
+
const remainder = ceilingUsd - heldAgainstRoot();
|
|
24247
24369
|
const projection = dispatchProjectionReserveUsd(gate, flatReserveUsd);
|
|
24248
24370
|
if (remainder <= 0 || remainder <= projection) deniedBy = "budget";
|
|
24249
24371
|
}
|
|
@@ -24253,13 +24375,14 @@ function preflightEstimate(input) {
|
|
|
24253
24375
|
label,
|
|
24254
24376
|
reserveUsd,
|
|
24255
24377
|
admitted: deniedBy === void 0,
|
|
24256
|
-
...deniedBy === void 0 ? {} : { deniedBy }
|
|
24378
|
+
...deniedBy === void 0 ? {} : { deniedBy },
|
|
24379
|
+
...ceilingUsd === void 0 ? {} : { heldAtEvaluationUsd: heldAgainstRoot() }
|
|
24257
24380
|
});
|
|
24258
24381
|
if (deniedBy === void 0) {
|
|
24259
24382
|
committed += reserveUsd;
|
|
24260
24383
|
spawned += 1;
|
|
24261
24384
|
children += 1;
|
|
24262
|
-
}
|
|
24385
|
+
} else if (deniedBy === "budget") childrenDeniedByBudget += 1;
|
|
24263
24386
|
}
|
|
24264
24387
|
}
|
|
24265
24388
|
const admitted = wave.filter((row) => row.admitted).length;
|
|
@@ -24277,6 +24400,19 @@ function preflightEstimate(input) {
|
|
|
24277
24400
|
message: `the declared wave admits ${String(admitted)} of ${String(wave.length)} spawns; denied before any work: ${deniedLabels.join(", ")}`
|
|
24278
24401
|
});
|
|
24279
24402
|
}
|
|
24403
|
+
{
|
|
24404
|
+
const acceptance = input.orchestrator?.acceptance;
|
|
24405
|
+
const minSuccessfulFloor = acceptance?.childPolicy !== void 0 && acceptance.childPolicy !== "all-ok" ? acceptance.childPolicy.minSuccessful : void 0;
|
|
24406
|
+
const rosterFloor = Math.max(acceptance?.minSpawnedChildren ?? 0, minSuccessfulFloor ?? 0);
|
|
24407
|
+
if (rosterFloor > 0 && children < rosterFloor && childrenDeniedByBudget > 0) {
|
|
24408
|
+
const demandedBy = (acceptance?.minSpawnedChildren ?? 0) >= (minSuccessfulFloor ?? 0) ? "acceptance.minSpawnedChildren" : "acceptance.childPolicy.minSuccessful";
|
|
24409
|
+
say({
|
|
24410
|
+
severity: "error",
|
|
24411
|
+
code: "admission-below-roster-floor",
|
|
24412
|
+
message: `the declared wave seats ${String(children)} of the ${String(rosterFloor)} children ${demandedBy} demands (${String(childrenDeniedByBudget)} denied by budget): the run would pay for the seated work and still settle rejected; re-admission after a child settles frees money only when its settled spend stays below the released reserve`
|
|
24413
|
+
});
|
|
24414
|
+
}
|
|
24415
|
+
}
|
|
24280
24416
|
if (ceilingUsd === void 0 && wave.length > 0) say({
|
|
24281
24417
|
severity: "info",
|
|
24282
24418
|
code: "no-usd-ceiling",
|
|
@@ -24500,6 +24636,7 @@ function preflightEstimate(input) {
|
|
|
24500
24636
|
admission: {
|
|
24501
24637
|
...ceilingUsd === void 0 ? {} : { ceilingUsd },
|
|
24502
24638
|
reservedForFinalizationUsd,
|
|
24639
|
+
synthesisReserveUsd: synthesisHoldUsd,
|
|
24503
24640
|
wave,
|
|
24504
24641
|
admitted,
|
|
24505
24642
|
denied
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.194.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",
|