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/README.md +11 -0
- package/dist/{_types-BHFM59hI.js → _types-ed8-0BH6.js} +14 -8
- package/dist/calculate-cost.d.ts +3 -3
- package/dist/calculate-cost.js +1 -1
- package/dist/{data-loader-CmW1xurn.js → data-loader-CwryIrwx.js} +124 -35
- package/dist/{data-loader-CgvyDaQD.d.ts → data-loader-DZMUuqrf.d.ts} +162 -5
- package/dist/data-loader.d.ts +3 -3
- package/dist/data-loader.js +5 -5
- package/dist/{debug-kkVHYWpk.js → debug-C8bVFK5q.js} +6 -6
- package/dist/debug.js +5 -5
- package/dist/index.js +308 -123
- package/dist/{logger-D0z-I-_d.js → logger-C35JCduT.js} +15 -15
- package/dist/logger.js +1 -1
- package/dist/{mcp-DbViDMcM.js → mcp-CqzLeEbX.js} +51 -35
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +5 -5
- package/dist/{pricing-fetcher-B3SvKOod.d.ts → pricing-fetcher-AYfCy7g-.d.ts} +6 -2
- package/dist/{pricing-fetcher-B5b61mDE.js → pricing-fetcher-CNjC0nXU.js} +18 -6
- package/dist/pricing-fetcher.d.ts +1 -1
- package/dist/pricing-fetcher.js +3 -3
- package/dist/{prompt-DsUFNEY7.js → prompt-lm8M58zJ.js} +4 -4
- package/package.json +1 -1
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-
|
|
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-
|
|
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-
|
|
7
|
-
import { description, log, logger, name, version } from "./logger-
|
|
8
|
-
import { detectMismatches, printMismatchReport } from "./debug-
|
|
9
|
-
import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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$
|
|
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$
|
|
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 =
|
|
3190
|
-
processedHashes =
|
|
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
|
-
|
|
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$
|
|
3689
|
-
case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.MODERATE: return import_picocolors$
|
|
3690
|
-
default: return import_picocolors$
|
|
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$
|
|
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 =
|
|
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$
|
|
3766
|
-
emptyChar: import_picocolors$
|
|
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$
|
|
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$
|
|
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$
|
|
3795
|
-
const sessionCol2 = `${import_picocolors$
|
|
3796
|
-
const sessionCol3 = `${import_picocolors$
|
|
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$
|
|
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$
|
|
3817
|
-
if (tokenPercent > 100) barColor = import_picocolors$
|
|
3818
|
-
else if (tokenPercent > 80) barColor = import_picocolors$
|
|
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$
|
|
3833
|
+
emptyChar: import_picocolors$6.default.gray("░"),
|
|
3823
3834
|
leftBracket: "[",
|
|
3824
3835
|
rightBracket: "]"
|
|
3825
|
-
}) : `[${import_picocolors$
|
|
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$
|
|
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$
|
|
3843
|
+
return `${import_picocolors$6.default.bold("Burn Rate:")} ${formattedRate} token/min ${rateIndicator}`;
|
|
3833
3844
|
};
|
|
3834
|
-
const usageLabel = import_picocolors$
|
|
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$
|
|
3839
|
-
let usageCol2 = config.tokenLimit != null && config.tokenLimit > 0 ? `${import_picocolors$
|
|
3840
|
-
const usageCol3 = `${import_picocolors$
|
|
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$
|
|
3849
|
-
if (usageCol2.length > 0) usageCol2 = `${import_picocolors$
|
|
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$
|
|
3874
|
-
if (projectedPercent > 100) projBarColor = import_picocolors$
|
|
3875
|
-
else if (projectedPercent > 80) projBarColor = import_picocolors$
|
|
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$
|
|
3890
|
+
emptyChar: import_picocolors$6.default.gray("░"),
|
|
3880
3891
|
leftBracket: "[",
|
|
3881
3892
|
rightBracket: "]"
|
|
3882
|
-
}) : `[${import_picocolors$
|
|
3883
|
-
const limitStatus = config.tokenLimit != null && config.tokenLimit > 0 ? projectedPercent > 100 ? import_picocolors$
|
|
3884
|
-
const projLabel = import_picocolors$
|
|
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$
|
|
3890
|
-
let projCol2 = `${import_picocolors$
|
|
3891
|
-
const projCol3 = `${import_picocolors$
|
|
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$
|
|
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 =
|
|
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 =
|
|
3920
|
-
terminal.write(`${marginStr}│${import_picocolors$
|
|
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$
|
|
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$
|
|
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$
|
|
3952
|
+
terminal.write(import_picocolors$6.default.gray(`Refresh: ${config.refreshInterval / 1e3}s | Ctrl+C: stop\n`));
|
|
3942
3953
|
}
|
|
3943
|
-
var import_picocolors$
|
|
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$
|
|
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$
|
|
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 =
|
|
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 =
|
|
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$
|
|
4224
|
-
log(`Time Remaining: ${import_picocolors$
|
|
4225
|
-
log(import_picocolors$
|
|
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$
|
|
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$
|
|
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$
|
|
4245
|
-
log(import_picocolors$
|
|
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$
|
|
4284
|
-
import_picocolors$
|
|
4285
|
-
import_picocolors$
|
|
4286
|
-
import_picocolors$
|
|
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$
|
|
4289
|
-
gapRow.push(import_picocolors$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
4327
|
+
content: import_picocolors$4.default.gray(`(assuming ${formatNumber(actualTokenLimit)} token limit)`),
|
|
4317
4328
|
hAlign: "right"
|
|
4318
4329
|
},
|
|
4319
|
-
import_picocolors$
|
|
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$
|
|
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$
|
|
4344
|
+
content: import_picocolors$4.default.gray("(assuming current burn rate)"),
|
|
4334
4345
|
hAlign: "right"
|
|
4335
4346
|
},
|
|
4336
|
-
import_picocolors$
|
|
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 =
|
|
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$
|
|
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$
|
|
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$
|
|
4666
|
+
import_picocolors$3.default.yellow("Total"),
|
|
4656
4667
|
"",
|
|
4657
|
-
import_picocolors$
|
|
4658
|
-
import_picocolors$
|
|
4659
|
-
import_picocolors$
|
|
4660
|
-
import_picocolors$
|
|
4661
|
-
import_picocolors$
|
|
4662
|
-
import_picocolors$
|
|
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
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
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
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
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$
|
|
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$
|
|
5274
|
+
import_picocolors$2.default.yellow("Total"),
|
|
5236
5275
|
"",
|
|
5237
|
-
import_picocolors$
|
|
5238
|
-
import_picocolors$
|
|
5239
|
-
import_picocolors$
|
|
5240
|
-
import_picocolors$
|
|
5241
|
-
import_picocolors$
|
|
5242
|
-
import_picocolors$
|
|
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 =
|
|
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);
|