@ai-dossier/cli 0.51.0 → 0.54.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 +73 -6
- package/dist/batch-suite-runner.d.ts +30 -6
- package/dist/batch-suite-runner.d.ts.map +1 -1
- package/dist/batch-suite-runner.js +86 -25
- package/dist/batch-suite-runner.js.map +1 -1
- package/dist/capability.d.ts +8 -0
- package/dist/capability.d.ts.map +1 -1
- package/dist/capability.js +16 -1
- package/dist/capability.js.map +1 -1
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/classify.d.ts.map +1 -1
- package/dist/commands/classify.js +8 -2
- package/dist/commands/classify.js.map +1 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +10 -1
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/sched.d.ts.map +1 -1
- package/dist/commands/sched.js +35 -0
- package/dist/commands/sched.js.map +1 -1
- package/dist/commands/usage.d.ts +84 -0
- package/dist/commands/usage.d.ts.map +1 -0
- package/dist/commands/usage.js +395 -0
- package/dist/commands/usage.js.map +1 -0
- package/dist/prescreen.d.ts +48 -5
- package/dist/prescreen.d.ts.map +1 -1
- package/dist/prescreen.js +195 -6
- package/dist/prescreen.js.map +1 -1
- package/dist/usage/collect-claude.d.ts +47 -0
- package/dist/usage/collect-claude.d.ts.map +1 -0
- package/dist/usage/collect-claude.js +237 -0
- package/dist/usage/collect-claude.js.map +1 -0
- package/dist/usage/collect-dispatch.d.ts +73 -0
- package/dist/usage/collect-dispatch.d.ts.map +1 -0
- package/dist/usage/collect-dispatch.js +297 -0
- package/dist/usage/collect-dispatch.js.map +1 -0
- package/dist/usage/collect-opencode.d.ts +74 -0
- package/dist/usage/collect-opencode.d.ts.map +1 -0
- package/dist/usage/collect-opencode.js +198 -0
- package/dist/usage/collect-opencode.js.map +1 -0
- package/dist/usage/host-session.d.ts +63 -0
- package/dist/usage/host-session.d.ts.map +1 -0
- package/dist/usage/host-session.js +325 -0
- package/dist/usage/host-session.js.map +1 -0
- package/dist/usage/ledger.d.ts +87 -0
- package/dist/usage/ledger.d.ts.map +1 -0
- package/dist/usage/ledger.js +268 -0
- package/dist/usage/ledger.js.map +1 -0
- package/dist/usage/types.d.ts +80 -0
- package/dist/usage/types.d.ts.map +1 -0
- package/dist/usage/types.js +11 -0
- package/dist/usage/types.js.map +1 -0
- package/dist/usage/util.d.ts +36 -0
- package/dist/usage/util.d.ts.map +1 -0
- package/dist/usage/util.js +158 -0
- package/dist/usage/util.js.map +1 -0
- package/package.json +2 -2
package/dist/prescreen.js
CHANGED
|
@@ -13,13 +13,21 @@
|
|
|
13
13
|
* a plan artifact, rule 10 confidence) falls through to the classifier's own bounded
|
|
14
14
|
* mechanical-tier pass, which is the intended safety net — not a gap this module needs to close.
|
|
15
15
|
*
|
|
16
|
+
* v2 (#772, `PRESCREEN_SCHEMA`): two outputs. `verdict: full` only for the EXCLUDING checks
|
|
17
|
+
* (hard-block label, open dependency, plan:v1 path floor, >8 predicted files); any finding —
|
|
18
|
+
* a text-floor keyword hit included — sets `review: full`. A text-floor hit alone is a batchable
|
|
19
|
+
* `candidate` reviewed at full depth (#770 Option A), and the text floor scans the change
|
|
20
|
+
* surface only (`floorScanText`: reference sections/lines and provenance clauses removed).
|
|
21
|
+
*
|
|
16
22
|
* Pure and dependency-free (no `gh`, network, or fs), same discipline as `plan-artifact.ts` and
|
|
17
23
|
* `runstate.ts` — unit-testable directly. Subprocess access (fetching the issue, resolving
|
|
18
24
|
* dependency state, filtering by submitted set) lives in the command layer (`commands/classify.ts`).
|
|
19
25
|
*/
|
|
20
26
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.MAX_DEPENDENCY_REFS = exports.TEXT_FLOOR_PATTERNS = void 0;
|
|
27
|
+
exports.PRESCREEN_SCHEMA = exports.MAX_DEPENDENCY_REFS = exports.TEXT_FLOOR_PATTERNS = void 0;
|
|
22
28
|
exports.stripQuotedSpans = stripQuotedSpans;
|
|
29
|
+
exports.stripReferenceMaterial = stripReferenceMaterial;
|
|
30
|
+
exports.floorScanText = floorScanText;
|
|
23
31
|
exports.extractDependencyRefs = extractDependencyRefs;
|
|
24
32
|
exports.prescreenIssue = prescreenIssue;
|
|
25
33
|
const hard_block_labels_1 = require("./hard-block-labels");
|
|
@@ -115,7 +123,10 @@ const MAX_QUOTED_SPAN = 120;
|
|
|
115
123
|
* issues are rejected by text-floor alone, including genuine risk-floor cases
|
|
116
124
|
* (#3403 `terraform`, #3901 `authorization`). That change would have gutted the
|
|
117
125
|
* deterministic rejection rate the pre-screen exists to provide, and #538's
|
|
118
|
-
* cost saving with it.
|
|
126
|
+
* cost saving with it. (#772 later made that move deliberately — but not as
|
|
127
|
+
* "advisory": a text-floor hit still costs no model call and now carries
|
|
128
|
+
* `review: full`, so the genuine risk-floor cases are reviewed at full depth
|
|
129
|
+
* inside a batch instead of being excluded from one. See `PRESCREEN_SCHEMA`.)
|
|
119
130
|
*
|
|
120
131
|
* Stripping quoted spans, by contrast, leaves all 15 fixture verdicts
|
|
121
132
|
* unchanged — the true positives name their risk surface in prose, not in
|
|
@@ -131,6 +142,166 @@ function stripQuotedSpans(text) {
|
|
|
131
142
|
.replace(new RegExp(`"[^"\\n]{0,${MAX_QUOTED_SPAN}}"`, 'g'), ' ')
|
|
132
143
|
.replace(new RegExp(`\`[^\`\\n]{0,${MAX_QUOTED_SPAN}}\``, 'g'), ' ');
|
|
133
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* #772: markdown section headings whose content is reference/provenance material, not the change
|
|
147
|
+
* surface — the whole section (to the next heading of the same or higher level) is dropped before
|
|
148
|
+
* the text floor runs. `Related`/`Context`/`Background` are the sections #772 names explicitly.
|
|
149
|
+
* A denylist on purpose: real issue bodies use arbitrary headings for their scope ("Problem",
|
|
150
|
+
* "What the user sees", "Fix"), so an allowlist of scope/requirements/acceptance headings would
|
|
151
|
+
* silently drop genuine scope. Matched against the WHOLE normalised heading text — "## Background
|
|
152
|
+
* jobs" or "## Origin validation" is scope, not reference material, and stays scanned.
|
|
153
|
+
*/
|
|
154
|
+
const IGNORED_SECTION_HEADING_RE = /^(?:related(?:\s+(?:issues?|prs?|work|links?|tickets?))?|references?|see\s+also|links|context|background|provenance|origin)$/i;
|
|
155
|
+
/**
|
|
156
|
+
* ATX markdown heading: 0–3 spaces, 1–6 `#`, then (optionally) whitespace + the heading text and an
|
|
157
|
+
* optional closing `#` run preceded by whitespace (CommonMark).
|
|
158
|
+
*/
|
|
159
|
+
const HEADING_RE = /^[ \t]{0,3}(#{1,6})(?:[ \t]+([^\n]*))?$/;
|
|
160
|
+
/** A fenced code block delimiter — a `#` line inside a fence is a shell comment, not a heading. */
|
|
161
|
+
const FENCE_RE = /^\s{0,3}(?:```|~~~)/;
|
|
162
|
+
/** Characters trimmed from the end of a heading: whitespace, `:`, emphasis, and a CommonMark closing `#` run. */
|
|
163
|
+
const HEADING_TRAILING_CHARS = ' \t\r\n\f\v:*_#';
|
|
164
|
+
/** Heading text with leading emoji/emphasis/punctuation and trailing `:`/emphasis/closing `#`s removed. */
|
|
165
|
+
function normaliseHeading(text) {
|
|
166
|
+
// Trailing trim by loop, not `/[…]+$/` — that regex is quadratic on a long whitespace run
|
|
167
|
+
// (untrusted issue body; #772 security review).
|
|
168
|
+
const trimmed = text.replace(/^[^\p{L}\p{N}]+/u, '');
|
|
169
|
+
let end = trimmed.length;
|
|
170
|
+
while (end > 0 && HEADING_TRAILING_CHARS.includes(trimmed[end - 1]))
|
|
171
|
+
end--;
|
|
172
|
+
return trimmed.slice(0, end);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Line-leading markdown decoration split off before the provenance tests: whitespace, blockquote
|
|
176
|
+
* `>`, list markers (`-`, `*`, `+`, `1.`), task boxes, and emphasis (`**`, `_`). Deliberately
|
|
177
|
+
* conservative — anything it does not strip only makes a provenance line LESS likely to be
|
|
178
|
+
* recognised, which errs toward scanning (the safe direction for a risk floor).
|
|
179
|
+
*/
|
|
180
|
+
const LINE_DECORATION_RE = /^(?:\s|>|[-*+](?=\s)|\d+[.)](?=\s)|\[[ xX]\]|\*\*|__|\*|_)*/;
|
|
181
|
+
/** Compile a phrase list into one alternation (each phrase escaped, whitespace-insensitive). */
|
|
182
|
+
function alternation(phrases) {
|
|
183
|
+
return phrases.map((p) => phrase(p).replace(/-/g, '[\\s-]?')).join('|');
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* #772: a line that STARTS with one of these markers is a pure reference line — "Parent: #770",
|
|
187
|
+
* "Related: #12", "Refs: #1709 …", "See also #10" — and is dropped whole. `related` needs a colon
|
|
188
|
+
* or a ref after it: "Related billing webhooks also fail" is scope prose.
|
|
189
|
+
*/
|
|
190
|
+
const REFERENCE_LINE_LEADS = [
|
|
191
|
+
'related:',
|
|
192
|
+
'related to #',
|
|
193
|
+
'related #',
|
|
194
|
+
'parent:',
|
|
195
|
+
'refs:',
|
|
196
|
+
'ref:',
|
|
197
|
+
'see also',
|
|
198
|
+
'provenance:',
|
|
199
|
+
];
|
|
200
|
+
const REFERENCE_LINE_RE = new RegExp(`^(?:${REFERENCE_LINE_LEADS.map((l) => phrase(l).replace(/:$/, '\\s*:')).join('|')})`, 'i');
|
|
201
|
+
/**
|
|
202
|
+
* #772: provenance phrases — where the issue came from, not what it touches ("Found by the #4103
|
|
203
|
+
* security review", "Follow-up to #4314", "Split from #99"). A clause that OPENS a sentence (line
|
|
204
|
+
* start, or after `.`/`;`/`!`/`?`) with one of these is stripped to the end of its clause (`.`, `;`,
|
|
205
|
+
* `!`, `?`, `,` or a dash followed by whitespace, or end of line) — so "Found by the #4103 review.
|
|
206
|
+
* Rotate the Stripe secrets." keeps the second sentence. Mid-sentence the same words are ordinary
|
|
207
|
+
* prose ("the token leak is found during checkout") and are left alone. "found in"/"reported in"
|
|
208
|
+
* are NOT provenance — they say where the bug is.
|
|
209
|
+
*/
|
|
210
|
+
const PROVENANCE_LEADS = [
|
|
211
|
+
'found by',
|
|
212
|
+
'found during',
|
|
213
|
+
'discovered by',
|
|
214
|
+
'discovered during',
|
|
215
|
+
'discovered while',
|
|
216
|
+
'surfaced by',
|
|
217
|
+
'surfaced during',
|
|
218
|
+
'spotted by',
|
|
219
|
+
'reported by',
|
|
220
|
+
'filed while',
|
|
221
|
+
'filed from',
|
|
222
|
+
'filed during',
|
|
223
|
+
'follow-up to',
|
|
224
|
+
'follow-up of',
|
|
225
|
+
'split from',
|
|
226
|
+
'split out of',
|
|
227
|
+
'split off from',
|
|
228
|
+
'spun off from',
|
|
229
|
+
'spun out of',
|
|
230
|
+
];
|
|
231
|
+
const PROVENANCE_CLAUSE_RE = new RegExp(`(^|[.;!?]\\s+)(?:${alternation(PROVENANCE_LEADS)})\\b.*?(?=[.;!?,—–](?:\\s|$)|\\s-\\s|$)`, 'gi');
|
|
232
|
+
/**
|
|
233
|
+
* A line carrying nothing but references: URLs, bare `#N` / `owner/repo#N` refs, and separators.
|
|
234
|
+
* A markdown link keeps its TEXT ("[Migrate billing tables](…)" is scope) — only the target is
|
|
235
|
+
* erased. Checked by erasing every reference and separator and testing for an empty remainder.
|
|
236
|
+
*/
|
|
237
|
+
function isLinkOnlyLine(line) {
|
|
238
|
+
const remainder = line
|
|
239
|
+
.replace(/\[([^[\]\n]*)\]\([^()\n]*\)/g, ' $1 ')
|
|
240
|
+
.replace(/<?https?:\/\/[^\s>)]+>?/g, ' ')
|
|
241
|
+
.replace(/(?<![\w.-])[\w.-]+\/[\w.-]+#\d+\b/g, ' ')
|
|
242
|
+
.replace(/#\d+\b/g, ' ')
|
|
243
|
+
.replace(/[\s\-*+>•|,;:/()[\]&.–—]|\band\b|\bor\b/gi, '');
|
|
244
|
+
return remainder === '' && /\S/.test(line);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* #772: the issue body with reference material removed — the part a text-floor keyword may
|
|
248
|
+
* legitimately fire on. Removes: sections under an {@link IGNORED_SECTION_HEADING_RE} heading
|
|
249
|
+
* (fence-aware — a `#` comment inside a code block is never a heading), reference lines
|
|
250
|
+
* ({@link REFERENCE_LINE_RE}), link-only lines, and sentence-opening provenance clauses
|
|
251
|
+
* ({@link PROVENANCE_CLAUSE_RE}). Quoted spans are handled separately by {@link stripQuotedSpans}
|
|
252
|
+
* (#627). Pure; line count is preserved (dropped lines become empty) so `stripQuotedSpans`'s
|
|
253
|
+
* same-line bound behaves exactly as before.
|
|
254
|
+
*/
|
|
255
|
+
function stripReferenceMaterial(body) {
|
|
256
|
+
const out = [];
|
|
257
|
+
/** Heading level of the ignored section currently being skipped, or null. */
|
|
258
|
+
let skipLevel = null;
|
|
259
|
+
let inFence = false;
|
|
260
|
+
for (const line of body.split('\n')) {
|
|
261
|
+
if (FENCE_RE.test(line)) {
|
|
262
|
+
inFence = !inFence;
|
|
263
|
+
out.push(skipLevel === null ? line : '');
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
const heading = inFence ? null : HEADING_RE.exec(line);
|
|
267
|
+
if (heading) {
|
|
268
|
+
const level = heading[1].length;
|
|
269
|
+
if (skipLevel !== null && level > skipLevel) {
|
|
270
|
+
out.push('');
|
|
271
|
+
continue; // a sub-heading inside an ignored section stays ignored
|
|
272
|
+
}
|
|
273
|
+
skipLevel = IGNORED_SECTION_HEADING_RE.test(normaliseHeading(heading[2] ?? ''))
|
|
274
|
+
? level
|
|
275
|
+
: null;
|
|
276
|
+
out.push(skipLevel === null ? line : '');
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
if (skipLevel !== null) {
|
|
280
|
+
out.push('');
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
if (inFence) {
|
|
284
|
+
out.push(line);
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
const decoration = LINE_DECORATION_RE.exec(line)?.[0] ?? '';
|
|
288
|
+
const content = line.slice(decoration.length);
|
|
289
|
+
if (REFERENCE_LINE_RE.test(content) || isLinkOnlyLine(content)) {
|
|
290
|
+
out.push('');
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
out.push(decoration + content.replace(PROVENANCE_CLAUSE_RE, '$1 '));
|
|
294
|
+
}
|
|
295
|
+
return out.join('\n');
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* The exact text the text floor scans (#772): title + section/provenance-filtered body + label
|
|
299
|
+
* names, with quoted spans blanked (#627). Exported so measurement tooling
|
|
300
|
+
* (`scripts/prescreen-backlog-measure.mjs`) and tests see precisely what the rule sees.
|
|
301
|
+
*/
|
|
302
|
+
function floorScanText(title, body, labels) {
|
|
303
|
+
return stripQuotedSpans(`${title}\n${stripReferenceMaterial(body)}\n${labels.join(' ')}`);
|
|
304
|
+
}
|
|
134
305
|
/** `Depends on #N` references resolved per issue; each costs a `gh` call downstream (command layer), same rationale as `MAX_ISSUE_SELECTION` (`issue-selection.ts`). */
|
|
135
306
|
exports.MAX_DEPENDENCY_REFS = 32;
|
|
136
307
|
/** `Depends on #N` (case-insensitive) — the same phrasing gate-issue and the classifier dossier parse. */
|
|
@@ -154,6 +325,20 @@ function extractDependencyRefs(text) {
|
|
|
154
325
|
}
|
|
155
326
|
return refs;
|
|
156
327
|
}
|
|
328
|
+
/**
|
|
329
|
+
* Version of the `classify prescreen` JSON contract (#772). v1 (implicit, pre-#772): any finding,
|
|
330
|
+
* text-floor included, meant `verdict: full`. v2: a text-floor hit is `verdict: candidate` +
|
|
331
|
+
* `review: full`; `verdict: full` is reserved for the checks that genuinely exclude an issue from
|
|
332
|
+
* a batch (hard-block label, open dependency, plan:v1 path floor, >8 predicted files).
|
|
333
|
+
*/
|
|
334
|
+
exports.PRESCREEN_SCHEMA = 'prescreen:v2';
|
|
335
|
+
/** Checks whose hit excludes the issue from batching outright (`verdict: full`). */
|
|
336
|
+
const EXCLUDING_CHECKS = new Set([
|
|
337
|
+
'hard-block-label',
|
|
338
|
+
'open-dependency',
|
|
339
|
+
'path-floor',
|
|
340
|
+
'file-count',
|
|
341
|
+
]);
|
|
157
342
|
/** Predicted files count above which RFC-0001 E.2 rule 5 ("Predicted files > 8") fires. */
|
|
158
343
|
const MAX_PREDICTED_FILES = 8;
|
|
159
344
|
/**
|
|
@@ -178,8 +363,8 @@ function sanitize(value) {
|
|
|
178
363
|
: cleaned;
|
|
179
364
|
}
|
|
180
365
|
/**
|
|
181
|
-
* Run every deterministic check, in order, and record every hit —
|
|
182
|
-
*
|
|
366
|
+
* Run every deterministic check, in order, and record every hit — an excluding hit decides
|
|
367
|
+
* `verdict`, any hit decides `review`, and the caller (and the rationale a consumer posts) gets the full list, matching the existing
|
|
183
368
|
* "a verdict may hit several" precedent in `issue-cycle-classifier.ds.md`.
|
|
184
369
|
*/
|
|
185
370
|
function prescreenIssue(input) {
|
|
@@ -191,7 +376,7 @@ function prescreenIssue(input) {
|
|
|
191
376
|
message: `Carries hard-block label '${sanitize(hardBlockLabel)}'.`,
|
|
192
377
|
});
|
|
193
378
|
}
|
|
194
|
-
const text =
|
|
379
|
+
const text = floorScanText(input.title, input.body, input.labels);
|
|
195
380
|
for (const pattern of exports.TEXT_FLOOR_PATTERNS) {
|
|
196
381
|
const hit = pattern.match(text);
|
|
197
382
|
if (hit !== null) {
|
|
@@ -220,6 +405,10 @@ function prescreenIssue(input) {
|
|
|
220
405
|
message: `Depends on #${dep}, which is open and outside the submitted set (rule9-open-dependency).`,
|
|
221
406
|
});
|
|
222
407
|
}
|
|
223
|
-
return {
|
|
408
|
+
return {
|
|
409
|
+
verdict: reasons.some((r) => EXCLUDING_CHECKS.has(r.check)) ? 'full' : 'candidate',
|
|
410
|
+
review: reasons.length > 0 ? 'full' : 'light',
|
|
411
|
+
reasons,
|
|
412
|
+
};
|
|
224
413
|
}
|
|
225
414
|
//# sourceMappingURL=prescreen.js.map
|
package/dist/prescreen.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prescreen.js","sourceRoot":"","sources":["../src/prescreen.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"prescreen.js","sourceRoot":"","sources":["../src/prescreen.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code collector (#769): per-message usage from the session
|
|
3
|
+
* transcripts under `~/.claude/projects/<slug>/`.
|
|
4
|
+
*
|
|
5
|
+
* Layout read (never written):
|
|
6
|
+
* <slug>/<sessionId>.jsonl — a top-level session
|
|
7
|
+
* <slug>/<sessionId>/subagents/agent-<id>.jsonl — its subagents (sidechains)
|
|
8
|
+
* <slug>/<sessionId>/subagents/agent-<id>.meta.json — subagent type/description
|
|
9
|
+
*
|
|
10
|
+
* Claude Code writes one transcript line per content block, each repeating
|
|
11
|
+
* the message's `usage`; rows are deduplicated on `message.id:requestId`
|
|
12
|
+
* (ccusage's key) so a multi-block message is counted once — also across
|
|
13
|
+
* files, since a subagent's messages must not be double-counted if the
|
|
14
|
+
* parent transcript ever echoes them.
|
|
15
|
+
*/
|
|
16
|
+
import type { LimitEvent, UsageRow } from './types';
|
|
17
|
+
export interface ClaudeCollectOptions {
|
|
18
|
+
/** `~/.claude/projects` (or `$CLAUDE_CONFIG_DIR/projects`). */
|
|
19
|
+
projectsDir: string;
|
|
20
|
+
/** Only messages at/after this time are collected; files older than it are skipped unread. */
|
|
21
|
+
sinceMs: number;
|
|
22
|
+
/** Only messages before this time (default: no upper bound). */
|
|
23
|
+
untilMs?: number;
|
|
24
|
+
host: string;
|
|
25
|
+
}
|
|
26
|
+
export interface ClaudeCollectResult {
|
|
27
|
+
rows: UsageRow[];
|
|
28
|
+
limits: LimitEvent[];
|
|
29
|
+
files: number;
|
|
30
|
+
}
|
|
31
|
+
/** Default Claude Code projects dir, honouring `CLAUDE_CONFIG_DIR`. */
|
|
32
|
+
export declare function defaultClaudeProjectsDir(env?: NodeJS.ProcessEnv): string;
|
|
33
|
+
interface TranscriptFile {
|
|
34
|
+
file: string;
|
|
35
|
+
/** Set for a subagent transcript: the parent session id (the directory name). */
|
|
36
|
+
parentSession: string | null;
|
|
37
|
+
title: string | null;
|
|
38
|
+
}
|
|
39
|
+
/** Every transcript modified at/after `sinceMs` — the incremental prefilter. */
|
|
40
|
+
export declare function listClaudeTranscripts(projectsDir: string, sinceMs: number): TranscriptFile[];
|
|
41
|
+
/**
|
|
42
|
+
* Parse the transcripts into usage rows and limit events. Read-only; files
|
|
43
|
+
* that cannot be read are skipped (their rows are simply absent).
|
|
44
|
+
*/
|
|
45
|
+
export declare function collectClaude(opts: ClaudeCollectOptions): ClaudeCollectResult;
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=collect-claude.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collect-claude.d.ts","sourceRoot":"","sources":["../../src/usage/collect-claude.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAepD,MAAM,WAAW,oBAAoB;IACnC,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB,8FAA8F;IAC9F,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,uEAAuE;AACvE,wBAAgB,wBAAwB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAGrF;AAED,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,iFAAiF;IACjF,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAcD,gFAAgF;AAChF,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,EAAE,CAsB5F;AAsBD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,oBAAoB,GAAG,mBAAmB,CAgH7E"}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Claude Code collector (#769): per-message usage from the session
|
|
4
|
+
* transcripts under `~/.claude/projects/<slug>/`.
|
|
5
|
+
*
|
|
6
|
+
* Layout read (never written):
|
|
7
|
+
* <slug>/<sessionId>.jsonl — a top-level session
|
|
8
|
+
* <slug>/<sessionId>/subagents/agent-<id>.jsonl — its subagents (sidechains)
|
|
9
|
+
* <slug>/<sessionId>/subagents/agent-<id>.meta.json — subagent type/description
|
|
10
|
+
*
|
|
11
|
+
* Claude Code writes one transcript line per content block, each repeating
|
|
12
|
+
* the message's `usage`; rows are deduplicated on `message.id:requestId`
|
|
13
|
+
* (ccusage's key) so a multi-block message is counted once — also across
|
|
14
|
+
* files, since a subagent's messages must not be double-counted if the
|
|
15
|
+
* parent transcript ever echoes them.
|
|
16
|
+
*/
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
+
}) : function(o, v) {
|
|
31
|
+
o["default"] = v;
|
|
32
|
+
});
|
|
33
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
+
var ownKeys = function(o) {
|
|
35
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
+
var ar = [];
|
|
37
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
+
return ar;
|
|
39
|
+
};
|
|
40
|
+
return ownKeys(o);
|
|
41
|
+
};
|
|
42
|
+
return function (mod) {
|
|
43
|
+
if (mod && mod.__esModule) return mod;
|
|
44
|
+
var result = {};
|
|
45
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
+
__setModuleDefault(result, mod);
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
})();
|
|
50
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
+
exports.defaultClaudeProjectsDir = defaultClaudeProjectsDir;
|
|
52
|
+
exports.listClaudeTranscripts = listClaudeTranscripts;
|
|
53
|
+
exports.collectClaude = collectClaude;
|
|
54
|
+
const fs = __importStar(require("node:fs"));
|
|
55
|
+
const os = __importStar(require("node:os"));
|
|
56
|
+
const path = __importStar(require("node:path"));
|
|
57
|
+
const util_1 = require("./util");
|
|
58
|
+
/** Claude Code's placeholder model on locally synthesized (API-error) messages — carries zero tokens. */
|
|
59
|
+
const SYNTHETIC_MODEL = '<synthetic>';
|
|
60
|
+
/** Default Claude Code projects dir, honouring `CLAUDE_CONFIG_DIR`. */
|
|
61
|
+
function defaultClaudeProjectsDir(env = process.env) {
|
|
62
|
+
const base = env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), '.claude');
|
|
63
|
+
return path.join(base, 'projects');
|
|
64
|
+
}
|
|
65
|
+
function subagentTitle(jsonlFile) {
|
|
66
|
+
try {
|
|
67
|
+
const meta = JSON.parse(fs.readFileSync(jsonlFile.replace(/\.jsonl$/, '.meta.json'), 'utf-8'));
|
|
68
|
+
const parts = [meta?.agentType, meta?.description].filter((p) => typeof p === 'string' && p.length > 0);
|
|
69
|
+
return parts.length > 0 ? (0, util_1.oneLine)(parts.join(': '), 120) : null;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** Every transcript modified at/after `sinceMs` — the incremental prefilter. */
|
|
76
|
+
function listClaudeTranscripts(projectsDir, sinceMs) {
|
|
77
|
+
const out = [];
|
|
78
|
+
const fresh = (file) => ((0, util_1.mtimeMs)(file) ?? 0) >= sinceMs;
|
|
79
|
+
for (const project of (0, util_1.safeReaddir)(projectsDir)) {
|
|
80
|
+
if (!project.isDirectory())
|
|
81
|
+
continue;
|
|
82
|
+
const projectDir = path.join(projectsDir, project.name);
|
|
83
|
+
for (const entry of (0, util_1.safeReaddir)(projectDir)) {
|
|
84
|
+
const full = path.join(projectDir, entry.name);
|
|
85
|
+
if (entry.isFile() && entry.name.endsWith('.jsonl')) {
|
|
86
|
+
if (fresh(full))
|
|
87
|
+
out.push({ file: full, parentSession: null, title: null });
|
|
88
|
+
}
|
|
89
|
+
else if (entry.isDirectory()) {
|
|
90
|
+
const subDir = path.join(full, 'subagents');
|
|
91
|
+
for (const sub of (0, util_1.safeReaddir)(subDir)) {
|
|
92
|
+
const subFile = path.join(subDir, sub.name);
|
|
93
|
+
if (sub.isFile() && sub.name.endsWith('.jsonl') && fresh(subFile)) {
|
|
94
|
+
out.push({ file: subFile, parentSession: entry.name, title: subagentTitle(subFile) });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return out;
|
|
101
|
+
}
|
|
102
|
+
function textOf(content) {
|
|
103
|
+
if (typeof content === 'string')
|
|
104
|
+
return content;
|
|
105
|
+
if (!Array.isArray(content))
|
|
106
|
+
return '';
|
|
107
|
+
return content
|
|
108
|
+
.map((block) => block && typeof block === 'object' && typeof block.text === 'string'
|
|
109
|
+
? block.text
|
|
110
|
+
: '')
|
|
111
|
+
.join(' ');
|
|
112
|
+
}
|
|
113
|
+
/** HTTP status embedded in an API-error message (`API Error: 429 …`), else null. */
|
|
114
|
+
function statusOf(record, text) {
|
|
115
|
+
const explicit = record.apiErrorStatus ?? record.status;
|
|
116
|
+
if (typeof explicit === 'number')
|
|
117
|
+
return explicit;
|
|
118
|
+
const match = text.match(/\b(4\d\d|5\d\d)\b/);
|
|
119
|
+
return match ? Number.parseInt(match[1], 10) : null;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Parse the transcripts into usage rows and limit events. Read-only; files
|
|
123
|
+
* that cannot be read are skipped (their rows are simply absent).
|
|
124
|
+
*/
|
|
125
|
+
function collectClaude(opts) {
|
|
126
|
+
const rows = [];
|
|
127
|
+
const limits = [];
|
|
128
|
+
// key → the row already emitted for that message (see the repeat handling below)
|
|
129
|
+
const seen = new Map();
|
|
130
|
+
const untilMs = opts.untilMs ?? Number.POSITIVE_INFINITY;
|
|
131
|
+
const files = listClaudeTranscripts(opts.projectsDir, opts.sinceMs);
|
|
132
|
+
for (const transcript of files) {
|
|
133
|
+
const fileSession = path.basename(transcript.file, '.jsonl');
|
|
134
|
+
(0, util_1.forEachLine)(transcript.file, (line) => {
|
|
135
|
+
// Cheap prefilter: only assistant records carry usage or API errors.
|
|
136
|
+
if (!line.includes('"assistant"'))
|
|
137
|
+
return;
|
|
138
|
+
let record;
|
|
139
|
+
try {
|
|
140
|
+
record = JSON.parse(line);
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (record.type !== 'assistant')
|
|
146
|
+
return;
|
|
147
|
+
const ts = typeof record.timestamp === 'string' ? record.timestamp : null;
|
|
148
|
+
const tsMs = ts ? Date.parse(ts) : Number.NaN;
|
|
149
|
+
if (!ts || Number.isNaN(tsMs) || tsMs < opts.sinceMs || tsMs >= untilMs)
|
|
150
|
+
return;
|
|
151
|
+
const message = (record.message ?? {});
|
|
152
|
+
const sessionId = typeof record.sessionId === 'string' && record.sessionId ? record.sessionId : fileSession;
|
|
153
|
+
const agentId = typeof record.agentId === 'string' && record.agentId ? record.agentId : null;
|
|
154
|
+
const isSubagent = transcript.parentSession !== null || record.isSidechain === true;
|
|
155
|
+
const session_id = isSubagent && agentId ? `${sessionId}/${agentId}` : sessionId;
|
|
156
|
+
const parent_session_id = isSubagent
|
|
157
|
+
? (transcript.parentSession ?? (agentId ? sessionId : null))
|
|
158
|
+
: null;
|
|
159
|
+
if (record.isApiErrorMessage === true) {
|
|
160
|
+
const text = textOf(message.content);
|
|
161
|
+
const error = typeof record.error === 'string' ? record.error : '';
|
|
162
|
+
if (util_1.LIMIT_TEXT_RE.test(text) || /rate_limit|overloaded/i.test(error)) {
|
|
163
|
+
limits.push({
|
|
164
|
+
ts,
|
|
165
|
+
host: opts.host,
|
|
166
|
+
source: 'claude-code',
|
|
167
|
+
provider: 'anthropic',
|
|
168
|
+
session_id,
|
|
169
|
+
unit: null,
|
|
170
|
+
status: statusOf(record, text),
|
|
171
|
+
detail: (0, util_1.oneLine)(text || error),
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const usage = message.usage;
|
|
177
|
+
if (!usage || typeof usage !== 'object')
|
|
178
|
+
return;
|
|
179
|
+
const model = typeof message.model === 'string' && message.model ? message.model : null;
|
|
180
|
+
if (model === SYNTHETIC_MODEL)
|
|
181
|
+
return;
|
|
182
|
+
const messageId = typeof message.id === 'string' ? message.id : null;
|
|
183
|
+
const requestId = typeof record.requestId === 'string' ? record.requestId : null;
|
|
184
|
+
const key = messageId
|
|
185
|
+
? `${messageId}:${requestId ?? ''}`
|
|
186
|
+
: typeof record.uuid === 'string'
|
|
187
|
+
? `uuid:${record.uuid}`
|
|
188
|
+
: null;
|
|
189
|
+
const input = (0, util_1.count)(usage.input_tokens);
|
|
190
|
+
const output = (0, util_1.count)(usage.output_tokens);
|
|
191
|
+
const cache_read = (0, util_1.count)(usage.cache_read_input_tokens);
|
|
192
|
+
const cache_write = (0, util_1.count)(usage.cache_creation_input_tokens);
|
|
193
|
+
const prior = key ? seen.get(key) : undefined;
|
|
194
|
+
if (prior) {
|
|
195
|
+
// A repeat line of an already-counted message. Earlier content-block
|
|
196
|
+
// lines carry a PARTIAL `output_tokens` (streaming); later ones the
|
|
197
|
+
// final count — so keep the max of each field, never the first line's.
|
|
198
|
+
prior.input = Math.max(prior.input, input);
|
|
199
|
+
prior.output = Math.max(prior.output, output);
|
|
200
|
+
prior.cache_read = Math.max(prior.cache_read, cache_read);
|
|
201
|
+
prior.cache_write = Math.max(prior.cache_write, cache_write);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
const cwd = typeof record.cwd === 'string' ? record.cwd : null;
|
|
205
|
+
const branch = typeof record.gitBranch === 'string' && record.gitBranch ? record.gitBranch : null;
|
|
206
|
+
const issue = (0, util_1.issueFromRef)(branch) ?? (0, util_1.issueFromRef)(cwd ? path.basename(cwd) : null);
|
|
207
|
+
const row = {
|
|
208
|
+
ts,
|
|
209
|
+
host: opts.host,
|
|
210
|
+
provider: 'anthropic',
|
|
211
|
+
model,
|
|
212
|
+
input,
|
|
213
|
+
output,
|
|
214
|
+
reasoning: 0,
|
|
215
|
+
cache_read,
|
|
216
|
+
cache_write,
|
|
217
|
+
cost_usd: typeof record.costUSD === 'number' ? record.costUSD : null,
|
|
218
|
+
source: 'claude-code',
|
|
219
|
+
session_id,
|
|
220
|
+
parent_session_id,
|
|
221
|
+
title: transcript.title,
|
|
222
|
+
cwd,
|
|
223
|
+
project: (0, util_1.projectOf)(cwd),
|
|
224
|
+
branch,
|
|
225
|
+
issue,
|
|
226
|
+
issue_source: issue === null ? null : 'branch',
|
|
227
|
+
batch: null,
|
|
228
|
+
unit: null,
|
|
229
|
+
};
|
|
230
|
+
if (key)
|
|
231
|
+
seen.set(key, row);
|
|
232
|
+
rows.push(row);
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
return { rows, limits, files: files.length };
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=collect-claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collect-claude.js","sourceRoot":"","sources":["../../src/usage/collect-claude.ts"],"names":[],"mappings":"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"}
|