ccusage 15.0.1 → 15.2.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.
@@ -951,7 +951,7 @@ function _getDefaultLogLevel() {
951
951
  }
952
952
  const consola = createConsola$1();
953
953
  var name = "ccusage";
954
- var version = "15.0.1";
954
+ var version = "15.2.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.d.ts CHANGED
@@ -10,6 +10,9 @@ declare const logger: ConsolaInstance;
10
10
  * Direct console.log function for cases where logger formatting is not desired
11
11
  */
12
12
  // eslint-disable-next-line no-console
13
- declare const log: (message?: any, ...optionalParams: any[]) => void;
13
+ declare const log: {
14
+ (...data: any[]): void;
15
+ (message?: any, ...optionalParams: any[]): void;
16
+ };
14
17
  //#endregion
15
18
  export { log, logger };
package/dist/logger.js CHANGED
@@ -1,2 +1,2 @@
1
- import { log, logger } from "./logger-r_DhIB_J.js";
1
+ import { log, logger } from "./logger-CeR-gFvq.js";
2
2
  export { log, logger };
@@ -1,7 +1,8 @@
1
- import { __commonJSMin, __toESM, require_usingCtx } from "./pricing-fetcher-DBzWmU38.js";
2
- import { ZodFirstPartyTypeKind, ZodOptional, ZodType, arrayType, booleanType, dateSchema, discriminatedUnionType, enumType, literalType, numberType, objectType, optionalType, recordType, stringType, unionType, unknownType } from "./_types-Cr2YEzKm.js";
3
- import { getDefaultClaudePath, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData } from "./data-loader-DQftfBz9.js";
4
- import { name, version } from "./logger-r_DhIB_J.js";
1
+ import { __commonJSMin, __toESM, require_usingCtx } from "./pricing-fetcher-fT0o6CKK.js";
2
+ import { ZodFirstPartyTypeKind, ZodOptional, ZodType, arrayType, booleanType, discriminatedUnionType, enumType, filterDateSchema, literalType, numberType, objectType, optionalType, recordType, stringType, unionType, unknownType } from "./_types-CmSE0O0q.js";
3
+ import { calculateTotals, createTotalsObject, getTotalTokens } from "./calculate-cost-B0RYn0Vm.js";
4
+ import { getClaudePaths, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData } from "./data-loader-CzOPffdg.js";
5
+ import { name, version } from "./logger-CeR-gFvq.js";
5
6
  import process from "node:process";
6
7
  const LATEST_PROTOCOL_VERSION = "2025-06-18";
7
8
  const SUPPORTED_PROTOCOL_VERSIONS = [
@@ -9148,8 +9149,120 @@ var Hono = class extends Hono$1 {
9148
9149
  }
9149
9150
  };
9150
9151
  var import_usingCtx = __toESM(require_usingCtx(), 1);
9152
+ const modelBreakdownSchema = objectType({
9153
+ modelName: stringType(),
9154
+ inputTokens: numberType(),
9155
+ outputTokens: numberType(),
9156
+ cacheCreationTokens: numberType().optional(),
9157
+ cacheReadTokens: numberType().optional(),
9158
+ cost: numberType()
9159
+ });
9160
+ const dailyUsageSchema = objectType({
9161
+ date: stringType(),
9162
+ inputTokens: numberType(),
9163
+ outputTokens: numberType(),
9164
+ cacheCreationTokens: numberType().optional(),
9165
+ cacheReadTokens: numberType().optional(),
9166
+ totalTokens: numberType(),
9167
+ totalCost: numberType(),
9168
+ modelsUsed: arrayType(stringType()),
9169
+ modelBreakdowns: arrayType(modelBreakdownSchema)
9170
+ });
9171
+ const sessionUsageSchema = objectType({
9172
+ sessionId: stringType(),
9173
+ inputTokens: numberType(),
9174
+ outputTokens: numberType(),
9175
+ cacheCreationTokens: numberType().optional(),
9176
+ cacheReadTokens: numberType().optional(),
9177
+ totalTokens: numberType(),
9178
+ totalCost: numberType(),
9179
+ lastActivity: stringType(),
9180
+ modelsUsed: arrayType(stringType()),
9181
+ modelBreakdowns: arrayType(modelBreakdownSchema)
9182
+ });
9183
+ const monthlyUsageSchema = objectType({
9184
+ month: stringType(),
9185
+ inputTokens: numberType(),
9186
+ outputTokens: numberType(),
9187
+ cacheCreationTokens: numberType().optional(),
9188
+ cacheReadTokens: numberType().optional(),
9189
+ totalTokens: numberType(),
9190
+ totalCost: numberType(),
9191
+ modelsUsed: arrayType(stringType()),
9192
+ modelBreakdowns: arrayType(modelBreakdownSchema)
9193
+ });
9194
+ const blockUsageSchema = objectType({
9195
+ id: stringType(),
9196
+ startTime: stringType(),
9197
+ endTime: stringType().optional(),
9198
+ actualEndTime: stringType().optional(),
9199
+ isActive: booleanType(),
9200
+ isGap: booleanType(),
9201
+ entries: numberType(),
9202
+ tokenCounts: objectType({
9203
+ inputTokens: numberType(),
9204
+ outputTokens: numberType(),
9205
+ cacheCreationInputTokens: numberType(),
9206
+ cacheReadInputTokens: numberType()
9207
+ }),
9208
+ totalTokens: numberType(),
9209
+ costUSD: numberType(),
9210
+ models: arrayType(stringType()),
9211
+ burnRate: numberType().nullable(),
9212
+ projection: unknownType().nullable()
9213
+ });
9214
+ const dailyResponseSchema = {
9215
+ daily: arrayType(dailyUsageSchema),
9216
+ totals: objectType({
9217
+ totalInputTokens: numberType().optional(),
9218
+ totalOutputTokens: numberType().optional(),
9219
+ totalCacheCreationTokens: numberType().optional(),
9220
+ totalCacheReadTokens: numberType().optional(),
9221
+ totalTokens: numberType().optional(),
9222
+ totalCost: numberType().optional(),
9223
+ modelsUsed: arrayType(stringType()).optional()
9224
+ })
9225
+ };
9226
+ const sessionResponseSchema = {
9227
+ sessions: arrayType(sessionUsageSchema),
9228
+ totals: objectType({
9229
+ totalInputTokens: numberType().optional(),
9230
+ totalOutputTokens: numberType().optional(),
9231
+ totalCacheCreationTokens: numberType().optional(),
9232
+ totalCacheReadTokens: numberType().optional(),
9233
+ totalTokens: numberType().optional(),
9234
+ totalCost: numberType().optional(),
9235
+ modelsUsed: arrayType(stringType()).optional()
9236
+ })
9237
+ };
9238
+ const monthlyResponseSchema = {
9239
+ monthly: arrayType(monthlyUsageSchema),
9240
+ totals: objectType({
9241
+ totalInputTokens: numberType().optional(),
9242
+ totalOutputTokens: numberType().optional(),
9243
+ totalCacheCreationTokens: numberType().optional(),
9244
+ totalCacheReadTokens: numberType().optional(),
9245
+ totalTokens: numberType().optional(),
9246
+ totalCost: numberType().optional(),
9247
+ modelsUsed: arrayType(stringType()).optional()
9248
+ })
9249
+ };
9250
+ const blocksResponseSchema = { blocks: arrayType(blockUsageSchema) };
9251
+ /**
9252
+ * Helper function to transform usage data with totals into JSON output format
9253
+ */
9254
+ function transformUsageDataWithTotals(data, totals, mapper, key) {
9255
+ return {
9256
+ [key]: data.map(mapper),
9257
+ totals: createTotalsObject(totals)
9258
+ };
9259
+ }
9151
9260
  /** Default options for the MCP server */
9152
- const defaultOptions = { claudePath: getDefaultClaudePath() };
9261
+ const defaultOptions = { claudePath: (() => {
9262
+ const paths = getClaudePaths();
9263
+ if (paths.length === 0) throw new Error("No valid Claude path found. Ensure getClaudePaths() returns at least one valid path.");
9264
+ return paths[0];
9265
+ })() };
9153
9266
  /**
9154
9267
  * Creates an MCP server with tools for showing usage reports.
9155
9268
  * Registers tools for daily, session, monthly, and blocks usage data.
@@ -9164,8 +9277,8 @@ function createMcpServer({ claudePath } = defaultOptions) {
9164
9277
  version
9165
9278
  });
9166
9279
  const parametersZodSchema = {
9167
- since: dateSchema.optional(),
9168
- until: dateSchema.optional(),
9280
+ since: filterDateSchema.optional(),
9281
+ until: filterDateSchema.optional(),
9169
9282
  mode: enumType([
9170
9283
  "auto",
9171
9284
  "calculate",
@@ -9174,55 +9287,125 @@ function createMcpServer({ claudePath } = defaultOptions) {
9174
9287
  };
9175
9288
  server.registerTool("daily", {
9176
9289
  description: "Show usage report grouped by date",
9177
- inputSchema: parametersZodSchema
9290
+ inputSchema: parametersZodSchema,
9291
+ outputSchema: dailyResponseSchema
9178
9292
  }, async (args) => {
9179
9293
  const dailyData = await loadDailyUsageData({
9180
9294
  ...args,
9181
9295
  claudePath
9182
9296
  });
9183
- return { content: [{
9184
- type: "text",
9185
- text: JSON.stringify(dailyData, null, 2)
9186
- }] };
9297
+ const totals = calculateTotals(dailyData);
9298
+ const jsonOutput = transformUsageDataWithTotals(dailyData, totals, (data) => ({
9299
+ date: data.date,
9300
+ inputTokens: data.inputTokens,
9301
+ outputTokens: data.outputTokens,
9302
+ cacheCreationTokens: data.cacheCreationTokens,
9303
+ cacheReadTokens: data.cacheReadTokens,
9304
+ totalTokens: getTotalTokens(data),
9305
+ totalCost: data.totalCost,
9306
+ modelsUsed: data.modelsUsed,
9307
+ modelBreakdowns: data.modelBreakdowns
9308
+ }), "daily");
9309
+ return {
9310
+ content: [{
9311
+ type: "text",
9312
+ text: JSON.stringify(jsonOutput, null, 2)
9313
+ }],
9314
+ structuredContent: jsonOutput
9315
+ };
9187
9316
  });
9188
9317
  server.registerTool("session", {
9189
9318
  description: "Show usage report grouped by conversation session",
9190
- inputSchema: parametersZodSchema
9319
+ inputSchema: parametersZodSchema,
9320
+ outputSchema: sessionResponseSchema
9191
9321
  }, async (args) => {
9192
9322
  const sessionData = await loadSessionData({
9193
9323
  ...args,
9194
9324
  claudePath
9195
9325
  });
9196
- return { content: [{
9197
- type: "text",
9198
- text: JSON.stringify(sessionData, null, 2)
9199
- }] };
9326
+ const totals = calculateTotals(sessionData);
9327
+ const jsonOutput = transformUsageDataWithTotals(sessionData, totals, (data) => ({
9328
+ sessionId: data.sessionId,
9329
+ inputTokens: data.inputTokens,
9330
+ outputTokens: data.outputTokens,
9331
+ cacheCreationTokens: data.cacheCreationTokens,
9332
+ cacheReadTokens: data.cacheReadTokens,
9333
+ totalTokens: getTotalTokens(data),
9334
+ totalCost: data.totalCost,
9335
+ lastActivity: data.lastActivity,
9336
+ modelsUsed: data.modelsUsed,
9337
+ modelBreakdowns: data.modelBreakdowns
9338
+ }), "sessions");
9339
+ return {
9340
+ content: [{
9341
+ type: "text",
9342
+ text: JSON.stringify(jsonOutput, null, 2)
9343
+ }],
9344
+ structuredContent: jsonOutput
9345
+ };
9200
9346
  });
9201
9347
  server.registerTool("monthly", {
9202
9348
  description: "Show usage report grouped by month",
9203
- inputSchema: parametersZodSchema
9349
+ inputSchema: parametersZodSchema,
9350
+ outputSchema: monthlyResponseSchema
9204
9351
  }, async (args) => {
9205
9352
  const monthlyData = await loadMonthlyUsageData({
9206
9353
  ...args,
9207
9354
  claudePath
9208
9355
  });
9209
- return { content: [{
9210
- type: "text",
9211
- text: JSON.stringify(monthlyData, null, 2)
9212
- }] };
9356
+ const totals = calculateTotals(monthlyData);
9357
+ const jsonOutput = transformUsageDataWithTotals(monthlyData, totals, (data) => ({
9358
+ month: data.month,
9359
+ inputTokens: data.inputTokens,
9360
+ outputTokens: data.outputTokens,
9361
+ cacheCreationTokens: data.cacheCreationTokens,
9362
+ cacheReadTokens: data.cacheReadTokens,
9363
+ totalTokens: getTotalTokens(data),
9364
+ totalCost: data.totalCost,
9365
+ modelsUsed: data.modelsUsed,
9366
+ modelBreakdowns: data.modelBreakdowns
9367
+ }), "monthly");
9368
+ return {
9369
+ content: [{
9370
+ type: "text",
9371
+ text: JSON.stringify(jsonOutput, null, 2)
9372
+ }],
9373
+ structuredContent: jsonOutput
9374
+ };
9213
9375
  });
9214
9376
  server.registerTool("blocks", {
9215
9377
  description: "Show usage report grouped by session billing blocks",
9216
- inputSchema: parametersZodSchema
9378
+ inputSchema: parametersZodSchema,
9379
+ outputSchema: blocksResponseSchema
9217
9380
  }, async (args) => {
9218
- const blocksData = await loadSessionBlockData({
9381
+ const blocks = await loadSessionBlockData({
9219
9382
  ...args,
9220
9383
  claudePath
9221
9384
  });
9222
- return { content: [{
9223
- type: "text",
9224
- text: JSON.stringify(blocksData, null, 2)
9225
- }] };
9385
+ const jsonOutput = { blocks: blocks.map((block) => {
9386
+ return {
9387
+ id: block.id,
9388
+ startTime: block.startTime.toISOString(),
9389
+ endTime: block.endTime.toISOString(),
9390
+ actualEndTime: block.actualEndTime?.toISOString() ?? null,
9391
+ isActive: block.isActive,
9392
+ isGap: block.isGap ?? false,
9393
+ entries: block.entries.length,
9394
+ tokenCounts: block.tokenCounts,
9395
+ totalTokens: block.tokenCounts.inputTokens + block.tokenCounts.outputTokens,
9396
+ costUSD: block.costUSD,
9397
+ models: block.models,
9398
+ burnRate: null,
9399
+ projection: null
9400
+ };
9401
+ }) };
9402
+ return {
9403
+ content: [{
9404
+ type: "text",
9405
+ text: JSON.stringify(jsonOutput, null, 2)
9406
+ }],
9407
+ structuredContent: jsonOutput
9408
+ };
9226
9409
  });
9227
9410
  return server;
9228
9411
  }
package/dist/mcp.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import "./pricing-fetcher-CXnYw4TA.js";
2
- import { LoadOptions } from "./data-loader-Bll0wMdK.js";
1
+ import { LoadOptions } from "./data-loader-BuHgMcpg.js";
2
+ import "./pricing-fetcher-CrV0acwD.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,6 +1,7 @@
1
- import "./pricing-fetcher-DBzWmU38.js";
2
- import "./_types-Cr2YEzKm.js";
3
- import "./data-loader-DQftfBz9.js";
4
- import "./logger-r_DhIB_J.js";
5
- import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-C-EN2PDc.js";
1
+ import "./pricing-fetcher-fT0o6CKK.js";
2
+ import "./_types-CmSE0O0q.js";
3
+ import "./calculate-cost-B0RYn0Vm.js";
4
+ import "./data-loader-CzOPffdg.js";
5
+ import "./logger-CeR-gFvq.js";
6
+ import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-DGCqhgBz.js";
6
7
  export { createMcpHttpApp, createMcpServer, startMcpServerStdio };
@@ -139,6 +139,8 @@ declare class PricingFetcher implements Disposable {
139
139
  * Clears the cached pricing data
140
140
  */
141
141
  clearCache(): void;
142
+ private loadOfflinePricing;
143
+ private handleFallbackToCachedPricing;
142
144
  private ensurePricingLoaded;
143
145
  /**
144
146
  * Fetches all available model pricing data
@@ -1,8 +1,8 @@
1
- import { modelPricingSchema } from "./_types-Cr2YEzKm.js";
2
- import { logger } from "./logger-r_DhIB_J.js";
1
+ import { modelPricingSchema } from "./_types-CmSE0O0q.js";
2
+ import { logger } from "./logger-CeR-gFvq.js";
3
3
  import { createRequire } from "node:module";
4
- import F, { homedir } from "node:os";
5
4
  import path from "node:path";
5
+ import F, { homedir } from "node:os";
6
6
  var __create = Object.create;
7
7
  var __defProp = Object.defineProperty;
8
8
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -120,6 +120,11 @@ const MIN_REFRESH_INTERVAL_SECONDS = 1;
120
120
  * Prevents too-slow updates that reduce monitoring effectiveness
121
121
  */
122
122
  const MAX_REFRESH_INTERVAL_SECONDS = 60;
123
+ /**
124
+ * Frame rate limit for live monitoring (16ms = ~60fps)
125
+ * Prevents terminal flickering and excessive CPU usage during rapid updates
126
+ */
127
+ const MIN_RENDER_INTERVAL_MS = 16;
123
128
  var require_usingCtx = __commonJSMin((exports, module) => {
124
129
  function _usingCtx() {
125
130
  var r = "function" == typeof SuppressedError ? SuppressedError : function(r$1, e$1) {
@@ -205,121 +210,146 @@ var PricingFetcher = class {
205
210
  this.cachedPricing = null;
206
211
  }
207
212
  /**
213
+ * Loads offline pricing data from pre-fetched cache
214
+ * @returns Map of model names to pricing information
215
+ */
216
+ async loadOfflinePricing() {
217
+ const pricing = new Map(Object.entries({
218
+ "claude-instant-1": {
219
+ "input_cost_per_token": 163e-8,
220
+ "output_cost_per_token": 551e-8
221
+ },
222
+ "claude-instant-1.2": {
223
+ "input_cost_per_token": 163e-9,
224
+ "output_cost_per_token": 551e-9
225
+ },
226
+ "claude-2": {
227
+ "input_cost_per_token": 8e-6,
228
+ "output_cost_per_token": 24e-6
229
+ },
230
+ "claude-2.1": {
231
+ "input_cost_per_token": 8e-6,
232
+ "output_cost_per_token": 24e-6
233
+ },
234
+ "claude-3-haiku-20240307": {
235
+ "input_cost_per_token": 25e-8,
236
+ "output_cost_per_token": 125e-8,
237
+ "cache_creation_input_token_cost": 3e-7,
238
+ "cache_read_input_token_cost": 3e-8
239
+ },
240
+ "claude-3-5-haiku-20241022": {
241
+ "input_cost_per_token": 8e-7,
242
+ "output_cost_per_token": 4e-6,
243
+ "cache_creation_input_token_cost": 1e-6,
244
+ "cache_read_input_token_cost": 8e-8
245
+ },
246
+ "claude-3-5-haiku-latest": {
247
+ "input_cost_per_token": 1e-6,
248
+ "output_cost_per_token": 5e-6,
249
+ "cache_creation_input_token_cost": 125e-8,
250
+ "cache_read_input_token_cost": 1e-7
251
+ },
252
+ "claude-3-opus-latest": {
253
+ "input_cost_per_token": 15e-6,
254
+ "output_cost_per_token": 75e-6,
255
+ "cache_creation_input_token_cost": 1875e-8,
256
+ "cache_read_input_token_cost": 15e-7
257
+ },
258
+ "claude-3-opus-20240229": {
259
+ "input_cost_per_token": 15e-6,
260
+ "output_cost_per_token": 75e-6,
261
+ "cache_creation_input_token_cost": 1875e-8,
262
+ "cache_read_input_token_cost": 15e-7
263
+ },
264
+ "claude-3-sonnet-20240229": {
265
+ "input_cost_per_token": 3e-6,
266
+ "output_cost_per_token": 15e-6
267
+ },
268
+ "claude-3-5-sonnet-latest": {
269
+ "input_cost_per_token": 3e-6,
270
+ "output_cost_per_token": 15e-6,
271
+ "cache_creation_input_token_cost": 375e-8,
272
+ "cache_read_input_token_cost": 3e-7
273
+ },
274
+ "claude-3-5-sonnet-20240620": {
275
+ "input_cost_per_token": 3e-6,
276
+ "output_cost_per_token": 15e-6,
277
+ "cache_creation_input_token_cost": 375e-8,
278
+ "cache_read_input_token_cost": 3e-7
279
+ },
280
+ "claude-opus-4-20250514": {
281
+ "input_cost_per_token": 15e-6,
282
+ "output_cost_per_token": 75e-6,
283
+ "cache_creation_input_token_cost": 1875e-8,
284
+ "cache_read_input_token_cost": 15e-7
285
+ },
286
+ "claude-sonnet-4-20250514": {
287
+ "input_cost_per_token": 3e-6,
288
+ "output_cost_per_token": 15e-6,
289
+ "cache_creation_input_token_cost": 375e-8,
290
+ "cache_read_input_token_cost": 3e-7
291
+ },
292
+ "claude-4-opus-20250514": {
293
+ "input_cost_per_token": 15e-6,
294
+ "output_cost_per_token": 75e-6,
295
+ "cache_creation_input_token_cost": 1875e-8,
296
+ "cache_read_input_token_cost": 15e-7
297
+ },
298
+ "claude-4-sonnet-20250514": {
299
+ "input_cost_per_token": 3e-6,
300
+ "output_cost_per_token": 15e-6,
301
+ "cache_creation_input_token_cost": 375e-8,
302
+ "cache_read_input_token_cost": 3e-7
303
+ },
304
+ "claude-3-7-sonnet-latest": {
305
+ "input_cost_per_token": 3e-6,
306
+ "output_cost_per_token": 15e-6,
307
+ "cache_creation_input_token_cost": 375e-8,
308
+ "cache_read_input_token_cost": 3e-7
309
+ },
310
+ "claude-3-7-sonnet-20250219": {
311
+ "input_cost_per_token": 3e-6,
312
+ "output_cost_per_token": 15e-6,
313
+ "cache_creation_input_token_cost": 375e-8,
314
+ "cache_read_input_token_cost": 3e-7
315
+ },
316
+ "claude-3-5-sonnet-20241022": {
317
+ "input_cost_per_token": 3e-6,
318
+ "output_cost_per_token": 15e-6,
319
+ "cache_creation_input_token_cost": 375e-8,
320
+ "cache_read_input_token_cost": 3e-7
321
+ }
322
+ }));
323
+ this.cachedPricing = pricing;
324
+ return pricing;
325
+ }
326
+ /**
327
+ * Handles fallback to offline pricing when network fetch fails
328
+ * @param originalError - The original error from the network fetch
329
+ * @returns Map of model names to pricing information
330
+ * @throws Error if both network fetch and fallback fail
331
+ */
332
+ async handleFallbackToCachedPricing(originalError) {
333
+ logger.warn("Failed to fetch model pricing from LiteLLM, falling back to cached pricing data");
334
+ logger.debug("Fetch error details:", originalError);
335
+ try {
336
+ const fallbackPricing = await this.loadOfflinePricing();
337
+ logger.info(`Using cached pricing data for ${fallbackPricing.size} models`);
338
+ return fallbackPricing;
339
+ } catch (fallbackError) {
340
+ logger.error("Failed to load cached pricing data as fallback:", fallbackError);
341
+ logger.error("Original fetch error:", originalError);
342
+ throw new Error("Could not fetch model pricing data and fallback data is unavailable");
343
+ }
344
+ }
345
+ /**
208
346
  * Ensures pricing data is loaded, either from cache or by fetching
347
+ * Automatically falls back to offline mode if network fetch fails
209
348
  * @returns Map of model names to pricing information
210
349
  */
211
350
  async ensurePricingLoaded() {
212
351
  if (this.cachedPricing != null) return this.cachedPricing;
213
- if (this.offline) {
214
- const pricing = new Map(Object.entries({
215
- "claude-instant-1": {
216
- "input_cost_per_token": 163e-8,
217
- "output_cost_per_token": 551e-8
218
- },
219
- "claude-instant-1.2": {
220
- "input_cost_per_token": 163e-9,
221
- "output_cost_per_token": 551e-9
222
- },
223
- "claude-2": {
224
- "input_cost_per_token": 8e-6,
225
- "output_cost_per_token": 24e-6
226
- },
227
- "claude-2.1": {
228
- "input_cost_per_token": 8e-6,
229
- "output_cost_per_token": 24e-6
230
- },
231
- "claude-3-haiku-20240307": {
232
- "input_cost_per_token": 25e-8,
233
- "output_cost_per_token": 125e-8,
234
- "cache_creation_input_token_cost": 3e-7,
235
- "cache_read_input_token_cost": 3e-8
236
- },
237
- "claude-3-5-haiku-20241022": {
238
- "input_cost_per_token": 8e-7,
239
- "output_cost_per_token": 4e-6,
240
- "cache_creation_input_token_cost": 1e-6,
241
- "cache_read_input_token_cost": 8e-8
242
- },
243
- "claude-3-5-haiku-latest": {
244
- "input_cost_per_token": 1e-6,
245
- "output_cost_per_token": 5e-6,
246
- "cache_creation_input_token_cost": 125e-8,
247
- "cache_read_input_token_cost": 1e-7
248
- },
249
- "claude-3-opus-latest": {
250
- "input_cost_per_token": 15e-6,
251
- "output_cost_per_token": 75e-6,
252
- "cache_creation_input_token_cost": 1875e-8,
253
- "cache_read_input_token_cost": 15e-7
254
- },
255
- "claude-3-opus-20240229": {
256
- "input_cost_per_token": 15e-6,
257
- "output_cost_per_token": 75e-6,
258
- "cache_creation_input_token_cost": 1875e-8,
259
- "cache_read_input_token_cost": 15e-7
260
- },
261
- "claude-3-sonnet-20240229": {
262
- "input_cost_per_token": 3e-6,
263
- "output_cost_per_token": 15e-6
264
- },
265
- "claude-3-5-sonnet-latest": {
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-20240620": {
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
- "claude-opus-4-20250514": {
278
- "input_cost_per_token": 15e-6,
279
- "output_cost_per_token": 75e-6,
280
- "cache_creation_input_token_cost": 1875e-8,
281
- "cache_read_input_token_cost": 15e-7
282
- },
283
- "claude-sonnet-4-20250514": {
284
- "input_cost_per_token": 3e-6,
285
- "output_cost_per_token": 15e-6,
286
- "cache_creation_input_token_cost": 375e-8,
287
- "cache_read_input_token_cost": 3e-7
288
- },
289
- "claude-4-opus-20250514": {
290
- "input_cost_per_token": 15e-6,
291
- "output_cost_per_token": 75e-6,
292
- "cache_creation_input_token_cost": 1875e-8,
293
- "cache_read_input_token_cost": 15e-7
294
- },
295
- "claude-4-sonnet-20250514": {
296
- "input_cost_per_token": 3e-6,
297
- "output_cost_per_token": 15e-6,
298
- "cache_creation_input_token_cost": 375e-8,
299
- "cache_read_input_token_cost": 3e-7
300
- },
301
- "claude-3-7-sonnet-latest": {
302
- "input_cost_per_token": 3e-6,
303
- "output_cost_per_token": 15e-6,
304
- "cache_creation_input_token_cost": 375e-8,
305
- "cache_read_input_token_cost": 3e-7
306
- },
307
- "claude-3-7-sonnet-20250219": {
308
- "input_cost_per_token": 3e-6,
309
- "output_cost_per_token": 15e-6,
310
- "cache_creation_input_token_cost": 375e-8,
311
- "cache_read_input_token_cost": 3e-7
312
- },
313
- "claude-3-5-sonnet-20241022": {
314
- "input_cost_per_token": 3e-6,
315
- "output_cost_per_token": 15e-6,
316
- "cache_creation_input_token_cost": 375e-8,
317
- "cache_read_input_token_cost": 3e-7
318
- }
319
- }));
320
- this.cachedPricing = pricing;
321
- return pricing;
322
- }
352
+ if (this.offline) return this.loadOfflinePricing();
323
353
  try {
324
354
  logger.warn("Fetching latest model pricing from LiteLLM...");
325
355
  const response = await fetch(LITELLM_PRICING_URL);
@@ -334,8 +364,7 @@ var PricingFetcher = class {
334
364
  logger.info(`Loaded pricing for ${pricing.size} models`);
335
365
  return pricing;
336
366
  } catch (error) {
337
- logger.error("Failed to fetch model pricing:", error);
338
- throw new Error("Could not fetch model pricing data");
367
+ return this.handleFallbackToCachedPricing(error);
339
368
  }
340
369
  }
341
370
  /**
@@ -404,4 +433,4 @@ var PricingFetcher = class {
404
433
  return cost;
405
434
  }
406
435
  };
407
- export { BLOCKS_COMPACT_WIDTH_THRESHOLD, BLOCKS_DEFAULT_TERMINAL_WIDTH, BLOCKS_WARNING_THRESHOLD, CLAUDE_CONFIG_DIR_ENV, CLAUDE_PROJECTS_DIR_NAME, DEBUG_MATCH_THRESHOLD_PERCENT, DEFAULT_CLAUDE_CODE_PATH, DEFAULT_CLAUDE_CONFIG_PATH, DEFAULT_RECENT_DAYS, DEFAULT_REFRESH_INTERVAL_SECONDS, MAX_REFRESH_INTERVAL_SECONDS, MCP_DEFAULT_PORT, MIN_REFRESH_INTERVAL_SECONDS, PricingFetcher, USAGE_DATA_GLOB_PATTERN, USER_HOME_DIR, __commonJSMin, __require, __toESM, require_usingCtx };
436
+ export { BLOCKS_COMPACT_WIDTH_THRESHOLD, BLOCKS_DEFAULT_TERMINAL_WIDTH, BLOCKS_WARNING_THRESHOLD, CLAUDE_CONFIG_DIR_ENV, CLAUDE_PROJECTS_DIR_NAME, DEBUG_MATCH_THRESHOLD_PERCENT, DEFAULT_CLAUDE_CODE_PATH, DEFAULT_CLAUDE_CONFIG_PATH, DEFAULT_RECENT_DAYS, DEFAULT_REFRESH_INTERVAL_SECONDS, MAX_REFRESH_INTERVAL_SECONDS, MCP_DEFAULT_PORT, MIN_REFRESH_INTERVAL_SECONDS, MIN_RENDER_INTERVAL_MS, PricingFetcher, USAGE_DATA_GLOB_PATTERN, USER_HOME_DIR, __commonJSMin, __require, __toESM, require_usingCtx };
@@ -1,2 +1,2 @@
1
- import { PricingFetcher } from "./pricing-fetcher-CXnYw4TA.js";
1
+ import { PricingFetcher } from "./pricing-fetcher-CrV0acwD.js";
2
2
  export { PricingFetcher };
@@ -1,4 +1,4 @@
1
- import { PricingFetcher } from "./pricing-fetcher-DBzWmU38.js";
2
- import "./_types-Cr2YEzKm.js";
3
- import "./logger-r_DhIB_J.js";
1
+ import { PricingFetcher } from "./pricing-fetcher-fT0o6CKK.js";
2
+ import "./_types-CmSE0O0q.js";
3
+ import "./logger-CeR-gFvq.js";
4
4
  export { PricingFetcher };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ccusage",
3
3
  "type": "module",
4
- "version": "15.0.1",
4
+ "version": "15.2.0",
5
5
  "description": "Usage analysis tool for Claude Code",
6
6
  "author": "ryoppippi",
7
7
  "license": "MIT",