ccusage 0.4.1 → 0.4.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/dist/index.js CHANGED
@@ -1,9 +1,13 @@
1
1
  #!/usr/bin/env node
2
- import { UsageDataSchema, __commonJS, __require, __toESM, boolean, calculateCostFromTokens, description, fetchModelPricing, getDefaultClaudePath, getModelPricing, glob, loadSessionData, loadUsageData, log, logger, name, number, object, optional, pipe, record, regex, safeParse, string, union, version } from "./data-loader-BBdPk24U.js";
3
- import { calculateTotals, createTotalsObject, getTotalTokens } from "./calculate-cost-DMC4FhU4.js";
4
- import { readFile } from "node:fs/promises";
5
- import { homedir } from "node:os";
6
- import path from "node:path";
2
+ import { __commonJS, __require, __toESM, loadSessionData, loadUsageData } from "./data-loader-B8mdiY5r.js";
3
+ import { formatCurrency, formatNumber } from "./utils-BeihwpHn.js";
4
+ import "./dist-D6rk8Ra5.js";
5
+ import { description, log, logger, name, version } from "./logger-nCODI08N.js";
6
+ import "./pricing-fetcher-bvi4lbXl.js";
7
+ import "./types-DjlBTM5P.js";
8
+ import { calculateTotals, createTotalsObject, getTotalTokens } from "./calculate-cost-BnufbprY.js";
9
+ import { detectMismatches, printMismatchReport } from "./debug-Oce2b5bO.js";
10
+ import { sharedCommandConfig } from "./shared-args-DWaGio0e.js";
7
11
  import process$1 from "node:process";
8
12
 
9
13
  //#region node_modules/gunshi/lib/utils-B_QNzw5q.js
@@ -1133,7 +1137,7 @@ async function executeCommand(cmd, ctx, name$1) {
1133
1137
 
1134
1138
  //#endregion
1135
1139
  //#region node_modules/cli-table3/src/debug.js
1136
- var require_debug = __commonJS({ "node_modules/cli-table3/src/debug.js"(exports, module) {
1140
+ var require_debug$1 = __commonJS({ "node_modules/cli-table3/src/debug.js"(exports, module) {
1137
1141
  let messages = [];
1138
1142
  let level = 0;
1139
1143
  const debug$3 = (msg, min) => {
@@ -1168,7 +1172,7 @@ var require_ansi_regex = __commonJS({ "node_modules/ansi-regex/index.js"(exports
1168
1172
  //#region node_modules/strip-ansi/index.js
1169
1173
  var require_strip_ansi = __commonJS({ "node_modules/strip-ansi/index.js"(exports, module) {
1170
1174
  const ansiRegex = require_ansi_regex();
1171
- module.exports = (string$1) => typeof string$1 === "string" ? string$1.replace(ansiRegex(), "") : string$1;
1175
+ module.exports = (string) => typeof string === "string" ? string.replace(ansiRegex(), "") : string;
1172
1176
  } });
1173
1177
 
1174
1178
  //#endregion
@@ -1197,14 +1201,14 @@ var require_string_width = __commonJS({ "node_modules/string-width/index.js"(exp
1197
1201
  const stripAnsi = require_strip_ansi();
1198
1202
  const isFullwidthCodePoint = require_is_fullwidth_code_point();
1199
1203
  const emojiRegex = require_emoji_regex();
1200
- const stringWidth$1 = (string$1) => {
1201
- if (typeof string$1 !== "string" || string$1.length === 0) return 0;
1202
- string$1 = stripAnsi(string$1);
1203
- if (string$1.length === 0) return 0;
1204
- string$1 = string$1.replace(emojiRegex(), " ");
1204
+ const stringWidth$1 = (string) => {
1205
+ if (typeof string !== "string" || string.length === 0) return 0;
1206
+ string = stripAnsi(string);
1207
+ if (string.length === 0) return 0;
1208
+ string = string.replace(emojiRegex(), " ");
1205
1209
  let width = 0;
1206
- for (let i = 0; i < string$1.length; i++) {
1207
- const code = string$1.codePointAt(i);
1210
+ for (let i = 0; i < string.length; i++) {
1211
+ const code = string.codePointAt(i);
1208
1212
  if (code <= 31 || code >= 127 && code <= 159) continue;
1209
1213
  if (code >= 768 && code <= 879) continue;
1210
1214
  if (code > 65535) i++;
@@ -1218,7 +1222,7 @@ var require_string_width = __commonJS({ "node_modules/string-width/index.js"(exp
1218
1222
 
1219
1223
  //#endregion
1220
1224
  //#region node_modules/cli-table3/src/utils.js
1221
- var require_utils = __commonJS({ "node_modules/cli-table3/src/utils.js"(exports, module) {
1225
+ var require_utils$1 = __commonJS({ "node_modules/cli-table3/src/utils.js"(exports, module) {
1222
1226
  const stringWidth = require_string_width();
1223
1227
  function codeRegex(capture) {
1224
1228
  return capture ? /\u001b\[((?:\d*;){0,5}\d*)m/g : /\u001b\[(?:\d*;){0,5}\d*m/g;
@@ -2181,8 +2185,8 @@ var require_safe = __commonJS({ "node_modules/@colors/colors/safe.js"(exports, m
2181
2185
  //#endregion
2182
2186
  //#region node_modules/cli-table3/src/cell.js
2183
2187
  var require_cell = __commonJS({ "node_modules/cli-table3/src/cell.js"(exports, module) {
2184
- const { info, debug: debug$2 } = require_debug();
2185
- const utils$1 = require_utils();
2188
+ const { info, debug: debug$2 } = require_debug$1();
2189
+ const utils$1 = require_utils$1();
2186
2190
  var Cell$1 = class Cell$1 {
2187
2191
  /**
2188
2192
  * A representation of a cell within the table.
@@ -2509,7 +2513,7 @@ var require_cell = __commonJS({ "node_modules/cli-table3/src/cell.js"(exports, m
2509
2513
  //#endregion
2510
2514
  //#region node_modules/cli-table3/src/layout-manager.js
2511
2515
  var require_layout_manager = __commonJS({ "node_modules/cli-table3/src/layout-manager.js"(exports, module) {
2512
- const { warn, debug: debug$1 } = require_debug();
2516
+ const { warn, debug: debug$1 } = require_debug$1();
2513
2517
  const Cell = require_cell();
2514
2518
  const { ColSpanCell, RowSpanCell } = Cell;
2515
2519
  (function() {
@@ -2719,8 +2723,8 @@ var require_layout_manager = __commonJS({ "node_modules/cli-table3/src/layout-ma
2719
2723
  //#endregion
2720
2724
  //#region node_modules/cli-table3/src/table.js
2721
2725
  var require_table = __commonJS({ "node_modules/cli-table3/src/table.js"(exports, module) {
2722
- const debug = require_debug();
2723
- const utils = require_utils();
2726
+ const debug = require_debug$1();
2727
+ const utils = require_utils$1();
2724
2728
  const tableLayout = require_layout_manager();
2725
2729
  var Table$2 = class extends Array {
2726
2730
  constructor(opts) {
@@ -2809,17 +2813,17 @@ var require_picocolors = __commonJS({ "node_modules/picocolors/picocolors.js"(ex
2809
2813
  let p = process || {}, argv = p.argv || [], env = p.env || {};
2810
2814
  let isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
2811
2815
  let formatter = (open, close, replace = open) => (input) => {
2812
- let string$1 = "" + input, index = string$1.indexOf(close, open.length);
2813
- return ~index ? open + replaceClose(string$1, close, replace, index) + close : open + string$1 + close;
2816
+ let string = "" + input, index = string.indexOf(close, open.length);
2817
+ return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
2814
2818
  };
2815
- let replaceClose = (string$1, close, replace, index) => {
2819
+ let replaceClose = (string, close, replace, index) => {
2816
2820
  let result = "", cursor = 0;
2817
2821
  do {
2818
- result += string$1.substring(cursor, index) + replace;
2822
+ result += string.substring(cursor, index) + replace;
2819
2823
  cursor = index + close.length;
2820
- index = string$1.indexOf(close, cursor);
2824
+ index = string.indexOf(close, cursor);
2821
2825
  } while (~index);
2822
- return result + string$1.substring(cursor);
2826
+ return result + string.substring(cursor);
2823
2827
  };
2824
2828
  let createColors = (enabled = isColorSupported) => {
2825
2829
  let f = enabled ? formatter : () => String;
@@ -2873,243 +2877,7 @@ var require_picocolors = __commonJS({ "node_modules/picocolors/picocolors.js"(ex
2873
2877
  } });
2874
2878
 
2875
2879
  //#endregion
2876
- //#region debug.ts
2877
- const MATCH_THRESHOLD_PERCENT = .1;
2878
- async function detectMismatches(claudePath) {
2879
- const claudeDir = claudePath || path.join(homedir(), ".claude", "projects");
2880
- const files = await glob(["**/*.jsonl"], {
2881
- cwd: claudeDir,
2882
- absolute: true
2883
- });
2884
- const modelPricing = await fetchModelPricing();
2885
- const stats = {
2886
- totalEntries: 0,
2887
- entriesWithBoth: 0,
2888
- matches: 0,
2889
- mismatches: 0,
2890
- discrepancies: [],
2891
- modelStats: new Map(),
2892
- versionStats: new Map()
2893
- };
2894
- for (const file of files) {
2895
- const content = await readFile(file, "utf-8");
2896
- const lines = content.trim().split("\n").filter((line) => line.length > 0);
2897
- for (const line of lines) try {
2898
- const parsed = JSON.parse(line);
2899
- const result = safeParse(UsageDataSchema, parsed);
2900
- if (!result.success) continue;
2901
- const data = result.output;
2902
- stats.totalEntries++;
2903
- if (data.costUSD !== void 0 && data.message.model && data.message.model !== "<synthetic>") {
2904
- stats.entriesWithBoth++;
2905
- const model = data.message.model;
2906
- const pricing = getModelPricing(model, modelPricing);
2907
- if (pricing) {
2908
- const calculatedCost = calculateCostFromTokens(data.message.usage, pricing);
2909
- const difference = Math.abs(data.costUSD - calculatedCost);
2910
- const percentDiff = data.costUSD > 0 ? difference / data.costUSD * 100 : 0;
2911
- const modelStat = stats.modelStats.get(model) || {
2912
- total: 0,
2913
- matches: 0,
2914
- mismatches: 0,
2915
- avgPercentDiff: 0
2916
- };
2917
- modelStat.total++;
2918
- if (data.version) {
2919
- const versionStat = stats.versionStats.get(data.version) || {
2920
- total: 0,
2921
- matches: 0,
2922
- mismatches: 0,
2923
- avgPercentDiff: 0
2924
- };
2925
- versionStat.total++;
2926
- if (percentDiff < MATCH_THRESHOLD_PERCENT) versionStat.matches++;
2927
- else versionStat.mismatches++;
2928
- versionStat.avgPercentDiff = (versionStat.avgPercentDiff * (versionStat.total - 1) + percentDiff) / versionStat.total;
2929
- stats.versionStats.set(data.version, versionStat);
2930
- }
2931
- if (percentDiff < .1) {
2932
- stats.matches++;
2933
- modelStat.matches++;
2934
- } else {
2935
- stats.mismatches++;
2936
- modelStat.mismatches++;
2937
- stats.discrepancies.push({
2938
- file: path.basename(file),
2939
- timestamp: data.timestamp,
2940
- model,
2941
- originalCost: data.costUSD,
2942
- calculatedCost,
2943
- difference,
2944
- percentDiff,
2945
- usage: data.message.usage
2946
- });
2947
- }
2948
- modelStat.avgPercentDiff = (modelStat.avgPercentDiff * (modelStat.total - 1) + percentDiff) / modelStat.total;
2949
- stats.modelStats.set(model, modelStat);
2950
- }
2951
- }
2952
- } catch (e) {}
2953
- }
2954
- return stats;
2955
- }
2956
- function printMismatchReport(stats, sampleCount = 5) {
2957
- if (stats.entriesWithBoth === 0) {
2958
- logger.info("No pricing data found to analyze.");
2959
- return;
2960
- }
2961
- const matchRate = stats.matches / stats.entriesWithBoth * 100;
2962
- logger.info("\n=== Pricing Mismatch Debug Report ===");
2963
- logger.info(`Total entries processed: ${stats.totalEntries.toLocaleString()}`);
2964
- logger.info(`Entries with both costUSD and model: ${stats.entriesWithBoth.toLocaleString()}`);
2965
- logger.info(`Matches (within 0.1%): ${stats.matches.toLocaleString()}`);
2966
- logger.info(`Mismatches: ${stats.mismatches.toLocaleString()}`);
2967
- logger.info(`Match rate: ${matchRate.toFixed(2)}%`);
2968
- if (stats.mismatches > 0 && stats.modelStats.size > 0) {
2969
- logger.info("\n=== Model Statistics ===");
2970
- const sortedModels = Array.from(stats.modelStats.entries()).sort((a, b) => b[1].mismatches - a[1].mismatches);
2971
- for (const [model, modelStat] of sortedModels) if (modelStat.mismatches > 0) {
2972
- const modelMatchRate = modelStat.matches / modelStat.total * 100;
2973
- logger.info(`${model}:`);
2974
- logger.info(` Total entries: ${modelStat.total.toLocaleString()}`);
2975
- logger.info(` Matches: ${modelStat.matches.toLocaleString()} (${modelMatchRate.toFixed(1)}%)`);
2976
- logger.info(` Mismatches: ${modelStat.mismatches.toLocaleString()}`);
2977
- logger.info(` Avg % difference: ${modelStat.avgPercentDiff.toFixed(1)}%`);
2978
- }
2979
- }
2980
- if (stats.mismatches > 0 && stats.versionStats.size > 0) {
2981
- logger.info("\n=== Version Statistics ===");
2982
- const sortedVersions = Array.from(stats.versionStats.entries()).filter(([_, versionStat]) => versionStat.mismatches > 0).sort((a, b) => b[1].mismatches - a[1].mismatches);
2983
- for (const [version$2, versionStat] of sortedVersions) {
2984
- const versionMatchRate = versionStat.matches / versionStat.total * 100;
2985
- logger.info(`${version$2}:`);
2986
- logger.info(` Total entries: ${versionStat.total.toLocaleString()}`);
2987
- logger.info(` Matches: ${versionStat.matches.toLocaleString()} (${versionMatchRate.toFixed(1)}%)`);
2988
- logger.info(` Mismatches: ${versionStat.mismatches.toLocaleString()}`);
2989
- logger.info(` Avg % difference: ${versionStat.avgPercentDiff.toFixed(1)}%`);
2990
- }
2991
- }
2992
- if (stats.discrepancies.length > 0 && sampleCount > 0) {
2993
- logger.info(`\n=== Sample Discrepancies (first ${sampleCount}) ===`);
2994
- const samples = stats.discrepancies.slice(0, sampleCount);
2995
- for (const disc of samples) {
2996
- logger.info(`File: ${disc.file}`);
2997
- logger.info(`Timestamp: ${disc.timestamp}`);
2998
- logger.info(`Model: ${disc.model}`);
2999
- logger.info(`Original cost: $${disc.originalCost.toFixed(6)}`);
3000
- logger.info(`Calculated cost: $${disc.calculatedCost.toFixed(6)}`);
3001
- logger.info(`Difference: $${disc.difference.toFixed(6)} (${disc.percentDiff.toFixed(2)}%)`);
3002
- logger.info(`Tokens: ${JSON.stringify(disc.usage)}`);
3003
- logger.info("---");
3004
- }
3005
- }
3006
- }
3007
-
3008
- //#endregion
3009
- //#region types.ts
3010
- const ModelSpecSchema = object({
3011
- max_tokens: optional(union([number(), string()])),
3012
- max_input_tokens: optional(union([number(), string()])),
3013
- max_output_tokens: optional(union([number(), string()])),
3014
- input_cost_per_token: optional(number()),
3015
- output_cost_per_token: optional(number()),
3016
- output_cost_per_reasoning_token: optional(number()),
3017
- cache_creation_input_token_cost: optional(number()),
3018
- cache_read_input_token_cost: optional(number()),
3019
- litellm_provider: optional(string()),
3020
- mode: optional(string()),
3021
- supports_function_calling: optional(boolean()),
3022
- supports_parallel_function_calling: optional(boolean()),
3023
- supports_vision: optional(boolean()),
3024
- supports_audio_input: optional(boolean()),
3025
- supports_audio_output: optional(boolean()),
3026
- supports_prompt_caching: optional(boolean()),
3027
- supports_response_schema: optional(boolean()),
3028
- supports_system_messages: optional(boolean()),
3029
- supports_reasoning: optional(boolean()),
3030
- supports_web_search: optional(boolean()),
3031
- search_context_cost_per_query: optional(object({
3032
- search_context_size_low: number(),
3033
- search_context_size_medium: number(),
3034
- search_context_size_high: number()
3035
- })),
3036
- deprecation_date: optional(string())
3037
- });
3038
- const LiteLLMModelPricesSchema = record(string(), ModelSpecSchema);
3039
- const dateSchema = pipe(string(), regex(/^\d{8}$/, "Date must be in YYYYMMDD format"));
3040
- const CostModes = [
3041
- "auto",
3042
- "calculate",
3043
- "display"
3044
- ];
3045
-
3046
- //#endregion
3047
- //#region shared-args.ts
3048
- const parseDateArg = (value) => {
3049
- const result = safeParse(dateSchema, value);
3050
- if (!result.success) throw new TypeError(result.issues[0].message);
3051
- return result.output;
3052
- };
3053
- const sharedArgs = {
3054
- since: {
3055
- type: "custom",
3056
- short: "s",
3057
- description: "Filter from date (YYYYMMDD format)",
3058
- parse: parseDateArg
3059
- },
3060
- until: {
3061
- type: "custom",
3062
- short: "u",
3063
- description: "Filter until date (YYYYMMDD format)",
3064
- parse: parseDateArg
3065
- },
3066
- path: {
3067
- type: "string",
3068
- short: "p",
3069
- description: "Custom path to Claude data directory",
3070
- default: getDefaultClaudePath()
3071
- },
3072
- json: {
3073
- type: "boolean",
3074
- short: "j",
3075
- description: "Output in JSON format",
3076
- default: false
3077
- },
3078
- mode: {
3079
- type: "enum",
3080
- short: "m",
3081
- description: "Cost calculation mode: auto (use costUSD if exists, otherwise calculate), calculate (always calculate), display (always use costUSD)",
3082
- default: "auto",
3083
- choices: CostModes
3084
- },
3085
- debug: {
3086
- type: "boolean",
3087
- short: "d",
3088
- description: "Show pricing mismatch information for debugging",
3089
- default: false
3090
- },
3091
- debugSamples: {
3092
- type: "number",
3093
- description: "Number of sample discrepancies to show in debug output (default: 5)",
3094
- default: 5
3095
- }
3096
- };
3097
- const sharedCommandConfig = {
3098
- args: sharedArgs,
3099
- toKebab: true
3100
- };
3101
-
3102
- //#endregion
3103
- //#region utils.ts
3104
- const formatNumber = (num) => {
3105
- return num.toLocaleString("en-US");
3106
- };
3107
- const formatCurrency = (amount) => {
3108
- return `$${amount.toFixed(2)}`;
3109
- };
3110
-
3111
- //#endregion
3112
- //#region commands/daily.ts
2880
+ //#region src/commands/daily.ts
3113
2881
  var import_cli_table3$1 = __toESM(require_cli_table3(), 1);
3114
2882
  var import_picocolors$1 = __toESM(require_picocolors(), 1);
3115
2883
  const dailyCommand = define({
@@ -3205,7 +2973,7 @@ const dailyCommand = define({
3205
2973
  });
3206
2974
 
3207
2975
  //#endregion
3208
- //#region commands/session.ts
2976
+ //#region src/commands/session.ts
3209
2977
  var import_cli_table3 = __toESM(require_cli_table3(), 1);
3210
2978
  var import_picocolors = __toESM(require_picocolors(), 1);
3211
2979
  const sessionCommand = define({
@@ -3321,7 +3089,7 @@ const sessionCommand = define({
3321
3089
  });
3322
3090
 
3323
3091
  //#endregion
3324
- //#region index.ts
3092
+ //#region src/commands/index.ts
3325
3093
  const subCommands = new Map();
3326
3094
  subCommands.set("daily", dailyCommand);
3327
3095
  subCommands.set("session", sessionCommand);