ccusage 0.6.1 → 0.6.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.
@@ -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-BY3-ryVq.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) {
@@ -2768,8 +3024,89 @@ async function glob(patternsOrOptions, options) {
2768
3024
  return crawl(opts, cwd, false);
2769
3025
  }
2770
3026
 
3027
+ //#endregion
3028
+ //#region src/utils.internal.ts
3029
+ function formatNumber(num) {
3030
+ return num.toLocaleString("en-US");
3031
+ }
3032
+ function formatCurrency(amount) {
3033
+ return `$${amount.toFixed(2)}`;
3034
+ }
3035
+ /**
3036
+ * WHY: Object.groupBy requires Node.js 21+. tsdown doesn't support runtime polyfills, only syntax transforms.
3037
+ */
3038
+ function groupBy(array$1, keyFn) {
3039
+ return array$1.reduce((groups, item) => {
3040
+ const key = keyFn(item);
3041
+ if (groups[key] == null) groups[key] = [];
3042
+ groups[key].push(item);
3043
+ return groups;
3044
+ }, {});
3045
+ }
3046
+
3047
+ //#endregion
3048
+ //#region node_modules/rolldown/node_modules/@oxc-project/runtime/src/helpers/usingCtx.js
3049
+ var require_usingCtx = __commonJS({ "node_modules/rolldown/node_modules/@oxc-project/runtime/src/helpers/usingCtx.js"(exports, module) {
3050
+ function _usingCtx() {
3051
+ var r = "function" == typeof SuppressedError ? SuppressedError : function(r$1, e$1) {
3052
+ var n$1 = Error();
3053
+ return n$1.name = "SuppressedError", n$1.error = r$1, n$1.suppressed = e$1, n$1;
3054
+ }, e = {}, n = [];
3055
+ function using(r$1, e$1) {
3056
+ if (null != e$1) {
3057
+ if (Object(e$1) !== e$1) throw new TypeError("using declarations can only be used with objects, functions, null, or undefined.");
3058
+ if (r$1) var o = e$1[Symbol.asyncDispose || Symbol["for"]("Symbol.asyncDispose")];
3059
+ if (void 0 === o && (o = e$1[Symbol.dispose || Symbol["for"]("Symbol.dispose")], r$1)) var t = o;
3060
+ if ("function" != typeof o) throw new TypeError("Object is not disposable.");
3061
+ t && (o = function o$1() {
3062
+ try {
3063
+ t.call(e$1);
3064
+ } catch (r$2) {
3065
+ return Promise.reject(r$2);
3066
+ }
3067
+ }), n.push({
3068
+ v: e$1,
3069
+ d: o,
3070
+ a: r$1
3071
+ });
3072
+ } else r$1 && n.push({
3073
+ d: e$1,
3074
+ a: r$1
3075
+ });
3076
+ return e$1;
3077
+ }
3078
+ return {
3079
+ e,
3080
+ u: using.bind(null, !1),
3081
+ a: using.bind(null, !0),
3082
+ d: function d() {
3083
+ var o, t = this.e, s = 0;
3084
+ function next() {
3085
+ for (; o = n.pop();) try {
3086
+ if (!o.a && 1 === s) return s = 0, n.push(o), Promise.resolve().then(next);
3087
+ if (o.d) {
3088
+ var r$1 = o.d.call(o.v);
3089
+ if (o.a) return s |= 2, Promise.resolve(r$1).then(next, err);
3090
+ } else s |= 1;
3091
+ } catch (r$2) {
3092
+ return err(r$2);
3093
+ }
3094
+ if (1 === s) return t !== e ? Promise.reject(t) : Promise.resolve();
3095
+ if (t !== e) throw t;
3096
+ }
3097
+ function err(n$1) {
3098
+ return t = t !== e ? new r(n$1, t) : n$1, next();
3099
+ }
3100
+ return next();
3101
+ }
3102
+ };
3103
+ }
3104
+ module.exports = _usingCtx, module.exports.__esModule = true, module.exports["default"] = module.exports;
3105
+ } });
3106
+
2771
3107
  //#endregion
2772
3108
  //#region src/data-loader.ts
3109
+ var import_usingCtx = __toESM(require_usingCtx(), 1);
2773
3110
  function getDefaultClaudePath() {
2774
3111
  return path.join(homedir(), ".claude");
2775
3112
  }
@@ -2821,159 +3158,174 @@ function formatDate(dateStr) {
2821
3158
  const day = String(date.getDate()).padStart(2, "0");
2822
3159
  return `${year}-${month}-${day}`;
2823
3160
  }
2824
- function calculateCostForEntry(data, mode, modelPricing) {
3161
+ async function calculateCostForEntry(data, mode, fetcher) {
2825
3162
  if (mode === "display") return data.costUSD ?? 0;
2826
3163
  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
- }
3164
+ if (data.message.model != null) return fetcher.calculateCostFromTokens(data.message.usage, data.message.model);
2831
3165
  return 0;
2832
3166
  }
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);
3167
+ if (mode === "auto") {
3168
+ if (data.costUSD != null) return data.costUSD;
3169
+ if (data.message.model != null) return fetcher.calculateCostFromTokens(data.message.usage, data.message.model);
3170
+ return 0;
2837
3171
  }
2838
- return 0;
3172
+ unreachable(mode);
2839
3173
  }
2840
3174
  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,
3175
+ try {
3176
+ var _usingCtx$1 = (0, import_usingCtx.default)();
3177
+ const claudePath = options?.claudePath ?? getDefaultClaudePath();
3178
+ const claudeDir = path.join(claudePath, "projects");
3179
+ const files = await glob(["**/*.jsonl"], {
3180
+ cwd: claudeDir,
3181
+ absolute: true
3182
+ });
3183
+ if (files.length === 0) return [];
3184
+ const mode = options?.mode ?? "auto";
3185
+ const fetcher = _usingCtx$1.u(mode === "display" ? null : new PricingFetcher());
3186
+ const allEntries = [];
3187
+ for (const file of files) {
3188
+ const content = await readFile(file, "utf-8");
3189
+ const lines = content.trim().split("\n").filter((line) => line.length > 0);
3190
+ for (const line of lines) try {
3191
+ const parsed = JSON.parse(line);
3192
+ const result = safeParse(UsageDataSchema, parsed);
3193
+ if (!result.success) continue;
3194
+ const data = result.output;
3195
+ const date = formatDate(data.timestamp);
3196
+ const cost = fetcher != null ? await calculateCostForEntry(data, mode, fetcher) : data.costUSD ?? 0;
3197
+ allEntries.push({
3198
+ data,
3199
+ date,
3200
+ cost
3201
+ });
3202
+ } catch {}
3203
+ }
3204
+ const groupedByDate = groupBy(allEntries, (entry) => entry.date);
3205
+ const results = Object.entries(groupedByDate).map(([date, entries]) => {
3206
+ if (entries == null) return void 0;
3207
+ return entries.reduce((acc, entry) => ({
3208
+ date,
3209
+ inputTokens: acc.inputTokens + (entry.data.message.usage.input_tokens ?? 0),
3210
+ outputTokens: acc.outputTokens + (entry.data.message.usage.output_tokens ?? 0),
3211
+ cacheCreationTokens: acc.cacheCreationTokens + (entry.data.message.usage.cache_creation_input_tokens ?? 0),
3212
+ cacheReadTokens: acc.cacheReadTokens + (entry.data.message.usage.cache_read_input_tokens ?? 0),
3213
+ totalCost: acc.totalCost + entry.cost
3214
+ }), {
2863
3215
  date,
2864
- cost
3216
+ inputTokens: 0,
3217
+ outputTokens: 0,
3218
+ cacheCreationTokens: 0,
3219
+ cacheReadTokens: 0,
3220
+ totalCost: 0
2865
3221
  });
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
3222
+ }).filter((item) => item != null).filter((item) => {
3223
+ if (options?.since != null || options?.until != null) {
3224
+ const dateStr = item.date.replace(/-/g, "");
3225
+ if (options.since != null && dateStr < options.since) return false;
3226
+ if (options.until != null && dateStr > options.until) return false;
3227
+ }
3228
+ return true;
2885
3229
  });
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());
3230
+ const sortOrder = options?.order ?? "desc";
3231
+ const sortedResults = sort(results);
3232
+ switch (sortOrder) {
3233
+ case "desc": return sortedResults.desc((item) => new Date(item.date).getTime());
3234
+ case "asc": return sortedResults.asc((item) => new Date(item.date).getTime());
3235
+ default: unreachable(sortOrder);
3236
+ }
3237
+ } catch (_) {
3238
+ _usingCtx$1.e = _;
3239
+ } finally {
3240
+ _usingCtx$1.d();
3241
+ }
2897
3242
  }
2898
3243
  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
3244
+ try {
3245
+ var _usingCtx3 = (0, import_usingCtx.default)();
3246
+ const claudePath = options?.claudePath ?? getDefaultClaudePath();
3247
+ const claudeDir = path.join(claudePath, "projects");
3248
+ const files = await glob(["**/*.jsonl"], {
3249
+ cwd: claudeDir,
3250
+ absolute: true
3251
+ });
3252
+ if (files.length === 0) return [];
3253
+ const mode = options?.mode ?? "auto";
3254
+ const fetcher = _usingCtx3.u(mode === "display" ? null : new PricingFetcher());
3255
+ const allEntries = [];
3256
+ for (const file of files) {
3257
+ const relativePath = path.relative(claudeDir, file);
3258
+ const parts = relativePath.split(path.sep);
3259
+ const sessionId = parts[parts.length - 2] ?? "unknown";
3260
+ const joinedPath = parts.slice(0, -2).join(path.sep);
3261
+ const projectPath = joinedPath.length > 0 ? joinedPath : "Unknown Project";
3262
+ const content = await readFile(file, "utf-8");
3263
+ const lines = content.trim().split("\n").filter((line) => line.length > 0);
3264
+ for (const line of lines) try {
3265
+ const parsed = JSON.parse(line);
3266
+ const result = safeParse(UsageDataSchema, parsed);
3267
+ if (!result.success) continue;
3268
+ const data = result.output;
3269
+ const sessionKey = `${projectPath}/${sessionId}`;
3270
+ const cost = fetcher != null ? await calculateCostForEntry(data, mode, fetcher) : data.costUSD ?? 0;
3271
+ allEntries.push({
3272
+ data,
3273
+ sessionKey,
3274
+ sessionId,
3275
+ projectPath,
3276
+ cost,
3277
+ timestamp: data.timestamp
3278
+ });
3279
+ } catch {}
3280
+ }
3281
+ const groupedBySessions = groupBy(allEntries, (entry) => entry.sessionKey);
3282
+ const results = Object.entries(groupedBySessions).map(([_, entries]) => {
3283
+ if (entries == null) return void 0;
3284
+ const latestEntry = entries.reduce((latest, current) => current.timestamp > latest.timestamp ? current : latest);
3285
+ const versionSet = /* @__PURE__ */ new Set();
3286
+ for (const entry of entries) if (entry.data.version != null) versionSet.add(entry.data.version);
3287
+ const aggregated = entries.reduce((acc, entry) => ({
3288
+ sessionId: latestEntry.sessionId,
3289
+ projectPath: latestEntry.projectPath,
3290
+ inputTokens: acc.inputTokens + (entry.data.message.usage.input_tokens ?? 0),
3291
+ outputTokens: acc.outputTokens + (entry.data.message.usage.output_tokens ?? 0),
3292
+ cacheCreationTokens: acc.cacheCreationTokens + (entry.data.message.usage.cache_creation_input_tokens ?? 0),
3293
+ cacheReadTokens: acc.cacheReadTokens + (entry.data.message.usage.cache_read_input_tokens ?? 0),
3294
+ totalCost: acc.totalCost + entry.cost,
3295
+ lastActivity: formatDate(latestEntry.timestamp),
3296
+ versions: Array.from(versionSet).sort()
3297
+ }), {
3298
+ sessionId: latestEntry.sessionId,
3299
+ projectPath: latestEntry.projectPath,
3300
+ inputTokens: 0,
3301
+ outputTokens: 0,
3302
+ cacheCreationTokens: 0,
3303
+ cacheReadTokens: 0,
3304
+ totalCost: 0,
3305
+ lastActivity: formatDate(latestEntry.timestamp),
3306
+ versions: Array.from(versionSet).sort()
2931
3307
  });
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()
3308
+ return aggregated;
3309
+ }).filter((item) => item != null).filter((item) => {
3310
+ if (options?.since != null || options?.until != null) {
3311
+ const dateStr = item.lastActivity.replace(/-/g, "");
3312
+ if (options.since != null && dateStr < options.since) return false;
3313
+ if (options.until != null && dateStr > options.until) return false;
3314
+ }
3315
+ return true;
2960
3316
  });
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());
3317
+ const sortOrder = options?.order ?? "desc";
3318
+ const sortedResults = sort(results);
3319
+ return sortOrder === "desc" ? sortedResults.desc((item) => new Date(item.lastActivity).getTime()) : sortedResults.asc((item) => new Date(item.lastActivity).getTime());
3320
+ } catch (_) {
3321
+ _usingCtx3.e = _;
3322
+ } finally {
3323
+ _usingCtx3.d();
3324
+ }
2973
3325
  }
2974
3326
  async function loadMonthlyUsageData(options) {
2975
3327
  const dailyData = await loadDailyUsageData(options);
2976
- const groupedByMonth = Object.groupBy(dailyData, (data) => data.date.substring(0, 7));
3328
+ const groupedByMonth = groupBy(dailyData, (data) => data.date.substring(0, 7));
2977
3329
  const monthlyArray = Object.entries(groupedByMonth).map(([month, dailyEntries]) => {
2978
3330
  if (dailyEntries == null) return void 0;
2979
3331
  return dailyEntries.reduce((acc, data) => ({
@@ -2998,4 +3350,4 @@ async function loadMonthlyUsageData(options) {
2998
3350
  }
2999
3351
 
3000
3352
  //#endregion
3001
- export { DailyUsageSchema, MonthlyUsageSchema, SessionUsageSchema, UsageDataSchema, __commonJS, __require, __toESM, calculateCostForEntry, formatDate, getDefaultClaudePath, glob, loadDailyUsageData, loadMonthlyUsageData, loadSessionData };
3353
+ export { DailyUsageSchema, MonthlyUsageSchema, SessionUsageSchema, UsageDataSchema, __commonJS, __require, __toESM, calculateCostForEntry, formatCurrency, formatDate, formatNumber, getDefaultClaudePath, glob, loadDailyUsageData, loadMonthlyUsageData, loadSessionData, require_usingCtx };