(modelUsage: Record<string, { count: number; tokens: number; cost: number }>)
| 325 | } |
| 326 | |
| 327 | function renderModelUsage(modelUsage: Record<string, { count: number; tokens: number; cost: number }>) { |
| 328 | console.log(`${colors.bold}Model Usage${colors.reset}`) |
| 329 | console.log() |
| 330 | |
| 331 | const sorted = Object.entries(modelUsage) |
| 332 | .sort(([, a], [, b]) => b.tokens - a.tokens) |
| 333 | .slice(0, 10) |
| 334 | |
| 335 | if (sorted.length === 0) { |
| 336 | console.log(`${colors.muted}No model usage data available${colors.reset}`) |
| 337 | return |
| 338 | } |
| 339 | |
| 340 | const maxTokens = Math.max(1, sorted[0][1].tokens) |
| 341 | |
| 342 | for (const [model, usage] of sorted) { |
| 343 | const barLength = Math.max(1, Math.floor((usage.tokens / maxTokens) * 30)) |
| 344 | const bar = "█".repeat(barLength) |
| 345 | const truncated = truncateModel(model, 38) |
| 346 | console.log( |
| 347 | `${colors.white}${truncated.padEnd(40)}${colors.reset}${colors.primary}${bar}${colors.reset} ${colors.muted}${usage.count}× · ${formatNumber(usage.tokens)} tokens · ${formatCurrency(usage.cost)}${colors.reset}`, |
| 348 | ) |
| 349 | } |
| 350 | } |
| 351 | |
| 352 | function renderCostOverview(stats: SessionStats, daysToShow: number, dateFilter?: DateFilter) { |
| 353 | console.log(`${colors.bold}Cost Summary${colors.reset}`) |
no test coverage detected