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.
- package/README.md +55 -22
- package/dist/calculate-cost.d.ts +2 -2
- package/dist/{data-loader-DP5qBPn6.js → data-loader-nOFcMg_V.js} +720 -171
- package/dist/data-loader-pCzn-ryX.d.ts +180 -0
- package/dist/data-loader.d.ts +3 -3
- package/dist/data-loader.js +5 -5
- package/dist/{debug-C_5Qx11m.js → debug-Bttss7TN.js} +42 -37
- package/dist/debug.js +5 -5
- package/dist/{dist-C0-Tf5eD.js → dist-BEQ1tJCL.js} +1 -18
- package/dist/{dist-LwbOR2Yw.js → dist-DAarI-SJ.js} +1 -1
- package/dist/{effect-WSjEuzC9-CJfWUy0j.js → effect-WSjEuzC9-ChJ5OQQf.js} +1 -1
- package/dist/{index-CISmcbXk-DCA05NUL.js → index-CISmcbXk-x9eVmhGM.js} +4 -4
- package/dist/index.js +84 -137
- package/dist/{logger-DsQC4OvA.js → logger-BPjA3VFO.js} +1 -1
- package/dist/logger.js +1 -1
- package/dist/{mcp-BQdv12mr.js → mcp-DCEVbd8C.js} +15 -9
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +6 -6
- package/dist/pricing-fetcher-CAeJvZnF.js +79 -0
- package/dist/{pricing-fetcher-CfEgfzSr.d.ts → pricing-fetcher-Dq-OLBp4.d.ts} +22 -10
- package/dist/pricing-fetcher.d.ts +2 -2
- package/dist/pricing-fetcher.js +4 -4
- package/dist/{sury-DmrZ3_Oj-CCL_DlTt.js → sury-DmrZ3_Oj-l0qqtY-f.js} +1 -1
- package/dist/valibot-CQk-M5rL-BNHzwpA0.js +10 -0
- package/dist/{zod-Db63SLXj-Dyc_OWjq.js → zod-Db63SLXj-N1oN-yiY.js} +1 -1
- package/package.json +1 -1
- package/dist/data-loader-VdEcqJHc.d.ts +0 -71
- package/dist/pricing-fetcher-BPUgMrB_.js +0 -60
- package/dist/valibot-CQk-M5rL-CkjrLVu1.js +0 -10
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { array, number, object, optional, pipe, regex, safeParse, string } from "./dist-
|
|
2
|
-
import {
|
|
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,
|
|
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 (
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
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
|
-
|
|
3282
|
+
unreachable(mode);
|
|
2839
3283
|
}
|
|
2840
3284
|
async function loadDailyUsageData(options) {
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
const
|
|
2853
|
-
const
|
|
2854
|
-
|
|
2855
|
-
const
|
|
2856
|
-
const
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
data,
|
|
2863
|
-
|
|
2864
|
-
|
|
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
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
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
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
})
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
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
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
const
|
|
2911
|
-
const
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
const
|
|
2919
|
-
const
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
data,
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
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
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
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
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
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 =
|
|
2977
|
-
const monthlyArray =
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
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:
|
|
2989
|
-
outputTokens:
|
|
2990
|
-
cacheCreationTokens:
|
|
2991
|
-
cacheReadTokens:
|
|
2992
|
-
totalCost
|
|
2993
|
-
|
|
2994
|
-
|
|
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 };
|