@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 CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { r as runCli, t as processIo } from "./io-Ghdg-hbD.js";
2
+ import { r as runCli, t as processIo } from "./io-CsvU0Iog.js";
3
3
  import { sanitizeTerminalText } from "@rulvar/core";
4
4
  import { inspect } from "node:util";
5
5
  //#region src/cli.ts
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-Ghdg-hbD.js";
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 priceUsd = (servedBy, usage) => {
108
+ const pricingOf = (servedBy) => {
109
109
  const { adapterId, model } = parseModelRef(servedBy);
110
- const pricing = resolvePricing(servedBy, engineOptions.pricing, byId.get(adapterId)?.caps(model).pricing);
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.119.0",
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.119.0"
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/store-sqlite": "1.119.0",
32
- "@rulvar/testing": "1.119.0",
33
- "@rulvar/planner": "1.119.0",
34
- "@rulvar/plan": "1.119.0",
35
- "@rulvar/evals": "1.119.0"
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"