| 47 | // consistent across both paths. `gen` = output, `fresh` = uncached input |
| 48 | // (input + cache_creation), `cached` = cache reads (≈free), `total` = all. |
| 49 | function sumTokens(file) { |
| 50 | const t = { gen: 0, fresh: 0, cached: 0 }; |
| 51 | for (const line of readFileSync(file, 'utf8').split('\n')) { |
| 52 | if (!line) continue; |
| 53 | let ev; try { ev = JSON.parse(line); } catch { continue; } |
| 54 | const u = ev.message?.usage; |
| 55 | if (!u) continue; |
| 56 | t.gen += u.output_tokens || 0; |
| 57 | t.fresh += (u.input_tokens || 0) + (u.cache_creation_input_tokens || 0); |
| 58 | t.cached += u.cache_read_input_tokens || 0; |
| 59 | } |
| 60 | return t; |
| 61 | } |
| 62 | |
| 63 | const mainCounts = tally(join(projDir, sessionId + '.jsonl')); |
| 64 | |