ccusage 15.5.2 → 15.6.0

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/dist/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import { BLOCKS_COMPACT_WIDTH_THRESHOLD, BLOCKS_DEFAULT_TERMINAL_WIDTH, BLOCKS_WARNING_THRESHOLD, BURN_RATE_THRESHOLDS, DEFAULT_RECENT_DAYS, DEFAULT_REFRESH_INTERVAL_SECONDS, MAX_REFRESH_INTERVAL_SECONDS, MCP_DEFAULT_PORT, MIN_REFRESH_INTERVAL_SECONDS, MIN_RENDER_INTERVAL_MS, PROJECT_ALIASES_ENV, PricingFetcher, __commonJSMin, __require, __toESM, isFailure, require_usingCtx, try_ } from "./pricing-fetcher-B5b61mDE.js";
2
+ import { BLOCKS_COMPACT_WIDTH_THRESHOLD, BLOCKS_DEFAULT_TERMINAL_WIDTH, BLOCKS_WARNING_THRESHOLD, BURN_RATE_THRESHOLDS, DEFAULT_RECENT_DAYS, DEFAULT_REFRESH_INTERVAL_SECONDS, MAX_REFRESH_INTERVAL_SECONDS, MCP_DEFAULT_PORT, MIN_REFRESH_INTERVAL_SECONDS, MIN_RENDER_INTERVAL_MS, PROJECT_ALIASES_ENV, PricingFetcher, WEEK_DAYS, __commonJSMin, __require, __toESM, isFailure, require_usingCtx, try_ } from "./pricing-fetcher-CNjC0nXU.js";
3
3
  import { getTotalTokens } from "./_token-utils-WjkbrjKv.js";
4
- import { CostModes, SortOrders, filterDateSchema } from "./_types-BHFM59hI.js";
4
+ import { CostModes, SortOrders, filterDateSchema } from "./_types-ed8-0BH6.js";
5
5
  import { calculateTotals, createTotalsObject } from "./calculate-cost-BDqO4yWA.js";
6
- import { DEFAULT_SESSION_DURATION_HOURS, calculateBurnRate, calculateCostForEntry, createUniqueHash, filterRecentBlocks, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, globUsageFiles, identifySessionBlocks, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, projectBlockUsage, sortFilesByTimestamp, uniq, usageDataSchema } from "./data-loader-CmW1xurn.js";
7
- import { description, log, logger, name, version } from "./logger-D0z-I-_d.js";
8
- import { detectMismatches, printMismatchReport } from "./debug-kkVHYWpk.js";
9
- import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-DbViDMcM.js";
6
+ import { DEFAULT_SESSION_DURATION_HOURS, calculateBurnRate, calculateCostForEntry, createUniqueHash, filterRecentBlocks, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, globUsageFiles, identifySessionBlocks, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, loadWeeklyUsageData, projectBlockUsage, sortFilesByTimestamp, uniq, usageDataSchema } from "./data-loader-CwryIrwx.js";
7
+ import { description, log, logger, name, version } from "./logger-C35JCduT.js";
8
+ import { detectMismatches, printMismatchReport } from "./debug-C8bVFK5q.js";
9
+ import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-CqzLeEbX.js";
10
10
  import { readFile } from "node:fs/promises";
11
11
  import process$1 from "node:process";
12
12
  import { createServer } from "node:http";
@@ -141,7 +141,7 @@ function createTranslationAdapter(options) {
141
141
  return new DefaultTranslation(options);
142
142
  }
143
143
  var DefaultTranslation = class {
144
- #resources = /* @__PURE__ */ new Map();
144
+ #resources = new Map();
145
145
  #options;
146
146
  constructor(options) {
147
147
  this.#options = options;
@@ -193,7 +193,7 @@ async function createCommandContext({ args, values, positionals, rest, argv: arg
193
193
  locale: localeStr,
194
194
  fallbackLocale: DEFAULT_LOCALE
195
195
  });
196
- const localeResources = /* @__PURE__ */ new Map();
196
+ const localeResources = new Map();
197
197
  let builtInLoadedResources;
198
198
  /**
199
199
  * load the built-in locale resources
@@ -2157,7 +2157,7 @@ var require_colors = __commonJSMin((exports, module) => {
2157
2157
  var util = __require("node:util");
2158
2158
  var ansiStyles = colors$1.styles = require_styles();
2159
2159
  var defineProps = Object.defineProperties;
2160
- var newLineRegex = /* @__PURE__ */ new RegExp(/[\r\n]+/g);
2160
+ var newLineRegex = new RegExp(/[\r\n]+/g);
2161
2161
  colors$1.supportsColor = require_supports_colors().supportsColor;
2162
2162
  if (typeof colors$1.enabled === "undefined") colors$1.enabled = colors$1.supportsColor() !== false;
2163
2163
  colors$1.enable = function() {
@@ -2939,7 +2939,7 @@ function stringWidth(string, options = {}) {
2939
2939
  return width;
2940
2940
  }
2941
2941
  var import_cli_table3 = __toESM(require_cli_table3(), 1);
2942
- var import_picocolors$6 = __toESM(require_picocolors(), 1);
2942
+ var import_picocolors$7 = __toESM(require_picocolors(), 1);
2943
2943
  /**
2944
2944
  * Responsive table class that adapts column widths based on terminal size
2945
2945
  * Automatically adjusts formatting and layout for different screen sizes
@@ -3175,7 +3175,7 @@ function pushBreakdownRows(table, breakdowns, extraColumns = 1, trailingColumns
3175
3175
  const row = [` └─ ${formatModelName(breakdown.modelName)}`];
3176
3176
  for (let i = 0; i < extraColumns; i++) row.push("");
3177
3177
  const totalTokens = breakdown.inputTokens + breakdown.outputTokens + breakdown.cacheCreationTokens + breakdown.cacheReadTokens;
3178
- row.push(import_picocolors$6.default.gray(formatNumber(breakdown.inputTokens)), import_picocolors$6.default.gray(formatNumber(breakdown.outputTokens)), import_picocolors$6.default.gray(formatNumber(breakdown.cacheCreationTokens)), import_picocolors$6.default.gray(formatNumber(breakdown.cacheReadTokens)), import_picocolors$6.default.gray(formatNumber(totalTokens)), import_picocolors$6.default.gray(formatCurrency(breakdown.cost)));
3178
+ row.push(import_picocolors$7.default.gray(formatNumber(breakdown.inputTokens)), import_picocolors$7.default.gray(formatNumber(breakdown.outputTokens)), import_picocolors$7.default.gray(formatNumber(breakdown.cacheCreationTokens)), import_picocolors$7.default.gray(formatNumber(breakdown.cacheReadTokens)), import_picocolors$7.default.gray(formatNumber(totalTokens)), import_picocolors$7.default.gray(formatCurrency(breakdown.cost)));
3179
3179
  for (let i = 0; i < trailingColumns; i++) row.push("");
3180
3180
  table.push(row);
3181
3181
  }
@@ -3186,8 +3186,8 @@ function pushBreakdownRows(table, breakdowns, extraColumns = 1, trailingColumns
3186
3186
  var LiveMonitor = class {
3187
3187
  config;
3188
3188
  fetcher = null;
3189
- lastFileTimestamps = /* @__PURE__ */ new Map();
3190
- processedHashes = /* @__PURE__ */ new Set();
3189
+ lastFileTimestamps = new Map();
3190
+ processedHashes = new Set();
3191
3191
  allEntries = [];
3192
3192
  constructor(config) {
3193
3193
  this.config = config;
@@ -3343,6 +3343,7 @@ const cursorTo = (x, y) => {
3343
3343
  if (typeof y !== "number") return ESC + (x + 1) + "G";
3344
3344
  return ESC + (y + 1) + SEP + (x + 1) + "H";
3345
3345
  };
3346
+ const cursorForward = (count = 1) => ESC + count + "C";
3346
3347
  const cursorLeft = ESC + "G";
3347
3348
  const cursorSavePosition = isTerminalApp ? "\x1B7" : ESC + "s";
3348
3349
  const cursorRestorePosition = isTerminalApp ? "\x1B8" : ESC + "u";
@@ -3678,16 +3679,26 @@ function centerText(text, width) {
3678
3679
  const rightPadding = width - textLength - leftPadding;
3679
3680
  return " ".repeat(leftPadding) + text + " ".repeat(rightPadding);
3680
3681
  }
3681
- var import_picocolors$5 = __toESM(require_picocolors(), 1);
3682
+ const SAVE_CURSOR = "\x1B7";
3683
+ const RESTORE_CURSOR = "\x1B8";
3684
+ /**
3685
+ * Draws an emoji with consistent 2-character width regardless of terminal behavior
3686
+ * @param emoji The emoji to draw
3687
+ * @returns A string containing ANSI escape sequences and the emoji
3688
+ */
3689
+ function drawEmoji(emoji) {
3690
+ return `${SAVE_CURSOR}${emoji}${RESTORE_CURSOR}${cursorForward(stringWidth(emoji))}`;
3691
+ }
3692
+ var import_picocolors$6 = __toESM(require_picocolors(), 1);
3682
3693
  /**
3683
3694
  * Get rate indicator (HIGH/MODERATE/NORMAL) based on burn rate
3684
3695
  */
3685
3696
  function getRateIndicator(burnRate) {
3686
3697
  if (burnRate == null) return "";
3687
3698
  switch (true) {
3688
- case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.HIGH: return import_picocolors$5.default.red("⚡ HIGH");
3689
- case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.MODERATE: return import_picocolors$5.default.yellow("⚡ MODERATE");
3690
- default: return import_picocolors$5.default.green("✓ NORMAL");
3699
+ case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.HIGH: return import_picocolors$6.default.red(`${drawEmoji("⚡")} HIGH`);
3700
+ case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.MODERATE: return import_picocolors$6.default.yellow(`${drawEmoji("⚡")} MODERATE`);
3701
+ default: return import_picocolors$6.default.green(`${drawEmoji("✓")} NORMAL`);
3691
3702
  }
3692
3703
  }
3693
3704
  /**
@@ -3704,7 +3715,7 @@ async function renderWaitingState(terminal, config, signal) {
3704
3715
  terminal.startBuffering();
3705
3716
  terminal.write(cursorTo(0, 0));
3706
3717
  terminal.write(eraseDown);
3707
- terminal.write(import_picocolors$5.default.yellow("No active session block found. Waiting...\n"));
3718
+ terminal.write(import_picocolors$6.default.yellow("No active session block found. Waiting...\n"));
3708
3719
  terminal.write(cursorHide);
3709
3720
  terminal.flush();
3710
3721
  await delayWithAbort(config.refreshInterval, signal);
@@ -3733,7 +3744,7 @@ function formatTokensShort(num) {
3733
3744
  */
3734
3745
  function renderLiveDisplay(terminal, block, config) {
3735
3746
  const width = terminal.width;
3736
- const now = /* @__PURE__ */ new Date();
3747
+ const now = new Date();
3737
3748
  const totalTokens = getTotalTokens(block.tokenCounts);
3738
3749
  const elapsed = (now.getTime() - block.startTime.getTime()) / (1e3 * 60);
3739
3750
  const remaining = (block.endTime.getTime() - now.getTime()) / (1e3 * 60);
@@ -3762,8 +3773,8 @@ function renderLiveDisplay(terminal, block, config) {
3762
3773
  const barWidth = boxWidth - labelWidth - maxRightTextWidth - spacing - boxPadding;
3763
3774
  const sessionProgressBar = createProgressBar(elapsed, sessionDuration, barWidth, {
3764
3775
  showPercentage: false,
3765
- fillChar: import_picocolors$5.default.cyan("█"),
3766
- emptyChar: import_picocolors$5.default.gray("░"),
3776
+ fillChar: import_picocolors$6.default.cyan("█"),
3777
+ emptyChar: import_picocolors$6.default.gray("░"),
3767
3778
  leftBracket: "[",
3768
3779
  rightBracket: "]"
3769
3780
  });
@@ -3783,17 +3794,17 @@ function renderLiveDisplay(terminal, block, config) {
3783
3794
  const detailsSpacing = 2;
3784
3795
  const detailsAvailableWidth = boxWidth - 3 - detailsIndent;
3785
3796
  terminal.write(`${marginStr}┌${"─".repeat(boxWidth - 2)}┐\n`);
3786
- terminal.write(`${marginStr}│${import_picocolors$5.default.bold(centerText("CLAUDE CODE - LIVE TOKEN USAGE MONITOR", boxWidth - 2))}│\n`);
3797
+ terminal.write(`${marginStr}│${import_picocolors$6.default.bold(centerText("CLAUDE CODE - LIVE TOKEN USAGE MONITOR", boxWidth - 2))}│\n`);
3787
3798
  terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
3788
3799
  terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
3789
- const sessionLabel = import_picocolors$5.default.bold("⏱️ SESSION");
3800
+ const sessionLabel = `${drawEmoji("⏱️")}${import_picocolors$6.default.bold(" SESSION")}`;
3790
3801
  const sessionLabelWidth = stringWidth(sessionLabel);
3791
3802
  const sessionBarStr = `${sessionLabel}${"".padEnd(Math.max(0, labelWidth - sessionLabelWidth))} ${sessionProgressBar} ${sessionRightText}`;
3792
3803
  const sessionBarPadded = sessionBarStr + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(sessionBarStr)));
3793
3804
  terminal.write(`${marginStr}│ ${sessionBarPadded}│\n`);
3794
- const sessionCol1 = `${import_picocolors$5.default.gray("Started:")} ${startTime}`;
3795
- const sessionCol2 = `${import_picocolors$5.default.gray("Elapsed:")} ${prettyMilliseconds(elapsed * 60 * 1e3, { compact: true })}`;
3796
- const sessionCol3 = `${import_picocolors$5.default.gray("Remaining:")} ${prettyMilliseconds(remaining * 60 * 1e3, { compact: true })} (${endTime})`;
3805
+ const sessionCol1 = `${import_picocolors$6.default.gray("Started:")} ${startTime}`;
3806
+ const sessionCol2 = `${import_picocolors$6.default.gray("Elapsed:")} ${prettyMilliseconds(elapsed * 60 * 1e3, { compact: true })}`;
3807
+ const sessionCol3 = `${import_picocolors$6.default.gray("Remaining:")} ${prettyMilliseconds(remaining * 60 * 1e3, { compact: true })} (${endTime})`;
3797
3808
  let sessionDetails = `${" ".repeat(detailsIndent)}${sessionCol1}${" ".repeat(detailsSpacing)}${sessionCol2}${" ".repeat(detailsSpacing)}${sessionCol3}`;
3798
3809
  const sessionDetailsWidth = stringWidth(sessionCol1) + stringWidth(sessionCol2) + stringWidth(sessionCol3) + detailsSpacing * 2;
3799
3810
  if (sessionDetailsWidth > detailsAvailableWidth) sessionDetails = `${" ".repeat(detailsIndent)}${sessionCol1}${" ".repeat(detailsSpacing)}${sessionCol3}`;
@@ -3805,7 +3816,7 @@ function renderLiveDisplay(terminal, block, config) {
3805
3816
  minute: "2-digit",
3806
3817
  hour12: true
3807
3818
  }) ?? null;
3808
- const usageLimitResetTime = resetTime !== null ? import_picocolors$5.default.red(`❌ USAGE LIMIT. RESET AT ${resetTime}`) : "";
3819
+ const usageLimitResetTime = resetTime !== null ? import_picocolors$6.default.red(`${drawEmoji("❌")} USAGE LIMIT. RESET AT ${resetTime}`) : "";
3809
3820
  usageLimitResetTimePadded = resetTime !== null ? usageLimitResetTime + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(usageLimitResetTime))) : null;
3810
3821
  }
3811
3822
  terminal.write(`${marginStr}│ ${sessionDetailsPadded}│\n`);
@@ -3813,31 +3824,31 @@ function renderLiveDisplay(terminal, block, config) {
3813
3824
  terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
3814
3825
  terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
3815
3826
  terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
3816
- let barColor = import_picocolors$5.default.green;
3817
- if (tokenPercent > 100) barColor = import_picocolors$5.default.red;
3818
- else if (tokenPercent > 80) barColor = import_picocolors$5.default.yellow;
3827
+ let barColor = import_picocolors$6.default.green;
3828
+ if (tokenPercent > 100) barColor = import_picocolors$6.default.red;
3829
+ else if (tokenPercent > 80) barColor = import_picocolors$6.default.yellow;
3819
3830
  const usageBar = config.tokenLimit != null && config.tokenLimit > 0 ? createProgressBar(totalTokens, config.tokenLimit, barWidth, {
3820
3831
  showPercentage: false,
3821
3832
  fillChar: barColor("█"),
3822
- emptyChar: import_picocolors$5.default.gray("░"),
3833
+ emptyChar: import_picocolors$6.default.gray("░"),
3823
3834
  leftBracket: "[",
3824
3835
  rightBracket: "]"
3825
- }) : `[${import_picocolors$5.default.green("█".repeat(Math.floor(barWidth * .1)))}${import_picocolors$5.default.gray("░".repeat(barWidth - Math.floor(barWidth * .1)))}]`;
3836
+ }) : `[${import_picocolors$6.default.green("█".repeat(Math.floor(barWidth * .1)))}${import_picocolors$6.default.gray("░".repeat(barWidth - Math.floor(barWidth * .1)))}]`;
3826
3837
  const burnRate = calculateBurnRate(block);
3827
3838
  const rateIndicator = getRateIndicator(burnRate);
3828
3839
  const buildRateDisplay = (useShort) => {
3829
- if (burnRate == null) return `${import_picocolors$5.default.bold("Burn Rate:")} N/A`;
3840
+ if (burnRate == null) return `${import_picocolors$6.default.bold("Burn Rate:")} N/A`;
3830
3841
  const rateValue = Math.round(burnRate.tokensPerMinute);
3831
3842
  const formattedRate = useShort ? formatTokensShort(rateValue) : formatNumber(rateValue);
3832
- return `${import_picocolors$5.default.bold("Burn Rate:")} ${formattedRate} token/min ${rateIndicator}`;
3843
+ return `${import_picocolors$6.default.bold("Burn Rate:")} ${formattedRate} token/min ${rateIndicator}`;
3833
3844
  };
3834
- const usageLabel = import_picocolors$5.default.bold("🔥 USAGE");
3845
+ const usageLabel = `${drawEmoji("🔥")}${import_picocolors$6.default.bold(" USAGE")}`;
3835
3846
  const usageLabelWidth = stringWidth(usageLabel);
3836
3847
  const usageBarStr = `${usageLabel}${"".padEnd(Math.max(0, labelWidth - usageLabelWidth))} ${usageBar} ${usageRightText}`;
3837
3848
  let rateDisplay = buildRateDisplay(false);
3838
- let usageCol1 = `${import_picocolors$5.default.gray("Tokens:")} ${formatTokenDisplay(totalTokens, false)} (${rateDisplay})`;
3839
- let usageCol2 = config.tokenLimit != null && config.tokenLimit > 0 ? `${import_picocolors$5.default.gray("Limit:")} ${formatTokenDisplay(config.tokenLimit, false)} tokens` : "";
3840
- const usageCol3 = `${import_picocolors$5.default.gray("Cost:")} ${formatCurrency(block.costUSD)}`;
3849
+ let usageCol1 = `${import_picocolors$6.default.gray("Tokens:")} ${formatTokenDisplay(totalTokens, false)} (${rateDisplay})`;
3850
+ let usageCol2 = config.tokenLimit != null && config.tokenLimit > 0 ? `${import_picocolors$6.default.gray("Limit:")} ${formatTokenDisplay(config.tokenLimit, false)} tokens` : "";
3851
+ const usageCol3 = `${import_picocolors$6.default.gray("Cost:")} ${formatCurrency(block.costUSD)}`;
3841
3852
  let totalWidth = stringWidth(usageCol1);
3842
3853
  if (usageCol2.length > 0) totalWidth += detailsSpacing + stringWidth(usageCol2);
3843
3854
  totalWidth += detailsSpacing + stringWidth(usageCol3);
@@ -3845,8 +3856,8 @@ function renderLiveDisplay(terminal, block, config) {
3845
3856
  if (totalWidth > detailsAvailableWidth) {
3846
3857
  useTwoLineLayout = true;
3847
3858
  rateDisplay = buildRateDisplay(true);
3848
- usageCol1 = `${import_picocolors$5.default.gray("Tokens:")} ${formatTokenDisplay(totalTokens, true)} (${rateDisplay})`;
3849
- if (usageCol2.length > 0) usageCol2 = `${import_picocolors$5.default.gray("Limit:")} ${formatTokenDisplay(config.tokenLimit, true)} tokens`;
3859
+ usageCol1 = `${import_picocolors$6.default.gray("Tokens:")} ${formatTokenDisplay(totalTokens, true)} (${rateDisplay})`;
3860
+ if (usageCol2.length > 0) usageCol2 = `${import_picocolors$6.default.gray("Limit:")} ${formatTokenDisplay(config.tokenLimit, true)} tokens`;
3850
3861
  }
3851
3862
  const usageBarPadded = usageBarStr + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(usageBarStr)));
3852
3863
  terminal.write(`${marginStr}│ ${usageBarPadded}│\n`);
@@ -3870,30 +3881,30 @@ function renderLiveDisplay(terminal, block, config) {
3870
3881
  terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
3871
3882
  terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
3872
3883
  if (projection != null) {
3873
- let projBarColor = import_picocolors$5.default.green;
3874
- if (projectedPercent > 100) projBarColor = import_picocolors$5.default.red;
3875
- else if (projectedPercent > 80) projBarColor = import_picocolors$5.default.yellow;
3884
+ let projBarColor = import_picocolors$6.default.green;
3885
+ if (projectedPercent > 100) projBarColor = import_picocolors$6.default.red;
3886
+ else if (projectedPercent > 80) projBarColor = import_picocolors$6.default.yellow;
3876
3887
  const projectionBar = config.tokenLimit != null && config.tokenLimit > 0 ? createProgressBar(projection.totalTokens, config.tokenLimit, barWidth, {
3877
3888
  showPercentage: false,
3878
3889
  fillChar: projBarColor("█"),
3879
- emptyChar: import_picocolors$5.default.gray("░"),
3890
+ emptyChar: import_picocolors$6.default.gray("░"),
3880
3891
  leftBracket: "[",
3881
3892
  rightBracket: "]"
3882
- }) : `[${import_picocolors$5.default.green("█".repeat(Math.floor(barWidth * .15)))}${import_picocolors$5.default.gray("░".repeat(barWidth - Math.floor(barWidth * .15)))}]`;
3883
- const limitStatus = config.tokenLimit != null && config.tokenLimit > 0 ? projectedPercent > 100 ? import_picocolors$5.default.red("❌ WILL EXCEED LIMIT") : projectedPercent > 80 ? import_picocolors$5.default.yellow("⚠️ APPROACHING LIMIT") : import_picocolors$5.default.green("✓ WITHIN LIMIT") : import_picocolors$5.default.green("✓ ON TRACK");
3884
- const projLabel = import_picocolors$5.default.bold("📈 PROJECTION");
3893
+ }) : `[${import_picocolors$6.default.green("█".repeat(Math.floor(barWidth * .15)))}${import_picocolors$6.default.gray("░".repeat(barWidth - Math.floor(barWidth * .15)))}]`;
3894
+ const limitStatus = config.tokenLimit != null && config.tokenLimit > 0 ? projectedPercent > 100 ? import_picocolors$6.default.red(`${drawEmoji("❌")} WILL EXCEED LIMIT`) : projectedPercent > 80 ? import_picocolors$6.default.yellow(`${drawEmoji("⚠️")} APPROACHING LIMIT`) : import_picocolors$6.default.green(`${drawEmoji("✓")} WITHIN LIMIT`) : import_picocolors$6.default.green(`${drawEmoji("✓")} ON TRACK`);
3895
+ const projLabel = `${drawEmoji("📈")}${import_picocolors$6.default.bold(" PROJECTION")}`;
3885
3896
  const projLabelWidth = stringWidth(projLabel);
3886
3897
  const projBarStr = `${projLabel}${"".padEnd(Math.max(0, labelWidth - projLabelWidth))} ${projectionBar} ${projectionRightText}`;
3887
3898
  const projBarPadded = projBarStr + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(projBarStr)));
3888
3899
  terminal.write(`${marginStr}│ ${projBarPadded}│\n`);
3889
- const projCol1 = `${import_picocolors$5.default.gray("Status:")} ${limitStatus}`;
3890
- let projCol2 = `${import_picocolors$5.default.gray("Tokens:")} ${formatTokenDisplay(projection.totalTokens, false)}`;
3891
- const projCol3 = `${import_picocolors$5.default.gray("Cost:")} ${formatCurrency(projection.totalCost)}`;
3900
+ const projCol1 = `${import_picocolors$6.default.gray("Status:")} ${limitStatus}`;
3901
+ let projCol2 = `${import_picocolors$6.default.gray("Tokens:")} ${formatTokenDisplay(projection.totalTokens, false)}`;
3902
+ const projCol3 = `${import_picocolors$6.default.gray("Cost:")} ${formatCurrency(projection.totalCost)}`;
3892
3903
  const projTotalWidth = stringWidth(projCol1) + stringWidth(projCol2) + stringWidth(projCol3) + detailsSpacing * 2;
3893
3904
  let projUseTwoLineLayout = false;
3894
3905
  if (projTotalWidth > detailsAvailableWidth) {
3895
3906
  projUseTwoLineLayout = true;
3896
- projCol2 = `${import_picocolors$5.default.gray("Tokens:")} ${formatTokenDisplay(projection.totalTokens, true)}`;
3907
+ projCol2 = `${import_picocolors$6.default.gray("Tokens:")} ${formatTokenDisplay(projection.totalTokens, true)}`;
3897
3908
  }
3898
3909
  if (projUseTwoLineLayout) {
3899
3910
  const projDetailsLine1 = `${" ".repeat(detailsIndent)}${projCol1}`;
@@ -3911,13 +3922,13 @@ function renderLiveDisplay(terminal, block, config) {
3911
3922
  }
3912
3923
  if (block.models.length > 0) {
3913
3924
  terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
3914
- const modelsLine = `⚙️ Models: ${formatModelsDisplay(block.models)}`;
3925
+ const modelsLine = `${drawEmoji("⚙️")} Models: ${formatModelsDisplay(block.models)}`;
3915
3926
  const modelsLinePadded = modelsLine + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(modelsLine)));
3916
3927
  terminal.write(`${marginStr}│ ${modelsLinePadded}│\n`);
3917
3928
  }
3918
3929
  terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
3919
- const refreshText = `↻ Refreshing every ${config.refreshInterval / 1e3}s • Press Ctrl+C to stop`;
3920
- terminal.write(`${marginStr}│${import_picocolors$5.default.gray(centerText(refreshText, boxWidth - 2))}│\n`);
3930
+ const refreshText = `${drawEmoji("↻")} Refreshing every ${config.refreshInterval / 1e3}s • Press Ctrl+C to stop`;
3931
+ terminal.write(`${marginStr}│${import_picocolors$6.default.gray(centerText(refreshText, boxWidth - 2))}│\n`);
3921
3932
  terminal.write(`${marginStr}└${"─".repeat(boxWidth - 2)}┘\n`);
3922
3933
  }
3923
3934
  /**
@@ -3925,22 +3936,22 @@ function renderLiveDisplay(terminal, block, config) {
3925
3936
  */
3926
3937
  function renderCompactLiveDisplay(terminal, block, config, totalTokens, elapsed, remaining) {
3927
3938
  const width = terminal.width;
3928
- terminal.write(`${import_picocolors$5.default.bold(centerText("LIVE MONITOR", width))}\n`);
3939
+ terminal.write(`${import_picocolors$6.default.bold(centerText("LIVE MONITOR", width))}\n`);
3929
3940
  terminal.write(`${"─".repeat(width)}\n`);
3930
3941
  const sessionPercent = elapsed / (elapsed + remaining) * 100;
3931
3942
  terminal.write(`Session: ${sessionPercent.toFixed(1)}% (${Math.floor(elapsed / 60)}h ${Math.floor(elapsed % 60)}m)\n`);
3932
3943
  if (config.tokenLimit != null && config.tokenLimit > 0) {
3933
3944
  const tokenPercent = totalTokens / config.tokenLimit * 100;
3934
- const status = tokenPercent > 100 ? import_picocolors$5.default.red("OVER") : tokenPercent > 80 ? import_picocolors$5.default.yellow("WARN") : import_picocolors$5.default.green("OK");
3945
+ const status = tokenPercent > 100 ? import_picocolors$6.default.red("OVER") : tokenPercent > 80 ? import_picocolors$6.default.yellow("WARN") : import_picocolors$6.default.green("OK");
3935
3946
  terminal.write(`Tokens: ${formatNumber(totalTokens)}/${formatNumber(config.tokenLimit)} ${status}\n`);
3936
3947
  } else terminal.write(`Tokens: ${formatNumber(totalTokens)}\n`);
3937
3948
  terminal.write(`Cost: ${formatCurrency(block.costUSD)}\n`);
3938
3949
  const burnRate = calculateBurnRate(block);
3939
3950
  if (burnRate != null) terminal.write(`Rate: ${formatNumber(burnRate.tokensPerMinute)}/min\n`);
3940
3951
  terminal.write(`${"─".repeat(width)}\n`);
3941
- terminal.write(import_picocolors$5.default.gray(`Refresh: ${config.refreshInterval / 1e3}s | Ctrl+C: stop\n`));
3952
+ terminal.write(import_picocolors$6.default.gray(`Refresh: ${config.refreshInterval / 1e3}s | Ctrl+C: stop\n`));
3942
3953
  }
3943
- var import_picocolors$4 = __toESM(require_picocolors(), 1);
3954
+ var import_picocolors$5 = __toESM(require_picocolors(), 1);
3944
3955
  var import_usingCtx = __toESM(require_usingCtx(), 1);
3945
3956
  async function startLiveMonitoring(config) {
3946
3957
  try {
@@ -4003,7 +4014,7 @@ async function startLiveMonitoring(config) {
4003
4014
  const errorMessage = error instanceof Error ? error.message : String(error);
4004
4015
  terminal.startBuffering();
4005
4016
  terminal.clearScreen();
4006
- terminal.write(import_picocolors$4.default.red(`Error: ${errorMessage}\n`));
4017
+ terminal.write(import_picocolors$5.default.red(`Error: ${errorMessage}\n`));
4007
4018
  terminal.flush();
4008
4019
  logger.error(`Live monitoring error: ${errorMessage}`);
4009
4020
  await delayWithAbort(config.refreshInterval, abortController.signal).catch(() => {});
@@ -4014,7 +4025,7 @@ async function startLiveMonitoring(config) {
4014
4025
  _usingCtx.d();
4015
4026
  }
4016
4027
  }
4017
- var import_picocolors$3 = __toESM(require_picocolors(), 1);
4028
+ var import_picocolors$4 = __toESM(require_picocolors(), 1);
4018
4029
  /**
4019
4030
  * Formats the time display for a session block
4020
4031
  * @param block - Session block to format
@@ -4038,7 +4049,7 @@ function formatBlockTime(block, compact = false) {
4038
4049
  }
4039
4050
  const duration = block.actualEndTime != null ? Math.round((block.actualEndTime.getTime() - block.startTime.getTime()) / (1e3 * 60)) : 0;
4040
4051
  if (block.isActive) {
4041
- const now = /* @__PURE__ */ new Date();
4052
+ const now = new Date();
4042
4053
  const elapsed = Math.round((now.getTime() - block.startTime.getTime()) / (1e3 * 60));
4043
4054
  const remaining = Math.round((block.endTime.getTime() - now.getTime()) / (1e3 * 60));
4044
4055
  const elapsedHours = Math.floor(elapsed / 60);
@@ -4217,22 +4228,22 @@ const blocksCommand = define({
4217
4228
  const burnRate = calculateBurnRate(block);
4218
4229
  const projection = projectBlockUsage(block);
4219
4230
  logger.box("Current Session Block Status");
4220
- const now = /* @__PURE__ */ new Date();
4231
+ const now = new Date();
4221
4232
  const elapsed = Math.round((now.getTime() - block.startTime.getTime()) / (1e3 * 60));
4222
4233
  const remaining = Math.round((block.endTime.getTime() - now.getTime()) / (1e3 * 60));
4223
- log(`Block Started: ${import_picocolors$3.default.cyan(block.startTime.toLocaleString())} (${import_picocolors$3.default.yellow(`${Math.floor(elapsed / 60)}h ${elapsed % 60}m`)} ago)`);
4224
- log(`Time Remaining: ${import_picocolors$3.default.green(`${Math.floor(remaining / 60)}h ${remaining % 60}m`)}\n`);
4225
- log(import_picocolors$3.default.bold("Current Usage:"));
4234
+ log(`Block Started: ${import_picocolors$4.default.cyan(block.startTime.toLocaleString())} (${import_picocolors$4.default.yellow(`${Math.floor(elapsed / 60)}h ${elapsed % 60}m`)} ago)`);
4235
+ log(`Time Remaining: ${import_picocolors$4.default.green(`${Math.floor(remaining / 60)}h ${remaining % 60}m`)}\n`);
4236
+ log(import_picocolors$4.default.bold("Current Usage:"));
4226
4237
  log(` Input Tokens: ${formatNumber(block.tokenCounts.inputTokens)}`);
4227
4238
  log(` Output Tokens: ${formatNumber(block.tokenCounts.outputTokens)}`);
4228
4239
  log(` Total Cost: ${formatCurrency(block.costUSD)}\n`);
4229
4240
  if (burnRate != null) {
4230
- log(import_picocolors$3.default.bold("Burn Rate:"));
4241
+ log(import_picocolors$4.default.bold("Burn Rate:"));
4231
4242
  log(` Tokens/minute: ${formatNumber(burnRate.tokensPerMinute)}`);
4232
4243
  log(` Cost/hour: ${formatCurrency(burnRate.costPerHour)}\n`);
4233
4244
  }
4234
4245
  if (projection != null) {
4235
- log(import_picocolors$3.default.bold("Projected Usage (if current rate continues):"));
4246
+ log(import_picocolors$4.default.bold("Projected Usage (if current rate continues):"));
4236
4247
  log(` Total Tokens: ${formatNumber(projection.totalTokens)}`);
4237
4248
  log(` Total Cost: ${formatCurrency(projection.totalCost)}\n`);
4238
4249
  if (ctx.values.tokenLimit != null) {
@@ -4241,8 +4252,8 @@ const blocksCommand = define({
4241
4252
  const currentTokens = getTotalTokens(block.tokenCounts);
4242
4253
  const remainingTokens = Math.max(0, limit - currentTokens);
4243
4254
  const percentUsed = projection.totalTokens / limit * 100;
4244
- const status = percentUsed > 100 ? import_picocolors$3.default.red("EXCEEDS LIMIT") : percentUsed > BLOCKS_WARNING_THRESHOLD * 100 ? import_picocolors$3.default.yellow("WARNING") : import_picocolors$3.default.green("OK");
4245
- log(import_picocolors$3.default.bold("Token Limit Status:"));
4255
+ const status = percentUsed > 100 ? import_picocolors$4.default.red("EXCEEDS LIMIT") : percentUsed > BLOCKS_WARNING_THRESHOLD * 100 ? import_picocolors$4.default.yellow("WARNING") : import_picocolors$4.default.green("OK");
4256
+ log(import_picocolors$4.default.bold("Token Limit Status:"));
4246
4257
  log(` Limit: ${formatNumber(limit)} tokens`);
4247
4258
  log(` Current Usage: ${formatNumber(currentTokens)} (${(currentTokens / limit * 100).toFixed(1)}%)`);
4248
4259
  log(` Remaining: ${formatNumber(remainingTokens)} tokens`);
@@ -4280,17 +4291,17 @@ const blocksCommand = define({
4280
4291
  const useCompactFormat = terminalWidth < BLOCKS_COMPACT_WIDTH_THRESHOLD;
4281
4292
  for (const block of blocks) if (block.isGap ?? false) {
4282
4293
  const gapRow = [
4283
- import_picocolors$3.default.gray(formatBlockTime(block, useCompactFormat)),
4284
- import_picocolors$3.default.gray("(inactive)"),
4285
- import_picocolors$3.default.gray("-"),
4286
- import_picocolors$3.default.gray("-")
4294
+ import_picocolors$4.default.gray(formatBlockTime(block, useCompactFormat)),
4295
+ import_picocolors$4.default.gray("(inactive)"),
4296
+ import_picocolors$4.default.gray("-"),
4297
+ import_picocolors$4.default.gray("-")
4287
4298
  ];
4288
- if (actualTokenLimit != null && actualTokenLimit > 0) gapRow.push(import_picocolors$3.default.gray("-"));
4289
- gapRow.push(import_picocolors$3.default.gray("-"));
4299
+ if (actualTokenLimit != null && actualTokenLimit > 0) gapRow.push(import_picocolors$4.default.gray("-"));
4300
+ gapRow.push(import_picocolors$4.default.gray("-"));
4290
4301
  table.push(gapRow);
4291
4302
  } else {
4292
4303
  const totalTokens = getTotalTokens(block.tokenCounts);
4293
- const status = block.isActive ? import_picocolors$3.default.green("ACTIVE") : "";
4304
+ const status = block.isActive ? import_picocolors$4.default.green("ACTIVE") : "";
4294
4305
  const row = [
4295
4306
  formatBlockTime(block, useCompactFormat),
4296
4307
  status,
@@ -4300,7 +4311,7 @@ const blocksCommand = define({
4300
4311
  if (actualTokenLimit != null && actualTokenLimit > 0) {
4301
4312
  const percentage = totalTokens / actualTokenLimit * 100;
4302
4313
  const percentText = `${percentage.toFixed(1)}%`;
4303
- row.push(percentage > 100 ? import_picocolors$3.default.red(percentText) : percentText);
4314
+ row.push(percentage > 100 ? import_picocolors$4.default.red(percentText) : percentText);
4304
4315
  }
4305
4316
  row.push(formatCurrency(block.costUSD));
4306
4317
  table.push(row);
@@ -4308,15 +4319,15 @@ const blocksCommand = define({
4308
4319
  if (actualTokenLimit != null && actualTokenLimit > 0) {
4309
4320
  const currentTokens = getTotalTokens(block.tokenCounts);
4310
4321
  const remainingTokens = Math.max(0, actualTokenLimit - currentTokens);
4311
- const remainingText = remainingTokens > 0 ? formatNumber(remainingTokens) : import_picocolors$3.default.red("0");
4322
+ const remainingText = remainingTokens > 0 ? formatNumber(remainingTokens) : import_picocolors$4.default.red("0");
4312
4323
  const remainingPercent = (actualTokenLimit - currentTokens) / actualTokenLimit * 100;
4313
- const remainingPercentText = remainingPercent > 0 ? `${remainingPercent.toFixed(1)}%` : import_picocolors$3.default.red("0.0%");
4324
+ const remainingPercentText = remainingPercent > 0 ? `${remainingPercent.toFixed(1)}%` : import_picocolors$4.default.red("0.0%");
4314
4325
  const remainingRow = [
4315
4326
  {
4316
- content: import_picocolors$3.default.gray(`(assuming ${formatNumber(actualTokenLimit)} token limit)`),
4327
+ content: import_picocolors$4.default.gray(`(assuming ${formatNumber(actualTokenLimit)} token limit)`),
4317
4328
  hAlign: "right"
4318
4329
  },
4319
- import_picocolors$3.default.blue("REMAINING"),
4330
+ import_picocolors$4.default.blue("REMAINING"),
4320
4331
  "",
4321
4332
  remainingText,
4322
4333
  remainingPercentText,
@@ -4327,13 +4338,13 @@ const blocksCommand = define({
4327
4338
  const projection = projectBlockUsage(block);
4328
4339
  if (projection != null) {
4329
4340
  const projectedTokens = formatNumber(projection.totalTokens);
4330
- const projectedText = actualTokenLimit != null && actualTokenLimit > 0 && projection.totalTokens > actualTokenLimit ? import_picocolors$3.default.red(projectedTokens) : projectedTokens;
4341
+ const projectedText = actualTokenLimit != null && actualTokenLimit > 0 && projection.totalTokens > actualTokenLimit ? import_picocolors$4.default.red(projectedTokens) : projectedTokens;
4331
4342
  const projectedRow = [
4332
4343
  {
4333
- content: import_picocolors$3.default.gray("(assuming current burn rate)"),
4344
+ content: import_picocolors$4.default.gray("(assuming current burn rate)"),
4334
4345
  hAlign: "right"
4335
4346
  },
4336
- import_picocolors$3.default.yellow("PROJECTED"),
4347
+ import_picocolors$4.default.yellow("PROJECTED"),
4337
4348
  "",
4338
4349
  projectedText
4339
4350
  ];
@@ -4395,7 +4406,7 @@ let aliasCache = null;
4395
4406
  */
4396
4407
  function getProjectAliases() {
4397
4408
  if (aliasCache !== null) return aliasCache;
4398
- aliasCache = /* @__PURE__ */ new Map();
4409
+ aliasCache = new Map();
4399
4410
  const aliasEnv = (process$1.env[PROJECT_ALIASES_ENV] ?? "").trim();
4400
4411
  if (aliasEnv === "") return aliasCache;
4401
4412
  const pairs = aliasEnv.split(",").map((pair) => pair.trim()).filter((pair) => pair !== "");
@@ -4488,7 +4499,7 @@ function formatProjectName(projectName) {
4488
4499
  if (aliases.has(parsed)) return aliases.get(parsed);
4489
4500
  return parsed;
4490
4501
  }
4491
- var import_picocolors$2 = __toESM(require_picocolors(), 1);
4502
+ var import_picocolors$3 = __toESM(require_picocolors(), 1);
4492
4503
  const dailyCommand = define({
4493
4504
  name: "daily",
4494
4505
  description: "Show usage report grouped by date",
@@ -4604,7 +4615,7 @@ const dailyCommand = define({
4604
4615
  ""
4605
4616
  ]);
4606
4617
  table.push([
4607
- import_picocolors$2.default.cyan(`Project: ${formatProjectName(projectName)}`),
4618
+ import_picocolors$3.default.cyan(`Project: ${formatProjectName(projectName)}`),
4608
4619
  "",
4609
4620
  "",
4610
4621
  "",
@@ -4652,14 +4663,14 @@ const dailyCommand = define({
4652
4663
  ""
4653
4664
  ]);
4654
4665
  table.push([
4655
- import_picocolors$2.default.yellow("Total"),
4666
+ import_picocolors$3.default.yellow("Total"),
4656
4667
  "",
4657
- import_picocolors$2.default.yellow(formatNumber(totals.inputTokens)),
4658
- import_picocolors$2.default.yellow(formatNumber(totals.outputTokens)),
4659
- import_picocolors$2.default.yellow(formatNumber(totals.cacheCreationTokens)),
4660
- import_picocolors$2.default.yellow(formatNumber(totals.cacheReadTokens)),
4661
- import_picocolors$2.default.yellow(formatNumber(getTotalTokens(totals))),
4662
- import_picocolors$2.default.yellow(formatCurrency(totals.totalCost))
4668
+ import_picocolors$3.default.yellow(formatNumber(totals.inputTokens)),
4669
+ import_picocolors$3.default.yellow(formatNumber(totals.outputTokens)),
4670
+ import_picocolors$3.default.yellow(formatNumber(totals.cacheCreationTokens)),
4671
+ import_picocolors$3.default.yellow(formatNumber(totals.cacheReadTokens)),
4672
+ import_picocolors$3.default.yellow(formatNumber(getTotalTokens(totals))),
4673
+ import_picocolors$3.default.yellow(formatCurrency(totals.totalCost))
4663
4674
  ]);
4664
4675
  log(table.toString());
4665
4676
  if (table.isCompactMode()) {
@@ -4884,13 +4895,13 @@ var Response2 = class _Response {
4884
4895
  });
4885
4896
  Object.setPrototypeOf(Response2, GlobalResponse);
4886
4897
  Object.setPrototypeOf(Response2.prototype, GlobalResponse.prototype);
4887
- function writeFromReadableStream(stream, writable) {
4888
- if (stream.locked) throw new TypeError("ReadableStream is locked.");
4889
- else if (writable.destroyed) return;
4890
- const reader = stream.getReader();
4898
+ async function readWithoutBlocking(readPromise) {
4899
+ return Promise.race([readPromise, Promise.resolve().then(() => Promise.resolve(void 0))]);
4900
+ }
4901
+ function writeFromReadableStreamDefaultReader(reader, writable, currentReadPromise) {
4891
4902
  const handleError = () => {};
4892
4903
  writable.on("error", handleError);
4893
- reader.read().then(flow, handleStreamError);
4904
+ (currentReadPromise ?? reader.read()).then(flow, handleStreamError);
4894
4905
  return reader.closed.finally(() => {
4895
4906
  writable.off("error", handleError);
4896
4907
  });
@@ -4910,6 +4921,11 @@ function writeFromReadableStream(stream, writable) {
4910
4921
  }
4911
4922
  }
4912
4923
  }
4924
+ function writeFromReadableStream(stream, writable) {
4925
+ if (stream.locked) throw new TypeError("ReadableStream is locked.");
4926
+ else if (writable.destroyed) return;
4927
+ return writeFromReadableStreamDefaultReader(stream.getReader(), writable);
4928
+ }
4913
4929
  var buildOutgoingHttpHeaders = (headers) => {
4914
4930
  const res = {};
4915
4931
  if (!(headers instanceof Headers)) headers = new Headers(headers ?? void 0);
@@ -4931,8 +4947,6 @@ global.fetch = (info$1, init$1) => {
4931
4947
  return webFetch(info$1, init$1);
4932
4948
  };
4933
4949
  var outgoingEnded = Symbol("outgoingEnded");
4934
- var regBuffer = /^no$/i;
4935
- var regContentType = /^(application\/json\b|text\/(?!event-stream\b))/i;
4936
4950
  var handleRequestError = () => new Response(null, { status: 400 });
4937
4951
  var handleFetchError = (e) => new Response(null, { status: e instanceof Error && (e.name === "TimeoutError" || e.constructor.name === "TimeoutError") ? 504 : 500 });
4938
4952
  var handleResponseError = (e, outgoing) => {
@@ -4975,16 +4989,41 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
4975
4989
  if (cacheKey in res) return responseViaCache(res, outgoing);
4976
4990
  const resHeaderRecord = buildOutgoingHttpHeaders(res.headers);
4977
4991
  if (res.body) {
4978
- const { "transfer-encoding": transferEncoding, "content-encoding": contentEncoding, "content-length": contentLength, "x-accel-buffering": accelBuffering, "content-type": contentType } = resHeaderRecord;
4979
- if (transferEncoding || contentEncoding || contentLength || accelBuffering && regBuffer.test(accelBuffering) || !regContentType.test(contentType)) {
4980
- outgoing.writeHead(res.status, resHeaderRecord);
4981
- flushHeaders(outgoing);
4982
- await writeFromReadableStream(res.body, outgoing);
4983
- } else {
4984
- const buffer = await res.arrayBuffer();
4985
- resHeaderRecord["content-length"] = buffer.byteLength;
4986
- outgoing.writeHead(res.status, resHeaderRecord);
4987
- outgoing.end(new Uint8Array(buffer));
4992
+ const reader = res.body.getReader();
4993
+ const values = [];
4994
+ let done = false;
4995
+ let currentReadPromise = void 0;
4996
+ let maxReadCount = 2;
4997
+ for (let i = 0; i < maxReadCount; i++) {
4998
+ currentReadPromise ||= reader.read();
4999
+ const chunk = await readWithoutBlocking(currentReadPromise).catch((e) => {
5000
+ console.error(e);
5001
+ done = true;
5002
+ });
5003
+ if (!chunk) {
5004
+ if (i === 1 && resHeaderRecord["transfer-encoding"] !== "chunked") {
5005
+ await new Promise((resolve) => setTimeout(resolve));
5006
+ maxReadCount = 3;
5007
+ continue;
5008
+ }
5009
+ break;
5010
+ }
5011
+ currentReadPromise = void 0;
5012
+ if (chunk.value) values.push(chunk.value);
5013
+ if (chunk.done) {
5014
+ done = true;
5015
+ break;
5016
+ }
5017
+ }
5018
+ if (done && !("content-length" in resHeaderRecord)) resHeaderRecord["content-length"] = values.reduce((acc, value) => acc + value.length, 0);
5019
+ outgoing.writeHead(res.status, resHeaderRecord);
5020
+ values.forEach((value) => {
5021
+ outgoing.write(value);
5022
+ });
5023
+ if (done) outgoing.end();
5024
+ else {
5025
+ if (values.length === 0) flushHeaders(outgoing);
5026
+ await writeFromReadableStreamDefaultReader(reader, outgoing, currentReadPromise);
4988
5027
  }
4989
5028
  } else if (resHeaderRecord[X_ALREADY_SENT]) {} else {
4990
5029
  outgoing.writeHead(res.status, resHeaderRecord);
@@ -5115,7 +5154,7 @@ const mcpCommand = define({
5115
5154
  }
5116
5155
  }
5117
5156
  });
5118
- var import_picocolors$1 = __toESM(require_picocolors(), 1);
5157
+ var import_picocolors$2 = __toESM(require_picocolors(), 1);
5119
5158
  const monthlyCommand = define({
5120
5159
  name: "monthly",
5121
5160
  description: "Show usage report grouped by month",
@@ -5232,14 +5271,14 @@ const monthlyCommand = define({
5232
5271
  ""
5233
5272
  ]);
5234
5273
  table.push([
5235
- import_picocolors$1.default.yellow("Total"),
5274
+ import_picocolors$2.default.yellow("Total"),
5236
5275
  "",
5237
- import_picocolors$1.default.yellow(formatNumber(totals.inputTokens)),
5238
- import_picocolors$1.default.yellow(formatNumber(totals.outputTokens)),
5239
- import_picocolors$1.default.yellow(formatNumber(totals.cacheCreationTokens)),
5240
- import_picocolors$1.default.yellow(formatNumber(totals.cacheReadTokens)),
5241
- import_picocolors$1.default.yellow(formatNumber(getTotalTokens(totals))),
5242
- import_picocolors$1.default.yellow(formatCurrency(totals.totalCost))
5276
+ import_picocolors$2.default.yellow(formatNumber(totals.inputTokens)),
5277
+ import_picocolors$2.default.yellow(formatNumber(totals.outputTokens)),
5278
+ import_picocolors$2.default.yellow(formatNumber(totals.cacheCreationTokens)),
5279
+ import_picocolors$2.default.yellow(formatNumber(totals.cacheReadTokens)),
5280
+ import_picocolors$2.default.yellow(formatNumber(getTotalTokens(totals))),
5281
+ import_picocolors$2.default.yellow(formatCurrency(totals.totalCost))
5243
5282
  ]);
5244
5283
  log(table.toString());
5245
5284
  if (table.isCompactMode()) {
@@ -5249,7 +5288,7 @@ const monthlyCommand = define({
5249
5288
  }
5250
5289
  }
5251
5290
  });
5252
- var import_picocolors = __toESM(require_picocolors(), 1);
5291
+ var import_picocolors$1 = __toESM(require_picocolors(), 1);
5253
5292
  const sessionCommand = define({
5254
5293
  name: "session",
5255
5294
  description: "Show usage report grouped by conversation session",
@@ -5364,6 +5403,152 @@ const sessionCommand = define({
5364
5403
  "",
5365
5404
  ""
5366
5405
  ]);
5406
+ table.push([
5407
+ import_picocolors$1.default.yellow("Total"),
5408
+ "",
5409
+ import_picocolors$1.default.yellow(formatNumber(totals.inputTokens)),
5410
+ import_picocolors$1.default.yellow(formatNumber(totals.outputTokens)),
5411
+ import_picocolors$1.default.yellow(formatNumber(totals.cacheCreationTokens)),
5412
+ import_picocolors$1.default.yellow(formatNumber(totals.cacheReadTokens)),
5413
+ import_picocolors$1.default.yellow(formatNumber(getTotalTokens(totals))),
5414
+ import_picocolors$1.default.yellow(formatCurrency(totals.totalCost)),
5415
+ ""
5416
+ ]);
5417
+ log(table.toString());
5418
+ if (table.isCompactMode()) {
5419
+ logger.info("\nRunning in Compact Mode");
5420
+ logger.info("Expand terminal width to see cache metrics and total tokens");
5421
+ }
5422
+ }
5423
+ }
5424
+ });
5425
+ var import_picocolors = __toESM(require_picocolors(), 1);
5426
+ const weeklyCommand = define({
5427
+ name: "weekly",
5428
+ description: "Show usage report grouped by week",
5429
+ args: {
5430
+ ...sharedArgs,
5431
+ startOfWeek: {
5432
+ type: "enum",
5433
+ short: "w",
5434
+ description: "Day to start the week on",
5435
+ default: "sunday",
5436
+ choices: WEEK_DAYS
5437
+ }
5438
+ },
5439
+ toKebab: true,
5440
+ async run(ctx) {
5441
+ if (ctx.values.json) logger.level = 0;
5442
+ const weeklyData = await loadWeeklyUsageData({
5443
+ since: ctx.values.since,
5444
+ until: ctx.values.until,
5445
+ mode: ctx.values.mode,
5446
+ order: ctx.values.order,
5447
+ offline: ctx.values.offline,
5448
+ startOfWeek: ctx.values.startOfWeek
5449
+ });
5450
+ if (weeklyData.length === 0) {
5451
+ if (ctx.values.json) {
5452
+ const emptyOutput = {
5453
+ weekly: [],
5454
+ totals: {
5455
+ inputTokens: 0,
5456
+ outputTokens: 0,
5457
+ cacheCreationTokens: 0,
5458
+ cacheReadTokens: 0,
5459
+ totalTokens: 0,
5460
+ totalCost: 0
5461
+ }
5462
+ };
5463
+ log(JSON.stringify(emptyOutput, null, 2));
5464
+ } else logger.warn("No Claude usage data found.");
5465
+ process$1.exit(0);
5466
+ }
5467
+ const totals = calculateTotals(weeklyData);
5468
+ if (ctx.values.debug && !ctx.values.json) {
5469
+ const mismatchStats = await detectMismatches(void 0);
5470
+ printMismatchReport(mismatchStats, ctx.values.debugSamples);
5471
+ }
5472
+ if (ctx.values.json) {
5473
+ const jsonOutput = {
5474
+ weekly: weeklyData.map((data) => ({
5475
+ week: data.week,
5476
+ inputTokens: data.inputTokens,
5477
+ outputTokens: data.outputTokens,
5478
+ cacheCreationTokens: data.cacheCreationTokens,
5479
+ cacheReadTokens: data.cacheReadTokens,
5480
+ totalTokens: getTotalTokens(data),
5481
+ totalCost: data.totalCost,
5482
+ modelsUsed: data.modelsUsed,
5483
+ modelBreakdowns: data.modelBreakdowns
5484
+ })),
5485
+ totals: createTotalsObject(totals)
5486
+ };
5487
+ log(JSON.stringify(jsonOutput, null, 2));
5488
+ } else {
5489
+ logger.box("Claude Code Token Usage Report - Weekly");
5490
+ const table = new ResponsiveTable({
5491
+ head: [
5492
+ "Week",
5493
+ "Models",
5494
+ "Input",
5495
+ "Output",
5496
+ "Cache Create",
5497
+ "Cache Read",
5498
+ "Total Tokens",
5499
+ "Cost (USD)"
5500
+ ],
5501
+ style: { head: ["cyan"] },
5502
+ colAligns: [
5503
+ "left",
5504
+ "left",
5505
+ "right",
5506
+ "right",
5507
+ "right",
5508
+ "right",
5509
+ "right",
5510
+ "right"
5511
+ ],
5512
+ dateFormatter: formatDateCompact,
5513
+ compactHead: [
5514
+ "Week",
5515
+ "Models",
5516
+ "Input",
5517
+ "Output",
5518
+ "Cost (USD)"
5519
+ ],
5520
+ compactColAligns: [
5521
+ "left",
5522
+ "left",
5523
+ "right",
5524
+ "right",
5525
+ "right"
5526
+ ],
5527
+ compactThreshold: 100
5528
+ });
5529
+ for (const data of weeklyData) {
5530
+ table.push([
5531
+ data.week,
5532
+ formatModelsDisplayMultiline(data.modelsUsed),
5533
+ formatNumber(data.inputTokens),
5534
+ formatNumber(data.outputTokens),
5535
+ formatNumber(data.cacheCreationTokens),
5536
+ formatNumber(data.cacheReadTokens),
5537
+ formatNumber(getTotalTokens(data)),
5538
+ formatCurrency(data.totalCost)
5539
+ ]);
5540
+ if (ctx.values.breakdown) pushBreakdownRows(table, data.modelBreakdowns);
5541
+ }
5542
+ table.push([
5543
+ "",
5544
+ "",
5545
+ "",
5546
+ "",
5547
+ "",
5548
+ "",
5549
+ "",
5550
+ ""
5551
+ ]);
5367
5552
  table.push([
5368
5553
  import_picocolors.default.yellow("Total"),
5369
5554
  "",
@@ -5372,8 +5557,7 @@ const sessionCommand = define({
5372
5557
  import_picocolors.default.yellow(formatNumber(totals.cacheCreationTokens)),
5373
5558
  import_picocolors.default.yellow(formatNumber(totals.cacheReadTokens)),
5374
5559
  import_picocolors.default.yellow(formatNumber(getTotalTokens(totals))),
5375
- import_picocolors.default.yellow(formatCurrency(totals.totalCost)),
5376
- ""
5560
+ import_picocolors.default.yellow(formatCurrency(totals.totalCost))
5377
5561
  ]);
5378
5562
  log(table.toString());
5379
5563
  if (table.isCompactMode()) {
@@ -5386,9 +5570,10 @@ const sessionCommand = define({
5386
5570
  /**
5387
5571
  * Map of available CLI subcommands
5388
5572
  */
5389
- const subCommands = /* @__PURE__ */ new Map();
5573
+ const subCommands = new Map();
5390
5574
  subCommands.set("daily", dailyCommand);
5391
5575
  subCommands.set("monthly", monthlyCommand);
5576
+ subCommands.set("weekly", weeklyCommand);
5392
5577
  subCommands.set("session", sessionCommand);
5393
5578
  subCommands.set("blocks", blocksCommand);
5394
5579
  subCommands.set("mcp", mcpCommand);