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.
- package/README.md +3 -4
- package/dist/calculate-cost.d.ts +2 -2
- package/dist/{data-loader-VdEcqJHc.d.ts → data-loader-B0tJZeHI.d.ts} +77 -4
- package/dist/{data-loader-DP5qBPn6.js → data-loader-BfnzLKGl.js} +491 -139
- package/dist/data-loader.d.ts +2 -2
- package/dist/data-loader.js +4 -4
- package/dist/{debug-C_5Qx11m.js → debug-Bf6GUNZE.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 +7 -16
- package/dist/{logger-DsQC4OvA.js → logger-DixU80sg.js} +1 -1
- package/dist/logger.js +1 -1
- package/dist/{mcp-BQdv12mr.js → mcp-nXxiNurt.js} +15 -9
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +6 -6
- package/dist/pricing-fetcher-BY3-ryVq.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/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-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,
|
|
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 (
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
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
|
-
|
|
3172
|
+
unreachable(mode);
|
|
2839
3173
|
}
|
|
2840
3174
|
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,
|
|
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
|
-
|
|
3216
|
+
inputTokens: 0,
|
|
3217
|
+
outputTokens: 0,
|
|
3218
|
+
cacheCreationTokens: 0,
|
|
3219
|
+
cacheReadTokens: 0,
|
|
3220
|
+
totalCost: 0
|
|
2865
3221
|
});
|
|
2866
|
-
}
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
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
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
})
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
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
|
-
|
|
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());
|
|
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 =
|
|
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 };
|