@djolex999/vir-cli 0.7.2 → 0.8.1
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/README.md +27 -3
- package/dist/cli/reconcile.js +223 -0
- package/dist/cli/reconcile.js.map +1 -0
- package/dist/cli/runAction.js +19 -0
- package/dist/cli/runAction.js.map +1 -0
- package/dist/cli.js +94 -52
- package/dist/cli.js.map +1 -1
- package/dist/config.js +8 -0
- package/dist/config.js.map +1 -1
- package/dist/pipeline/distiller.js +123 -20
- package/dist/pipeline/distiller.js.map +1 -1
- package/dist/pipeline/run.js +6 -0
- package/dist/pipeline/run.js.map +1 -1
- package/dist/state/db.js +17 -0
- package/dist/state/db.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -113,6 +113,14 @@ results, not better."_ Fair. Vir addresses it in layers:
|
|
|
113
113
|
list rates + Kie's discount), so the numbers reflect _your_ bill — not a
|
|
114
114
|
blended guess. Kie rates are approximate; override them in `config.pricing` if
|
|
115
115
|
a report looks off.
|
|
116
|
+
- **Reliable failures (v0.8.0).** Every command now exits non-zero on failure —
|
|
117
|
+
no more silent successes hiding broken distills. `vir reconcile --dry-run`
|
|
118
|
+
reports any pre-0.8.0 sessions that landed with empty content (e.g. via the
|
|
119
|
+
v0.7.1 Kie-200-with-body-error bug); `vir reconcile` retries them, bypassing
|
|
120
|
+
the SHA-256 processed-cache for just those rows. Retries that fail again
|
|
121
|
+
leave the row untouched so a second pass can catch them once the underlying
|
|
122
|
+
cause is fixed. Kie 404s carrying an `api_error` body envelope (transient
|
|
123
|
+
service hiccups) are now retried alongside 429/5xx.
|
|
116
124
|
|
|
117
125
|
The bet: with these controls, signal-to-noise stays high enough that the vault
|
|
118
126
|
is a net positive. If your discipline is strong enough to maintain `CLAUDE.md`
|
|
@@ -293,9 +301,21 @@ Distill output dominates. A multi-hour Claude Code epic with hundreds of tool ca
|
|
|
293
301
|
- `vir cost --top 5` shows your most expensive sessions.
|
|
294
302
|
- `vir run --dry-run` previews per-session cost projections before the live run. Estimates are recalibrated from real v0.7.0 token data and run as a rough projection; actual cost varies with session content.
|
|
295
303
|
|
|
296
|
-
###
|
|
304
|
+
### Hybrid routing
|
|
297
305
|
|
|
298
|
-
|
|
306
|
+
Haiku is ~3× cheaper than Sonnet and captures equal-or-more concrete detail on routine and tool-heavy sessions. Calibration data shows it only misses higher-order judgment/architectural lessons on **decision-heavy** and **very large** sessions. Hybrid routing exploits that: route routine sessions to Haiku, reserve Sonnet for where it matters.
|
|
307
|
+
|
|
308
|
+
When `models.distillFast` is set, each session is routed after classification:
|
|
309
|
+
|
|
310
|
+
- `category === "decision"` → `models.distill` (Sonnet)
|
|
311
|
+
- `inputTokens > models.distillThreshold` (default `100000`) → `models.distill`
|
|
312
|
+
- otherwise → `models.distillFast` (Haiku)
|
|
313
|
+
|
|
314
|
+
**New installs** (`vir init`) enable hybrid by default — `distillFast` is set to the Haiku model. **Existing installs** are unaffected on upgrade: with `distillFast` unset, `models.distill` is used for every session exactly as before. Opt in by adding `"distillFast": "claude-haiku-4-5"` (Kie) or `"claude-haiku-4-5-20251001"` (Anthropic) to `models` in `~/.vir/config.json`.
|
|
315
|
+
|
|
316
|
+
`vir run --force-model haiku|sonnet` **bypasses hybrid routing entirely** and forces every session to the named model for that run — useful for A/B comparison. Force-model wins over hybrid.
|
|
317
|
+
|
|
318
|
+
To go all-cheap instead, set `models.distill` itself to the Haiku model (quality degrades on decision-heavy and very large sessions).
|
|
299
319
|
|
|
300
320
|
## Platform support
|
|
301
321
|
|
|
@@ -351,6 +371,8 @@ with your distro, init system, and Node version.
|
|
|
351
371
|
| `vir status` | free | Knowledge heatmap + daemon status |
|
|
352
372
|
| `vir doctor` | cheap | Diagnose installation issues |
|
|
353
373
|
| `vir doctor --json` | cheap | Machine-readable install/health snapshot |
|
|
374
|
+
| `vir reconcile --dry-run` | free | Report sessions that silently failed pre-0.7.2 |
|
|
375
|
+
| `vir reconcile` | $$ | Retry those sessions — bypasses cache for them only |
|
|
354
376
|
|
|
355
377
|
Both `vir query` and `vir doctor` accept `--json` for programmatic consumers
|
|
356
378
|
(e.g. the [vir-obsidian](https://github.com/djolex999/vir) plugin). `query --json`
|
|
@@ -427,7 +449,9 @@ Located at `~/.vir/config.json`.
|
|
|
427
449
|
| `filterToolCalls` | `moderate` | Tool-output filtering: `aggressive` \| `moderate` \| `off` |
|
|
428
450
|
| `retrievalDiversity`| `0.3` | MMR diversity (0..1): 0.0 = pure relevance, 1.0 = pure diversity |
|
|
429
451
|
| `models.classify` | `claude-haiku-4-5-20251001` | Classify model |
|
|
430
|
-
| `models.distill` | `claude-sonnet-4-6` | Distill model
|
|
452
|
+
| `models.distill` | `claude-sonnet-4-6` | Distill model — the "smart" model for decision/large sessions |
|
|
453
|
+
| `models.distillFast`| _(unset)_ | Cheap model for routine sessions. Set → hybrid routing on; unset → `distill` used for everything |
|
|
454
|
+
| `models.distillThreshold`| `100000` | Input-token ceiling above which a session is forced to `distill` |
|
|
431
455
|
| `pricing` | _(built-in)_ | Optional per-provider `$/1M` overrides (`inputPer1M`/`outputPer1M`). Anthropic defaults track list rates; Kie defaults are approximate — verify on your Kie dashboard |
|
|
432
456
|
|
|
433
457
|
## Vault structure
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { createInterface } from "node:readline/promises";
|
|
4
|
+
import { stdin, stdout } from "node:process";
|
|
5
|
+
import { readCostLog } from "../cost/log.js";
|
|
6
|
+
import { computeCost } from "../cost/pricing.js";
|
|
7
|
+
import { Distiller, normalizeModelName, resolveModelShorthand } from "../pipeline/distiller.js";
|
|
8
|
+
import { scoreSession } from "../pipeline/filter.js";
|
|
9
|
+
import { parseSession } from "../pipeline/parser.js";
|
|
10
|
+
import { scrub } from "../pipeline/scrubber.js";
|
|
11
|
+
import { filterToolCalls } from "../pipeline/toolCallFilter.js";
|
|
12
|
+
import { VaultWriter } from "../pipeline/writer.js";
|
|
13
|
+
import { deriveSessionId, StateDb } from "../state/db.js";
|
|
14
|
+
import * as ui from "../ui/display.js";
|
|
15
|
+
// Cost-estimate constants must stay in sync with run.ts's dry-run estimator —
|
|
16
|
+
// transcripts tokenize denser than the chars/4 house heuristic, ~chars/3, and
|
|
17
|
+
// classify/distill output medians come from real cost.log calibration.
|
|
18
|
+
const CHARS_PER_TOKEN = 3;
|
|
19
|
+
const CLASSIFY_OUTPUT_TOKENS = 350;
|
|
20
|
+
const DISTILL_OUTPUT_TOKENS = 4500;
|
|
21
|
+
// Pure selector for unit tests. Mirrors the SQL filter in
|
|
22
|
+
// db.listReconcileTargets exactly: skipped=0 (we tried to distill) AND
|
|
23
|
+
// content is null-or-empty (no usable output landed).
|
|
24
|
+
//
|
|
25
|
+
// Both shapes share one cause — pre-0.7.2 the Kie-200-with-body-error path
|
|
26
|
+
// silently produced an empty distill string; errored runs landed as null.
|
|
27
|
+
// Reconcile retries either.
|
|
28
|
+
export function selectReconcileTargets(rows) {
|
|
29
|
+
return rows.filter((r) => r.skipped === 0 && (r.content === null || r.content === ""));
|
|
30
|
+
}
|
|
31
|
+
// Build the per-target summary (cost estimate + collateral flag) without doing
|
|
32
|
+
// any network work. Used by both the dry-run report and the live confirmation.
|
|
33
|
+
export function summarizeReconcileTargets(cfg, targets, costSessionIds, forceDistillModel) {
|
|
34
|
+
const classifyModel = normalizeModelName(cfg.models.classify, cfg.provider);
|
|
35
|
+
const distillModel = normalizeModelName(resolveModelShorthand(forceDistillModel ?? cfg.models.distill), cfg.provider);
|
|
36
|
+
let totalCost = 0;
|
|
37
|
+
let collateralCount = 0;
|
|
38
|
+
const rows = [];
|
|
39
|
+
for (const t of targets) {
|
|
40
|
+
const sessionId = deriveSessionId(t.path);
|
|
41
|
+
const hadCostRecord = costSessionIds.has(sessionId);
|
|
42
|
+
if (hadCostRecord)
|
|
43
|
+
collateralCount += 1;
|
|
44
|
+
let estimatedCost = 0;
|
|
45
|
+
if (existsSync(t.path)) {
|
|
46
|
+
try {
|
|
47
|
+
const parsed = parseSession(t.path, t.hash);
|
|
48
|
+
const classifyIn = Math.ceil(scrub(parsed.rawSummary).length / CHARS_PER_TOKEN);
|
|
49
|
+
const distillIn = Math.ceil(scrub(filterToolCalls(parsed.transcriptText, cfg.filterToolCalls).filtered).length / CHARS_PER_TOKEN);
|
|
50
|
+
estimatedCost =
|
|
51
|
+
computeCost(cfg.provider, classifyModel, classifyIn, CLASSIFY_OUTPUT_TOKENS, cfg.pricing) +
|
|
52
|
+
computeCost(cfg.provider, distillModel, distillIn, DISTILL_OUTPUT_TOKENS, cfg.pricing);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// Bad jsonl now — we'll still attempt retry, but skip the estimate.
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
totalCost += estimatedCost;
|
|
59
|
+
rows.push({
|
|
60
|
+
path: t.path,
|
|
61
|
+
sessionId,
|
|
62
|
+
hadCostRecord,
|
|
63
|
+
estimatedCost,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return { rows, totalCost, collateralCount };
|
|
67
|
+
}
|
|
68
|
+
async function confirmReconcile(targetCount, totalCost) {
|
|
69
|
+
ui.box([
|
|
70
|
+
`${ui.text(String(targetCount))} ${ui.dim("sessions to retry")}`,
|
|
71
|
+
`${ui.dim("estimated:")} ${ui.warn(ui.formatUsd(totalCost))}`,
|
|
72
|
+
], { title: "reconcile cost estimate" });
|
|
73
|
+
const rl = createInterface({ input: stdin, output: stdout });
|
|
74
|
+
const ans = (await rl.question(ui.muted("continue? (y/n) ")))
|
|
75
|
+
.trim()
|
|
76
|
+
.toLowerCase();
|
|
77
|
+
rl.close();
|
|
78
|
+
return ans === "y" || ans === "yes";
|
|
79
|
+
}
|
|
80
|
+
export async function runReconcile(cfg, opts = {}) {
|
|
81
|
+
const db = new StateDb();
|
|
82
|
+
try {
|
|
83
|
+
ui.header(opts.dryRun ? "reconcile --dry-run" : "reconcile");
|
|
84
|
+
ui.blank();
|
|
85
|
+
const targets = db.listReconcileTargets();
|
|
86
|
+
if (targets.length === 0) {
|
|
87
|
+
ui.row(ui.success(ui.CHECK), ui.text("nothing to reconcile — every session has content"));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
// Build the set of session IDs that already have any distill cost record,
|
|
91
|
+
// so we can report "false-cost collateral" — sessions we paid for but got
|
|
92
|
+
// no content from.
|
|
93
|
+
const costSessionIds = new Set();
|
|
94
|
+
for (const r of readCostLog()) {
|
|
95
|
+
if (r.stage === "distill" && r.session && r.estimated_cost_usd > 0) {
|
|
96
|
+
costSessionIds.add(r.session);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const { rows, totalCost, collateralCount } = summarizeReconcileTargets(cfg, targets, costSessionIds);
|
|
100
|
+
for (const r of rows) {
|
|
101
|
+
const id = r.sessionId.slice(0, 8);
|
|
102
|
+
const marker = r.hadCostRecord ? ui.warn("$") : ui.dim(" ");
|
|
103
|
+
ui.line(` ${ui.dim(ui.BULLET)} ${marker} ${ui.text(id.padEnd(10))} ${ui.dim(`est ${ui.formatUsd(r.estimatedCost)}`)}`);
|
|
104
|
+
}
|
|
105
|
+
ui.blank();
|
|
106
|
+
ui.divider();
|
|
107
|
+
ui.summary({
|
|
108
|
+
recoverable: { value: rows.length, color: ui.info },
|
|
109
|
+
"est. retry cost": { value: ui.formatUsd(totalCost), color: ui.warn },
|
|
110
|
+
"false-cost collateral": {
|
|
111
|
+
value: collateralCount,
|
|
112
|
+
color: collateralCount > 0 ? ui.warn : ui.dim,
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
ui.divider();
|
|
116
|
+
if (opts.dryRun) {
|
|
117
|
+
ui.line(ui.dim(" dry run — nothing retried. Collateral count = sessions we paid for but got no content from."));
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (opts.yes !== true) {
|
|
121
|
+
const proceed = await confirmReconcile(rows.length, totalCost);
|
|
122
|
+
if (!proceed) {
|
|
123
|
+
ui.line(ui.dim("aborted"));
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const writer = new VaultWriter(cfg, db);
|
|
128
|
+
const distiller = new Distiller(cfg);
|
|
129
|
+
let recovered = 0;
|
|
130
|
+
let stillFailed = 0;
|
|
131
|
+
let missingFile = 0;
|
|
132
|
+
for (const t of targets) {
|
|
133
|
+
if (!existsSync(t.path)) {
|
|
134
|
+
missingFile += 1;
|
|
135
|
+
ui.row(ui.warn(ui.WARN_GLYPH), ui.text(`missing on disk — skipped: ${t.path.slice(-60)}`));
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
// Bypass the SHA-256 processed-cache check intentionally — these rows
|
|
139
|
+
// are cached but we know their stored content is empty, so we want a
|
|
140
|
+
// forced retry. Parse, score, distill, then update the row in place.
|
|
141
|
+
try {
|
|
142
|
+
const parsed = parseSession(t.path, t.hash);
|
|
143
|
+
const score = scoreSession(parsed, cfg.filterThreshold);
|
|
144
|
+
if (!score.passes) {
|
|
145
|
+
// The filter rejects this now — record as skipped so a future
|
|
146
|
+
// reconcile pass doesn't keep retrying it.
|
|
147
|
+
db.record({
|
|
148
|
+
path: t.path,
|
|
149
|
+
hash: t.hash,
|
|
150
|
+
skipped: true,
|
|
151
|
+
notePaths: [],
|
|
152
|
+
});
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
const scrubbedSummary = scrub(parsed.rawSummary);
|
|
156
|
+
const toolFilter = filterToolCalls(parsed.transcriptText, cfg.filterToolCalls);
|
|
157
|
+
const scrubbedContent = scrub(toolFilter.filtered);
|
|
158
|
+
const note = await distiller.run(parsed, scrubbedSummary, scrubbedContent);
|
|
159
|
+
if (!note) {
|
|
160
|
+
// Low confidence — record as skipped so we don't keep retrying.
|
|
161
|
+
db.record({
|
|
162
|
+
path: t.path,
|
|
163
|
+
hash: t.hash,
|
|
164
|
+
skipped: true,
|
|
165
|
+
notePaths: [],
|
|
166
|
+
});
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
const written = await writer.write(parsed, note);
|
|
170
|
+
db.record({
|
|
171
|
+
path: t.path,
|
|
172
|
+
hash: t.hash,
|
|
173
|
+
skipped: false,
|
|
174
|
+
notePaths: written,
|
|
175
|
+
content: note.markdown,
|
|
176
|
+
category: note.classification.category,
|
|
177
|
+
topic: note.classification.topic,
|
|
178
|
+
project: note.classification.project,
|
|
179
|
+
confidence: note.classification.confidence,
|
|
180
|
+
startedAt: parsed.startedAt,
|
|
181
|
+
});
|
|
182
|
+
recovered += 1;
|
|
183
|
+
ui.categoryRow(note.classification.category, note.classification.topic);
|
|
184
|
+
// Same pacing as run.ts — let the provider breathe between calls.
|
|
185
|
+
await new Promise((r) => setTimeout(r, 2000));
|
|
186
|
+
}
|
|
187
|
+
catch (err) {
|
|
188
|
+
// A retry that fails again must leave the row as-is (content still
|
|
189
|
+
// null/empty) so the next reconcile pass can catch it. Do NOT mark
|
|
190
|
+
// it processed-with-empty.
|
|
191
|
+
stillFailed += 1;
|
|
192
|
+
const msg = err.message ?? String(err);
|
|
193
|
+
ui.row(ui.errorColor(ui.CROSS), ui.text(`retry failed: ${deriveSessionId(t.path).slice(0, 8)} — ${msg}`));
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
ui.blank();
|
|
197
|
+
ui.divider();
|
|
198
|
+
ui.summary({
|
|
199
|
+
recovered: { value: recovered, color: ui.success },
|
|
200
|
+
"still failed": {
|
|
201
|
+
value: stillFailed,
|
|
202
|
+
color: stillFailed > 0 ? ui.errorColor : ui.dim,
|
|
203
|
+
},
|
|
204
|
+
"missing file": {
|
|
205
|
+
value: missingFile,
|
|
206
|
+
color: missingFile > 0 ? ui.warn : ui.dim,
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
ui.divider();
|
|
210
|
+
// Surface "still failed" via a non-zero exit so the caller (or a CI
|
|
211
|
+
// harness running reconcile periodically) knows recovery is incomplete.
|
|
212
|
+
// The wrapper in cli.ts treats `process.exitCode = 1` as the failure
|
|
213
|
+
// signal; we DON'T throw because the partial recovery is real progress.
|
|
214
|
+
if (stillFailed > 0) {
|
|
215
|
+
process.exitCode = 1;
|
|
216
|
+
ui.line(chalk.dim(` ${stillFailed} session(s) still failed — re-run \`vir reconcile\` after the underlying cause is fixed`));
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
finally {
|
|
220
|
+
db.close();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=reconcile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconcile.js","sourceRoot":"","sources":["../../src/cli/reconcile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
export function runAction(fn, opts = {}) {
|
|
3
|
+
const logError = opts.logError ?? ((m) => console.error(chalk.red(m)));
|
|
4
|
+
return async (...args) => {
|
|
5
|
+
try {
|
|
6
|
+
await fn(...args);
|
|
7
|
+
}
|
|
8
|
+
catch (err) {
|
|
9
|
+
const msg = err instanceof Error
|
|
10
|
+
? err.message
|
|
11
|
+
: typeof err === "string"
|
|
12
|
+
? err
|
|
13
|
+
: JSON.stringify(err);
|
|
14
|
+
logError(msg);
|
|
15
|
+
process.exitCode = 1;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=runAction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runAction.js","sourceRoot":"","sources":["../../src/cli/runAction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAuB1B,MAAM,UAAU,SAAS,CACvB,EAAuC,EACvC,OAAyB,EAAE;IAE3B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/E,OAAO,KAAK,EAAE,GAAG,IAAU,EAAiB,EAAE;QAC5C,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QACpB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GACP,GAAG,YAAY,KAAK;gBAClB,CAAC,CAAC,GAAG,CAAC,OAAO;gBACb,CAAC,CAAC,OAAO,GAAG,KAAK,QAAQ;oBACvB,CAAC,CAAC,GAAG;oBACL,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YAC5B,QAAQ,CAAC,GAAG,CAAC,CAAC;YACd,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|