@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.
Files changed (57) hide show
  1. package/README.md +73 -6
  2. package/dist/batch-suite-runner.d.ts +30 -6
  3. package/dist/batch-suite-runner.d.ts.map +1 -1
  4. package/dist/batch-suite-runner.js +86 -25
  5. package/dist/batch-suite-runner.js.map +1 -1
  6. package/dist/capability.d.ts +8 -0
  7. package/dist/capability.d.ts.map +1 -1
  8. package/dist/capability.js +16 -1
  9. package/dist/capability.js.map +1 -1
  10. package/dist/cli.js +2 -0
  11. package/dist/cli.js.map +1 -1
  12. package/dist/commands/classify.d.ts.map +1 -1
  13. package/dist/commands/classify.js +8 -2
  14. package/dist/commands/classify.js.map +1 -1
  15. package/dist/commands/run.d.ts.map +1 -1
  16. package/dist/commands/run.js +10 -1
  17. package/dist/commands/run.js.map +1 -1
  18. package/dist/commands/sched.d.ts.map +1 -1
  19. package/dist/commands/sched.js +35 -0
  20. package/dist/commands/sched.js.map +1 -1
  21. package/dist/commands/usage.d.ts +84 -0
  22. package/dist/commands/usage.d.ts.map +1 -0
  23. package/dist/commands/usage.js +395 -0
  24. package/dist/commands/usage.js.map +1 -0
  25. package/dist/prescreen.d.ts +48 -5
  26. package/dist/prescreen.d.ts.map +1 -1
  27. package/dist/prescreen.js +195 -6
  28. package/dist/prescreen.js.map +1 -1
  29. package/dist/usage/collect-claude.d.ts +47 -0
  30. package/dist/usage/collect-claude.d.ts.map +1 -0
  31. package/dist/usage/collect-claude.js +237 -0
  32. package/dist/usage/collect-claude.js.map +1 -0
  33. package/dist/usage/collect-dispatch.d.ts +73 -0
  34. package/dist/usage/collect-dispatch.d.ts.map +1 -0
  35. package/dist/usage/collect-dispatch.js +297 -0
  36. package/dist/usage/collect-dispatch.js.map +1 -0
  37. package/dist/usage/collect-opencode.d.ts +74 -0
  38. package/dist/usage/collect-opencode.d.ts.map +1 -0
  39. package/dist/usage/collect-opencode.js +198 -0
  40. package/dist/usage/collect-opencode.js.map +1 -0
  41. package/dist/usage/host-session.d.ts +63 -0
  42. package/dist/usage/host-session.d.ts.map +1 -0
  43. package/dist/usage/host-session.js +325 -0
  44. package/dist/usage/host-session.js.map +1 -0
  45. package/dist/usage/ledger.d.ts +87 -0
  46. package/dist/usage/ledger.d.ts.map +1 -0
  47. package/dist/usage/ledger.js +268 -0
  48. package/dist/usage/ledger.js.map +1 -0
  49. package/dist/usage/types.d.ts +80 -0
  50. package/dist/usage/types.d.ts.map +1 -0
  51. package/dist/usage/types.js +11 -0
  52. package/dist/usage/types.js.map +1 -0
  53. package/dist/usage/util.d.ts +36 -0
  54. package/dist/usage/util.d.ts.map +1 -0
  55. package/dist/usage/util.js +158 -0
  56. package/dist/usage/util.js.map +1 -0
  57. 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 — first hit decides `verdict`,
182
- * but the caller (and the rationale a consumer posts) gets the full list, matching the existing
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 = stripQuotedSpans(`${input.title}\n${input.body}\n${input.labels.join(' ')}`);
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 { verdict: reasons.length > 0 ? 'full' : 'candidate', reasons };
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
@@ -1 +1 @@
1
- {"version":3,"file":"prescreen.js","sourceRoot":"","sources":["../src/prescreen.ts"],"names":[],"mappings":"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"}
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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"}