ccusage 15.3.1 → 15.4.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.
@@ -1,4 +1,4 @@
1
- import { DailyUsage, MonthlyUsage, SessionUsage } from "./data-loader-a9CiVyT5.js";
1
+ import { DailyUsage, MonthlyUsage, SessionUsage } from "./data-loader-7c4yXbqG.js";
2
2
  import "./pricing-fetcher-B3SvKOod.js";
3
3
 
4
4
  //#region src/_token-utils.d.ts
@@ -446,6 +446,19 @@ declare function calculateCostForEntry(data: UsageData, mode: CostMode, fetcher:
446
446
  * @returns Usage limit expiration date
447
447
  */
448
448
  declare function getUsageLimitResetTime(data: UsageData): Date | null;
449
+ /**
450
+ * Result of glob operation with base directory information
451
+ */
452
+ type GlobResult = {
453
+ file: string;
454
+ baseDir: string;
455
+ };
456
+ /**
457
+ * Glob files from multiple Claude paths in parallel
458
+ * @param claudePaths - Array of Claude base paths
459
+ * @returns Array of file paths with their base directories
460
+ */
461
+ declare function globUsageFiles(claudePaths: string[]): Promise<GlobResult[]>;
449
462
  /**
450
463
  * Date range filter for limiting usage data by date
451
464
  */
@@ -492,4 +505,4 @@ declare function loadMonthlyUsageData(options?: LoadOptions): Promise<MonthlyUsa
492
505
  */
493
506
  declare function loadSessionBlockData(options?: LoadOptions): Promise<SessionBlock[]>;
494
507
  //#endregion
495
- export { DailyUsage, DateFilter, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema };
508
+ export { DailyUsage, DateFilter, GlobResult, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, globUsageFiles, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema };
@@ -1,7 +1,7 @@
1
- import { CLAUDE_CONFIG_DIR_ENV, CLAUDE_PROJECTS_DIR_NAME, DEFAULT_CLAUDE_CODE_PATH, DEFAULT_CLAUDE_CONFIG_PATH, DEFAULT_RECENT_DAYS, PricingFetcher, USAGE_DATA_GLOB_PATTERN, USER_HOME_DIR, __commonJSMin, __require, __toESM, isFailure, isPromise, require_usingCtx } from "./pricing-fetcher-DpoTR8Md.js";
1
+ import { CLAUDE_CONFIG_DIR_ENV, CLAUDE_PROJECTS_DIR_NAME, DEFAULT_CLAUDE_CODE_PATH, DEFAULT_CLAUDE_CONFIG_PATH, DEFAULT_RECENT_DAYS, PricingFetcher, USAGE_DATA_GLOB_PATTERN, USER_HOME_DIR, __commonJSMin, __require, __toESM, isFailure, isPromise, require_usingCtx } from "./pricing-fetcher-KIIpXo8L.js";
2
2
  import { getTotalTokens } from "./_token-utils-WjkbrjKv.js";
3
3
  import { activityDateSchema, arrayType, booleanType, createDailyDate, createMonthlyDate, createProjectPath, createSessionId, dailyDateSchema, isoTimestampSchema, messageIdSchema, modelNameSchema, monthlyDateSchema, numberType, objectType, projectPathSchema, requestIdSchema, sessionIdSchema, stringType, versionSchema } from "./_types-BHFM59hI.js";
4
- import { logger } from "./logger-D7tlrIfv.js";
4
+ import { logger } from "./logger-mXUMXvyg.js";
5
5
  import a, { readFile } from "node:fs/promises";
6
6
  import path, { posix } from "node:path";
7
7
  import process$1 from "node:process";
@@ -251,7 +251,7 @@ const unwrap = (...args) => {
251
251
  const apply = (r) => {
252
252
  if (isFailure(r)) {
253
253
  if (hasDefault$1) return defaultValue$1;
254
- throw new Error(String(r.error));
254
+ throw r.error;
255
255
  }
256
256
  return r.value;
257
257
  };
@@ -263,7 +263,7 @@ const unwrap = (...args) => {
263
263
  const apply = (r) => {
264
264
  if (isFailure(r)) {
265
265
  if (hasDefault) return defaultValue;
266
- throw new Error(String(r.error));
266
+ throw r.error;
267
267
  }
268
268
  return r.value;
269
269
  };
@@ -3518,16 +3518,26 @@ function extractUniqueModels(entries, getModel) {
3518
3518
  return uniq(entries.map(getModel).filter((m$1) => m$1 != null && m$1 !== "<synthetic>"));
3519
3519
  }
3520
3520
  /**
3521
+ * Shared method for formatting dates with proper timezone handling
3522
+ * @param dateStr - Input date string
3523
+ * @param twoLine - Whether to format as two lines (true) or single line (false)
3524
+ * @returns Formatted date string
3525
+ */
3526
+ function formatDateInternal(dateStr, twoLine) {
3527
+ const date = new Date(dateStr);
3528
+ const hasTimezone = /Z|[+-]\d{2}:\d{2}/.test(dateStr);
3529
+ const year = hasTimezone ? date.getUTCFullYear() : date.getFullYear();
3530
+ const month = String(hasTimezone ? date.getUTCMonth() + 1 : date.getMonth() + 1).padStart(2, "0");
3531
+ const day = String(hasTimezone ? date.getUTCDate() : date.getDate()).padStart(2, "0");
3532
+ return twoLine ? `${year}\n${month}-${day}` : `${year}-${month}-${day}`;
3533
+ }
3534
+ /**
3521
3535
  * Formats a date string to YYYY-MM-DD format
3522
3536
  * @param dateStr - Input date string
3523
3537
  * @returns Formatted date string in YYYY-MM-DD format
3524
3538
  */
3525
3539
  function formatDate(dateStr) {
3526
- const date = new Date(dateStr);
3527
- const year = date.getFullYear();
3528
- const month = String(date.getMonth() + 1).padStart(2, "0");
3529
- const day = String(date.getDate()).padStart(2, "0");
3530
- return `${year}-${month}-${day}`;
3540
+ return formatDateInternal(dateStr, false);
3531
3541
  }
3532
3542
  /**
3533
3543
  * Formats a date string to compact format with year on first line and month-day on second
@@ -3535,11 +3545,7 @@ function formatDate(dateStr) {
3535
3545
  * @returns Formatted date string with newline separator (YYYY\nMM-DD)
3536
3546
  */
3537
3547
  function formatDateCompact(dateStr) {
3538
- const date = new Date(dateStr);
3539
- const year = date.getFullYear();
3540
- const month = String(date.getMonth() + 1).padStart(2, "0");
3541
- const day = String(date.getDate()).padStart(2, "0");
3542
- return `${year}\n${month}-${day}`;
3548
+ return formatDateInternal(dateStr, true);
3543
3549
  }
3544
3550
  /**
3545
3551
  * Generic function to sort items by date based on sort order
@@ -3647,6 +3653,25 @@ function getUsageLimitResetTime(data) {
3647
3653
  return resetTime;
3648
3654
  }
3649
3655
  /**
3656
+ * Glob files from multiple Claude paths in parallel
3657
+ * @param claudePaths - Array of Claude base paths
3658
+ * @returns Array of file paths with their base directories
3659
+ */
3660
+ async function globUsageFiles(claudePaths) {
3661
+ const filePromises = claudePaths.map(async (claudePath) => {
3662
+ const claudeDir = path.join(claudePath, CLAUDE_PROJECTS_DIR_NAME);
3663
+ const files = await glob([USAGE_DATA_GLOB_PATTERN], {
3664
+ cwd: claudeDir,
3665
+ absolute: true
3666
+ }).catch(() => []);
3667
+ return files.map((file) => ({
3668
+ file,
3669
+ baseDir: claudeDir
3670
+ }));
3671
+ });
3672
+ return (await Promise.all(filePromises)).flat();
3673
+ }
3674
+ /**
3650
3675
  * Loads and aggregates Claude usage data by day
3651
3676
  * Processes all JSONL files in the Claude projects directory and groups usage by date
3652
3677
  * @param options - Optional configuration for loading and filtering data
@@ -3656,17 +3681,10 @@ async function loadDailyUsageData(options) {
3656
3681
  try {
3657
3682
  var _usingCtx = (0, import_usingCtx.default)();
3658
3683
  const claudePaths = toArray(options?.claudePath ?? getClaudePaths());
3659
- const allFiles = [];
3660
- for (const claudePath of claudePaths) {
3661
- const claudeDir = path.join(claudePath, CLAUDE_PROJECTS_DIR_NAME);
3662
- const files = await glob([USAGE_DATA_GLOB_PATTERN], {
3663
- cwd: claudeDir,
3664
- absolute: true
3665
- });
3666
- allFiles.push(...files);
3667
- }
3668
- if (allFiles.length === 0) return [];
3669
- const sortedFiles = await sortFilesByTimestamp(allFiles);
3684
+ const allFiles = await globUsageFiles(claudePaths);
3685
+ const fileList = allFiles.map((f$1) => f$1.file);
3686
+ if (fileList.length === 0) return [];
3687
+ const sortedFiles = await sortFilesByTimestamp(fileList);
3670
3688
  const mode = options?.mode ?? "auto";
3671
3689
  const fetcher = _usingCtx.u(mode === "display" ? null : new PricingFetcher(options?.offline));
3672
3690
  const processedHashes = /* @__PURE__ */ new Set();
@@ -3724,18 +3742,7 @@ async function loadSessionData(options) {
3724
3742
  try {
3725
3743
  var _usingCtx3 = (0, import_usingCtx.default)();
3726
3744
  const claudePaths = toArray(options?.claudePath ?? getClaudePaths());
3727
- const filesWithBase = [];
3728
- for (const claudePath of claudePaths) {
3729
- const claudeDir = path.join(claudePath, CLAUDE_PROJECTS_DIR_NAME);
3730
- const files = await glob([USAGE_DATA_GLOB_PATTERN], {
3731
- cwd: claudeDir,
3732
- absolute: true
3733
- });
3734
- for (const file of files) filesWithBase.push({
3735
- file,
3736
- baseDir: claudeDir
3737
- });
3738
- }
3745
+ const filesWithBase = await globUsageFiles(claudePaths);
3739
3746
  if (filesWithBase.length === 0) return [];
3740
3747
  const fileToBaseMap = new Map(filesWithBase.map((f$1) => [f$1.file, f$1.baseDir]));
3741
3748
  const sortedFilesWithBase = await sortFilesByTimestamp(filesWithBase.map((f$1) => f$1.file)).then((sortedFiles) => sortedFiles.map((file) => ({
@@ -3915,4 +3922,4 @@ async function loadSessionBlockData(options) {
3915
3922
  _usingCtx4.d();
3916
3923
  }
3917
3924
  }
3918
- export { DEFAULT_SESSION_DURATION_HOURS, calculateBurnRate, calculateCostForEntry, createUniqueHash, dailyUsageSchema, filterRecentBlocks, formatDate, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, glob, identifySessionBlocks, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, projectBlockUsage, sessionUsageSchema, sortFilesByTimestamp, uniq, unwrap, usageDataSchema };
3925
+ export { DEFAULT_SESSION_DURATION_HOURS, calculateBurnRate, calculateCostForEntry, createUniqueHash, dailyUsageSchema, filterRecentBlocks, formatDate, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, glob, globUsageFiles, identifySessionBlocks, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, projectBlockUsage, sessionUsageSchema, sortFilesByTimestamp, uniq, unwrap, usageDataSchema };
@@ -1,3 +1,3 @@
1
- import { DailyUsage, DateFilter, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema } from "./data-loader-a9CiVyT5.js";
1
+ import { DailyUsage, DateFilter, GlobResult, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, globUsageFiles, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema } from "./data-loader-7c4yXbqG.js";
2
2
  import "./pricing-fetcher-B3SvKOod.js";
3
- export { DailyUsage, DateFilter, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema };
3
+ export { DailyUsage, DateFilter, GlobResult, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, globUsageFiles, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema };
@@ -1,6 +1,6 @@
1
- import "./pricing-fetcher-DpoTR8Md.js";
1
+ import "./pricing-fetcher-KIIpXo8L.js";
2
2
  import "./_token-utils-WjkbrjKv.js";
3
3
  import "./_types-BHFM59hI.js";
4
- import { calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema } from "./data-loader-DqK3z1AK.js";
5
- import "./logger-D7tlrIfv.js";
6
- export { calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema };
4
+ import { calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, globUsageFiles, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema } from "./data-loader-BNrxyvc9.js";
5
+ import "./logger-mXUMXvyg.js";
6
+ export { calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, globUsageFiles, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema };
@@ -1,6 +1,6 @@
1
- import { CLAUDE_PROJECTS_DIR_NAME, DEBUG_MATCH_THRESHOLD_PERCENT, PricingFetcher, USAGE_DATA_GLOB_PATTERN, __toESM, isFailure, require_usingCtx, try_ } from "./pricing-fetcher-DpoTR8Md.js";
2
- import { getClaudePaths, glob, unwrap, usageDataSchema } from "./data-loader-DqK3z1AK.js";
3
- import { logger } from "./logger-D7tlrIfv.js";
1
+ import { CLAUDE_PROJECTS_DIR_NAME, DEBUG_MATCH_THRESHOLD_PERCENT, PricingFetcher, USAGE_DATA_GLOB_PATTERN, __toESM, isFailure, require_usingCtx, try_ } from "./pricing-fetcher-KIIpXo8L.js";
2
+ import { getClaudePaths, glob, unwrap, usageDataSchema } from "./data-loader-BNrxyvc9.js";
3
+ import { logger } from "./logger-mXUMXvyg.js";
4
4
  import { readFile } from "node:fs/promises";
5
5
  import path from "node:path";
6
6
  var import_usingCtx = __toESM(require_usingCtx(), 1);
package/dist/debug.js CHANGED
@@ -1,7 +1,7 @@
1
- import "./pricing-fetcher-DpoTR8Md.js";
1
+ import "./pricing-fetcher-KIIpXo8L.js";
2
2
  import "./_token-utils-WjkbrjKv.js";
3
3
  import "./_types-BHFM59hI.js";
4
- import "./data-loader-DqK3z1AK.js";
5
- import "./logger-D7tlrIfv.js";
6
- import { detectMismatches, printMismatchReport } from "./debug-Cby_QhQQ.js";
4
+ import "./data-loader-BNrxyvc9.js";
5
+ import "./logger-mXUMXvyg.js";
6
+ import { detectMismatches, printMismatchReport } from "./debug-Brn3ODNf.js";
7
7
  export { detectMismatches, printMismatchReport };
package/dist/index.js CHANGED
@@ -1,14 +1,13 @@
1
1
  #!/usr/bin/env node
2
- import { BLOCKS_COMPACT_WIDTH_THRESHOLD, BLOCKS_DEFAULT_TERMINAL_WIDTH, BLOCKS_WARNING_THRESHOLD, BURN_RATE_THRESHOLDS, CLAUDE_PROJECTS_DIR_NAME, DEFAULT_RECENT_DAYS, DEFAULT_REFRESH_INTERVAL_SECONDS, MAX_REFRESH_INTERVAL_SECONDS, MCP_DEFAULT_PORT, MIN_REFRESH_INTERVAL_SECONDS, MIN_RENDER_INTERVAL_MS, PricingFetcher, USAGE_DATA_GLOB_PATTERN, __commonJSMin, __require, __toESM, isFailure, require_usingCtx, try_ } from "./pricing-fetcher-DpoTR8Md.js";
2
+ import { BLOCKS_COMPACT_WIDTH_THRESHOLD, BLOCKS_DEFAULT_TERMINAL_WIDTH, BLOCKS_WARNING_THRESHOLD, BURN_RATE_THRESHOLDS, DEFAULT_RECENT_DAYS, DEFAULT_REFRESH_INTERVAL_SECONDS, MAX_REFRESH_INTERVAL_SECONDS, MCP_DEFAULT_PORT, MIN_REFRESH_INTERVAL_SECONDS, MIN_RENDER_INTERVAL_MS, PricingFetcher, __commonJSMin, __require, __toESM, isFailure, require_usingCtx, try_ } from "./pricing-fetcher-KIIpXo8L.js";
3
3
  import { getTotalTokens } from "./_token-utils-WjkbrjKv.js";
4
4
  import { CostModes, SortOrders, filterDateSchema } from "./_types-BHFM59hI.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, glob, identifySessionBlocks, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, projectBlockUsage, sortFilesByTimestamp, uniq, usageDataSchema } from "./data-loader-DqK3z1AK.js";
7
- import { description, log, logger, name, version } from "./logger-D7tlrIfv.js";
8
- import { detectMismatches, printMismatchReport } from "./debug-Cby_QhQQ.js";
9
- import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-CFT0dcvs.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-BNrxyvc9.js";
7
+ import { description, log, logger, name, version } from "./logger-mXUMXvyg.js";
8
+ import { detectMismatches, printMismatchReport } from "./debug-Brn3ODNf.js";
9
+ import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-CQw7snVU.js";
10
10
  import { readFile } from "node:fs/promises";
11
- import path from "node:path";
12
11
  import process$1 from "node:process";
13
12
  import { createServer } from "node:http";
14
13
  import { Http2ServerRequest } from "node:http2";
@@ -3205,14 +3204,11 @@ var LiveMonitor = class {
3205
3204
  * Only reads new or modified files since last check
3206
3205
  */
3207
3206
  async getActiveBlock() {
3208
- const claudeDir = path.join(this.config.claudePath, CLAUDE_PROJECTS_DIR_NAME);
3209
- const files = await glob([USAGE_DATA_GLOB_PATTERN], {
3210
- cwd: claudeDir,
3211
- absolute: true
3212
- });
3213
- if (files.length === 0) return null;
3207
+ const results = await globUsageFiles(this.config.claudePaths);
3208
+ const allFiles = results.map((r) => r.file);
3209
+ if (allFiles.length === 0) return null;
3214
3210
  const filesToRead = [];
3215
- for (const file of files) {
3211
+ for (const file of allFiles) {
3216
3212
  const timestamp = await getEarliestTimestamp(file);
3217
3213
  const lastTimestamp = this.lastFileTimestamps.get(file);
3218
3214
  if (timestamp != null && (lastTimestamp == null || timestamp.getTime() > lastTimestamp)) {
@@ -3745,7 +3741,7 @@ const DETAIL_COLUMN_WIDTHS = {
3745
3741
  function renderLiveDisplay(terminal, block, config) {
3746
3742
  const width = terminal.width;
3747
3743
  const now = /* @__PURE__ */ new Date();
3748
- const totalTokens = block.tokenCounts.inputTokens + block.tokenCounts.outputTokens;
3744
+ const totalTokens = getTotalTokens(block.tokenCounts);
3749
3745
  const elapsed = (now.getTime() - block.startTime.getTime()) / (1e3 * 60);
3750
3746
  const remaining = (block.endTime.getTime() - now.getTime()) / (1e3 * 60);
3751
3747
  if (width < 60) {
@@ -3952,7 +3948,7 @@ async function startLiveMonitoring(config) {
3952
3948
  terminal.clearScreen();
3953
3949
  terminal.hideCursor();
3954
3950
  const monitor = _usingCtx.u(new LiveMonitor({
3955
- claudePath: config.claudePath,
3951
+ claudePaths: config.claudePaths,
3956
3952
  sessionDurationHours: config.sessionDurationHours,
3957
3953
  mode: config.mode,
3958
3954
  order: config.order
@@ -4052,8 +4048,7 @@ function formatModels(models) {
4052
4048
  * @returns Parsed token limit or undefined if invalid
4053
4049
  */
4054
4050
  function parseTokenLimit(value, maxFromAll) {
4055
- if (value == null || value === "") return void 0;
4056
- if (value === "max") return maxFromAll > 0 ? maxFromAll : void 0;
4051
+ if (value == null || value === "" || value === "max") return maxFromAll > 0 ? maxFromAll : void 0;
4057
4052
  const limit = Number.parseInt(value, 10);
4058
4053
  return Number.isNaN(limit) ? void 0 : limit;
4059
4054
  }
@@ -4117,7 +4112,7 @@ const blocksCommand = define({
4117
4112
  process$1.exit(0);
4118
4113
  }
4119
4114
  let maxTokensFromAll = 0;
4120
- if (ctx.values.tokenLimit === "max") {
4115
+ if (ctx.values.tokenLimit === "max" || ctx.values.tokenLimit == null || ctx.values.tokenLimit === "") {
4121
4116
  for (const block of blocks) if (!(block.isGap ?? false) && !block.isActive) {
4122
4117
  const blockTokens = getTotalTokens(block.tokenCounts);
4123
4118
  if (blockTokens > maxTokensFromAll) maxTokensFromAll = blockTokens;
@@ -4151,7 +4146,7 @@ const blocksCommand = define({
4151
4146
  throw new Error("No valid Claude data directory found");
4152
4147
  }
4153
4148
  await startLiveMonitoring({
4154
- claudePath: paths[0],
4149
+ claudePaths: paths,
4155
4150
  tokenLimit: parseTokenLimit(tokenLimitValue, maxTokensFromAll),
4156
4151
  refreshInterval: refreshInterval * 1e3,
4157
4152
  sessionDurationHours: ctx.values.sessionLength,
@@ -4173,7 +4168,7 @@ const blocksCommand = define({
4173
4168
  isGap: block.isGap ?? false,
4174
4169
  entries: block.entries.length,
4175
4170
  tokenCounts: block.tokenCounts,
4176
- totalTokens: block.tokenCounts.inputTokens + block.tokenCounts.outputTokens,
4171
+ totalTokens: getTotalTokens(block.tokenCounts),
4177
4172
  costUSD: block.costUSD,
4178
4173
  models: block.models,
4179
4174
  burnRate,
@@ -4474,6 +4469,7 @@ var Request = class extends GlobalRequest {
4474
4469
  super(input, options);
4475
4470
  }
4476
4471
  };
4472
+ var wrapBodyStream = Symbol("wrapBodyStream");
4477
4473
  var newRequestFromIncoming = (method, url, incoming, abortController) => {
4478
4474
  const headerRecord = [];
4479
4475
  const rawHeaders = incoming.rawHeaders;
@@ -4498,7 +4494,19 @@ var newRequestFromIncoming = (method, url, incoming, abortController) => {
4498
4494
  controller.enqueue(incoming.rawBody);
4499
4495
  controller.close();
4500
4496
  } });
4501
- else init$1.body = Readable.toWeb(incoming);
4497
+ else if (incoming[wrapBodyStream]) {
4498
+ let reader;
4499
+ init$1.body = new ReadableStream({ async pull(controller) {
4500
+ try {
4501
+ reader ||= Readable.toWeb(incoming).getReader();
4502
+ const { done, value } = await reader.read();
4503
+ if (done) controller.close();
4504
+ else controller.enqueue(value);
4505
+ } catch (error) {
4506
+ controller.error(error);
4507
+ }
4508
+ } });
4509
+ } else init$1.body = Readable.toWeb(incoming);
4502
4510
  return new Request(url, init$1);
4503
4511
  };
4504
4512
  var getRequestCache = Symbol("getRequestCache");
@@ -4709,6 +4717,7 @@ global.fetch = (info$1, init$1) => {
4709
4717
  };
4710
4718
  return webFetch(info$1, init$1);
4711
4719
  };
4720
+ var outgoingEnded = Symbol("outgoingEnded");
4712
4721
  var regBuffer = /^no$/i;
4713
4722
  var regContentType = /^(application\/json\b|text\/(?!event-stream\b))/i;
4714
4723
  var handleRequestError = () => new Response(null, { status: 400 });
@@ -4737,8 +4746,9 @@ var responseViaCache = async (res, outgoing) => {
4737
4746
  else if (body instanceof Blob) outgoing.end(new Uint8Array(await body.arrayBuffer()));
4738
4747
  else {
4739
4748
  flushHeaders(outgoing);
4740
- return writeFromReadableStream(body, outgoing)?.catch((e) => handleResponseError(e, outgoing));
4749
+ await writeFromReadableStream(body, outgoing)?.catch((e) => handleResponseError(e, outgoing));
4741
4750
  }
4751
+ outgoing[outgoingEnded]?.();
4742
4752
  };
4743
4753
  var responseViaResponseObject = async (res, outgoing, options = {}) => {
4744
4754
  if (res instanceof Promise) if (options.errorHandler) try {
@@ -4767,8 +4777,10 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
4767
4777
  outgoing.writeHead(res.status, resHeaderRecord);
4768
4778
  outgoing.end();
4769
4779
  }
4780
+ outgoing[outgoingEnded]?.();
4770
4781
  };
4771
4782
  var getRequestListener = (fetchCallback, options = {}) => {
4783
+ const autoCleanupIncoming = options.autoCleanupIncoming ?? true;
4772
4784
  if (options.overrideGlobalObjects !== false && global.Request !== Request) {
4773
4785
  Object.defineProperty(global, "Request", { value: Request });
4774
4786
  Object.defineProperty(global, "Response", { value: Response2 });
@@ -4777,11 +4789,32 @@ var getRequestListener = (fetchCallback, options = {}) => {
4777
4789
  let res, req;
4778
4790
  try {
4779
4791
  req = newRequest(incoming, options.hostname);
4792
+ let incomingEnded = !autoCleanupIncoming || incoming.method === "GET" || incoming.method === "HEAD";
4793
+ if (!incomingEnded) {
4794
+ incoming[wrapBodyStream] = true;
4795
+ incoming.on("end", () => {
4796
+ incomingEnded = true;
4797
+ });
4798
+ if (incoming instanceof Http2ServerRequest) outgoing[outgoingEnded] = () => {
4799
+ if (!incomingEnded) setTimeout(() => {
4800
+ if (!incomingEnded) setTimeout(() => {
4801
+ incoming.destroy();
4802
+ outgoing.destroy();
4803
+ });
4804
+ });
4805
+ };
4806
+ }
4780
4807
  outgoing.on("close", () => {
4781
4808
  const abortController = req[abortControllerKey];
4782
- if (!abortController) return;
4783
- if (incoming.errored) req[abortControllerKey].abort(incoming.errored.toString());
4784
- else if (!outgoing.writableFinished) req[abortControllerKey].abort("Client connection prematurely closed.");
4809
+ if (abortController) {
4810
+ if (incoming.errored) req[abortControllerKey].abort(incoming.errored.toString());
4811
+ else if (!outgoing.writableFinished) req[abortControllerKey].abort("Client connection prematurely closed.");
4812
+ }
4813
+ if (!incomingEnded) setTimeout(() => {
4814
+ if (!incomingEnded) setTimeout(() => {
4815
+ incoming.destroy();
4816
+ });
4817
+ });
4785
4818
  });
4786
4819
  res = fetchCallback(req, {
4787
4820
  incoming,
@@ -4807,7 +4840,8 @@ var createAdaptorServer = (options) => {
4807
4840
  const fetchCallback = options.fetch;
4808
4841
  const requestListener = getRequestListener(fetchCallback, {
4809
4842
  hostname: options.hostname,
4810
- overrideGlobalObjects: options.overrideGlobalObjects
4843
+ overrideGlobalObjects: options.overrideGlobalObjects,
4844
+ autoCleanupIncoming: options.autoCleanupIncoming
4811
4845
  });
4812
4846
  const createServer$1 = options.createServer || createServer;
4813
4847
  const server = createServer$1(options.serverOptions || {}, requestListener);
@@ -951,7 +951,7 @@ function _getDefaultLogLevel() {
951
951
  }
952
952
  const consola = createConsola$1();
953
953
  var name = "ccusage";
954
- var version = "15.3.1";
954
+ var version = "15.4.0";
955
955
  var description = "Usage analysis tool for Claude Code";
956
956
  /**
957
957
  * Application logger instance with package name tag
package/dist/logger.js CHANGED
@@ -1,2 +1,2 @@
1
- import { log, logger } from "./logger-D7tlrIfv.js";
1
+ import { log, logger } from "./logger-mXUMXvyg.js";
2
2
  export { log, logger };
@@ -1,9 +1,9 @@
1
- import { __commonJSMin, __toESM, require_usingCtx } from "./pricing-fetcher-DpoTR8Md.js";
1
+ import { __commonJSMin, __toESM, require_usingCtx } from "./pricing-fetcher-KIIpXo8L.js";
2
2
  import { getTotalTokens } from "./_token-utils-WjkbrjKv.js";
3
3
  import { ZodFirstPartyTypeKind, ZodOptional, ZodType, arrayType, booleanType, discriminatedUnionType, enumType, filterDateSchema, literalType, numberType, objectType, optionalType, recordType, stringType, unionType, unknownType } from "./_types-BHFM59hI.js";
4
4
  import { calculateTotals, createTotalsObject } from "./calculate-cost-BDqO4yWA.js";
5
- import { getClaudePaths, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData } from "./data-loader-DqK3z1AK.js";
6
- import { name, version } from "./logger-D7tlrIfv.js";
5
+ import { getClaudePaths, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData } from "./data-loader-BNrxyvc9.js";
6
+ import { name, version } from "./logger-mXUMXvyg.js";
7
7
  import process from "node:process";
8
8
  const LATEST_PROTOCOL_VERSION = "2025-06-18";
9
9
  const SUPPORTED_PROTOCOL_VERSIONS = [
@@ -606,7 +606,7 @@ const ElicitRequestSchema = RequestSchema.extend({
606
606
  const ElicitResultSchema = ResultSchema.extend({
607
607
  action: enumType([
608
608
  "accept",
609
- "reject",
609
+ "decline",
610
610
  "cancel"
611
611
  ]),
612
612
  content: optionalType(recordType(stringType(), unknownType()))
@@ -1054,7 +1054,7 @@ var HonoRequest = class {
1054
1054
  return bodyCache[key] = raw$1[key]();
1055
1055
  };
1056
1056
  json() {
1057
- return this.#cachedBody("json");
1057
+ return this.#cachedBody("text").then((text) => JSON.parse(text));
1058
1058
  }
1059
1059
  text() {
1060
1060
  return this.#cachedBody("text");
@@ -8561,10 +8561,6 @@ var McpServer = class {
8561
8561
  return registeredResourceTemplate;
8562
8562
  }
8563
8563
  }
8564
- /**
8565
- * Registers a resource with a config object and callback.
8566
- * For static resources, use a URI string. For dynamic resources, use a ResourceTemplate.
8567
- */
8568
8564
  registerResource(name$1, uriOrTemplate, config, readCallback) {
8569
8565
  if (typeof uriOrTemplate === "string") {
8570
8566
  if (this._registeredResources[uriOrTemplate]) throw new Error(`Resource ${uriOrTemplate} is already registered`);
@@ -8766,7 +8762,10 @@ var McpServer = class {
8766
8762
  if (this.isConnected()) this.server.sendPromptListChanged();
8767
8763
  }
8768
8764
  };
8769
- const EMPTY_OBJECT_JSON_SCHEMA = { type: "object" };
8765
+ const EMPTY_OBJECT_JSON_SCHEMA = {
8766
+ type: "object",
8767
+ properties: {}
8768
+ };
8770
8769
  function isZodRawShape(obj) {
8771
8770
  if (typeof obj !== "object" || obj === null) return false;
8772
8771
  const isEmptyObject = Object.keys(obj).length === 0;
package/dist/mcp.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { LoadOptions } from "./data-loader-a9CiVyT5.js";
1
+ import { LoadOptions } from "./data-loader-7c4yXbqG.js";
2
2
  import "./pricing-fetcher-B3SvKOod.js";
3
3
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
4
  import { Hono } from "hono/tiny";
package/dist/mcp.js CHANGED
@@ -1,8 +1,8 @@
1
- import "./pricing-fetcher-DpoTR8Md.js";
1
+ import "./pricing-fetcher-KIIpXo8L.js";
2
2
  import "./_token-utils-WjkbrjKv.js";
3
3
  import "./_types-BHFM59hI.js";
4
4
  import "./calculate-cost-BDqO4yWA.js";
5
- import "./data-loader-DqK3z1AK.js";
6
- import "./logger-D7tlrIfv.js";
7
- import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-CFT0dcvs.js";
5
+ import "./data-loader-BNrxyvc9.js";
6
+ import "./logger-mXUMXvyg.js";
7
+ import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-CQw7snVU.js";
8
8
  export { createMcpHttpApp, createMcpServer, startMcpServerStdio };
@@ -1,5 +1,5 @@
1
1
  import { modelPricingSchema } from "./_types-BHFM59hI.js";
2
- import { logger } from "./logger-D7tlrIfv.js";
2
+ import { logger } from "./logger-mXUMXvyg.js";
3
3
  import { createRequire } from "node:module";
4
4
  import path from "node:path";
5
5
  import F, { homedir } from "node:os";
@@ -47,6 +47,7 @@ const andThrough = (fn) => (result) => {
47
47
  };
48
48
  return isPromise(result) ? result.then(apply) : apply(result);
49
49
  };
50
+ const isSuccess = (result) => "Success" === result.type;
50
51
  const succeed = (...args) => {
51
52
  const value = args[0];
52
53
  if (void 0 === value) return { type: "Success" };
@@ -71,7 +72,6 @@ const fail = (...args) => {
71
72
  error
72
73
  };
73
74
  };
74
- const isSuccess = (result) => "Success" === result.type;
75
75
  const inspect = (fn) => (result) => {
76
76
  const apply = (r) => {
77
77
  if (isSuccess(r)) fn(r.value);
@@ -324,14 +324,6 @@ var PricingFetcher = class {
324
324
  loadOfflinePricing = try_({
325
325
  try: async () => {
326
326
  const pricing = new Map(Object.entries({
327
- "claude-instant-1": {
328
- "input_cost_per_token": 163e-8,
329
- "output_cost_per_token": 551e-8
330
- },
331
- "claude-instant-1.2": {
332
- "input_cost_per_token": 163e-9,
333
- "output_cost_per_token": 551e-9
334
- },
335
327
  "claude-2": {
336
328
  "input_cost_per_token": 8e-6,
337
329
  "output_cost_per_token": 24e-6
@@ -1,4 +1,4 @@
1
- import { PricingFetcher } from "./pricing-fetcher-DpoTR8Md.js";
1
+ import { PricingFetcher } from "./pricing-fetcher-KIIpXo8L.js";
2
2
  import "./_types-BHFM59hI.js";
3
- import "./logger-D7tlrIfv.js";
3
+ import "./logger-mXUMXvyg.js";
4
4
  export { PricingFetcher };
package/package.json CHANGED
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "ccusage",
3
- "type": "module",
4
- "version": "15.3.1",
3
+ "version": "15.4.0",
5
4
  "description": "Usage analysis tool for Claude Code",
6
- "author": "ryoppippi",
7
- "license": "MIT",
8
- "funding": "https://github.com/ryoppippi/ccusage?sponsor=1",
9
5
  "homepage": "https://github.com/ryoppippi/ccusage#readme",
6
+ "bugs": {
7
+ "url": "https://github.com/ryoppippi/ccusage/issues"
8
+ },
10
9
  "repository": {
11
10
  "type": "git",
12
11
  "url": "git+https://github.com/ryoppippi/ccusage.git"
13
12
  },
14
- "bugs": {
15
- "url": "https://github.com/ryoppippi/ccusage/issues"
16
- },
13
+ "funding": "https://github.com/ryoppippi/ccusage?sponsor=1",
14
+ "license": "MIT",
15
+ "author": "ryoppippi",
16
+ "type": "module",
17
17
  "exports": {
18
18
  ".": "./dist/index.js",
19
19
  "./calculate-cost": "./dist/calculate-cost.js",
@@ -32,6 +32,6 @@
32
32
  "dist"
33
33
  ],
34
34
  "engines": {
35
- "node": ">=20.19.3"
35
+ "node": ">=20.19.4"
36
36
  }
37
37
  }