@ai-dossier/cli 0.51.0 → 0.53.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 +38 -2
- 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/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/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
|
@@ -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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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scheduler + dossier-run attribution for the usage ledger (#769).
|
|
3
|
+
*
|
|
4
|
+
* Tokens are NOT read from here: every sched-dispatched agent's tokens are
|
|
5
|
+
* already in the Claude Code transcripts / opencode.db on the same host, and
|
|
6
|
+
* `runs.jsonl`'s token columns would double-count them. What these sources
|
|
7
|
+
* add is *attribution*:
|
|
8
|
+
*
|
|
9
|
+
* - sched dispatch logs (`~/.dossier/sched/<project>/runs/*.log`) name the
|
|
10
|
+
* unit/batch/issue in their filename and carry the agent's own session id
|
|
11
|
+
* in the stream (opencode `sessionID`, claude `session_id`) → an
|
|
12
|
+
* authoritative session → issue/batch join.
|
|
13
|
+
* - sched `events.jsonl` records dispatch-failure/-unhealthy walls (#629/#505)
|
|
14
|
+
* → limit events.
|
|
15
|
+
* - `runs.jsonl` entries written with `session_id` (#769) → how many
|
|
16
|
+
* `ai-dossier run` invocations each session made.
|
|
17
|
+
*/
|
|
18
|
+
import type { LimitEvent, UsageRow } from './types';
|
|
19
|
+
/** A session that a sched dispatch log proves belongs to a unit. */
|
|
20
|
+
export interface DispatchRef {
|
|
21
|
+
session_id: string;
|
|
22
|
+
unit: string;
|
|
23
|
+
issue: number | null;
|
|
24
|
+
batch: string | null;
|
|
25
|
+
/** `member` | `fix` | `tail` | `report` | `issue` | `other`. */
|
|
26
|
+
role: string;
|
|
27
|
+
/** sched project slug (`owner-repo`). */
|
|
28
|
+
project: string;
|
|
29
|
+
/** Model from the dispatch preamble's argv, when it named one. */
|
|
30
|
+
model: string | null;
|
|
31
|
+
log: string;
|
|
32
|
+
}
|
|
33
|
+
/** Filename → unit attribution. Mirrors `packages/sched`'s `unitLogName`-based builders. */
|
|
34
|
+
export declare function parseDispatchLogName(name: string): Pick<DispatchRef, 'unit' | 'issue' | 'batch' | 'role'> | null;
|
|
35
|
+
/**
|
|
36
|
+
* Every agent session in a dispatch log, each with the model of the
|
|
37
|
+
* `sched-dispatch` preamble that precedes it (logs are append-mode: a
|
|
38
|
+
* redispatched unit holds several dispatches, possibly on different agents).
|
|
39
|
+
* Only a record's TOP-LEVEL `sessionID` (opencode) / `session_id` (claude)
|
|
40
|
+
* counts — a tool call's input or output that merely mentions another
|
|
41
|
+
* session id must not attribute that session to this unit.
|
|
42
|
+
*/
|
|
43
|
+
export declare function sessionsIn(content: string): {
|
|
44
|
+
session_id: string;
|
|
45
|
+
model: string | null;
|
|
46
|
+
}[];
|
|
47
|
+
/** Session ids only — see {@link sessionsIn}. */
|
|
48
|
+
export declare function sessionIdsIn(content: string): string[];
|
|
49
|
+
/**
|
|
50
|
+
* session id → dispatch attribution, across every sched project under
|
|
51
|
+
* `schedRoot` (`~/.dossier/sched`). Logs last modified before `sinceMs`
|
|
52
|
+
* cannot hold a session active in the window and are skipped unread.
|
|
53
|
+
*/
|
|
54
|
+
export declare function indexDispatchLogs(schedRoot: string, sinceMs: number): Map<string, DispatchRef>;
|
|
55
|
+
/**
|
|
56
|
+
* Stamp dispatch attribution onto rows in place. A subagent/child session
|
|
57
|
+
* inherits its parent's dispatch (a batch member's opencode child session is
|
|
58
|
+
* still that member's spend). Dispatch attribution replaces the branch
|
|
59
|
+
* heuristic; a row whose store recorded no model falls back to the
|
|
60
|
+
* preamble's model.
|
|
61
|
+
*/
|
|
62
|
+
export declare function applyDispatchIndex(rows: UsageRow[], index: Map<string, DispatchRef>): void;
|
|
63
|
+
/**
|
|
64
|
+
* Provider named by a limit message — sched events record none, but the
|
|
65
|
+
* provider's own wording does (`claude.ai/settings/usage` → anthropic). Null
|
|
66
|
+
* when it cannot be told, so the view compares against every provider.
|
|
67
|
+
*/
|
|
68
|
+
export declare function providerFromText(text: string): string | null;
|
|
69
|
+
/** sched `dispatch-failure` / `dispatch-unhealthy` limit walls in `[sinceMs, untilMs)`. */
|
|
70
|
+
export declare function collectSchedLimitEvents(schedRoot: string, sinceMs: number, untilMs: number, host: string): LimitEvent[];
|
|
71
|
+
/** session id → number of `ai-dossier run` invocations recorded from it in `[sinceMs, untilMs)`. */
|
|
72
|
+
export declare function countDossierRuns(runsLog: string, sinceMs: number, untilMs: number): Map<string, number>;
|
|
73
|
+
//# sourceMappingURL=collect-dispatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collect-dispatch.d.ts","sourceRoot":"","sources":["../../src/usage/collect-dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAMpD,oEAAoE;AACpE,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,4FAA4F;AAC5F,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,GACX,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC,GAAG,IAAI,CAa/D;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EAAE,CAsB1F;AAKD,iDAAiD;AACjD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAEtD;AAmBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAmB9F;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,IAAI,CA6B1F;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM5D;AAED,2FAA2F;AAC3F,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,GACX,UAAU,EAAE,CAkCd;AAED,oGAAoG;AACpG,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAiBrB"}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Scheduler + dossier-run attribution for the usage ledger (#769).
|
|
4
|
+
*
|
|
5
|
+
* Tokens are NOT read from here: every sched-dispatched agent's tokens are
|
|
6
|
+
* already in the Claude Code transcripts / opencode.db on the same host, and
|
|
7
|
+
* `runs.jsonl`'s token columns would double-count them. What these sources
|
|
8
|
+
* add is *attribution*:
|
|
9
|
+
*
|
|
10
|
+
* - sched dispatch logs (`~/.dossier/sched/<project>/runs/*.log`) name the
|
|
11
|
+
* unit/batch/issue in their filename and carry the agent's own session id
|
|
12
|
+
* in the stream (opencode `sessionID`, claude `session_id`) → an
|
|
13
|
+
* authoritative session → issue/batch join.
|
|
14
|
+
* - sched `events.jsonl` records dispatch-failure/-unhealthy walls (#629/#505)
|
|
15
|
+
* → limit events.
|
|
16
|
+
* - `runs.jsonl` entries written with `session_id` (#769) → how many
|
|
17
|
+
* `ai-dossier run` invocations each session made.
|
|
18
|
+
*/
|
|
19
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
22
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
23
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
24
|
+
}
|
|
25
|
+
Object.defineProperty(o, k2, desc);
|
|
26
|
+
}) : (function(o, m, k, k2) {
|
|
27
|
+
if (k2 === undefined) k2 = k;
|
|
28
|
+
o[k2] = m[k];
|
|
29
|
+
}));
|
|
30
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
31
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
32
|
+
}) : function(o, v) {
|
|
33
|
+
o["default"] = v;
|
|
34
|
+
});
|
|
35
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
36
|
+
var ownKeys = function(o) {
|
|
37
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
38
|
+
var ar = [];
|
|
39
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
40
|
+
return ar;
|
|
41
|
+
};
|
|
42
|
+
return ownKeys(o);
|
|
43
|
+
};
|
|
44
|
+
return function (mod) {
|
|
45
|
+
if (mod && mod.__esModule) return mod;
|
|
46
|
+
var result = {};
|
|
47
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
48
|
+
__setModuleDefault(result, mod);
|
|
49
|
+
return result;
|
|
50
|
+
};
|
|
51
|
+
})();
|
|
52
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
|
+
exports.parseDispatchLogName = parseDispatchLogName;
|
|
54
|
+
exports.sessionsIn = sessionsIn;
|
|
55
|
+
exports.sessionIdsIn = sessionIdsIn;
|
|
56
|
+
exports.indexDispatchLogs = indexDispatchLogs;
|
|
57
|
+
exports.applyDispatchIndex = applyDispatchIndex;
|
|
58
|
+
exports.providerFromText = providerFromText;
|
|
59
|
+
exports.collectSchedLimitEvents = collectSchedLimitEvents;
|
|
60
|
+
exports.countDossierRuns = countDossierRuns;
|
|
61
|
+
const fs = __importStar(require("node:fs"));
|
|
62
|
+
const path = __importStar(require("node:path"));
|
|
63
|
+
const sched_1 = require("@ai-dossier/sched");
|
|
64
|
+
const util_1 = require("./util");
|
|
65
|
+
/** Most bytes of one dispatch log scanned for session ids (streams can be large). */
|
|
66
|
+
const MAX_LOG_SCAN_BYTES = 32 * 1024 * 1024;
|
|
67
|
+
/** Filename → unit attribution. Mirrors `packages/sched`'s `unitLogName`-based builders. */
|
|
68
|
+
function parseDispatchLogName(name) {
|
|
69
|
+
let m = name.match(/^batch-(.+)-m\d+-(\d+)\.log$/);
|
|
70
|
+
if (m)
|
|
71
|
+
return { unit: `issue:${m[2]}`, issue: Number(m[2]), batch: m[1], role: 'member' };
|
|
72
|
+
m = name.match(/^batch-(.+)-fix-(\d+)\.log$/);
|
|
73
|
+
if (m)
|
|
74
|
+
return { unit: `issue:${m[2]}`, issue: Number(m[2]), batch: m[1], role: 'fix' };
|
|
75
|
+
m = name.match(/^batch-(.+)-(tail|report)\.log$/);
|
|
76
|
+
if (m)
|
|
77
|
+
return { unit: `batch:${m[1]}`, issue: null, batch: m[1], role: m[2] };
|
|
78
|
+
m = name.match(/^issue-(\d+)\.log$/);
|
|
79
|
+
if (m)
|
|
80
|
+
return { unit: `issue:${m[1]}`, issue: Number(m[1]), batch: null, role: 'issue' };
|
|
81
|
+
if (name.endsWith('.log')) {
|
|
82
|
+
return { unit: name.slice(0, -'.log'.length), issue: null, batch: null, role: 'other' };
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Every agent session in a dispatch log, each with the model of the
|
|
88
|
+
* `sched-dispatch` preamble that precedes it (logs are append-mode: a
|
|
89
|
+
* redispatched unit holds several dispatches, possibly on different agents).
|
|
90
|
+
* Only a record's TOP-LEVEL `sessionID` (opencode) / `session_id` (claude)
|
|
91
|
+
* counts — a tool call's input or output that merely mentions another
|
|
92
|
+
* session id must not attribute that session to this unit.
|
|
93
|
+
*/
|
|
94
|
+
function sessionsIn(content) {
|
|
95
|
+
const found = new Map();
|
|
96
|
+
let model = null;
|
|
97
|
+
for (const line of content.split('\n')) {
|
|
98
|
+
const cmd = (0, sched_1.parsePreambleLine)(line);
|
|
99
|
+
if (cmd) {
|
|
100
|
+
model = (0, sched_1.modelFromCmd)(cmd);
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (!line.includes('"sessionID"') && !line.includes('"session_id"'))
|
|
104
|
+
continue;
|
|
105
|
+
let record;
|
|
106
|
+
try {
|
|
107
|
+
record = JSON.parse(line);
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
const id = record.sessionID ?? record.session_id;
|
|
113
|
+
if (typeof id === 'string' && SESSION_ID_SHAPE.test(id) && !found.has(id)) {
|
|
114
|
+
found.set(id, model);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return [...found].map(([session_id, m]) => ({ session_id, model: m }));
|
|
118
|
+
}
|
|
119
|
+
const SESSION_ID_SHAPE = /^(?:ses_[A-Za-z0-9]+|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/;
|
|
120
|
+
/** Session ids only — see {@link sessionsIn}. */
|
|
121
|
+
function sessionIdsIn(content) {
|
|
122
|
+
return sessionsIn(content).map((s) => s.session_id);
|
|
123
|
+
}
|
|
124
|
+
function readBounded(file) {
|
|
125
|
+
try {
|
|
126
|
+
const size = fs.statSync(file).size;
|
|
127
|
+
if (size <= MAX_LOG_SCAN_BYTES)
|
|
128
|
+
return fs.readFileSync(file, 'utf-8');
|
|
129
|
+
const fd = fs.openSync(file, 'r');
|
|
130
|
+
try {
|
|
131
|
+
const buffer = Buffer.allocUnsafe(MAX_LOG_SCAN_BYTES);
|
|
132
|
+
const read = fs.readSync(fd, buffer, 0, MAX_LOG_SCAN_BYTES, 0);
|
|
133
|
+
return buffer.subarray(0, read).toString('utf-8');
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
fs.closeSync(fd);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* session id → dispatch attribution, across every sched project under
|
|
145
|
+
* `schedRoot` (`~/.dossier/sched`). Logs last modified before `sinceMs`
|
|
146
|
+
* cannot hold a session active in the window and are skipped unread.
|
|
147
|
+
*/
|
|
148
|
+
function indexDispatchLogs(schedRoot, sinceMs) {
|
|
149
|
+
const index = new Map();
|
|
150
|
+
for (const project of (0, util_1.safeReaddir)(schedRoot)) {
|
|
151
|
+
if (!project.isDirectory())
|
|
152
|
+
continue;
|
|
153
|
+
const runsDir = path.join(schedRoot, project.name, 'runs');
|
|
154
|
+
for (const entry of (0, util_1.safeReaddir)(runsDir)) {
|
|
155
|
+
if (!entry.isFile())
|
|
156
|
+
continue;
|
|
157
|
+
const parsed = parseDispatchLogName(entry.name);
|
|
158
|
+
if (!parsed)
|
|
159
|
+
continue;
|
|
160
|
+
const log = path.join(runsDir, entry.name);
|
|
161
|
+
if (((0, util_1.mtimeMs)(log) ?? 0) < sinceMs)
|
|
162
|
+
continue;
|
|
163
|
+
const content = readBounded(log);
|
|
164
|
+
if (!content)
|
|
165
|
+
continue;
|
|
166
|
+
for (const { session_id, model } of sessionsIn(content)) {
|
|
167
|
+
index.set(session_id, { session_id, ...parsed, project: project.name, model, log });
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return index;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Stamp dispatch attribution onto rows in place. A subagent/child session
|
|
175
|
+
* inherits its parent's dispatch (a batch member's opencode child session is
|
|
176
|
+
* still that member's spend). Dispatch attribution replaces the branch
|
|
177
|
+
* heuristic; a row whose store recorded no model falls back to the
|
|
178
|
+
* preamble's model.
|
|
179
|
+
*/
|
|
180
|
+
function applyDispatchIndex(rows, index) {
|
|
181
|
+
if (index.size === 0)
|
|
182
|
+
return;
|
|
183
|
+
// session → parent, so a grandchild (a subagent's own subagent) still
|
|
184
|
+
// reaches the dispatched root.
|
|
185
|
+
const parentOf = new Map();
|
|
186
|
+
for (const row of rows) {
|
|
187
|
+
if (row.parent_session_id)
|
|
188
|
+
parentOf.set(row.session_id, row.parent_session_id);
|
|
189
|
+
}
|
|
190
|
+
const refFor = (session) => {
|
|
191
|
+
let current = session;
|
|
192
|
+
for (let depth = 0; current && depth < 16; depth++) {
|
|
193
|
+
const ref = index.get(current);
|
|
194
|
+
if (ref)
|
|
195
|
+
return ref;
|
|
196
|
+
current = parentOf.get(current);
|
|
197
|
+
}
|
|
198
|
+
return undefined;
|
|
199
|
+
};
|
|
200
|
+
for (const row of rows) {
|
|
201
|
+
const ref = refFor(row.session_id) ?? (row.parent_session_id ? refFor(row.parent_session_id) : undefined);
|
|
202
|
+
if (!ref)
|
|
203
|
+
continue;
|
|
204
|
+
row.unit = ref.unit;
|
|
205
|
+
row.batch = ref.batch;
|
|
206
|
+
if (ref.issue !== null) {
|
|
207
|
+
row.issue = ref.issue;
|
|
208
|
+
row.issue_source = 'dispatch';
|
|
209
|
+
}
|
|
210
|
+
if (row.model === null && ref.model)
|
|
211
|
+
row.model = ref.model;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Provider named by a limit message — sched events record none, but the
|
|
216
|
+
* provider's own wording does (`claude.ai/settings/usage` → anthropic). Null
|
|
217
|
+
* when it cannot be told, so the view compares against every provider.
|
|
218
|
+
*/
|
|
219
|
+
function providerFromText(text) {
|
|
220
|
+
if (/claude|anthropic/i.test(text))
|
|
221
|
+
return 'anthropic';
|
|
222
|
+
if (/openai|chatgpt|codex/i.test(text))
|
|
223
|
+
return 'openai';
|
|
224
|
+
if (/z\.ai|zhipu|glm/i.test(text))
|
|
225
|
+
return 'zai';
|
|
226
|
+
if (/alibaba|dashscope|qwen/i.test(text))
|
|
227
|
+
return 'alibaba';
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
/** sched `dispatch-failure` / `dispatch-unhealthy` limit walls in `[sinceMs, untilMs)`. */
|
|
231
|
+
function collectSchedLimitEvents(schedRoot, sinceMs, untilMs, host) {
|
|
232
|
+
const out = [];
|
|
233
|
+
for (const project of (0, util_1.safeReaddir)(schedRoot)) {
|
|
234
|
+
if (!project.isDirectory())
|
|
235
|
+
continue;
|
|
236
|
+
const file = path.join(schedRoot, project.name, 'events.jsonl');
|
|
237
|
+
if (((0, util_1.mtimeMs)(file) ?? 0) < sinceMs)
|
|
238
|
+
continue;
|
|
239
|
+
(0, util_1.forEachLine)(file, (line) => {
|
|
240
|
+
if (!line.includes('"dispatch-'))
|
|
241
|
+
return;
|
|
242
|
+
let event;
|
|
243
|
+
try {
|
|
244
|
+
event = JSON.parse(line);
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
if (event.event !== 'dispatch-failure' && event.event !== 'dispatch-unhealthy')
|
|
250
|
+
return;
|
|
251
|
+
const ts = typeof event.ts === 'string' ? event.ts : null;
|
|
252
|
+
const tsMs = ts ? Date.parse(ts) : Number.NaN;
|
|
253
|
+
if (!ts || Number.isNaN(tsMs) || tsMs < sinceMs || tsMs >= untilMs)
|
|
254
|
+
return;
|
|
255
|
+
const status = typeof event.api_error_status === 'number' ? event.api_error_status : null;
|
|
256
|
+
const detail = (0, util_1.oneLine)(event.detail);
|
|
257
|
+
if (status !== 429 && !util_1.LIMIT_TEXT_RE.test(detail))
|
|
258
|
+
return;
|
|
259
|
+
out.push({
|
|
260
|
+
ts,
|
|
261
|
+
host,
|
|
262
|
+
source: 'sched',
|
|
263
|
+
provider: providerFromText(detail),
|
|
264
|
+
session_id: null,
|
|
265
|
+
unit: typeof event.unit === 'string' ? event.unit : null,
|
|
266
|
+
status,
|
|
267
|
+
detail: `[${project.name}] ${event.event}: ${detail}`,
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
return out;
|
|
272
|
+
}
|
|
273
|
+
/** session id → number of `ai-dossier run` invocations recorded from it in `[sinceMs, untilMs)`. */
|
|
274
|
+
function countDossierRuns(runsLog, sinceMs, untilMs) {
|
|
275
|
+
const counts = new Map();
|
|
276
|
+
if (((0, util_1.mtimeMs)(runsLog) ?? 0) < sinceMs)
|
|
277
|
+
return counts;
|
|
278
|
+
(0, util_1.forEachLine)(runsLog, (line) => {
|
|
279
|
+
if (!line.includes('"session_id"'))
|
|
280
|
+
return;
|
|
281
|
+
let entry;
|
|
282
|
+
try {
|
|
283
|
+
entry = JSON.parse(line);
|
|
284
|
+
}
|
|
285
|
+
catch {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
if (!entry.session_id)
|
|
289
|
+
return;
|
|
290
|
+
const tsMs = Date.parse(entry.timestamp);
|
|
291
|
+
if (Number.isNaN(tsMs) || tsMs < sinceMs || tsMs >= untilMs)
|
|
292
|
+
return;
|
|
293
|
+
counts.set(entry.session_id, (counts.get(entry.session_id) ?? 0) + 1);
|
|
294
|
+
});
|
|
295
|
+
return counts;
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=collect-dispatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collect-dispatch.js","sourceRoot":"","sources":["../../src/usage/collect-dispatch.ts"],"names":[],"mappings":"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"}
|