ccusage 0.8.0 → 9.0.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 +25 -5
- package/dist/calculate-cost.d.ts +2 -2
- package/dist/chunk-BLXvPPr8.js +30 -0
- package/dist/{data-loader-Bz6Vemxw.js → data-loader-Ca8k_uX0.js} +235 -294
- package/dist/{data-loader-amTZCtBR.d.ts → data-loader-OGaMjZTD.d.ts} +8 -80
- package/dist/data-loader.d.ts +3 -3
- package/dist/data-loader.js +5 -5
- package/dist/{debug-DQXeZIjf.js → debug-zCcXwR8p.js} +5 -4
- package/dist/debug.js +5 -5
- package/dist/{dist-DAarI-SJ.js → dist-BZzwBtZs.js} +1 -1
- package/dist/{effect-WSjEuzC9-ChJ5OQQf.js → effect-WSjEuzC9-DHMVzzyB.js} +1 -1
- package/dist/{esm-Dqsc1zmX.js → esm-BU3FhOe-.js} +1 -1
- package/dist/{index-CISmcbXk-x9eVmhGM.js → index-CISmcbXk-CW1Gj6Ab.js} +5 -5
- package/dist/index.js +199 -1760
- package/dist/{logger-DN-RT9jL.js → logger-DKw-DPXD.js} +3 -3
- package/dist/logger.js +1 -1
- package/dist/{mcp-DZXbfmbs.js → mcp-BRFYI5rd.js} +42 -50
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +7 -7
- package/dist/{pricing-fetcher-Dq-OLBp4.d.ts → pricing-fetcher-BkSZh4lR.d.ts} +83 -3
- package/dist/pricing-fetcher-BlxDpqFj.js +205 -0
- package/dist/pricing-fetcher.d.ts +2 -2
- package/dist/pricing-fetcher.js +3 -3
- package/dist/{sury-DmrZ3_Oj-l0qqtY-f.js → sury-DmrZ3_Oj-Cpjsc2Lm.js} +1 -1
- package/dist/utils.table-DRzF8vZJ.js +1838 -0
- package/dist/utils.table.d.ts +24 -0
- package/dist/utils.table.js +3 -0
- package/dist/valibot-CQk-M5rL-BcaCeUrF.js +10 -0
- package/dist/{zod-Db63SLXj-N1oN-yiY.js → zod-Db63SLXj-BIXn64AP.js} +3 -3
- package/package.json +2 -1
- package/dist/pricing-fetcher-DMNBE90M.js +0 -79
- package/dist/valibot-CQk-M5rL-BNHzwpA0.js +0 -10
- /package/dist/{arktype-C-GObzDh-Bx7Fdrqj.js → arktype-C-GObzDh-CNoBqQrr.js} +0 -0
- /package/dist/{core-B0ovMhJe.js → core-DHCbAXJf.js} +0 -0
- /package/dist/{dist-BEQ1tJCL.js → dist-DCvt9hEv.js} +0 -0
- /package/dist/{prompt-CUbwSrjo.js → prompt-DtZgx4wU.js} +0 -0
- /package/dist/{types-DS8M8QF_.js → types-BlyCnKwN.js} +0 -0
|
@@ -1,39 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { readFile } from "node:fs/promises";
|
|
1
|
+
import { __commonJS, __require, __toESM } from "./chunk-BLXvPPr8.js";
|
|
2
|
+
import { array, number, object, optional, pipe, regex, safeParse, string } from "./dist-DCvt9hEv.js";
|
|
3
|
+
import { logger } from "./logger-DKw-DPXD.js";
|
|
4
|
+
import { PricingFetcher } from "./pricing-fetcher-BlxDpqFj.js";
|
|
5
|
+
import fsPromises, { readFile } from "node:fs/promises";
|
|
6
6
|
import { homedir } from "node:os";
|
|
7
7
|
import path from "node:path";
|
|
8
|
+
import process$1 from "node:process";
|
|
9
|
+
import fs from "node:fs";
|
|
8
10
|
import path$1, { posix } from "path";
|
|
9
11
|
|
|
10
|
-
//#region rolldown:runtime
|
|
11
|
-
var __create = Object.create;
|
|
12
|
-
var __defProp = Object.defineProperty;
|
|
13
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
14
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
15
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
16
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
17
|
-
var __commonJS = (cb, mod) => function() {
|
|
18
|
-
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
19
|
-
};
|
|
20
|
-
var __copyProps = (to, from, except, desc) => {
|
|
21
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
22
|
-
key = keys[i];
|
|
23
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
24
|
-
get: ((k) => from[k]).bind(null, key),
|
|
25
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
return to;
|
|
29
|
-
};
|
|
30
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
31
|
-
value: mod,
|
|
32
|
-
enumerable: true
|
|
33
|
-
}) : target, mod));
|
|
34
|
-
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
35
|
-
|
|
36
|
-
//#endregion
|
|
37
12
|
//#region node_modules/@jsr/core__unknownutil/is/string.js
|
|
38
13
|
/**
|
|
39
14
|
* Return `true` if the type of `x` is `string`.
|
|
@@ -289,6 +264,19 @@ function isObject$1(x) {
|
|
|
289
264
|
throw new UnreachableError(args);
|
|
290
265
|
}
|
|
291
266
|
|
|
267
|
+
//#endregion
|
|
268
|
+
//#region node_modules/es-toolkit/dist/array/groupBy.mjs
|
|
269
|
+
function groupBy(arr, getKeyFromItem) {
|
|
270
|
+
const result = {};
|
|
271
|
+
for (let i = 0; i < arr.length; i++) {
|
|
272
|
+
const item = arr[i];
|
|
273
|
+
const key = getKeyFromItem(item);
|
|
274
|
+
if (!Object.hasOwn(result, key)) result[key] = [];
|
|
275
|
+
result[key].push(item);
|
|
276
|
+
}
|
|
277
|
+
return result;
|
|
278
|
+
}
|
|
279
|
+
|
|
292
280
|
//#endregion
|
|
293
281
|
//#region node_modules/fast-sort/dist/sort.mjs
|
|
294
282
|
var castComparer = function(comparer) {
|
|
@@ -390,6 +378,34 @@ var inPlaceSort = createNewSortInstance({
|
|
|
390
378
|
inPlaceSorting: true
|
|
391
379
|
});
|
|
392
380
|
|
|
381
|
+
//#endregion
|
|
382
|
+
//#region node_modules/path-type/index.js
|
|
383
|
+
async function isType(fsStatType, statsMethodName, filePath) {
|
|
384
|
+
if (typeof filePath !== "string") throw new TypeError(`Expected a string, got ${typeof filePath}`);
|
|
385
|
+
try {
|
|
386
|
+
const stats = await fsPromises[fsStatType](filePath);
|
|
387
|
+
return stats[statsMethodName]();
|
|
388
|
+
} catch (error) {
|
|
389
|
+
if (error.code === "ENOENT") return false;
|
|
390
|
+
throw error;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
function isTypeSync(fsStatType, statsMethodName, filePath) {
|
|
394
|
+
if (typeof filePath !== "string") throw new TypeError(`Expected a string, got ${typeof filePath}`);
|
|
395
|
+
try {
|
|
396
|
+
return fs[fsStatType](filePath)[statsMethodName]();
|
|
397
|
+
} catch (error) {
|
|
398
|
+
if (error.code === "ENOENT") return false;
|
|
399
|
+
throw error;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
const isFile = isType.bind(void 0, "stat", "isFile");
|
|
403
|
+
const isDirectory = isType.bind(void 0, "stat", "isDirectory");
|
|
404
|
+
const isSymlink = isType.bind(void 0, "lstat", "isSymbolicLink");
|
|
405
|
+
const isFileSync = isTypeSync.bind(void 0, "statSync", "isFile");
|
|
406
|
+
const isDirectorySync = isTypeSync.bind(void 0, "statSync", "isDirectory");
|
|
407
|
+
const isSymlinkSync = isTypeSync.bind(void 0, "lstatSync", "isSymbolicLink");
|
|
408
|
+
|
|
393
409
|
//#endregion
|
|
394
410
|
//#region node_modules/fdir/dist/utils.js
|
|
395
411
|
var require_utils$1 = __commonJS({ "node_modules/fdir/dist/utils.js"(exports) {
|
|
@@ -2497,7 +2513,7 @@ var require_picomatch$1 = __commonJS({ "node_modules/picomatch/lib/picomatch.js"
|
|
|
2497
2513
|
* @api public
|
|
2498
2514
|
*/
|
|
2499
2515
|
picomatch$2.parse = (pattern, options) => {
|
|
2500
|
-
if (Array.isArray(pattern)) return pattern.map((p
|
|
2516
|
+
if (Array.isArray(pattern)) return pattern.map((p) => picomatch$2.parse(p, options));
|
|
2501
2517
|
return parse(pattern, {
|
|
2502
2518
|
...options,
|
|
2503
2519
|
fastpaths: false
|
|
@@ -2794,7 +2810,7 @@ var require_dist$1 = __commonJS({ "node_modules/fdir/dist/index.js"(exports) {
|
|
|
2794
2810
|
o[k2] = m[k];
|
|
2795
2811
|
});
|
|
2796
2812
|
var __exportStar = void 0 && (void 0).__exportStar || function(m, exports$1) {
|
|
2797
|
-
for (var p
|
|
2813
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports$1, p)) __createBinding(exports$1, m, p);
|
|
2798
2814
|
};
|
|
2799
2815
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2800
2816
|
exports.fdir = void 0;
|
|
@@ -2936,9 +2952,9 @@ function processPatterns({ patterns, ignore = [], expandDirectories = true }, cw
|
|
|
2936
2952
|
function getRelativePath(path$1$1, cwd, root) {
|
|
2937
2953
|
return posix.relative(cwd, `${root}/${path$1$1}`) || ".";
|
|
2938
2954
|
}
|
|
2939
|
-
function processPath(path$1$1, cwd, root, isDirectory, absolute) {
|
|
2955
|
+
function processPath(path$1$1, cwd, root, isDirectory$1, absolute) {
|
|
2940
2956
|
const relativePath = absolute ? path$1$1.slice(root === "/" ? 1 : root.length + 1) || "." : path$1$1;
|
|
2941
|
-
if (root === cwd) return isDirectory && relativePath !== "." ? relativePath.slice(0, -1) : relativePath;
|
|
2957
|
+
if (root === cwd) return isDirectory$1 && relativePath !== "." ? relativePath.slice(0, -1) : relativePath;
|
|
2942
2958
|
return getRelativePath(relativePath, cwd, root);
|
|
2943
2959
|
}
|
|
2944
2960
|
function formatPaths(paths, cwd, root) {
|
|
@@ -2974,20 +2990,20 @@ function crawl(options, cwd, sync$1) {
|
|
|
2974
2990
|
nocase
|
|
2975
2991
|
});
|
|
2976
2992
|
const fdirOptions = {
|
|
2977
|
-
filters: [options.debug ? (p
|
|
2978
|
-
const path$1$1 = processPath(p
|
|
2993
|
+
filters: [options.debug ? (p, isDirectory$1) => {
|
|
2994
|
+
const path$1$1 = processPath(p, cwd, props.root, isDirectory$1, options.absolute);
|
|
2979
2995
|
const matches = matcher(path$1$1);
|
|
2980
2996
|
if (matches) log(`matched ${path$1$1}`);
|
|
2981
2997
|
return matches;
|
|
2982
|
-
} : (p
|
|
2983
|
-
exclude: options.debug ? (_, p
|
|
2984
|
-
const relativePath = processPath(p
|
|
2998
|
+
} : (p, isDirectory$1) => matcher(processPath(p, cwd, props.root, isDirectory$1, options.absolute))],
|
|
2999
|
+
exclude: options.debug ? (_, p) => {
|
|
3000
|
+
const relativePath = processPath(p, cwd, props.root, true, true);
|
|
2985
3001
|
const skipped = relativePath !== "." && !partialMatcher(relativePath) || ignore(relativePath);
|
|
2986
|
-
if (skipped) log(`skipped ${p
|
|
2987
|
-
else log(`crawling ${p
|
|
3002
|
+
if (skipped) log(`skipped ${p}`);
|
|
3003
|
+
else log(`crawling ${p}`);
|
|
2988
3004
|
return skipped;
|
|
2989
|
-
} : (_, p
|
|
2990
|
-
const relativePath = processPath(p
|
|
3005
|
+
} : (_, p) => {
|
|
3006
|
+
const relativePath = processPath(p, cwd, props.root, true, true);
|
|
2991
3007
|
return relativePath !== "." && !partialMatcher(relativePath) || ignore(relativePath);
|
|
2992
3008
|
},
|
|
2993
3009
|
pathSeparator: "/",
|
|
@@ -3025,122 +3041,6 @@ async function glob(patternsOrOptions, options) {
|
|
|
3025
3041
|
return crawl(opts, cwd, false);
|
|
3026
3042
|
}
|
|
3027
3043
|
|
|
3028
|
-
//#endregion
|
|
3029
|
-
//#region node_modules/picocolors/picocolors.js
|
|
3030
|
-
var require_picocolors = __commonJS({ "node_modules/picocolors/picocolors.js"(exports, module) {
|
|
3031
|
-
let p = process || {}, argv = p.argv || [], env = p.env || {};
|
|
3032
|
-
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);
|
|
3033
|
-
let formatter = (open, close, replace = open) => (input) => {
|
|
3034
|
-
let string$1 = "" + input, index = string$1.indexOf(close, open.length);
|
|
3035
|
-
return ~index ? open + replaceClose(string$1, close, replace, index) + close : open + string$1 + close;
|
|
3036
|
-
};
|
|
3037
|
-
let replaceClose = (string$1, close, replace, index) => {
|
|
3038
|
-
let result = "", cursor = 0;
|
|
3039
|
-
do {
|
|
3040
|
-
result += string$1.substring(cursor, index) + replace;
|
|
3041
|
-
cursor = index + close.length;
|
|
3042
|
-
index = string$1.indexOf(close, cursor);
|
|
3043
|
-
} while (~index);
|
|
3044
|
-
return result + string$1.substring(cursor);
|
|
3045
|
-
};
|
|
3046
|
-
let createColors = (enabled = isColorSupported) => {
|
|
3047
|
-
let f = enabled ? formatter : () => String;
|
|
3048
|
-
return {
|
|
3049
|
-
isColorSupported: enabled,
|
|
3050
|
-
reset: f("\x1B[0m", "\x1B[0m"),
|
|
3051
|
-
bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
|
|
3052
|
-
dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
|
|
3053
|
-
italic: f("\x1B[3m", "\x1B[23m"),
|
|
3054
|
-
underline: f("\x1B[4m", "\x1B[24m"),
|
|
3055
|
-
inverse: f("\x1B[7m", "\x1B[27m"),
|
|
3056
|
-
hidden: f("\x1B[8m", "\x1B[28m"),
|
|
3057
|
-
strikethrough: f("\x1B[9m", "\x1B[29m"),
|
|
3058
|
-
black: f("\x1B[30m", "\x1B[39m"),
|
|
3059
|
-
red: f("\x1B[31m", "\x1B[39m"),
|
|
3060
|
-
green: f("\x1B[32m", "\x1B[39m"),
|
|
3061
|
-
yellow: f("\x1B[33m", "\x1B[39m"),
|
|
3062
|
-
blue: f("\x1B[34m", "\x1B[39m"),
|
|
3063
|
-
magenta: f("\x1B[35m", "\x1B[39m"),
|
|
3064
|
-
cyan: f("\x1B[36m", "\x1B[39m"),
|
|
3065
|
-
white: f("\x1B[37m", "\x1B[39m"),
|
|
3066
|
-
gray: f("\x1B[90m", "\x1B[39m"),
|
|
3067
|
-
bgBlack: f("\x1B[40m", "\x1B[49m"),
|
|
3068
|
-
bgRed: f("\x1B[41m", "\x1B[49m"),
|
|
3069
|
-
bgGreen: f("\x1B[42m", "\x1B[49m"),
|
|
3070
|
-
bgYellow: f("\x1B[43m", "\x1B[49m"),
|
|
3071
|
-
bgBlue: f("\x1B[44m", "\x1B[49m"),
|
|
3072
|
-
bgMagenta: f("\x1B[45m", "\x1B[49m"),
|
|
3073
|
-
bgCyan: f("\x1B[46m", "\x1B[49m"),
|
|
3074
|
-
bgWhite: f("\x1B[47m", "\x1B[49m"),
|
|
3075
|
-
blackBright: f("\x1B[90m", "\x1B[39m"),
|
|
3076
|
-
redBright: f("\x1B[91m", "\x1B[39m"),
|
|
3077
|
-
greenBright: f("\x1B[92m", "\x1B[39m"),
|
|
3078
|
-
yellowBright: f("\x1B[93m", "\x1B[39m"),
|
|
3079
|
-
blueBright: f("\x1B[94m", "\x1B[39m"),
|
|
3080
|
-
magentaBright: f("\x1B[95m", "\x1B[39m"),
|
|
3081
|
-
cyanBright: f("\x1B[96m", "\x1B[39m"),
|
|
3082
|
-
whiteBright: f("\x1B[97m", "\x1B[39m"),
|
|
3083
|
-
bgBlackBright: f("\x1B[100m", "\x1B[49m"),
|
|
3084
|
-
bgRedBright: f("\x1B[101m", "\x1B[49m"),
|
|
3085
|
-
bgGreenBright: f("\x1B[102m", "\x1B[49m"),
|
|
3086
|
-
bgYellowBright: f("\x1B[103m", "\x1B[49m"),
|
|
3087
|
-
bgBlueBright: f("\x1B[104m", "\x1B[49m"),
|
|
3088
|
-
bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
|
|
3089
|
-
bgCyanBright: f("\x1B[106m", "\x1B[49m"),
|
|
3090
|
-
bgWhiteBright: f("\x1B[107m", "\x1B[49m")
|
|
3091
|
-
};
|
|
3092
|
-
};
|
|
3093
|
-
module.exports = createColors();
|
|
3094
|
-
module.exports.createColors = createColors;
|
|
3095
|
-
} });
|
|
3096
|
-
|
|
3097
|
-
//#endregion
|
|
3098
|
-
//#region src/utils.internal.ts
|
|
3099
|
-
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
3100
|
-
function formatNumber(num) {
|
|
3101
|
-
return num.toLocaleString("en-US");
|
|
3102
|
-
}
|
|
3103
|
-
function formatCurrency(amount) {
|
|
3104
|
-
return `$${amount.toFixed(2)}`;
|
|
3105
|
-
}
|
|
3106
|
-
/**
|
|
3107
|
-
* WHY: Object.groupBy requires Node.js 21+. tsdown doesn't support runtime polyfills, only syntax transforms.
|
|
3108
|
-
*/
|
|
3109
|
-
function groupBy(array$1, keyFn) {
|
|
3110
|
-
return array$1.reduce((groups, item) => {
|
|
3111
|
-
const key = keyFn(item);
|
|
3112
|
-
if (groups[key] == null) groups[key] = [];
|
|
3113
|
-
groups[key].push(item);
|
|
3114
|
-
return groups;
|
|
3115
|
-
}, {});
|
|
3116
|
-
}
|
|
3117
|
-
function formatModelName(modelName) {
|
|
3118
|
-
const match = modelName.match(/claude-(\w+)-(\d+)-\d+/);
|
|
3119
|
-
if (match != null) return `${match[1]}-${match[2]}`;
|
|
3120
|
-
return modelName;
|
|
3121
|
-
}
|
|
3122
|
-
function formatModelsDisplay(models) {
|
|
3123
|
-
const uniqueModels = [...new Set(models.map(formatModelName))];
|
|
3124
|
-
return uniqueModels.sort().join(", ");
|
|
3125
|
-
}
|
|
3126
|
-
/**
|
|
3127
|
-
* Pushes model breakdown rows to a table
|
|
3128
|
-
* @param table - The table to push rows to
|
|
3129
|
-
* @param breakdowns - Array of model breakdowns
|
|
3130
|
-
* @param extraColumns - Number of extra empty columns before the data (default: 1 for models column)
|
|
3131
|
-
* @param trailingColumns - Number of extra empty columns after the data (default: 0)
|
|
3132
|
-
*/
|
|
3133
|
-
function pushBreakdownRows(table, breakdowns, extraColumns = 1, trailingColumns = 0) {
|
|
3134
|
-
for (const breakdown of breakdowns) {
|
|
3135
|
-
const row = [` └─ ${formatModelName(breakdown.modelName)}`];
|
|
3136
|
-
for (let i = 0; i < extraColumns; i++) row.push("");
|
|
3137
|
-
const totalTokens = breakdown.inputTokens + breakdown.outputTokens + breakdown.cacheCreationTokens + breakdown.cacheReadTokens;
|
|
3138
|
-
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)));
|
|
3139
|
-
for (let i = 0; i < trailingColumns; i++) row.push("");
|
|
3140
|
-
table.push(row);
|
|
3141
|
-
}
|
|
3142
|
-
}
|
|
3143
|
-
|
|
3144
3044
|
//#endregion
|
|
3145
3045
|
//#region node_modules/rolldown/node_modules/@oxc-project/runtime/src/helpers/usingCtx.js
|
|
3146
3046
|
var require_usingCtx = __commonJS({ "node_modules/rolldown/node_modules/@oxc-project/runtime/src/helpers/usingCtx.js"(exports, module) {
|
|
@@ -3204,8 +3104,17 @@ var require_usingCtx = __commonJS({ "node_modules/rolldown/node_modules/@oxc-pro
|
|
|
3204
3104
|
//#endregion
|
|
3205
3105
|
//#region src/data-loader.ts
|
|
3206
3106
|
var import_usingCtx = __toESM(require_usingCtx(), 1);
|
|
3107
|
+
const DEFAULT_CLAUDE_CODE_PATH = path.join(homedir(), ".claude");
|
|
3108
|
+
/**
|
|
3109
|
+
* Default path for Claude data directory
|
|
3110
|
+
* Uses environment variable CLAUDE_CONFIG_DIR if set, otherwise defaults to ~/.claude
|
|
3111
|
+
*/
|
|
3207
3112
|
function getDefaultClaudePath() {
|
|
3208
|
-
|
|
3113
|
+
const envClaudeCodePath = process$1.env.CLAUDE_CONFIG_DIR?.trim() ?? DEFAULT_CLAUDE_CODE_PATH;
|
|
3114
|
+
if (!isDirectorySync(envClaudeCodePath)) throw new Error(` Claude data directory does not exist: ${envClaudeCodePath}.
|
|
3115
|
+
Please set CLAUDE_CONFIG_DIR to a valid path, or ensure ${DEFAULT_CLAUDE_CODE_PATH} exists.
|
|
3116
|
+
`.trim());
|
|
3117
|
+
return envClaudeCodePath;
|
|
3209
3118
|
}
|
|
3210
3119
|
const UsageDataSchema = object({
|
|
3211
3120
|
timestamp: string(),
|
|
@@ -3264,6 +3173,123 @@ const MonthlyUsageSchema = object({
|
|
|
3264
3173
|
modelsUsed: array(string()),
|
|
3265
3174
|
modelBreakdowns: array(ModelBreakdownSchema)
|
|
3266
3175
|
});
|
|
3176
|
+
/**
|
|
3177
|
+
* Aggregates token counts and costs by model name
|
|
3178
|
+
*/
|
|
3179
|
+
function aggregateByModel(entries, getModel, getUsage, getCost) {
|
|
3180
|
+
const modelAggregates = /* @__PURE__ */ new Map();
|
|
3181
|
+
const defaultStats = {
|
|
3182
|
+
inputTokens: 0,
|
|
3183
|
+
outputTokens: 0,
|
|
3184
|
+
cacheCreationTokens: 0,
|
|
3185
|
+
cacheReadTokens: 0,
|
|
3186
|
+
cost: 0
|
|
3187
|
+
};
|
|
3188
|
+
for (const entry of entries) {
|
|
3189
|
+
const modelName = getModel(entry) ?? "unknown";
|
|
3190
|
+
if (modelName === "<synthetic>") continue;
|
|
3191
|
+
const usage = getUsage(entry);
|
|
3192
|
+
const cost = getCost(entry);
|
|
3193
|
+
const existing = modelAggregates.get(modelName) ?? defaultStats;
|
|
3194
|
+
modelAggregates.set(modelName, {
|
|
3195
|
+
inputTokens: existing.inputTokens + (usage.input_tokens ?? 0),
|
|
3196
|
+
outputTokens: existing.outputTokens + (usage.output_tokens ?? 0),
|
|
3197
|
+
cacheCreationTokens: existing.cacheCreationTokens + (usage.cache_creation_input_tokens ?? 0),
|
|
3198
|
+
cacheReadTokens: existing.cacheReadTokens + (usage.cache_read_input_tokens ?? 0),
|
|
3199
|
+
cost: existing.cost + cost
|
|
3200
|
+
});
|
|
3201
|
+
}
|
|
3202
|
+
return modelAggregates;
|
|
3203
|
+
}
|
|
3204
|
+
/**
|
|
3205
|
+
* Aggregates model breakdowns from multiple sources
|
|
3206
|
+
*/
|
|
3207
|
+
function aggregateModelBreakdowns(breakdowns) {
|
|
3208
|
+
const modelAggregates = /* @__PURE__ */ new Map();
|
|
3209
|
+
const defaultStats = {
|
|
3210
|
+
inputTokens: 0,
|
|
3211
|
+
outputTokens: 0,
|
|
3212
|
+
cacheCreationTokens: 0,
|
|
3213
|
+
cacheReadTokens: 0,
|
|
3214
|
+
cost: 0
|
|
3215
|
+
};
|
|
3216
|
+
for (const breakdown of breakdowns) {
|
|
3217
|
+
if (breakdown.modelName === "<synthetic>") continue;
|
|
3218
|
+
const existing = modelAggregates.get(breakdown.modelName) ?? defaultStats;
|
|
3219
|
+
modelAggregates.set(breakdown.modelName, {
|
|
3220
|
+
inputTokens: existing.inputTokens + breakdown.inputTokens,
|
|
3221
|
+
outputTokens: existing.outputTokens + breakdown.outputTokens,
|
|
3222
|
+
cacheCreationTokens: existing.cacheCreationTokens + breakdown.cacheCreationTokens,
|
|
3223
|
+
cacheReadTokens: existing.cacheReadTokens + breakdown.cacheReadTokens,
|
|
3224
|
+
cost: existing.cost + breakdown.cost
|
|
3225
|
+
});
|
|
3226
|
+
}
|
|
3227
|
+
return modelAggregates;
|
|
3228
|
+
}
|
|
3229
|
+
/**
|
|
3230
|
+
* Converts model aggregates to sorted model breakdowns
|
|
3231
|
+
*/
|
|
3232
|
+
function createModelBreakdowns(modelAggregates) {
|
|
3233
|
+
return Array.from(modelAggregates.entries()).map(([modelName, stats]) => ({
|
|
3234
|
+
modelName,
|
|
3235
|
+
...stats
|
|
3236
|
+
})).sort((a, b) => b.cost - a.cost);
|
|
3237
|
+
}
|
|
3238
|
+
/**
|
|
3239
|
+
* Calculates total token counts and costs from entries
|
|
3240
|
+
*/
|
|
3241
|
+
function calculateTotals(entries, getUsage, getCost) {
|
|
3242
|
+
return entries.reduce((acc, entry) => {
|
|
3243
|
+
const usage = getUsage(entry);
|
|
3244
|
+
const cost = getCost(entry);
|
|
3245
|
+
return {
|
|
3246
|
+
inputTokens: acc.inputTokens + (usage.input_tokens ?? 0),
|
|
3247
|
+
outputTokens: acc.outputTokens + (usage.output_tokens ?? 0),
|
|
3248
|
+
cacheCreationTokens: acc.cacheCreationTokens + (usage.cache_creation_input_tokens ?? 0),
|
|
3249
|
+
cacheReadTokens: acc.cacheReadTokens + (usage.cache_read_input_tokens ?? 0),
|
|
3250
|
+
cost: acc.cost + cost,
|
|
3251
|
+
totalCost: acc.totalCost + cost
|
|
3252
|
+
};
|
|
3253
|
+
}, {
|
|
3254
|
+
inputTokens: 0,
|
|
3255
|
+
outputTokens: 0,
|
|
3256
|
+
cacheCreationTokens: 0,
|
|
3257
|
+
cacheReadTokens: 0,
|
|
3258
|
+
cost: 0,
|
|
3259
|
+
totalCost: 0
|
|
3260
|
+
});
|
|
3261
|
+
}
|
|
3262
|
+
/**
|
|
3263
|
+
* Filters items by date range
|
|
3264
|
+
*/
|
|
3265
|
+
function filterByDateRange(items, getDate, since, until) {
|
|
3266
|
+
if (since == null && until == null) return items;
|
|
3267
|
+
return items.filter((item) => {
|
|
3268
|
+
const dateStr = getDate(item).substring(0, 10).replace(/-/g, "");
|
|
3269
|
+
if (since != null && dateStr < since) return false;
|
|
3270
|
+
if (until != null && dateStr > until) return false;
|
|
3271
|
+
return true;
|
|
3272
|
+
});
|
|
3273
|
+
}
|
|
3274
|
+
/**
|
|
3275
|
+
* Checks if an entry is a duplicate based on hash
|
|
3276
|
+
*/
|
|
3277
|
+
function isDuplicateEntry(uniqueHash, processedHashes) {
|
|
3278
|
+
if (uniqueHash == null) return false;
|
|
3279
|
+
return processedHashes.has(uniqueHash);
|
|
3280
|
+
}
|
|
3281
|
+
/**
|
|
3282
|
+
* Marks an entry as processed
|
|
3283
|
+
*/
|
|
3284
|
+
function markAsProcessed(uniqueHash, processedHashes) {
|
|
3285
|
+
if (uniqueHash != null) processedHashes.add(uniqueHash);
|
|
3286
|
+
}
|
|
3287
|
+
/**
|
|
3288
|
+
* Extracts unique models from entries, excluding synthetic model
|
|
3289
|
+
*/
|
|
3290
|
+
function extractUniqueModels(entries, getModel) {
|
|
3291
|
+
return [...new Set(entries.map(getModel).filter((m) => m != null && m !== "<synthetic>"))];
|
|
3292
|
+
}
|
|
3267
3293
|
function formatDate(dateStr) {
|
|
3268
3294
|
const date = new Date(dateStr);
|
|
3269
3295
|
const year = date.getFullYear();
|
|
@@ -3271,6 +3297,28 @@ function formatDate(dateStr) {
|
|
|
3271
3297
|
const day = String(date.getDate()).padStart(2, "0");
|
|
3272
3298
|
return `${year}-${month}-${day}`;
|
|
3273
3299
|
}
|
|
3300
|
+
function formatDateCompact(dateStr) {
|
|
3301
|
+
const date = new Date(dateStr);
|
|
3302
|
+
const year = date.getFullYear();
|
|
3303
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
3304
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
3305
|
+
return `${year}\n${month}-${day}`;
|
|
3306
|
+
}
|
|
3307
|
+
/**
|
|
3308
|
+
* Generic function to sort items by date based on sort order
|
|
3309
|
+
* @param items - Array of items to sort
|
|
3310
|
+
* @param getDate - Function to extract date/timestamp from item
|
|
3311
|
+
* @param order - Sort order (asc or desc)
|
|
3312
|
+
* @returns Sorted array
|
|
3313
|
+
*/
|
|
3314
|
+
function sortByDate(items, getDate, order = "desc") {
|
|
3315
|
+
const sorted = sort(items);
|
|
3316
|
+
switch (order) {
|
|
3317
|
+
case "desc": return sorted.desc((item) => new Date(getDate(item)).getTime());
|
|
3318
|
+
case "asc": return sorted.asc((item) => new Date(getDate(item)).getTime());
|
|
3319
|
+
default: unreachable(order);
|
|
3320
|
+
}
|
|
3321
|
+
}
|
|
3274
3322
|
/**
|
|
3275
3323
|
* Create a unique identifier for deduplication using message ID and request ID
|
|
3276
3324
|
*/
|
|
@@ -3350,7 +3398,7 @@ async function loadDailyUsageData(options) {
|
|
|
3350
3398
|
if (files.length === 0) return [];
|
|
3351
3399
|
const sortedFiles = await sortFilesByTimestamp(files);
|
|
3352
3400
|
const mode = options?.mode ?? "auto";
|
|
3353
|
-
const fetcher = _usingCtx$1.u(mode === "display" ? null : new PricingFetcher());
|
|
3401
|
+
const fetcher = _usingCtx$1.u(mode === "display" ? null : new PricingFetcher(options?.offline));
|
|
3354
3402
|
const processedHashes = /* @__PURE__ */ new Set();
|
|
3355
3403
|
const allEntries = [];
|
|
3356
3404
|
for (const file of sortedFiles) {
|
|
@@ -3362,8 +3410,8 @@ async function loadDailyUsageData(options) {
|
|
|
3362
3410
|
if (!result.success) continue;
|
|
3363
3411
|
const data = result.output;
|
|
3364
3412
|
const uniqueHash = createUniqueHash(data);
|
|
3365
|
-
if (uniqueHash
|
|
3366
|
-
|
|
3413
|
+
if (isDuplicateEntry(uniqueHash, processedHashes)) continue;
|
|
3414
|
+
markAsProcessed(uniqueHash, processedHashes);
|
|
3367
3415
|
const date = formatDate(data.timestamp);
|
|
3368
3416
|
const cost = fetcher != null ? await calculateCostForEntry(data, mode, fetcher) : data.costUSD ?? 0;
|
|
3369
3417
|
allEntries.push({
|
|
@@ -3377,64 +3425,19 @@ async function loadDailyUsageData(options) {
|
|
|
3377
3425
|
const groupedByDate = groupBy(allEntries, (entry) => entry.date);
|
|
3378
3426
|
const results = Object.entries(groupedByDate).map(([date, entries]) => {
|
|
3379
3427
|
if (entries == null) return void 0;
|
|
3380
|
-
const modelAggregates =
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
const existing = modelAggregates.get(modelName) ?? {
|
|
3385
|
-
inputTokens: 0,
|
|
3386
|
-
outputTokens: 0,
|
|
3387
|
-
cacheCreationTokens: 0,
|
|
3388
|
-
cacheReadTokens: 0,
|
|
3389
|
-
cost: 0
|
|
3390
|
-
};
|
|
3391
|
-
modelAggregates.set(modelName, {
|
|
3392
|
-
inputTokens: existing.inputTokens + (entry.data.message.usage.input_tokens ?? 0),
|
|
3393
|
-
outputTokens: existing.outputTokens + (entry.data.message.usage.output_tokens ?? 0),
|
|
3394
|
-
cacheCreationTokens: existing.cacheCreationTokens + (entry.data.message.usage.cache_creation_input_tokens ?? 0),
|
|
3395
|
-
cacheReadTokens: existing.cacheReadTokens + (entry.data.message.usage.cache_read_input_tokens ?? 0),
|
|
3396
|
-
cost: existing.cost + entry.cost
|
|
3397
|
-
});
|
|
3398
|
-
}
|
|
3399
|
-
const modelBreakdowns = Array.from(modelAggregates.entries()).map(([modelName, stats]) => ({
|
|
3400
|
-
modelName,
|
|
3401
|
-
...stats
|
|
3402
|
-
})).sort((a, b) => b.cost - a.cost);
|
|
3403
|
-
const totals = entries.reduce((acc, entry) => ({
|
|
3404
|
-
inputTokens: acc.inputTokens + (entry.data.message.usage.input_tokens ?? 0),
|
|
3405
|
-
outputTokens: acc.outputTokens + (entry.data.message.usage.output_tokens ?? 0),
|
|
3406
|
-
cacheCreationTokens: acc.cacheCreationTokens + (entry.data.message.usage.cache_creation_input_tokens ?? 0),
|
|
3407
|
-
cacheReadTokens: acc.cacheReadTokens + (entry.data.message.usage.cache_read_input_tokens ?? 0),
|
|
3408
|
-
totalCost: acc.totalCost + entry.cost
|
|
3409
|
-
}), {
|
|
3410
|
-
inputTokens: 0,
|
|
3411
|
-
outputTokens: 0,
|
|
3412
|
-
cacheCreationTokens: 0,
|
|
3413
|
-
cacheReadTokens: 0,
|
|
3414
|
-
totalCost: 0
|
|
3415
|
-
});
|
|
3416
|
-
const modelsUsed = [...new Set(entries.map((e) => e.model).filter((m) => m != null && m !== "<synthetic>"))];
|
|
3428
|
+
const modelAggregates = aggregateByModel(entries, (entry) => entry.model, (entry) => entry.data.message.usage, (entry) => entry.cost);
|
|
3429
|
+
const modelBreakdowns = createModelBreakdowns(modelAggregates);
|
|
3430
|
+
const totals = calculateTotals(entries, (entry) => entry.data.message.usage, (entry) => entry.cost);
|
|
3431
|
+
const modelsUsed = extractUniqueModels(entries, (e) => e.model);
|
|
3417
3432
|
return {
|
|
3418
3433
|
date,
|
|
3419
3434
|
...totals,
|
|
3420
3435
|
modelsUsed,
|
|
3421
3436
|
modelBreakdowns
|
|
3422
3437
|
};
|
|
3423
|
-
}).filter((item) => item != null)
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
if (options.since != null && dateStr < options.since) return false;
|
|
3427
|
-
if (options.until != null && dateStr > options.until) return false;
|
|
3428
|
-
}
|
|
3429
|
-
return true;
|
|
3430
|
-
});
|
|
3431
|
-
const sortOrder = options?.order ?? "desc";
|
|
3432
|
-
const sortedResults = sort(results);
|
|
3433
|
-
switch (sortOrder) {
|
|
3434
|
-
case "desc": return sortedResults.desc((item) => new Date(item.date).getTime());
|
|
3435
|
-
case "asc": return sortedResults.asc((item) => new Date(item.date).getTime());
|
|
3436
|
-
default: unreachable(sortOrder);
|
|
3437
|
-
}
|
|
3438
|
+
}).filter((item) => item != null);
|
|
3439
|
+
const filtered = filterByDateRange(results, (item) => item.date, options?.since, options?.until);
|
|
3440
|
+
return sortByDate(filtered, (item) => item.date, options?.order);
|
|
3438
3441
|
} catch (_) {
|
|
3439
3442
|
_usingCtx$1.e = _;
|
|
3440
3443
|
} finally {
|
|
@@ -3453,7 +3456,7 @@ async function loadSessionData(options) {
|
|
|
3453
3456
|
if (files.length === 0) return [];
|
|
3454
3457
|
const sortedFiles = await sortFilesByTimestamp(files);
|
|
3455
3458
|
const mode = options?.mode ?? "auto";
|
|
3456
|
-
const fetcher = _usingCtx3.u(mode === "display" ? null : new PricingFetcher());
|
|
3459
|
+
const fetcher = _usingCtx3.u(mode === "display" ? null : new PricingFetcher(options?.offline));
|
|
3457
3460
|
const processedHashes = /* @__PURE__ */ new Set();
|
|
3458
3461
|
const allEntries = [];
|
|
3459
3462
|
for (const file of sortedFiles) {
|
|
@@ -3470,8 +3473,8 @@ async function loadSessionData(options) {
|
|
|
3470
3473
|
if (!result.success) continue;
|
|
3471
3474
|
const data = result.output;
|
|
3472
3475
|
const uniqueHash = createUniqueHash(data);
|
|
3473
|
-
if (uniqueHash
|
|
3474
|
-
|
|
3476
|
+
if (isDuplicateEntry(uniqueHash, processedHashes)) continue;
|
|
3477
|
+
markAsProcessed(uniqueHash, processedHashes);
|
|
3475
3478
|
const sessionKey = `${projectPath}/${sessionId}`;
|
|
3476
3479
|
const cost = fetcher != null ? await calculateCostForEntry(data, mode, fetcher) : data.costUSD ?? 0;
|
|
3477
3480
|
allEntries.push({
|
|
@@ -3491,43 +3494,10 @@ async function loadSessionData(options) {
|
|
|
3491
3494
|
const latestEntry = entries.reduce((latest, current) => current.timestamp > latest.timestamp ? current : latest);
|
|
3492
3495
|
const versionSet = /* @__PURE__ */ new Set();
|
|
3493
3496
|
for (const entry of entries) if (entry.data.version != null) versionSet.add(entry.data.version);
|
|
3494
|
-
const modelAggregates =
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
const existing = modelAggregates.get(modelName) ?? {
|
|
3499
|
-
inputTokens: 0,
|
|
3500
|
-
outputTokens: 0,
|
|
3501
|
-
cacheCreationTokens: 0,
|
|
3502
|
-
cacheReadTokens: 0,
|
|
3503
|
-
cost: 0
|
|
3504
|
-
};
|
|
3505
|
-
modelAggregates.set(modelName, {
|
|
3506
|
-
inputTokens: existing.inputTokens + (entry.data.message.usage.input_tokens ?? 0),
|
|
3507
|
-
outputTokens: existing.outputTokens + (entry.data.message.usage.output_tokens ?? 0),
|
|
3508
|
-
cacheCreationTokens: existing.cacheCreationTokens + (entry.data.message.usage.cache_creation_input_tokens ?? 0),
|
|
3509
|
-
cacheReadTokens: existing.cacheReadTokens + (entry.data.message.usage.cache_read_input_tokens ?? 0),
|
|
3510
|
-
cost: existing.cost + entry.cost
|
|
3511
|
-
});
|
|
3512
|
-
}
|
|
3513
|
-
const modelBreakdowns = Array.from(modelAggregates.entries()).map(([modelName, stats]) => ({
|
|
3514
|
-
modelName,
|
|
3515
|
-
...stats
|
|
3516
|
-
})).sort((a, b) => b.cost - a.cost);
|
|
3517
|
-
const totals = entries.reduce((acc, entry) => ({
|
|
3518
|
-
inputTokens: acc.inputTokens + (entry.data.message.usage.input_tokens ?? 0),
|
|
3519
|
-
outputTokens: acc.outputTokens + (entry.data.message.usage.output_tokens ?? 0),
|
|
3520
|
-
cacheCreationTokens: acc.cacheCreationTokens + (entry.data.message.usage.cache_creation_input_tokens ?? 0),
|
|
3521
|
-
cacheReadTokens: acc.cacheReadTokens + (entry.data.message.usage.cache_read_input_tokens ?? 0),
|
|
3522
|
-
totalCost: acc.totalCost + entry.cost
|
|
3523
|
-
}), {
|
|
3524
|
-
inputTokens: 0,
|
|
3525
|
-
outputTokens: 0,
|
|
3526
|
-
cacheCreationTokens: 0,
|
|
3527
|
-
cacheReadTokens: 0,
|
|
3528
|
-
totalCost: 0
|
|
3529
|
-
});
|
|
3530
|
-
const modelsUsed = [...new Set(entries.map((e) => e.model).filter((m) => m != null && m !== "<synthetic>"))];
|
|
3497
|
+
const modelAggregates = aggregateByModel(entries, (entry) => entry.model, (entry) => entry.data.message.usage, (entry) => entry.cost);
|
|
3498
|
+
const modelBreakdowns = createModelBreakdowns(modelAggregates);
|
|
3499
|
+
const totals = calculateTotals(entries, (entry) => entry.data.message.usage, (entry) => entry.cost);
|
|
3500
|
+
const modelsUsed = extractUniqueModels(entries, (e) => e.model);
|
|
3531
3501
|
return {
|
|
3532
3502
|
sessionId: latestEntry.sessionId,
|
|
3533
3503
|
projectPath: latestEntry.projectPath,
|
|
@@ -3537,17 +3507,9 @@ async function loadSessionData(options) {
|
|
|
3537
3507
|
modelsUsed,
|
|
3538
3508
|
modelBreakdowns
|
|
3539
3509
|
};
|
|
3540
|
-
}).filter((item) => item != null)
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
if (options.since != null && dateStr < options.since) return false;
|
|
3544
|
-
if (options.until != null && dateStr > options.until) return false;
|
|
3545
|
-
}
|
|
3546
|
-
return true;
|
|
3547
|
-
});
|
|
3548
|
-
const sortOrder = options?.order ?? "desc";
|
|
3549
|
-
const sortedResults = sort(results);
|
|
3550
|
-
return sortOrder === "desc" ? sortedResults.desc((item) => new Date(item.lastActivity).getTime()) : sortedResults.asc((item) => new Date(item.lastActivity).getTime());
|
|
3510
|
+
}).filter((item) => item != null);
|
|
3511
|
+
const filtered = filterByDateRange(results, (item) => item.lastActivity, options?.since, options?.until);
|
|
3512
|
+
return sortByDate(filtered, (item) => item.lastActivity, options?.order);
|
|
3551
3513
|
} catch (_) {
|
|
3552
3514
|
_usingCtx3.e = _;
|
|
3553
3515
|
} finally {
|
|
@@ -3560,28 +3522,9 @@ async function loadMonthlyUsageData(options) {
|
|
|
3560
3522
|
const monthlyArray = [];
|
|
3561
3523
|
for (const [month, dailyEntries] of Object.entries(groupedByMonth)) {
|
|
3562
3524
|
if (dailyEntries == null) continue;
|
|
3563
|
-
const
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
const existing = modelAggregates.get(breakdown.modelName) ?? {
|
|
3567
|
-
inputTokens: 0,
|
|
3568
|
-
outputTokens: 0,
|
|
3569
|
-
cacheCreationTokens: 0,
|
|
3570
|
-
cacheReadTokens: 0,
|
|
3571
|
-
cost: 0
|
|
3572
|
-
};
|
|
3573
|
-
modelAggregates.set(breakdown.modelName, {
|
|
3574
|
-
inputTokens: existing.inputTokens + breakdown.inputTokens,
|
|
3575
|
-
outputTokens: existing.outputTokens + breakdown.outputTokens,
|
|
3576
|
-
cacheCreationTokens: existing.cacheCreationTokens + breakdown.cacheCreationTokens,
|
|
3577
|
-
cacheReadTokens: existing.cacheReadTokens + breakdown.cacheReadTokens,
|
|
3578
|
-
cost: existing.cost + breakdown.cost
|
|
3579
|
-
});
|
|
3580
|
-
}
|
|
3581
|
-
const modelBreakdowns = Array.from(modelAggregates.entries()).map(([modelName, stats]) => ({
|
|
3582
|
-
modelName,
|
|
3583
|
-
...stats
|
|
3584
|
-
})).sort((a, b) => b.cost - a.cost);
|
|
3525
|
+
const allBreakdowns = dailyEntries.flatMap((daily) => daily.modelBreakdowns);
|
|
3526
|
+
const modelAggregates = aggregateModelBreakdowns(allBreakdowns);
|
|
3527
|
+
const modelBreakdowns = createModelBreakdowns(modelAggregates);
|
|
3585
3528
|
const modelsSet = /* @__PURE__ */ new Set();
|
|
3586
3529
|
for (const data of dailyEntries) for (const model of data.modelsUsed) if (model !== "<synthetic>") modelsSet.add(model);
|
|
3587
3530
|
let totalInputTokens = 0;
|
|
@@ -3608,10 +3551,8 @@ async function loadMonthlyUsageData(options) {
|
|
|
3608
3551
|
};
|
|
3609
3552
|
monthlyArray.push(monthlyUsage);
|
|
3610
3553
|
}
|
|
3611
|
-
|
|
3612
|
-
const sortedMonthly = sort(monthlyArray);
|
|
3613
|
-
return sortOrder === "desc" ? sortedMonthly.desc((item) => item.month) : sortedMonthly.asc((item) => item.month);
|
|
3554
|
+
return sortByDate(monthlyArray, (item) => `${item.month}-01`, options?.order);
|
|
3614
3555
|
}
|
|
3615
3556
|
|
|
3616
3557
|
//#endregion
|
|
3617
|
-
export { DailyUsageSchema, ModelBreakdownSchema, MonthlyUsageSchema, SessionUsageSchema, UsageDataSchema,
|
|
3558
|
+
export { DailyUsageSchema, ModelBreakdownSchema, MonthlyUsageSchema, SessionUsageSchema, UsageDataSchema, calculateCostForEntry, createUniqueHash, formatDate, formatDateCompact, getDefaultClaudePath, getEarliestTimestamp, glob, loadDailyUsageData, loadMonthlyUsageData, loadSessionData, require_usingCtx, sortFilesByTimestamp };
|