@djolex999/vir-cli 0.12.0 → 0.14.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.
@@ -0,0 +1,189 @@
1
+ import { closeSync, openSync, readSync, readdirSync } from "node:fs";
2
+ import { basename, dirname, join, relative, sep } from "node:path";
3
+ import { computeCost } from "../cost/pricing.js";
4
+ function defaultReadDir(path) {
5
+ try {
6
+ return readdirSync(path, { withFileTypes: true })
7
+ .filter((e) => e.isDirectory())
8
+ .map((e) => e.name);
9
+ }
10
+ catch {
11
+ return [];
12
+ }
13
+ }
14
+ // Claude Code encodes a session's cwd into the transcript dir name by
15
+ // replacing every non-alphanumeric character with "-". Apply the same
16
+ // encoding to real dir names so on-disk candidates compare against the
17
+ // encoded segments byte-for-byte.
18
+ function encodeSegment(name) {
19
+ return name.replace(/[^A-Za-z0-9]/g, "-");
20
+ }
21
+ // Walk the real filesystem from `cur`, consuming `remaining` (the encoded
22
+ // path with its leading dash stripped). Dashes are ambiguous — they encode
23
+ // both path separators and literal dashes/dots/spaces — so try candidates
24
+ // longest-encoding-first and backtrack: only a FULL resolution counts.
25
+ // Returns the on-disk basename of the resolved leaf, or null.
26
+ function resolveEncoded(cur, remaining, readDir) {
27
+ const candidates = readDir(cur)
28
+ .map((name) => ({ name, enc: encodeSegment(name) }))
29
+ .filter(({ enc }) => enc.length > 0 &&
30
+ (enc === remaining || remaining.startsWith(enc + "-")))
31
+ .sort((a, b) => b.enc.length - a.enc.length);
32
+ for (const { name, enc } of candidates) {
33
+ if (enc === remaining)
34
+ return name;
35
+ const leaf = resolveEncoded(join(cur, name), remaining.slice(enc.length + 1), readDir);
36
+ if (leaf !== null)
37
+ return leaf;
38
+ }
39
+ return null;
40
+ }
41
+ // Decode a transcript directory name ("-Users-me-projects-my-app") to its
42
+ // project name ("my-app") by resolving the encoded absolute path against
43
+ // directories that actually exist on disk, longest match wins. Falls back to
44
+ // the raw dir name when nothing fully resolves — never throws, never guesses.
45
+ export function decodeProjectName(dirName, projectsDir, deps) {
46
+ const readDir = deps?.readDir ?? defaultReadDir;
47
+ const name = dirName.includes("/") && dirName.startsWith(projectsDir)
48
+ ? basename(dirName)
49
+ : dirName;
50
+ if (!name.startsWith("-"))
51
+ return name;
52
+ const leaf = resolveEncoded("/", name.slice(1), readDir);
53
+ return leaf ?? name;
54
+ }
55
+ export function classifyTranscript(path, projectsDir) {
56
+ const rel = relative(projectsDir, path);
57
+ if (rel.startsWith(".."))
58
+ return "session";
59
+ const segments = rel.split(sep);
60
+ // segments[0] is the encoded project dir; look for `subagents` below it.
61
+ const subIdx = segments.indexOf("subagents", 1);
62
+ if (subIdx === -1)
63
+ return "session";
64
+ const below = segments.slice(subIdx + 1);
65
+ const isWorkflow = below.some((s) => s === "workflows" || s.startsWith("wf_"));
66
+ return isWorkflow ? "workflow" : "sidechain";
67
+ }
68
+ // SDK launch signature: the first `type:"user"` line's `entrypoint` starting
69
+ // with "sdk" marks an agent-internal transcript (review/verify harness agents
70
+ // stored top-level). Keyed on entrypoint ONLY — promptSource reads "sdk" even
71
+ // on desktop-launched human sessions (the C23 serbeval trap), and turn count
72
+ // would kill single-prompt autonomous runs. Returns the entrypoint, or null
73
+ // for human sessions, truncated heads, or anything unparseable — a miss here
74
+ // falls through to the parser backstop, never to a paid call.
75
+ export function sniffAgentEntrypoint(head) {
76
+ for (const line of head.split("\n")) {
77
+ if (line.trim().length === 0)
78
+ continue;
79
+ let evt;
80
+ try {
81
+ evt = JSON.parse(line);
82
+ }
83
+ catch {
84
+ // truncated tail line or garbage — never a user line we can trust
85
+ continue;
86
+ }
87
+ if (evt.type !== "user")
88
+ continue;
89
+ return typeof evt.entrypoint === "string" &&
90
+ evt.entrypoint.startsWith("sdk")
91
+ ? evt.entrypoint
92
+ : null;
93
+ }
94
+ return null;
95
+ }
96
+ // How much of a transcript the scan-time sniff reads. Review-agent first
97
+ // prompts embed whole diffs, so the first user line can be tens of KB; 256KB
98
+ // covers every observed case while staying trivial next to the full-file
99
+ // read the scanner already does for hashing.
100
+ export const SNIFF_HEAD_BYTES = 262_144;
101
+ export function readTranscriptHead(path, bytes = SNIFF_HEAD_BYTES) {
102
+ try {
103
+ const fd = openSync(path, "r");
104
+ try {
105
+ const buf = Buffer.alloc(bytes);
106
+ const n = readSync(fd, buf, 0, bytes, 0);
107
+ return buf.toString("utf8", 0, n);
108
+ }
109
+ finally {
110
+ closeSync(fd);
111
+ }
112
+ }
113
+ catch {
114
+ return "";
115
+ }
116
+ }
117
+ // Rough triage category for the init wizard's counts line
118
+ // ("21 interactive · 67 SDK-launched · 9 stubs"). Display-only — the run
119
+ // gate uses sniffAgentEntrypoint directly. A stub is a tiny COMPLETE
120
+ // transcript (head covers the whole file) with ≤10 non-blank lines: /clear
121
+ // markers and aborted launches. A truncated head is always interactive —
122
+ // never downgrade what we can't see.
123
+ export function categorizeTranscriptHead(head, sizeBytes) {
124
+ if (sniffAgentEntrypoint(head) !== null)
125
+ return "agent";
126
+ const complete = head.length >= sizeBytes;
127
+ const lines = head.split("\n").filter((l) => l.trim().length > 0).length;
128
+ return complete && lines <= 10 ? "stub" : "interactive";
129
+ }
130
+ export function decideProject(name, configured, flags) {
131
+ const configuredDecision = configured[name];
132
+ if (configuredDecision === "exclude")
133
+ return "exclude";
134
+ if (flags?.excludeProject?.includes(name) === true)
135
+ return "flag-skip";
136
+ if (flags?.only !== undefined &&
137
+ flags.only.length > 0 &&
138
+ !flags.only.includes(name)) {
139
+ return "flag-skip";
140
+ }
141
+ return configuredDecision === "include" ? "include" : "pending";
142
+ }
143
+ // Group discovered sessions by decoded project name. Two transcript dirs can
144
+ // decode to the same project (rare, but a renamed cwd does it) — they merge.
145
+ // The decode cache matters: decodeProjectName walks the filesystem, and a
146
+ // scan can hold hundreds of sessions across a handful of dirs.
147
+ export function groupByProject(sessions, projectsDir, deps) {
148
+ const cache = new Map();
149
+ const groups = new Map();
150
+ for (const s of sessions) {
151
+ // The project dir is the FIRST segment under projectsDir — workflow and
152
+ // subagent transcripts nest one level deeper (<encoded>/<session-id>/
153
+ // wf_*.jsonl) and must group under their project, not the inner dir.
154
+ const rel = relative(projectsDir, s.path);
155
+ const dirName = !rel.startsWith("..") && rel.includes(sep)
156
+ ? (rel.split(sep)[0] ?? basename(dirname(s.path)))
157
+ : basename(dirname(s.path));
158
+ let name = cache.get(dirName);
159
+ if (name === undefined) {
160
+ name = decodeProjectName(dirName, projectsDir, deps);
161
+ cache.set(dirName, name);
162
+ }
163
+ let g = groups.get(name);
164
+ if (!g) {
165
+ g = { name, sessions: [], totalBytes: 0 };
166
+ groups.set(name, g);
167
+ }
168
+ g.sessions.push(s);
169
+ g.totalBytes += s.size;
170
+ }
171
+ return groups;
172
+ }
173
+ // Rough per-session cost estimate from raw transcript size — for the triage
174
+ // UIs (init multi-select, undecided prompt, `vir projects`), NOT billing.
175
+ // Derivation from real dry-run calibration: transcript prose+tools ≈ half the
176
+ // JSONL bytes, the moderate tool filter keeps ~45% of that, chars/3 density
177
+ // → distill input ≈ bytes/13; classify sees prose only ≈ bytes/60. Upper
178
+ // bound: heuristic-filtered sessions actually cost nothing.
179
+ const DISTILL_BYTES_PER_TOKEN = 13;
180
+ const CLASSIFY_BYTES_PER_TOKEN = 60;
181
+ const MAX_DISTILL_INPUT_TOKENS = 150_000;
182
+ const MAX_CLASSIFY_INPUT_TOKENS = 30_000;
183
+ export function estimateSessionCost(provider, classifyModel, distillModel, sizeBytes, pricing, kieTopUpTier) {
184
+ const classifyIn = Math.min(Math.ceil(sizeBytes / CLASSIFY_BYTES_PER_TOKEN), MAX_CLASSIFY_INPUT_TOKENS);
185
+ const distillIn = Math.min(Math.ceil(sizeBytes / DISTILL_BYTES_PER_TOKEN), MAX_DISTILL_INPUT_TOKENS);
186
+ return (computeCost(provider, classifyModel, classifyIn, 350, pricing, kieTopUpTier) +
187
+ computeCost(provider, distillModel, distillIn, 4500, pricing, kieTopUpTier));
188
+ }
189
+ //# sourceMappingURL=projects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects.js","sourceRoot":"","sources":["../../src/pipeline/projects.ts"],"names":[],"mappings":"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"}