@sentropic/agent-stats-core 0.1.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 (50) hide show
  1. package/README.md +4 -0
  2. package/dist/aggregations.d.ts +87 -0
  3. package/dist/aggregations.d.ts.map +1 -0
  4. package/dist/aggregations.js +242 -0
  5. package/dist/aggregations.js.map +1 -0
  6. package/dist/analyze.d.ts +93 -0
  7. package/dist/analyze.d.ts.map +1 -0
  8. package/dist/analyze.js +143 -0
  9. package/dist/analyze.js.map +1 -0
  10. package/dist/anomalies.d.ts +37 -0
  11. package/dist/anomalies.d.ts.map +1 -0
  12. package/dist/anomalies.js +188 -0
  13. package/dist/anomalies.js.map +1 -0
  14. package/dist/cleanser.d.ts +56 -0
  15. package/dist/cleanser.d.ts.map +1 -0
  16. package/dist/cleanser.js +132 -0
  17. package/dist/cleanser.js.map +1 -0
  18. package/dist/collect.d.ts +43 -0
  19. package/dist/collect.d.ts.map +1 -0
  20. package/dist/collect.js +140 -0
  21. package/dist/collect.js.map +1 -0
  22. package/dist/index.d.ts +18 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +18 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/parsers/claude.d.ts +33 -0
  27. package/dist/parsers/claude.d.ts.map +1 -0
  28. package/dist/parsers/claude.js +169 -0
  29. package/dist/parsers/claude.js.map +1 -0
  30. package/dist/parsers/codex.d.ts +69 -0
  31. package/dist/parsers/codex.d.ts.map +1 -0
  32. package/dist/parsers/codex.js +262 -0
  33. package/dist/parsers/codex.js.map +1 -0
  34. package/dist/rate-card.d.ts +50 -0
  35. package/dist/rate-card.d.ts.map +1 -0
  36. package/dist/rate-card.js +138 -0
  37. package/dist/rate-card.js.map +1 -0
  38. package/dist/schema.d.ts +138 -0
  39. package/dist/schema.d.ts.map +1 -0
  40. package/dist/schema.js +37 -0
  41. package/dist/schema.js.map +1 -0
  42. package/dist/secrets.d.ts +24 -0
  43. package/dist/secrets.d.ts.map +1 -0
  44. package/dist/secrets.js +45 -0
  45. package/dist/secrets.js.map +1 -0
  46. package/dist/storage.d.ts +33 -0
  47. package/dist/storage.d.ts.map +1 -0
  48. package/dist/storage.js +112 -0
  49. package/dist/storage.js.map +1 -0
  50. package/package.json +53 -0
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Parser for Claude Code session jsonl files
3
+ * (`~/.claude/projects/<cwd-encoded>/<sessionId>.jsonl`).
4
+ *
5
+ * Streams the file line-by-line and yields normalized `SessionEvent`s.
6
+ *
7
+ * Known top-level types (May 2026):
8
+ * assistant, user, attachment, permission-mode, ai-title, custom-title,
9
+ * agent-name, last-prompt, system, file-history-snapshot, queue-operation
10
+ *
11
+ * Known `message.content[]` sub-types:
12
+ * text, tool_use, tool_result, thinking, (raw string content)
13
+ */
14
+ import type { SessionEvent } from '../schema.js';
15
+ interface ClaudeParseOptions {
16
+ /** Absolute path of the session jsonl. Used to derive sessionId/projectCwd if not in the file. */
17
+ filePath: string;
18
+ /** Hard-cap on lines processed (for tests). */
19
+ maxLines?: number;
20
+ }
21
+ /**
22
+ * Parse a single Claude jsonl session file and yield normalized events.
23
+ *
24
+ * Notes:
25
+ * - Emits a synthetic `session_start` from the first timestamped record.
26
+ * - Emits `session_end` from the last record.
27
+ * - The session id is derived from the filename (basename without extension).
28
+ * - The project cwd is read from the first record that carries one, falling
29
+ * back to a sanitized form of the parent directory name.
30
+ */
31
+ export declare function parseClaudeSession(opts: ClaudeParseOptions): AsyncGenerator<SessionEvent, void, unknown>;
32
+ export {};
33
+ //# sourceMappingURL=claude.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/parsers/claude.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,OAAO,KAAK,EAAE,YAAY,EAAS,MAAM,cAAc,CAAC;AAExD,UAAU,kBAAkB;IAC1B,kGAAkG;IAClG,QAAQ,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AA0DD;;;;;;;;;GASG;AACH,wBAAuB,kBAAkB,CACvC,IAAI,EAAE,kBAAkB,GACvB,cAAc,CAAC,YAAY,EAAE,IAAI,EAAE,OAAO,CAAC,CA4H7C"}
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Parser for Claude Code session jsonl files
3
+ * (`~/.claude/projects/<cwd-encoded>/<sessionId>.jsonl`).
4
+ *
5
+ * Streams the file line-by-line and yields normalized `SessionEvent`s.
6
+ *
7
+ * Known top-level types (May 2026):
8
+ * assistant, user, attachment, permission-mode, ai-title, custom-title,
9
+ * agent-name, last-prompt, system, file-history-snapshot, queue-operation
10
+ *
11
+ * Known `message.content[]` sub-types:
12
+ * text, tool_use, tool_result, thinking, (raw string content)
13
+ */
14
+ import { createHash } from 'node:crypto';
15
+ import { createReadStream } from 'node:fs';
16
+ import { createInterface } from 'node:readline';
17
+ const sha256short = (text) => createHash('sha256').update(text).digest('hex').slice(0, 16);
18
+ function categorizeTool(name) {
19
+ if (name === 'Bash')
20
+ return 'bash';
21
+ if (name.startsWith('mcp__'))
22
+ return 'mcp';
23
+ if (['Read', 'Write', 'Edit', 'Glob', 'Grep', 'NotebookEdit', 'WebFetch', 'WebSearch'].includes(name))
24
+ return 'native';
25
+ return 'unknown';
26
+ }
27
+ function normalizeUsage(raw) {
28
+ return {
29
+ newInputTokens: raw?.input_tokens ?? 0,
30
+ cachedInputTokens: raw?.cache_read_input_tokens ?? 0,
31
+ cacheWriteTokens: raw?.cache_creation_input_tokens ?? 0,
32
+ outputTokens: raw?.output_tokens ?? 0,
33
+ reasoningTokens: 0, // Claude doesn't expose reasoning sub-count.
34
+ };
35
+ }
36
+ /**
37
+ * Parse a single Claude jsonl session file and yield normalized events.
38
+ *
39
+ * Notes:
40
+ * - Emits a synthetic `session_start` from the first timestamped record.
41
+ * - Emits `session_end` from the last record.
42
+ * - The session id is derived from the filename (basename without extension).
43
+ * - The project cwd is read from the first record that carries one, falling
44
+ * back to a sanitized form of the parent directory name.
45
+ */
46
+ export async function* parseClaudeSession(opts) {
47
+ const stream = createReadStream(opts.filePath, { encoding: 'utf8' });
48
+ const rl = createInterface({ input: stream, crlfDelay: Infinity });
49
+ const fileBase = opts.filePath.split('/').pop() ?? opts.filePath;
50
+ const sessionIdFromFile = fileBase.replace(/\.jsonl$/, '');
51
+ let sessionId = sessionIdFromFile;
52
+ let projectCwd = '';
53
+ let firstTs;
54
+ let lastTs;
55
+ let lineCount = 0;
56
+ let startEmitted = false;
57
+ // Defer the start event until we have at least one timestamp + cwd.
58
+ const buffer = [];
59
+ function flush() {
60
+ const out = buffer.splice(0);
61
+ return out;
62
+ }
63
+ for await (const line of rl) {
64
+ lineCount += 1;
65
+ if (opts.maxLines !== undefined && lineCount > opts.maxLines)
66
+ break;
67
+ if (!line.trim())
68
+ continue;
69
+ let rec;
70
+ try {
71
+ rec = JSON.parse(line);
72
+ }
73
+ catch {
74
+ continue;
75
+ }
76
+ if (rec.sessionId)
77
+ sessionId = rec.sessionId;
78
+ if (rec.cwd)
79
+ projectCwd = rec.cwd;
80
+ const ts = rec.timestamp;
81
+ if (ts) {
82
+ if (!firstTs)
83
+ firstTs = ts;
84
+ lastTs = ts;
85
+ }
86
+ // Emit session_start lazily once we have ts + cwd (or first ts at least).
87
+ if (!startEmitted && firstTs) {
88
+ startEmitted = true;
89
+ const startEvent = {
90
+ kind: 'session_start',
91
+ ts: firstTs,
92
+ tool: 'claude',
93
+ sessionId,
94
+ projectCwd,
95
+ isSubagent: false, // Claude Task sub-agents would be detected differently.
96
+ };
97
+ buffer.push(startEvent);
98
+ }
99
+ const recTs = ts ?? firstTs ?? new Date(0).toISOString();
100
+ const base = { tool: 'claude', sessionId, projectCwd, ts: recTs };
101
+ // user / assistant turn record (carries `message`)
102
+ if (rec.type === 'assistant' && rec.message) {
103
+ const msg = rec.message;
104
+ // Emit tool_use / tool_result / skill_invoke from content[]
105
+ if (Array.isArray(msg.content)) {
106
+ for (const c of msg.content) {
107
+ if (c.type === 'tool_use' && c.name) {
108
+ buffer.push({
109
+ ...base,
110
+ kind: 'tool_call',
111
+ name: c.name,
112
+ category: categorizeTool(c.name),
113
+ inputBytes: c.input ? JSON.stringify(c.input).length : 0,
114
+ });
115
+ }
116
+ }
117
+ }
118
+ // Emit turn event when usage is present.
119
+ if (msg.usage) {
120
+ buffer.push({
121
+ ...base,
122
+ kind: 'turn',
123
+ model: msg.model ?? 'unknown',
124
+ usage: normalizeUsage(msg.usage),
125
+ });
126
+ }
127
+ }
128
+ else if (rec.type === 'user' && rec.message) {
129
+ const msg = rec.message;
130
+ // user message can be string OR array of content items; extract text length + hash
131
+ let text = '';
132
+ if (typeof msg.content === 'string') {
133
+ text = msg.content;
134
+ }
135
+ else if (Array.isArray(msg.content)) {
136
+ for (const c of msg.content) {
137
+ if (c.type === 'text' && typeof c.text === 'string')
138
+ text += c.text;
139
+ }
140
+ }
141
+ if (text) {
142
+ buffer.push({
143
+ ...base,
144
+ kind: 'user_prompt',
145
+ textLength: text.length,
146
+ textHash: sha256short(text),
147
+ });
148
+ }
149
+ }
150
+ else if (rec.type === 'attachment') {
151
+ // Detect SessionStart hooks for skill invocations.
152
+ const hookName = rec.attachment?.hookName ?? '';
153
+ if (hookName.startsWith('Skill') || hookName === 'SessionStart:startup') {
154
+ // No-op for now; skills are tracked through tool_use of Skill tool.
155
+ }
156
+ }
157
+ yield* flush();
158
+ }
159
+ if (lastTs && startEmitted) {
160
+ yield {
161
+ kind: 'session_end',
162
+ ts: lastTs,
163
+ tool: 'claude',
164
+ sessionId,
165
+ projectCwd,
166
+ };
167
+ }
168
+ }
169
+ //# sourceMappingURL=claude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/parsers/claude.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Parser for Codex CLI session rollouts.
3
+ *
4
+ * Two-stage:
5
+ * 1. `indexCodexSessions(opts)` queries `~/.codex/state_5.sqlite`
6
+ * (table `threads`) for sessions matching cwd / time-range filters and
7
+ * returns a list of `CodexIndexEntry` pointing to the rollout paths.
8
+ * 2. `parseCodexRollout({filePath})` streams a single rollout jsonl and
9
+ * yields normalized `SessionEvent`s.
10
+ *
11
+ * Codex rollout top-level types seen in May 2026:
12
+ * session_meta, event_msg, response_item, compacted, turn_context.
13
+ *
14
+ * `event_msg.payload.type` sub-types include:
15
+ * token_count, agent_message, user_message, task_started, task_complete,
16
+ * turn_aborted, context_compacted, mcp_tool_call_begin / *_end,
17
+ * web_search_begin / *_end, exec_command_begin / *_end,
18
+ * patch_apply_begin / *_end.
19
+ *
20
+ * `response_item.payload.type` sub-types: message, function_call,
21
+ * function_call_output, reasoning.
22
+ */
23
+ import type { SessionEvent } from '../schema.js';
24
+ export interface CodexIndexEntry {
25
+ /** Thread id (uuid v7). */
26
+ id: string;
27
+ /** Absolute path to the rollout jsonl. */
28
+ rolloutPath: string;
29
+ /** Working directory at the time of the session. */
30
+ cwd: string;
31
+ /** Model id chosen at session create time (column added later; may be null). */
32
+ model?: string;
33
+ /** Unix seconds. */
34
+ createdAt: number;
35
+ updatedAt: number;
36
+ /** Codex's running `tokens_used` counter for this thread. */
37
+ tokensUsed: number;
38
+ /** Whether this session source is `subagent`. */
39
+ isSubagent: boolean;
40
+ }
41
+ export interface IndexCodexOptions {
42
+ /** Path to state_5.sqlite (default: ~/.codex/state_5.sqlite). */
43
+ dbPath?: string;
44
+ /** Lower bound on created_at. */
45
+ since?: Date;
46
+ /** Upper bound on created_at. */
47
+ until?: Date;
48
+ /** Filter on cwd (exact or prefix; pass with trailing slash for prefix). */
49
+ projectCwd?: string;
50
+ /** Hard limit on number of returned entries. */
51
+ limit?: number;
52
+ }
53
+ /**
54
+ * Query the Codex threads DB and return matching session entries.
55
+ *
56
+ * The function opens the DB in readonly mode and never mutates anything.
57
+ */
58
+ export declare function indexCodexSessions(opts?: IndexCodexOptions): CodexIndexEntry[];
59
+ export interface ParseCodexRolloutOptions {
60
+ filePath: string;
61
+ /** Optional sessionId/cwd override (when caller already has the index entry). */
62
+ sessionId?: string;
63
+ projectCwd?: string;
64
+ }
65
+ /**
66
+ * Stream-parse a Codex rollout jsonl and yield normalized events.
67
+ */
68
+ export declare function parseCodexRollout(opts: ParseCodexRolloutOptions): AsyncGenerator<SessionEvent, void, unknown>;
69
+ //# sourceMappingURL=codex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/parsers/codex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAQH,OAAO,KAAK,EAAE,YAAY,EAAS,MAAM,cAAc,CAAC;AAOxD,MAAM,WAAW,eAAe;IAC9B,2BAA2B;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,GAAG,EAAE,MAAM,CAAC;IACZ,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,UAAU,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,KAAK,CAAC,EAAE,IAAI,CAAC;IACb,iCAAiC;IACjC,KAAK,CAAC,EAAE,IAAI,CAAC;IACb,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAaD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,iBAAsB,GAAG,eAAe,EAAE,CAgDlF;AAuFD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAuB,iBAAiB,CACtC,IAAI,EAAE,wBAAwB,GAC7B,cAAc,CAAC,YAAY,EAAE,IAAI,EAAE,OAAO,CAAC,CA6J7C"}
@@ -0,0 +1,262 @@
1
+ /**
2
+ * Parser for Codex CLI session rollouts.
3
+ *
4
+ * Two-stage:
5
+ * 1. `indexCodexSessions(opts)` queries `~/.codex/state_5.sqlite`
6
+ * (table `threads`) for sessions matching cwd / time-range filters and
7
+ * returns a list of `CodexIndexEntry` pointing to the rollout paths.
8
+ * 2. `parseCodexRollout({filePath})` streams a single rollout jsonl and
9
+ * yields normalized `SessionEvent`s.
10
+ *
11
+ * Codex rollout top-level types seen in May 2026:
12
+ * session_meta, event_msg, response_item, compacted, turn_context.
13
+ *
14
+ * `event_msg.payload.type` sub-types include:
15
+ * token_count, agent_message, user_message, task_started, task_complete,
16
+ * turn_aborted, context_compacted, mcp_tool_call_begin / *_end,
17
+ * web_search_begin / *_end, exec_command_begin / *_end,
18
+ * patch_apply_begin / *_end.
19
+ *
20
+ * `response_item.payload.type` sub-types: message, function_call,
21
+ * function_call_output, reasoning.
22
+ */
23
+ import { createHash } from 'node:crypto';
24
+ import { createReadStream } from 'node:fs';
25
+ import { createInterface } from 'node:readline';
26
+ import Database from 'better-sqlite3';
27
+ import { ZERO_USAGE } from '../schema.js';
28
+ /**
29
+ * Query the Codex threads DB and return matching session entries.
30
+ *
31
+ * The function opens the DB in readonly mode and never mutates anything.
32
+ */
33
+ export function indexCodexSessions(opts = {}) {
34
+ const dbPath = opts.dbPath ?? `${process.env['HOME'] ?? ''}/.codex/state_5.sqlite`;
35
+ const db = new Database(dbPath, { readonly: true, fileMustExist: true });
36
+ try {
37
+ const conditions = [];
38
+ const params = {};
39
+ if (opts.since) {
40
+ conditions.push('created_at >= $since');
41
+ params['since'] = Math.floor(opts.since.getTime() / 1000);
42
+ }
43
+ if (opts.until) {
44
+ conditions.push('created_at <= $until');
45
+ params['until'] = Math.floor(opts.until.getTime() / 1000);
46
+ }
47
+ if (opts.projectCwd) {
48
+ if (opts.projectCwd.endsWith('/')) {
49
+ conditions.push('cwd LIKE $cwdPrefix');
50
+ params['cwdPrefix'] = `${opts.projectCwd}%`;
51
+ }
52
+ else {
53
+ conditions.push('cwd = $cwd');
54
+ params['cwd'] = opts.projectCwd;
55
+ }
56
+ }
57
+ const where = conditions.length ? `WHERE ${conditions.join(' AND ')}` : '';
58
+ const limit = opts.limit ? `LIMIT ${Math.floor(opts.limit)}` : '';
59
+ const sql = `
60
+ SELECT
61
+ id, rollout_path, cwd, model, created_at, updated_at, tokens_used,
62
+ thread_source
63
+ FROM threads
64
+ ${where}
65
+ ORDER BY created_at DESC
66
+ ${limit}
67
+ `;
68
+ const rows = db.prepare(sql).all(params);
69
+ return rows.map((r) => ({
70
+ id: r.id,
71
+ rolloutPath: r.rollout_path,
72
+ cwd: r.cwd,
73
+ ...(r.model !== null ? { model: r.model } : {}),
74
+ createdAt: r.created_at,
75
+ updatedAt: r.updated_at,
76
+ tokensUsed: r.tokens_used,
77
+ isSubagent: r.thread_source === 'subagent',
78
+ }));
79
+ }
80
+ finally {
81
+ db.close();
82
+ }
83
+ }
84
+ function normalizeCodexUsage(raw) {
85
+ if (!raw)
86
+ return ZERO_USAGE;
87
+ const cached = raw.cached_input_tokens ?? 0;
88
+ const total = raw.input_tokens ?? 0;
89
+ return {
90
+ newInputTokens: Math.max(0, total - cached),
91
+ cachedInputTokens: cached,
92
+ cacheWriteTokens: 0, // Codex doesn't expose cache writes separately.
93
+ outputTokens: raw.output_tokens ?? 0,
94
+ reasoningTokens: raw.reasoning_output_tokens ?? 0,
95
+ };
96
+ }
97
+ const sha256short = (text) => createHash('sha256').update(text).digest('hex').slice(0, 16);
98
+ function categorizeCodexTool(name) {
99
+ if (name.startsWith('mcp__') || name.startsWith('mcp_'))
100
+ return 'mcp';
101
+ if (name === 'shell' || name === 'exec_command' || name === 'bash')
102
+ return 'bash';
103
+ if (['Read', 'Write', 'Edit', 'apply_patch', 'patch_apply', 'view_image'].some((n) => name.includes(n)))
104
+ return 'native';
105
+ return 'function';
106
+ }
107
+ /**
108
+ * Stream-parse a Codex rollout jsonl and yield normalized events.
109
+ */
110
+ export async function* parseCodexRollout(opts) {
111
+ const stream = createReadStream(opts.filePath, { encoding: 'utf8' });
112
+ const rl = createInterface({ input: stream, crlfDelay: Infinity });
113
+ const fileBase = opts.filePath.split('/').pop() ?? opts.filePath;
114
+ // rollout filenames are: rollout-YYYY-MM-DDTHH-MM-SS-<uuid>.jsonl
115
+ const uuidMatch = fileBase.match(/-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/);
116
+ let sessionId = opts.sessionId ?? uuidMatch?.[1] ?? fileBase.replace(/\.jsonl$/, '');
117
+ let projectCwd = opts.projectCwd ?? '';
118
+ let model = 'unknown';
119
+ let lastTs;
120
+ let startEmitted = false;
121
+ for await (const line of rl) {
122
+ if (!line.trim())
123
+ continue;
124
+ let rec;
125
+ try {
126
+ rec = JSON.parse(line);
127
+ }
128
+ catch {
129
+ continue;
130
+ }
131
+ const ts = rec.timestamp ?? new Date(0).toISOString();
132
+ lastTs = ts;
133
+ const base = { tool: 'codex', sessionId, projectCwd, ts };
134
+ if (rec.type === 'session_meta') {
135
+ const p = (rec.payload ?? {});
136
+ if (p.id)
137
+ sessionId = p.id;
138
+ if (p.cwd)
139
+ projectCwd = p.cwd;
140
+ const parentId = p.source?.subagent?.thread_spawn?.parent_thread_id;
141
+ const depth = p.source?.subagent?.thread_spawn?.depth;
142
+ const isSub = p.thread_source === 'subagent';
143
+ yield {
144
+ ...base,
145
+ sessionId,
146
+ projectCwd,
147
+ kind: 'session_start',
148
+ ...(p.model_provider ? { model: p.model_provider } : {}),
149
+ ...(parentId ? { forkedFromId: parentId } : {}),
150
+ ...(typeof depth === 'number' ? { subagentDepth: depth } : {}),
151
+ ...(p.agent_nickname ? { agentNickname: p.agent_nickname } : {}),
152
+ ...(p.cli_version ? { cliVersion: p.cli_version } : {}),
153
+ isSubagent: isSub,
154
+ };
155
+ startEmitted = true;
156
+ continue;
157
+ }
158
+ if (rec.type === 'event_msg') {
159
+ const p = (rec.payload ?? {});
160
+ switch (p.type) {
161
+ case 'token_count': {
162
+ const last = p.info?.last_token_usage;
163
+ if (last && (last.input_tokens ?? 0) + (last.output_tokens ?? 0) > 0) {
164
+ const rl1 = p.rate_limits?.primary?.used_percent;
165
+ const rl2 = p.rate_limits?.secondary?.used_percent;
166
+ yield {
167
+ ...base,
168
+ kind: 'turn',
169
+ model,
170
+ usage: normalizeCodexUsage(last),
171
+ ...(p.info?.total_token_usage
172
+ ? { cumulative: normalizeCodexUsage(p.info.total_token_usage) }
173
+ : {}),
174
+ ...(typeof rl1 === 'number' && typeof rl2 === 'number'
175
+ ? { rateLimit: { primaryPercent: rl1, secondaryPercent: rl2 } }
176
+ : {}),
177
+ };
178
+ }
179
+ break;
180
+ }
181
+ case 'context_compacted':
182
+ yield { ...base, kind: 'compaction' };
183
+ break;
184
+ case 'user_message': {
185
+ const text = typeof p.message === 'string' ? p.message : '';
186
+ if (text) {
187
+ yield {
188
+ ...base,
189
+ kind: 'user_prompt',
190
+ textLength: text.length,
191
+ textHash: sha256short(text),
192
+ };
193
+ }
194
+ break;
195
+ }
196
+ case 'mcp_tool_call_end': {
197
+ const name = `mcp__${p.server ?? 'unknown'}__${p.tool ?? 'unknown'}`;
198
+ const out = p.result ? JSON.stringify(p.result).length : 0;
199
+ yield {
200
+ ...base,
201
+ kind: 'tool_call',
202
+ name,
203
+ category: 'mcp',
204
+ outputBytes: out,
205
+ };
206
+ break;
207
+ }
208
+ case 'exec_command_end': {
209
+ const out = (p.aggregated_output?.length ?? 0) + (p.stdout?.length ?? 0) + (p.stderr?.length ?? 0);
210
+ const cmdArr = Array.isArray(p.command) ? p.command : [];
211
+ const cmdName = typeof cmdArr[0] === 'string' ? cmdArr[0] : 'shell';
212
+ yield {
213
+ ...base,
214
+ kind: 'tool_call',
215
+ name: cmdName,
216
+ category: 'bash',
217
+ outputBytes: out,
218
+ ...(typeof p.exit_code === 'number' && p.exit_code !== 0 ? { error: true } : {}),
219
+ };
220
+ break;
221
+ }
222
+ case 'web_search_end':
223
+ yield {
224
+ ...base,
225
+ kind: 'tool_call',
226
+ name: 'web_search',
227
+ category: 'native',
228
+ };
229
+ break;
230
+ default:
231
+ break;
232
+ }
233
+ continue;
234
+ }
235
+ if (rec.type === 'response_item') {
236
+ const p = (rec.payload ?? {});
237
+ if (p.type === 'function_call' && typeof p.name === 'string') {
238
+ yield {
239
+ ...base,
240
+ kind: 'tool_call',
241
+ name: p.name,
242
+ category: categorizeCodexTool(p.name),
243
+ };
244
+ }
245
+ continue;
246
+ }
247
+ if (rec.type === 'compacted') {
248
+ yield { ...base, kind: 'compaction' };
249
+ continue;
250
+ }
251
+ }
252
+ if (startEmitted && lastTs) {
253
+ yield {
254
+ kind: 'session_end',
255
+ ts: lastTs,
256
+ tool: 'codex',
257
+ sessionId,
258
+ projectCwd,
259
+ };
260
+ }
261
+ }
262
+ //# sourceMappingURL=codex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/parsers/codex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Rate cards used to estimate the credits / cost burnt by each turn.
3
+ *
4
+ * Two distinct currencies coexist:
5
+ * - **Codex credits**: published in OpenAI's Codex rate card (credits /
6
+ * 1M tokens). The Pro weekly bucket sums these.
7
+ * - **Claude USD cents**: Anthropic's public API list price, expressed as
8
+ * `100 × $` per 1M tokens, so a $1.25 input rate becomes 125.
9
+ *
10
+ * Mixing the two in the same aggregate makes no sense; the aggregator splits
11
+ * them into separate sub-totals (`codexCredits` vs `claudeUsdCents`).
12
+ *
13
+ * Sources (May 2026):
14
+ * - Codex rate card (developers.openai.com/codex/pricing,
15
+ * help.openai.com codex-rate-card)
16
+ * - Anthropic pricing page
17
+ * - Cross-referenced with the project memory
18
+ * `reference_codex-quota-equation`
19
+ *
20
+ * All numbers may drift; update from the source when OpenAI / Anthropic
21
+ * change their public pricing.
22
+ */
23
+ import type { Usage } from './schema.js';
24
+ export type CostCurrency = 'codex_credits' | 'claude_usd_cents' | 'unknown';
25
+ /** Rate weights per 1M tokens for one model. */
26
+ export interface ModelRates {
27
+ newInputPerMillion: number;
28
+ cachedPerMillion: number;
29
+ cacheWritePerMillion: number;
30
+ outputPerMillion: number;
31
+ currency: CostCurrency;
32
+ }
33
+ export declare const ZERO_RATES: ModelRates;
34
+ /**
35
+ * Default rate card. Keys MUST match the model id reported by the parser
36
+ * (Codex `model_provider` value, Claude `message.model` value). Aliases /
37
+ * fallbacks are resolved by `resolveRates`.
38
+ */
39
+ export declare const DEFAULT_RATE_CARD: Record<string, ModelRates>;
40
+ /**
41
+ * Resolve the rate-card entry for a model. Returns `ZERO_RATES` when the
42
+ * model is not registered, so callers always get a defined value.
43
+ */
44
+ export declare function resolveRates(model: string | undefined, card?: Record<string, ModelRates>): ModelRates;
45
+ /** Compute the cost of a single turn's usage given the model. */
46
+ export declare function estimateCost(usage: Usage, rates: ModelRates): {
47
+ amount: number;
48
+ currency: CostCurrency;
49
+ };
50
+ //# sourceMappingURL=rate-card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-card.d.ts","sourceRoot":"","sources":["../src/rate-card.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,MAAM,YAAY,GAAG,eAAe,GAAG,kBAAkB,GAAG,SAAS,CAAC;AAE5E,gDAAgD;AAChD,MAAM,WAAW,UAAU;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED,eAAO,MAAM,UAAU,EAAE,UAMxB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAsExD,CAAC;AAEF;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAqB,GACnD,UAAU,CAcZ;AAED,iEAAiE;AACjE,wBAAgB,YAAY,CAC1B,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,UAAU,GAChB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAA;CAAE,CAQ5C"}