@rulvar/cli 1.119.0 → 1.121.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/cli.js +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +2 -1
- package/dist/{io-Ghdg-hbD.js → io-CsvU0Iog.js} +58 -3
- package/package.json +7 -7
package/dist/cli.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CreateEngineOptions, Engine, JournalStore, KeyDeriver, LeasableStore, ModelRef, PreflightInput, RunHandle, RunMeta, RunOutcome, Usage, Workflow, WorkflowEvent, WorkflowRegistry } from "@rulvar/core";
|
|
1
|
+
import { CreateEngineOptions, Engine, JournalStore, KeyDeriver, LeasableStore, ModelRef, PreflightInput, Pricing, RunHandle, RunMeta, RunOutcome, Usage, Workflow, WorkflowEvent, WorkflowRegistry } from "@rulvar/core";
|
|
2
2
|
|
|
3
3
|
//#region src/io.d.ts
|
|
4
4
|
interface CliIo {
|
|
@@ -166,6 +166,13 @@ interface AssembledCli {
|
|
|
166
166
|
/** The journal-fold price function (table wins over caps). */
|
|
167
167
|
priceUsd: (servedBy: ModelRef, usage: Usage) => number | undefined;
|
|
168
168
|
/**
|
|
169
|
+
* The resolved pricing row behind priceUsd (table wins over caps),
|
|
170
|
+
* surfaced for the provenance renderers (RV814): the invoice names
|
|
171
|
+
* each priced model's `ratesVerifiedAt` with its age, and the row is
|
|
172
|
+
* where the date lives.
|
|
173
|
+
*/
|
|
174
|
+
pricingOf: (servedBy: ModelRef) => Pricing | undefined;
|
|
175
|
+
/**
|
|
169
176
|
* The deployment's argsHash salt (engineOptions.security, RV-217),
|
|
170
177
|
* surfaced so the CLI resume args gate hashes supplied --args the
|
|
171
178
|
* same way the engine hashed the genesis args.
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as loadCliConfig, a as invoiceCommand, c as runCommand, d as reportOutcome, f as strictExitCode, g as assembleEngine, h as DEFAULT_STORE_DIR, i as inspectCommand, l as runsLsCommand, m as renderEventLine, n as HELP, o as preflightCommand, p as attachProgress, r as runCli, s as resumeCommand, t as processIo, u as driveRun, v as loadWorkflowModule, y as looksLikeFile } from "./io-
|
|
1
|
+
import { _ as loadCliConfig, a as invoiceCommand, c as runCommand, d as reportOutcome, f as strictExitCode, g as assembleEngine, h as DEFAULT_STORE_DIR, i as inspectCommand, l as runsLsCommand, m as renderEventLine, n as HELP, o as preflightCommand, p as attachProgress, r as runCli, s as resumeCommand, t as processIo, u as driveRun, v as loadWorkflowModule, y as looksLikeFile } from "./io-CsvU0Iog.js";
|
|
2
2
|
import { ConfigError, InvalidResolutionError, JournalCompatibilityError, LeaseHeldError, Replayer, RulvarError, buildDeriverRegistry, compileSecretMasker, costReportFromJournal, journalPricingSnapshot, maskSecrets, normalizeEntry, readRunMeta, scanJournalCompatibility, validateSchemaSpec } from "@rulvar/core";
|
|
3
3
|
//#region src/server.ts
|
|
4
4
|
/**
|
|
@@ -990,6 +990,7 @@ async function toOtel(run, tracer, options = {}) {
|
|
|
990
990
|
if (runOpen !== void 0 && event.degradedReasons !== void 0) runOpen.span.setAttribute("rulvar.run.degradedReasons", JSON.stringify(event.degradedReasons));
|
|
991
991
|
if (runOpen !== void 0 && event.salvagedPartialChildren !== void 0) runOpen.span.setAttribute("rulvar.run.salvagedPartialChildren", JSON.stringify(event.salvagedPartialChildren));
|
|
992
992
|
if (runOpen !== void 0 && event.salvagedTerminalOutputChildren !== void 0) runOpen.span.setAttribute("rulvar.run.salvagedTerminalOutputChildren", JSON.stringify(event.salvagedTerminalOutputChildren));
|
|
993
|
+
if (runOpen !== void 0 && event.acceptanceChildren !== void 0) runOpen.span.setAttribute("rulvar.run.acceptanceChildren", JSON.stringify(event.acceptanceChildren));
|
|
993
994
|
endSpan(event.spanId, event.ts, event.status);
|
|
994
995
|
break;
|
|
995
996
|
}
|
|
@@ -105,9 +105,12 @@ function assembleEngine(options) {
|
|
|
105
105
|
}
|
|
106
106
|
});
|
|
107
107
|
const byId = new Map(adapters.map((adapter) => [adapter.id, adapter]));
|
|
108
|
-
const
|
|
108
|
+
const pricingOf = (servedBy) => {
|
|
109
109
|
const { adapterId, model } = parseModelRef(servedBy);
|
|
110
|
-
|
|
110
|
+
return resolvePricing(servedBy, engineOptions.pricing, byId.get(adapterId)?.caps(model).pricing);
|
|
111
|
+
};
|
|
112
|
+
const priceUsd = (servedBy, usage) => {
|
|
113
|
+
const pricing = pricingOf(servedBy);
|
|
111
114
|
return pricing === void 0 ? void 0 : priceUsdOf(pricing, usage);
|
|
112
115
|
};
|
|
113
116
|
const argsHashSalt = engineOptions.security?.argsHashSalt;
|
|
@@ -117,6 +120,7 @@ function assembleEngine(options) {
|
|
|
117
120
|
store,
|
|
118
121
|
workflows,
|
|
119
122
|
priceUsd,
|
|
123
|
+
pricingOf,
|
|
120
124
|
...argsHashSalt === void 0 ? {} : { argsHashSalt },
|
|
121
125
|
...currentPricingVersion === void 0 ? {} : { currentPricingVersion }
|
|
122
126
|
};
|
|
@@ -1109,6 +1113,24 @@ async function inspectCommand(argv, context) {
|
|
|
1109
1113
|
if (cost.abandoned.usd > 0) context.io.out(`gross: $${cost.grossUsd.toFixed(4)} (abandoned: $${cost.abandoned.usd.toFixed(4)}; see rulvar invoice)`);
|
|
1110
1114
|
for (const [model, usd] of Object.entries(cost.byModel)) context.io.out(` ${model}: $${usd.toFixed(4)}`);
|
|
1111
1115
|
for (const item of cost.unpriced) context.io.out(` unpriced: ${item.model} (${item.usage.inputTokens + item.usage.outputTokens} tok)`);
|
|
1116
|
+
for (const entry of entries) {
|
|
1117
|
+
if (entry.kind !== "decision") continue;
|
|
1118
|
+
const value = entry.value;
|
|
1119
|
+
if (value?.decisionType === "orchestrator_acceptance") {
|
|
1120
|
+
context.io.out(`acceptance: ${value.verdict ?? "unknown"} (completion ${value.completion ?? "unknown"}; gate on the status and completion PAIR)`);
|
|
1121
|
+
if ((value.salvagedPartialChildren?.length ?? 0) > 0) context.io.out(` salvaged partial: ${(value.salvagedPartialChildren ?? []).join(", ")}`);
|
|
1122
|
+
if ((value.salvagedTerminalOutputChildren?.length ?? 0) > 0) context.io.out(` salvaged terminal output: ${(value.salvagedTerminalOutputChildren ?? []).join(", ")}`);
|
|
1123
|
+
for (const child of value.children ?? []) {
|
|
1124
|
+
if (child.evidence === void 0) continue;
|
|
1125
|
+
const marker = child.evidence.met ? "met" : child.evidence.waivedBySalvage === true ? "below floor, waived by salvage" : "below floor";
|
|
1126
|
+
context.io.out(` evidence ${child.child}: ${String(child.evidence.recordedEntries)} of ${String(child.evidence.minEntries)} (${marker})`);
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
if (value?.decisionType === "quota_drift") {
|
|
1130
|
+
const drift = entry.value;
|
|
1131
|
+
context.io.out(`quota drift: ${drift.provider ?? "?"}:${drift.model ?? "?"} ${drift.dimension ?? "?"} declared ${String(drift.declaredPerMinute ?? "?")}/min vs provider ${String(drift.reportedPerMinute ?? "?")}/min (per-minute window, not cumulative)`);
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1112
1134
|
for (const entry of entries) {
|
|
1113
1135
|
const status = entry.status === void 0 ? "" : ` ${entry.status}`;
|
|
1114
1136
|
const served = entry.servedBy === void 0 ? "" : ` servedBy=${entry.servedBy}`;
|
|
@@ -1167,6 +1189,8 @@ async function invoiceCommand(argv, context) {
|
|
|
1167
1189
|
context.io.out(`rows: ${invoice.rows.length} (reconciliation failures: ${invoice.reconciliationFailures}${invoice.usageUnknownRows === void 0 ? "" : `; usage unknown: ${invoice.usageUnknownRows}`})`);
|
|
1168
1190
|
context.io.out(`pricing basis: ${invoice.pricingBasis} ` + (invoice.rowUsdNonAdditive ? "(row usd is non-additive: an aggregate-priced remainder or legacy entry is in the fold; allocatedUsd sums to gross)" : "(rows are additive: every provider call priced per request; allocatedUsd agrees and sums to gross)"));
|
|
1169
1191
|
context.io.out(snapshot === void 0 ? "pricing rates: current table (no snapshot in the journal)" : "pricing rates: run-settle pins composed with the current table" + pinVersionsSuffix(snapshot, assembled.currentPricingVersion));
|
|
1192
|
+
const verified = ratesVerifiedLine(invoice, snapshot, assembled.pricingOf, Date.now());
|
|
1193
|
+
if (verified !== void 0) context.io.out(verified);
|
|
1170
1194
|
for (const row of invoice.rows) {
|
|
1171
1195
|
const usd = row.usd === void 0 ? "unpriced" : `$${row.usd.toFixed(4)}`;
|
|
1172
1196
|
const tokens = row.usage.inputTokens + row.usage.outputTokens;
|
|
@@ -1197,6 +1221,37 @@ function pinVersionsSuffix(snapshot, currentPricingVersion) {
|
|
|
1197
1221
|
if (currentPricingVersion !== void 0) parts.push(`current ${currentPricingVersion}`);
|
|
1198
1222
|
return parts.length === 0 ? "" : ` (${parts.join("; ")})`;
|
|
1199
1223
|
}
|
|
1224
|
+
/**
|
|
1225
|
+
* ` (age Nd)` for an ISO date against the wall clock; empty when the
|
|
1226
|
+
* date does not parse or lies in the future (a malformed or clock-skewed
|
|
1227
|
+
* stamp renders as the bare date, never as a negative age).
|
|
1228
|
+
*/
|
|
1229
|
+
function ageSuffixOf(date, nowMs) {
|
|
1230
|
+
const parsed = Date.parse(date);
|
|
1231
|
+
if (!Number.isFinite(parsed) || parsed > nowMs) return "";
|
|
1232
|
+
return ` (age ${String(Math.floor((nowMs - parsed) / 864e5))}d)`;
|
|
1233
|
+
}
|
|
1234
|
+
/**
|
|
1235
|
+
* `rates verified: <model> <date> (age Nd), <model> no date` over the
|
|
1236
|
+
* models the invoice rows name (RV814). Per model, the date is the
|
|
1237
|
+
* LAST settle pin's row when the journal pins one, because those are
|
|
1238
|
+
* the rates that priced settled history whatever today's table says; a
|
|
1239
|
+
* model outside the pins reads the current table's row. A pinned row
|
|
1240
|
+
* without a stamp is honestly `no date`, never today's table date.
|
|
1241
|
+
* Undefined when no applicable row names a date: journals priced under
|
|
1242
|
+
* pre-stamp tables keep their historical output byte for byte.
|
|
1243
|
+
*/
|
|
1244
|
+
function ratesVerifiedLine(invoice, snapshot, pricingOf, nowMs) {
|
|
1245
|
+
const dated = [...new Set(invoice.rows.map((row) => row.servedBy))].sort().map((model) => {
|
|
1246
|
+
const pinRow = snapshot?.rows.find((row) => row.model === model);
|
|
1247
|
+
return {
|
|
1248
|
+
model,
|
|
1249
|
+
date: pinRow !== void 0 ? pinRow.rates.ratesVerifiedAt : pricingOf(model)?.ratesVerifiedAt
|
|
1250
|
+
};
|
|
1251
|
+
});
|
|
1252
|
+
if (!dated.some((entry) => entry.date !== void 0)) return;
|
|
1253
|
+
return `rates verified: ${dated.map(({ model, date }) => date === void 0 ? `${model} no date` : `${model} ${date}${ageSuffixOf(date, nowMs)}`).join(", ")}`;
|
|
1254
|
+
}
|
|
1200
1255
|
function renderPreflight(report, io) {
|
|
1201
1256
|
io.out("preflight: effective limits and admission projection (zero provider dispatches)");
|
|
1202
1257
|
const perProvider = report.concurrency.perProvider;
|
|
@@ -1211,7 +1266,7 @@ function renderPreflight(report, io) {
|
|
|
1211
1266
|
io.out(`quota: ${report.quota.configured ? "configured" : "none"}` + (report.quota.tenant === void 0 ? "" : ` tenant=${report.quota.tenant}`) + (report.quota.rules === void 0 ? "" : ` rules=${report.quota.rules}`));
|
|
1212
1267
|
io.out(`run limits: ${JSON.stringify(report.runLimits)}`);
|
|
1213
1268
|
for (const spawn of report.spawns) {
|
|
1214
|
-
io.out(`spawn '${spawn.label}' role=${spawn.role} x${spawn.count} servedBy=${spawn.servedBy ?? "UNROUTED"}${spawn.unpriced === true ? " (unpriced)" : ""} reserve=${usdOf(spawn.admissionReserveUsd)} (${spawn.reserveSource})` + (spawn.maxOutputTokensPerTurn === void 0 ? "" : ` maxOutput=${spawn.maxOutputTokensPerTurn}`) + (spawn.turnFloorUsd === void 0 ? "" : ` turnFloor=${usdOf(spawn.turnFloorUsd)}`) + ` toolCallCeiling=${spawn.executedToolCallCeiling ?? "unlimited"} projectedTurns=${spawn.projectedProviderTurns}`);
|
|
1269
|
+
io.out(`spawn '${spawn.label}' role=${spawn.role} x${spawn.count} servedBy=${spawn.servedBy ?? "UNROUTED"}${spawn.unpriced === true ? " (unpriced)" : ""}` + (spawn.ratesVerifiedAt === void 0 ? "" : ` ratesVerified=${spawn.ratesVerifiedAt}${ageSuffixOf(spawn.ratesVerifiedAt, Date.now())}`) + ` reserve=${usdOf(spawn.admissionReserveUsd)} (${spawn.reserveSource})` + (spawn.maxOutputTokensPerTurn === void 0 ? "" : ` maxOutput=${spawn.maxOutputTokensPerTurn}`) + (spawn.turnFloorUsd === void 0 ? "" : ` turnFloor=${usdOf(spawn.turnFloorUsd)}`) + ` toolCallCeiling=${spawn.executedToolCallCeiling ?? "unlimited"} projectedTurns=${spawn.projectedProviderTurns}`);
|
|
1215
1270
|
io.out(` limits: ${JSON.stringify(spawn.limits)}`);
|
|
1216
1271
|
for (const row of spawn.toolCeilings) {
|
|
1217
1272
|
if (row.tool === "(any)" && row.ceiling === null) continue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.121.0",
|
|
4
4
|
"description": "Rulvar shell: run/resume/runs/inspect/plan/kb commands, TUI progress, createServer, createWorker, OTel exporter.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -22,17 +22,17 @@
|
|
|
22
22
|
"access": "public"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@rulvar/core": "1.
|
|
25
|
+
"@rulvar/core": "1.121.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^22.20.1",
|
|
29
29
|
"tsdown": "^0.22.14",
|
|
30
30
|
"typescript": "~6.0.3",
|
|
31
|
-
"@rulvar/
|
|
32
|
-
"@rulvar/
|
|
33
|
-
"@rulvar/planner": "1.
|
|
34
|
-
"@rulvar/plan": "1.
|
|
35
|
-
"@rulvar/evals": "1.
|
|
31
|
+
"@rulvar/testing": "1.121.0",
|
|
32
|
+
"@rulvar/store-sqlite": "1.121.0",
|
|
33
|
+
"@rulvar/planner": "1.121.0",
|
|
34
|
+
"@rulvar/plan": "1.121.0",
|
|
35
|
+
"@rulvar/evals": "1.121.0"
|
|
36
36
|
},
|
|
37
37
|
"bin": {
|
|
38
38
|
"rulvar": "./dist/cli.js"
|