ccusage 15.10.0 → 16.1.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 +1 -0
- package/config-schema.json +788 -0
- package/dist/calculate-cost.d.ts +1 -1
- package/dist/{data-loader-BJnD_oR3.d.ts → data-loader--Ga8BPdt.d.ts} +4 -0
- package/dist/{data-loader-Dhwqb-FE.js → data-loader-D9y22SrV.js} +3 -3
- package/dist/data-loader.d.ts +1 -1
- package/dist/data-loader.js +3 -3
- package/dist/{debug-DseOsUbb.js → debug-CSXph9NF.js} +3 -3
- package/dist/debug.js +4 -4
- package/dist/index.js +219 -106
- package/dist/{logger-yNFB24CE.js → logger-Cyk_YiBe.js} +1 -1
- package/dist/logger.js +1 -1
- package/dist/{mcp-Cfnsg0lJ.js → mcp-DRjw50Q4.js} +10 -10
- package/dist/mcp.d.ts +2 -4
- package/dist/mcp.js +4 -4
- package/dist/{pricing-fetcher-D3tIkxxO.js → pricing-fetcher-5FVKt1XA.js} +4 -4
- package/dist/pricing-fetcher.js +2 -2
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { BLOCKS_COMPACT_WIDTH_THRESHOLD, BLOCKS_DEFAULT_TERMINAL_WIDTH, BLOCKS_WARNING_THRESHOLD, BURN_RATE_THRESHOLDS, DEFAULT_RECENT_DAYS, DEFAULT_REFRESH_INTERVAL_SECONDS, MAX_REFRESH_INTERVAL_SECONDS, MCP_DEFAULT_PORT, MIN_REFRESH_INTERVAL_SECONDS, MIN_RENDER_INTERVAL_MS,
|
|
2
|
+
import { BLOCKS_COMPACT_WIDTH_THRESHOLD, BLOCKS_DEFAULT_TERMINAL_WIDTH, BLOCKS_WARNING_THRESHOLD, BURN_RATE_THRESHOLDS, CONFIG_FILE_NAME, DEFAULT_RECENT_DAYS, DEFAULT_REFRESH_INTERVAL_SECONDS, MAX_REFRESH_INTERVAL_SECONDS, MCP_DEFAULT_PORT, MIN_REFRESH_INTERVAL_SECONDS, MIN_RENDER_INTERVAL_MS, PricingFetcher, WEEK_DAYS, __commonJSMin, __require, __toESM, inspect, inspectError, isFailure, isSuccess, map, pipe, require_usingCtx, succeed, try_ } from "./pricing-fetcher-5FVKt1XA.js";
|
|
3
3
|
import { getTotalTokens } from "./_token-utils-WjkbrjKv.js";
|
|
4
4
|
import { CostModes, SortOrders, filterDateSchema, statuslineHookJsonSchema } from "./_types-BbEk8t2a.js";
|
|
5
5
|
import { calculateTotals, createTotalsObject } from "./calculate-cost-BDqO4yWA.js";
|
|
6
|
-
import { DEFAULT_SESSION_DURATION_HOURS, calculateBurnRate, calculateContextTokens, calculateCostForEntry, createUniqueHash, filterRecentBlocks, formatDateCompact, getClaudePaths, getContextUsageThresholds, getEarliestTimestamp, getUsageLimitResetTime, globUsageFiles, identifySessionBlocks, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, loadSessionUsageById, loadWeeklyUsageData, projectBlockUsage, sortFilesByTimestamp, uniq, unwrap, usageDataSchema } from "./data-loader-
|
|
7
|
-
import { description, log, logger, name, version } from "./logger-
|
|
8
|
-
import { detectMismatches, printMismatchReport } from "./debug-
|
|
9
|
-
import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-
|
|
6
|
+
import { DEFAULT_SESSION_DURATION_HOURS, calculateBurnRate, calculateContextTokens, calculateCostForEntry, createUniqueHash, filterRecentBlocks, formatDateCompact, getClaudePaths, getContextUsageThresholds, getEarliestTimestamp, getUsageLimitResetTime, globUsageFiles, identifySessionBlocks, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, loadSessionUsageById, loadWeeklyUsageData, projectBlockUsage, sortFilesByTimestamp, toArray, uniq, unwrap, usageDataSchema } from "./data-loader-D9y22SrV.js";
|
|
7
|
+
import { description, log, logger, name, version } from "./logger-Cyk_YiBe.js";
|
|
8
|
+
import { detectMismatches, printMismatchReport } from "./debug-CSXph9NF.js";
|
|
9
|
+
import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-DRjw50Q4.js";
|
|
10
10
|
import a, { readFile, stat } from "node:fs/promises";
|
|
11
11
|
import path, { join } from "node:path";
|
|
12
12
|
import process$1 from "node:process";
|
|
@@ -817,7 +817,94 @@ var require_picocolors = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
817
817
|
};
|
|
818
818
|
};
|
|
819
819
|
module.exports = createColors(), module.exports.createColors = createColors;
|
|
820
|
-
})), import_picocolors$8 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
|
|
820
|
+
})), import_picocolors$8 = /* @__PURE__ */ __toESM(require_picocolors(), 1), import_usingCtx$3 = /* @__PURE__ */ __toESM(require_usingCtx(), 1);
|
|
821
|
+
function extractExplicitArgs(tokens) {
|
|
822
|
+
const explicit = {};
|
|
823
|
+
for (const token of tokens) if (typeof token === "object" && token !== null) {
|
|
824
|
+
const t = token;
|
|
825
|
+
if (t.kind === "option" && typeof t.name === "string") explicit[t.name] = true;
|
|
826
|
+
}
|
|
827
|
+
return explicit;
|
|
828
|
+
}
|
|
829
|
+
function getConfigSearchPaths() {
|
|
830
|
+
const claudeConfigDirs = [join(process$1.cwd(), ".ccusage"), ...toArray(getClaudePaths())];
|
|
831
|
+
return claudeConfigDirs.map((dir) => join(dir, CONFIG_FILE_NAME));
|
|
832
|
+
}
|
|
833
|
+
function validateConfigJson(data) {
|
|
834
|
+
if (typeof data !== "object" || data === null) return false;
|
|
835
|
+
const config = data;
|
|
836
|
+
return !(config.$schema != null && typeof config.$schema !== "string" || config.defaults != null && (typeof config.defaults !== "object" || config.defaults === null) || config.commands != null && (typeof config.commands !== "object" || config.commands === null));
|
|
837
|
+
}
|
|
838
|
+
function loadConfigFile(filePath, debug$4 = false) {
|
|
839
|
+
if (!existsSync(filePath)) {
|
|
840
|
+
if (debug$4) logger.info(` • Checking: ${filePath} (not found)`);
|
|
841
|
+
return void 0;
|
|
842
|
+
}
|
|
843
|
+
const parseConfigFileResult = pipe(try_({
|
|
844
|
+
try: () => {
|
|
845
|
+
const content = readFileSync(filePath, "utf-8"), data = JSON.parse(content);
|
|
846
|
+
if (!validateConfigJson(data)) throw new Error("Invalid configuration structure");
|
|
847
|
+
return data.source = filePath, data;
|
|
848
|
+
},
|
|
849
|
+
catch: (error) => error
|
|
850
|
+
})(), inspect(() => {
|
|
851
|
+
if (logger.debug(`Parsed configuration file: ${filePath}`), debug$4) logger.info(` • Checking: ${filePath} (found ✓)`);
|
|
852
|
+
}), inspectError((error) => {
|
|
853
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
854
|
+
if (logger.warn(`Error parsing configuration file at ${filePath}: ${errorMessage}`), debug$4) logger.info(` • Checking: ${filePath} (error: ${errorMessage})`);
|
|
855
|
+
}), unwrap(void 0));
|
|
856
|
+
return parseConfigFileResult;
|
|
857
|
+
}
|
|
858
|
+
function loadConfig(configPath, debug$4 = false) {
|
|
859
|
+
if (debug$4) logger.info("Debug mode enabled - showing config loading details\n");
|
|
860
|
+
if (configPath != null) {
|
|
861
|
+
if (debug$4) logger.info("Using specified config file:"), logger.info(` • Path: ${configPath}`);
|
|
862
|
+
const config = loadConfigFile(configPath, debug$4);
|
|
863
|
+
if (config == null) logger.warn(`Configuration file not found or invalid: ${configPath}`);
|
|
864
|
+
else if (debug$4) logger.info(""), logger.info(`Loaded config from: ${configPath}`), logger.info(` • Schema: ${config.$schema ?? "none"}`), logger.info(` • Has defaults: ${config.defaults != null ? "yes" : "no"}${config.defaults != null ? ` (${Object.keys(config.defaults).length} options)` : ""}`), logger.info(` • Has command configs: ${config.commands != null ? "yes" : "no"}${config.commands != null ? ` (${Object.keys(config.commands).join(", ")})` : ""}`);
|
|
865
|
+
return config;
|
|
866
|
+
}
|
|
867
|
+
if (debug$4) logger.info("Searching for config files:");
|
|
868
|
+
for (const searchPath of getConfigSearchPaths()) {
|
|
869
|
+
const config = loadConfigFile(searchPath, debug$4);
|
|
870
|
+
if (config != null) {
|
|
871
|
+
if (debug$4) logger.info(""), logger.info(`Loaded config from: ${searchPath}`), logger.info(` • Schema: ${config.$schema ?? "none"}`), logger.info(` • Has defaults: ${config.defaults != null ? "yes" : "no"}${config.defaults != null ? ` (${Object.keys(config.defaults).length} options)` : ""}`), logger.info(` • Has command configs: ${config.commands != null ? "yes" : "no"}${config.commands != null ? ` (${Object.keys(config.commands).join(", ")})` : ""}`);
|
|
872
|
+
return config;
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
if (logger.debug("No valid configuration file found"), debug$4) logger.info(""), logger.info("No valid configuration file found");
|
|
876
|
+
return void 0;
|
|
877
|
+
}
|
|
878
|
+
function mergeConfigWithArgs(ctx, config, debug$4 = false) {
|
|
879
|
+
if (config == null) {
|
|
880
|
+
if (debug$4) logger.info(""), logger.info(`No config file loaded, using CLI args only for '${ctx.name ?? "unknown"}' command`);
|
|
881
|
+
return ctx.values;
|
|
882
|
+
}
|
|
883
|
+
const merged = {}, commandName = ctx.name, sources = {};
|
|
884
|
+
if (config.defaults != null) for (const [key, value$1] of Object.entries(config.defaults)) merged[key] = value$1, sources[key] = "defaults";
|
|
885
|
+
if (commandName != null && config.commands?.[commandName] != null) for (const [key, value$1] of Object.entries(config.commands[commandName])) merged[key] = value$1, sources[key] = "command config";
|
|
886
|
+
const explicit = extractExplicitArgs(ctx.tokens);
|
|
887
|
+
for (const [key, value$1] of Object.entries(ctx.values)) if (value$1 != null && explicit[key] === true) merged[key] = value$1, sources[key] = "CLI";
|
|
888
|
+
if (logger.debug(`Merged config for ${commandName ?? "unknown"}:`, merged), debug$4) {
|
|
889
|
+
logger.info(""), logger.info(`Merging options for '${commandName ?? "unknown"}' command:`);
|
|
890
|
+
const bySource = {
|
|
891
|
+
"defaults": [],
|
|
892
|
+
"command config": [],
|
|
893
|
+
"CLI": []
|
|
894
|
+
};
|
|
895
|
+
for (const [key, source] of Object.entries(sources)) if (bySource[source] != null) bySource[source].push(`${key}=${JSON.stringify(merged[key])}`);
|
|
896
|
+
if (bySource.defaults.length > 0) logger.info(` • From defaults: ${bySource.defaults.join(", ")}`);
|
|
897
|
+
if (bySource["command config"].length > 0) logger.info(` • From command config: ${bySource["command config"].join(", ")}`);
|
|
898
|
+
if (bySource.CLI.length > 0) logger.info(` • From CLI args: ${bySource.CLI.join(", ")}`);
|
|
899
|
+
logger.info(" • Final merged options: {");
|
|
900
|
+
for (const [key, value$1] of Object.entries(merged)) {
|
|
901
|
+
const source = sources[key] ?? "unknown";
|
|
902
|
+
logger.info(` ${key}: ${JSON.stringify(value$1)} (from ${source}),`);
|
|
903
|
+
}
|
|
904
|
+
logger.info(" }");
|
|
905
|
+
}
|
|
906
|
+
return merged;
|
|
907
|
+
}
|
|
821
908
|
const getContext = (raw) => ({
|
|
822
909
|
start: process$1.hrtime.bigint(),
|
|
823
910
|
command: raw.map((part) => getCommandPart(stripVTControlCharacters(part))).join(" "),
|
|
@@ -1077,6 +1164,10 @@ const sharedArgs = {
|
|
|
1077
1164
|
short: "q",
|
|
1078
1165
|
description: "Process JSON output with jq command (requires jq binary, implies --json)"
|
|
1079
1166
|
},
|
|
1167
|
+
config: {
|
|
1168
|
+
type: "string",
|
|
1169
|
+
description: "Path to configuration file (default: auto-discovery)"
|
|
1170
|
+
},
|
|
1080
1171
|
compact: {
|
|
1081
1172
|
type: "boolean",
|
|
1082
1173
|
description: "Force compact mode for narrow displays (better for screenshots)",
|
|
@@ -3072,7 +3163,7 @@ const blocksCommand = define({
|
|
|
3072
3163
|
},
|
|
3073
3164
|
toKebab: true,
|
|
3074
3165
|
async run(ctx) {
|
|
3075
|
-
const
|
|
3166
|
+
const config = loadConfig(ctx.values.config, ctx.values.debug), mergedOptions = mergeConfigWithArgs(ctx, config, ctx.values.debug), useJson = mergedOptions.json || mergedOptions.jq != null;
|
|
3076
3167
|
if (useJson) logger.level = 0;
|
|
3077
3168
|
if (ctx.values.sessionLength <= 0) logger.error("Session length must be a positive number"), process$1.exit(1);
|
|
3078
3169
|
let blocks = await loadSessionBlockData({
|
|
@@ -3285,19 +3376,6 @@ function groupDataByProject(dailyData) {
|
|
|
3285
3376
|
}
|
|
3286
3377
|
return projects;
|
|
3287
3378
|
}
|
|
3288
|
-
let aliasCache = null;
|
|
3289
|
-
function getProjectAliases() {
|
|
3290
|
-
if (aliasCache !== null) return aliasCache;
|
|
3291
|
-
aliasCache = /* @__PURE__ */ new Map();
|
|
3292
|
-
const aliasEnv = (process$1.env[PROJECT_ALIASES_ENV] ?? "").trim();
|
|
3293
|
-
if (aliasEnv === "") return aliasCache;
|
|
3294
|
-
const pairs$1 = aliasEnv.split(",").map((pair$1) => pair$1.trim()).filter((pair$1) => pair$1 !== "");
|
|
3295
|
-
for (const pair$1 of pairs$1) {
|
|
3296
|
-
const parts = pair$1.split("=").map((s) => s.trim()), rawName = parts[0], alias = parts[1];
|
|
3297
|
-
if (rawName != null && alias != null && rawName !== "" && alias !== "") aliasCache.set(rawName, alias);
|
|
3298
|
-
}
|
|
3299
|
-
return aliasCache;
|
|
3300
|
-
}
|
|
3301
3379
|
function parseProjectName(projectName) {
|
|
3302
3380
|
if (projectName === "unknown" || projectName === "") return "Unknown Project";
|
|
3303
3381
|
let cleaned = projectName;
|
|
@@ -3328,11 +3406,10 @@ function parseProjectName(projectName) {
|
|
|
3328
3406
|
}
|
|
3329
3407
|
return cleaned = cleaned.replace(/^[/\\-]+|[/\\-]+$/g, ""), cleaned !== "" ? cleaned : projectName !== "" ? projectName : "Unknown Project";
|
|
3330
3408
|
}
|
|
3331
|
-
function formatProjectName(projectName) {
|
|
3332
|
-
|
|
3333
|
-
if (aliases.has(projectName)) return aliases.get(projectName);
|
|
3409
|
+
function formatProjectName(projectName, aliases) {
|
|
3410
|
+
if (aliases != null && aliases.has(projectName)) return aliases.get(projectName);
|
|
3334
3411
|
const parsed = parseProjectName(projectName);
|
|
3335
|
-
return aliases.has(parsed) ? aliases.get(parsed) : parsed;
|
|
3412
|
+
return aliases != null && aliases.has(parsed) ? aliases.get(parsed) : parsed;
|
|
3336
3413
|
}
|
|
3337
3414
|
var import_picocolors$4 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
|
|
3338
3415
|
const dailyCommand = define({
|
|
@@ -3351,21 +3428,29 @@ const dailyCommand = define({
|
|
|
3351
3428
|
type: "string",
|
|
3352
3429
|
short: "p",
|
|
3353
3430
|
description: "Filter to specific project name"
|
|
3431
|
+
},
|
|
3432
|
+
projectAliases: {
|
|
3433
|
+
type: "string",
|
|
3434
|
+
description: "Comma-separated project aliases (e.g., 'ccusage=Usage Tracker,myproject=My Project')",
|
|
3435
|
+
hidden: true
|
|
3354
3436
|
}
|
|
3355
3437
|
},
|
|
3356
3438
|
async run(ctx) {
|
|
3357
|
-
const
|
|
3439
|
+
const config = loadConfig(ctx.values.config, ctx.values.debug), mergedOptions = mergeConfigWithArgs(ctx, config, ctx.values.debug);
|
|
3440
|
+
let projectAliases;
|
|
3441
|
+
if (mergedOptions.projectAliases != null && typeof mergedOptions.projectAliases === "string") {
|
|
3442
|
+
projectAliases = /* @__PURE__ */ new Map();
|
|
3443
|
+
const pairs$1 = mergedOptions.projectAliases.split(",").map((pair$1) => pair$1.trim()).filter((pair$1) => pair$1 !== "");
|
|
3444
|
+
for (const pair$1 of pairs$1) {
|
|
3445
|
+
const parts = pair$1.split("=").map((s) => s.trim()), rawName = parts[0], alias = parts[1];
|
|
3446
|
+
if (rawName != null && alias != null && rawName !== "" && alias !== "") projectAliases.set(rawName, alias);
|
|
3447
|
+
}
|
|
3448
|
+
}
|
|
3449
|
+
const useJson = Boolean(mergedOptions.json) || mergedOptions.jq != null;
|
|
3358
3450
|
if (useJson) logger.level = 0;
|
|
3359
3451
|
const dailyData = await loadDailyUsageData({
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
mode: ctx.values.mode,
|
|
3363
|
-
order: ctx.values.order,
|
|
3364
|
-
offline: ctx.values.offline,
|
|
3365
|
-
groupByProject: ctx.values.instances,
|
|
3366
|
-
project: ctx.values.project,
|
|
3367
|
-
timezone: ctx.values.timezone,
|
|
3368
|
-
locale: ctx.values.locale
|
|
3452
|
+
...mergedOptions,
|
|
3453
|
+
groupByProject: mergedOptions.instances
|
|
3369
3454
|
});
|
|
3370
3455
|
if (dailyData.length === 0) {
|
|
3371
3456
|
if (useJson) log(JSON.stringify([]));
|
|
@@ -3373,12 +3458,12 @@ const dailyCommand = define({
|
|
|
3373
3458
|
process$1.exit(0);
|
|
3374
3459
|
}
|
|
3375
3460
|
const totals = calculateTotals(dailyData);
|
|
3376
|
-
if (
|
|
3461
|
+
if (mergedOptions.debug && !useJson) {
|
|
3377
3462
|
const mismatchStats = await detectMismatches(void 0);
|
|
3378
|
-
printMismatchReport(mismatchStats,
|
|
3463
|
+
printMismatchReport(mismatchStats, mergedOptions.debugSamples);
|
|
3379
3464
|
}
|
|
3380
3465
|
if (useJson) {
|
|
3381
|
-
const jsonOutput =
|
|
3466
|
+
const jsonOutput = Boolean(mergedOptions.instances) && dailyData.some((d) => d.project != null) ? {
|
|
3382
3467
|
projects: groupByProject(dailyData),
|
|
3383
3468
|
totals: createTotalsObject(totals)
|
|
3384
3469
|
} : {
|
|
@@ -3396,8 +3481,8 @@ const dailyCommand = define({
|
|
|
3396
3481
|
})),
|
|
3397
3482
|
totals: createTotalsObject(totals)
|
|
3398
3483
|
};
|
|
3399
|
-
if (
|
|
3400
|
-
const jqResult = await processWithJq(jsonOutput,
|
|
3484
|
+
if (mergedOptions.jq != null) {
|
|
3485
|
+
const jqResult = await processWithJq(jsonOutput, mergedOptions.jq);
|
|
3401
3486
|
if (isFailure(jqResult)) logger.error(jqResult.error.message), process$1.exit(1);
|
|
3402
3487
|
log(jqResult.value);
|
|
3403
3488
|
} else log(JSON.stringify(jsonOutput, null, 2));
|
|
@@ -3425,7 +3510,7 @@ const dailyCommand = define({
|
|
|
3425
3510
|
"right",
|
|
3426
3511
|
"right"
|
|
3427
3512
|
],
|
|
3428
|
-
dateFormatter: (dateStr) => formatDateCompact(dateStr,
|
|
3513
|
+
dateFormatter: (dateStr) => formatDateCompact(dateStr, mergedOptions.timezone, mergedOptions.locale ?? void 0),
|
|
3429
3514
|
compactHead: [
|
|
3430
3515
|
"Date",
|
|
3431
3516
|
"Models",
|
|
@@ -3443,7 +3528,7 @@ const dailyCommand = define({
|
|
|
3443
3528
|
compactThreshold: 100,
|
|
3444
3529
|
forceCompact: ctx.values.compact
|
|
3445
3530
|
});
|
|
3446
|
-
if (
|
|
3531
|
+
if (Boolean(mergedOptions.instances) && dailyData.some((d) => d.project != null)) {
|
|
3447
3532
|
const projectGroups = groupDataByProject(dailyData);
|
|
3448
3533
|
let isFirstProject = true;
|
|
3449
3534
|
for (const [projectName, projectData] of Object.entries(projectGroups)) {
|
|
@@ -3458,7 +3543,7 @@ const dailyCommand = define({
|
|
|
3458
3543
|
""
|
|
3459
3544
|
]);
|
|
3460
3545
|
table.push([
|
|
3461
|
-
import_picocolors$4.default.cyan(`Project: ${formatProjectName(projectName)}`),
|
|
3546
|
+
import_picocolors$4.default.cyan(`Project: ${formatProjectName(projectName, projectAliases)}`),
|
|
3462
3547
|
"",
|
|
3463
3548
|
"",
|
|
3464
3549
|
"",
|
|
@@ -3476,7 +3561,7 @@ const dailyCommand = define({
|
|
|
3476
3561
|
formatNumber(data.cacheReadTokens),
|
|
3477
3562
|
formatNumber(getTotalTokens(data)),
|
|
3478
3563
|
formatCurrency(data.totalCost)
|
|
3479
|
-
]),
|
|
3564
|
+
]), mergedOptions.breakdown) pushBreakdownRows(table, data.modelBreakdowns);
|
|
3480
3565
|
isFirstProject = false;
|
|
3481
3566
|
}
|
|
3482
3567
|
} else for (const data of dailyData) if (table.push([
|
|
@@ -3488,7 +3573,7 @@ const dailyCommand = define({
|
|
|
3488
3573
|
formatNumber(data.cacheReadTokens),
|
|
3489
3574
|
formatNumber(getTotalTokens(data)),
|
|
3490
3575
|
formatCurrency(data.totalCost)
|
|
3491
|
-
]),
|
|
3576
|
+
]), mergedOptions.breakdown) pushBreakdownRows(table, data.modelBreakdowns);
|
|
3492
3577
|
if (table.push([
|
|
3493
3578
|
"",
|
|
3494
3579
|
"",
|
|
@@ -3900,17 +3985,9 @@ const monthlyCommand = define({
|
|
|
3900
3985
|
description: "Show usage report grouped by month",
|
|
3901
3986
|
...sharedCommandConfig,
|
|
3902
3987
|
async run(ctx) {
|
|
3903
|
-
const
|
|
3988
|
+
const config = loadConfig(ctx.values.config, ctx.values.debug), mergedOptions = mergeConfigWithArgs(ctx, config, ctx.values.debug), useJson = Boolean(mergedOptions.json) || mergedOptions.jq != null;
|
|
3904
3989
|
if (useJson) logger.level = 0;
|
|
3905
|
-
const monthlyData = await loadMonthlyUsageData(
|
|
3906
|
-
since: ctx.values.since,
|
|
3907
|
-
until: ctx.values.until,
|
|
3908
|
-
mode: ctx.values.mode,
|
|
3909
|
-
order: ctx.values.order,
|
|
3910
|
-
offline: ctx.values.offline,
|
|
3911
|
-
timezone: ctx.values.timezone,
|
|
3912
|
-
locale: ctx.values.locale
|
|
3913
|
-
});
|
|
3990
|
+
const monthlyData = await loadMonthlyUsageData(mergedOptions);
|
|
3914
3991
|
if (monthlyData.length === 0) {
|
|
3915
3992
|
if (useJson) {
|
|
3916
3993
|
const emptyOutput = {
|
|
@@ -3929,9 +4006,9 @@ const monthlyCommand = define({
|
|
|
3929
4006
|
process$1.exit(0);
|
|
3930
4007
|
}
|
|
3931
4008
|
const totals = calculateTotals(monthlyData);
|
|
3932
|
-
if (
|
|
4009
|
+
if (mergedOptions.debug && !useJson) {
|
|
3933
4010
|
const mismatchStats = await detectMismatches(void 0);
|
|
3934
|
-
printMismatchReport(mismatchStats,
|
|
4011
|
+
printMismatchReport(mismatchStats, mergedOptions.debugSamples);
|
|
3935
4012
|
}
|
|
3936
4013
|
if (useJson) {
|
|
3937
4014
|
const jsonOutput = {
|
|
@@ -3948,8 +4025,8 @@ const monthlyCommand = define({
|
|
|
3948
4025
|
})),
|
|
3949
4026
|
totals: createTotalsObject(totals)
|
|
3950
4027
|
};
|
|
3951
|
-
if (
|
|
3952
|
-
const jqResult = await processWithJq(jsonOutput,
|
|
4028
|
+
if (mergedOptions.jq != null) {
|
|
4029
|
+
const jqResult = await processWithJq(jsonOutput, mergedOptions.jq);
|
|
3953
4030
|
if (isFailure(jqResult)) logger.error(jqResult.error.message), process$1.exit(1);
|
|
3954
4031
|
log(jqResult.value);
|
|
3955
4032
|
} else log(JSON.stringify(jsonOutput, null, 2));
|
|
@@ -3977,7 +4054,7 @@ const monthlyCommand = define({
|
|
|
3977
4054
|
"right",
|
|
3978
4055
|
"right"
|
|
3979
4056
|
],
|
|
3980
|
-
dateFormatter: (dateStr) => formatDateCompact(dateStr,
|
|
4057
|
+
dateFormatter: (dateStr) => formatDateCompact(dateStr, mergedOptions.timezone, mergedOptions.locale ?? "en-CA"),
|
|
3981
4058
|
compactHead: [
|
|
3982
4059
|
"Month",
|
|
3983
4060
|
"Models",
|
|
@@ -4004,7 +4081,7 @@ const monthlyCommand = define({
|
|
|
4004
4081
|
formatNumber(data.cacheReadTokens),
|
|
4005
4082
|
formatNumber(getTotalTokens(data)),
|
|
4006
4083
|
formatCurrency(data.totalCost)
|
|
4007
|
-
]),
|
|
4084
|
+
]), mergedOptions.breakdown) pushBreakdownRows(table, data.modelBreakdowns);
|
|
4008
4085
|
if (table.push([
|
|
4009
4086
|
"",
|
|
4010
4087
|
"",
|
|
@@ -4116,15 +4193,15 @@ const sessionCommand = define({
|
|
|
4116
4193
|
},
|
|
4117
4194
|
toKebab: true,
|
|
4118
4195
|
async run(ctx) {
|
|
4119
|
-
const
|
|
4196
|
+
const config = loadConfig(ctx.values.config, ctx.values.debug), mergedOptions = mergeConfigWithArgs(ctx, config, ctx.values.debug), useJson = mergedOptions.json || mergedOptions.jq != null;
|
|
4120
4197
|
if (useJson) logger.level = 0;
|
|
4121
|
-
if (
|
|
4122
|
-
id:
|
|
4123
|
-
mode:
|
|
4124
|
-
offline:
|
|
4125
|
-
jq:
|
|
4126
|
-
timezone:
|
|
4127
|
-
locale:
|
|
4198
|
+
if (mergedOptions.id != null) return handleSessionIdLookup({ values: {
|
|
4199
|
+
id: mergedOptions.id,
|
|
4200
|
+
mode: mergedOptions.mode,
|
|
4201
|
+
offline: mergedOptions.offline,
|
|
4202
|
+
jq: mergedOptions.jq,
|
|
4203
|
+
timezone: mergedOptions.timezone,
|
|
4204
|
+
locale: mergedOptions.locale ?? "en-CA"
|
|
4128
4205
|
} }, useJson);
|
|
4129
4206
|
const sessionData = await loadSessionData({
|
|
4130
4207
|
since: ctx.values.since,
|
|
@@ -5132,7 +5209,12 @@ function getSemaphore(sessionId) {
|
|
|
5132
5209
|
const semaphore = createLimoJson(semaphorePath);
|
|
5133
5210
|
return semaphore;
|
|
5134
5211
|
}
|
|
5135
|
-
const
|
|
5212
|
+
const visualBurnRateChoices = [
|
|
5213
|
+
"off",
|
|
5214
|
+
"emoji",
|
|
5215
|
+
"text",
|
|
5216
|
+
"emoji-text"
|
|
5217
|
+
], statuslineCommand = define({
|
|
5136
5218
|
name: "statusline",
|
|
5137
5219
|
description: "Display compact status line for Claude Code hooks with hybrid time+file caching (Beta)",
|
|
5138
5220
|
toKebab: true,
|
|
@@ -5141,6 +5223,15 @@ const statuslineCommand = define({
|
|
|
5141
5223
|
...sharedArgs.offline,
|
|
5142
5224
|
default: true
|
|
5143
5225
|
},
|
|
5226
|
+
visualBurnRate: {
|
|
5227
|
+
type: "enum",
|
|
5228
|
+
choices: visualBurnRateChoices,
|
|
5229
|
+
description: "Controls the visualization of the burn rate status",
|
|
5230
|
+
default: "off",
|
|
5231
|
+
short: "vb",
|
|
5232
|
+
negatable: false,
|
|
5233
|
+
toKebab: true
|
|
5234
|
+
},
|
|
5144
5235
|
cache: {
|
|
5145
5236
|
type: "boolean",
|
|
5146
5237
|
description: "Enable cache for status line output (default: true)",
|
|
@@ -5150,16 +5241,18 @@ const statuslineCommand = define({
|
|
|
5150
5241
|
type: "number",
|
|
5151
5242
|
description: `Refresh interval in seconds for cache expiry (default: ${DEFAULT_REFRESH_INTERVAL_SECONDS})`,
|
|
5152
5243
|
default: DEFAULT_REFRESH_INTERVAL_SECONDS
|
|
5153
|
-
}
|
|
5244
|
+
},
|
|
5245
|
+
config: sharedArgs.config,
|
|
5246
|
+
debug: sharedArgs.debug
|
|
5154
5247
|
},
|
|
5155
5248
|
async run(ctx) {
|
|
5156
5249
|
logger.level = 0;
|
|
5157
|
-
const
|
|
5250
|
+
const config = loadConfig(ctx.values.config, ctx.values.debug), mergedOptions = mergeConfigWithArgs(ctx, config, ctx.values.debug), refreshInterval = mergedOptions.refreshInterval, stdin$2 = await getStdin();
|
|
5158
5251
|
if (stdin$2.length === 0) log("❌ No input provided"), process$1.exit(1);
|
|
5159
5252
|
const hookDataJson = JSON.parse(stdin$2.trim()), hookDataParseResult = statuslineHookJsonSchema.safeParse(hookDataJson);
|
|
5160
5253
|
if (!hookDataParseResult.success) log("❌ Invalid input format:", hookDataParseResult.error.message), process$1.exit(1);
|
|
5161
5254
|
const hookData = hookDataParseResult.data, sessionId = hookData.session_id, initialSemaphoreState = pipe(succeed(getSemaphore(sessionId)), map((semaphore) => semaphore.data), unwrap(void 0)), currentMtime = await getFileModifiedTime(hookData.transcript_path);
|
|
5162
|
-
if (
|
|
5255
|
+
if (mergedOptions.cache && initialSemaphoreState != null) {
|
|
5163
5256
|
const now = Date.now(), timeElapsed = now - (initialSemaphoreState.lastUpdateTime ?? 0), isExpired = timeElapsed >= refreshInterval * 1e3, isFileModified = initialSemaphoreState.transcriptMtime !== currentMtime;
|
|
5164
5257
|
if (!isExpired && !isFileModified) {
|
|
5165
5258
|
log(initialSemaphoreState.lastOutput);
|
|
@@ -5209,7 +5302,7 @@ const statuslineCommand = define({
|
|
|
5209
5302
|
const sessionCost = await pipe(try_({
|
|
5210
5303
|
try: loadSessionUsageById(sessionId, {
|
|
5211
5304
|
mode: "auto",
|
|
5212
|
-
offline:
|
|
5305
|
+
offline: mergedOptions.offline
|
|
5213
5306
|
}),
|
|
5214
5307
|
catch: (error) => error
|
|
5215
5308
|
}), map((sessionCost$1) => sessionCost$1?.totalCost), inspectError((error) => logger.error("Failed to load session data:", error)), unwrap(void 0)), today = /* @__PURE__ */ new Date(), todayStr = today.toISOString().split("T")[0]?.replace(/-/g, "") ?? "", todayCost = await pipe(try_({
|
|
@@ -5217,7 +5310,7 @@ const statuslineCommand = define({
|
|
|
5217
5310
|
since: todayStr,
|
|
5218
5311
|
until: todayStr,
|
|
5219
5312
|
mode: "auto",
|
|
5220
|
-
offline:
|
|
5313
|
+
offline: mergedOptions.offline
|
|
5221
5314
|
}),
|
|
5222
5315
|
catch: (error) => error
|
|
5223
5316
|
}), map((dailyData) => {
|
|
@@ -5229,7 +5322,7 @@ const statuslineCommand = define({
|
|
|
5229
5322
|
}), inspectError((error) => logger.error("Failed to load daily data:", error)), unwrap(0)), { blockInfo, burnRateInfo } = await pipe(try_({
|
|
5230
5323
|
try: loadSessionBlockData({
|
|
5231
5324
|
mode: "auto",
|
|
5232
|
-
offline:
|
|
5325
|
+
offline: mergedOptions.offline
|
|
5233
5326
|
}),
|
|
5234
5327
|
catch: (error) => error
|
|
5235
5328
|
}), map((blocks) => {
|
|
@@ -5242,8 +5335,26 @@ const statuslineCommand = define({
|
|
|
5242
5335
|
});
|
|
5243
5336
|
if (activeBlock != null) {
|
|
5244
5337
|
const now = /* @__PURE__ */ new Date(), remaining = Math.round((activeBlock.endTime.getTime() - now.getTime()) / (1e3 * 60)), blockCost = activeBlock.costUSD, blockInfo$1 = `${formatCurrency(blockCost)} block (${formatRemainingTime(remaining)})`, burnRate = calculateBurnRate(activeBlock), burnRateInfo$1 = burnRate != null ? (() => {
|
|
5245
|
-
const costPerHour = burnRate.costPerHour, costPerHourStr = `${formatCurrency(costPerHour)}/hr`,
|
|
5246
|
-
|
|
5338
|
+
const renderEmojiStatus = ctx.values.visualBurnRate === "emoji" || ctx.values.visualBurnRate === "emoji-text", renderTextStatus = ctx.values.visualBurnRate === "text" || ctx.values.visualBurnRate === "emoji-text", costPerHour = burnRate.costPerHour, costPerHourStr = `${formatCurrency(costPerHour)}/hr`, burnStatus = burnRate.tokensPerMinuteForIndicator < 2e3 ? "normal" : burnRate.tokensPerMinuteForIndicator < 5e3 ? "moderate" : "high", burnStatusMappings = {
|
|
5339
|
+
normal: {
|
|
5340
|
+
emoji: "🟢",
|
|
5341
|
+
textValue: "Normal",
|
|
5342
|
+
coloredString: import_picocolors$1.default.green
|
|
5343
|
+
},
|
|
5344
|
+
moderate: {
|
|
5345
|
+
emoji: "⚠️",
|
|
5346
|
+
textValue: "Moderate",
|
|
5347
|
+
coloredString: import_picocolors$1.default.yellow
|
|
5348
|
+
},
|
|
5349
|
+
high: {
|
|
5350
|
+
emoji: "🚨",
|
|
5351
|
+
textValue: "High",
|
|
5352
|
+
coloredString: import_picocolors$1.default.red
|
|
5353
|
+
}
|
|
5354
|
+
}, { emoji, textValue, coloredString } = burnStatusMappings[burnStatus], burnRateOutputSegments = [coloredString(costPerHourStr)];
|
|
5355
|
+
if (renderEmojiStatus) burnRateOutputSegments.push(emoji);
|
|
5356
|
+
if (renderTextStatus) burnRateOutputSegments.push(coloredString(`(${textValue})`));
|
|
5357
|
+
return ` | 🔥 ${burnRateOutputSegments.join(" ")}`;
|
|
5247
5358
|
})() : "";
|
|
5248
5359
|
return {
|
|
5249
5360
|
blockInfo: blockInfo$1,
|
|
@@ -5258,7 +5369,7 @@ const statuslineCommand = define({
|
|
|
5258
5369
|
blockInfo: "No active block",
|
|
5259
5370
|
burnRateInfo: ""
|
|
5260
5371
|
})), contextInfo = await pipe(try_({
|
|
5261
|
-
try: calculateContextTokens(hookData.transcript_path, hookData.model.id,
|
|
5372
|
+
try: calculateContextTokens(hookData.transcript_path, hookData.model.id, mergedOptions.offline),
|
|
5262
5373
|
catch: (error) => error
|
|
5263
5374
|
}), inspectError((error) => logger.debug(`Failed to calculate context tokens: ${error instanceof Error ? error.message : String(error)}`)), map((ctx$1) => {
|
|
5264
5375
|
if (ctx$1 == null) return void 0;
|
|
@@ -5272,7 +5383,7 @@ const statuslineCommand = define({
|
|
|
5272
5383
|
if (isSuccess(mainProcessingResult)) try {
|
|
5273
5384
|
var _usingCtx3 = (0, import_usingCtx.default)();
|
|
5274
5385
|
const statusLine = mainProcessingResult.value;
|
|
5275
|
-
if (log(statusLine), !
|
|
5386
|
+
if (log(statusLine), !mergedOptions.cache) return;
|
|
5276
5387
|
const semaphore = _usingCtx3.u(getSemaphore(sessionId));
|
|
5277
5388
|
semaphore.data = {
|
|
5278
5389
|
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -5293,7 +5404,7 @@ const statuslineCommand = define({
|
|
|
5293
5404
|
var _usingCtx4 = (0, import_usingCtx.default)();
|
|
5294
5405
|
if (initialSemaphoreState?.lastOutput != null && initialSemaphoreState.lastOutput !== "") log(initialSemaphoreState.lastOutput);
|
|
5295
5406
|
else log("❌ Error generating status");
|
|
5296
|
-
if (logger.error("Error in statusline command:", mainProcessingResult.error), !
|
|
5407
|
+
if (logger.error("Error in statusline command:", mainProcessingResult.error), !mergedOptions.cache) return;
|
|
5297
5408
|
const semaphore = _usingCtx4.u(getSemaphore(sessionId));
|
|
5298
5409
|
if (semaphore.data != null) semaphore.data.isUpdating = false, semaphore.data.pid = void 0;
|
|
5299
5410
|
} catch (_) {
|
|
@@ -5319,18 +5430,9 @@ const weeklyCommand = define({
|
|
|
5319
5430
|
},
|
|
5320
5431
|
toKebab: true,
|
|
5321
5432
|
async run(ctx) {
|
|
5322
|
-
const
|
|
5433
|
+
const config = loadConfig(ctx.values.config, ctx.values.debug), mergedOptions = mergeConfigWithArgs(ctx, config, ctx.values.debug), useJson = Boolean(mergedOptions.json) || mergedOptions.jq != null;
|
|
5323
5434
|
if (useJson) logger.level = 0;
|
|
5324
|
-
const weeklyData = await loadWeeklyUsageData(
|
|
5325
|
-
since: ctx.values.since,
|
|
5326
|
-
until: ctx.values.until,
|
|
5327
|
-
timezone: ctx.values.timezone,
|
|
5328
|
-
mode: ctx.values.mode,
|
|
5329
|
-
order: ctx.values.order,
|
|
5330
|
-
offline: ctx.values.offline,
|
|
5331
|
-
startOfWeek: ctx.values.startOfWeek,
|
|
5332
|
-
locale: ctx.values.locale
|
|
5333
|
-
});
|
|
5435
|
+
const weeklyData = await loadWeeklyUsageData(mergedOptions);
|
|
5334
5436
|
if (weeklyData.length === 0) {
|
|
5335
5437
|
if (useJson) {
|
|
5336
5438
|
const emptyOutput = {
|
|
@@ -5349,9 +5451,9 @@ const weeklyCommand = define({
|
|
|
5349
5451
|
process$1.exit(0);
|
|
5350
5452
|
}
|
|
5351
5453
|
const totals = calculateTotals(weeklyData);
|
|
5352
|
-
if (
|
|
5454
|
+
if (mergedOptions.debug && !useJson) {
|
|
5353
5455
|
const mismatchStats = await detectMismatches(void 0);
|
|
5354
|
-
printMismatchReport(mismatchStats,
|
|
5456
|
+
printMismatchReport(mismatchStats, mergedOptions.debugSamples);
|
|
5355
5457
|
}
|
|
5356
5458
|
if (useJson) {
|
|
5357
5459
|
const jsonOutput = {
|
|
@@ -5368,8 +5470,8 @@ const weeklyCommand = define({
|
|
|
5368
5470
|
})),
|
|
5369
5471
|
totals: createTotalsObject(totals)
|
|
5370
5472
|
};
|
|
5371
|
-
if (
|
|
5372
|
-
const jqResult = await processWithJq(jsonOutput,
|
|
5473
|
+
if (mergedOptions.jq != null) {
|
|
5474
|
+
const jqResult = await processWithJq(jsonOutput, mergedOptions.jq);
|
|
5373
5475
|
if (isFailure(jqResult)) logger.error(jqResult.error.message), process$1.exit(1);
|
|
5374
5476
|
log(jqResult.value);
|
|
5375
5477
|
} else log(JSON.stringify(jsonOutput, null, 2));
|
|
@@ -5397,7 +5499,7 @@ const weeklyCommand = define({
|
|
|
5397
5499
|
"right",
|
|
5398
5500
|
"right"
|
|
5399
5501
|
],
|
|
5400
|
-
dateFormatter: (dateStr) => formatDateCompact(dateStr,
|
|
5502
|
+
dateFormatter: (dateStr) => formatDateCompact(dateStr, mergedOptions.timezone, mergedOptions.locale ?? void 0),
|
|
5401
5503
|
compactHead: [
|
|
5402
5504
|
"Week",
|
|
5403
5505
|
"Models",
|
|
@@ -5424,7 +5526,7 @@ const weeklyCommand = define({
|
|
|
5424
5526
|
formatNumber(data.cacheReadTokens),
|
|
5425
5527
|
formatNumber(getTotalTokens(data)),
|
|
5426
5528
|
formatCurrency(data.totalCost)
|
|
5427
|
-
]),
|
|
5529
|
+
]), mergedOptions.breakdown) pushBreakdownRows(table, data.modelBreakdowns);
|
|
5428
5530
|
if (table.push([
|
|
5429
5531
|
"",
|
|
5430
5532
|
"",
|
|
@@ -5446,14 +5548,25 @@ const weeklyCommand = define({
|
|
|
5446
5548
|
]), log(table.toString()), table.isCompactMode()) logger.info("\nRunning in Compact Mode"), logger.info("Expand terminal width to see cache metrics and total tokens");
|
|
5447
5549
|
}
|
|
5448
5550
|
}
|
|
5449
|
-
}),
|
|
5450
|
-
|
|
5551
|
+
}), subCommandUnion = [
|
|
5552
|
+
["daily", dailyCommand],
|
|
5553
|
+
["monthly", monthlyCommand],
|
|
5554
|
+
["weekly", weeklyCommand],
|
|
5555
|
+
["session", sessionCommand],
|
|
5556
|
+
["blocks", blocksCommand],
|
|
5557
|
+
["mcp", mcpCommand],
|
|
5558
|
+
["statusline", statuslineCommand]
|
|
5559
|
+
], subCommands = /* @__PURE__ */ new Map();
|
|
5560
|
+
for (const [name$1, command] of subCommandUnion) subCommands.set(name$1, command);
|
|
5451
5561
|
const mainCommand = dailyCommand;
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5562
|
+
async function run() {
|
|
5563
|
+
await cli(process$1.argv.slice(2), mainCommand, {
|
|
5564
|
+
name,
|
|
5565
|
+
version,
|
|
5566
|
+
description,
|
|
5567
|
+
subCommands,
|
|
5568
|
+
renderHeader: null
|
|
5569
|
+
});
|
|
5570
|
+
}
|
|
5571
|
+
await run();
|
|
5459
5572
|
export {};
|
|
@@ -761,7 +761,7 @@ function _getDefaultLogLevel() {
|
|
|
761
761
|
return g ? LogLevels.debug : R ? LogLevels.warn : LogLevels.info;
|
|
762
762
|
}
|
|
763
763
|
const consola = createConsola$1();
|
|
764
|
-
var name = "ccusage", version = "
|
|
764
|
+
var name = "ccusage", version = "16.1.0", description = "Usage analysis tool for Claude Code";
|
|
765
765
|
const logger = consola.withTag(name);
|
|
766
766
|
if (process$1.env.LOG_LEVEL != null) {
|
|
767
767
|
const level = Number.parseInt(process$1.env.LOG_LEVEL, 10);
|
package/dist/logger.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { log, logger } from "./logger-
|
|
1
|
+
import { log, logger } from "./logger-Cyk_YiBe.js";
|
|
2
2
|
export { log, logger };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { __commonJSMin, __toESM, require_usingCtx } from "./pricing-fetcher-
|
|
1
|
+
import { __commonJSMin, __toESM, require_usingCtx } from "./pricing-fetcher-5FVKt1XA.js";
|
|
2
2
|
import { getTotalTokens } from "./_token-utils-WjkbrjKv.js";
|
|
3
3
|
import { ZodFirstPartyTypeKind, ZodOptional, ZodType, arrayType, booleanType, discriminatedUnionType, enumType, filterDateSchema, literalType, numberType, objectType, optionalType, recordType, stringType, unionType, unknownType } from "./_types-BbEk8t2a.js";
|
|
4
4
|
import { calculateTotals, createTotalsObject } from "./calculate-cost-BDqO4yWA.js";
|
|
5
|
-
import { getClaudePaths, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData } from "./data-loader-
|
|
6
|
-
import { name, version } from "./logger-
|
|
5
|
+
import { getClaudePaths, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData } from "./data-loader-D9y22SrV.js";
|
|
6
|
+
import { name, version } from "./logger-Cyk_YiBe.js";
|
|
7
7
|
import process from "node:process";
|
|
8
8
|
const LATEST_PROTOCOL_VERSION = "2025-06-18", SUPPORTED_PROTOCOL_VERSIONS = [
|
|
9
9
|
LATEST_PROTOCOL_VERSION,
|
|
@@ -6670,12 +6670,12 @@ function transformUsageDataWithTotals(data, totals, mapper, key) {
|
|
|
6670
6670
|
totals: createTotalsObject(totals)
|
|
6671
6671
|
};
|
|
6672
6672
|
}
|
|
6673
|
-
|
|
6673
|
+
function defaultOptions() {
|
|
6674
6674
|
const paths = getClaudePaths();
|
|
6675
6675
|
if (paths.length === 0) throw new Error("No valid Claude path found. Ensure getClaudePaths() returns at least one valid path.");
|
|
6676
|
-
return paths[0];
|
|
6677
|
-
}
|
|
6678
|
-
function createMcpServer(
|
|
6676
|
+
return { claudePath: paths[0] };
|
|
6677
|
+
}
|
|
6678
|
+
function createMcpServer(options) {
|
|
6679
6679
|
const server = new McpServer({
|
|
6680
6680
|
name,
|
|
6681
6681
|
version
|
|
@@ -6689,7 +6689,7 @@ function createMcpServer({ claudePath } = defaultOptions) {
|
|
|
6689
6689
|
]).default("auto").optional(),
|
|
6690
6690
|
timezone: stringType().optional(),
|
|
6691
6691
|
locale: stringType().default("en-CA").optional()
|
|
6692
|
-
};
|
|
6692
|
+
}, { claudePath } = options ?? defaultOptions();
|
|
6693
6693
|
return server.registerTool("daily", {
|
|
6694
6694
|
description: "Show usage report grouped by date",
|
|
6695
6695
|
inputSchema: parametersZodSchema,
|
|
@@ -6807,8 +6807,8 @@ async function startMcpServerStdio(server) {
|
|
|
6807
6807
|
const transport = new StdioServerTransport();
|
|
6808
6808
|
await server.connect(transport);
|
|
6809
6809
|
}
|
|
6810
|
-
function createMcpHttpApp(options
|
|
6811
|
-
const app = new Hono(), mcpServer = createMcpServer(options);
|
|
6810
|
+
function createMcpHttpApp(options) {
|
|
6811
|
+
const app = new Hono(), mcpServer = createMcpServer(options ?? defaultOptions());
|
|
6812
6812
|
return app.all("/", async (c) => {
|
|
6813
6813
|
const transport = new StreamableHTTPTransport();
|
|
6814
6814
|
return await mcpServer.connect(transport), transport.handleRequest(c);
|