tokenleak 0.4.0 → 0.4.1

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/package.json +1 -1
  2. package/tokenleak.js +22 -13
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tokenleak",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Visualise your AI coding-assistant token usage across providers — heatmaps, dashboards, and shareable cards.",
5
5
  "type": "module",
6
6
  "bin": {
package/tokenleak.js CHANGED
@@ -736,7 +736,7 @@ function computePreviousPeriod(current) {
736
736
  };
737
737
  }
738
738
  // packages/core/dist/index.js
739
- var VERSION = "0.4.0";
739
+ var VERSION = "0.4.1";
740
740
 
741
741
  // packages/registry/dist/models/normalizer.js
742
742
  var DATE_SUFFIX_PATTERN = /-\d{8}$/;
@@ -1650,7 +1650,13 @@ function renderHeatmap(daily, theme, options = {}) {
1650
1650
  }
1651
1651
 
1652
1652
  // packages/renderers/dist/svg/svg-renderer.js
1653
- var MIN_SVG_WIDTH = 800;
1653
+ var MIN_SVG_WIDTH = 1000;
1654
+ var MAX_STAT_VALUE_CHARS = 28;
1655
+ function truncateText(value, maxChars) {
1656
+ if (value.length <= maxChars)
1657
+ return value;
1658
+ return value.slice(0, maxChars - 1) + "\u2026";
1659
+ }
1654
1660
  function renderHeaderStat(x, y, label, value, theme, align = "end") {
1655
1661
  const anchor = align === "end" ? "end" : "start";
1656
1662
  return group([
@@ -1682,7 +1688,7 @@ function renderBottomStat(x, y, label, value, theme) {
1682
1688
  }),
1683
1689
  text(x, y + 32, value, {
1684
1690
  fill: theme.foreground,
1685
- "font-size": 22,
1691
+ "font-size": 18,
1686
1692
  "font-family": FONT_FAMILY,
1687
1693
  "font-weight": "700"
1688
1694
  })
@@ -1728,21 +1734,24 @@ class SvgRenderer {
1728
1734
  }
1729
1735
  sections.push(`<line x1="${PADDING}" y1="${y}" x2="${PADDING + contentWidth}" y2="${y}" stroke="${escapeXml(theme.border)}" stroke-width="1"/>`);
1730
1736
  y += SECTION_GAP;
1731
- const numCards = 4;
1732
- const cardWidth = contentWidth / numCards;
1737
+ const col1Width = contentWidth * 0.35;
1738
+ const col2Width = contentWidth * 0.35;
1739
+ const col3Width = contentWidth * 0.15;
1740
+ const col4Width = contentWidth * 0.15;
1733
1741
  const topModel = stats.topModels.length > 0 ? stats.topModels[0] : null;
1734
- const topModelLabel = topModel ? `${topModel.model} (${formatNumber(topModel.tokens)})` : "N/A";
1742
+ const topModelLabel = topModel ? truncateText(`${topModel.model} (${formatNumber(topModel.tokens)})`, MAX_STAT_VALUE_CHARS) : "N/A";
1735
1743
  sections.push(renderBottomStat(PADDING, y, "MOST USED MODEL", topModelLabel, theme));
1736
- const recent30Label = stats.rolling30dTopModel ? `${stats.rolling30dTopModel} (${formatNumber(stats.rolling30dTokens)})` : formatNumber(stats.rolling30dTokens);
1737
- sections.push(renderBottomStat(PADDING + cardWidth, y, "RECENT USE (LAST 30 DAYS)", recent30Label, theme));
1738
- sections.push(renderBottomStat(PADDING + cardWidth * 2, y, "LONGEST STREAK", `${stats.longestStreak} days`, theme));
1739
- sections.push(renderBottomStat(PADDING + cardWidth * 3, y, "CURRENT STREAK", `${stats.currentStreak} days`, theme));
1744
+ const recent30Label = stats.rolling30dTopModel ? truncateText(`${stats.rolling30dTopModel} (${formatNumber(stats.rolling30dTokens)})`, MAX_STAT_VALUE_CHARS) : formatNumber(stats.rolling30dTokens);
1745
+ sections.push(renderBottomStat(PADDING + col1Width, y, "RECENT USE (LAST 30 DAYS)", recent30Label, theme));
1746
+ sections.push(renderBottomStat(PADDING + col1Width + col2Width, y, "LONGEST STREAK", `${stats.longestStreak} days`, theme));
1747
+ sections.push(renderBottomStat(PADDING + col1Width + col2Width + col3Width, y, "CURRENT STREAK", `${stats.currentStreak} days`, theme));
1740
1748
  y += 56 + SECTION_GAP;
1749
+ const evenCardWidth = contentWidth / 4;
1741
1750
  sections.push(`<line x1="${PADDING}" y1="${y - SECTION_GAP / 2}" x2="${PADDING + contentWidth}" y2="${y - SECTION_GAP / 2}" stroke="${escapeXml(theme.border)}" stroke-width="1"/>`);
1742
1751
  sections.push(renderBottomStat(PADDING, y, "TOTAL COST", stats.totalCost >= 100 ? `$${stats.totalCost.toFixed(0)}` : `$${stats.totalCost.toFixed(2)}`, theme));
1743
- sections.push(renderBottomStat(PADDING + cardWidth, y, "CACHE HIT RATE", `${(stats.cacheHitRate * 100).toFixed(1)}%`, theme));
1744
- sections.push(renderBottomStat(PADDING + cardWidth * 2, y, "ACTIVE DAYS", `${stats.activeDays} / ${stats.totalDays}`, theme));
1745
- sections.push(renderBottomStat(PADDING + cardWidth * 3, y, "AVG DAILY TOKENS", formatNumber(stats.averageDailyTokens), theme));
1752
+ sections.push(renderBottomStat(PADDING + evenCardWidth, y, "CACHE HIT RATE", `${(stats.cacheHitRate * 100).toFixed(1)}%`, theme));
1753
+ sections.push(renderBottomStat(PADDING + evenCardWidth * 2, y, "ACTIVE DAYS", `${stats.activeDays} / ${stats.totalDays}`, theme));
1754
+ sections.push(renderBottomStat(PADDING + evenCardWidth * 3, y, "AVG DAILY TOKENS", formatNumber(stats.averageDailyTokens), theme));
1746
1755
  y += 56 + PADDING;
1747
1756
  const totalHeight = y;
1748
1757
  const svgWidth = Math.max(contentWidth + PADDING * 2, MIN_SVG_WIDTH);