ccusage 15.2.0 → 15.3.1

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/index.js CHANGED
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import { BLOCKS_COMPACT_WIDTH_THRESHOLD, BLOCKS_DEFAULT_TERMINAL_WIDTH, BLOCKS_WARNING_THRESHOLD, CLAUDE_PROJECTS_DIR_NAME, 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, __commonJSMin, __require, __toESM, require_usingCtx } from "./pricing-fetcher-fT0o6CKK.js";
3
- import { CostModes, SortOrders, filterDateSchema } from "./_types-CmSE0O0q.js";
4
- import { calculateTotals, createTotalsObject, getTotalTokens } from "./calculate-cost-B0RYn0Vm.js";
5
- import { DEFAULT_SESSION_DURATION_HOURS, calculateBurnRate, calculateCostForEntry, createUniqueHash, filterRecentBlocks, formatDateCompact, getClaudePaths, getEarliestTimestamp, glob, identifySessionBlocks, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, projectBlockUsage, sortFilesByTimestamp, uniq, usageDataSchema } from "./data-loader-CzOPffdg.js";
6
- import { description, log, logger, name, version } from "./logger-CeR-gFvq.js";
7
- import { detectMismatches, printMismatchReport } from "./debug-CCsUo8-n.js";
8
- import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-DGCqhgBz.js";
2
+ import { BLOCKS_COMPACT_WIDTH_THRESHOLD, BLOCKS_DEFAULT_TERMINAL_WIDTH, BLOCKS_WARNING_THRESHOLD, BURN_RATE_THRESHOLDS, CLAUDE_PROJECTS_DIR_NAME, 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, __commonJSMin, __require, __toESM, isFailure, require_usingCtx, try_ } from "./pricing-fetcher-DpoTR8Md.js";
3
+ import { getTotalTokens } from "./_token-utils-WjkbrjKv.js";
4
+ import { CostModes, SortOrders, filterDateSchema } from "./_types-BHFM59hI.js";
5
+ import { calculateTotals, createTotalsObject } from "./calculate-cost-BDqO4yWA.js";
6
+ import { DEFAULT_SESSION_DURATION_HOURS, calculateBurnRate, calculateCostForEntry, createUniqueHash, filterRecentBlocks, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, glob, identifySessionBlocks, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, projectBlockUsage, sortFilesByTimestamp, uniq, usageDataSchema } from "./data-loader-DqK3z1AK.js";
7
+ import { description, log, logger, name, version } from "./logger-D7tlrIfv.js";
8
+ import { detectMismatches, printMismatchReport } from "./debug-Cby_QhQQ.js";
9
+ import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-CFT0dcvs.js";
9
10
  import { readFile } from "node:fs/promises";
10
11
  import path from "node:path";
11
12
  import process$1 from "node:process";
@@ -1257,6 +1258,14 @@ const sharedArgs = {
1257
1258
  short: "O",
1258
1259
  description: "Use cached pricing data for Claude models instead of fetching from API",
1259
1260
  default: false
1261
+ },
1262
+ color: {
1263
+ type: "boolean",
1264
+ description: "Enable colored output (default: auto). FORCE_COLOR=1 has the same effect."
1265
+ },
1266
+ noColor: {
1267
+ type: "boolean",
1268
+ description: "Disable colored output (default: auto). NO_COLOR=1 has the same effect."
1260
1269
  }
1261
1270
  };
1262
1271
  /**
@@ -2149,7 +2158,7 @@ var require_colors = __commonJSMin((exports, module) => {
2149
2158
  var util = __require("node:util");
2150
2159
  var ansiStyles = colors$1.styles = require_styles();
2151
2160
  var defineProps = Object.defineProperties;
2152
- var newLineRegex = new RegExp(/[\r\n]+/g);
2161
+ var newLineRegex = /* @__PURE__ */ new RegExp(/[\r\n]+/g);
2153
2162
  colors$1.supportsColor = require_supports_colors().supportsColor;
2154
2163
  if (typeof colors$1.enabled === "undefined") colors$1.enabled = colors$1.supportsColor() !== false;
2155
2164
  colors$1.enable = function() {
@@ -3214,7 +3223,9 @@ var LiveMonitor = class {
3214
3223
  if (filesToRead.length > 0) {
3215
3224
  const sortedFiles = await sortFilesByTimestamp(filesToRead);
3216
3225
  for (const file of sortedFiles) {
3217
- const content = await readFile(file, "utf-8");
3226
+ const content = await readFile(file, "utf-8").catch(() => {
3227
+ return "";
3228
+ });
3218
3229
  const lines = content.trim().split("\n").filter((line) => line.length > 0);
3219
3230
  for (const line of lines) try {
3220
3231
  const parsed = JSON.parse(line);
@@ -3225,6 +3236,7 @@ var LiveMonitor = class {
3225
3236
  if (uniqueHash != null && this.processedHashes.has(uniqueHash)) continue;
3226
3237
  if (uniqueHash != null) this.processedHashes.add(uniqueHash);
3227
3238
  const costUSD = await (this.config.mode === "display" ? Promise.resolve(data.costUSD ?? 0) : calculateCostForEntry(data, this.config.mode, this.fetcher));
3239
+ const usageLimitResetTime = getUsageLimitResetTime(data);
3228
3240
  this.allEntries.push({
3229
3241
  timestamp: new Date(data.timestamp),
3230
3242
  usage: {
@@ -3235,7 +3247,8 @@ var LiveMonitor = class {
3235
3247
  },
3236
3248
  costUSD,
3237
3249
  model: data.message.model ?? "<synthetic>",
3238
- version: data.version
3250
+ version: data.version,
3251
+ usageLimitResetTime: usageLimitResetTime ?? void 0
3239
3252
  });
3240
3253
  } catch {}
3241
3254
  }
@@ -3671,6 +3684,17 @@ function centerText(text, width) {
3671
3684
  }
3672
3685
  var import_picocolors$5 = __toESM(require_picocolors(), 1);
3673
3686
  /**
3687
+ * Get rate indicator (HIGH/MODERATE/NORMAL) based on burn rate
3688
+ */
3689
+ function getRateIndicator(burnRate) {
3690
+ if (burnRate == null) return "";
3691
+ switch (true) {
3692
+ case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.HIGH: return import_picocolors$5.default.red("⚡ HIGH");
3693
+ case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.MODERATE: return import_picocolors$5.default.yellow("⚡ MODERATE");
3694
+ default: return import_picocolors$5.default.green("✓ NORMAL");
3695
+ }
3696
+ }
3697
+ /**
3674
3698
  * Delay with AbortSignal support and graceful error handling
3675
3699
  */
3676
3700
  async function delayWithAbort(ms, signal) {
@@ -3774,7 +3798,18 @@ function renderLiveDisplay(terminal, block, config) {
3774
3798
  const pad2 = " ".repeat(Math.max(0, DETAIL_COLUMN_WIDTHS.col2 - col2Visible));
3775
3799
  const sessionDetails = ` ${col1}${pad1}${pad2}${col3}`;
3776
3800
  const sessionDetailsPadded = sessionDetails + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(sessionDetails)));
3801
+ let usageLimitResetTimePadded = null;
3802
+ if (block.usageLimitResetTime !== void 0 && now < block.usageLimitResetTime) {
3803
+ const resetTime = block.usageLimitResetTime?.toLocaleTimeString(void 0, {
3804
+ hour: "2-digit",
3805
+ minute: "2-digit",
3806
+ hour12: true
3807
+ }) ?? null;
3808
+ const usageLimitResetTime = resetTime !== null ? import_picocolors$5.default.red(`❌ USAGE LIMIT. RESET AT ${resetTime}`) : "";
3809
+ usageLimitResetTimePadded = resetTime !== null ? usageLimitResetTime + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(usageLimitResetTime))) : null;
3810
+ }
3777
3811
  terminal.write(`${marginStr}│ ${sessionDetailsPadded}│\n`);
3812
+ if (usageLimitResetTimePadded !== null) terminal.write(`${marginStr}│ ${usageLimitResetTimePadded}│\n`);
3778
3813
  terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
3779
3814
  terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
3780
3815
  terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
@@ -3790,7 +3825,7 @@ function renderLiveDisplay(terminal, block, config) {
3790
3825
  rightBracket: "]"
3791
3826
  }) : `[${import_picocolors$5.default.green("█".repeat(Math.floor(barWidth * .1)))}${import_picocolors$5.default.gray("░".repeat(barWidth - Math.floor(barWidth * .1)))}]`;
3792
3827
  const burnRate = calculateBurnRate(block);
3793
- const rateIndicator = burnRate != null ? burnRate.tokensPerMinute > 1e3 ? import_picocolors$5.default.red("⚡ HIGH") : burnRate.tokensPerMinute > 500 ? import_picocolors$5.default.yellow("⚡ MODERATE") : import_picocolors$5.default.green("✓ NORMAL") : "";
3828
+ const rateIndicator = getRateIndicator(burnRate);
3794
3829
  const rateDisplay = burnRate != null ? `${import_picocolors$5.default.bold("Burn Rate:")} ${Math.round(burnRate.tokensPerMinute)} token/min ${rateIndicator}` : `${import_picocolors$5.default.bold("Burn Rate:")} N/A`;
3795
3830
  const usageLabel = import_picocolors$5.default.bold("🔥 USAGE");
3796
3831
  const usageLabelWidth = stringWidth(usageLabel);
@@ -3922,25 +3957,30 @@ async function startLiveMonitoring(config) {
3922
3957
  mode: config.mode,
3923
3958
  order: config.order
3924
3959
  }));
3925
- try {
3926
- while (!abortController.signal.aborted) {
3927
- const now = Date.now();
3928
- const timeSinceLastRender = now - lastRenderTime;
3929
- if (timeSinceLastRender < MIN_RENDER_INTERVAL_MS) {
3930
- await delayWithAbort(MIN_RENDER_INTERVAL_MS - timeSinceLastRender, abortController.signal);
3931
- continue;
3932
- }
3933
- const activeBlock = await monitor.getActiveBlock();
3934
- monitor.clearCache();
3935
- if (activeBlock == null) {
3936
- await renderWaitingState(terminal, config, abortController.signal);
3937
- continue;
3960
+ const monitoringResult = await try_({
3961
+ try: async () => {
3962
+ while (!abortController.signal.aborted) {
3963
+ const now = Date.now();
3964
+ const timeSinceLastRender = now - lastRenderTime;
3965
+ if (timeSinceLastRender < MIN_RENDER_INTERVAL_MS) {
3966
+ await delayWithAbort(MIN_RENDER_INTERVAL_MS - timeSinceLastRender, abortController.signal);
3967
+ continue;
3968
+ }
3969
+ const activeBlock = await monitor.getActiveBlock();
3970
+ monitor.clearCache();
3971
+ if (activeBlock == null) {
3972
+ await renderWaitingState(terminal, config, abortController.signal);
3973
+ continue;
3974
+ }
3975
+ renderActiveBlock(terminal, activeBlock, config);
3976
+ lastRenderTime = Date.now();
3977
+ await delayWithAbort(config.refreshInterval, abortController.signal);
3938
3978
  }
3939
- renderActiveBlock(terminal, activeBlock, config);
3940
- lastRenderTime = Date.now();
3941
- await delayWithAbort(config.refreshInterval, abortController.signal);
3942
- }
3943
- } catch (error) {
3979
+ },
3980
+ catch: (error) => error
3981
+ })();
3982
+ if (isFailure(monitoringResult)) {
3983
+ const error = monitoringResult.error;
3944
3984
  if ((error instanceof DOMException || error instanceof Error) && error.name === "AbortError") return;
3945
3985
  const errorMessage = error instanceof Error ? error.message : String(error);
3946
3986
  terminal.startBuffering();
@@ -4079,7 +4119,7 @@ const blocksCommand = define({
4079
4119
  let maxTokensFromAll = 0;
4080
4120
  if (ctx.values.tokenLimit === "max") {
4081
4121
  for (const block of blocks) if (!(block.isGap ?? false) && !block.isActive) {
4082
- const blockTokens = block.tokenCounts.inputTokens + block.tokenCounts.outputTokens;
4122
+ const blockTokens = getTotalTokens(block.tokenCounts);
4083
4123
  if (blockTokens > maxTokensFromAll) maxTokensFromAll = blockTokens;
4084
4124
  }
4085
4125
  if (!ctx.values.json && maxTokensFromAll > 0) logger.info(`Using max tokens from previous sessions: ${formatNumber(maxTokensFromAll)}`);
@@ -4146,7 +4186,8 @@ const blocksCommand = define({
4146
4186
  percentUsed: projection.totalTokens / limit * 100,
4147
4187
  status: projection.totalTokens > limit ? "exceeds" : projection.totalTokens > limit * BLOCKS_WARNING_THRESHOLD ? "warning" : "ok"
4148
4188
  } : void 0;
4149
- })() : void 0
4189
+ })() : void 0,
4190
+ usageLimitResetTime: block.usageLimitResetTime
4150
4191
  };
4151
4192
  }) };
4152
4193
  log(JSON.stringify(jsonOutput, null, 2));
@@ -4180,7 +4221,7 @@ const blocksCommand = define({
4180
4221
  if (ctx.values.tokenLimit != null) {
4181
4222
  const limit = parseTokenLimit(ctx.values.tokenLimit, maxTokensFromAll);
4182
4223
  if (limit != null && limit > 0) {
4183
- const currentTokens = block.tokenCounts.inputTokens + block.tokenCounts.outputTokens;
4224
+ const currentTokens = getTotalTokens(block.tokenCounts);
4184
4225
  const remainingTokens = Math.max(0, limit - currentTokens);
4185
4226
  const percentUsed = projection.totalTokens / limit * 100;
4186
4227
  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");
@@ -4231,7 +4272,7 @@ const blocksCommand = define({
4231
4272
  gapRow.push(import_picocolors$3.default.gray("-"));
4232
4273
  table.push(gapRow);
4233
4274
  } else {
4234
- const totalTokens = block.tokenCounts.inputTokens + block.tokenCounts.outputTokens;
4275
+ const totalTokens = getTotalTokens(block.tokenCounts);
4235
4276
  const status = block.isActive ? import_picocolors$3.default.green("ACTIVE") : "";
4236
4277
  const row = [
4237
4278
  formatBlockTime(block, useCompactFormat),
@@ -4248,7 +4289,7 @@ const blocksCommand = define({
4248
4289
  table.push(row);
4249
4290
  if (block.isActive) {
4250
4291
  if (actualTokenLimit != null && actualTokenLimit > 0) {
4251
- const currentTokens = block.tokenCounts.inputTokens + block.tokenCounts.outputTokens;
4292
+ const currentTokens = getTotalTokens(block.tokenCounts);
4252
4293
  const remainingTokens = Math.max(0, actualTokenLimit - currentTokens);
4253
4294
  const remainingText = remainingTokens > 0 ? formatNumber(remainingTokens) : import_picocolors$3.default.red("0");
4254
4295
  const remainingPercent = (actualTokenLimit - currentTokens) / actualTokenLimit * 100;
@@ -915,7 +915,7 @@ ${indent}`);
915
915
  line = space > 0 && (opts.columns || 0) >= 80 ? left + " ".repeat(space) + right : (right ? `${colors.gray(`[${right}]`)} ` : "") + left;
916
916
  line += characterFormat(additional.length > 0 ? "\n" + additional.join("\n") : "");
917
917
  if (logObj.type === "trace") {
918
- const _err = new Error("Trace: " + logObj.message);
918
+ const _err = /* @__PURE__ */ new Error("Trace: " + logObj.message);
919
919
  line += this.formatStack(_err.stack || "", _err.message);
920
920
  }
921
921
  return isBadge ? "\n" + line + "\n" : line;
@@ -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-j5YimnLx.js").then((m) => m.prompt(...args)),
941
+ prompt: (...args) => import("./prompt-DsUFNEY7.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 = "15.2.0";
954
+ var version = "15.3.1";
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-CeR-gFvq.js";
1
+ import { log, logger } from "./logger-D7tlrIfv.js";
2
2
  export { log, logger };
@@ -1,8 +1,9 @@
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";
1
+ import { __commonJSMin, __toESM, require_usingCtx } from "./pricing-fetcher-DpoTR8Md.js";
2
+ import { getTotalTokens } from "./_token-utils-WjkbrjKv.js";
3
+ import { ZodFirstPartyTypeKind, ZodOptional, ZodType, arrayType, booleanType, discriminatedUnionType, enumType, filterDateSchema, literalType, numberType, objectType, optionalType, recordType, stringType, unionType, unknownType } from "./_types-BHFM59hI.js";
4
+ import { calculateTotals, createTotalsObject } from "./calculate-cost-BDqO4yWA.js";
5
+ import { getClaudePaths, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData } from "./data-loader-DqK3z1AK.js";
6
+ import { name, version } from "./logger-D7tlrIfv.js";
6
7
  import process from "node:process";
7
8
  const LATEST_PROTOCOL_VERSION = "2025-06-18";
8
9
  const SUPPORTED_PROTOCOL_VERSIONS = [
@@ -1323,7 +1324,7 @@ var StreamableHTTPTransport = class {
1323
1324
  data: JSON.stringify(message)
1324
1325
  });
1325
1326
  } catch {
1326
- this.onerror?.(new Error("Failed replay events"));
1327
+ this.onerror?.(/* @__PURE__ */ new Error("Failed replay events"));
1327
1328
  throw new HTTPException(500, { message: "Failed replay events" });
1328
1329
  }
1329
1330
  } });
@@ -1651,18 +1652,25 @@ var Protocol = class {
1651
1652
  * The Protocol object assumes ownership of the Transport, replacing any callbacks that have already been set, and expects that it is the only user of the Transport instance going forward.
1652
1653
  */
1653
1654
  async connect(transport) {
1655
+ var _a, _b, _c;
1654
1656
  this._transport = transport;
1657
+ const _onclose = (_a = this.transport) === null || _a === void 0 ? void 0 : _a.onclose;
1655
1658
  this._transport.onclose = () => {
1659
+ _onclose === null || _onclose === void 0 || _onclose();
1656
1660
  this._onclose();
1657
1661
  };
1662
+ const _onerror = (_b = this.transport) === null || _b === void 0 ? void 0 : _b.onerror;
1658
1663
  this._transport.onerror = (error) => {
1664
+ _onerror === null || _onerror === void 0 || _onerror(error);
1659
1665
  this._onerror(error);
1660
1666
  };
1667
+ const _onmessage = (_c = this._transport) === null || _c === void 0 ? void 0 : _c.onmessage;
1661
1668
  this._transport.onmessage = (message, extra) => {
1669
+ _onmessage === null || _onmessage === void 0 || _onmessage(message, extra);
1662
1670
  if (isJSONRPCResponse(message) || isJSONRPCError(message)) this._onresponse(message);
1663
1671
  else if (isJSONRPCRequest(message)) this._onrequest(message, extra);
1664
1672
  else if (isJSONRPCNotification(message)) this._onnotification(message);
1665
- else this._onerror(new Error(`Unknown message type: ${JSON.stringify(message)}`));
1673
+ else this._onerror(/* @__PURE__ */ new Error(`Unknown message type: ${JSON.stringify(message)}`));
1666
1674
  };
1667
1675
  await this._transport.start();
1668
1676
  }
@@ -1684,7 +1692,7 @@ var Protocol = class {
1684
1692
  var _a;
1685
1693
  const handler = (_a = this._notificationHandlers.get(notification.method)) !== null && _a !== void 0 ? _a : this.fallbackNotificationHandler;
1686
1694
  if (handler === void 0) return;
1687
- Promise.resolve().then(() => handler(notification)).catch((error) => this._onerror(new Error(`Uncaught error in notification handler: ${error}`)));
1695
+ Promise.resolve().then(() => handler(notification)).catch((error) => this._onerror(/* @__PURE__ */ new Error(`Uncaught error in notification handler: ${error}`)));
1688
1696
  }
1689
1697
  _onrequest(request, extra) {
1690
1698
  var _a, _b, _c, _d;
@@ -1697,7 +1705,7 @@ var Protocol = class {
1697
1705
  code: ErrorCode.MethodNotFound,
1698
1706
  message: "Method not found"
1699
1707
  }
1700
- }).catch((error) => this._onerror(new Error(`Failed to send an error response: ${error}`)));
1708
+ }).catch((error) => this._onerror(/* @__PURE__ */ new Error(`Failed to send an error response: ${error}`)));
1701
1709
  return;
1702
1710
  }
1703
1711
  const abortController = new AbortController();
@@ -1712,7 +1720,8 @@ var Protocol = class {
1712
1720
  relatedRequestId: request.id
1713
1721
  }),
1714
1722
  authInfo: extra === null || extra === void 0 ? void 0 : extra.authInfo,
1715
- requestId: request.id
1723
+ requestId: request.id,
1724
+ requestInfo: extra === null || extra === void 0 ? void 0 : extra.requestInfo
1716
1725
  };
1717
1726
  Promise.resolve().then(() => handler(request, fullExtra)).then((result) => {
1718
1727
  var _a$1;
@@ -1733,7 +1742,7 @@ var Protocol = class {
1733
1742
  message: (_b$1 = error.message) !== null && _b$1 !== void 0 ? _b$1 : "Internal error"
1734
1743
  }
1735
1744
  });
1736
- }).catch((error) => this._onerror(new Error(`Failed to send response: ${error}`))).finally(() => {
1745
+ }).catch((error) => this._onerror(/* @__PURE__ */ new Error(`Failed to send response: ${error}`))).finally(() => {
1737
1746
  this._requestHandlerAbortControllers.delete(request.id);
1738
1747
  });
1739
1748
  }
@@ -1742,7 +1751,7 @@ var Protocol = class {
1742
1751
  const messageId = Number(progressToken);
1743
1752
  const handler = this._progressHandlers.get(messageId);
1744
1753
  if (!handler) {
1745
- this._onerror(new Error(`Received a progress notification for an unknown token: ${JSON.stringify(notification)}`));
1754
+ this._onerror(/* @__PURE__ */ new Error(`Received a progress notification for an unknown token: ${JSON.stringify(notification)}`));
1746
1755
  return;
1747
1756
  }
1748
1757
  const responseHandler = this._responseHandlers.get(messageId);
@@ -1759,7 +1768,7 @@ var Protocol = class {
1759
1768
  const messageId = Number(response.id);
1760
1769
  const handler = this._responseHandlers.get(messageId);
1761
1770
  if (handler === void 0) {
1762
- this._onerror(new Error(`Received a response for an unknown message ID: ${JSON.stringify(response)}`));
1771
+ this._onerror(/* @__PURE__ */ new Error(`Received a response for an unknown message ID: ${JSON.stringify(response)}`));
1763
1772
  return;
1764
1773
  }
1765
1774
  this._responseHandlers.delete(messageId);
@@ -1791,7 +1800,7 @@ var Protocol = class {
1791
1800
  return new Promise((resolve$4, reject) => {
1792
1801
  var _a, _b, _c, _d, _e, _f;
1793
1802
  if (!this._transport) {
1794
- reject(new Error("Not connected"));
1803
+ reject(/* @__PURE__ */ new Error("Not connected"));
1795
1804
  return;
1796
1805
  }
1797
1806
  if (((_a = this._options) === null || _a === void 0 ? void 0 : _a.enforceStrictCapabilities) === true) this.assertCapabilityForMethod(request.method);
@@ -1828,7 +1837,7 @@ var Protocol = class {
1828
1837
  relatedRequestId,
1829
1838
  resumptionToken,
1830
1839
  onresumptiontoken
1831
- }).catch((error) => this._onerror(new Error(`Failed to send cancellation: ${error}`)));
1840
+ }).catch((error) => this._onerror(/* @__PURE__ */ new Error(`Failed to send cancellation: ${error}`)));
1832
1841
  reject(reason);
1833
1842
  };
1834
1843
  this._responseHandlers.set(messageId, (response) => {
@@ -1977,8 +1986,8 @@ var require_uri_all = __commonJSMin((exports, module) => {
1977
1986
  UNRESERVED: new RegExp(UNRESERVED$$$1, "g"),
1978
1987
  OTHER_CHARS: new RegExp(merge("[^\\%]", UNRESERVED$$$1, RESERVED$$), "g"),
1979
1988
  PCT_ENCODED: new RegExp(PCT_ENCODED$$1, "g"),
1980
- IPV4ADDRESS: new RegExp("^(" + IPV4ADDRESS$ + ")$"),
1981
- IPV6ADDRESS: new RegExp("^\\[?(" + IPV6ADDRESS$ + ")" + subexp(subexp("\\%25|\\%(?!" + HEXDIG$$$1 + "{2})") + "(" + ZONEID$ + ")") + "?\\]?$")
1989
+ IPV4ADDRESS: /* @__PURE__ */ new RegExp("^(" + IPV4ADDRESS$ + ")$"),
1990
+ IPV6ADDRESS: /* @__PURE__ */ new RegExp("^\\[?(" + IPV6ADDRESS$ + ")" + subexp(subexp("\\%25|\\%(?!" + HEXDIG$$$1 + "{2})") + "(" + ZONEID$ + ")") + "?\\]?$")
1982
1991
  };
1983
1992
  }
1984
1993
  var URI_PROTOCOL = buildExps(false);
@@ -7664,7 +7673,7 @@ function parseStringDef(def, refs) {
7664
7673
  function escapeLiteralCheckValue(literal, refs) {
7665
7674
  return refs.patternStrategy === "escape" ? escapeNonAlphaNumeric(literal) : literal;
7666
7675
  }
7667
- const ALPHA_NUMERIC = new Set("ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvxyz0123456789");
7676
+ const ALPHA_NUMERIC = /* @__PURE__ */ new Set("ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvxyz0123456789");
7668
7677
  function escapeNonAlphaNumeric(source) {
7669
7678
  let result = "";
7670
7679
  for (let i = 0; i < source.length; i++) {
@@ -8412,7 +8421,7 @@ var McpServer = class {
8412
8421
  };
8413
8422
  }
8414
8423
  }
8415
- if (tool.outputSchema) {
8424
+ if (tool.outputSchema && !result.isError) {
8416
8425
  if (!result.structuredContent) throw new McpError(ErrorCode.InvalidParams, `Tool ${request.params.name} has an output schema but no structured content was provided`);
8417
8426
  const parseResult = await tool.outputSchema.safeParseAsync(result.structuredContent);
8418
8427
  if (!parseResult.success) throw new McpError(ErrorCode.InvalidParams, `Invalid structured content for tool ${request.params.name}: ${parseResult.error.message}`);
@@ -9122,7 +9131,7 @@ var PatternRouter = class {
9122
9131
  });
9123
9132
  try {
9124
9133
  this.#routes.push([
9125
- new RegExp(`^${parts.join("")}${endsWithWildcard ? "" : "/?$"}`),
9134
+ /* @__PURE__ */ new RegExp(`^${parts.join("")}${endsWithWildcard ? "" : "/?$"}`),
9126
9135
  method,
9127
9136
  handler
9128
9137
  ]);
package/dist/mcp.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { LoadOptions } from "./data-loader-BuHgMcpg.js";
2
- import "./pricing-fetcher-CrV0acwD.js";
1
+ import { LoadOptions } from "./data-loader-a9CiVyT5.js";
2
+ import "./pricing-fetcher-B3SvKOod.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,7 +1,8 @@
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";
1
+ import "./pricing-fetcher-DpoTR8Md.js";
2
+ import "./_token-utils-WjkbrjKv.js";
3
+ import "./_types-BHFM59hI.js";
4
+ import "./calculate-cost-BDqO4yWA.js";
5
+ import "./data-loader-DqK3z1AK.js";
6
+ import "./logger-D7tlrIfv.js";
7
+ import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-CFT0dcvs.js";
7
8
  export { createMcpHttpApp, createMcpServer, startMcpServerStdio };
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import { Result } from "@praha/byethrow";
2
3
 
3
4
  //#region node_modules/type-fest/source/observable-like.d.ts
4
5
  declare global {
@@ -139,6 +140,10 @@ declare class PricingFetcher implements Disposable {
139
140
  * Clears the cached pricing data
140
141
  */
141
142
  clearCache(): void;
143
+ /**
144
+ * Loads offline pricing data from pre-fetched cache
145
+ * @returns Map of model names to pricing information
146
+ */
142
147
  private loadOfflinePricing;
143
148
  private handleFallbackToCachedPricing;
144
149
  private ensurePricingLoaded;
@@ -146,14 +151,14 @@ declare class PricingFetcher implements Disposable {
146
151
  * Fetches all available model pricing data
147
152
  * @returns Map of model names to pricing information
148
153
  */
149
- fetchModelPricing(): Promise<Map<string, ModelPricing>>;
154
+ fetchModelPricing(): Result.ResultAsync<Map<string, ModelPricing>, Error>;
150
155
  /**
151
156
  * Gets pricing information for a specific model with fallback matching
152
157
  * Tries exact match first, then provider prefixes, then partial matches
153
158
  * @param modelName - Name of the model to get pricing for
154
159
  * @returns Model pricing information or null if not found
155
160
  */
156
- getModelPricing(modelName: string): Promise<ModelPricing | null>;
161
+ getModelPricing(modelName: string): Result.ResultAsync<ModelPricing | null, Error>;
157
162
  /**
158
163
  * Calculates the cost for given token usage and model
159
164
  * @param tokens - Token usage breakdown
@@ -169,7 +174,7 @@ declare class PricingFetcher implements Disposable {
169
174
  output_tokens: number;
170
175
  cache_creation_input_tokens?: number;
171
176
  cache_read_input_tokens?: number;
172
- }, modelName: string): Promise<number>;
177
+ }, modelName: string): Result.ResultAsync<number, Error>;
173
178
  /**
174
179
  * Calculates cost from token usage and pricing information
175
180
  * @param tokens - Token usage breakdown