ai-heatmap 1.17.7 → 1.17.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-heatmap",
3
- "version": "1.17.7",
3
+ "version": "1.17.9",
4
4
  "description": "AI usage cost heatmap powered by ccusage + react-activity-calendar",
5
5
  "type": "module",
6
6
  "bin": {
@@ -59,14 +59,46 @@ if (!mergeOnly) {
59
59
  if (untilFlag) cmd += ` ${untilFlag}`;
60
60
 
61
61
  console.log(`Running: ${cmd}`);
62
- const raw = execSync(cmd, { encoding: "utf-8", timeout: 300000 });
62
+ let raw;
63
+ try {
64
+ raw = execSync(cmd, { encoding: "utf-8", timeout: 300000 });
65
+ } catch (err) {
66
+ if (err.code === "ETIMEDOUT" || err.signal === "SIGTERM") {
67
+ console.error("\nError: ccusage timed out after 5 minutes.");
68
+ console.error("This may be caused by a slow network or npm registry issue.");
69
+ console.error("Try running manually: npx clear-npx-cache && npx --yes ccusage@latest daily --json");
70
+ } else {
71
+ console.error("\nError running ccusage:", err.message);
72
+ if (err.stderr) console.error(err.stderr);
73
+ }
74
+ process.exit(1);
75
+ }
63
76
  const { daily } = JSON.parse(raw);
64
77
 
65
- const costs = daily.map((d) => d.totalCost);
66
- const maxCost = Math.max(...costs);
78
+ // Build a map of existing data, merging duplicate dates by summing
79
+ const dataMap = new Map();
80
+ for (const d of daily) {
81
+ if (!dataMap.has(d.date)) {
82
+ dataMap.set(d.date, { ...d });
83
+ } else {
84
+ const existing = dataMap.get(d.date);
85
+ existing.totalCost = (existing.totalCost ?? 0) + (d.totalCost ?? 0);
86
+ existing.inputTokens = (existing.inputTokens ?? 0) + (d.inputTokens ?? 0);
87
+ existing.outputTokens = (existing.outputTokens ?? 0) + (d.outputTokens ?? 0);
88
+ existing.totalTokens = (existing.totalTokens ?? 0) + (d.totalTokens ?? 0);
89
+ existing.cacheReadTokens = (existing.cacheReadTokens ?? 0) + (d.cacheReadTokens ?? 0);
90
+ existing.cacheCreationTokens = (existing.cacheCreationTokens ?? 0) + (d.cacheCreationTokens ?? 0);
91
+ existing.modelsUsed = [...new Set([...(existing.modelsUsed ?? []), ...(d.modelsUsed ?? [])])];
92
+ const bdMap = new Map((existing.modelBreakdowns ?? []).map((m) => [m.modelName, m.cost ?? 0]));
93
+ for (const mb of (d.modelBreakdowns ?? [])) {
94
+ bdMap.set(mb.modelName, (bdMap.get(mb.modelName) ?? 0) + (mb.cost ?? 0));
95
+ }
96
+ existing.modelBreakdowns = [...bdMap.entries()].map(([modelName, cost]) => ({ modelName, cost }));
97
+ }
98
+ }
67
99
 
68
- // Build a map of existing data
69
- const dataMap = new Map(daily.map((d) => [d.date, d]));
100
+ const costs = [...dataMap.values()].map((d) => d.totalCost);
101
+ const maxCost = Math.max(...costs);
70
102
 
71
103
  // Fill 365 days (from today back 364 days)
72
104
  const today = new Date();