vibestats 1.0.8 → 1.0.9

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 (2) hide show
  1. package/dist/index.js +46 -1
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -365,6 +365,46 @@ function parseCodexJsonl() {
365
365
  }
366
366
  return entries;
367
367
  }
368
+ function parseStatsCacheJson() {
369
+ const cachePath = join(getClaudeDir(), "stats-cache.json");
370
+ if (!existsSync(cachePath)) return [];
371
+ try {
372
+ const cache = JSON.parse(readFileSync(cachePath, "utf-8"));
373
+ const entries = [];
374
+ if (!cache.dailyModelTokens || !cache.modelUsage) return [];
375
+ for (const day of cache.dailyModelTokens) {
376
+ for (const [modelId, totalTokens] of Object.entries(day.tokensByModel)) {
377
+ const usage = cache.modelUsage[modelId];
378
+ if (!usage) continue;
379
+ const allTimeTotal = usage.inputTokens + usage.outputTokens + usage.cacheReadInputTokens + usage.cacheCreationInputTokens;
380
+ if (allTimeTotal === 0) continue;
381
+ const inputRatio = usage.inputTokens / allTimeTotal;
382
+ const outputRatio = usage.outputTokens / allTimeTotal;
383
+ const cacheReadRatio = usage.cacheReadInputTokens / allTimeTotal;
384
+ const cacheWriteRatio = usage.cacheCreationInputTokens / allTimeTotal;
385
+ const inputTokens = Math.round(totalTokens * inputRatio);
386
+ const outputTokens = Math.round(totalTokens * outputRatio);
387
+ const cacheReadTokens = Math.round(totalTokens * cacheReadRatio);
388
+ const cacheWriteTokens = Math.round(totalTokens * cacheWriteRatio);
389
+ const pricing = getModelPricing(modelId);
390
+ const cost = inputTokens * pricing.input / 1e6 + outputTokens * pricing.output / 1e6 + cacheWriteTokens * pricing.cacheWrite / 1e6 + cacheReadTokens * pricing.cacheRead / 1e6;
391
+ entries.push({
392
+ date: day.date,
393
+ model: getModelDisplayName(modelId),
394
+ inputTokens,
395
+ outputTokens,
396
+ cacheWriteTokens,
397
+ cacheReadTokens,
398
+ cost,
399
+ source: "claude"
400
+ });
401
+ }
402
+ }
403
+ return entries;
404
+ } catch {
405
+ return [];
406
+ }
407
+ }
368
408
  function filterByDateRange(entries, since, until) {
369
409
  return entries.filter((e) => {
370
410
  if (since && e.date < since) return false;
@@ -495,7 +535,12 @@ function loadUsageStats(options) {
495
535
  const { aggregation, since, until, codexOnly, combined } = options;
496
536
  let entries = [];
497
537
  if (!codexOnly) {
498
- entries = entries.concat(parseClaudeJsonl());
538
+ const jsonlEntries = parseClaudeJsonl();
539
+ const cacheEntries = parseStatsCacheJson();
540
+ const jsonlDates = new Set(jsonlEntries.map((e) => e.date));
541
+ const supplementalEntries = cacheEntries.filter((e) => !jsonlDates.has(e.date));
542
+ entries = entries.concat(jsonlEntries);
543
+ entries = entries.concat(supplementalEntries);
499
544
  }
500
545
  if (codexOnly || combined) {
501
546
  entries = entries.concat(parseCodexJsonl());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibestats",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "AI coding stats - usage tracking and annual wrapped for Claude Code & Codex",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",