@rulvar/core 1.222.0 → 1.224.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 +31 -4
- package/dist/index.js +68 -5
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -7623,8 +7623,10 @@ interface RunOptions {
|
|
|
7623
7623
|
* used to be per-invocation and unrecorded, so a resumed segment
|
|
7624
7624
|
* silently ran without the bound the original invocation declared
|
|
7625
7625
|
* (the seventeenth comparison benchmark's top FinOps gap). A run
|
|
7626
|
-
* started without the cap stays uncapped for its whole life
|
|
7627
|
-
*
|
|
7626
|
+
* started without the cap stays uncapped for its whole life unless
|
|
7627
|
+
* a host changes the posture through the explicit, validated,
|
|
7628
|
+
* journaled ResumeOptions.run override (RV2208); nothing changes it
|
|
7629
|
+
* silently.
|
|
7628
7630
|
*/
|
|
7629
7631
|
maxInFlightExposureUsd?: number;
|
|
7630
7632
|
/**
|
|
@@ -7637,7 +7639,9 @@ interface RunOptions {
|
|
|
7637
7639
|
* and `allowUnpriced` (exact model refs the host KNOWS are free,
|
|
7638
7640
|
* the explicit exception). Recorded in RunMeta at genesis and
|
|
7639
7641
|
* restored on every resume, the exposure cap's rule (RV1504): a
|
|
7640
|
-
* FinOps posture a resumed segment silently drops is not a posture
|
|
7642
|
+
* FinOps posture a resumed segment silently drops is not a posture
|
|
7643
|
+
* (and unlike the two ceilings, ResumeOptions.run has no field for
|
|
7644
|
+
* this gate: pricing hygiene is not a per-segment decision).
|
|
7641
7645
|
* Absent by default: dispatch behavior stays byte identical, and an
|
|
7642
7646
|
* unpriced model keeps debiting nothing, the documented ceiling
|
|
7643
7647
|
* hole this mode exists to close.
|
|
@@ -7711,6 +7715,27 @@ interface ResumeOptions {
|
|
|
7711
7715
|
* meta/blob surfaces remain advisory (the fenced run state RFC).
|
|
7712
7716
|
*/
|
|
7713
7717
|
lease?: Lease;
|
|
7718
|
+
/**
|
|
7719
|
+
* Ceiling overrides for the resumed segment and the run's remaining
|
|
7720
|
+
* life (RV2208). The RV1504 rule stands: the RunMeta-recorded
|
|
7721
|
+
* posture is what a bare resume restores; this field is the ONE
|
|
7722
|
+
* explicit way to change that posture after genesis. Each supplied
|
|
7723
|
+
* value is validated exactly like its RunOptions counterpart,
|
|
7724
|
+
* applied to this segment's budget, written back by the segment's
|
|
7725
|
+
* first meta write (a LATER bare resume restores the overridden
|
|
7726
|
+
* posture, not the genesis one), and journaled as a
|
|
7727
|
+
* `run_budget_override` decision naming the recorded and applied
|
|
7728
|
+
* values and the settled spend it was judged against. A `budgetUsd`
|
|
7729
|
+
* below the journal's settled spend refuses typed before ownership,
|
|
7730
|
+
* meta, or any append: such a ceiling would exhaust the segment
|
|
7731
|
+
* before its first turn and read like a fresh money death. Absent
|
|
7732
|
+
* fields keep the recorded values; an absent object keeps the
|
|
7733
|
+
* historical behavior byte for byte.
|
|
7734
|
+
*/
|
|
7735
|
+
run?: {
|
|
7736
|
+
budgetUsd?: number;
|
|
7737
|
+
maxInFlightExposureUsd?: number;
|
|
7738
|
+
};
|
|
7714
7739
|
}
|
|
7715
7740
|
interface ResumeHandle<R> extends RunHandle<R> {
|
|
7716
7741
|
/** Resolves at settle with the replay accounting. */
|
|
@@ -7726,7 +7751,9 @@ interface Engine {
|
|
|
7726
7751
|
* A compiled run resumes WITHOUT wf: the engine rehydrates the
|
|
7727
7752
|
* persisted source pinned by workflowHash; supplying a compiled wf
|
|
7728
7753
|
* whose source hash differs from the recorded one is a typed
|
|
7729
|
-
* ConfigError (M6-T02).
|
|
7754
|
+
* ConfigError (M6-T02). ResumeOptions.run (RV2208) overrides the
|
|
7755
|
+
* recorded budget ceilings for the run's remaining life, with a
|
|
7756
|
+
* journaled decision and a typed floor at the settled spend.
|
|
7730
7757
|
*/
|
|
7731
7758
|
resume<A, R>(runId: string, wf?: Workflow<A, R> | CompiledWorkflow, options?: ResumeOptions): ResumeHandle<R>;
|
|
7732
7759
|
/**
|
package/dist/index.js
CHANGED
|
@@ -12719,7 +12719,8 @@ async function runAgent(options) {
|
|
|
12719
12719
|
kind: "budget",
|
|
12720
12720
|
retryable: false
|
|
12721
12721
|
};
|
|
12722
|
-
|
|
12722
|
+
const lastMessage = messages[messages.length - 1];
|
|
12723
|
+
errorMessage = (grantedRepairTurns > 0 && lastMessage !== void 0 && lastMessage.parts.some((part) => part.type === "tool-result" && part.name === options.terminalTool?.name && part.isError === true) ? "the granted repair turn could not be funded: " : "") + (thrown instanceof Error ? thrown.message : String(thrown));
|
|
12723
12724
|
break;
|
|
12724
12725
|
}
|
|
12725
12726
|
turns += 1;
|
|
@@ -24228,8 +24229,32 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
24228
24229
|
try {
|
|
24229
24230
|
result = await runtime.runInScope(orchestratorState, () => ctx.agent(orchestratorPrompt(goal, opts?.maxSpawns, promptLines.length === 0 ? void 0 : promptLines), agentOpts));
|
|
24230
24231
|
} catch (thrown) {
|
|
24232
|
+
if (thrown instanceof BudgetExhaustedError) {
|
|
24233
|
+
const repairEntryRef = thrown.data?.entryRef;
|
|
24234
|
+
const repairTerminal = typeof repairEntryRef === "number" ? internals.replayer.snapshot().find((entry) => entry.seq === repairEntryRef) : void 0;
|
|
24235
|
+
const repairMessage = repairTerminal?.error?.message ?? "";
|
|
24236
|
+
if (repairMessage.includes("the granted repair turn could not be funded: ")) {
|
|
24237
|
+
const repairDeclineKey = deriverV2.deriveKey({ kind: "orchestrator-repair-grant-declined" });
|
|
24238
|
+
if (!internals.replayer.snapshot().some((entry) => entry.kind === "decision" && entry.key === repairDeclineKey)) await internals.replayer.appendSinglePhase({
|
|
24239
|
+
scope: callingState.scope,
|
|
24240
|
+
key: repairDeclineKey,
|
|
24241
|
+
kind: "decision",
|
|
24242
|
+
status: "ok",
|
|
24243
|
+
spanId: internals.spans.mint(callingState.spanId),
|
|
24244
|
+
site: "orchestrator-budget",
|
|
24245
|
+
value: {
|
|
24246
|
+
decisionType: "orchestrator_repair_grant_declined",
|
|
24247
|
+
reason: repairMessage.slice(0, 300),
|
|
24248
|
+
terminalRef: repairTerminal?.seq ?? null,
|
|
24249
|
+
remainingUsd: internals.budget.remainingUsd() ?? null
|
|
24250
|
+
}
|
|
24251
|
+
});
|
|
24252
|
+
throw new FailRunError(`the orchestrator finish could not complete its granted repair: ${repairMessage}`, { data: { source: "orchestrator_finish_validation" } });
|
|
24253
|
+
}
|
|
24254
|
+
}
|
|
24231
24255
|
const budgetReason = thrown instanceof BudgetExhaustedError ? thrown.data?.reason : void 0;
|
|
24232
|
-
|
|
24256
|
+
const crossed = thrown instanceof BudgetExhaustedError ? thrown.data : void 0;
|
|
24257
|
+
if (budgetReason !== "in-flight-exposure" && budgetReason !== "output-floor" && crossed?.source !== "root" && crossed?.account !== "run") throw thrown;
|
|
24233
24258
|
const exposureKey = deriverV2.deriveKey({ kind: "orchestrator-exposure-fallback" });
|
|
24234
24259
|
if (!internals.replayer.snapshot().some((entry) => entry.kind === "decision" && entry.key === exposureKey)) await internals.replayer.appendSinglePhase({
|
|
24235
24260
|
scope: callingState.scope,
|
|
@@ -24240,7 +24265,7 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
24240
24265
|
site: "orchestrator-budget",
|
|
24241
24266
|
value: {
|
|
24242
24267
|
decisionType: "orchestrator_finalize_fallback",
|
|
24243
|
-
reason: budgetReason === "output-floor" ? "budget-floor" : "exposure-abort",
|
|
24268
|
+
reason: budgetReason === "output-floor" ? "budget-floor" : budgetReason === "in-flight-exposure" ? "exposure-abort" : "budget-ceiling",
|
|
24244
24269
|
turnsUsed: 0,
|
|
24245
24270
|
foldParams: {
|
|
24246
24271
|
planHash: "",
|
|
@@ -26516,8 +26541,8 @@ function createEngine(options) {
|
|
|
26516
26541
|
});
|
|
26517
26542
|
const rootSpanId = spans.mint();
|
|
26518
26543
|
let budgetSeed;
|
|
26519
|
-
const ceilingUsd = opts?.budgetUsd ?? resumeCtx?.budgetUsd;
|
|
26520
|
-
const exposureCapUsd = opts?.maxInFlightExposureUsd ?? resumeCtx?.maxInFlightExposureUsd;
|
|
26544
|
+
const ceilingUsd = opts?.budgetUsd ?? resumeCtx?.budgetOverride?.budgetUsd ?? resumeCtx?.budgetUsd;
|
|
26545
|
+
const exposureCapUsd = opts?.maxInFlightExposureUsd ?? resumeCtx?.budgetOverride?.maxInFlightExposureUsd ?? resumeCtx?.maxInFlightExposureUsd;
|
|
26521
26546
|
const strictPricing = opts?.strictPricing === void 0 ? resumeCtx?.strictPricing : opts.strictPricing === true ? {} : opts.strictPricing === false ? void 0 : {
|
|
26522
26547
|
...opts.strictPricing.maxRatesAgeDays === void 0 ? {} : { maxRatesAgeDays: opts.strictPricing.maxRatesAgeDays },
|
|
26523
26548
|
...opts.strictPricing.allowUnpriced === void 0 ? {} : { allowUnpriced: [...opts.strictPricing.allowUnpriced] }
|
|
@@ -26565,6 +26590,8 @@ function createEngine(options) {
|
|
|
26565
26590
|
agentsSpawned: prior.agentsSpawned,
|
|
26566
26591
|
accounts: accountSpendFromJournal(replayer.snapshot(), priorPriceUsd)
|
|
26567
26592
|
};
|
|
26593
|
+
const overrideCeilingUsd = resumeCtx.budgetOverride?.budgetUsd;
|
|
26594
|
+
if (overrideCeilingUsd !== void 0 && budgetSeed.usd > overrideCeilingUsd) throw new ConfigError(`ResumeOptions.run.budgetUsd ${String(overrideCeilingUsd)} is below the ${budgetSeed.usd.toFixed(4)} USD the journal already records as settled spend; a ceiling below spent exhausts the resumed segment before its first turn. Pass a value at or above the recorded spend, or resume without the override`);
|
|
26568
26595
|
}
|
|
26569
26596
|
const controller = new AbortController();
|
|
26570
26597
|
let cancelReason;
|
|
@@ -26760,6 +26787,34 @@ function createEngine(options) {
|
|
|
26760
26787
|
let wireError;
|
|
26761
26788
|
let pending = [];
|
|
26762
26789
|
if (compiled !== void 0 && resumeCtx?.strict !== true) await transcripts.put(workflowSourceRef(runId), new TextEncoder().encode(compiled.source), segmentLease.current);
|
|
26790
|
+
if (resumeCtx?.budgetOverride !== void 0 && resumeCtx.strict !== true) {
|
|
26791
|
+
const override = resumeCtx.budgetOverride;
|
|
26792
|
+
await replayer.appendSinglePhase({
|
|
26793
|
+
scope: "",
|
|
26794
|
+
key: deriverV2.deriveKey({
|
|
26795
|
+
kind: "run-budget-override",
|
|
26796
|
+
segment: segmentsBefore + 1
|
|
26797
|
+
}),
|
|
26798
|
+
kind: "decision",
|
|
26799
|
+
status: "ok",
|
|
26800
|
+
spanId: rootSpanId,
|
|
26801
|
+
site: "run-budget-override",
|
|
26802
|
+
value: {
|
|
26803
|
+
decisionType: "run_budget_override",
|
|
26804
|
+
source: "resume-options",
|
|
26805
|
+
segment: segmentsBefore + 1,
|
|
26806
|
+
...override.budgetUsd === void 0 ? {} : { budgetUsd: {
|
|
26807
|
+
recorded: resumeCtx.budgetUsd ?? null,
|
|
26808
|
+
applied: override.budgetUsd
|
|
26809
|
+
} },
|
|
26810
|
+
...override.maxInFlightExposureUsd === void 0 ? {} : { maxInFlightExposureUsd: {
|
|
26811
|
+
recorded: resumeCtx.maxInFlightExposureUsd ?? null,
|
|
26812
|
+
applied: override.maxInFlightExposureUsd
|
|
26813
|
+
} },
|
|
26814
|
+
...budgetSeed === void 0 ? {} : { settledSpendUsd: budgetSeed.usd }
|
|
26815
|
+
}
|
|
26816
|
+
});
|
|
26817
|
+
}
|
|
26763
26818
|
await putMeta("running");
|
|
26764
26819
|
bus.emit({
|
|
26765
26820
|
type: "run:start",
|
|
@@ -27004,6 +27059,8 @@ function createEngine(options) {
|
|
|
27004
27059
|
previewResolve = resolve;
|
|
27005
27060
|
});
|
|
27006
27061
|
const handlePromise = (async () => {
|
|
27062
|
+
if (resumeOptions?.run?.budgetUsd !== void 0) requireNonNegativeNumber(resumeOptions.run.budgetUsd, "ResumeOptions.run.budgetUsd");
|
|
27063
|
+
if (resumeOptions?.run?.maxInFlightExposureUsd !== void 0) requireNonNegativeNumber(resumeOptions.run.maxInFlightExposureUsd, "ResumeOptions.run.maxInFlightExposureUsd");
|
|
27007
27064
|
const meta = await readRunMeta(journal, runId);
|
|
27008
27065
|
let supplied = wf;
|
|
27009
27066
|
if (supplied === void 0 && meta?.workflowSourceRef === void 0) {
|
|
@@ -27045,12 +27102,18 @@ function createEngine(options) {
|
|
|
27045
27102
|
code: "RULVAR_LEGACY_CACHE_SEMANTICS",
|
|
27046
27103
|
type: "RulvarWarning"
|
|
27047
27104
|
});
|
|
27105
|
+
const runOverride = resumeOptions?.run;
|
|
27106
|
+
const budgetOverride = runOverride === void 0 || runOverride.budgetUsd === void 0 && runOverride.maxInFlightExposureUsd === void 0 ? void 0 : {
|
|
27107
|
+
...runOverride.budgetUsd === void 0 ? {} : { budgetUsd: runOverride.budgetUsd },
|
|
27108
|
+
...runOverride.maxInFlightExposureUsd === void 0 ? {} : { maxInFlightExposureUsd: runOverride.maxInFlightExposureUsd }
|
|
27109
|
+
};
|
|
27048
27110
|
return run(bound, resumeOptions?.args, void 0, {
|
|
27049
27111
|
runId,
|
|
27050
27112
|
priorEntries,
|
|
27051
27113
|
strict: resumeOptions?.dryRun ?? false,
|
|
27052
27114
|
invalidate: resumeOptions?.invalidate ?? [],
|
|
27053
27115
|
...resumeOptions?.lease === void 0 ? {} : { lease: resumeOptions.lease },
|
|
27116
|
+
...budgetOverride === void 0 ? {} : { budgetOverride },
|
|
27054
27117
|
...typeof meta?.budgetUsd === "number" ? { budgetUsd: meta.budgetUsd } : {},
|
|
27055
27118
|
...typeof meta?.maxInFlightExposureUsd === "number" ? { maxInFlightExposureUsd: meta.maxInFlightExposureUsd } : {},
|
|
27056
27119
|
...typeof meta?.strictPricing === "object" && meta.strictPricing !== null ? { strictPricing: meta.strictPricing } : {},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.224.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",
|