@rulvar/core 1.208.0 → 1.210.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 +58 -0
- package/dist/index.js +77 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -5551,6 +5551,20 @@ interface RunAgentOptions<S extends SchemaSpec = JsonSchema> {
|
|
|
5551
5551
|
* else. See applyCachePolicy for the exact shape.
|
|
5552
5552
|
*/
|
|
5553
5553
|
cache?: CachePolicy;
|
|
5554
|
+
/**
|
|
5555
|
+
* The incremental billing seam (RV2008): called with every
|
|
5556
|
+
* ProviderCallRecord the moment the wire call settles and the record
|
|
5557
|
+
* is minted, so the caller can journal it while the invocation is
|
|
5558
|
+
* still running. The parity rerun lost ~$0.99 of root dispatches
|
|
5559
|
+
* because records rode ONLY the terminal entry and the process died
|
|
5560
|
+
* before one existed; with the seam the crash window shrinks to the
|
|
5561
|
+
* single in-flight turn. Restored records (a checkpoint reboot)
|
|
5562
|
+
* never re-emit: they were journaled by the segment that minted
|
|
5563
|
+
* them.
|
|
5564
|
+
*/
|
|
5565
|
+
billing?: {
|
|
5566
|
+
onProviderCall: (record: ProviderCallRecord) => void;
|
|
5567
|
+
};
|
|
5554
5568
|
events?: RuntimeEventSink;
|
|
5555
5569
|
transcript?: {
|
|
5556
5570
|
mintRef(): string;
|
|
@@ -12630,6 +12644,32 @@ interface InvoiceExport {
|
|
|
12630
12644
|
usageApprox?: boolean;
|
|
12631
12645
|
/** The rates provenance (RV407); present when the caller declared it. */
|
|
12632
12646
|
pricing?: InvoicePricingProvenance;
|
|
12647
|
+
/**
|
|
12648
|
+
* The unsettled lane (RV2008): dispatches whose agent is still
|
|
12649
|
+
* RUNNING at the journal's edge, recovered from the incremental
|
|
12650
|
+
* provider-call rows the loop journals as each wire call settles.
|
|
12651
|
+
* Deliberately OUTSIDE the settled totals above: run_settle stays
|
|
12652
|
+
* the billing boundary, and this section prices what the crash
|
|
12653
|
+
* window preserved anyway, the ~$0.99 of parity root dispatches
|
|
12654
|
+
* that used to live only in process memory. Present only when such
|
|
12655
|
+
* rows exist; a journal whose roster is closed never carries it.
|
|
12656
|
+
*/
|
|
12657
|
+
unsettled?: {
|
|
12658
|
+
usd: number;
|
|
12659
|
+
wireRequests: number;
|
|
12660
|
+
rows: Array<{
|
|
12661
|
+
agentRef: number;
|
|
12662
|
+
scope: string;
|
|
12663
|
+
ordinal: number;
|
|
12664
|
+
servedBy: ModelRef;
|
|
12665
|
+
role: string;
|
|
12666
|
+
attempt: number;
|
|
12667
|
+
outcome: string;
|
|
12668
|
+
usage: Usage;
|
|
12669
|
+
usd?: number;
|
|
12670
|
+
responseId?: string;
|
|
12671
|
+
}>;
|
|
12672
|
+
};
|
|
12633
12673
|
}
|
|
12634
12674
|
/**
|
|
12635
12675
|
* The pure invoice fold. Pass the same entries and price table you
|
|
@@ -13131,6 +13171,24 @@ interface PreflightSpawnReport {
|
|
|
13131
13171
|
* turn grows with the prompt, so this is a floor, never a cap.
|
|
13132
13172
|
*/
|
|
13133
13173
|
turnFloorUsd?: number;
|
|
13174
|
+
/**
|
|
13175
|
+
* The loop's input floor over its projected turns, UNCACHED
|
|
13176
|
+
* (RV2007): the declared prompt floor (`estInputTokens`) re-billed
|
|
13177
|
+
* at the full input rate on every projected provider turn. A floor
|
|
13178
|
+
* over the static prefix: real prompts grow. Present when the shape
|
|
13179
|
+
* prices and projects more than one turn.
|
|
13180
|
+
*/
|
|
13181
|
+
uncachedLoopInputFloorUsd?: number;
|
|
13182
|
+
/**
|
|
13183
|
+
* The same loop under the RV2006 cache policy: one cache write of
|
|
13184
|
+
* the prompt floor plus a cache read on every later turn, priced by
|
|
13185
|
+
* the row's cache rates. Present beside the uncached figure when
|
|
13186
|
+
* the row carries cache rates. The parity worker shape (36k-token
|
|
13187
|
+
* prompt floor, a long cycle) prices the difference at roughly
|
|
13188
|
+
* three to four times, the gap between four seats fitting a $6
|
|
13189
|
+
* envelope and three seats dying against it.
|
|
13190
|
+
*/
|
|
13191
|
+
cachedLoopInputFloorUsd?: number;
|
|
13134
13192
|
/** Executed-call ceiling across any tool mix; null = unlimited. */
|
|
13135
13193
|
executedToolCallCeiling: number | null;
|
|
13136
13194
|
/**
|
package/dist/index.js
CHANGED
|
@@ -12511,6 +12511,7 @@ async function runAgent(options) {
|
|
|
12511
12511
|
if (outcome.aborted !== void 0) record.aborted = outcome.aborted;
|
|
12512
12512
|
else if (outcome.wireError !== void 0) record.errorCode = outcome.wireError.code;
|
|
12513
12513
|
providerCalls.push(record);
|
|
12514
|
+
options.billing?.onProviderCall(record);
|
|
12514
12515
|
addCallUsd(site.role, target.resolved.ref, accounted);
|
|
12515
12516
|
const limited = outcome.wireError?.data;
|
|
12516
12517
|
if (limited?.kind === "rate-limit" && typeof limited.reportedLimits === "object" && limited.reportedLimits !== null) rateLimitObservations.set(`${target.adapter.id}:${target.resolved.model}`, {
|
|
@@ -14809,6 +14810,35 @@ function invoiceFromJournal(entries, priceUsd, options) {
|
|
|
14809
14810
|
}
|
|
14810
14811
|
}
|
|
14811
14812
|
const unallocatedUsd = allocateRows(rows, entries, priceUsd, report.grossUsd);
|
|
14813
|
+
const terminalRefs = new Set(entries.filter((entry) => entry.kind === "agent" && entry.status !== "running").map((entry) => entry.ref));
|
|
14814
|
+
const runningBySeq = new Map(entries.filter((entry) => entry.kind === "agent" && entry.status === "running").map((entry) => [entry.seq, entry]));
|
|
14815
|
+
const unsettledRows = [];
|
|
14816
|
+
for (const entry of entries) {
|
|
14817
|
+
if (entry.kind !== "decision") continue;
|
|
14818
|
+
const value = entry.value;
|
|
14819
|
+
if (value?.decisionType !== "provider-call" || typeof value.agentRef !== "number" || terminalRefs.has(value.agentRef)) continue;
|
|
14820
|
+
const running = runningBySeq.get(value.agentRef);
|
|
14821
|
+
const record = value.record;
|
|
14822
|
+
if (running === void 0 || record?.usage === void 0 || typeof record.ordinal !== "number" || typeof record.servedBy !== "string") continue;
|
|
14823
|
+
const usd = rowUsd(priceUsd, record.servedBy, record.usage, entry.seq);
|
|
14824
|
+
unsettledRows.push({
|
|
14825
|
+
agentRef: value.agentRef,
|
|
14826
|
+
scope: running.scope,
|
|
14827
|
+
ordinal: record.ordinal,
|
|
14828
|
+
servedBy: record.servedBy,
|
|
14829
|
+
role: typeof record.role === "string" ? record.role : "loop",
|
|
14830
|
+
attempt: typeof record.attempt === "number" ? record.attempt : 1,
|
|
14831
|
+
outcome: typeof record.outcome === "string" ? record.outcome : "ok",
|
|
14832
|
+
usage: record.usage,
|
|
14833
|
+
...usd === void 0 ? {} : { usd },
|
|
14834
|
+
...typeof record.responseId === "string" ? { responseId: record.responseId } : {}
|
|
14835
|
+
});
|
|
14836
|
+
}
|
|
14837
|
+
const unsettled = unsettledRows.length === 0 ? void 0 : {
|
|
14838
|
+
usd: unsettledRows.reduce((sum, row) => sum + (row.usd ?? 0), 0),
|
|
14839
|
+
wireRequests: unsettledRows.length,
|
|
14840
|
+
rows: unsettledRows
|
|
14841
|
+
};
|
|
14812
14842
|
const usageApprox = report.usageApprox === true || report.abandoned.usageApprox === true;
|
|
14813
14843
|
const invoice = {
|
|
14814
14844
|
rows,
|
|
@@ -14821,6 +14851,7 @@ function invoiceFromJournal(entries, priceUsd, options) {
|
|
|
14821
14851
|
unpriced: [...report.unpriced, ...report.abandoned.unpriced],
|
|
14822
14852
|
reconciliationFailures: rows.filter((row) => row.reconciliation !== "provider-id-present").length,
|
|
14823
14853
|
cardinality: cardinalityOf(rows),
|
|
14854
|
+
...unsettled === void 0 ? {} : { unsettled },
|
|
14824
14855
|
...(() => {
|
|
14825
14856
|
const count = rows.filter((row) => row.usageUnknown === true).length;
|
|
14826
14857
|
return count === 0 ? {} : { usageUnknownRows: count };
|
|
@@ -18003,6 +18034,27 @@ function createCtx(internals, rootWorkflow) {
|
|
|
18003
18034
|
const cachePolicy = opts.cache ?? profile?.cache ?? internals.defaults.cache;
|
|
18004
18035
|
if (cachePolicy !== void 0) runAgentOptions.cache = cachePolicy;
|
|
18005
18036
|
}
|
|
18037
|
+
runAgentOptions.billing = { onProviderCall: (record) => {
|
|
18038
|
+
internals.replayer.appendSinglePhase({
|
|
18039
|
+
scope: state.scope,
|
|
18040
|
+
key: `pc:${String(running.seq)}:${String(record.ordinal)}`,
|
|
18041
|
+
kind: "decision",
|
|
18042
|
+
status: "ok",
|
|
18043
|
+
spanId,
|
|
18044
|
+
site: "provider-call",
|
|
18045
|
+
value: {
|
|
18046
|
+
decisionType: "provider-call",
|
|
18047
|
+
agentRef: running.seq,
|
|
18048
|
+
record
|
|
18049
|
+
}
|
|
18050
|
+
}).catch((thrown) => {
|
|
18051
|
+
internals.events.emit({
|
|
18052
|
+
type: "log",
|
|
18053
|
+
level: "warn",
|
|
18054
|
+
msg: `incremental billing row failed to append; the terminal entry remains the canonical record (${thrown instanceof Error ? thrown.message : String(thrown)})`
|
|
18055
|
+
}, spanId);
|
|
18056
|
+
});
|
|
18057
|
+
} };
|
|
18006
18058
|
runAgentOptions.summarize = summarize;
|
|
18007
18059
|
if (profile?.compaction !== void 0) runAgentOptions.compaction = profile.compaction;
|
|
18008
18060
|
if (profile?.evidenceContract !== void 0) runAgentOptions.evidenceContract = profile.evidenceContract;
|
|
@@ -24474,6 +24526,29 @@ function preflightEstimate(input) {
|
|
|
24474
24526
|
const toolCeilings = toolCeilingsOf(limits);
|
|
24475
24527
|
const executedToolCallCeiling = overallExecutedCeiling(limits, toolCeilings);
|
|
24476
24528
|
const projectedProviderTurns = projectedProviderTurnsOf(limits, executedToolCallCeiling);
|
|
24529
|
+
let uncachedLoopInputFloorUsd;
|
|
24530
|
+
let cachedLoopInputFloorUsd;
|
|
24531
|
+
if (pricing !== void 0 && (spec.estInputTokens ?? 0) > 0 && Number.isFinite(projectedProviderTurns) && projectedProviderTurns > 1) {
|
|
24532
|
+
const loopInputTokens = spec.estInputTokens ?? 0;
|
|
24533
|
+
uncachedLoopInputFloorUsd = projectedProviderTurns * priceUsdOf(pricing, {
|
|
24534
|
+
inputTokens: loopInputTokens,
|
|
24535
|
+
outputTokens: 0,
|
|
24536
|
+
cacheReadTokens: 0,
|
|
24537
|
+
cacheWriteTokens: 0
|
|
24538
|
+
});
|
|
24539
|
+
if (pricing.cacheReadUsdPerMTok !== void 0 && pricing.cacheWriteUsdPerMTok !== void 0) cachedLoopInputFloorUsd = priceUsdOf(pricing, {
|
|
24540
|
+
inputTokens: projectedProviderTurns * loopInputTokens,
|
|
24541
|
+
outputTokens: 0,
|
|
24542
|
+
cacheReadTokens: (projectedProviderTurns - 1) * loopInputTokens,
|
|
24543
|
+
cacheWriteTokens: loopInputTokens
|
|
24544
|
+
});
|
|
24545
|
+
}
|
|
24546
|
+
if (caps?.promptCaching === "explicit" && engine.defaults?.cache?.mode === "off" && uncachedLoopInputFloorUsd !== void 0 && cachedLoopInputFloorUsd !== void 0 && projectedProviderTurns >= 4) say({
|
|
24547
|
+
severity: "warning",
|
|
24548
|
+
code: "uncached-long-loop",
|
|
24549
|
+
message: `spawn '${label}' projects ${String(projectedProviderTurns)} provider turns on the explicit-caching '${servedBy ?? ""}' with the cache policy OFF: the loop's input floor re-bills every turn (${uncachedLoopInputFloorUsd.toFixed(4)} USD uncached against ${cachedLoopInputFloorUsd.toFixed(4)} USD under the default policy); drop defaults.cache { mode: 'off' } or scope the opt-out to the profiles that need it`,
|
|
24550
|
+
spawn: label
|
|
24551
|
+
});
|
|
24477
24552
|
for (const row of toolCeilings) {
|
|
24478
24553
|
if (row.tool === ANY_TOOL) continue;
|
|
24479
24554
|
const cost = limits.toolUnits?.costs?.[row.tool];
|
|
@@ -24610,6 +24685,8 @@ function preflightEstimate(input) {
|
|
|
24610
24685
|
reserveSource,
|
|
24611
24686
|
...outputBound === void 0 ? {} : { maxOutputTokensPerTurn: outputBound },
|
|
24612
24687
|
...turnFloorUsd === void 0 ? {} : { turnFloorUsd },
|
|
24688
|
+
...uncachedLoopInputFloorUsd === void 0 ? {} : { uncachedLoopInputFloorUsd },
|
|
24689
|
+
...cachedLoopInputFloorUsd === void 0 ? {} : { cachedLoopInputFloorUsd },
|
|
24613
24690
|
executedToolCallCeiling,
|
|
24614
24691
|
projectedProviderTurns,
|
|
24615
24692
|
toolCeilings
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.210.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",
|