@rulvar/cli 1.48.0 → 1.50.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.js +54 -10
- package/dist/{io-BK1hP3Od.js → io-DK9Ji_H2.js} +115 -2
- package/package.json +7 -7
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as looksLikeFile, a as resumeCommand, c as driveRun, d as attachProgress, f as renderEventLine, g as loadWorkflowModule, h as loadCliConfig, i as inspectCommand, l as reportOutcome, m as assembleEngine, n as HELP, o as runCommand, p as DEFAULT_STORE_DIR, r as runCli, s as runsLsCommand, t as processIo, u as strictExitCode } from "./io-
|
|
1
|
+
import { _ as looksLikeFile, a as resumeCommand, c as driveRun, d as attachProgress, f as renderEventLine, g as loadWorkflowModule, h as loadCliConfig, i as inspectCommand, l as reportOutcome, m as assembleEngine, n as HELP, o as runCommand, p as DEFAULT_STORE_DIR, r as runCli, s as runsLsCommand, t as processIo, u as strictExitCode } from "./io-DK9Ji_H2.js";
|
|
2
2
|
import { ConfigError, InvalidResolutionError, JournalCompatibilityError, LeaseHeldError, Replayer, RulvarError, buildDeriverRegistry, costReportFromJournal, maskSecrets, normalizeEntry, readRunMeta, scanJournalCompatibility, validateSchemaSpec } from "@rulvar/core";
|
|
3
3
|
//#region src/server.ts
|
|
4
4
|
/**
|
|
@@ -775,8 +775,13 @@ function createWorker(engine, options) {
|
|
|
775
775
|
* tracer)` maps the spanId tree of a run 1:1 onto OTel spans: one span
|
|
776
776
|
* per rulvar span, parented per the span hierarchy (run > phase >
|
|
777
777
|
* agent > tool > child), with start/end timestamps from the lifecycle
|
|
778
|
-
* events
|
|
779
|
-
*
|
|
778
|
+
* events; each agent:phase pair additionally becomes a child span of
|
|
779
|
+
* its agent span keyed (spanId, invocation), carrying the phase's role,
|
|
780
|
+
* model, usage, and cost. Events without an own span (log,
|
|
781
|
+
* budget:update) attach as span events on their enclosing span. An
|
|
782
|
+
* opener for an already-open span never duplicates it (replayed
|
|
783
|
+
* re-emissions mark the original; a pre-RV-207 stream's extra per-phase
|
|
784
|
+
* agent:start cannot leak the agent span unended).
|
|
780
785
|
*
|
|
781
786
|
* `@opentelemetry/api` ^1.9 is an OPTIONAL peer: the CLI has no OTel
|
|
782
787
|
* dependency, and the exporter is typed against a minimal structural
|
|
@@ -799,11 +804,24 @@ function msOf(ts) {
|
|
|
799
804
|
/** The OTel status codes (UNSET 0, OK 1, ERROR 2); inlined to avoid the peer. */
|
|
800
805
|
const STATUS_OK = 1;
|
|
801
806
|
const STATUS_ERROR = 2;
|
|
807
|
+
/**
|
|
808
|
+
* Usage, cost, and retry attributes on a closing span, defensively: the
|
|
809
|
+
* exporter tolerates foreign or truncated streams, so absent fields
|
|
810
|
+
* simply do not become attributes.
|
|
811
|
+
*/
|
|
812
|
+
function setUsageAttributes(open, event, retryKey, retries) {
|
|
813
|
+
if (open === void 0) return;
|
|
814
|
+
if (typeof event.usage?.inputTokens === "number") open.span.setAttribute("gen_ai.usage.input_tokens", event.usage.inputTokens);
|
|
815
|
+
if (typeof event.usage?.outputTokens === "number") open.span.setAttribute("gen_ai.usage.output_tokens", event.usage.outputTokens);
|
|
816
|
+
if (typeof event.costUsd === "number") open.span.setAttribute("rulvar.cost_usd", event.costUsd);
|
|
817
|
+
if (typeof retries === "number") open.span.setAttribute(retryKey, retries);
|
|
818
|
+
}
|
|
802
819
|
function spanName(event) {
|
|
803
820
|
switch (event.type) {
|
|
804
821
|
case "run:start": return `run ${event.workflow}`;
|
|
805
822
|
case "phase:start": return `phase ${event.phase}`;
|
|
806
823
|
case "agent:start": return `agent ${event.agentType || "(anon)"} ${event.role}`;
|
|
824
|
+
case "agent:phase:start": return `invocation ${event.role}`;
|
|
807
825
|
case "tool:start": return `tool ${event.toolName}`;
|
|
808
826
|
case "child:start": return `workflow ${event.workflow}`;
|
|
809
827
|
default: return event.type;
|
|
@@ -822,6 +840,12 @@ function openAttributes(event, runId) {
|
|
|
822
840
|
attrs["gen_ai.request.model"] = event.model;
|
|
823
841
|
attrs["gen_ai.operation.name"] = event.role;
|
|
824
842
|
}
|
|
843
|
+
if (event.type === "agent:phase:start") {
|
|
844
|
+
attrs["rulvar.agent_type"] = event.agentType;
|
|
845
|
+
attrs["gen_ai.request.model"] = event.model;
|
|
846
|
+
attrs["gen_ai.operation.name"] = event.role;
|
|
847
|
+
attrs["rulvar.invocation"] = event.invocation;
|
|
848
|
+
}
|
|
825
849
|
if (event.type === "tool:start") attrs["rulvar.tool_name"] = event.toolName;
|
|
826
850
|
for (const [key, value] of Object.entries(attrs)) if (typeof value === "string") attrs[key] = maskSecrets(value);
|
|
827
851
|
return attrs;
|
|
@@ -838,12 +862,13 @@ async function toOtel(run, tracer, options = {}) {
|
|
|
838
862
|
const stack = [];
|
|
839
863
|
let created = 0;
|
|
840
864
|
const { contextApi, setSpan } = options;
|
|
841
|
-
const startSpan = (event) => {
|
|
842
|
-
|
|
843
|
-
|
|
865
|
+
const startSpan = (event, key = event.spanId, parentKey) => {
|
|
866
|
+
const parentId = parentKey ?? event.parentSpanId;
|
|
867
|
+
if (openBySpanId.has(key)) {
|
|
868
|
+
if (event.replayed === true) openBySpanId.get(key)?.span.setAttribute("rulvar.replayed", true);
|
|
844
869
|
return;
|
|
845
870
|
}
|
|
846
|
-
const parent =
|
|
871
|
+
const parent = parentId === void 0 ? void 0 : openBySpanId.get(parentId);
|
|
847
872
|
const parentContext = parent !== void 0 && contextApi !== void 0 && setSpan !== void 0 ? setSpan(contextApi.active(), parent.span) : void 0;
|
|
848
873
|
const span = tracer.startSpan(spanName(event), {
|
|
849
874
|
startTime: msOf(event.ts),
|
|
@@ -852,10 +877,10 @@ async function toOtel(run, tracer, options = {}) {
|
|
|
852
877
|
created += 1;
|
|
853
878
|
const open = {
|
|
854
879
|
span,
|
|
855
|
-
spanId:
|
|
856
|
-
...
|
|
880
|
+
spanId: key,
|
|
881
|
+
...parentId === void 0 ? {} : { parentSpanId: parentId }
|
|
857
882
|
};
|
|
858
|
-
openBySpanId.set(
|
|
883
|
+
openBySpanId.set(key, open);
|
|
859
884
|
stack.push(open);
|
|
860
885
|
};
|
|
861
886
|
const endSpan = (spanId, ts, status, message) => {
|
|
@@ -880,7 +905,17 @@ async function toOtel(run, tracer, options = {}) {
|
|
|
880
905
|
case "run:end":
|
|
881
906
|
endSpan(event.spanId, event.ts, event.status);
|
|
882
907
|
break;
|
|
908
|
+
case "agent:phase:start":
|
|
909
|
+
startSpan(event, `${event.spanId}#${event.invocation}`, event.spanId);
|
|
910
|
+
break;
|
|
911
|
+
case "agent:phase:end": {
|
|
912
|
+
const key = `${event.spanId}#${event.invocation}`;
|
|
913
|
+
setUsageAttributes(openBySpanId.get(key), event, "rulvar.retries", event.retries);
|
|
914
|
+
endSpan(key, event.ts, event.outcome);
|
|
915
|
+
break;
|
|
916
|
+
}
|
|
883
917
|
case "agent:end":
|
|
918
|
+
setUsageAttributes(openBySpanId.get(event.spanId), event, "rulvar.retry_count", event.retryCount);
|
|
884
919
|
endSpan(event.spanId, event.ts, event.status);
|
|
885
920
|
break;
|
|
886
921
|
case "tool:end":
|
|
@@ -889,6 +924,15 @@ async function toOtel(run, tracer, options = {}) {
|
|
|
889
924
|
case "child:end":
|
|
890
925
|
endSpan(event.spanId, event.ts, event.status);
|
|
891
926
|
break;
|
|
927
|
+
case "determinism:warning":
|
|
928
|
+
(openBySpanId.get(event.spanId) ?? stack[stack.length - 1])?.span.addEvent("determinism:warning", {
|
|
929
|
+
"rulvar.entry_seq": event.seq,
|
|
930
|
+
"rulvar.determinism.category": event.category,
|
|
931
|
+
"rulvar.determinism.provenance": event.provenance,
|
|
932
|
+
...event.file === void 0 ? {} : { "code.filepath": maskSecrets(event.file) },
|
|
933
|
+
...event.line === void 0 ? {} : { "code.lineno": event.line }
|
|
934
|
+
});
|
|
935
|
+
break;
|
|
892
936
|
default: (openBySpanId.get(event.spanId) ?? stack[stack.length - 1])?.span.addEvent(event.type, { "rulvar.entry_seq": event.seq });
|
|
893
937
|
}
|
|
894
938
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConfigError, FileModelKnowledgeStore, INBOX_PROPOSAL_TTL_DAYS, JsonlFileStore, LeaseHeldError, auditRuns, claimExpired, claimExpiry, compilePermissionPreset, costReportFromJournal, createEngine, hashRunArgs, parseModelRef, priceUsdOf, proposalStatement, readRunMeta, reconcileRunMeta, remeasureQueue, resolvePricing, runProfile, sanitizeTerminalText } from "@rulvar/core";
|
|
1
|
+
import { ConfigError, FileModelKnowledgeStore, INBOX_PROPOSAL_TTL_DAYS, JsonlFileStore, LeaseHeldError, auditRuns, claimExpired, claimExpiry, compilePermissionPreset, costReportFromJournal, createEngine, hashRunArgs, hashRunOutput, lastRunSettle, parseModelRef, priceUsdOf, proposalStatement, readRunMeta, reconcileRunMeta, remeasureQueue, resolvePricing, runProfile, sanitizeTerminalText } from "@rulvar/core";
|
|
2
2
|
import { join, resolve } from "node:path";
|
|
3
3
|
import { existsSync, statSync } from "node:fs";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
@@ -197,12 +197,18 @@ function rawEventLine(event) {
|
|
|
197
197
|
case "run:start": return `run ${str(event.runId)} ${event.resumed === true ? "resumed" : "started"} (workflow ${str(event.workflow)})`;
|
|
198
198
|
case "phase:start": return `phase ${str(event.phase)}`;
|
|
199
199
|
case "agent:start": return `${replayMark}agent ${who}${str(event.label) === "" ? "" : ` [${str(event.label)}]`} ${str(event.role)} on ${str(event.model)}`;
|
|
200
|
-
case "agent:
|
|
200
|
+
case "agent:phase:start": return `${replayMark}agent ${who} ${str(event.role)} phase on ${str(event.model)}`;
|
|
201
|
+
case "agent:phase:end": return `${replayMark}agent ${who} ${str(event.role)} phase ${str(event.outcome)} (${money(num(event.costUsd))}, ${String(num(event.usage?.inputTokens) + num(event.usage?.outputTokens))} tok, ${String(num(event.durationMs))}ms${num(event.retries) > 0 ? `, ${String(num(event.retries))} retries` : ""})`;
|
|
202
|
+
case "agent:end": return `${replayMark}agent ${who} ${str(event.status)} (${money(num(event.costUsd))}, ${String(num(event.usage?.inputTokens) + num(event.usage?.outputTokens))} tok${num(event.retryCount) > 0 ? `, ${String(num(event.retryCount))} retries` : ""})${event.usageApprox === true ? " approx" : ""}`;
|
|
201
203
|
case "agent:error": return `agent ${who} error: ${str(event.error?.message)}${event.willRetry === true ? " (will retry)" : ""}`;
|
|
202
204
|
case "agent:queued": return `agent ${who} queued`;
|
|
203
205
|
case "tool:start": return `${replayMark}tool ${str(event.toolName)}`;
|
|
204
206
|
case "tool:end": return `${replayMark}tool ${str(event.toolName)} ${str(event.outcome)} (${String(num(event.durationMs))}ms)`;
|
|
205
207
|
case "approval:pending": return `approval pending: tool ${str(event.toolName)} (entry ${String(num(event.entryRef))})`;
|
|
208
|
+
case "determinism:warning": {
|
|
209
|
+
const where = str(event.file) === "" ? str(event.frame) : `at ${str(event.file)}:${String(num(event.line))}:${String(num(event.column))}`;
|
|
210
|
+
return `determinism ${str(event.category)} (${str(event.provenance)}) ${where}`;
|
|
211
|
+
}
|
|
206
212
|
case "log": return event.level === "debug" ? void 0 : `${str(event.level)}: ${str(event.msg)}`;
|
|
207
213
|
case "run:end": return `run ${str(event.runId)} ${str(event.status)}${event.usageApprox === true ? " (cost approx)" : ""}`;
|
|
208
214
|
default: return;
|
|
@@ -219,12 +225,15 @@ function attachProgress(handle, io) {
|
|
|
219
225
|
"run:start",
|
|
220
226
|
"phase:start",
|
|
221
227
|
"agent:start",
|
|
228
|
+
"agent:phase:start",
|
|
229
|
+
"agent:phase:end",
|
|
222
230
|
"agent:end",
|
|
223
231
|
"agent:error",
|
|
224
232
|
"agent:queued",
|
|
225
233
|
"tool:start",
|
|
226
234
|
"tool:end",
|
|
227
235
|
"approval:pending",
|
|
236
|
+
"determinism:warning",
|
|
228
237
|
"log",
|
|
229
238
|
"run:end"
|
|
230
239
|
]) detachers.push(handle.on(type, forward));
|
|
@@ -437,6 +446,16 @@ const GRAMMAR = {
|
|
|
437
446
|
{ name: "strict" }
|
|
438
447
|
]
|
|
439
448
|
},
|
|
449
|
+
replay: {
|
|
450
|
+
command: "replay",
|
|
451
|
+
positionals: ["<runId>"],
|
|
452
|
+
flags: [
|
|
453
|
+
ARGS,
|
|
454
|
+
STORE,
|
|
455
|
+
{ name: "assert-no-live" },
|
|
456
|
+
{ name: "compare-output-hash" }
|
|
457
|
+
]
|
|
458
|
+
},
|
|
440
459
|
"runs ls": {
|
|
441
460
|
command: "runs ls",
|
|
442
461
|
positionals: [],
|
|
@@ -560,6 +579,7 @@ function helpCommandLines() {
|
|
|
560
579
|
const top = [
|
|
561
580
|
GRAMMAR.run,
|
|
562
581
|
GRAMMAR.resume,
|
|
582
|
+
GRAMMAR.replay,
|
|
563
583
|
GRAMMAR["runs ls"],
|
|
564
584
|
GRAMMAR["runs audit"],
|
|
565
585
|
GRAMMAR.inspect,
|
|
@@ -863,6 +883,92 @@ async function resumeCommand(argv, context) {
|
|
|
863
883
|
return parsed.values.strict === true ? strictExitCode(outcome, base, context.io) : base;
|
|
864
884
|
}
|
|
865
885
|
/**
|
|
886
|
+
* `rulvar replay` (RV-209): replay-strict verification of a recorded
|
|
887
|
+
* run. Resumes under the engine's dry-run mode (zero journal or meta
|
|
888
|
+
* writes, zero adapter calls; the first would-be-live call is a typed
|
|
889
|
+
* JournalMissError settle), then reports the replay accounting, every
|
|
890
|
+
* determinism warning the re-executed body raised (with its localized
|
|
891
|
+
* frame), and the output digest comparison against the journaled
|
|
892
|
+
* settle. `--assert-no-live` exits nonzero unless the replay was pure
|
|
893
|
+
* (zero misses, zero reruns); `--compare-output-hash` exits nonzero
|
|
894
|
+
* unless the replayed result's JCS sha256 equals the recorded
|
|
895
|
+
* `outputHash`. Without flags the command reports and exits 0, so it
|
|
896
|
+
* can sit in a pipeline as a diagnostic before it gates anything.
|
|
897
|
+
* Args follow the resume binding exactly, but there is no
|
|
898
|
+
* --allow-args-change here: changed args change the logical run, and a
|
|
899
|
+
* verification against a different logical run proves nothing.
|
|
900
|
+
*/
|
|
901
|
+
async function replayCommand(argv, context) {
|
|
902
|
+
const parsed = parseCommand(GRAMMAR.replay, argv);
|
|
903
|
+
const runId = parsed.positionals[0];
|
|
904
|
+
const rawArgs = parsed.values.args;
|
|
905
|
+
const args = parseArgsJson(rawArgs);
|
|
906
|
+
const argsGiven = rawArgs !== void 0;
|
|
907
|
+
const assertNoLive = parsed.values["assert-no-live"] === true;
|
|
908
|
+
const compareOutputHash = parsed.values["compare-output-hash"] === true;
|
|
909
|
+
const store = parsed.values.store;
|
|
910
|
+
const assembled = assembleEngine({
|
|
911
|
+
config: await loadCliConfig(context.cwd),
|
|
912
|
+
...store === void 0 ? {} : { storePath: store },
|
|
913
|
+
cwd: context.cwd
|
|
914
|
+
});
|
|
915
|
+
const meta = await readRunMeta(assembled.store, runId);
|
|
916
|
+
if (meta === void 0) throw new ConfigError(`run '${runId}' not found in the store`);
|
|
917
|
+
enforceArgsBinding({
|
|
918
|
+
meta,
|
|
919
|
+
argsGiven,
|
|
920
|
+
args,
|
|
921
|
+
allowChange: false,
|
|
922
|
+
io: context.io
|
|
923
|
+
});
|
|
924
|
+
const name = meta.workflowName;
|
|
925
|
+
const workflow = name === void 0 ? void 0 : assembled.workflows[name];
|
|
926
|
+
if (workflow === void 0) throw new ConfigError(`run '${runId}' was started from workflow '${name ?? "(unknown)"}'; register it under that name in rulvar.config.mjs workflows to replay (replay requires the in-process workflow value)`);
|
|
927
|
+
const handle = assembled.engine.resume(runId, workflow, {
|
|
928
|
+
args,
|
|
929
|
+
dryRun: true
|
|
930
|
+
});
|
|
931
|
+
const warnings = [];
|
|
932
|
+
const consumer = (async () => {
|
|
933
|
+
for await (const event of handle.events) if (event.type === "determinism:warning") warnings.push(event);
|
|
934
|
+
})().catch(() => void 0);
|
|
935
|
+
const outcome = await handle.result;
|
|
936
|
+
const preview = await handle.preview;
|
|
937
|
+
await consumer;
|
|
938
|
+
const recorded = lastRunSettle(await assembled.store.load(runId));
|
|
939
|
+
const io = context.io;
|
|
940
|
+
io.err(`replay of '${sanitizeTerminalText(runId)}' (zero journal or meta writes, zero adapter calls):`);
|
|
941
|
+
io.err(` hits: ${preview.hits} misses: ${preview.misses} reruns: ${preview.reruns} skipped: ${preview.skipped}`);
|
|
942
|
+
io.err(recorded === void 0 ? " recorded settle: none (journal predates the settle entry)" : ` recorded settle: ${recorded.runStatus}`);
|
|
943
|
+
io.err(` replayed settle: ${outcome.status}`);
|
|
944
|
+
if (outcome.error !== void 0 && outcome.error.code !== "journal_miss") io.err(` error: ${sanitizeTerminalText(outcome.error.message)}`);
|
|
945
|
+
for (const warning of warnings) {
|
|
946
|
+
const where = warning.file === void 0 ? warning.frame : `at ${warning.file}:${warning.line ?? "?"}:${warning.column ?? "?"}`;
|
|
947
|
+
io.err(` determinism: ${warning.category} (${warning.provenance}) ${sanitizeTerminalText(where)}`);
|
|
948
|
+
}
|
|
949
|
+
let exit = 0;
|
|
950
|
+
if (assertNoLive) if (preview.misses === 0 && preview.reruns === 0 && outcome.error?.code !== "journal_miss") io.err(" assert-no-live: PASS (pure replay, zero would-be-live calls)");
|
|
951
|
+
else {
|
|
952
|
+
io.err(` assert-no-live: FAIL (misses ${preview.misses}, reruns ${preview.reruns}: a real resume would perform new paid work)`);
|
|
953
|
+
exit = 1;
|
|
954
|
+
}
|
|
955
|
+
if (compareOutputHash) {
|
|
956
|
+
const replayedHash = hashRunOutput(outcome.value);
|
|
957
|
+
if (recorded?.outputHash === void 0) {
|
|
958
|
+
io.err(" compare-output-hash: FAIL (the recorded settle carries no output hash: the run predates it, settled without a value, or the value is not JCS-serializable)");
|
|
959
|
+
exit = 1;
|
|
960
|
+
} else if (replayedHash === void 0) {
|
|
961
|
+
io.err(" compare-output-hash: FAIL (the replayed run produced no hashable value)");
|
|
962
|
+
exit = 1;
|
|
963
|
+
} else if (replayedHash === recorded.outputHash) io.err(` compare-output-hash: PASS (${replayedHash.slice(0, 12)})`);
|
|
964
|
+
else {
|
|
965
|
+
io.err(` compare-output-hash: FAIL (recorded ${recorded.outputHash.slice(0, 12)}, replayed ${replayedHash.slice(0, 12)}: the workflow does not reproduce its output)`);
|
|
966
|
+
exit = 1;
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
return exit;
|
|
970
|
+
}
|
|
971
|
+
/**
|
|
866
972
|
* The stranded run probe and reconciler (fenced run state RFC, phase
|
|
867
973
|
* 3): audits every run the catalog lists against its journal, prints
|
|
868
974
|
* the divergences worker sweeps can never see, and with --repair
|
|
@@ -1430,6 +1536,12 @@ runs audit compares every run's meta row against its journal and names
|
|
|
1430
1536
|
the divergences worker sweeps cannot see (a stranded run's terminal
|
|
1431
1537
|
meta over live journal work); --repair rewrites the sound ones from
|
|
1432
1538
|
the journal under a brief lease, exit 1 while any divergence remains.
|
|
1539
|
+
replay verifies a recorded run without paying: a dry-run resume (zero
|
|
1540
|
+
journal or meta writes, zero adapter calls) that reports replay
|
|
1541
|
+
accounting, localized determinism warnings, and the output digest;
|
|
1542
|
+
--assert-no-live exits 1 unless the replay is pure, and
|
|
1543
|
+
--compare-output-hash exits 1 unless the replayed result's digest
|
|
1544
|
+
equals the journaled one.
|
|
1433
1545
|
plan asks the planner model (role plan) to write a workflow script,
|
|
1434
1546
|
lints and self-repairs it, then runs it in the worker sandbox; --dry-run
|
|
1435
1547
|
prints the accepted script without running. Both stages are paid runs
|
|
@@ -1458,6 +1570,7 @@ async function runCli(argv, options) {
|
|
|
1458
1570
|
switch (command) {
|
|
1459
1571
|
case "run": return await runCommand(rest, context);
|
|
1460
1572
|
case "resume": return await resumeCommand(rest, context);
|
|
1573
|
+
case "replay": return await replayCommand(rest, context);
|
|
1461
1574
|
case "runs": {
|
|
1462
1575
|
const [sub, ...subRest] = rest;
|
|
1463
1576
|
if (sub === "ls") return await runsLsCommand(subRest, context);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.50.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.50.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^22.20.0",
|
|
29
29
|
"tsdown": "^0.22.3",
|
|
30
30
|
"typescript": "~6.0.3",
|
|
31
|
-
"@rulvar/testing": "1.
|
|
32
|
-
"@rulvar/store-sqlite": "1.
|
|
33
|
-
"@rulvar/planner": "1.
|
|
34
|
-
"@rulvar/
|
|
35
|
-
"@rulvar/
|
|
31
|
+
"@rulvar/testing": "1.50.0",
|
|
32
|
+
"@rulvar/store-sqlite": "1.50.0",
|
|
33
|
+
"@rulvar/planner": "1.50.0",
|
|
34
|
+
"@rulvar/plan": "1.50.0",
|
|
35
|
+
"@rulvar/evals": "1.50.0"
|
|
36
36
|
},
|
|
37
37
|
"bin": {
|
|
38
38
|
"rulvar": "./dist/cli.js"
|