ccusage 0.6.1 → 0.7.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,5 +1,5 @@
1
- import { array, number, object, optional, pipe, regex, safeParse, string } from "./dist-C0-Tf5eD.js";
2
- import { calculateCostFromTokens, fetchModelPricing, getModelPricing } from "./pricing-fetcher-BPUgMrB_.js";
1
+ import { array, number, object, optional, pipe, regex, safeParse, string } from "./dist-BEQ1tJCL.js";
2
+ import { PricingFetcher } from "./pricing-fetcher-CAeJvZnF.js";
3
3
  import { createRequire } from "node:module";
4
4
  import { readFile } from "node:fs/promises";
5
5
  import { homedir } from "node:os";
@@ -32,6 +32,262 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
32
32
  }) : target, mod));
33
33
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
34
34
 
35
+ //#endregion
36
+ //#region node_modules/@jsr/core__unknownutil/is/string.js
37
+ /**
38
+ * Return `true` if the type of `x` is `string`.
39
+ *
40
+ * ```ts
41
+ * import { is } from "@core/unknownutil";
42
+ *
43
+ * const a: unknown = "a";
44
+ * if (is.String(a)) {
45
+ * const _: string = a;
46
+ * }
47
+ * ```
48
+ */ function isString(x) {
49
+ return typeof x === "string";
50
+ }
51
+
52
+ //#endregion
53
+ //#region node_modules/@jsr/core__unknownutil/is/record.js
54
+ /**
55
+ * Return `true` if the type of `x` satisfies `Record<PropertyKey, unknown>`.
56
+ *
57
+ * Note that this function returns `true` for ambiguous instances like `Set`, `Map`, `Date`, `Promise`, etc.
58
+ * Use {@linkcode [is/record-object].isRecordObject|isRecordObject} instead if you want to check if `x` is an instance of `Object`.
59
+ *
60
+ * ```ts
61
+ * import { is } from "@core/unknownutil";
62
+ *
63
+ * const a: unknown = {"a": 0, "b": 1};
64
+ * if (is.Record(a)) {
65
+ * const _: Record<PropertyKey, unknown> = a;
66
+ * }
67
+ *
68
+ * const b: unknown = new Set();
69
+ * if (is.Record(b)) {
70
+ * const _: Record<PropertyKey, unknown> = b;
71
+ * }
72
+ * ```
73
+ */ function isRecord(x) {
74
+ return x != null && !Array.isArray(x) && typeof x === "object";
75
+ }
76
+
77
+ //#endregion
78
+ //#region node_modules/@jsr/core__unknownutil/_inspect.js
79
+ const defaultThreshold = 20;
80
+ /**
81
+ * Inspect a value
82
+ */ function inspect(value, options = {}) {
83
+ if (value === null) return "null";
84
+ else if (Array.isArray(value)) return inspectArray(value, options);
85
+ switch (typeof value) {
86
+ case "string": return JSON.stringify(value);
87
+ case "bigint": return `${value}n`;
88
+ case "object":
89
+ if (value.constructor?.name !== "Object") return value.constructor?.name;
90
+ return inspectRecord(value, options);
91
+ case "function": return value.name || "(anonymous)";
92
+ }
93
+ return value?.toString() ?? "undefined";
94
+ }
95
+ function inspectArray(value, options) {
96
+ const { threshold = defaultThreshold } = options;
97
+ const vs = value.map((v) => inspect(v, options));
98
+ const s = vs.join(", ");
99
+ if (s.length <= threshold) return `[${s}]`;
100
+ const m = vs.join(",\n");
101
+ return `[\n${indent(2, m)}\n]`;
102
+ }
103
+ function inspectRecord(value, options) {
104
+ const { threshold = defaultThreshold } = options;
105
+ const vs = [...Object.keys(value), ...Object.getOwnPropertySymbols(value)].map((k) => `${k.toString()}: ${inspect(value[k], options)}`);
106
+ const s = vs.join(", ");
107
+ if (s.length <= threshold) return `{${s}}`;
108
+ const m = vs.join(",\n");
109
+ return `{\n${indent(2, m)}\n}`;
110
+ }
111
+ function indent(level, text) {
112
+ const prefix = " ".repeat(level);
113
+ return text.split("\n").map((line) => `${prefix}${line}`).join("\n");
114
+ }
115
+
116
+ //#endregion
117
+ //#region node_modules/@jsr/core__unknownutil/_funcutil.js
118
+ /**
119
+ * Rewrite the function name.
120
+ */ function rewriteName(fn, name, ...args) {
121
+ let cachedName;
122
+ return Object.defineProperties(fn, { name: { get: () => {
123
+ if (cachedName) return cachedName;
124
+ cachedName = `${name}(${args.map((v) => inspect(v)).join(", ")})`;
125
+ return cachedName;
126
+ } } });
127
+ }
128
+
129
+ //#endregion
130
+ //#region node_modules/@jsr/core__unknownutil/_annotation.js
131
+ function annotate(fn, name, value) {
132
+ return Object.defineProperties(fn, { [name]: { value } });
133
+ }
134
+ function hasAnnotation(fn, name) {
135
+ return !!fn[name];
136
+ }
137
+
138
+ //#endregion
139
+ //#region node_modules/@jsr/core__unknownutil/is/object_of.js
140
+ /**
141
+ * Return a type predicate function that returns `true` if the type of `x` is `ObjectOf<T>`.
142
+ *
143
+ * Use {@linkcode [is/record-of].isRecordOf|isRecordOf} if you want to check if the type of `x` is a record of `T`.
144
+ *
145
+ * If {@linkcode [as/optional].asOptional|asOptional} is specified in the predicate function in `predObj`, the property becomes optional.
146
+ * If {@linkcode [as/readonly].asReadonly|asReadonly} is specified in the predicate function in `predObj`, the property becomes readonly.
147
+ *
148
+ * The number of keys of `x` must be greater than or equal to the number of keys of `predObj`.
149
+ * Use {@linkcode [is/strict-of].isStrictOf|isStrictOf} if you want to check the exact number of keys.
150
+ *
151
+ * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost.
152
+ *
153
+ * ```ts
154
+ * import { as, is } from "@core/unknownutil";
155
+ *
156
+ * const isMyType = is.ObjectOf({
157
+ * a: is.Number,
158
+ * b: is.String,
159
+ * c: as.Optional(is.Boolean),
160
+ * d: as.Readonly(is.String),
161
+ * });
162
+ * const a: unknown = { a: 0, b: "a", d: "d" };
163
+ * if (isMyType(a)) {
164
+ * const _: { a: number; b: string; c?: boolean | undefined, readonly d: string } = a;
165
+ * }
166
+ * ```
167
+ */ function isObjectOf(predObj) {
168
+ const preds = [...Object.keys(predObj), ...Object.getOwnPropertySymbols(predObj)].map((k) => [k, predObj[k]]);
169
+ const pred = rewriteName((x) => {
170
+ if (!isObject$1(x)) return false;
171
+ return preds.every(([k, pred$1]) => pred$1(x[k]));
172
+ }, "isObjectOf", predObj);
173
+ return annotate(pred, "predObj", predObj);
174
+ }
175
+ function isObject$1(x) {
176
+ if (x == null) return false;
177
+ if (typeof x !== "object" && typeof x !== "function") return false;
178
+ if (Array.isArray(x)) return false;
179
+ return true;
180
+ }
181
+
182
+ //#endregion
183
+ //#region node_modules/@jsr/core__unknownutil/as/optional.js
184
+ /**
185
+ * Annotate the given predicate function as optional.
186
+ *
187
+ * Use this function to annotate a predicate function of `predObj` in {@linkcode [is/object-of].isObjectOf|isObjectOf}.
188
+ *
189
+ * Note that the annotated predicate function will return `true` if the type of `x` is `T` or `undefined`, indicating that
190
+ * this function is not just for annotation but it also changes the behavior of the predicate function.
191
+ *
192
+ * Use {@linkcode asUnoptional} to remove the annotation.
193
+ * Use {@linkcode hasOptional} to check if a predicate function has annotated with this function.
194
+ *
195
+ * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost.
196
+ *
197
+ * ```ts
198
+ * import { as, is } from "@core/unknownutil";
199
+ *
200
+ * const isMyType = is.ObjectOf({
201
+ * foo: as.Optional(is.String),
202
+ * });
203
+ * const a: unknown = {};
204
+ * if (isMyType(a)) {
205
+ * const _: {foo?: string} = a;
206
+ * }
207
+ * ```
208
+ */ function asOptional(pred) {
209
+ if (hasAnnotation(pred, "optional")) return pred;
210
+ return rewriteName(annotate((x) => x === void 0 || pred(x), "optional", pred), "asOptional", pred);
211
+ }
212
+
213
+ //#endregion
214
+ //#region node_modules/@core/errorutil/error_object.js
215
+ /**
216
+ * Check if a value is an error object
217
+ */ const isErrorObject = isObjectOf({
218
+ proto: isString,
219
+ name: isString,
220
+ message: isString,
221
+ stack: asOptional(isString),
222
+ attributes: isRecord
223
+ });
224
+
225
+ //#endregion
226
+ //#region node_modules/@core/errorutil/unreachable.js
227
+ /**
228
+ * Error indicating that this part is unreachable.
229
+ */ var UnreachableError = class UnreachableError extends Error {
230
+ args;
231
+ constructor(args) {
232
+ super(`unreachable: ${args}`);
233
+ if (Error.captureStackTrace) Error.captureStackTrace(this, UnreachableError);
234
+ this.name = this.constructor.name;
235
+ this.args = args;
236
+ }
237
+ };
238
+ /**
239
+ * Function indicating that this part is unreachable.
240
+ *
241
+ * For example, the following code passed type checking.
242
+ *
243
+ * ```ts
244
+ * import { unreachable } from "@core/errorutil/unreachable";
245
+ *
246
+ * type Animal = "dog" | "cat";
247
+ *
248
+ * function say(animal: Animal): void {
249
+ * switch (animal) {
250
+ * case "dog":
251
+ * console.log("dog");
252
+ * break;
253
+ * case "cat":
254
+ * console.log("dog");
255
+ * break;
256
+ * default:
257
+ * unreachable(animal);
258
+ * }
259
+ * }
260
+ * say("dog");
261
+ * ```
262
+ *
263
+ * But the following code because a case for "bird" is missing.
264
+ *
265
+ * ```ts
266
+ * import { unreachable } from "@core/errorutil/unreachable";
267
+ *
268
+ * type Animal = "dog" | "cat" | "bird";
269
+ *
270
+ * function say(animal: Animal): void {
271
+ * switch (animal) {
272
+ * case "dog":
273
+ * console.log("dog");
274
+ * break;
275
+ * case "cat":
276
+ * console.log("dog");
277
+ * break;
278
+ * default: {
279
+ * // The line below causes a type error if we uncomment it.
280
+ * // error: TS2345 [ERROR]: Argument of type 'string' is not assignable to parameter of type 'never'.
281
+ * //unreachable(animal);
282
+ * }
283
+ * }
284
+ * }
285
+ * say("dog");
286
+ * ```
287
+ */ function unreachable(...args) {
288
+ throw new UnreachableError(args);
289
+ }
290
+
35
291
  //#endregion
36
292
  //#region node_modules/fast-sort/dist/sort.mjs
37
293
  var castComparer = function(comparer) {
@@ -2240,7 +2496,7 @@ var require_picomatch$1 = __commonJS({ "node_modules/picomatch/lib/picomatch.js"
2240
2496
  * @api public
2241
2497
  */
2242
2498
  picomatch$2.parse = (pattern, options) => {
2243
- if (Array.isArray(pattern)) return pattern.map((p) => picomatch$2.parse(p, options));
2499
+ if (Array.isArray(pattern)) return pattern.map((p$1) => picomatch$2.parse(p$1, options));
2244
2500
  return parse(pattern, {
2245
2501
  ...options,
2246
2502
  fastpaths: false
@@ -2537,7 +2793,7 @@ var require_dist$1 = __commonJS({ "node_modules/fdir/dist/index.js"(exports) {
2537
2793
  o[k2] = m[k];
2538
2794
  });
2539
2795
  var __exportStar = void 0 && (void 0).__exportStar || function(m, exports$1) {
2540
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports$1, p)) __createBinding(exports$1, m, p);
2796
+ for (var p$1 in m) if (p$1 !== "default" && !Object.prototype.hasOwnProperty.call(exports$1, p$1)) __createBinding(exports$1, m, p$1);
2541
2797
  };
2542
2798
  Object.defineProperty(exports, "__esModule", { value: true });
2543
2799
  exports.fdir = void 0;
@@ -2717,20 +2973,20 @@ function crawl(options, cwd, sync$1) {
2717
2973
  nocase
2718
2974
  });
2719
2975
  const fdirOptions = {
2720
- filters: [options.debug ? (p, isDirectory) => {
2721
- const path$1$1 = processPath(p, cwd, props.root, isDirectory, options.absolute);
2976
+ filters: [options.debug ? (p$1, isDirectory) => {
2977
+ const path$1$1 = processPath(p$1, cwd, props.root, isDirectory, options.absolute);
2722
2978
  const matches = matcher(path$1$1);
2723
2979
  if (matches) log(`matched ${path$1$1}`);
2724
2980
  return matches;
2725
- } : (p, isDirectory) => matcher(processPath(p, cwd, props.root, isDirectory, options.absolute))],
2726
- exclude: options.debug ? (_, p) => {
2727
- const relativePath = processPath(p, cwd, props.root, true, true);
2981
+ } : (p$1, isDirectory) => matcher(processPath(p$1, cwd, props.root, isDirectory, options.absolute))],
2982
+ exclude: options.debug ? (_, p$1) => {
2983
+ const relativePath = processPath(p$1, cwd, props.root, true, true);
2728
2984
  const skipped = relativePath !== "." && !partialMatcher(relativePath) || ignore(relativePath);
2729
- if (skipped) log(`skipped ${p}`);
2730
- else log(`crawling ${p}`);
2985
+ if (skipped) log(`skipped ${p$1}`);
2986
+ else log(`crawling ${p$1}`);
2731
2987
  return skipped;
2732
- } : (_, p) => {
2733
- const relativePath = processPath(p, cwd, props.root, true, true);
2988
+ } : (_, p$1) => {
2989
+ const relativePath = processPath(p$1, cwd, props.root, true, true);
2734
2990
  return relativePath !== "." && !partialMatcher(relativePath) || ignore(relativePath);
2735
2991
  },
2736
2992
  pathSeparator: "/",
@@ -2768,8 +3024,185 @@ async function glob(patternsOrOptions, options) {
2768
3024
  return crawl(opts, cwd, false);
2769
3025
  }
2770
3026
 
3027
+ //#endregion
3028
+ //#region node_modules/picocolors/picocolors.js
3029
+ var require_picocolors = __commonJS({ "node_modules/picocolors/picocolors.js"(exports, module) {
3030
+ let p = process || {}, argv = p.argv || [], env = p.env || {};
3031
+ 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);
3032
+ let formatter = (open, close, replace = open) => (input) => {
3033
+ let string$1 = "" + input, index = string$1.indexOf(close, open.length);
3034
+ return ~index ? open + replaceClose(string$1, close, replace, index) + close : open + string$1 + close;
3035
+ };
3036
+ let replaceClose = (string$1, close, replace, index) => {
3037
+ let result = "", cursor = 0;
3038
+ do {
3039
+ result += string$1.substring(cursor, index) + replace;
3040
+ cursor = index + close.length;
3041
+ index = string$1.indexOf(close, cursor);
3042
+ } while (~index);
3043
+ return result + string$1.substring(cursor);
3044
+ };
3045
+ let createColors = (enabled = isColorSupported) => {
3046
+ let f = enabled ? formatter : () => String;
3047
+ return {
3048
+ isColorSupported: enabled,
3049
+ reset: f("\x1B[0m", "\x1B[0m"),
3050
+ bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
3051
+ dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
3052
+ italic: f("\x1B[3m", "\x1B[23m"),
3053
+ underline: f("\x1B[4m", "\x1B[24m"),
3054
+ inverse: f("\x1B[7m", "\x1B[27m"),
3055
+ hidden: f("\x1B[8m", "\x1B[28m"),
3056
+ strikethrough: f("\x1B[9m", "\x1B[29m"),
3057
+ black: f("\x1B[30m", "\x1B[39m"),
3058
+ red: f("\x1B[31m", "\x1B[39m"),
3059
+ green: f("\x1B[32m", "\x1B[39m"),
3060
+ yellow: f("\x1B[33m", "\x1B[39m"),
3061
+ blue: f("\x1B[34m", "\x1B[39m"),
3062
+ magenta: f("\x1B[35m", "\x1B[39m"),
3063
+ cyan: f("\x1B[36m", "\x1B[39m"),
3064
+ white: f("\x1B[37m", "\x1B[39m"),
3065
+ gray: f("\x1B[90m", "\x1B[39m"),
3066
+ bgBlack: f("\x1B[40m", "\x1B[49m"),
3067
+ bgRed: f("\x1B[41m", "\x1B[49m"),
3068
+ bgGreen: f("\x1B[42m", "\x1B[49m"),
3069
+ bgYellow: f("\x1B[43m", "\x1B[49m"),
3070
+ bgBlue: f("\x1B[44m", "\x1B[49m"),
3071
+ bgMagenta: f("\x1B[45m", "\x1B[49m"),
3072
+ bgCyan: f("\x1B[46m", "\x1B[49m"),
3073
+ bgWhite: f("\x1B[47m", "\x1B[49m"),
3074
+ blackBright: f("\x1B[90m", "\x1B[39m"),
3075
+ redBright: f("\x1B[91m", "\x1B[39m"),
3076
+ greenBright: f("\x1B[92m", "\x1B[39m"),
3077
+ yellowBright: f("\x1B[93m", "\x1B[39m"),
3078
+ blueBright: f("\x1B[94m", "\x1B[39m"),
3079
+ magentaBright: f("\x1B[95m", "\x1B[39m"),
3080
+ cyanBright: f("\x1B[96m", "\x1B[39m"),
3081
+ whiteBright: f("\x1B[97m", "\x1B[39m"),
3082
+ bgBlackBright: f("\x1B[100m", "\x1B[49m"),
3083
+ bgRedBright: f("\x1B[101m", "\x1B[49m"),
3084
+ bgGreenBright: f("\x1B[102m", "\x1B[49m"),
3085
+ bgYellowBright: f("\x1B[103m", "\x1B[49m"),
3086
+ bgBlueBright: f("\x1B[104m", "\x1B[49m"),
3087
+ bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
3088
+ bgCyanBright: f("\x1B[106m", "\x1B[49m"),
3089
+ bgWhiteBright: f("\x1B[107m", "\x1B[49m")
3090
+ };
3091
+ };
3092
+ module.exports = createColors();
3093
+ module.exports.createColors = createColors;
3094
+ } });
3095
+
3096
+ //#endregion
3097
+ //#region src/utils.internal.ts
3098
+ var import_picocolors = __toESM(require_picocolors(), 1);
3099
+ function formatNumber(num) {
3100
+ return num.toLocaleString("en-US");
3101
+ }
3102
+ function formatCurrency(amount) {
3103
+ return `$${amount.toFixed(2)}`;
3104
+ }
3105
+ /**
3106
+ * WHY: Object.groupBy requires Node.js 21+. tsdown doesn't support runtime polyfills, only syntax transforms.
3107
+ */
3108
+ function groupBy(array$1, keyFn) {
3109
+ return array$1.reduce((groups, item) => {
3110
+ const key = keyFn(item);
3111
+ if (groups[key] == null) groups[key] = [];
3112
+ groups[key].push(item);
3113
+ return groups;
3114
+ }, {});
3115
+ }
3116
+ function formatModelName(modelName) {
3117
+ const match = modelName.match(/claude-(\w+)-(\d+)-\d+/);
3118
+ if (match != null) return `${match[1]}-${match[2]}`;
3119
+ return modelName;
3120
+ }
3121
+ function formatModelsDisplay(models) {
3122
+ const uniqueModels = [...new Set(models.map(formatModelName))];
3123
+ return uniqueModels.sort().join(", ");
3124
+ }
3125
+ /**
3126
+ * Pushes model breakdown rows to a table
3127
+ * @param table - The table to push rows to
3128
+ * @param breakdowns - Array of model breakdowns
3129
+ * @param extraColumns - Number of extra empty columns before the data (default: 1 for models column)
3130
+ * @param trailingColumns - Number of extra empty columns after the data (default: 0)
3131
+ */
3132
+ function pushBreakdownRows(table, breakdowns, extraColumns = 1, trailingColumns = 0) {
3133
+ for (const breakdown of breakdowns) {
3134
+ const row = [` └─ ${formatModelName(breakdown.modelName)}`];
3135
+ for (let i = 0; i < extraColumns; i++) row.push("");
3136
+ const totalTokens = breakdown.inputTokens + breakdown.outputTokens + breakdown.cacheCreationTokens + breakdown.cacheReadTokens;
3137
+ row.push(import_picocolors.default.gray(formatNumber(breakdown.inputTokens)), import_picocolors.default.gray(formatNumber(breakdown.outputTokens)), import_picocolors.default.gray(formatNumber(breakdown.cacheCreationTokens)), import_picocolors.default.gray(formatNumber(breakdown.cacheReadTokens)), import_picocolors.default.gray(formatNumber(totalTokens)), import_picocolors.default.gray(formatCurrency(breakdown.cost)));
3138
+ for (let i = 0; i < trailingColumns; i++) row.push("");
3139
+ table.push(row);
3140
+ }
3141
+ }
3142
+
3143
+ //#endregion
3144
+ //#region node_modules/rolldown/node_modules/@oxc-project/runtime/src/helpers/usingCtx.js
3145
+ var require_usingCtx = __commonJS({ "node_modules/rolldown/node_modules/@oxc-project/runtime/src/helpers/usingCtx.js"(exports, module) {
3146
+ function _usingCtx() {
3147
+ var r = "function" == typeof SuppressedError ? SuppressedError : function(r$1, e$1) {
3148
+ var n$1 = Error();
3149
+ return n$1.name = "SuppressedError", n$1.error = r$1, n$1.suppressed = e$1, n$1;
3150
+ }, e = {}, n = [];
3151
+ function using(r$1, e$1) {
3152
+ if (null != e$1) {
3153
+ if (Object(e$1) !== e$1) throw new TypeError("using declarations can only be used with objects, functions, null, or undefined.");
3154
+ if (r$1) var o = e$1[Symbol.asyncDispose || Symbol["for"]("Symbol.asyncDispose")];
3155
+ if (void 0 === o && (o = e$1[Symbol.dispose || Symbol["for"]("Symbol.dispose")], r$1)) var t = o;
3156
+ if ("function" != typeof o) throw new TypeError("Object is not disposable.");
3157
+ t && (o = function o$1() {
3158
+ try {
3159
+ t.call(e$1);
3160
+ } catch (r$2) {
3161
+ return Promise.reject(r$2);
3162
+ }
3163
+ }), n.push({
3164
+ v: e$1,
3165
+ d: o,
3166
+ a: r$1
3167
+ });
3168
+ } else r$1 && n.push({
3169
+ d: e$1,
3170
+ a: r$1
3171
+ });
3172
+ return e$1;
3173
+ }
3174
+ return {
3175
+ e,
3176
+ u: using.bind(null, !1),
3177
+ a: using.bind(null, !0),
3178
+ d: function d() {
3179
+ var o, t = this.e, s = 0;
3180
+ function next() {
3181
+ for (; o = n.pop();) try {
3182
+ if (!o.a && 1 === s) return s = 0, n.push(o), Promise.resolve().then(next);
3183
+ if (o.d) {
3184
+ var r$1 = o.d.call(o.v);
3185
+ if (o.a) return s |= 2, Promise.resolve(r$1).then(next, err);
3186
+ } else s |= 1;
3187
+ } catch (r$2) {
3188
+ return err(r$2);
3189
+ }
3190
+ if (1 === s) return t !== e ? Promise.reject(t) : Promise.resolve();
3191
+ if (t !== e) throw t;
3192
+ }
3193
+ function err(n$1) {
3194
+ return t = t !== e ? new r(n$1, t) : n$1, next();
3195
+ }
3196
+ return next();
3197
+ }
3198
+ };
3199
+ }
3200
+ module.exports = _usingCtx, module.exports.__esModule = true, module.exports["default"] = module.exports;
3201
+ } });
3202
+
2771
3203
  //#endregion
2772
3204
  //#region src/data-loader.ts
3205
+ var import_usingCtx = __toESM(require_usingCtx(), 1);
2773
3206
  function getDefaultClaudePath() {
2774
3207
  return path.join(homedir(), ".claude");
2775
3208
  }
@@ -2787,13 +3220,23 @@ const UsageDataSchema = object({
2787
3220
  }),
2788
3221
  costUSD: optional(number())
2789
3222
  });
3223
+ const ModelBreakdownSchema = object({
3224
+ modelName: string(),
3225
+ inputTokens: number(),
3226
+ outputTokens: number(),
3227
+ cacheCreationTokens: number(),
3228
+ cacheReadTokens: number(),
3229
+ cost: number()
3230
+ });
2790
3231
  const DailyUsageSchema = object({
2791
3232
  date: pipe(string(), regex(/^\d{4}-\d{2}-\d{2}$/)),
2792
3233
  inputTokens: number(),
2793
3234
  outputTokens: number(),
2794
3235
  cacheCreationTokens: number(),
2795
3236
  cacheReadTokens: number(),
2796
- totalCost: number()
3237
+ totalCost: number(),
3238
+ modelsUsed: array(string()),
3239
+ modelBreakdowns: array(ModelBreakdownSchema)
2797
3240
  });
2798
3241
  const SessionUsageSchema = object({
2799
3242
  sessionId: string(),
@@ -2804,7 +3247,9 @@ const SessionUsageSchema = object({
2804
3247
  cacheReadTokens: number(),
2805
3248
  totalCost: number(),
2806
3249
  lastActivity: string(),
2807
- versions: array(string())
3250
+ versions: array(string()),
3251
+ modelsUsed: array(string()),
3252
+ modelBreakdowns: array(ModelBreakdownSchema)
2808
3253
  });
2809
3254
  const MonthlyUsageSchema = object({
2810
3255
  month: pipe(string(), regex(/^\d{4}-\d{2}$/)),
@@ -2812,7 +3257,9 @@ const MonthlyUsageSchema = object({
2812
3257
  outputTokens: number(),
2813
3258
  cacheCreationTokens: number(),
2814
3259
  cacheReadTokens: number(),
2815
- totalCost: number()
3260
+ totalCost: number(),
3261
+ modelsUsed: array(string()),
3262
+ modelBreakdowns: array(ModelBreakdownSchema)
2816
3263
  });
2817
3264
  function formatDate(dateStr) {
2818
3265
  const date = new Date(dateStr);
@@ -2821,181 +3268,283 @@ function formatDate(dateStr) {
2821
3268
  const day = String(date.getDate()).padStart(2, "0");
2822
3269
  return `${year}-${month}-${day}`;
2823
3270
  }
2824
- function calculateCostForEntry(data, mode, modelPricing) {
3271
+ async function calculateCostForEntry(data, mode, fetcher) {
2825
3272
  if (mode === "display") return data.costUSD ?? 0;
2826
3273
  if (mode === "calculate") {
2827
- if (data.message.model != null) {
2828
- const pricing = getModelPricing(data.message.model, modelPricing);
2829
- if (pricing != null) return calculateCostFromTokens(data.message.usage, pricing);
2830
- }
3274
+ if (data.message.model != null) return fetcher.calculateCostFromTokens(data.message.usage, data.message.model);
2831
3275
  return 0;
2832
3276
  }
2833
- if (data.costUSD != null) return data.costUSD;
2834
- if (data.message.model != null) {
2835
- const pricing = getModelPricing(data.message.model, modelPricing);
2836
- if (pricing != null) return calculateCostFromTokens(data.message.usage, pricing);
3277
+ if (mode === "auto") {
3278
+ if (data.costUSD != null) return data.costUSD;
3279
+ if (data.message.model != null) return fetcher.calculateCostFromTokens(data.message.usage, data.message.model);
3280
+ return 0;
2837
3281
  }
2838
- return 0;
3282
+ unreachable(mode);
2839
3283
  }
2840
3284
  async function loadDailyUsageData(options) {
2841
- const claudePath = options?.claudePath ?? getDefaultClaudePath();
2842
- const claudeDir = path.join(claudePath, "projects");
2843
- const files = await glob(["**/*.jsonl"], {
2844
- cwd: claudeDir,
2845
- absolute: true
2846
- });
2847
- if (files.length === 0) return [];
2848
- const mode = options?.mode ?? "auto";
2849
- const modelPricing = mode === "display" ? {} : await fetchModelPricing();
2850
- const allEntries = [];
2851
- for (const file of files) {
2852
- const content = await readFile(file, "utf-8");
2853
- const lines = content.trim().split("\n").filter((line) => line.length > 0);
2854
- for (const line of lines) try {
2855
- const parsed = JSON.parse(line);
2856
- const result = safeParse(UsageDataSchema, parsed);
2857
- if (!result.success) continue;
2858
- const data = result.output;
2859
- const date = formatDate(data.timestamp);
2860
- const cost = calculateCostForEntry(data, mode, modelPricing);
2861
- allEntries.push({
2862
- data,
2863
- date,
2864
- cost
3285
+ try {
3286
+ var _usingCtx$1 = (0, import_usingCtx.default)();
3287
+ const claudePath = options?.claudePath ?? getDefaultClaudePath();
3288
+ const claudeDir = path.join(claudePath, "projects");
3289
+ const files = await glob(["**/*.jsonl"], {
3290
+ cwd: claudeDir,
3291
+ absolute: true
3292
+ });
3293
+ if (files.length === 0) return [];
3294
+ const mode = options?.mode ?? "auto";
3295
+ const fetcher = _usingCtx$1.u(mode === "display" ? null : new PricingFetcher());
3296
+ const allEntries = [];
3297
+ for (const file of files) {
3298
+ const content = await readFile(file, "utf-8");
3299
+ const lines = content.trim().split("\n").filter((line) => line.length > 0);
3300
+ for (const line of lines) try {
3301
+ const parsed = JSON.parse(line);
3302
+ const result = safeParse(UsageDataSchema, parsed);
3303
+ if (!result.success) continue;
3304
+ const data = result.output;
3305
+ const date = formatDate(data.timestamp);
3306
+ const cost = fetcher != null ? await calculateCostForEntry(data, mode, fetcher) : data.costUSD ?? 0;
3307
+ allEntries.push({
3308
+ data,
3309
+ date,
3310
+ cost,
3311
+ model: data.message.model
3312
+ });
3313
+ } catch {}
3314
+ }
3315
+ const groupedByDate = groupBy(allEntries, (entry) => entry.date);
3316
+ const results = Object.entries(groupedByDate).map(([date, entries]) => {
3317
+ if (entries == null) return void 0;
3318
+ const modelAggregates = /* @__PURE__ */ new Map();
3319
+ for (const entry of entries) {
3320
+ const modelName = entry.model ?? "unknown";
3321
+ if (modelName === "<synthetic>") continue;
3322
+ const existing = modelAggregates.get(modelName) ?? {
3323
+ inputTokens: 0,
3324
+ outputTokens: 0,
3325
+ cacheCreationTokens: 0,
3326
+ cacheReadTokens: 0,
3327
+ cost: 0
3328
+ };
3329
+ modelAggregates.set(modelName, {
3330
+ inputTokens: existing.inputTokens + (entry.data.message.usage.input_tokens ?? 0),
3331
+ outputTokens: existing.outputTokens + (entry.data.message.usage.output_tokens ?? 0),
3332
+ cacheCreationTokens: existing.cacheCreationTokens + (entry.data.message.usage.cache_creation_input_tokens ?? 0),
3333
+ cacheReadTokens: existing.cacheReadTokens + (entry.data.message.usage.cache_read_input_tokens ?? 0),
3334
+ cost: existing.cost + entry.cost
3335
+ });
3336
+ }
3337
+ const modelBreakdowns = Array.from(modelAggregates.entries()).map(([modelName, stats]) => ({
3338
+ modelName,
3339
+ ...stats
3340
+ })).sort((a, b) => b.cost - a.cost);
3341
+ const totals = entries.reduce((acc, entry) => ({
3342
+ inputTokens: acc.inputTokens + (entry.data.message.usage.input_tokens ?? 0),
3343
+ outputTokens: acc.outputTokens + (entry.data.message.usage.output_tokens ?? 0),
3344
+ cacheCreationTokens: acc.cacheCreationTokens + (entry.data.message.usage.cache_creation_input_tokens ?? 0),
3345
+ cacheReadTokens: acc.cacheReadTokens + (entry.data.message.usage.cache_read_input_tokens ?? 0),
3346
+ totalCost: acc.totalCost + entry.cost
3347
+ }), {
3348
+ inputTokens: 0,
3349
+ outputTokens: 0,
3350
+ cacheCreationTokens: 0,
3351
+ cacheReadTokens: 0,
3352
+ totalCost: 0
2865
3353
  });
2866
- } catch {}
2867
- }
2868
- const groupedByDate = Object.groupBy(allEntries, (entry) => entry.date);
2869
- const results = Object.entries(groupedByDate).map(([date, entries]) => {
2870
- if (entries == null) return void 0;
2871
- return entries.reduce((acc, entry) => ({
2872
- date,
2873
- inputTokens: acc.inputTokens + (entry.data.message.usage.input_tokens ?? 0),
2874
- outputTokens: acc.outputTokens + (entry.data.message.usage.output_tokens ?? 0),
2875
- cacheCreationTokens: acc.cacheCreationTokens + (entry.data.message.usage.cache_creation_input_tokens ?? 0),
2876
- cacheReadTokens: acc.cacheReadTokens + (entry.data.message.usage.cache_read_input_tokens ?? 0),
2877
- totalCost: acc.totalCost + entry.cost
2878
- }), {
2879
- date,
2880
- inputTokens: 0,
2881
- outputTokens: 0,
2882
- cacheCreationTokens: 0,
2883
- cacheReadTokens: 0,
2884
- totalCost: 0
3354
+ const modelsUsed = [...new Set(entries.map((e) => e.model).filter((m) => m != null && m !== "<synthetic>"))];
3355
+ return {
3356
+ date,
3357
+ ...totals,
3358
+ modelsUsed,
3359
+ modelBreakdowns
3360
+ };
3361
+ }).filter((item) => item != null).filter((item) => {
3362
+ if (options?.since != null || options?.until != null) {
3363
+ const dateStr = item.date.replace(/-/g, "");
3364
+ if (options.since != null && dateStr < options.since) return false;
3365
+ if (options.until != null && dateStr > options.until) return false;
3366
+ }
3367
+ return true;
2885
3368
  });
2886
- }).filter((item) => item != null).filter((item) => {
2887
- if (options?.since != null || options?.until != null) {
2888
- const dateStr = item.date.replace(/-/g, "");
2889
- if (options.since != null && dateStr < options.since) return false;
2890
- if (options.until != null && dateStr > options.until) return false;
2891
- }
2892
- return true;
2893
- });
2894
- const sortOrder = options?.order ?? "desc";
2895
- const sortedResults = sort(results);
2896
- return sortOrder === "desc" ? sortedResults.desc((item) => new Date(item.date).getTime()) : sortedResults.asc((item) => new Date(item.date).getTime());
3369
+ const sortOrder = options?.order ?? "desc";
3370
+ const sortedResults = sort(results);
3371
+ switch (sortOrder) {
3372
+ case "desc": return sortedResults.desc((item) => new Date(item.date).getTime());
3373
+ case "asc": return sortedResults.asc((item) => new Date(item.date).getTime());
3374
+ default: unreachable(sortOrder);
3375
+ }
3376
+ } catch (_) {
3377
+ _usingCtx$1.e = _;
3378
+ } finally {
3379
+ _usingCtx$1.d();
3380
+ }
2897
3381
  }
2898
3382
  async function loadSessionData(options) {
2899
- const claudePath = options?.claudePath ?? getDefaultClaudePath();
2900
- const claudeDir = path.join(claudePath, "projects");
2901
- const files = await glob(["**/*.jsonl"], {
2902
- cwd: claudeDir,
2903
- absolute: true
2904
- });
2905
- if (files.length === 0) return [];
2906
- const mode = options?.mode ?? "auto";
2907
- const modelPricing = mode === "display" ? {} : await fetchModelPricing();
2908
- const allEntries = [];
2909
- for (const file of files) {
2910
- const relativePath = path.relative(claudeDir, file);
2911
- const parts = relativePath.split(path.sep);
2912
- const sessionId = parts[parts.length - 2] ?? "unknown";
2913
- const joinedPath = parts.slice(0, -2).join(path.sep);
2914
- const projectPath = joinedPath.length > 0 ? joinedPath : "Unknown Project";
2915
- const content = await readFile(file, "utf-8");
2916
- const lines = content.trim().split("\n").filter((line) => line.length > 0);
2917
- for (const line of lines) try {
2918
- const parsed = JSON.parse(line);
2919
- const result = safeParse(UsageDataSchema, parsed);
2920
- if (!result.success) continue;
2921
- const data = result.output;
2922
- const sessionKey = `${projectPath}/${sessionId}`;
2923
- const cost = calculateCostForEntry(data, mode, modelPricing);
2924
- allEntries.push({
2925
- data,
2926
- sessionKey,
2927
- sessionId,
2928
- projectPath,
2929
- cost,
2930
- timestamp: data.timestamp
3383
+ try {
3384
+ var _usingCtx3 = (0, import_usingCtx.default)();
3385
+ const claudePath = options?.claudePath ?? getDefaultClaudePath();
3386
+ const claudeDir = path.join(claudePath, "projects");
3387
+ const files = await glob(["**/*.jsonl"], {
3388
+ cwd: claudeDir,
3389
+ absolute: true
3390
+ });
3391
+ if (files.length === 0) return [];
3392
+ const mode = options?.mode ?? "auto";
3393
+ const fetcher = _usingCtx3.u(mode === "display" ? null : new PricingFetcher());
3394
+ const allEntries = [];
3395
+ for (const file of files) {
3396
+ const relativePath = path.relative(claudeDir, file);
3397
+ const parts = relativePath.split(path.sep);
3398
+ const sessionId = parts[parts.length - 2] ?? "unknown";
3399
+ const joinedPath = parts.slice(0, -2).join(path.sep);
3400
+ const projectPath = joinedPath.length > 0 ? joinedPath : "Unknown Project";
3401
+ const content = await readFile(file, "utf-8");
3402
+ const lines = content.trim().split("\n").filter((line) => line.length > 0);
3403
+ for (const line of lines) try {
3404
+ const parsed = JSON.parse(line);
3405
+ const result = safeParse(UsageDataSchema, parsed);
3406
+ if (!result.success) continue;
3407
+ const data = result.output;
3408
+ const sessionKey = `${projectPath}/${sessionId}`;
3409
+ const cost = fetcher != null ? await calculateCostForEntry(data, mode, fetcher) : data.costUSD ?? 0;
3410
+ allEntries.push({
3411
+ data,
3412
+ sessionKey,
3413
+ sessionId,
3414
+ projectPath,
3415
+ cost,
3416
+ timestamp: data.timestamp,
3417
+ model: data.message.model
3418
+ });
3419
+ } catch {}
3420
+ }
3421
+ const groupedBySessions = groupBy(allEntries, (entry) => entry.sessionKey);
3422
+ const results = Object.entries(groupedBySessions).map(([_, entries]) => {
3423
+ if (entries == null) return void 0;
3424
+ const latestEntry = entries.reduce((latest, current) => current.timestamp > latest.timestamp ? current : latest);
3425
+ const versionSet = /* @__PURE__ */ new Set();
3426
+ for (const entry of entries) if (entry.data.version != null) versionSet.add(entry.data.version);
3427
+ const modelAggregates = /* @__PURE__ */ new Map();
3428
+ for (const entry of entries) {
3429
+ const modelName = entry.model ?? "unknown";
3430
+ if (modelName === "<synthetic>") continue;
3431
+ const existing = modelAggregates.get(modelName) ?? {
3432
+ inputTokens: 0,
3433
+ outputTokens: 0,
3434
+ cacheCreationTokens: 0,
3435
+ cacheReadTokens: 0,
3436
+ cost: 0
3437
+ };
3438
+ modelAggregates.set(modelName, {
3439
+ inputTokens: existing.inputTokens + (entry.data.message.usage.input_tokens ?? 0),
3440
+ outputTokens: existing.outputTokens + (entry.data.message.usage.output_tokens ?? 0),
3441
+ cacheCreationTokens: existing.cacheCreationTokens + (entry.data.message.usage.cache_creation_input_tokens ?? 0),
3442
+ cacheReadTokens: existing.cacheReadTokens + (entry.data.message.usage.cache_read_input_tokens ?? 0),
3443
+ cost: existing.cost + entry.cost
3444
+ });
3445
+ }
3446
+ const modelBreakdowns = Array.from(modelAggregates.entries()).map(([modelName, stats]) => ({
3447
+ modelName,
3448
+ ...stats
3449
+ })).sort((a, b) => b.cost - a.cost);
3450
+ const totals = entries.reduce((acc, entry) => ({
3451
+ inputTokens: acc.inputTokens + (entry.data.message.usage.input_tokens ?? 0),
3452
+ outputTokens: acc.outputTokens + (entry.data.message.usage.output_tokens ?? 0),
3453
+ cacheCreationTokens: acc.cacheCreationTokens + (entry.data.message.usage.cache_creation_input_tokens ?? 0),
3454
+ cacheReadTokens: acc.cacheReadTokens + (entry.data.message.usage.cache_read_input_tokens ?? 0),
3455
+ totalCost: acc.totalCost + entry.cost
3456
+ }), {
3457
+ inputTokens: 0,
3458
+ outputTokens: 0,
3459
+ cacheCreationTokens: 0,
3460
+ cacheReadTokens: 0,
3461
+ totalCost: 0
2931
3462
  });
2932
- } catch {}
2933
- }
2934
- const groupedBySessions = Object.groupBy(allEntries, (entry) => entry.sessionKey);
2935
- const results = Object.entries(groupedBySessions).map(([_, entries]) => {
2936
- if (entries == null) return void 0;
2937
- const latestEntry = entries.reduce((latest, current) => current.timestamp > latest.timestamp ? current : latest);
2938
- const versionSet = /* @__PURE__ */ new Set();
2939
- for (const entry of entries) if (entry.data.version != null) versionSet.add(entry.data.version);
2940
- const aggregated = entries.reduce((acc, entry) => ({
2941
- sessionId: latestEntry.sessionId,
2942
- projectPath: latestEntry.projectPath,
2943
- inputTokens: acc.inputTokens + (entry.data.message.usage.input_tokens ?? 0),
2944
- outputTokens: acc.outputTokens + (entry.data.message.usage.output_tokens ?? 0),
2945
- cacheCreationTokens: acc.cacheCreationTokens + (entry.data.message.usage.cache_creation_input_tokens ?? 0),
2946
- cacheReadTokens: acc.cacheReadTokens + (entry.data.message.usage.cache_read_input_tokens ?? 0),
2947
- totalCost: acc.totalCost + entry.cost,
2948
- lastActivity: formatDate(latestEntry.timestamp),
2949
- versions: Array.from(versionSet).sort()
2950
- }), {
2951
- sessionId: latestEntry.sessionId,
2952
- projectPath: latestEntry.projectPath,
2953
- inputTokens: 0,
2954
- outputTokens: 0,
2955
- cacheCreationTokens: 0,
2956
- cacheReadTokens: 0,
2957
- totalCost: 0,
2958
- lastActivity: formatDate(latestEntry.timestamp),
2959
- versions: Array.from(versionSet).sort()
3463
+ const modelsUsed = [...new Set(entries.map((e) => e.model).filter((m) => m != null && m !== "<synthetic>"))];
3464
+ return {
3465
+ sessionId: latestEntry.sessionId,
3466
+ projectPath: latestEntry.projectPath,
3467
+ ...totals,
3468
+ lastActivity: formatDate(latestEntry.timestamp),
3469
+ versions: Array.from(versionSet).sort(),
3470
+ modelsUsed,
3471
+ modelBreakdowns
3472
+ };
3473
+ }).filter((item) => item != null).filter((item) => {
3474
+ if (options?.since != null || options?.until != null) {
3475
+ const dateStr = item.lastActivity.replace(/-/g, "");
3476
+ if (options.since != null && dateStr < options.since) return false;
3477
+ if (options.until != null && dateStr > options.until) return false;
3478
+ }
3479
+ return true;
2960
3480
  });
2961
- return aggregated;
2962
- }).filter((item) => item != null).filter((item) => {
2963
- if (options?.since != null || options?.until != null) {
2964
- const dateStr = item.lastActivity.replace(/-/g, "");
2965
- if (options.since != null && dateStr < options.since) return false;
2966
- if (options.until != null && dateStr > options.until) return false;
2967
- }
2968
- return true;
2969
- });
2970
- const sortOrder = options?.order ?? "desc";
2971
- const sortedResults = sort(results);
2972
- return sortOrder === "desc" ? sortedResults.desc((item) => new Date(item.lastActivity).getTime()) : sortedResults.asc((item) => new Date(item.lastActivity).getTime());
3481
+ const sortOrder = options?.order ?? "desc";
3482
+ const sortedResults = sort(results);
3483
+ return sortOrder === "desc" ? sortedResults.desc((item) => new Date(item.lastActivity).getTime()) : sortedResults.asc((item) => new Date(item.lastActivity).getTime());
3484
+ } catch (_) {
3485
+ _usingCtx3.e = _;
3486
+ } finally {
3487
+ _usingCtx3.d();
3488
+ }
2973
3489
  }
2974
3490
  async function loadMonthlyUsageData(options) {
2975
3491
  const dailyData = await loadDailyUsageData(options);
2976
- const groupedByMonth = Object.groupBy(dailyData, (data) => data.date.substring(0, 7));
2977
- const monthlyArray = Object.entries(groupedByMonth).map(([month, dailyEntries]) => {
2978
- if (dailyEntries == null) return void 0;
2979
- return dailyEntries.reduce((acc, data) => ({
2980
- month,
2981
- inputTokens: acc.inputTokens + data.inputTokens,
2982
- outputTokens: acc.outputTokens + data.outputTokens,
2983
- cacheCreationTokens: acc.cacheCreationTokens + data.cacheCreationTokens,
2984
- cacheReadTokens: acc.cacheReadTokens + data.cacheReadTokens,
2985
- totalCost: acc.totalCost + data.totalCost
2986
- }), {
3492
+ const groupedByMonth = groupBy(dailyData, (data) => data.date.substring(0, 7));
3493
+ const monthlyArray = [];
3494
+ for (const [month, dailyEntries] of Object.entries(groupedByMonth)) {
3495
+ if (dailyEntries == null) continue;
3496
+ const modelAggregates = /* @__PURE__ */ new Map();
3497
+ for (const daily of dailyEntries) for (const breakdown of daily.modelBreakdowns) {
3498
+ if (breakdown.modelName === "<synthetic>") continue;
3499
+ const existing = modelAggregates.get(breakdown.modelName) ?? {
3500
+ inputTokens: 0,
3501
+ outputTokens: 0,
3502
+ cacheCreationTokens: 0,
3503
+ cacheReadTokens: 0,
3504
+ cost: 0
3505
+ };
3506
+ modelAggregates.set(breakdown.modelName, {
3507
+ inputTokens: existing.inputTokens + breakdown.inputTokens,
3508
+ outputTokens: existing.outputTokens + breakdown.outputTokens,
3509
+ cacheCreationTokens: existing.cacheCreationTokens + breakdown.cacheCreationTokens,
3510
+ cacheReadTokens: existing.cacheReadTokens + breakdown.cacheReadTokens,
3511
+ cost: existing.cost + breakdown.cost
3512
+ });
3513
+ }
3514
+ const modelBreakdowns = Array.from(modelAggregates.entries()).map(([modelName, stats]) => ({
3515
+ modelName,
3516
+ ...stats
3517
+ })).sort((a, b) => b.cost - a.cost);
3518
+ const modelsSet = /* @__PURE__ */ new Set();
3519
+ for (const data of dailyEntries) for (const model of data.modelsUsed) if (model !== "<synthetic>") modelsSet.add(model);
3520
+ let totalInputTokens = 0;
3521
+ let totalOutputTokens = 0;
3522
+ let totalCacheCreationTokens = 0;
3523
+ let totalCacheReadTokens = 0;
3524
+ let totalCost = 0;
3525
+ for (const daily of dailyEntries) {
3526
+ totalInputTokens += daily.inputTokens;
3527
+ totalOutputTokens += daily.outputTokens;
3528
+ totalCacheCreationTokens += daily.cacheCreationTokens;
3529
+ totalCacheReadTokens += daily.cacheReadTokens;
3530
+ totalCost += daily.totalCost;
3531
+ }
3532
+ const monthlyUsage = {
2987
3533
  month,
2988
- inputTokens: 0,
2989
- outputTokens: 0,
2990
- cacheCreationTokens: 0,
2991
- cacheReadTokens: 0,
2992
- totalCost: 0
2993
- });
2994
- }).filter((item) => item != null);
3534
+ inputTokens: totalInputTokens,
3535
+ outputTokens: totalOutputTokens,
3536
+ cacheCreationTokens: totalCacheCreationTokens,
3537
+ cacheReadTokens: totalCacheReadTokens,
3538
+ totalCost,
3539
+ modelsUsed: Array.from(modelsSet),
3540
+ modelBreakdowns
3541
+ };
3542
+ monthlyArray.push(monthlyUsage);
3543
+ }
2995
3544
  const sortOrder = options?.order ?? "desc";
2996
3545
  const sortedMonthly = sort(monthlyArray);
2997
3546
  return sortOrder === "desc" ? sortedMonthly.desc((item) => item.month) : sortedMonthly.asc((item) => item.month);
2998
3547
  }
2999
3548
 
3000
3549
  //#endregion
3001
- export { DailyUsageSchema, MonthlyUsageSchema, SessionUsageSchema, UsageDataSchema, __commonJS, __require, __toESM, calculateCostForEntry, formatDate, getDefaultClaudePath, glob, loadDailyUsageData, loadMonthlyUsageData, loadSessionData };
3550
+ export { DailyUsageSchema, ModelBreakdownSchema, MonthlyUsageSchema, SessionUsageSchema, UsageDataSchema, __commonJS, __require, __toESM, calculateCostForEntry, formatCurrency, formatDate, formatModelsDisplay, formatNumber, getDefaultClaudePath, glob, loadDailyUsageData, loadMonthlyUsageData, loadSessionData, pushBreakdownRows, require_picocolors, require_usingCtx };