ccusage 17.2.1 → 18.0.2
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 +12 -31
- package/config-schema.json +13 -62
- package/dist/calculate-cost.d.ts +1 -1
- package/dist/{data-loader-fDs6JbEv.d.ts → data-loader-BRnqe1-8.d.ts} +1 -1
- package/dist/{data-loader-DZaU_svm.js → data-loader-DpmcwQJo.js} +2 -9
- package/dist/data-loader.d.ts +1 -1
- package/dist/data-loader.js +2 -2
- package/dist/{debug-Cv9UXi84.js → debug-CCOfmDX-.js} +2 -2
- package/dist/debug.js +3 -3
- package/dist/index.js +27 -880
- package/dist/{logger-B6CjbhRV.js → logger-CZDKWAOd.js} +1 -1
- package/dist/logger.js +1 -1
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as
|
|
2
|
+
import { $ as inspectError, D as calculateBurnRate, E as DEFAULT_SESSION_DURATION_HOURS, F as BLOCKS_COMPACT_WIDTH_THRESHOLD, H as DEFAULT_LOCALE, I as BLOCKS_DEFAULT_TERMINAL_WIDTH, J as uniq, K as WEEK_DAYS, L as BLOCKS_WARNING_THRESHOLD, M as getFileModifiedTime, N as unreachable, O as filterRecentBlocks, P as _usingCtx, Q as map$2, U as DEFAULT_RECENT_DAYS, V as DEFAULT_CONTEXT_USAGE_THRESHOLDS, W as DEFAULT_REFRESH_INTERVAL_SECONDS, X as try_, Y as unwrap, Z as pipe, _ as loadWeeklyUsageData, at as __commonJSMin, et as inspect, f as loadDailyUsageData, g as loadSessionUsageById, h as loadSessionData, it as toArray, j as formatDateCompact, k as projectBlockUsage, m as loadSessionBlockData, n as calculateContextTokens, nt as isSuccess, ot as __require, p as loadMonthlyUsageData, rt as isFailure, s as getClaudePaths, st as __toESM, tt as succeed, z as CONFIG_FILE_NAME } from "./data-loader-DpmcwQJo.js";
|
|
3
3
|
import { D as maxValue, E as integer$1, F as string, I as transform, L as trim, M as parse$1, N as pipe$1, O as minValue, P as safeParse, R as union, T as flatten, d as filterDateSchema, k as number, n as SortOrders, t as CostModes, w as check, y as statuslineHookJsonSchema, z as getTotalTokens } from "./_types-BFL_bTNX.js";
|
|
4
4
|
import { n as createTotalsObject, t as calculateTotals } from "./calculate-cost-CKH-OC_c.js";
|
|
5
|
-
import { a as version, i as name, n as logger, r as description, t as log } from "./logger-
|
|
6
|
-
import { n as printMismatchReport, t as detectMismatches } from "./debug-
|
|
5
|
+
import { a as version, i as name, n as logger, r as description, t as log } from "./logger-CZDKWAOd.js";
|
|
6
|
+
import { n as printMismatchReport, t as detectMismatches } from "./debug-CCOfmDX-.js";
|
|
7
7
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
8
|
-
import a
|
|
8
|
+
import a from "node:fs/promises";
|
|
9
9
|
import path, { join } from "node:path";
|
|
10
10
|
import process$1 from "node:process";
|
|
11
11
|
import { tmpdir } from "node:os";
|
|
@@ -1194,19 +1194,19 @@ var require_utils = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
1194
1194
|
function hyperlink(url, text) {
|
|
1195
1195
|
const OSC = "\x1B]";
|
|
1196
1196
|
const BEL = "\x07";
|
|
1197
|
-
const SEP
|
|
1197
|
+
const SEP = ";";
|
|
1198
1198
|
return [
|
|
1199
1199
|
OSC,
|
|
1200
1200
|
"8",
|
|
1201
|
-
SEP
|
|
1202
|
-
SEP
|
|
1201
|
+
SEP,
|
|
1202
|
+
SEP,
|
|
1203
1203
|
url || text,
|
|
1204
1204
|
BEL,
|
|
1205
1205
|
text,
|
|
1206
1206
|
OSC,
|
|
1207
1207
|
"8",
|
|
1208
|
-
SEP
|
|
1209
|
-
SEP
|
|
1208
|
+
SEP,
|
|
1209
|
+
SEP,
|
|
1210
1210
|
BEL
|
|
1211
1211
|
].join("");
|
|
1212
1212
|
}
|
|
@@ -2466,7 +2466,7 @@ var require_picocolors = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
2466
2466
|
module.exports = createColors();
|
|
2467
2467
|
module.exports.createColors = createColors;
|
|
2468
2468
|
}));
|
|
2469
|
-
var import_picocolors$
|
|
2469
|
+
var import_picocolors$3 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
|
|
2470
2470
|
var import_cli_table3 = /* @__PURE__ */ __toESM(require_cli_table3(), 1);
|
|
2471
2471
|
function ansiRegex({ onlyFirst = false } = {}) {
|
|
2472
2472
|
return new RegExp(`(?:\\u001B\\][\\s\\S]*?(?:\\u0007|\\u001B\\u005C|\\u009C))|[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]`, onlyFirst ? void 0 : "g");
|
|
@@ -2660,13 +2660,16 @@ function formatCurrency(amount) {
|
|
|
2660
2660
|
return `$${amount.toFixed(2)}`;
|
|
2661
2661
|
}
|
|
2662
2662
|
function formatModelName(modelName) {
|
|
2663
|
-
const
|
|
2663
|
+
const piMatch = modelName.match(/^\[pi\] (.+)$/);
|
|
2664
|
+
if (piMatch?.[1] != null) return `[pi] ${formatModelName(piMatch[1])}`;
|
|
2665
|
+
const anthropicMatch = modelName.match(/^anthropic\/claude-(\w+)-([\d.]+)$/);
|
|
2666
|
+
if (anthropicMatch != null) return `${anthropicMatch[1]}-${anthropicMatch[2]}`;
|
|
2667
|
+
const match = modelName.match(/^claude-(\w+)-([\d-]+)-(\d{8})$/);
|
|
2664
2668
|
if (match != null) return `${match[1]}-${match[2]}`;
|
|
2669
|
+
const noDateMatch = modelName.match(/^claude-(\w+)-([\d-]+)$/);
|
|
2670
|
+
if (noDateMatch != null) return `${noDateMatch[1]}-${noDateMatch[2]}`;
|
|
2665
2671
|
return modelName;
|
|
2666
2672
|
}
|
|
2667
|
-
function formatModelsDisplay(models) {
|
|
2668
|
-
return uniq(models.map(formatModelName)).sort().join(", ");
|
|
2669
|
-
}
|
|
2670
2673
|
function formatModelsDisplayMultiline(models) {
|
|
2671
2674
|
return uniq(models.map(formatModelName)).sort().map((model) => `- ${model}`).join("\n");
|
|
2672
2675
|
}
|
|
@@ -2675,7 +2678,7 @@ function pushBreakdownRows(table, breakdowns, extraColumns = 1, trailingColumns
|
|
|
2675
2678
|
const row = [` └─ ${formatModelName(breakdown.modelName)}`];
|
|
2676
2679
|
for (let i = 0; i < extraColumns; i++) row.push("");
|
|
2677
2680
|
const totalTokens = breakdown.inputTokens + breakdown.outputTokens + breakdown.cacheCreationTokens + breakdown.cacheReadTokens;
|
|
2678
|
-
row.push(import_picocolors$
|
|
2681
|
+
row.push(import_picocolors$3.default.gray(formatNumber(breakdown.inputTokens)), import_picocolors$3.default.gray(formatNumber(breakdown.outputTokens)), import_picocolors$3.default.gray(formatNumber(breakdown.cacheCreationTokens)), import_picocolors$3.default.gray(formatNumber(breakdown.cacheReadTokens)), import_picocolors$3.default.gray(formatNumber(totalTokens)), import_picocolors$3.default.gray(formatCurrency(breakdown.cost)));
|
|
2679
2682
|
for (let i = 0; i < trailingColumns; i++) row.push("");
|
|
2680
2683
|
table.push(row);
|
|
2681
2684
|
}
|
|
@@ -2750,14 +2753,14 @@ function formatUsageDataRow(firstColumnValue, data, lastActivity) {
|
|
|
2750
2753
|
function formatTotalsRow(totals, includeLastActivity = false) {
|
|
2751
2754
|
const totalTokens = totals.inputTokens + totals.outputTokens + totals.cacheCreationTokens + totals.cacheReadTokens;
|
|
2752
2755
|
const row = [
|
|
2753
|
-
import_picocolors$
|
|
2756
|
+
import_picocolors$3.default.yellow("Total"),
|
|
2754
2757
|
"",
|
|
2755
|
-
import_picocolors$
|
|
2756
|
-
import_picocolors$
|
|
2757
|
-
import_picocolors$
|
|
2758
|
-
import_picocolors$
|
|
2759
|
-
import_picocolors$
|
|
2760
|
-
import_picocolors$
|
|
2758
|
+
import_picocolors$3.default.yellow(formatNumber(totals.inputTokens)),
|
|
2759
|
+
import_picocolors$3.default.yellow(formatNumber(totals.outputTokens)),
|
|
2760
|
+
import_picocolors$3.default.yellow(formatNumber(totals.cacheCreationTokens)),
|
|
2761
|
+
import_picocolors$3.default.yellow(formatNumber(totals.cacheReadTokens)),
|
|
2762
|
+
import_picocolors$3.default.yellow(formatNumber(totalTokens)),
|
|
2763
|
+
import_picocolors$3.default.yellow(formatCurrency(totals.totalCost))
|
|
2761
2764
|
];
|
|
2762
2765
|
if (includeLastActivity) row.push("");
|
|
2763
2766
|
return row;
|
|
@@ -2875,9 +2878,9 @@ function mergeConfigWithArgs(ctx, config, debug$4 = false) {
|
|
|
2875
2878
|
logger.info("");
|
|
2876
2879
|
logger.info(`Merging options for '${commandName ?? "unknown"}' command:`);
|
|
2877
2880
|
const bySource = {
|
|
2878
|
-
|
|
2881
|
+
defaults: [],
|
|
2879
2882
|
"command config": [],
|
|
2880
|
-
|
|
2883
|
+
CLI: []
|
|
2881
2884
|
};
|
|
2882
2885
|
for (const [key, source] of Object.entries(sources)) if (bySource[source] != null) bySource[source].push(`${key}=${JSON.stringify(merged[key])}`);
|
|
2883
2886
|
if (bySource.defaults.length > 0) logger.info(` • From defaults: ${bySource.defaults.join(", ")}`);
|
|
@@ -3235,828 +3238,6 @@ const sharedCommandConfig = {
|
|
|
3235
3238
|
args: sharedArgs,
|
|
3236
3239
|
toKebab: true
|
|
3237
3240
|
};
|
|
3238
|
-
const isBrowser = globalThis.window?.document !== void 0;
|
|
3239
|
-
globalThis.process?.versions?.node;
|
|
3240
|
-
globalThis.process?.versions?.bun;
|
|
3241
|
-
globalThis.Deno?.version?.deno;
|
|
3242
|
-
globalThis.process?.versions?.electron;
|
|
3243
|
-
globalThis.navigator?.userAgent?.includes("jsdom");
|
|
3244
|
-
typeof WorkerGlobalScope !== "undefined" && globalThis instanceof WorkerGlobalScope;
|
|
3245
|
-
typeof DedicatedWorkerGlobalScope !== "undefined" && globalThis instanceof DedicatedWorkerGlobalScope;
|
|
3246
|
-
typeof SharedWorkerGlobalScope !== "undefined" && globalThis instanceof SharedWorkerGlobalScope;
|
|
3247
|
-
typeof ServiceWorkerGlobalScope !== "undefined" && globalThis instanceof ServiceWorkerGlobalScope;
|
|
3248
|
-
const platform = globalThis.navigator?.userAgentData?.platform;
|
|
3249
|
-
platform === "macOS" || globalThis.navigator?.platform === "MacIntel" || globalThis.navigator?.userAgent?.includes(" Mac ") === true || globalThis.process?.platform;
|
|
3250
|
-
platform === "Windows" || globalThis.navigator?.platform === "Win32" || globalThis.process?.platform;
|
|
3251
|
-
platform === "Linux" || globalThis.navigator?.platform?.startsWith("Linux") === true || globalThis.navigator?.userAgent?.includes(" Linux ") === true || globalThis.process?.platform;
|
|
3252
|
-
platform === "iOS" || globalThis.navigator?.platform === "MacIntel" && globalThis.navigator?.maxTouchPoints > 1 || /iPad|iPhone|iPod/.test(globalThis.navigator?.platform);
|
|
3253
|
-
platform === "Android" || globalThis.navigator?.platform === "Android" || globalThis.navigator?.userAgent?.includes(" Android ") === true || globalThis.process?.platform;
|
|
3254
|
-
const ESC = "\x1B[";
|
|
3255
|
-
const SEP = ";";
|
|
3256
|
-
const isTerminalApp = !isBrowser && process$1.env.TERM_PROGRAM === "Apple_Terminal";
|
|
3257
|
-
const isWindows = !isBrowser && process$1.platform === "win32";
|
|
3258
|
-
isBrowser || process$1.cwd;
|
|
3259
|
-
const cursorTo = (x, y) => {
|
|
3260
|
-
if (typeof x !== "number") throw new TypeError("The `x` argument is required");
|
|
3261
|
-
if (typeof y !== "number") return ESC + (x + 1) + "G";
|
|
3262
|
-
return ESC + (y + 1) + SEP + (x + 1) + "H";
|
|
3263
|
-
};
|
|
3264
|
-
const cursorForward = (count = 1) => ESC + count + "C";
|
|
3265
|
-
ESC + "";
|
|
3266
|
-
isTerminalApp || ESC + "";
|
|
3267
|
-
isTerminalApp || ESC + "";
|
|
3268
|
-
ESC + "";
|
|
3269
|
-
ESC + "";
|
|
3270
|
-
ESC + "";
|
|
3271
|
-
const cursorHide = ESC + "?25l";
|
|
3272
|
-
const cursorShow = ESC + "?25h";
|
|
3273
|
-
ESC + "";
|
|
3274
|
-
ESC + "";
|
|
3275
|
-
ESC + "";
|
|
3276
|
-
const eraseDown = ESC + "J";
|
|
3277
|
-
ESC + "";
|
|
3278
|
-
const eraseScreen = ESC + "2J";
|
|
3279
|
-
ESC + "";
|
|
3280
|
-
ESC + "";
|
|
3281
|
-
const clearScreen = "\x1Bc";
|
|
3282
|
-
`${eraseScreen}${ESC}`;
|
|
3283
|
-
isWindows ? `${eraseScreen}${ESC}` : `${eraseScreen}${ESC}${ESC}`;
|
|
3284
|
-
const enterAlternativeScreen = ESC + "?1049h";
|
|
3285
|
-
const exitAlternativeScreen = ESC + "?1049l";
|
|
3286
|
-
const SYNC_START = "\x1B[?2026h";
|
|
3287
|
-
const SYNC_END = "\x1B[?2026l";
|
|
3288
|
-
const DISABLE_LINE_WRAP = "\x1B[?7l";
|
|
3289
|
-
const ENABLE_LINE_WRAP = "\x1B[?7h";
|
|
3290
|
-
const ANSI_RESET = "\x1B[0m";
|
|
3291
|
-
var TerminalManager = class {
|
|
3292
|
-
stream;
|
|
3293
|
-
cursorHidden = false;
|
|
3294
|
-
buffer = [];
|
|
3295
|
-
useBuffering = false;
|
|
3296
|
-
alternateScreenActive = false;
|
|
3297
|
-
syncMode = false;
|
|
3298
|
-
constructor(stream = process$1.stdout) {
|
|
3299
|
-
this.stream = stream;
|
|
3300
|
-
}
|
|
3301
|
-
hideCursor() {
|
|
3302
|
-
if (!this.cursorHidden && this.stream.isTTY) {
|
|
3303
|
-
this.stream.write(cursorHide);
|
|
3304
|
-
this.cursorHidden = true;
|
|
3305
|
-
}
|
|
3306
|
-
}
|
|
3307
|
-
showCursor() {
|
|
3308
|
-
if (this.cursorHidden && this.stream.isTTY) {
|
|
3309
|
-
this.stream.write(cursorShow);
|
|
3310
|
-
this.cursorHidden = false;
|
|
3311
|
-
}
|
|
3312
|
-
}
|
|
3313
|
-
clearScreen() {
|
|
3314
|
-
if (this.stream.isTTY) {
|
|
3315
|
-
this.stream.write(clearScreen);
|
|
3316
|
-
this.stream.write(cursorTo(0, 0));
|
|
3317
|
-
}
|
|
3318
|
-
}
|
|
3319
|
-
write(text) {
|
|
3320
|
-
if (this.useBuffering) this.buffer.push(text);
|
|
3321
|
-
else this.stream.write(text);
|
|
3322
|
-
}
|
|
3323
|
-
startBuffering() {
|
|
3324
|
-
this.useBuffering = true;
|
|
3325
|
-
this.buffer = [];
|
|
3326
|
-
}
|
|
3327
|
-
flush() {
|
|
3328
|
-
if (this.useBuffering && this.buffer.length > 0) {
|
|
3329
|
-
if (this.syncMode && this.stream.isTTY) this.stream.write(SYNC_START + this.buffer.join("") + SYNC_END);
|
|
3330
|
-
else this.stream.write(this.buffer.join(""));
|
|
3331
|
-
this.buffer = [];
|
|
3332
|
-
}
|
|
3333
|
-
this.useBuffering = false;
|
|
3334
|
-
}
|
|
3335
|
-
enterAlternateScreen() {
|
|
3336
|
-
if (!this.alternateScreenActive && this.stream.isTTY) {
|
|
3337
|
-
this.stream.write(enterAlternativeScreen);
|
|
3338
|
-
this.stream.write(DISABLE_LINE_WRAP);
|
|
3339
|
-
this.alternateScreenActive = true;
|
|
3340
|
-
}
|
|
3341
|
-
}
|
|
3342
|
-
exitAlternateScreen() {
|
|
3343
|
-
if (this.alternateScreenActive && this.stream.isTTY) {
|
|
3344
|
-
this.stream.write(ENABLE_LINE_WRAP);
|
|
3345
|
-
this.stream.write(exitAlternativeScreen);
|
|
3346
|
-
this.alternateScreenActive = false;
|
|
3347
|
-
}
|
|
3348
|
-
}
|
|
3349
|
-
enableSyncMode() {
|
|
3350
|
-
this.syncMode = true;
|
|
3351
|
-
}
|
|
3352
|
-
disableSyncMode() {
|
|
3353
|
-
this.syncMode = false;
|
|
3354
|
-
}
|
|
3355
|
-
get width() {
|
|
3356
|
-
return this.stream.columns || 80;
|
|
3357
|
-
}
|
|
3358
|
-
get height() {
|
|
3359
|
-
return this.stream.rows || 24;
|
|
3360
|
-
}
|
|
3361
|
-
get isTTY() {
|
|
3362
|
-
return this.stream.isTTY ?? false;
|
|
3363
|
-
}
|
|
3364
|
-
cleanup() {
|
|
3365
|
-
this.showCursor();
|
|
3366
|
-
this.exitAlternateScreen();
|
|
3367
|
-
this.disableSyncMode();
|
|
3368
|
-
}
|
|
3369
|
-
};
|
|
3370
|
-
function createProgressBar(value$1, max, width, options = {}) {
|
|
3371
|
-
const { showPercentage = true, showValues = false, fillChar = "█", emptyChar = "░", leftBracket = "[", rightBracket = "]", colors: colors$2 = {} } = options;
|
|
3372
|
-
const percentage = max > 0 ? Math.min(100, value$1 / max * 100) : 0;
|
|
3373
|
-
const fillWidth = Math.round(percentage / 100 * width);
|
|
3374
|
-
const emptyWidth = width - fillWidth;
|
|
3375
|
-
let color = "";
|
|
3376
|
-
if (colors$2.critical != null && percentage >= 90) color = colors$2.critical;
|
|
3377
|
-
else if (colors$2.high != null && percentage >= 80) color = colors$2.high;
|
|
3378
|
-
else if (colors$2.medium != null && percentage >= 50) color = colors$2.medium;
|
|
3379
|
-
else if (colors$2.low != null) color = colors$2.low;
|
|
3380
|
-
let bar = leftBracket;
|
|
3381
|
-
if (color !== "") bar += color;
|
|
3382
|
-
bar += fillChar.repeat(fillWidth);
|
|
3383
|
-
bar += emptyChar.repeat(emptyWidth);
|
|
3384
|
-
if (color !== "") bar += ANSI_RESET;
|
|
3385
|
-
bar += rightBracket;
|
|
3386
|
-
if (showPercentage) bar += ` ${percentage.toFixed(1)}%`;
|
|
3387
|
-
if (showValues) bar += ` (${value$1}/${max})`;
|
|
3388
|
-
return bar;
|
|
3389
|
-
}
|
|
3390
|
-
function centerText(text, width) {
|
|
3391
|
-
const textLength = stringWidth(text);
|
|
3392
|
-
if (textLength >= width) return text;
|
|
3393
|
-
const leftPadding = Math.floor((width - textLength) / 2);
|
|
3394
|
-
const rightPadding = width - textLength - leftPadding;
|
|
3395
|
-
return " ".repeat(leftPadding) + text + " ".repeat(rightPadding);
|
|
3396
|
-
}
|
|
3397
|
-
const SAVE_CURSOR = "\x1B7";
|
|
3398
|
-
const RESTORE_CURSOR = "\x1B8";
|
|
3399
|
-
function drawEmoji(emoji) {
|
|
3400
|
-
return `${SAVE_CURSOR}${emoji}${RESTORE_CURSOR}${cursorForward(stringWidth(emoji))}`;
|
|
3401
|
-
}
|
|
3402
|
-
var Node = class {
|
|
3403
|
-
value;
|
|
3404
|
-
next;
|
|
3405
|
-
constructor(value$1) {
|
|
3406
|
-
this.value = value$1;
|
|
3407
|
-
}
|
|
3408
|
-
};
|
|
3409
|
-
var Queue = class {
|
|
3410
|
-
#head;
|
|
3411
|
-
#tail;
|
|
3412
|
-
#size;
|
|
3413
|
-
constructor() {
|
|
3414
|
-
this.clear();
|
|
3415
|
-
}
|
|
3416
|
-
enqueue(value$1) {
|
|
3417
|
-
const node = new Node(value$1);
|
|
3418
|
-
if (this.#head) {
|
|
3419
|
-
this.#tail.next = node;
|
|
3420
|
-
this.#tail = node;
|
|
3421
|
-
} else {
|
|
3422
|
-
this.#head = node;
|
|
3423
|
-
this.#tail = node;
|
|
3424
|
-
}
|
|
3425
|
-
this.#size++;
|
|
3426
|
-
}
|
|
3427
|
-
dequeue() {
|
|
3428
|
-
const current = this.#head;
|
|
3429
|
-
if (!current) return;
|
|
3430
|
-
this.#head = this.#head.next;
|
|
3431
|
-
this.#size--;
|
|
3432
|
-
return current.value;
|
|
3433
|
-
}
|
|
3434
|
-
peek() {
|
|
3435
|
-
if (!this.#head) return;
|
|
3436
|
-
return this.#head.value;
|
|
3437
|
-
}
|
|
3438
|
-
clear() {
|
|
3439
|
-
this.#head = void 0;
|
|
3440
|
-
this.#tail = void 0;
|
|
3441
|
-
this.#size = 0;
|
|
3442
|
-
}
|
|
3443
|
-
get size() {
|
|
3444
|
-
return this.#size;
|
|
3445
|
-
}
|
|
3446
|
-
*[Symbol.iterator]() {
|
|
3447
|
-
let current = this.#head;
|
|
3448
|
-
while (current) {
|
|
3449
|
-
yield current.value;
|
|
3450
|
-
current = current.next;
|
|
3451
|
-
}
|
|
3452
|
-
}
|
|
3453
|
-
*drain() {
|
|
3454
|
-
while (this.#head) yield this.dequeue();
|
|
3455
|
-
}
|
|
3456
|
-
};
|
|
3457
|
-
function pLimit(concurrency) {
|
|
3458
|
-
validateConcurrency(concurrency);
|
|
3459
|
-
const queue = new Queue();
|
|
3460
|
-
let activeCount = 0;
|
|
3461
|
-
const resumeNext = () => {
|
|
3462
|
-
if (activeCount < concurrency && queue.size > 0) {
|
|
3463
|
-
activeCount++;
|
|
3464
|
-
queue.dequeue()();
|
|
3465
|
-
}
|
|
3466
|
-
};
|
|
3467
|
-
const next = () => {
|
|
3468
|
-
activeCount--;
|
|
3469
|
-
resumeNext();
|
|
3470
|
-
};
|
|
3471
|
-
const run$1 = async (function_, resolve$1, arguments_) => {
|
|
3472
|
-
const result = (async () => function_(...arguments_))();
|
|
3473
|
-
resolve$1(result);
|
|
3474
|
-
try {
|
|
3475
|
-
await result;
|
|
3476
|
-
} catch {}
|
|
3477
|
-
next();
|
|
3478
|
-
};
|
|
3479
|
-
const enqueue = (function_, resolve$1, arguments_) => {
|
|
3480
|
-
new Promise((internalResolve) => {
|
|
3481
|
-
queue.enqueue(internalResolve);
|
|
3482
|
-
}).then(run$1.bind(void 0, function_, resolve$1, arguments_));
|
|
3483
|
-
if (activeCount < concurrency) resumeNext();
|
|
3484
|
-
};
|
|
3485
|
-
const generator = (function_, ...arguments_) => new Promise((resolve$1) => {
|
|
3486
|
-
enqueue(function_, resolve$1, arguments_);
|
|
3487
|
-
});
|
|
3488
|
-
Object.defineProperties(generator, {
|
|
3489
|
-
activeCount: { get: () => activeCount },
|
|
3490
|
-
pendingCount: { get: () => queue.size },
|
|
3491
|
-
clearQueue: { value() {
|
|
3492
|
-
queue.clear();
|
|
3493
|
-
} },
|
|
3494
|
-
concurrency: {
|
|
3495
|
-
get: () => concurrency,
|
|
3496
|
-
set(newConcurrency) {
|
|
3497
|
-
validateConcurrency(newConcurrency);
|
|
3498
|
-
concurrency = newConcurrency;
|
|
3499
|
-
queueMicrotask(() => {
|
|
3500
|
-
while (activeCount < concurrency && queue.size > 0) resumeNext();
|
|
3501
|
-
});
|
|
3502
|
-
}
|
|
3503
|
-
},
|
|
3504
|
-
map: { async value(array, function_) {
|
|
3505
|
-
const promises = array.map((value$1, index) => this(function_, value$1, index));
|
|
3506
|
-
return Promise.all(promises);
|
|
3507
|
-
} }
|
|
3508
|
-
});
|
|
3509
|
-
return generator;
|
|
3510
|
-
}
|
|
3511
|
-
function validateConcurrency(concurrency) {
|
|
3512
|
-
if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) throw new TypeError("Expected `concurrency` to be a number from 1 and up");
|
|
3513
|
-
}
|
|
3514
|
-
const RETENTION_HOURS = 24;
|
|
3515
|
-
const FILE_CONCURRENCY = 5;
|
|
3516
|
-
async function isRecentFile(filePath, cutoffTime) {
|
|
3517
|
-
return pipe(try_({
|
|
3518
|
-
try: stat(filePath),
|
|
3519
|
-
catch: (error) => error
|
|
3520
|
-
}), map$2((fileStats) => fileStats.mtime >= cutoffTime), unwrap(false));
|
|
3521
|
-
}
|
|
3522
|
-
function createLiveMonitorState(config) {
|
|
3523
|
-
const fetcher = config.mode !== "display" ? new PricingFetcher() : null;
|
|
3524
|
-
return {
|
|
3525
|
-
fetcher,
|
|
3526
|
-
lastFileTimestamps: /* @__PURE__ */ new Map(),
|
|
3527
|
-
processedHashes: /* @__PURE__ */ new Set(),
|
|
3528
|
-
allEntries: [],
|
|
3529
|
-
[Symbol.dispose]() {
|
|
3530
|
-
fetcher?.[Symbol.dispose]();
|
|
3531
|
-
}
|
|
3532
|
-
};
|
|
3533
|
-
}
|
|
3534
|
-
function clearLiveMonitorCache(state) {
|
|
3535
|
-
state.lastFileTimestamps.clear();
|
|
3536
|
-
state.processedHashes.clear();
|
|
3537
|
-
state.allEntries = [];
|
|
3538
|
-
}
|
|
3539
|
-
function cleanupOldEntries(state, cutoffTime) {
|
|
3540
|
-
const initialCount = state.allEntries.length;
|
|
3541
|
-
state.allEntries = state.allEntries.filter((entry) => entry.timestamp >= cutoffTime);
|
|
3542
|
-
if (initialCount - state.allEntries.length > 100) state.processedHashes.clear();
|
|
3543
|
-
}
|
|
3544
|
-
async function processFileContent(state, config, content, cutoffTime) {
|
|
3545
|
-
const lines = content.trim().split("\n").filter((line) => line.length > 0);
|
|
3546
|
-
for (const line of lines) {
|
|
3547
|
-
const dataResult = pipe(try_({
|
|
3548
|
-
try: () => JSON.parse(line),
|
|
3549
|
-
catch: (error) => error
|
|
3550
|
-
})(), andThen((data$1) => {
|
|
3551
|
-
const parseResult = safeParse(usageDataSchema, data$1);
|
|
3552
|
-
return parseResult.success ? succeed(parseResult.output) : fail(parseResult.issues);
|
|
3553
|
-
}));
|
|
3554
|
-
if (isFailure(dataResult)) continue;
|
|
3555
|
-
const data = unwrap(dataResult);
|
|
3556
|
-
const entryTime = new Date(data.timestamp);
|
|
3557
|
-
if (entryTime < cutoffTime) continue;
|
|
3558
|
-
const uniqueHash = createUniqueHash(data);
|
|
3559
|
-
if (uniqueHash != null && state.processedHashes.has(uniqueHash)) continue;
|
|
3560
|
-
if (uniqueHash != null) state.processedHashes.add(uniqueHash);
|
|
3561
|
-
const costUSD = await (config.mode === "display" ? Promise.resolve(data.costUSD ?? 0) : calculateCostForEntry(data, config.mode, state.fetcher));
|
|
3562
|
-
const usageLimitResetTime = getUsageLimitResetTime(data);
|
|
3563
|
-
state.allEntries.push({
|
|
3564
|
-
timestamp: entryTime,
|
|
3565
|
-
usage: {
|
|
3566
|
-
inputTokens: data.message.usage.input_tokens ?? 0,
|
|
3567
|
-
outputTokens: data.message.usage.output_tokens ?? 0,
|
|
3568
|
-
cacheCreationInputTokens: data.message.usage.cache_creation_input_tokens ?? 0,
|
|
3569
|
-
cacheReadInputTokens: data.message.usage.cache_read_input_tokens ?? 0
|
|
3570
|
-
},
|
|
3571
|
-
costUSD,
|
|
3572
|
-
model: data.message.model ?? "<synthetic>",
|
|
3573
|
-
version: data.version,
|
|
3574
|
-
usageLimitResetTime: usageLimitResetTime ?? void 0
|
|
3575
|
-
});
|
|
3576
|
-
}
|
|
3577
|
-
}
|
|
3578
|
-
async function getActiveBlock(state, config) {
|
|
3579
|
-
const cutoffTime = /* @__PURE__ */ new Date(Date.now() - RETENTION_HOURS * 60 * 60 * 1e3);
|
|
3580
|
-
const allFiles = (await globUsageFiles(config.claudePaths)).map((r) => r.file);
|
|
3581
|
-
if (allFiles.length === 0) return null;
|
|
3582
|
-
const candidateFiles = [];
|
|
3583
|
-
for (const file of allFiles) if (await isRecentFile(file, cutoffTime)) candidateFiles.push(file);
|
|
3584
|
-
const filesToRead = [];
|
|
3585
|
-
for (const file of candidateFiles) {
|
|
3586
|
-
const timestamp$1 = await getEarliestTimestamp(file);
|
|
3587
|
-
const lastTimestamp = state.lastFileTimestamps.get(file);
|
|
3588
|
-
if (timestamp$1 != null && (lastTimestamp == null || timestamp$1.getTime() > lastTimestamp)) {
|
|
3589
|
-
filesToRead.push(file);
|
|
3590
|
-
state.lastFileTimestamps.set(file, timestamp$1.getTime());
|
|
3591
|
-
}
|
|
3592
|
-
}
|
|
3593
|
-
cleanupOldEntries(state, cutoffTime);
|
|
3594
|
-
if (filesToRead.length > 0) {
|
|
3595
|
-
const sortedFiles = await sortFilesByTimestamp(filesToRead);
|
|
3596
|
-
const fileLimit = pLimit(FILE_CONCURRENCY);
|
|
3597
|
-
const fileResults = await Promise.allSettled(sortedFiles.map(async (file) => fileLimit(async () => ({
|
|
3598
|
-
file,
|
|
3599
|
-
content: await readFile(file, "utf-8")
|
|
3600
|
-
}))));
|
|
3601
|
-
for (const result of fileResults) if (result.status === "fulfilled") {
|
|
3602
|
-
const { content } = result.value;
|
|
3603
|
-
await processFileContent(state, config, content, cutoffTime);
|
|
3604
|
-
}
|
|
3605
|
-
}
|
|
3606
|
-
const blocks = identifySessionBlocks(state.allEntries, config.sessionDurationHours);
|
|
3607
|
-
return (config.order === "asc" ? blocks : blocks.reverse()).find((block) => block.isActive) ?? null;
|
|
3608
|
-
}
|
|
3609
|
-
function delay(ms, options = {}) {
|
|
3610
|
-
const { signal, persistent = true } = options;
|
|
3611
|
-
if (signal?.aborted) return Promise.reject(signal.reason);
|
|
3612
|
-
return new Promise((resolve$1, reject) => {
|
|
3613
|
-
const abort = () => {
|
|
3614
|
-
clearTimeout(+i);
|
|
3615
|
-
reject(signal?.reason);
|
|
3616
|
-
};
|
|
3617
|
-
const done = () => {
|
|
3618
|
-
signal?.removeEventListener("abort", abort);
|
|
3619
|
-
resolve$1();
|
|
3620
|
-
};
|
|
3621
|
-
const i = setArbitraryLengthTimeout(done, ms);
|
|
3622
|
-
signal?.addEventListener("abort", abort, { once: true });
|
|
3623
|
-
if (persistent === false) try {
|
|
3624
|
-
Deno.unrefTimer(i);
|
|
3625
|
-
} catch (error) {
|
|
3626
|
-
if (!(error instanceof ReferenceError)) throw error;
|
|
3627
|
-
console.error("`persistent` option is only available in Deno");
|
|
3628
|
-
}
|
|
3629
|
-
});
|
|
3630
|
-
}
|
|
3631
|
-
const I32_MAX = 2 ** 31 - 1;
|
|
3632
|
-
function setArbitraryLengthTimeout(callback, delay$1) {
|
|
3633
|
-
let currentDelay = delay$1 = Math.trunc(Math.max(delay$1, 0) || 0);
|
|
3634
|
-
const start = Date.now();
|
|
3635
|
-
let timeoutId;
|
|
3636
|
-
const queueTimeout = () => {
|
|
3637
|
-
currentDelay = delay$1 - (Date.now() - start);
|
|
3638
|
-
timeoutId = currentDelay > I32_MAX ? setTimeout(queueTimeout, I32_MAX) : setTimeout(callback, currentDelay);
|
|
3639
|
-
};
|
|
3640
|
-
queueTimeout();
|
|
3641
|
-
return { valueOf: () => timeoutId };
|
|
3642
|
-
}
|
|
3643
|
-
Symbol.asyncIterator;
|
|
3644
|
-
const toZeroIfInfinity = (value$1) => Number.isFinite(value$1) ? value$1 : 0;
|
|
3645
|
-
function parseNumber(milliseconds) {
|
|
3646
|
-
return {
|
|
3647
|
-
days: Math.trunc(milliseconds / 864e5),
|
|
3648
|
-
hours: Math.trunc(milliseconds / 36e5 % 24),
|
|
3649
|
-
minutes: Math.trunc(milliseconds / 6e4 % 60),
|
|
3650
|
-
seconds: Math.trunc(milliseconds / 1e3 % 60),
|
|
3651
|
-
milliseconds: Math.trunc(milliseconds % 1e3),
|
|
3652
|
-
microseconds: Math.trunc(toZeroIfInfinity(milliseconds * 1e3) % 1e3),
|
|
3653
|
-
nanoseconds: Math.trunc(toZeroIfInfinity(milliseconds * 1e6) % 1e3)
|
|
3654
|
-
};
|
|
3655
|
-
}
|
|
3656
|
-
function parseBigint(milliseconds) {
|
|
3657
|
-
return {
|
|
3658
|
-
days: milliseconds / 86400000n,
|
|
3659
|
-
hours: milliseconds / 3600000n % 24n,
|
|
3660
|
-
minutes: milliseconds / 60000n % 60n,
|
|
3661
|
-
seconds: milliseconds / 1000n % 60n,
|
|
3662
|
-
milliseconds: milliseconds % 1000n,
|
|
3663
|
-
microseconds: 0n,
|
|
3664
|
-
nanoseconds: 0n
|
|
3665
|
-
};
|
|
3666
|
-
}
|
|
3667
|
-
function parseMilliseconds(milliseconds) {
|
|
3668
|
-
switch (typeof milliseconds) {
|
|
3669
|
-
case "number":
|
|
3670
|
-
if (Number.isFinite(milliseconds)) return parseNumber(milliseconds);
|
|
3671
|
-
break;
|
|
3672
|
-
case "bigint": return parseBigint(milliseconds);
|
|
3673
|
-
}
|
|
3674
|
-
throw new TypeError("Expected a finite number or bigint");
|
|
3675
|
-
}
|
|
3676
|
-
const isZero = (value$1) => value$1 === 0 || value$1 === 0n;
|
|
3677
|
-
const pluralize = (word, count) => count === 1 || count === 1n ? word : `${word}s`;
|
|
3678
|
-
const SECOND_ROUNDING_EPSILON = 1e-7;
|
|
3679
|
-
const ONE_DAY_IN_MILLISECONDS = 24n * 60n * 60n * 1000n;
|
|
3680
|
-
function prettyMilliseconds(milliseconds, options) {
|
|
3681
|
-
const isBigInt = typeof milliseconds === "bigint";
|
|
3682
|
-
if (!isBigInt && !Number.isFinite(milliseconds)) throw new TypeError("Expected a finite number or bigint");
|
|
3683
|
-
options = { ...options };
|
|
3684
|
-
const sign = milliseconds < 0 ? "-" : "";
|
|
3685
|
-
milliseconds = milliseconds < 0 ? -milliseconds : milliseconds;
|
|
3686
|
-
if (options.colonNotation) {
|
|
3687
|
-
options.compact = false;
|
|
3688
|
-
options.formatSubMilliseconds = false;
|
|
3689
|
-
options.separateMilliseconds = false;
|
|
3690
|
-
options.verbose = false;
|
|
3691
|
-
}
|
|
3692
|
-
if (options.compact) {
|
|
3693
|
-
options.unitCount = 1;
|
|
3694
|
-
options.secondsDecimalDigits = 0;
|
|
3695
|
-
options.millisecondsDecimalDigits = 0;
|
|
3696
|
-
}
|
|
3697
|
-
let result = [];
|
|
3698
|
-
const floorDecimals = (value$1, decimalDigits) => {
|
|
3699
|
-
const flooredInterimValue = Math.floor(value$1 * 10 ** decimalDigits + SECOND_ROUNDING_EPSILON);
|
|
3700
|
-
return (Math.round(flooredInterimValue) / 10 ** decimalDigits).toFixed(decimalDigits);
|
|
3701
|
-
};
|
|
3702
|
-
const add = (value$1, long, short, valueString) => {
|
|
3703
|
-
if ((result.length === 0 || !options.colonNotation) && isZero(value$1) && !(options.colonNotation && short === "m")) return;
|
|
3704
|
-
valueString ??= String(value$1);
|
|
3705
|
-
if (options.colonNotation) {
|
|
3706
|
-
const wholeDigits = valueString.includes(".") ? valueString.split(".")[0].length : valueString.length;
|
|
3707
|
-
const minLength = result.length > 0 ? 2 : 1;
|
|
3708
|
-
valueString = "0".repeat(Math.max(0, minLength - wholeDigits)) + valueString;
|
|
3709
|
-
} else valueString += options.verbose ? " " + pluralize(long, value$1) : short;
|
|
3710
|
-
result.push(valueString);
|
|
3711
|
-
};
|
|
3712
|
-
const parsed = parseMilliseconds(milliseconds);
|
|
3713
|
-
const days = BigInt(parsed.days);
|
|
3714
|
-
if (options.hideYearAndDays) add(BigInt(days) * 24n + BigInt(parsed.hours), "hour", "h");
|
|
3715
|
-
else {
|
|
3716
|
-
if (options.hideYear) add(days, "day", "d");
|
|
3717
|
-
else {
|
|
3718
|
-
add(days / 365n, "year", "y");
|
|
3719
|
-
add(days % 365n, "day", "d");
|
|
3720
|
-
}
|
|
3721
|
-
add(Number(parsed.hours), "hour", "h");
|
|
3722
|
-
}
|
|
3723
|
-
add(Number(parsed.minutes), "minute", "m");
|
|
3724
|
-
if (!options.hideSeconds) if (options.separateMilliseconds || options.formatSubMilliseconds || !options.colonNotation && milliseconds < 1e3 && !options.subSecondsAsDecimals) {
|
|
3725
|
-
const seconds = Number(parsed.seconds);
|
|
3726
|
-
const milliseconds$1 = Number(parsed.milliseconds);
|
|
3727
|
-
const microseconds = Number(parsed.microseconds);
|
|
3728
|
-
const nanoseconds = Number(parsed.nanoseconds);
|
|
3729
|
-
add(seconds, "second", "s");
|
|
3730
|
-
if (options.formatSubMilliseconds) {
|
|
3731
|
-
add(milliseconds$1, "millisecond", "ms");
|
|
3732
|
-
add(microseconds, "microsecond", "µs");
|
|
3733
|
-
add(nanoseconds, "nanosecond", "ns");
|
|
3734
|
-
} else {
|
|
3735
|
-
const millisecondsAndBelow = milliseconds$1 + microseconds / 1e3 + nanoseconds / 1e6;
|
|
3736
|
-
const millisecondsDecimalDigits = typeof options.millisecondsDecimalDigits === "number" ? options.millisecondsDecimalDigits : 0;
|
|
3737
|
-
const millisecondsString = millisecondsDecimalDigits ? millisecondsAndBelow.toFixed(millisecondsDecimalDigits) : millisecondsAndBelow >= 1 ? Math.round(millisecondsAndBelow) : Math.ceil(millisecondsAndBelow);
|
|
3738
|
-
add(Number.parseFloat(millisecondsString), "millisecond", "ms", millisecondsString);
|
|
3739
|
-
}
|
|
3740
|
-
} else {
|
|
3741
|
-
const secondsFixed = floorDecimals((isBigInt ? Number(milliseconds % ONE_DAY_IN_MILLISECONDS) : milliseconds) / 1e3 % 60, typeof options.secondsDecimalDigits === "number" ? options.secondsDecimalDigits : 1);
|
|
3742
|
-
const secondsString = options.keepDecimalsOnWholeSeconds ? secondsFixed : secondsFixed.replace(/\.0+$/, "");
|
|
3743
|
-
add(Number.parseFloat(secondsString), "second", "s", secondsString);
|
|
3744
|
-
}
|
|
3745
|
-
if (result.length === 0) return sign + "0" + (options.verbose ? " milliseconds" : "ms");
|
|
3746
|
-
const separator = options.colonNotation ? ":" : " ";
|
|
3747
|
-
if (typeof options.unitCount === "number") result = result.slice(0, Math.max(options.unitCount, 1));
|
|
3748
|
-
return sign + result.join(separator);
|
|
3749
|
-
}
|
|
3750
|
-
var import_picocolors$4 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
|
|
3751
|
-
function getRateIndicator(burnRate) {
|
|
3752
|
-
if (burnRate == null) return "";
|
|
3753
|
-
switch (true) {
|
|
3754
|
-
case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.HIGH: return import_picocolors$4.default.red(`${drawEmoji("⚡")} HIGH`);
|
|
3755
|
-
case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.MODERATE: return import_picocolors$4.default.yellow(`${drawEmoji("⚡")} MODERATE`);
|
|
3756
|
-
default: return import_picocolors$4.default.green(`${drawEmoji("✓")} NORMAL`);
|
|
3757
|
-
}
|
|
3758
|
-
}
|
|
3759
|
-
async function delayWithAbort(ms, signal) {
|
|
3760
|
-
await delay(ms, { signal });
|
|
3761
|
-
}
|
|
3762
|
-
async function renderWaitingState(terminal, config, signal) {
|
|
3763
|
-
terminal.startBuffering();
|
|
3764
|
-
terminal.write(cursorTo(0, 0));
|
|
3765
|
-
terminal.write(eraseDown);
|
|
3766
|
-
terminal.write(import_picocolors$4.default.yellow("No active session block found. Waiting...\n"));
|
|
3767
|
-
terminal.write(cursorHide);
|
|
3768
|
-
terminal.flush();
|
|
3769
|
-
await delayWithAbort(config.refreshInterval, signal);
|
|
3770
|
-
}
|
|
3771
|
-
function renderActiveBlock(terminal, activeBlock, config) {
|
|
3772
|
-
terminal.startBuffering();
|
|
3773
|
-
terminal.write(cursorTo(0, 0));
|
|
3774
|
-
terminal.write(eraseDown);
|
|
3775
|
-
renderLiveDisplay(terminal, activeBlock, config);
|
|
3776
|
-
terminal.write(cursorHide);
|
|
3777
|
-
terminal.flush();
|
|
3778
|
-
}
|
|
3779
|
-
function formatTokensShort(num) {
|
|
3780
|
-
if (num >= 1e3) return `${(num / 1e3).toFixed(1)}k`;
|
|
3781
|
-
return num.toString();
|
|
3782
|
-
}
|
|
3783
|
-
function renderLiveDisplay(terminal, block, config) {
|
|
3784
|
-
const width = terminal.width;
|
|
3785
|
-
const now = /* @__PURE__ */ new Date();
|
|
3786
|
-
const totalTokens = getTotalTokens(block.tokenCounts);
|
|
3787
|
-
const elapsed = (now.getTime() - block.startTime.getTime()) / (1e3 * 60);
|
|
3788
|
-
const remaining = (block.endTime.getTime() - now.getTime()) / (1e3 * 60);
|
|
3789
|
-
const formatTokenDisplay = (tokens, useShort) => {
|
|
3790
|
-
return useShort ? formatTokensShort(tokens) : formatNumber(tokens);
|
|
3791
|
-
};
|
|
3792
|
-
if (width < 60) {
|
|
3793
|
-
renderCompactLiveDisplay(terminal, block, config, totalTokens, elapsed, remaining);
|
|
3794
|
-
return;
|
|
3795
|
-
}
|
|
3796
|
-
const boxWidth = Math.min(120, width - 2);
|
|
3797
|
-
const boxMargin = Math.floor((width - boxWidth) / 2);
|
|
3798
|
-
const marginStr = " ".repeat(boxMargin);
|
|
3799
|
-
const sessionDuration = elapsed + remaining;
|
|
3800
|
-
const sessionRightText = `${(elapsed / sessionDuration * 100).toFixed(1).padStart(6)}%`;
|
|
3801
|
-
const tokenPercent = config.tokenLimit != null && config.tokenLimit > 0 ? totalTokens / config.tokenLimit * 100 : 0;
|
|
3802
|
-
const usageRightText = config.tokenLimit != null && config.tokenLimit > 0 ? `${tokenPercent.toFixed(1).padStart(6)}% (${formatTokensShort(totalTokens)}/${formatTokensShort(config.tokenLimit)})` : `(${formatTokensShort(totalTokens)} tokens)`;
|
|
3803
|
-
const projection = projectBlockUsage(block);
|
|
3804
|
-
const projectedPercent = projection != null && config.tokenLimit != null && config.tokenLimit > 0 ? projection.totalTokens / config.tokenLimit * 100 : 0;
|
|
3805
|
-
const projectionRightText = projection != null ? config.tokenLimit != null && config.tokenLimit > 0 ? `${projectedPercent.toFixed(1).padStart(6)}% (${formatTokensShort(projection.totalTokens)}/${formatTokensShort(config.tokenLimit)})` : `(${formatTokensShort(projection.totalTokens)} tokens)` : "";
|
|
3806
|
-
const maxRightTextWidth = Math.max(stringWidth(sessionRightText), stringWidth(usageRightText), projection != null ? stringWidth(projectionRightText) : 0);
|
|
3807
|
-
const labelWidth = 14;
|
|
3808
|
-
const barWidth = boxWidth - labelWidth - maxRightTextWidth - 4 - 4;
|
|
3809
|
-
const sessionProgressBar = createProgressBar(elapsed, sessionDuration, barWidth, {
|
|
3810
|
-
showPercentage: false,
|
|
3811
|
-
fillChar: import_picocolors$4.default.cyan("█"),
|
|
3812
|
-
emptyChar: import_picocolors$4.default.gray("░"),
|
|
3813
|
-
leftBracket: "[",
|
|
3814
|
-
rightBracket: "]"
|
|
3815
|
-
});
|
|
3816
|
-
const startTime = block.startTime.toLocaleTimeString(void 0, {
|
|
3817
|
-
hour: "2-digit",
|
|
3818
|
-
minute: "2-digit",
|
|
3819
|
-
second: "2-digit",
|
|
3820
|
-
hour12: true
|
|
3821
|
-
});
|
|
3822
|
-
const endTime = block.endTime.toLocaleTimeString(void 0, {
|
|
3823
|
-
hour: "2-digit",
|
|
3824
|
-
minute: "2-digit",
|
|
3825
|
-
second: "2-digit",
|
|
3826
|
-
hour12: true
|
|
3827
|
-
});
|
|
3828
|
-
const detailsIndent = 3;
|
|
3829
|
-
const detailsSpacing = 2;
|
|
3830
|
-
const detailsAvailableWidth = boxWidth - 3 - detailsIndent;
|
|
3831
|
-
terminal.write(`${marginStr}┌${"─".repeat(boxWidth - 2)}┐\n`);
|
|
3832
|
-
terminal.write(`${marginStr}│${import_picocolors$4.default.bold(centerText("CLAUDE CODE - LIVE TOKEN USAGE MONITOR", boxWidth - 2))}│\n`);
|
|
3833
|
-
terminal.write(`${marginStr}│${import_picocolors$4.default.yellow(centerText("⚠️ DEPRECATED - Will be removed in next major version", boxWidth - 2))}│\n`);
|
|
3834
|
-
terminal.write(`${marginStr}│${import_picocolors$4.default.gray(centerText("Use https://claude.ai/settings/usage instead", boxWidth - 2))}│\n`);
|
|
3835
|
-
terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
|
|
3836
|
-
terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
|
|
3837
|
-
const sessionLabel = `${drawEmoji("⏱️")}${import_picocolors$4.default.bold(" SESSION")}`;
|
|
3838
|
-
const sessionLabelWidth = stringWidth(sessionLabel);
|
|
3839
|
-
const sessionBarStr = `${sessionLabel}${"".padEnd(Math.max(0, labelWidth - sessionLabelWidth))} ${sessionProgressBar} ${sessionRightText}`;
|
|
3840
|
-
const sessionBarPadded = sessionBarStr + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(sessionBarStr)));
|
|
3841
|
-
terminal.write(`${marginStr}│ ${sessionBarPadded}│\n`);
|
|
3842
|
-
const sessionCol1 = `${import_picocolors$4.default.gray("Started:")} ${startTime}`;
|
|
3843
|
-
const sessionCol2 = `${import_picocolors$4.default.gray("Elapsed:")} ${prettyMilliseconds(elapsed * 60 * 1e3, { compact: true })}`;
|
|
3844
|
-
const sessionCol3 = `${import_picocolors$4.default.gray("Remaining:")} ${prettyMilliseconds(remaining * 60 * 1e3, { compact: true })} (${endTime})`;
|
|
3845
|
-
let sessionDetails = `${" ".repeat(detailsIndent)}${sessionCol1}${" ".repeat(detailsSpacing)}${sessionCol2}${" ".repeat(detailsSpacing)}${sessionCol3}`;
|
|
3846
|
-
if (stringWidth(sessionCol1) + stringWidth(sessionCol2) + stringWidth(sessionCol3) + detailsSpacing * 2 > detailsAvailableWidth) sessionDetails = `${" ".repeat(detailsIndent)}${sessionCol1}${" ".repeat(detailsSpacing)}${sessionCol3}`;
|
|
3847
|
-
const sessionDetailsPadded = sessionDetails + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(sessionDetails)));
|
|
3848
|
-
let usageLimitResetTimePadded = null;
|
|
3849
|
-
if (block.usageLimitResetTime !== void 0 && now < block.usageLimitResetTime) {
|
|
3850
|
-
const resetTime = block.usageLimitResetTime?.toLocaleTimeString(void 0, {
|
|
3851
|
-
hour: "2-digit",
|
|
3852
|
-
minute: "2-digit",
|
|
3853
|
-
hour12: true
|
|
3854
|
-
}) ?? null;
|
|
3855
|
-
const usageLimitResetTime = resetTime !== null ? import_picocolors$4.default.red(`${drawEmoji("❌")} USAGE LIMIT. RESET AT ${resetTime}`) : "";
|
|
3856
|
-
usageLimitResetTimePadded = resetTime !== null ? usageLimitResetTime + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(usageLimitResetTime))) : null;
|
|
3857
|
-
}
|
|
3858
|
-
terminal.write(`${marginStr}│ ${sessionDetailsPadded}│\n`);
|
|
3859
|
-
if (usageLimitResetTimePadded !== null) terminal.write(`${marginStr}│ ${usageLimitResetTimePadded}│\n`);
|
|
3860
|
-
terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
|
|
3861
|
-
terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
|
|
3862
|
-
terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
|
|
3863
|
-
let barColor = import_picocolors$4.default.green;
|
|
3864
|
-
if (tokenPercent > 100) barColor = import_picocolors$4.default.red;
|
|
3865
|
-
else if (tokenPercent > 80) barColor = import_picocolors$4.default.yellow;
|
|
3866
|
-
const usageBar = config.tokenLimit != null && config.tokenLimit > 0 ? createProgressBar(totalTokens, config.tokenLimit, barWidth, {
|
|
3867
|
-
showPercentage: false,
|
|
3868
|
-
fillChar: barColor("█"),
|
|
3869
|
-
emptyChar: import_picocolors$4.default.gray("░"),
|
|
3870
|
-
leftBracket: "[",
|
|
3871
|
-
rightBracket: "]"
|
|
3872
|
-
}) : `[${import_picocolors$4.default.green("█".repeat(Math.floor(barWidth * .1)))}${import_picocolors$4.default.gray("░".repeat(barWidth - Math.floor(barWidth * .1)))}]`;
|
|
3873
|
-
const burnRate = calculateBurnRate(block);
|
|
3874
|
-
const rateIndicator = getRateIndicator(burnRate);
|
|
3875
|
-
const buildRateDisplay = (useShort) => {
|
|
3876
|
-
if (burnRate == null) return `${import_picocolors$4.default.bold("Burn Rate:")} N/A`;
|
|
3877
|
-
const rateValue = Math.round(burnRate.tokensPerMinute);
|
|
3878
|
-
const formattedRate = useShort ? formatTokensShort(rateValue) : formatNumber(rateValue);
|
|
3879
|
-
return `${import_picocolors$4.default.bold("Burn Rate:")} ${formattedRate} token/min ${rateIndicator}`;
|
|
3880
|
-
};
|
|
3881
|
-
const usageLabel = `${drawEmoji("🔥")}${import_picocolors$4.default.bold(" USAGE")}`;
|
|
3882
|
-
const usageLabelWidth = stringWidth(usageLabel);
|
|
3883
|
-
const usageBarStr = `${usageLabel}${"".padEnd(Math.max(0, labelWidth - usageLabelWidth))} ${usageBar} ${usageRightText}`;
|
|
3884
|
-
let rateDisplay = buildRateDisplay(false);
|
|
3885
|
-
let usageCol1 = `${import_picocolors$4.default.gray("Tokens:")} ${formatTokenDisplay(totalTokens, false)} (${rateDisplay})`;
|
|
3886
|
-
let usageCol2 = config.tokenLimit != null && config.tokenLimit > 0 ? `${import_picocolors$4.default.gray("Limit:")} ${formatTokenDisplay(config.tokenLimit, false)} tokens` : "";
|
|
3887
|
-
const usageCol3 = `${import_picocolors$4.default.gray("Cost:")} ${formatCurrency(block.costUSD)}`;
|
|
3888
|
-
let totalWidth = stringWidth(usageCol1);
|
|
3889
|
-
if (usageCol2.length > 0) totalWidth += detailsSpacing + stringWidth(usageCol2);
|
|
3890
|
-
totalWidth += detailsSpacing + stringWidth(usageCol3);
|
|
3891
|
-
let useTwoLineLayout = false;
|
|
3892
|
-
if (totalWidth > detailsAvailableWidth) {
|
|
3893
|
-
useTwoLineLayout = true;
|
|
3894
|
-
rateDisplay = buildRateDisplay(true);
|
|
3895
|
-
usageCol1 = `${import_picocolors$4.default.gray("Tokens:")} ${formatTokenDisplay(totalTokens, true)} (${rateDisplay})`;
|
|
3896
|
-
if (usageCol2.length > 0) usageCol2 = `${import_picocolors$4.default.gray("Limit:")} ${formatTokenDisplay(config.tokenLimit, true)} tokens`;
|
|
3897
|
-
}
|
|
3898
|
-
const usageBarPadded = usageBarStr + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(usageBarStr)));
|
|
3899
|
-
terminal.write(`${marginStr}│ ${usageBarPadded}│\n`);
|
|
3900
|
-
if (useTwoLineLayout) {
|
|
3901
|
-
const usageDetailsLine1 = `${" ".repeat(detailsIndent)}${usageCol1}`;
|
|
3902
|
-
const usageDetailsLine1Padded = usageDetailsLine1 + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(usageDetailsLine1)));
|
|
3903
|
-
terminal.write(`${marginStr}│ ${usageDetailsLine1Padded}│\n`);
|
|
3904
|
-
let usageDetailsLine2;
|
|
3905
|
-
if (usageCol2.length > 0) usageDetailsLine2 = `${" ".repeat(detailsIndent)}${usageCol2}${" ".repeat(detailsSpacing)}${usageCol3}`;
|
|
3906
|
-
else usageDetailsLine2 = `${" ".repeat(detailsIndent)}${usageCol3}`;
|
|
3907
|
-
const usageDetailsLine2Padded = usageDetailsLine2 + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(usageDetailsLine2)));
|
|
3908
|
-
terminal.write(`${marginStr}│ ${usageDetailsLine2Padded}│\n`);
|
|
3909
|
-
} else {
|
|
3910
|
-
let usageDetails;
|
|
3911
|
-
if (usageCol2.length > 0) usageDetails = `${" ".repeat(detailsIndent)}${usageCol1}${" ".repeat(detailsSpacing)}${usageCol2}${" ".repeat(detailsSpacing)}${usageCol3}`;
|
|
3912
|
-
else usageDetails = `${" ".repeat(detailsIndent)}${usageCol1}${" ".repeat(detailsSpacing)}${usageCol3}`;
|
|
3913
|
-
const usageDetailsPadded = usageDetails + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(usageDetails)));
|
|
3914
|
-
terminal.write(`${marginStr}│ ${usageDetailsPadded}│\n`);
|
|
3915
|
-
}
|
|
3916
|
-
terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
|
|
3917
|
-
terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
|
|
3918
|
-
terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
|
|
3919
|
-
if (projection != null) {
|
|
3920
|
-
let projBarColor = import_picocolors$4.default.green;
|
|
3921
|
-
if (projectedPercent > 100) projBarColor = import_picocolors$4.default.red;
|
|
3922
|
-
else if (projectedPercent > 80) projBarColor = import_picocolors$4.default.yellow;
|
|
3923
|
-
const projectionBar = config.tokenLimit != null && config.tokenLimit > 0 ? createProgressBar(projection.totalTokens, config.tokenLimit, barWidth, {
|
|
3924
|
-
showPercentage: false,
|
|
3925
|
-
fillChar: projBarColor("█"),
|
|
3926
|
-
emptyChar: import_picocolors$4.default.gray("░"),
|
|
3927
|
-
leftBracket: "[",
|
|
3928
|
-
rightBracket: "]"
|
|
3929
|
-
}) : `[${import_picocolors$4.default.green("█".repeat(Math.floor(barWidth * .15)))}${import_picocolors$4.default.gray("░".repeat(barWidth - Math.floor(barWidth * .15)))}]`;
|
|
3930
|
-
const limitStatus = config.tokenLimit != null && config.tokenLimit > 0 ? projectedPercent > 100 ? import_picocolors$4.default.red(`${drawEmoji("❌")} WILL EXCEED LIMIT`) : projectedPercent > 80 ? import_picocolors$4.default.yellow(`${drawEmoji("⚠️")} APPROACHING LIMIT`) : import_picocolors$4.default.green(`${drawEmoji("✓")} WITHIN LIMIT`) : import_picocolors$4.default.green(`${drawEmoji("✓")} ON TRACK`);
|
|
3931
|
-
const projLabel = `${drawEmoji("📈")}${import_picocolors$4.default.bold(" PROJECTION")}`;
|
|
3932
|
-
const projLabelWidth = stringWidth(projLabel);
|
|
3933
|
-
const projBarStr = `${projLabel}${"".padEnd(Math.max(0, labelWidth - projLabelWidth))} ${projectionBar} ${projectionRightText}`;
|
|
3934
|
-
const projBarPadded = projBarStr + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(projBarStr)));
|
|
3935
|
-
terminal.write(`${marginStr}│ ${projBarPadded}│\n`);
|
|
3936
|
-
const projCol1 = `${import_picocolors$4.default.gray("Status:")} ${limitStatus}`;
|
|
3937
|
-
let projCol2 = `${import_picocolors$4.default.gray("Tokens:")} ${formatTokenDisplay(projection.totalTokens, false)}`;
|
|
3938
|
-
const projCol3 = `${import_picocolors$4.default.gray("Cost:")} ${formatCurrency(projection.totalCost)}`;
|
|
3939
|
-
const projTotalWidth = stringWidth(projCol1) + stringWidth(projCol2) + stringWidth(projCol3) + detailsSpacing * 2;
|
|
3940
|
-
let projUseTwoLineLayout = false;
|
|
3941
|
-
if (projTotalWidth > detailsAvailableWidth) {
|
|
3942
|
-
projUseTwoLineLayout = true;
|
|
3943
|
-
projCol2 = `${import_picocolors$4.default.gray("Tokens:")} ${formatTokenDisplay(projection.totalTokens, true)}`;
|
|
3944
|
-
}
|
|
3945
|
-
if (projUseTwoLineLayout) {
|
|
3946
|
-
const projDetailsLine1 = `${" ".repeat(detailsIndent)}${projCol1}`;
|
|
3947
|
-
const projDetailsLine1Padded = projDetailsLine1 + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(projDetailsLine1)));
|
|
3948
|
-
terminal.write(`${marginStr}│ ${projDetailsLine1Padded}│\n`);
|
|
3949
|
-
const projDetailsLine2 = `${" ".repeat(detailsIndent)}${projCol2}${" ".repeat(detailsSpacing)}${projCol3}`;
|
|
3950
|
-
const projDetailsLine2Padded = projDetailsLine2 + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(projDetailsLine2)));
|
|
3951
|
-
terminal.write(`${marginStr}│ ${projDetailsLine2Padded}│\n`);
|
|
3952
|
-
} else {
|
|
3953
|
-
const projDetails = `${" ".repeat(detailsIndent)}${projCol1}${" ".repeat(detailsSpacing)}${projCol2}${" ".repeat(detailsSpacing)}${projCol3}`;
|
|
3954
|
-
const projDetailsPadded = projDetails + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(projDetails)));
|
|
3955
|
-
terminal.write(`${marginStr}│ ${projDetailsPadded}│\n`);
|
|
3956
|
-
}
|
|
3957
|
-
terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
|
|
3958
|
-
}
|
|
3959
|
-
if (block.models.length > 0) {
|
|
3960
|
-
terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
|
|
3961
|
-
const modelsLine = `${drawEmoji("⚙️")} Models: ${formatModelsDisplay(block.models)}`;
|
|
3962
|
-
const modelsLinePadded = modelsLine + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(modelsLine)));
|
|
3963
|
-
terminal.write(`${marginStr}│ ${modelsLinePadded}│\n`);
|
|
3964
|
-
}
|
|
3965
|
-
terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
|
|
3966
|
-
const refreshText = `${drawEmoji("↻")} Refreshing every ${config.refreshInterval / 1e3}s • Press Ctrl+C to stop`;
|
|
3967
|
-
terminal.write(`${marginStr}│${import_picocolors$4.default.gray(centerText(refreshText, boxWidth - 2))}│\n`);
|
|
3968
|
-
terminal.write(`${marginStr}└${"─".repeat(boxWidth - 2)}┘\n`);
|
|
3969
|
-
}
|
|
3970
|
-
function renderCompactLiveDisplay(terminal, block, config, totalTokens, elapsed, remaining) {
|
|
3971
|
-
const width = terminal.width;
|
|
3972
|
-
terminal.write(`${import_picocolors$4.default.bold(centerText("LIVE MONITOR", width))}\n`);
|
|
3973
|
-
terminal.write(`${"─".repeat(width)}\n`);
|
|
3974
|
-
const sessionPercent = elapsed / (elapsed + remaining) * 100;
|
|
3975
|
-
terminal.write(`Session: ${sessionPercent.toFixed(1)}% (${Math.floor(elapsed / 60)}h ${Math.floor(elapsed % 60)}m)\n`);
|
|
3976
|
-
if (config.tokenLimit != null && config.tokenLimit > 0) {
|
|
3977
|
-
const tokenPercent = totalTokens / config.tokenLimit * 100;
|
|
3978
|
-
const status = tokenPercent > 100 ? import_picocolors$4.default.red("OVER") : tokenPercent > 80 ? import_picocolors$4.default.yellow("WARN") : import_picocolors$4.default.green("OK");
|
|
3979
|
-
terminal.write(`Tokens: ${formatNumber(totalTokens)}/${formatNumber(config.tokenLimit)} ${status}\n`);
|
|
3980
|
-
} else terminal.write(`Tokens: ${formatNumber(totalTokens)}\n`);
|
|
3981
|
-
terminal.write(`Cost: ${formatCurrency(block.costUSD)}\n`);
|
|
3982
|
-
const burnRate = calculateBurnRate(block);
|
|
3983
|
-
if (burnRate != null) terminal.write(`Rate: ${formatNumber(burnRate.tokensPerMinute)}/min\n`);
|
|
3984
|
-
terminal.write(`${"─".repeat(width)}\n`);
|
|
3985
|
-
terminal.write(import_picocolors$4.default.gray(`Refresh: ${config.refreshInterval / 1e3}s | Ctrl+C: stop\n`));
|
|
3986
|
-
}
|
|
3987
|
-
var import_picocolors$3 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
|
|
3988
|
-
async function startLiveMonitoring(config) {
|
|
3989
|
-
try {
|
|
3990
|
-
var _usingCtx$1 = _usingCtx();
|
|
3991
|
-
const terminal = new TerminalManager();
|
|
3992
|
-
const abortController = new AbortController();
|
|
3993
|
-
let lastRenderTime = 0;
|
|
3994
|
-
const monitorConfig = {
|
|
3995
|
-
claudePaths: config.claudePaths,
|
|
3996
|
-
sessionDurationHours: config.sessionDurationHours,
|
|
3997
|
-
mode: config.mode,
|
|
3998
|
-
order: config.order
|
|
3999
|
-
};
|
|
4000
|
-
const monitorState = _usingCtx$1.u(createLiveMonitorState(monitorConfig));
|
|
4001
|
-
const cleanup = () => {
|
|
4002
|
-
abortController.abort();
|
|
4003
|
-
terminal.cleanup();
|
|
4004
|
-
terminal.clearScreen();
|
|
4005
|
-
logger.info("Live monitoring stopped.");
|
|
4006
|
-
if (process$1.exitCode == null) process$1.exit(0);
|
|
4007
|
-
};
|
|
4008
|
-
process$1.on("SIGINT", cleanup);
|
|
4009
|
-
process$1.on("SIGTERM", cleanup);
|
|
4010
|
-
terminal.enterAlternateScreen();
|
|
4011
|
-
terminal.enableSyncMode();
|
|
4012
|
-
terminal.clearScreen();
|
|
4013
|
-
terminal.hideCursor();
|
|
4014
|
-
const monitoringResult = await try_({
|
|
4015
|
-
try: async () => {
|
|
4016
|
-
while (!abortController.signal.aborted) {
|
|
4017
|
-
const timeSinceLastRender = Date.now() - lastRenderTime;
|
|
4018
|
-
if (timeSinceLastRender < MIN_RENDER_INTERVAL_MS) {
|
|
4019
|
-
await delayWithAbort(MIN_RENDER_INTERVAL_MS - timeSinceLastRender, abortController.signal);
|
|
4020
|
-
continue;
|
|
4021
|
-
}
|
|
4022
|
-
const activeBlock = await getActiveBlock(monitorState, monitorConfig);
|
|
4023
|
-
clearLiveMonitorCache(monitorState);
|
|
4024
|
-
if (activeBlock == null) {
|
|
4025
|
-
await renderWaitingState(terminal, config, abortController.signal);
|
|
4026
|
-
continue;
|
|
4027
|
-
}
|
|
4028
|
-
renderActiveBlock(terminal, activeBlock, config);
|
|
4029
|
-
lastRenderTime = Date.now();
|
|
4030
|
-
let resizeEventHandler;
|
|
4031
|
-
try {
|
|
4032
|
-
await Promise.race([delayWithAbort(config.refreshInterval, abortController.signal), new Promise((resolve$1) => {
|
|
4033
|
-
resizeEventHandler = resolve$1;
|
|
4034
|
-
process$1.stdout.once("resize", resolve$1);
|
|
4035
|
-
})]);
|
|
4036
|
-
} finally {
|
|
4037
|
-
if (resizeEventHandler != null) process$1.stdout.removeListener("resize", resizeEventHandler);
|
|
4038
|
-
}
|
|
4039
|
-
}
|
|
4040
|
-
},
|
|
4041
|
-
catch: (error) => error
|
|
4042
|
-
})();
|
|
4043
|
-
if (isFailure(monitoringResult)) {
|
|
4044
|
-
const error = monitoringResult.error;
|
|
4045
|
-
if ((error instanceof DOMException || error instanceof Error) && error.name === "AbortError") return;
|
|
4046
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4047
|
-
terminal.startBuffering();
|
|
4048
|
-
terminal.clearScreen();
|
|
4049
|
-
terminal.write(import_picocolors$3.default.red(`Error: ${errorMessage}\n`));
|
|
4050
|
-
terminal.flush();
|
|
4051
|
-
logger.error(`Live monitoring error: ${errorMessage}`);
|
|
4052
|
-
await delayWithAbort(config.refreshInterval, abortController.signal).catch(() => {});
|
|
4053
|
-
}
|
|
4054
|
-
} catch (_$1) {
|
|
4055
|
-
_usingCtx$1.e = _$1;
|
|
4056
|
-
} finally {
|
|
4057
|
-
_usingCtx$1.d();
|
|
4058
|
-
}
|
|
4059
|
-
}
|
|
4060
3241
|
var import_picocolors$2 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
|
|
4061
3242
|
function formatBlockTime(block, compact = false, locale) {
|
|
4062
3243
|
const start = compact ? block.startTime.toLocaleString(locale, {
|
|
@@ -4127,16 +3308,6 @@ const blocksCommand = define({
|
|
|
4127
3308
|
short: "n",
|
|
4128
3309
|
description: `Session block duration in hours (default: ${DEFAULT_SESSION_DURATION_HOURS})`,
|
|
4129
3310
|
default: DEFAULT_SESSION_DURATION_HOURS
|
|
4130
|
-
},
|
|
4131
|
-
live: {
|
|
4132
|
-
type: "boolean",
|
|
4133
|
-
description: "Live monitoring mode with real-time updates",
|
|
4134
|
-
default: false
|
|
4135
|
-
},
|
|
4136
|
-
refreshInterval: {
|
|
4137
|
-
type: "number",
|
|
4138
|
-
description: `Refresh interval in seconds for live mode (default: ${DEFAULT_REFRESH_INTERVAL_SECONDS})`,
|
|
4139
|
-
default: DEFAULT_REFRESH_INTERVAL_SECONDS
|
|
4140
3311
|
}
|
|
4141
3312
|
},
|
|
4142
3313
|
toKebab: true,
|
|
@@ -4183,30 +3354,6 @@ const blocksCommand = define({
|
|
|
4183
3354
|
process$1.exit(0);
|
|
4184
3355
|
}
|
|
4185
3356
|
}
|
|
4186
|
-
if (ctx.values.live && !useJson) {
|
|
4187
|
-
if (!ctx.values.active) logger.info("Live mode automatically shows only active blocks.");
|
|
4188
|
-
let tokenLimitValue = ctx.values.tokenLimit;
|
|
4189
|
-
if (tokenLimitValue == null || tokenLimitValue === "") {
|
|
4190
|
-
tokenLimitValue = "max";
|
|
4191
|
-
if (maxTokensFromAll > 0) logger.info(`No token limit specified, using max from previous sessions: ${formatNumber(maxTokensFromAll)}`);
|
|
4192
|
-
}
|
|
4193
|
-
const refreshInterval = Math.max(MIN_REFRESH_INTERVAL_SECONDS, Math.min(MAX_REFRESH_INTERVAL_SECONDS, ctx.values.refreshInterval));
|
|
4194
|
-
if (refreshInterval !== ctx.values.refreshInterval) logger.warn(`Refresh interval adjusted to ${refreshInterval} seconds (valid range: ${MIN_REFRESH_INTERVAL_SECONDS}-${MAX_REFRESH_INTERVAL_SECONDS})`);
|
|
4195
|
-
const paths = getClaudePaths();
|
|
4196
|
-
if (paths.length === 0) {
|
|
4197
|
-
logger.error("No valid Claude data directory found");
|
|
4198
|
-
throw new Error("No valid Claude data directory found");
|
|
4199
|
-
}
|
|
4200
|
-
await startLiveMonitoring({
|
|
4201
|
-
claudePaths: paths,
|
|
4202
|
-
tokenLimit: parseTokenLimit(tokenLimitValue, maxTokensFromAll),
|
|
4203
|
-
refreshInterval: refreshInterval * 1e3,
|
|
4204
|
-
sessionDurationHours: ctx.values.sessionLength,
|
|
4205
|
-
mode: ctx.values.mode,
|
|
4206
|
-
order: ctx.values.order
|
|
4207
|
-
});
|
|
4208
|
-
return;
|
|
4209
|
-
}
|
|
4210
3357
|
if (useJson) {
|
|
4211
3358
|
const jsonOutput = { blocks: blocks.map((block) => {
|
|
4212
3359
|
const burnRate = block.isActive ? calculateBurnRate(block) : null;
|