ccstatusline-usage 2.3.11 → 2.3.13

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/README.md CHANGED
@@ -67,6 +67,17 @@ Session: [████░░░░░░░░░░░] 27.0% | Weekly: [██
67
67
 
68
68
  ## 🆕 Recent Updates
69
69
 
70
+ ### [v2.3.13](https://github.com/pcvelz/ccstatusline-usage/releases/tag/v2.3.13) - Fix timer color regression from v2.3.12
71
+
72
+ - [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Fix timer color** — In v2.3.12, the Reset Timer widget color setting was applied to both the `Extra: €X/€Y` output and the countdown timer (e.g. `4:28 hr`), causing the timer to appear red. The dark red is now applied inline only to the `Extra:` path; the countdown timer respects the widget's configured color as before.
73
+
74
+ ### [v2.3.12](https://github.com/pcvelz/ccstatusline-usage/releases/tag/v2.3.12) - Split bar for extra usage, stable effective-total, 100% clamp
75
+
76
+ - [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Split bar at 100%** — Session and Weekly usage bars switch to a split display when the limit is reached and extra usage is active: left half (full) shows the base usage, right half (dark red) shows how much of the extra budget has been spent.
77
+ - [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Stable effective-total** — Set `extraUsageBalance` (cents) in `~/.config/ccstatusline/settings.json` to your spending ceiling (`spent + account_balance` at config time, e.g. €153.23 + €56.06 → `20929`). The denominator stays fixed as spending continues, capped at the API monthly limit. Without this setting, the monthly limit is used directly.
78
+ - [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Extra usage color via config** — The `Extra: €X/€Y` Reset Timer output color is now driven by the widget's color setting (configurable in TUI or settings.json) instead of being hardcoded.
79
+ - [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Usage clamped to 100%** — Session and Weekly bars and percentage labels cap at 100% even if the API returns values above 100.
80
+
70
81
  ### [v2.3.11](https://github.com/pcvelz/ccstatusline-usage/releases/tag/v2.3.11) - Fix dual-cache drift between Weekly Usage and Weekly Pace
71
82
 
72
83
  - [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Unified usage data source** — Session Usage, Weekly Usage, and Reset Timer widgets now read from the shared `context.usageData` pipeline instead of maintaining a separate API cache. Previously, around the weekly reset boundary the two caches could drift and show contradictory data (e.g. `Weekly: 99%` alongside `Pace: D1/7 +2%`). Deleted ~330 lines of duplicate fetching/caching infrastructure from `ApiUsage.tsx` (556 → 227 lines). Upstream merge: #278 (JSONL token overcounting fix), #283 (model display name parenthetical strip — integrated into fork's existing `[1m]`-aware display logic).
@@ -55593,7 +55593,7 @@ function getTerminalWidth() {
55593
55593
  function canDetectTerminalWidth() {
55594
55594
  return probeTerminalWidth() !== null;
55595
55595
  }
55596
- var __dirname = "/Users/peter/Documents/Code/ccstatusline-usage/src/utils", PACKAGE_VERSION = "2.3.11";
55596
+ var __dirname = "/Users/peter/Documents/Code/ccstatusline-usage/src/utils", PACKAGE_VERSION = "2.3.13";
55597
55597
  var init_terminal = () => {};
55598
55598
 
55599
55599
  // src/utils/renderer.ts
@@ -62130,6 +62130,13 @@ function getUsageErrorMessage(error48) {
62130
62130
  return "[Parse Error]";
62131
62131
  }
62132
62132
  }
62133
+ function makeSplitUsageBar(extraPercent, totalWidth) {
62134
+ const halfWidth = Math.floor((totalWidth - 1) / 2);
62135
+ const clamped = Math.max(0, Math.min(100, extraPercent));
62136
+ const rightFilled = Math.round(clamped / 100 * halfWidth);
62137
+ const rightEmpty = halfWidth - rightFilled;
62138
+ return "[" + "█".repeat(halfWidth) + "|" + DARK_RED_OPEN + "█".repeat(rightFilled) + "░".repeat(rightEmpty) + DARK_RED_CLOSE + "]";
62139
+ }
62133
62140
  function makePendulumBar(delta, halfWidth = 7) {
62134
62141
  const clamped = Math.max(-100, Math.min(100, delta));
62135
62142
  const fill2 = Math.min(halfWidth, Math.round(Math.abs(clamped) / 100 * halfWidth));
@@ -62138,6 +62145,7 @@ function makePendulumBar(delta, halfWidth = 7) {
62138
62145
  }
62139
62146
  return "[" + "░".repeat(halfWidth) + "|" + "█".repeat(fill2) + "░".repeat(halfWidth - fill2) + "]";
62140
62147
  }
62148
+ var DARK_RED_OPEN = "\x1B[38;2;204;0;0m", DARK_RED_CLOSE = "\x1B[39m";
62141
62149
  var init_usage_windows = __esm(() => {
62142
62150
  init_jsonl();
62143
62151
  init_usage_types();
@@ -63140,13 +63148,28 @@ function getBarWidth(size2) {
63140
63148
  return DEFAULT_BAR_WIDTH;
63141
63149
  }
63142
63150
  function makeProgressBar(percent, width = DEFAULT_BAR_WIDTH) {
63143
- const filled = Math.round(percent / 100 * width);
63151
+ const clamped = Math.min(100, Math.max(0, percent));
63152
+ const filled = Math.round(clamped / 100 * width);
63144
63153
  const empty2 = width - filled;
63145
63154
  return "[" + "█".repeat(filled) + "░".repeat(empty2) + "]";
63146
63155
  }
63147
63156
  function formatUsageBar(label, shortLabel, percent, size2) {
63148
63157
  const bar = makeProgressBar(percent, getBarWidth(size2));
63149
- return `${size2 === "mobile" ? shortLabel : label}: ${bar} ${percent.toFixed(1)}%`;
63158
+ const display = Math.min(100, percent);
63159
+ return `${size2 === "mobile" ? shortLabel : label}: ${bar} ${display.toFixed(1)}%`;
63160
+ }
63161
+ function formatSplitUsageBar(label, shortLabel, extraPercent, size2) {
63162
+ const bar = makeSplitUsageBar(extraPercent, getBarWidth(size2));
63163
+ return `${size2 === "mobile" ? shortLabel : label}: ${bar} 100.0%`;
63164
+ }
63165
+ function computeEffectiveTotal(extraUsed, extraLimit, ceiling) {
63166
+ if (ceiling === undefined)
63167
+ return extraLimit;
63168
+ return Math.min(ceiling, extraLimit);
63169
+ }
63170
+ function computeExtraPercent(extraUsed, extraLimit, ceiling) {
63171
+ const denominator = computeEffectiveTotal(extraUsed, extraLimit, ceiling);
63172
+ return denominator > 0 ? extraUsed / denominator * 100 : 0;
63150
63173
  }
63151
63174
  function getCurrencySymbol() {
63152
63175
  try {
@@ -63177,7 +63200,7 @@ class SessionUsageWidget {
63177
63200
  getEditorDisplay(_item) {
63178
63201
  return { displayText: this.getDisplayName() };
63179
63202
  }
63180
- render(_item, context, _settings) {
63203
+ render(_item, context, settings) {
63181
63204
  if (context.isPreview)
63182
63205
  return "Session: [███░░░░░░░░░░░░] 20%";
63183
63206
  const data = context.usageData ?? {};
@@ -63185,7 +63208,14 @@ class SessionUsageWidget {
63185
63208
  return getUsageErrorMessage(data.error);
63186
63209
  if (data.sessionUsage === undefined)
63187
63210
  return null;
63188
- return formatUsageBar("Session", "S", data.sessionUsage, getDisplaySize(context));
63211
+ const size2 = getDisplaySize(context);
63212
+ const extraUsed = data.extraUsageUsed;
63213
+ const extraLimit = data.extraUsageLimit;
63214
+ if (size2 !== "mobile" && data.extraUsageEnabled === true && extraUsed !== undefined && extraLimit !== undefined && data.sessionUsage >= 100 && (data.weeklyUsage === undefined || data.weeklyUsage < 100)) {
63215
+ const extraPercent = computeExtraPercent(extraUsed, extraLimit, settings.extraUsageBalance);
63216
+ return formatSplitUsageBar("Session", "S", extraPercent, size2);
63217
+ }
63218
+ return formatUsageBar("Session", "S", data.sessionUsage, size2);
63189
63219
  }
63190
63220
  supportsRawValue() {
63191
63221
  return false;
@@ -63211,7 +63241,7 @@ class WeeklyUsageWidget {
63211
63241
  getEditorDisplay(_item) {
63212
63242
  return { displayText: this.getDisplayName() };
63213
63243
  }
63214
- render(_item, context, _settings) {
63244
+ render(_item, context, settings) {
63215
63245
  if (context.isPreview)
63216
63246
  return "Weekly: [██░░░░░░░░░░░░░] 12%";
63217
63247
  const data = context.usageData ?? {};
@@ -63219,7 +63249,14 @@ class WeeklyUsageWidget {
63219
63249
  return getUsageErrorMessage(data.error);
63220
63250
  if (data.weeklyUsage === undefined)
63221
63251
  return null;
63222
- return formatUsageBar("Weekly", "W", data.weeklyUsage, getDisplaySize(context));
63252
+ const size2 = getDisplaySize(context);
63253
+ const extraUsed = data.extraUsageUsed;
63254
+ const extraLimit = data.extraUsageLimit;
63255
+ if (size2 !== "mobile" && data.extraUsageEnabled === true && extraUsed !== undefined && extraLimit !== undefined && data.weeklyUsage >= 100) {
63256
+ const extraPercent = computeExtraPercent(extraUsed, extraLimit, settings.extraUsageBalance);
63257
+ return formatSplitUsageBar("Weekly", "W", extraPercent, size2);
63258
+ }
63259
+ return formatUsageBar("Weekly", "W", data.weeklyUsage, size2);
63223
63260
  }
63224
63261
  supportsRawValue() {
63225
63262
  return false;
@@ -63258,9 +63295,9 @@ class ResetTimerWidget {
63258
63295
  const isChargedModel = is1mModel && !isOpus;
63259
63296
  if (data.extraUsageEnabled && data.extraUsageUsed !== undefined && data.extraUsageLimit !== undefined && (data.weeklyUsage !== undefined && data.weeklyUsage >= 100 || data.sessionUsage !== undefined && data.sessionUsage >= 100 || isChargedModel)) {
63260
63297
  const used = formatCents(data.extraUsageUsed);
63261
- const displayLimit = settings.extraUsageBalance ?? data.extraUsageLimit;
63262
- const limit = formatCents(displayLimit);
63263
- return `Extra: ${used}/${limit}`;
63298
+ const effectiveTotal = computeEffectiveTotal(data.extraUsageUsed, data.extraUsageLimit, settings.extraUsageBalance);
63299
+ const limit = formatCents(effectiveTotal);
63300
+ return `${DARK_RED_OPEN2}Extra: ${used}/${limit}${DARK_RED_CLOSE2}`;
63264
63301
  }
63265
63302
  if (!data.sessionResetAt)
63266
63303
  return null;
@@ -63333,7 +63370,7 @@ class ContextBarWidget {
63333
63370
  return true;
63334
63371
  }
63335
63372
  }
63336
- var MOBILE_THRESHOLD = 134, MEDIUM_THRESHOLD2 = 178, MOBILE_BAR_WIDTH = 4, MEDIUM_BAR_WIDTH = 8, DEFAULT_BAR_WIDTH = 15;
63373
+ var DARK_RED_OPEN2 = "\x1B[38;2;204;0;0m", DARK_RED_CLOSE2 = "\x1B[39m", MOBILE_THRESHOLD = 134, MEDIUM_THRESHOLD2 = 178, MOBILE_BAR_WIDTH = 4, MEDIUM_BAR_WIDTH = 8, DEFAULT_BAR_WIDTH = 15;
63337
63374
  var init_ApiUsage = __esm(() => {
63338
63375
  init_usage();
63339
63376
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccstatusline-usage",
3
- "version": "2.3.11",
3
+ "version": "2.3.13",
4
4
  "description": "A customizable status line formatter for Claude Code CLI",
5
5
  "module": "src/ccstatusline.ts",
6
6
  "type": "module",