ccusage 0.6.0 → 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.
Files changed (46) hide show
  1. package/README.md +29 -22
  2. package/dist/calculate-cost.d.ts +11 -8
  3. package/dist/{core-BgFXUe_h.js → core-B0ovMhJe.js} +4 -4
  4. package/dist/data-loader-B0tJZeHI.d.ts +144 -0
  5. package/dist/{data-loader-CDv0IYZx.js → data-loader-BfnzLKGl.js} +503 -131
  6. package/dist/data-loader.d.ts +2 -4
  7. package/dist/data-loader.js +4 -4
  8. package/dist/{debug-Dk36WQTw.js → debug-Bf6GUNZE.js} +45 -40
  9. package/dist/debug.d.ts +4 -4
  10. package/dist/debug.js +5 -5
  11. package/dist/{dist-FwNhpFrW.js → dist-BEQ1tJCL.js} +1 -109
  12. package/dist/{dist-C_i5I27w.js → dist-DAarI-SJ.js} +5 -5
  13. package/dist/{effect-WSjEuzC9-BsxP11fz.js → effect-WSjEuzC9-ChJ5OQQf.js} +1 -1
  14. package/dist/{esm-vjyZjnpZ.js → esm-Dqsc1zmX.js} +1 -1
  15. package/dist/{index-CISmcbXk-BotItq1T.js → index-CISmcbXk-x9eVmhGM.js} +5 -5
  16. package/dist/index.js +108 -42
  17. package/dist/{logger-DhDyJEC5.js → logger-DixU80sg.js} +17 -17
  18. package/dist/logger.js +1 -1
  19. package/dist/{mcp-G-TIOcuj.js → mcp-nXxiNurt.js} +93 -78
  20. package/dist/mcp.d.ts +2 -4
  21. package/dist/mcp.js +7 -8
  22. package/dist/pricing-fetcher-BY3-ryVq.js +79 -0
  23. package/dist/{index-BurjgCfW.d.ts → pricing-fetcher-Dq-OLBp4.d.ts} +31 -249
  24. package/dist/pricing-fetcher.d.ts +2 -3
  25. package/dist/pricing-fetcher.js +4 -4
  26. package/dist/{prompt-IToGuko2.js → prompt-DljZqwMa.js} +4 -4
  27. package/dist/{sury-DmrZ3_Oj-DhGOjCNc.js → sury-DmrZ3_Oj-l0qqtY-f.js} +1 -1
  28. package/dist/{types-CFnCBr2I.js → types-DS8M8QF_.js} +4 -4
  29. package/dist/valibot-CQk-M5rL-BNHzwpA0.js +10 -0
  30. package/dist/{zod-Db63SLXj-BWdcigdx.js → zod-Db63SLXj-N1oN-yiY.js} +3 -3
  31. package/package.json +8 -11
  32. package/dist/data-loader-aUOjeZ06.d.ts +0 -67
  33. package/dist/pricing-fetcher-BCv1Vods.js +0 -60
  34. package/dist/pricing-fetcher-DygIroMj.d.ts +0 -21
  35. package/dist/shared-args-BtMSktLn.js +0 -68
  36. package/dist/shared-args.d.ts +0 -108
  37. package/dist/shared-args.js +0 -8
  38. package/dist/types-BcXIBMQk.js +0 -42
  39. package/dist/types-y1JQzaKZ.d.ts +0 -81
  40. package/dist/types.d.ts +0 -3
  41. package/dist/types.js +0 -4
  42. package/dist/utils-C7kg8MXN.js +0 -10
  43. package/dist/utils.d.ts +0 -5
  44. package/dist/utils.js +0 -3
  45. package/dist/valibot-CQk-M5rL-Cq5E7F3g.js +0 -10
  46. /package/dist/{arktype-C-GObzDh-Dj1DVoqC.js → arktype-C-GObzDh-Bx7Fdrqj.js} +0 -0
@@ -1,5 +1,5 @@
1
- import { array, number, object, optional, pipe, regex, safeParse, string } from "./dist-FwNhpFrW.js";
2
- import { calculateCostFromTokens, fetchModelPricing, getModelPricing } from "./pricing-fetcher-BCv1Vods.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) {
@@ -575,7 +831,7 @@ var require_walker = __commonJS({ "node_modules/fdir/dist/api/walker.js"(exports
575
831
  counts: new counter_1.Counter(),
576
832
  options,
577
833
  queue: new queue_1.Queue((error, state) => this.callbackInvoker(state, error, callback$1)),
578
- symlinks: new Map(),
834
+ symlinks: /* @__PURE__ */ new Map(),
579
835
  visited: [""].slice(0, 0),
580
836
  controller: new AbortController()
581
837
  };
@@ -2608,7 +2864,7 @@ function isDynamicPattern(pattern, options) {
2608
2864
  return scan$2.isGlob || scan$2.negated;
2609
2865
  }
2610
2866
  function log(...tasks) {
2611
- console.log(`[tinyglobby ${new Date().toLocaleTimeString("es")}]`, ...tasks);
2867
+ console.log(`[tinyglobby ${(/* @__PURE__ */ new Date()).toLocaleTimeString("es")}]`, ...tasks);
2612
2868
  }
2613
2869
  const PARENT_DIRECTORY = /^(\/?\.\.)+/;
2614
2870
  const ESCAPING_BACKSLASHES = /\\(?=[()[\]{}!*+?@|])/g;
@@ -2768,9 +3024,92 @@ 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
2773
- const getDefaultClaudePath = () => path.join(homedir(), ".claude");
3109
+ var import_usingCtx = __toESM(require_usingCtx(), 1);
3110
+ function getDefaultClaudePath() {
3111
+ return path.join(homedir(), ".claude");
3112
+ }
2774
3113
  const UsageDataSchema = object({
2775
3114
  timestamp: string(),
2776
3115
  version: optional(string()),
@@ -2812,170 +3151,203 @@ const MonthlyUsageSchema = object({
2812
3151
  cacheReadTokens: number(),
2813
3152
  totalCost: number()
2814
3153
  });
2815
- const formatDate = (dateStr) => {
3154
+ function formatDate(dateStr) {
2816
3155
  const date = new Date(dateStr);
2817
3156
  const year = date.getFullYear();
2818
3157
  const month = String(date.getMonth() + 1).padStart(2, "0");
2819
3158
  const day = String(date.getDate()).padStart(2, "0");
2820
3159
  return `${year}-${month}-${day}`;
2821
- };
2822
- const calculateCostForEntry = (data, mode, modelPricing) => {
3160
+ }
3161
+ async function calculateCostForEntry(data, mode, fetcher) {
2823
3162
  if (mode === "display") return data.costUSD ?? 0;
2824
3163
  if (mode === "calculate") {
2825
- if (data.message.model) {
2826
- const pricing = getModelPricing(data.message.model, modelPricing);
2827
- if (pricing) return calculateCostFromTokens(data.message.usage, pricing);
2828
- }
3164
+ if (data.message.model != null) return fetcher.calculateCostFromTokens(data.message.usage, data.message.model);
2829
3165
  return 0;
2830
3166
  }
2831
- if (data.costUSD !== void 0) return data.costUSD;
2832
- if (data.message.model) {
2833
- const pricing = getModelPricing(data.message.model, modelPricing);
2834
- if (pricing) 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;
2835
3171
  }
2836
- return 0;
2837
- };
3172
+ unreachable(mode);
3173
+ }
2838
3174
  async function loadDailyUsageData(options) {
2839
- const claudePath = options?.claudePath ?? getDefaultClaudePath();
2840
- const claudeDir = path.join(claudePath, "projects");
2841
- const files = await glob(["**/*.jsonl"], {
2842
- cwd: claudeDir,
2843
- absolute: true
2844
- });
2845
- if (files.length === 0) return [];
2846
- const mode = options?.mode || "auto";
2847
- const modelPricing = mode === "display" ? {} : await fetchModelPricing();
2848
- const dailyMap = new Map();
2849
- for (const file of files) {
2850
- const content = await readFile(file, "utf-8");
2851
- const lines = content.trim().split("\n").filter((line) => line.length > 0);
2852
- for (const line of lines) try {
2853
- const parsed = JSON.parse(line);
2854
- const result = safeParse(UsageDataSchema, parsed);
2855
- if (!result.success) continue;
2856
- const data = result.output;
2857
- const date = formatDate(data.timestamp);
2858
- const existing = dailyMap.get(date) || {
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
+ }), {
2859
3215
  date,
2860
3216
  inputTokens: 0,
2861
3217
  outputTokens: 0,
2862
3218
  cacheCreationTokens: 0,
2863
3219
  cacheReadTokens: 0,
2864
3220
  totalCost: 0
2865
- };
2866
- existing.inputTokens += data.message.usage.input_tokens ?? 0;
2867
- existing.outputTokens += data.message.usage.output_tokens ?? 0;
2868
- existing.cacheCreationTokens += data.message.usage.cache_creation_input_tokens ?? 0;
2869
- existing.cacheReadTokens += data.message.usage.cache_read_input_tokens ?? 0;
2870
- const cost = calculateCostForEntry(data, mode, modelPricing);
2871
- existing.totalCost += cost;
2872
- dailyMap.set(date, existing);
2873
- } catch (e) {}
3221
+ });
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;
3229
+ });
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();
2874
3241
  }
2875
- let results = Array.from(dailyMap.values());
2876
- if (options?.since || options?.until) results = results.filter((data) => {
2877
- const dateStr = data.date.replace(/-/g, "");
2878
- if (options.since && dateStr < options.since) return false;
2879
- if (options.until && dateStr > options.until) return false;
2880
- return true;
2881
- });
2882
- const sortOrder = options?.order || "desc";
2883
- const sortedResults = sort(results);
2884
- return sortOrder === "desc" ? sortedResults.desc((item) => new Date(item.date).getTime()) : sortedResults.asc((item) => new Date(item.date).getTime());
2885
3242
  }
2886
3243
  async function loadSessionData(options) {
2887
- const claudePath = options?.claudePath ?? getDefaultClaudePath();
2888
- const claudeDir = path.join(claudePath, "projects");
2889
- const files = await glob(["**/*.jsonl"], {
2890
- cwd: claudeDir,
2891
- absolute: true
2892
- });
2893
- if (files.length === 0) return [];
2894
- const mode = options?.mode || "auto";
2895
- const modelPricing = mode === "display" ? {} : await fetchModelPricing();
2896
- const sessionMap = new Map();
2897
- for (const file of files) {
2898
- const relativePath = path.relative(claudeDir, file);
2899
- const parts = relativePath.split(path.sep);
2900
- const sessionId = parts[parts.length - 2];
2901
- const projectPath = parts.slice(0, -2).join(path.sep);
2902
- const content = await readFile(file, "utf-8");
2903
- const lines = content.trim().split("\n").filter((line) => line.length > 0);
2904
- let lastTimestamp = "";
2905
- for (const line of lines) try {
2906
- const parsed = JSON.parse(line);
2907
- const result = safeParse(UsageDataSchema, parsed);
2908
- if (!result.success) continue;
2909
- const data = result.output;
2910
- const key = `${projectPath}/${sessionId}`;
2911
- const existing = sessionMap.get(key) || {
2912
- sessionId: sessionId || "unknown",
2913
- projectPath: projectPath || "Unknown Project",
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,
2914
3300
  inputTokens: 0,
2915
3301
  outputTokens: 0,
2916
3302
  cacheCreationTokens: 0,
2917
3303
  cacheReadTokens: 0,
2918
3304
  totalCost: 0,
2919
- lastActivity: "",
2920
- versions: [],
2921
- versionSet: new Set()
2922
- };
2923
- existing.inputTokens += data.message.usage.input_tokens ?? 0;
2924
- existing.outputTokens += data.message.usage.output_tokens ?? 0;
2925
- existing.cacheCreationTokens += data.message.usage.cache_creation_input_tokens ?? 0;
2926
- existing.cacheReadTokens += data.message.usage.cache_read_input_tokens ?? 0;
2927
- const cost = calculateCostForEntry(data, mode, modelPricing);
2928
- existing.totalCost += cost;
2929
- if (data.timestamp > lastTimestamp) {
2930
- lastTimestamp = data.timestamp;
2931
- existing.lastActivity = formatDate(data.timestamp);
3305
+ lastActivity: formatDate(latestEntry.timestamp),
3306
+ versions: Array.from(versionSet).sort()
3307
+ });
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;
2932
3314
  }
2933
- if (data.version) existing.versionSet.add(data.version);
2934
- sessionMap.set(key, existing);
2935
- } catch (e) {}
3315
+ return true;
3316
+ });
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();
2936
3324
  }
2937
- let results = Array.from(sessionMap.values()).map((session) => {
2938
- const { versionSet,...sessionData } = session;
2939
- return {
2940
- ...sessionData,
2941
- versions: Array.from(versionSet).sort()
2942
- };
2943
- });
2944
- if (options?.since || options?.until) results = results.filter((session) => {
2945
- const dateStr = session.lastActivity.replace(/-/g, "");
2946
- if (options.since && dateStr < options.since) return false;
2947
- if (options.until && dateStr > options.until) return false;
2948
- return true;
2949
- });
2950
- const sortOrder = options?.order || "desc";
2951
- const sortedResults = sort(results);
2952
- return sortOrder === "desc" ? sortedResults.desc((item) => new Date(item.lastActivity).getTime()) : sortedResults.asc((item) => new Date(item.lastActivity).getTime());
2953
3325
  }
2954
3326
  async function loadMonthlyUsageData(options) {
2955
3327
  const dailyData = await loadDailyUsageData(options);
2956
- const monthlyMap = new Map();
2957
- for (const data of dailyData) {
2958
- const month = data.date.substring(0, 7);
2959
- const existing = monthlyMap.get(month) || {
3328
+ const groupedByMonth = groupBy(dailyData, (data) => data.date.substring(0, 7));
3329
+ const monthlyArray = Object.entries(groupedByMonth).map(([month, dailyEntries]) => {
3330
+ if (dailyEntries == null) return void 0;
3331
+ return dailyEntries.reduce((acc, data) => ({
3332
+ month,
3333
+ inputTokens: acc.inputTokens + data.inputTokens,
3334
+ outputTokens: acc.outputTokens + data.outputTokens,
3335
+ cacheCreationTokens: acc.cacheCreationTokens + data.cacheCreationTokens,
3336
+ cacheReadTokens: acc.cacheReadTokens + data.cacheReadTokens,
3337
+ totalCost: acc.totalCost + data.totalCost
3338
+ }), {
2960
3339
  month,
2961
3340
  inputTokens: 0,
2962
3341
  outputTokens: 0,
2963
3342
  cacheCreationTokens: 0,
2964
3343
  cacheReadTokens: 0,
2965
3344
  totalCost: 0
2966
- };
2967
- existing.inputTokens += data.inputTokens;
2968
- existing.outputTokens += data.outputTokens;
2969
- existing.cacheCreationTokens += data.cacheCreationTokens;
2970
- existing.cacheReadTokens += data.cacheReadTokens;
2971
- existing.totalCost += data.totalCost;
2972
- monthlyMap.set(month, existing);
2973
- }
2974
- const monthlyArray = Array.from(monthlyMap.values());
2975
- const sortOrder = options?.order || "desc";
3345
+ });
3346
+ }).filter((item) => item != null);
3347
+ const sortOrder = options?.order ?? "desc";
2976
3348
  const sortedMonthly = sort(monthlyArray);
2977
3349
  return sortOrder === "desc" ? sortedMonthly.desc((item) => item.month) : sortedMonthly.asc((item) => item.month);
2978
3350
  }
2979
3351
 
2980
3352
  //#endregion
2981
- 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 };