ccusage 12.3.2 → 12.4.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/dist/calculate-cost.d.ts +2 -2
- package/dist/calculate-cost.js +2 -1
- package/dist/{data-loader-i0_91kbD.js → data-loader-BL0D1ClF.js} +46 -50
- package/dist/{data-loader-CBwn9vk0.d.ts → data-loader-BrxITdVN.d.ts} +42 -42
- package/dist/data-loader.d.ts +2 -2
- package/dist/data-loader.js +4 -3
- package/dist/{debug-DUZvOm08.js → debug-DzMUvq_R.js} +6 -11
- package/dist/debug.js +5 -4
- package/dist/index.js +16 -31
- package/dist/{logger-BfzGx5lS.js → logger-Cyt2-axs.js} +2 -2
- package/dist/logger.js +1 -1
- package/dist/{mcp-Bx-_DNLG.js → mcp-Cx7Vxuva.js} +4 -3
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +5 -4
- package/dist/pricing-fetcher-5y05qfeL.js +365 -0
- package/dist/{pricing-fetcher-BkOpRIdx.d.ts → pricing-fetcher-A6FC8DhM.d.ts} +1 -0
- package/dist/pricing-fetcher.d.ts +1 -1
- package/dist/pricing-fetcher.js +3 -2
- package/dist/{pricing-fetcher-mFPZYGXl.js → types.internal-CX7kpidj.js} +19 -312
- package/package.json +1 -1
- /package/dist/{calculate-cost-D3IraeGW.js → calculate-cost-CoS7we68.js} +0 -0
- /package/dist/{prompt-E8j7mEMw.js → prompt-j5YimnLx.js} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
2
|
+
import { BLOCKS_COMPACT_WIDTH_THRESHOLD, BLOCKS_DEFAULT_TERMINAL_WIDTH, BLOCKS_WARNING_THRESHOLD, DEFAULT_RECENT_DAYS, MCP_DEFAULT_PORT, __commonJSMin, __require, __toESM } from "./pricing-fetcher-5y05qfeL.js";
|
|
3
|
+
import { CostModes, SortOrders, dateSchema } from "./types.internal-CX7kpidj.js";
|
|
4
|
+
import { calculateTotals, createTotalsObject, getTotalTokens } from "./calculate-cost-CoS7we68.js";
|
|
5
|
+
import { DEFAULT_SESSION_DURATION_HOURS, calculateBurnRate, filterRecentBlocks, formatDateCompact, getDefaultClaudePath, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, projectBlockUsage, uniq } from "./data-loader-BL0D1ClF.js";
|
|
6
|
+
import { description, log, logger, name, version } from "./logger-Cyt2-axs.js";
|
|
7
|
+
import { detectMismatches, printMismatchReport } from "./debug-DzMUvq_R.js";
|
|
8
|
+
import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-Cx7Vxuva.js";
|
|
8
9
|
import process$1 from "node:process";
|
|
9
10
|
import { createServer } from "node:http";
|
|
10
11
|
import { Http2ServerRequest } from "node:http2";
|
|
@@ -3078,7 +3079,7 @@ function formatModelName(modelName) {
|
|
|
3078
3079
|
* @returns Formatted string with unique, sorted model names separated by commas
|
|
3079
3080
|
*/
|
|
3080
3081
|
function formatModelsDisplay(models) {
|
|
3081
|
-
const uniqueModels =
|
|
3082
|
+
const uniqueModels = uniq(models.map(formatModelName));
|
|
3082
3083
|
return uniqueModels.sort().join(", ");
|
|
3083
3084
|
}
|
|
3084
3085
|
/**
|
|
@@ -3101,22 +3102,6 @@ function pushBreakdownRows(table, breakdowns, extraColumns = 1, trailingColumns
|
|
|
3101
3102
|
}
|
|
3102
3103
|
var import_picocolors$3 = __toESM(require_picocolors(), 1);
|
|
3103
3104
|
/**
|
|
3104
|
-
* Default number of recent days to show in blocks view
|
|
3105
|
-
*/
|
|
3106
|
-
const RECENT_DAYS_DEFAULT = 3;
|
|
3107
|
-
/**
|
|
3108
|
-
* Threshold percentage for showing usage warnings (80%)
|
|
3109
|
-
*/
|
|
3110
|
-
const WARNING_THRESHOLD = .8;
|
|
3111
|
-
/**
|
|
3112
|
-
* Terminal width threshold for switching to compact display mode
|
|
3113
|
-
*/
|
|
3114
|
-
const COMPACT_WIDTH_THRESHOLD = 120;
|
|
3115
|
-
/**
|
|
3116
|
-
* Default terminal width when stdout.columns is not available
|
|
3117
|
-
*/
|
|
3118
|
-
const DEFAULT_TERMINAL_WIDTH = 120;
|
|
3119
|
-
/**
|
|
3120
3105
|
* Formats the time display for a session block
|
|
3121
3106
|
* @param block - Session block to format
|
|
3122
3107
|
* @param compact - Whether to use compact formatting for narrow terminals
|
|
@@ -3191,7 +3176,7 @@ const blocksCommand = define({
|
|
|
3191
3176
|
recent: {
|
|
3192
3177
|
type: "boolean",
|
|
3193
3178
|
short: "r",
|
|
3194
|
-
description: `Show blocks from last ${
|
|
3179
|
+
description: `Show blocks from last ${DEFAULT_RECENT_DAYS} days (including active)`,
|
|
3195
3180
|
default: false
|
|
3196
3181
|
},
|
|
3197
3182
|
tokenLimit: {
|
|
@@ -3234,7 +3219,7 @@ const blocksCommand = define({
|
|
|
3234
3219
|
}
|
|
3235
3220
|
if (!ctx.values.json && maxTokensFromAll > 0) logger.info(`Using max tokens from previous sessions: ${formatNumber(maxTokensFromAll)}`);
|
|
3236
3221
|
}
|
|
3237
|
-
if (ctx.values.recent) blocks = filterRecentBlocks(blocks,
|
|
3222
|
+
if (ctx.values.recent) blocks = filterRecentBlocks(blocks, DEFAULT_RECENT_DAYS);
|
|
3238
3223
|
if (ctx.values.active) {
|
|
3239
3224
|
blocks = blocks.filter((block) => block.isActive);
|
|
3240
3225
|
if (blocks.length === 0) {
|
|
@@ -3270,7 +3255,7 @@ const blocksCommand = define({
|
|
|
3270
3255
|
limit,
|
|
3271
3256
|
projectedUsage: projection.totalTokens,
|
|
3272
3257
|
percentUsed: projection.totalTokens / limit * 100,
|
|
3273
|
-
status: projection.totalTokens > limit ? "exceeds" : projection.totalTokens > limit *
|
|
3258
|
+
status: projection.totalTokens > limit ? "exceeds" : projection.totalTokens > limit * BLOCKS_WARNING_THRESHOLD ? "warning" : "ok"
|
|
3274
3259
|
} : void 0;
|
|
3275
3260
|
})() : void 0
|
|
3276
3261
|
};
|
|
@@ -3309,7 +3294,7 @@ const blocksCommand = define({
|
|
|
3309
3294
|
const currentTokens = block.tokenCounts.inputTokens + block.tokenCounts.outputTokens;
|
|
3310
3295
|
const remainingTokens = Math.max(0, limit - currentTokens);
|
|
3311
3296
|
const percentUsed = projection.totalTokens / limit * 100;
|
|
3312
|
-
const status = percentUsed > 100 ? import_picocolors$3.default.red("EXCEEDS LIMIT") : percentUsed >
|
|
3297
|
+
const status = percentUsed > 100 ? import_picocolors$3.default.red("EXCEEDS LIMIT") : percentUsed > BLOCKS_WARNING_THRESHOLD * 100 ? import_picocolors$3.default.yellow("WARNING") : import_picocolors$3.default.green("OK");
|
|
3313
3298
|
log(import_picocolors$3.default.bold("Token Limit Status:"));
|
|
3314
3299
|
log(` Limit: ${formatNumber(limit)} tokens`);
|
|
3315
3300
|
log(` Current Usage: ${formatNumber(currentTokens)} (${(currentTokens / limit * 100).toFixed(1)}%)`);
|
|
@@ -3344,8 +3329,8 @@ const blocksCommand = define({
|
|
|
3344
3329
|
style: { head: ["cyan"] },
|
|
3345
3330
|
colAligns: tableAligns
|
|
3346
3331
|
});
|
|
3347
|
-
const terminalWidth = process$1.stdout.columns ||
|
|
3348
|
-
const useCompactFormat = terminalWidth <
|
|
3332
|
+
const terminalWidth = process$1.stdout.columns || BLOCKS_DEFAULT_TERMINAL_WIDTH;
|
|
3333
|
+
const useCompactFormat = terminalWidth < BLOCKS_COMPACT_WIDTH_THRESHOLD;
|
|
3349
3334
|
for (const block of blocks) if (block.isGap ?? false) {
|
|
3350
3335
|
const gapRow = [
|
|
3351
3336
|
import_picocolors$3.default.gray(formatBlockTime(block, useCompactFormat)),
|
|
@@ -3906,8 +3891,8 @@ const mcpCommand = define({
|
|
|
3906
3891
|
},
|
|
3907
3892
|
port: {
|
|
3908
3893
|
type: "number",
|
|
3909
|
-
description:
|
|
3910
|
-
default:
|
|
3894
|
+
description: `Port for HTTP transport (default: ${MCP_DEFAULT_PORT})`,
|
|
3895
|
+
default: MCP_DEFAULT_PORT
|
|
3911
3896
|
}
|
|
3912
3897
|
},
|
|
3913
3898
|
async run(ctx) {
|
|
@@ -938,7 +938,7 @@ function createConsola$1(options = {}) {
|
|
|
938
938
|
defaults: { level },
|
|
939
939
|
stdout: process.stdout,
|
|
940
940
|
stderr: process.stderr,
|
|
941
|
-
prompt: (...args) => import("./prompt-
|
|
941
|
+
prompt: (...args) => import("./prompt-j5YimnLx.js").then((m) => m.prompt(...args)),
|
|
942
942
|
reporters: options.reporters || [options.fancy ?? !(T || R) ? new FancyReporter() : new BasicReporter()],
|
|
943
943
|
...options
|
|
944
944
|
});
|
|
@@ -951,7 +951,7 @@ function _getDefaultLogLevel() {
|
|
|
951
951
|
}
|
|
952
952
|
const consola = createConsola$1();
|
|
953
953
|
var name = "ccusage";
|
|
954
|
-
var version = "12.
|
|
954
|
+
var version = "12.4.0";
|
|
955
955
|
var description = "Usage analysis tool for Claude Code";
|
|
956
956
|
/**
|
|
957
957
|
* Application logger instance with package name tag
|
package/dist/logger.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { log, logger } from "./logger-
|
|
1
|
+
import { log, logger } from "./logger-Cyt2-axs.js";
|
|
2
2
|
export { log, logger };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { __commonJSMin, __toESM, require_usingCtx } from "./pricing-fetcher-5y05qfeL.js";
|
|
2
|
+
import { ZodFirstPartyTypeKind, ZodOptional, ZodType, arrayType, booleanType, dateSchema, discriminatedUnionType, enumType, literalType, numberType, objectType, optionalType, recordType, stringType, unionType, unknownType } from "./types.internal-CX7kpidj.js";
|
|
3
|
+
import { getDefaultClaudePath, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData } from "./data-loader-BL0D1ClF.js";
|
|
4
|
+
import { name, version } from "./logger-Cyt2-axs.js";
|
|
4
5
|
import process from "node:process";
|
|
5
6
|
const LATEST_PROTOCOL_VERSION = "2025-03-26";
|
|
6
7
|
const SUPPORTED_PROTOCOL_VERSIONS = [
|
package/dist/mcp.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import "./pricing-fetcher-
|
|
2
|
-
import { LoadOptions } from "./data-loader-
|
|
1
|
+
import "./pricing-fetcher-A6FC8DhM.js";
|
|
2
|
+
import { LoadOptions } from "./data-loader-BrxITdVN.js";
|
|
3
3
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
4
|
import { Hono } from "hono/tiny";
|
|
5
5
|
|
package/dist/mcp.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import "./pricing-fetcher-
|
|
2
|
-
import "./
|
|
3
|
-
import "./
|
|
4
|
-
import
|
|
1
|
+
import "./pricing-fetcher-5y05qfeL.js";
|
|
2
|
+
import "./types.internal-CX7kpidj.js";
|
|
3
|
+
import "./data-loader-BL0D1ClF.js";
|
|
4
|
+
import "./logger-Cyt2-axs.js";
|
|
5
|
+
import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-Cx7Vxuva.js";
|
|
5
6
|
export { createMcpHttpApp, createMcpServer, startMcpServerStdio };
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import { modelPricingSchema } from "./types.internal-CX7kpidj.js";
|
|
2
|
+
import { logger } from "./logger-Cyt2-axs.js";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
var __create = Object.create;
|
|
6
|
+
var __defProp = Object.defineProperty;
|
|
7
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
8
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
9
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
10
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
11
|
+
var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
14
|
+
key = keys[i];
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
16
|
+
get: ((k) => from[k]).bind(null, key),
|
|
17
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
23
|
+
value: mod,
|
|
24
|
+
enumerable: true
|
|
25
|
+
}) : target, mod));
|
|
26
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
27
|
+
/**
|
|
28
|
+
* URL for LiteLLM's model pricing and context window data
|
|
29
|
+
*/
|
|
30
|
+
const LITELLM_PRICING_URL = "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json";
|
|
31
|
+
/**
|
|
32
|
+
* Default number of recent days to include when filtering blocks
|
|
33
|
+
* Used in both session blocks and commands for consistent behavior
|
|
34
|
+
*/
|
|
35
|
+
const DEFAULT_RECENT_DAYS = 3;
|
|
36
|
+
/**
|
|
37
|
+
* Threshold percentage for showing usage warnings in blocks command (80%)
|
|
38
|
+
* When usage exceeds this percentage of limits, warnings are displayed
|
|
39
|
+
*/
|
|
40
|
+
const BLOCKS_WARNING_THRESHOLD = .8;
|
|
41
|
+
/**
|
|
42
|
+
* Terminal width threshold for switching to compact display mode in blocks command
|
|
43
|
+
* Below this width, tables use more compact formatting
|
|
44
|
+
*/
|
|
45
|
+
const BLOCKS_COMPACT_WIDTH_THRESHOLD = 120;
|
|
46
|
+
/**
|
|
47
|
+
* Default terminal width when stdout.columns is not available in blocks command
|
|
48
|
+
* Used as fallback for responsive table formatting
|
|
49
|
+
*/
|
|
50
|
+
const BLOCKS_DEFAULT_TERMINAL_WIDTH = 120;
|
|
51
|
+
/**
|
|
52
|
+
* Threshold percentage for considering costs as matching (0.1% tolerance)
|
|
53
|
+
* Used in debug cost validation to allow for minor calculation differences
|
|
54
|
+
*/
|
|
55
|
+
const DEBUG_MATCH_THRESHOLD_PERCENT = .1;
|
|
56
|
+
/**
|
|
57
|
+
* Default Claude data directory path (~/.claude)
|
|
58
|
+
* Used as base path for loading usage data from JSONL files
|
|
59
|
+
*/
|
|
60
|
+
const DEFAULT_CLAUDE_CODE_PATH = ".claude";
|
|
61
|
+
/**
|
|
62
|
+
* Claude projects directory name within the data directory
|
|
63
|
+
* Contains subdirectories for each project with usage data
|
|
64
|
+
*/
|
|
65
|
+
const CLAUDE_PROJECTS_DIR_NAME = "projects";
|
|
66
|
+
/**
|
|
67
|
+
* JSONL file glob pattern for finding usage data files
|
|
68
|
+
* Used to recursively find all JSONL files in project directories
|
|
69
|
+
*/
|
|
70
|
+
const USAGE_DATA_GLOB_PATTERN = "**/*.jsonl";
|
|
71
|
+
/**
|
|
72
|
+
* Default port for MCP server HTTP transport
|
|
73
|
+
* Used when no port is specified for MCP server communication
|
|
74
|
+
*/
|
|
75
|
+
const MCP_DEFAULT_PORT = 8080;
|
|
76
|
+
/**
|
|
77
|
+
* User's home directory path
|
|
78
|
+
* Centralized access to OS home directory for consistent path building
|
|
79
|
+
*/
|
|
80
|
+
const USER_HOME_DIR = homedir();
|
|
81
|
+
var require_usingCtx = __commonJSMin((exports, module) => {
|
|
82
|
+
function _usingCtx() {
|
|
83
|
+
var r = "function" == typeof SuppressedError ? SuppressedError : function(r$1, e$1) {
|
|
84
|
+
var n$1 = Error();
|
|
85
|
+
return n$1.name = "SuppressedError", n$1.error = r$1, n$1.suppressed = e$1, n$1;
|
|
86
|
+
}, e = {}, n = [];
|
|
87
|
+
function using(r$1, e$1) {
|
|
88
|
+
if (null != e$1) {
|
|
89
|
+
if (Object(e$1) !== e$1) throw new TypeError("using declarations can only be used with objects, functions, null, or undefined.");
|
|
90
|
+
if (r$1) var o = e$1[Symbol.asyncDispose || Symbol["for"]("Symbol.asyncDispose")];
|
|
91
|
+
if (void 0 === o && (o = e$1[Symbol.dispose || Symbol["for"]("Symbol.dispose")], r$1)) var t = o;
|
|
92
|
+
if ("function" != typeof o) throw new TypeError("Object is not disposable.");
|
|
93
|
+
t && (o = function o$1() {
|
|
94
|
+
try {
|
|
95
|
+
t.call(e$1);
|
|
96
|
+
} catch (r$2) {
|
|
97
|
+
return Promise.reject(r$2);
|
|
98
|
+
}
|
|
99
|
+
}), n.push({
|
|
100
|
+
v: e$1,
|
|
101
|
+
d: o,
|
|
102
|
+
a: r$1
|
|
103
|
+
});
|
|
104
|
+
} else r$1 && n.push({
|
|
105
|
+
d: e$1,
|
|
106
|
+
a: r$1
|
|
107
|
+
});
|
|
108
|
+
return e$1;
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
e,
|
|
112
|
+
u: using.bind(null, !1),
|
|
113
|
+
a: using.bind(null, !0),
|
|
114
|
+
d: function d() {
|
|
115
|
+
var o, t = this.e, s = 0;
|
|
116
|
+
function next() {
|
|
117
|
+
for (; o = n.pop();) try {
|
|
118
|
+
if (!o.a && 1 === s) return s = 0, n.push(o), Promise.resolve().then(next);
|
|
119
|
+
if (o.d) {
|
|
120
|
+
var r$1 = o.d.call(o.v);
|
|
121
|
+
if (o.a) return s |= 2, Promise.resolve(r$1).then(next, err);
|
|
122
|
+
} else s |= 1;
|
|
123
|
+
} catch (r$2) {
|
|
124
|
+
return err(r$2);
|
|
125
|
+
}
|
|
126
|
+
if (1 === s) return t !== e ? Promise.reject(t) : Promise.resolve();
|
|
127
|
+
if (t !== e) throw t;
|
|
128
|
+
}
|
|
129
|
+
function err(n$1) {
|
|
130
|
+
return t = t !== e ? new r(n$1, t) : n$1, next();
|
|
131
|
+
}
|
|
132
|
+
return next();
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
module.exports = _usingCtx, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
137
|
+
});
|
|
138
|
+
var import_usingCtx = __toESM(require_usingCtx(), 1);
|
|
139
|
+
/**
|
|
140
|
+
* Fetches and caches model pricing information from LiteLLM
|
|
141
|
+
* Implements Disposable pattern for automatic resource cleanup
|
|
142
|
+
*/
|
|
143
|
+
var PricingFetcher = class {
|
|
144
|
+
cachedPricing = null;
|
|
145
|
+
offline;
|
|
146
|
+
/**
|
|
147
|
+
* Creates a new PricingFetcher instance
|
|
148
|
+
* @param offline - Whether to use pre-fetched pricing data instead of fetching from API
|
|
149
|
+
*/
|
|
150
|
+
constructor(offline = false) {
|
|
151
|
+
this.offline = offline;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Implements Disposable interface for automatic cleanup
|
|
155
|
+
*/
|
|
156
|
+
[Symbol.dispose]() {
|
|
157
|
+
this.clearCache();
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Clears the cached pricing data
|
|
161
|
+
*/
|
|
162
|
+
clearCache() {
|
|
163
|
+
this.cachedPricing = null;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Ensures pricing data is loaded, either from cache or by fetching
|
|
167
|
+
* @returns Map of model names to pricing information
|
|
168
|
+
*/
|
|
169
|
+
async ensurePricingLoaded() {
|
|
170
|
+
if (this.cachedPricing != null) return this.cachedPricing;
|
|
171
|
+
if (this.offline) {
|
|
172
|
+
const pricing = new Map(Object.entries({
|
|
173
|
+
"claude-instant-1": {
|
|
174
|
+
"input_cost_per_token": 163e-8,
|
|
175
|
+
"output_cost_per_token": 551e-8
|
|
176
|
+
},
|
|
177
|
+
"claude-instant-1.2": {
|
|
178
|
+
"input_cost_per_token": 163e-9,
|
|
179
|
+
"output_cost_per_token": 551e-9
|
|
180
|
+
},
|
|
181
|
+
"claude-2": {
|
|
182
|
+
"input_cost_per_token": 8e-6,
|
|
183
|
+
"output_cost_per_token": 24e-6
|
|
184
|
+
},
|
|
185
|
+
"claude-2.1": {
|
|
186
|
+
"input_cost_per_token": 8e-6,
|
|
187
|
+
"output_cost_per_token": 24e-6
|
|
188
|
+
},
|
|
189
|
+
"claude-3-haiku-20240307": {
|
|
190
|
+
"input_cost_per_token": 25e-8,
|
|
191
|
+
"output_cost_per_token": 125e-8,
|
|
192
|
+
"cache_creation_input_token_cost": 3e-7,
|
|
193
|
+
"cache_read_input_token_cost": 3e-8
|
|
194
|
+
},
|
|
195
|
+
"claude-3-5-haiku-20241022": {
|
|
196
|
+
"input_cost_per_token": 8e-7,
|
|
197
|
+
"output_cost_per_token": 4e-6,
|
|
198
|
+
"cache_creation_input_token_cost": 1e-6,
|
|
199
|
+
"cache_read_input_token_cost": 8e-8
|
|
200
|
+
},
|
|
201
|
+
"claude-3-5-haiku-latest": {
|
|
202
|
+
"input_cost_per_token": 1e-6,
|
|
203
|
+
"output_cost_per_token": 5e-6,
|
|
204
|
+
"cache_creation_input_token_cost": 125e-8,
|
|
205
|
+
"cache_read_input_token_cost": 1e-7
|
|
206
|
+
},
|
|
207
|
+
"claude-3-opus-latest": {
|
|
208
|
+
"input_cost_per_token": 15e-6,
|
|
209
|
+
"output_cost_per_token": 75e-6,
|
|
210
|
+
"cache_creation_input_token_cost": 1875e-8,
|
|
211
|
+
"cache_read_input_token_cost": 15e-7
|
|
212
|
+
},
|
|
213
|
+
"claude-3-opus-20240229": {
|
|
214
|
+
"input_cost_per_token": 15e-6,
|
|
215
|
+
"output_cost_per_token": 75e-6,
|
|
216
|
+
"cache_creation_input_token_cost": 1875e-8,
|
|
217
|
+
"cache_read_input_token_cost": 15e-7
|
|
218
|
+
},
|
|
219
|
+
"claude-3-sonnet-20240229": {
|
|
220
|
+
"input_cost_per_token": 3e-6,
|
|
221
|
+
"output_cost_per_token": 15e-6
|
|
222
|
+
},
|
|
223
|
+
"claude-3-5-sonnet-latest": {
|
|
224
|
+
"input_cost_per_token": 3e-6,
|
|
225
|
+
"output_cost_per_token": 15e-6,
|
|
226
|
+
"cache_creation_input_token_cost": 375e-8,
|
|
227
|
+
"cache_read_input_token_cost": 3e-7
|
|
228
|
+
},
|
|
229
|
+
"claude-3-5-sonnet-20240620": {
|
|
230
|
+
"input_cost_per_token": 3e-6,
|
|
231
|
+
"output_cost_per_token": 15e-6,
|
|
232
|
+
"cache_creation_input_token_cost": 375e-8,
|
|
233
|
+
"cache_read_input_token_cost": 3e-7
|
|
234
|
+
},
|
|
235
|
+
"claude-opus-4-20250514": {
|
|
236
|
+
"input_cost_per_token": 15e-6,
|
|
237
|
+
"output_cost_per_token": 75e-6,
|
|
238
|
+
"cache_creation_input_token_cost": 1875e-8,
|
|
239
|
+
"cache_read_input_token_cost": 15e-7
|
|
240
|
+
},
|
|
241
|
+
"claude-sonnet-4-20250514": {
|
|
242
|
+
"input_cost_per_token": 3e-6,
|
|
243
|
+
"output_cost_per_token": 15e-6,
|
|
244
|
+
"cache_creation_input_token_cost": 375e-8,
|
|
245
|
+
"cache_read_input_token_cost": 3e-7
|
|
246
|
+
},
|
|
247
|
+
"claude-4-opus-20250514": {
|
|
248
|
+
"input_cost_per_token": 15e-6,
|
|
249
|
+
"output_cost_per_token": 75e-6,
|
|
250
|
+
"cache_creation_input_token_cost": 1875e-8,
|
|
251
|
+
"cache_read_input_token_cost": 15e-7
|
|
252
|
+
},
|
|
253
|
+
"claude-4-sonnet-20250514": {
|
|
254
|
+
"input_cost_per_token": 3e-6,
|
|
255
|
+
"output_cost_per_token": 15e-6,
|
|
256
|
+
"cache_creation_input_token_cost": 375e-8,
|
|
257
|
+
"cache_read_input_token_cost": 3e-7
|
|
258
|
+
},
|
|
259
|
+
"claude-3-7-sonnet-latest": {
|
|
260
|
+
"input_cost_per_token": 3e-6,
|
|
261
|
+
"output_cost_per_token": 15e-6,
|
|
262
|
+
"cache_creation_input_token_cost": 375e-8,
|
|
263
|
+
"cache_read_input_token_cost": 3e-7
|
|
264
|
+
},
|
|
265
|
+
"claude-3-7-sonnet-20250219": {
|
|
266
|
+
"input_cost_per_token": 3e-6,
|
|
267
|
+
"output_cost_per_token": 15e-6,
|
|
268
|
+
"cache_creation_input_token_cost": 375e-8,
|
|
269
|
+
"cache_read_input_token_cost": 3e-7
|
|
270
|
+
},
|
|
271
|
+
"claude-3-5-sonnet-20241022": {
|
|
272
|
+
"input_cost_per_token": 3e-6,
|
|
273
|
+
"output_cost_per_token": 15e-6,
|
|
274
|
+
"cache_creation_input_token_cost": 375e-8,
|
|
275
|
+
"cache_read_input_token_cost": 3e-7
|
|
276
|
+
}
|
|
277
|
+
}));
|
|
278
|
+
this.cachedPricing = pricing;
|
|
279
|
+
return pricing;
|
|
280
|
+
}
|
|
281
|
+
try {
|
|
282
|
+
logger.warn("Fetching latest model pricing from LiteLLM...");
|
|
283
|
+
const response = await fetch(LITELLM_PRICING_URL);
|
|
284
|
+
if (!response.ok) throw new Error(`Failed to fetch pricing data: ${response.statusText}`);
|
|
285
|
+
const data = await response.json();
|
|
286
|
+
const pricing = /* @__PURE__ */ new Map();
|
|
287
|
+
for (const [modelName, modelData] of Object.entries(data)) if (typeof modelData === "object" && modelData !== null) {
|
|
288
|
+
const parsed = modelPricingSchema.safeParse(modelData);
|
|
289
|
+
if (parsed.success) pricing.set(modelName, parsed.data);
|
|
290
|
+
}
|
|
291
|
+
this.cachedPricing = pricing;
|
|
292
|
+
logger.info(`Loaded pricing for ${pricing.size} models`);
|
|
293
|
+
return pricing;
|
|
294
|
+
} catch (error) {
|
|
295
|
+
logger.error("Failed to fetch model pricing:", error);
|
|
296
|
+
throw new Error("Could not fetch model pricing data");
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Fetches all available model pricing data
|
|
301
|
+
* @returns Map of model names to pricing information
|
|
302
|
+
*/
|
|
303
|
+
async fetchModelPricing() {
|
|
304
|
+
return this.ensurePricingLoaded();
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Gets pricing information for a specific model with fallback matching
|
|
308
|
+
* Tries exact match first, then provider prefixes, then partial matches
|
|
309
|
+
* @param modelName - Name of the model to get pricing for
|
|
310
|
+
* @returns Model pricing information or null if not found
|
|
311
|
+
*/
|
|
312
|
+
async getModelPricing(modelName) {
|
|
313
|
+
const pricing = await this.ensurePricingLoaded();
|
|
314
|
+
const directMatch = pricing.get(modelName);
|
|
315
|
+
if (directMatch != null) return directMatch;
|
|
316
|
+
const variations = [
|
|
317
|
+
modelName,
|
|
318
|
+
`anthropic/${modelName}`,
|
|
319
|
+
`claude-3-5-${modelName}`,
|
|
320
|
+
`claude-3-${modelName}`,
|
|
321
|
+
`claude-${modelName}`
|
|
322
|
+
];
|
|
323
|
+
for (const variant of variations) {
|
|
324
|
+
const match = pricing.get(variant);
|
|
325
|
+
if (match != null) return match;
|
|
326
|
+
}
|
|
327
|
+
const lowerModel = modelName.toLowerCase();
|
|
328
|
+
for (const [key, value] of pricing) if (key.toLowerCase().includes(lowerModel) || lowerModel.includes(key.toLowerCase())) return value;
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Calculates the cost for given token usage and model
|
|
333
|
+
* @param tokens - Token usage breakdown
|
|
334
|
+
* @param tokens.input_tokens - Number of input tokens
|
|
335
|
+
* @param tokens.output_tokens - Number of output tokens
|
|
336
|
+
* @param tokens.cache_creation_input_tokens - Number of cache creation tokens
|
|
337
|
+
* @param tokens.cache_read_input_tokens - Number of cache read tokens
|
|
338
|
+
* @param modelName - Name of the model used
|
|
339
|
+
* @returns Total cost in USD
|
|
340
|
+
*/
|
|
341
|
+
async calculateCostFromTokens(tokens, modelName) {
|
|
342
|
+
const pricing = await this.getModelPricing(modelName);
|
|
343
|
+
if (pricing == null) return 0;
|
|
344
|
+
return this.calculateCostFromPricing(tokens, pricing);
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Calculates cost from token usage and pricing information
|
|
348
|
+
* @param tokens - Token usage breakdown
|
|
349
|
+
* @param tokens.input_tokens - Number of input tokens
|
|
350
|
+
* @param tokens.output_tokens - Number of output tokens
|
|
351
|
+
* @param tokens.cache_creation_input_tokens - Number of cache creation tokens
|
|
352
|
+
* @param tokens.cache_read_input_tokens - Number of cache read tokens
|
|
353
|
+
* @param pricing - Model pricing rates
|
|
354
|
+
* @returns Total cost in USD
|
|
355
|
+
*/
|
|
356
|
+
calculateCostFromPricing(tokens, pricing) {
|
|
357
|
+
let cost = 0;
|
|
358
|
+
if (pricing.input_cost_per_token != null) cost += tokens.input_tokens * pricing.input_cost_per_token;
|
|
359
|
+
if (pricing.output_cost_per_token != null) cost += tokens.output_tokens * pricing.output_cost_per_token;
|
|
360
|
+
if (tokens.cache_creation_input_tokens != null && pricing.cache_creation_input_token_cost != null) cost += tokens.cache_creation_input_tokens * pricing.cache_creation_input_token_cost;
|
|
361
|
+
if (tokens.cache_read_input_tokens != null && pricing.cache_read_input_token_cost != null) cost += tokens.cache_read_input_tokens * pricing.cache_read_input_token_cost;
|
|
362
|
+
return cost;
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
export { BLOCKS_COMPACT_WIDTH_THRESHOLD, BLOCKS_DEFAULT_TERMINAL_WIDTH, BLOCKS_WARNING_THRESHOLD, CLAUDE_PROJECTS_DIR_NAME, DEBUG_MATCH_THRESHOLD_PERCENT, DEFAULT_CLAUDE_CODE_PATH, DEFAULT_RECENT_DAYS, MCP_DEFAULT_PORT, PricingFetcher, USAGE_DATA_GLOB_PATTERN, USER_HOME_DIR, __commonJSMin, __require, __toESM, require_usingCtx };
|
|
@@ -74,6 +74,7 @@ type NumberBool = typeof numberBool[number];
|
|
|
74
74
|
type TupleToUnion<ArrayType> = ArrayType extends readonly unknown[] ? ArrayType[number] : never;
|
|
75
75
|
//#endregion
|
|
76
76
|
//#region src/types.internal.d.ts
|
|
77
|
+
|
|
77
78
|
/**
|
|
78
79
|
* Available cost calculation modes
|
|
79
80
|
* - auto: Use pre-calculated costs when available, otherwise calculate from tokens
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { PricingFetcher } from "./pricing-fetcher-
|
|
1
|
+
import { PricingFetcher } from "./pricing-fetcher-A6FC8DhM.js";
|
|
2
2
|
export { PricingFetcher };
|
package/dist/pricing-fetcher.js
CHANGED