@djolex999/vir-cli 0.7.1 → 0.8.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/README.md +18 -4
- 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 +167 -48
- package/dist/cli.js.map +1 -1
- package/dist/config.js +3 -0
- package/dist/config.js.map +1 -1
- package/dist/output/json.js +12 -4
- package/dist/output/json.js.map +1 -1
- package/dist/pipeline/composer.js +208 -0
- package/dist/pipeline/composer.js.map +1 -0
- package/dist/pipeline/distiller.js +48 -4
- package/dist/pipeline/distiller.js.map +1 -1
- package/dist/pipeline/writer.js +79 -1
- package/dist/pipeline/writer.js.map +1 -1
- package/dist/state/db.js +114 -0
- package/dist/state/db.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ developer-tools, mcp, local-first, cross-platform, llm-wiki
|
|
|
18
18
|
<a href="https://www.npmjs.com/package/@djolex999/vir-cli"><img src="https://img.shields.io/npm/v/@djolex999/vir-cli?color=7c6af7&label=npm" alt="npm version"></a>
|
|
19
19
|
<a href="https://www.npmjs.com/package/@djolex999/vir-cli"><img src="https://img.shields.io/npm/dw/@djolex999/vir-cli?color=4fd1a0" alt="npm downloads"></a>
|
|
20
20
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-22d3ee" alt="license"></a>
|
|
21
|
-
<a href="#project-status"><img src="https://img.shields.io/badge/tests-
|
|
21
|
+
<a href="#project-status"><img src="https://img.shields.io/badge/tests-147%20passing-22c55e" alt="tests"></a>
|
|
22
22
|
<a href="#project-status"><img src="https://img.shields.io/badge/platforms-macOS%20%7C%20Linux-lightgrey" alt="platforms"></a>
|
|
23
23
|
<a href="https://modelcontextprotocol.io"><img src="https://img.shields.io/badge/MCP-server-c084fc" alt="mcp"></a>
|
|
24
24
|
<a href="#"><img src="https://img.shields.io/badge/local--first-yes-f59e0b" alt="local-first"></a>
|
|
@@ -71,8 +71,6 @@ Vir is actively developed. In the next 30–60 days:
|
|
|
71
71
|
- **Obsidian plugin v1** — sidebar, command palette, canvas integration,
|
|
72
72
|
submitted to the community plugin marketplace
|
|
73
73
|
- **Multi-agent support** — Codex CLI, Cursor, Aider, Cline (one per release)
|
|
74
|
-
- **Topic synthesis** — `vir compose` generates LLM Wiki-style topic pages that
|
|
75
|
-
merge insights across sessions
|
|
76
74
|
- **PDF/paper ingestion** — broaden beyond developer workflows
|
|
77
75
|
|
|
78
76
|
Track progress via [GitHub issues](https://github.com/djolex999/vir/issues) or
|
|
@@ -104,6 +102,10 @@ results, not better."_ Fair. Vir addresses it in layers:
|
|
|
104
102
|
- **MMR-diverse retrieval**. Queries return notes covering different aspects of
|
|
105
103
|
the topic, not 5 similar duplicates. The retrieval algorithm balances
|
|
106
104
|
relevance against diversity automatically.
|
|
105
|
+
- **Topic synthesis** via `vir compose "<topic>"`. Embedding-searches the vault
|
|
106
|
+
for related session notes and articles, then synthesizes them into a single
|
|
107
|
+
topic page under `topics/`, with each source wikilinked so it backlinks in
|
|
108
|
+
Obsidian's graph. `--dry-run` previews the sources and cost for free.
|
|
107
109
|
- **Cost transparency.** `vir run --dry-run` estimates per-session cost _before_
|
|
108
110
|
you spend a cent; `vir cost` reports the actuals (total, median, p90, top
|
|
109
111
|
sessions) from a local `~/.vir/cost.log`; and `--force-model haiku|sonnet`
|
|
@@ -111,6 +113,14 @@ results, not better."_ Fair. Vir addresses it in layers:
|
|
|
111
113
|
list rates + Kie's discount), so the numbers reflect _your_ bill — not a
|
|
112
114
|
blended guess. Kie rates are approximate; override them in `config.pricing` if
|
|
113
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.
|
|
114
124
|
|
|
115
125
|
The bet: with these controls, signal-to-noise stays high enough that the vault
|
|
116
126
|
is a net positive. If your discipline is strong enough to maintain `CLAUDE.md`
|
|
@@ -327,6 +337,8 @@ with your distro, init system, and Node version.
|
|
|
327
337
|
| `vir cost --by-session` | free | Full per-session cost distribution |
|
|
328
338
|
| `vir query "<question>"` | cheap | Semantic search your vault |
|
|
329
339
|
| `vir query … --json` | cheap | Machine-readable results for tooling |
|
|
340
|
+
| `vir compose "<topic>"` | $$ | Synthesize a topic page from related notes |
|
|
341
|
+
| `vir compose … --dry-run` | free | Preview sources + cost, exit before LLM |
|
|
330
342
|
| `vir summarize <project>` | cheap | Cross-session project synthesis |
|
|
331
343
|
| `vir summarize --all` | $$ | Summarize all projects |
|
|
332
344
|
| `vir lint` | cheap | Find orphans, stale notes, contradictions |
|
|
@@ -347,6 +359,8 @@ with your distro, init system, and Node version.
|
|
|
347
359
|
| `vir status` | free | Knowledge heatmap + daemon status |
|
|
348
360
|
| `vir doctor` | cheap | Diagnose installation issues |
|
|
349
361
|
| `vir doctor --json` | cheap | Machine-readable install/health snapshot |
|
|
362
|
+
| `vir reconcile --dry-run` | free | Report sessions that silently failed pre-0.7.2 |
|
|
363
|
+
| `vir reconcile` | $$ | Retry those sessions — bypasses cache for them only |
|
|
350
364
|
|
|
351
365
|
Both `vir query` and `vir doctor` accept `--json` for programmatic consumers
|
|
352
366
|
(e.g. the [vir-obsidian](https://github.com/djolex999/vir) plugin). `query --json`
|
|
@@ -453,7 +467,7 @@ vault/vir/
|
|
|
453
467
|
|
|
454
468
|
| | |
|
|
455
469
|
| -------------- | ----------------------------------------- |
|
|
456
|
-
| Tests |
|
|
470
|
+
| Tests | 147 passing |
|
|
457
471
|
| Platforms | macOS (launchd), Linux (systemd/cron) |
|
|
458
472
|
| Node | 20+ |
|
|
459
473
|
| First-run cost | $1–5 (Kie.ai recommended for 72% savings) |
|
|
@@ -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"}
|