usage-board 3.2.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +1 -1
- package/dist/public/_nuxt/37OOe3RF.js +1 -0
- package/dist/public/_nuxt/65Ayv2XK.js +146 -0
- package/dist/public/_nuxt/BOWwkrCY.js +25 -0
- package/dist/public/_nuxt/C0GhHHgI.js +3 -0
- package/dist/public/_nuxt/{CLHpvfq1.js → D7qEPtpx.js} +1 -1
- package/dist/public/_nuxt/D9-Yw1TR.js +1 -0
- package/dist/public/_nuxt/DF2WsXH3.js +1 -0
- package/dist/public/_nuxt/DKaPq50Z.js +6 -0
- package/dist/public/_nuxt/{CBu27bzx.js → DXWxIyGU.js} +1 -1
- package/dist/public/_nuxt/De8DvPWL.js +1 -0
- package/dist/public/_nuxt/DgMMKsPE.js +258 -0
- package/dist/public/_nuxt/DxvuOJRP.js +1 -0
- package/dist/public/_nuxt/Jp5cgQZi.js +4 -0
- package/dist/public/_nuxt/builds/latest.json +1 -1
- package/dist/public/_nuxt/builds/meta/7ce9c611-6071-4cbd-8926-1e53d9ef21bd.json +1 -0
- package/dist/public/_nuxt/entry.DnkKc-6G.css +1 -0
- package/dist/public/_nuxt/qXgLTL_3.js +21 -0
- package/dist/public/_nuxt/y6mAKUDU.js +1 -0
- package/dist/server/chunks/build/client.precomputed.mjs +1 -1
- package/dist/server/chunks/nitro/nitro.mjs +2192 -1409
- package/dist/server/chunks/routes/api/analysis/agent/session.json.mjs +1 -1
- package/dist/server/chunks/routes/api/analysis/agent/token.json.mjs +1 -1
- package/dist/server/chunks/routes/api/analysis/cache.json.mjs +1 -1
- package/dist/server/chunks/routes/api/analysis/hot-project.json.mjs +1 -1
- package/dist/server/chunks/routes/api/analysis/model.json.mjs +1 -1
- package/dist/server/chunks/routes/api/analysis/overview-cards.json.mjs +4 -4
- package/dist/server/chunks/routes/api/analysis/session.json.mjs +1 -1
- package/dist/server/chunks/routes/api/analysis/token/daily.json.mjs +1 -1
- package/dist/server/chunks/routes/api/analysis/token/today-hourly.json.mjs +21 -0
- package/dist/server/chunks/routes/api/analysis/token.json.mjs +1 -1
- package/dist/server/chunks/routes/api/payload.json.mjs +2 -2
- package/dist/server/chunks/routes/api/projects/_project/modules.get.mjs +2 -2
- package/dist/server/chunks/routes/api/projects/catalog.get.mjs +2 -2
- package/dist/server/chunks/routes/renderer.mjs +2 -2
- package/dist/server/chunks/routes/ws.mjs +2 -2
- package/dist/server/index.mjs +2 -2
- package/dist/server/package.json +1 -1
- package/package.json +2 -2
- package/dist/public/_nuxt/BL-DadsH.js +0 -260
- package/dist/public/_nuxt/BO_d_Oyx.js +0 -6
- package/dist/public/_nuxt/BtuXxixc.js +0 -25
- package/dist/public/_nuxt/CC4_0abj.js +0 -1
- package/dist/public/_nuxt/CGsjOcfM.js +0 -21
- package/dist/public/_nuxt/COBlwcVj.js +0 -1
- package/dist/public/_nuxt/CjeAKHhp.js +0 -1
- package/dist/public/_nuxt/CvvesHM7.js +0 -105
- package/dist/public/_nuxt/IstswKJB.js +0 -4
- package/dist/public/_nuxt/N8W_Dp-N.js +0 -119
- package/dist/public/_nuxt/builds/meta/be10c896-ee75-4f4f-911d-c3f0a8b4d417.json +0 -1
- package/dist/public/_nuxt/entry.vHfFzkyD.css +0 -1
- package/dist/public/_nuxt/vkAmg0G5.js +0 -1
- package/dist/public/_nuxt/wUprbfrX.js +0 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import process from 'node:process';globalThis._importMeta_=globalThis._importMeta_||{url:"file:///_entry.js",env:process.env};import
|
|
2
|
-
import http from 'node:http';
|
|
1
|
+
import process from 'node:process';globalThis._importMeta_=globalThis._importMeta_||{url:"file:///_entry.js",env:process.env};import http from 'node:http';
|
|
3
2
|
import https from 'node:https';
|
|
4
3
|
import { EventEmitter } from 'node:events';
|
|
5
4
|
import { Buffer as Buffer$1 } from 'node:buffer';
|
|
6
|
-
import { promises, existsSync, mkdirSync, readFileSync, statSync, accessSync, constants } from 'node:fs';
|
|
5
|
+
import { promises, existsSync, mkdirSync, readFileSync, statSync, readdirSync, accessSync, constants } from 'node:fs';
|
|
7
6
|
import { resolve as resolve$1, dirname as dirname$1, join, sep, basename as basename$1 } from 'node:path';
|
|
8
7
|
import { createHash } from 'node:crypto';
|
|
9
8
|
import { DatabaseSync } from 'node:sqlite';
|
|
9
|
+
import { formatNumber } from '@lonewolfyx/utils';
|
|
10
10
|
import { glob } from 'glob';
|
|
11
11
|
import chokidar from 'chokidar';
|
|
12
12
|
import { homedir } from 'node:os';
|
|
@@ -4163,9 +4163,13 @@ const inlineAppConfig = {
|
|
|
4163
4163
|
"wi",
|
|
4164
4164
|
"wpf",
|
|
4165
4165
|
"zmdi",
|
|
4166
|
-
"zondicons"
|
|
4166
|
+
"zondicons",
|
|
4167
|
+
"ai"
|
|
4167
4168
|
],
|
|
4168
|
-
"fetchTimeout": 1500
|
|
4169
|
+
"fetchTimeout": 1500,
|
|
4170
|
+
"customCollections": [
|
|
4171
|
+
"ai"
|
|
4172
|
+
]
|
|
4169
4173
|
}
|
|
4170
4174
|
};
|
|
4171
4175
|
|
|
@@ -4267,7 +4271,7 @@ function _expandFromEnv(value) {
|
|
|
4267
4271
|
const _inlineRuntimeConfig = {
|
|
4268
4272
|
"app": {
|
|
4269
4273
|
"baseURL": "/",
|
|
4270
|
-
"buildId": "
|
|
4274
|
+
"buildId": "7ce9c611-6071-4cbd-8926-1e53d9ef21bd",
|
|
4271
4275
|
"buildAssetsDir": "/_nuxt/",
|
|
4272
4276
|
"cdnURL": ""
|
|
4273
4277
|
},
|
|
@@ -4295,7 +4299,7 @@ const _inlineRuntimeConfig = {
|
|
|
4295
4299
|
}
|
|
4296
4300
|
},
|
|
4297
4301
|
"public": {
|
|
4298
|
-
"appVersion": "
|
|
4302
|
+
"appVersion": "4.0.0",
|
|
4299
4303
|
"home": "/Users/tangchenghui"
|
|
4300
4304
|
},
|
|
4301
4305
|
"icon": {
|
|
@@ -4710,7 +4714,17 @@ function defineNitroPlugin(def) {
|
|
|
4710
4714
|
}
|
|
4711
4715
|
|
|
4712
4716
|
function openSqliteDatabase(location, options) {
|
|
4713
|
-
|
|
4717
|
+
const database = new DatabaseSync(location, options != null ? options : {});
|
|
4718
|
+
try {
|
|
4719
|
+
database.exec("PRAGMA journal_mode = WAL");
|
|
4720
|
+
database.exec("PRAGMA synchronous = NORMAL");
|
|
4721
|
+
} catch {
|
|
4722
|
+
}
|
|
4723
|
+
try {
|
|
4724
|
+
database.exec("PRAGMA busy_timeout = 15000");
|
|
4725
|
+
} catch {
|
|
4726
|
+
}
|
|
4727
|
+
return database;
|
|
4714
4728
|
}
|
|
4715
4729
|
|
|
4716
4730
|
const PROJECT_USAGE_PLATFORMS = [
|
|
@@ -4780,10 +4794,296 @@ function normalizeProjectUsageDetail(detail) {
|
|
|
4780
4794
|
};
|
|
4781
4795
|
}
|
|
4782
4796
|
|
|
4797
|
+
const compactNumberFormatter = new Intl.NumberFormat("en-US", {
|
|
4798
|
+
notation: "compact",
|
|
4799
|
+
maximumFractionDigits: 1
|
|
4800
|
+
});
|
|
4801
|
+
const currencyFormatter = new Intl.NumberFormat("en-US", {
|
|
4802
|
+
style: "currency",
|
|
4803
|
+
currency: "USD",
|
|
4804
|
+
minimumFractionDigits: 2,
|
|
4805
|
+
maximumFractionDigits: 2
|
|
4806
|
+
});
|
|
4807
|
+
const percentFormatter = new Intl.NumberFormat("en-US", {
|
|
4808
|
+
style: "percent",
|
|
4809
|
+
minimumFractionDigits: 1,
|
|
4810
|
+
maximumFractionDigits: 1
|
|
4811
|
+
});
|
|
4812
|
+
const dateKeyFormatter = new Intl.DateTimeFormat("en-CA", {
|
|
4813
|
+
day: "2-digit",
|
|
4814
|
+
month: "2-digit",
|
|
4815
|
+
year: "numeric"
|
|
4816
|
+
});
|
|
4817
|
+
const dateLabelFormatter = new Intl.DateTimeFormat("en-US", {
|
|
4818
|
+
day: "2-digit",
|
|
4819
|
+
month: "short",
|
|
4820
|
+
timeZone: "UTC",
|
|
4821
|
+
year: "numeric"
|
|
4822
|
+
});
|
|
4823
|
+
function normalizeNumber(value) {
|
|
4824
|
+
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
4825
|
+
}
|
|
4826
|
+
function roundCurrency(value) {
|
|
4827
|
+
return Math.round(value * 1e6) / 1e6;
|
|
4828
|
+
}
|
|
4829
|
+
function uniqueItems(items) {
|
|
4830
|
+
return Array.from(new Set(items));
|
|
4831
|
+
}
|
|
4832
|
+
function formatCompactNumber(value) {
|
|
4833
|
+
return compactNumberFormatter.format(normalizeNumber(value));
|
|
4834
|
+
}
|
|
4835
|
+
function formatCurrency(value) {
|
|
4836
|
+
return currencyFormatter.format(normalizeNumber(value));
|
|
4837
|
+
}
|
|
4838
|
+
function formatPercent(value) {
|
|
4839
|
+
return percentFormatter.format(normalizeNumber(value));
|
|
4840
|
+
}
|
|
4841
|
+
function buildPercentTrend(currentValue, previousValue) {
|
|
4842
|
+
const current = normalizeNumber(currentValue);
|
|
4843
|
+
const previous = normalizeNumber(previousValue);
|
|
4844
|
+
if (previous === 0) {
|
|
4845
|
+
return {
|
|
4846
|
+
label: current > 0 ? "+100%" : "0%",
|
|
4847
|
+
tone: current > 0 ? "up" : "neutral"
|
|
4848
|
+
};
|
|
4849
|
+
}
|
|
4850
|
+
const ratio = (current - previous) / previous;
|
|
4851
|
+
return {
|
|
4852
|
+
label: formatSignedPercent(ratio),
|
|
4853
|
+
tone: getTrendTone(ratio)
|
|
4854
|
+
};
|
|
4855
|
+
}
|
|
4856
|
+
function buildGrowthTrend(currentValue, previousValue, formatValue) {
|
|
4857
|
+
const current = Math.max(normalizeNumber(currentValue), 0);
|
|
4858
|
+
const previous = Math.max(normalizeNumber(previousValue), 0);
|
|
4859
|
+
if (previous === 0) {
|
|
4860
|
+
if (current === 0) {
|
|
4861
|
+
return {
|
|
4862
|
+
trend: "0.0%",
|
|
4863
|
+
trendTone: "neutral"
|
|
4864
|
+
};
|
|
4865
|
+
}
|
|
4866
|
+
return {
|
|
4867
|
+
trend: `+${formatValue(current)}`,
|
|
4868
|
+
trendTone: "up"
|
|
4869
|
+
};
|
|
4870
|
+
}
|
|
4871
|
+
const ratio = (current - previous) / previous;
|
|
4872
|
+
return {
|
|
4873
|
+
trend: formatSignedPercent(ratio),
|
|
4874
|
+
trendTone: getTrendTone(ratio)
|
|
4875
|
+
};
|
|
4876
|
+
}
|
|
4877
|
+
function buildInputOutputTokenSubvalue(usage) {
|
|
4878
|
+
var _a, _b;
|
|
4879
|
+
return {
|
|
4880
|
+
items: [
|
|
4881
|
+
{
|
|
4882
|
+
label: "In",
|
|
4883
|
+
value: formatCompactNumber((_a = usage == null ? void 0 : usage.inputTokens) != null ? _a : 0)
|
|
4884
|
+
},
|
|
4885
|
+
{
|
|
4886
|
+
label: "Out",
|
|
4887
|
+
value: formatCompactNumber((_b = usage == null ? void 0 : usage.outputTokens) != null ? _b : 0)
|
|
4888
|
+
}
|
|
4889
|
+
]
|
|
4890
|
+
};
|
|
4891
|
+
}
|
|
4892
|
+
function buildOverviewCardsWithTodayTokenBreakdown(overviewCards, dailyTokenUsage) {
|
|
4893
|
+
const todayDateKey = getDateKey(/* @__PURE__ */ new Date());
|
|
4894
|
+
return overviewCards.map((card) => card.name === "Today Tokens" ? {
|
|
4895
|
+
...card,
|
|
4896
|
+
subvalue: buildInputOutputTokenSubvalue(
|
|
4897
|
+
dailyTokenUsage.find((item) => getDateKeyFromLabel(item.date) === todayDateKey)
|
|
4898
|
+
)
|
|
4899
|
+
} : card);
|
|
4900
|
+
}
|
|
4901
|
+
function getDateKey(date) {
|
|
4902
|
+
var _a, _b, _c, _d, _e, _f;
|
|
4903
|
+
const parts = dateKeyFormatter.formatToParts(date);
|
|
4904
|
+
const year = (_b = (_a = parts.find((part) => part.type === "year")) == null ? void 0 : _a.value) != null ? _b : "0000";
|
|
4905
|
+
const month = (_d = (_c = parts.find((part) => part.type === "month")) == null ? void 0 : _c.value) != null ? _d : "01";
|
|
4906
|
+
const day = (_f = (_e = parts.find((part) => part.type === "day")) == null ? void 0 : _e.value) != null ? _f : "01";
|
|
4907
|
+
return `${year}-${month}-${day}`;
|
|
4908
|
+
}
|
|
4909
|
+
function getDateKeyFromLabel(label) {
|
|
4910
|
+
const date = new Date(label);
|
|
4911
|
+
if (Number.isNaN(date.getTime())) {
|
|
4912
|
+
return label;
|
|
4913
|
+
}
|
|
4914
|
+
return getDateKey(date);
|
|
4915
|
+
}
|
|
4916
|
+
function getPreviousDateKey(dateKey) {
|
|
4917
|
+
const [year, month, day] = dateKey.split("-").map((value) => Number.parseInt(value, 10));
|
|
4918
|
+
const date = new Date(year || 0, (month || 1) - 1, day || 1);
|
|
4919
|
+
date.setDate(date.getDate() - 1);
|
|
4920
|
+
return getDateKey(date);
|
|
4921
|
+
}
|
|
4922
|
+
function formatDateLabelFromDateKey(dateKey, fallback = dateKey) {
|
|
4923
|
+
const [year, month, day] = dateKey.split("-").map((value) => Number.parseInt(value, 10));
|
|
4924
|
+
if (!year || !month || !day) {
|
|
4925
|
+
return fallback;
|
|
4926
|
+
}
|
|
4927
|
+
return dateLabelFormatter.format(new Date(Date.UTC(year, month - 1, day)));
|
|
4928
|
+
}
|
|
4929
|
+
function buildProjectUsage(sessionUsage) {
|
|
4930
|
+
var _a;
|
|
4931
|
+
const projects = /* @__PURE__ */ new Map();
|
|
4932
|
+
for (const session of sessionUsage) {
|
|
4933
|
+
const project = (_a = projects.get(session.project)) != null ? _a : {
|
|
4934
|
+
costUSD: 0,
|
|
4935
|
+
repository: session.repository,
|
|
4936
|
+
sessions: 0,
|
|
4937
|
+
tokenTotal: 0
|
|
4938
|
+
};
|
|
4939
|
+
project.costUSD += session.costUSD;
|
|
4940
|
+
project.sessions += 1;
|
|
4941
|
+
project.tokenTotal += session.tokenTotal;
|
|
4942
|
+
projects.set(session.project, project);
|
|
4943
|
+
}
|
|
4944
|
+
const maxCost = Math.max(...Array.from(projects.values()).map((project) => project.costUSD), 0);
|
|
4945
|
+
return Array.from(projects.entries()).map(([label, project]) => ({
|
|
4946
|
+
costUSD: project.costUSD,
|
|
4947
|
+
detail: `${project.sessions} sessions / ${formatCompactNumber(project.tokenTotal)} tokens`,
|
|
4948
|
+
label,
|
|
4949
|
+
percent: maxCost > 0 ? project.costUSD / maxCost * 100 : 0,
|
|
4950
|
+
repository: project.repository,
|
|
4951
|
+
sessions: project.sessions,
|
|
4952
|
+
tokenTotal: project.tokenTotal,
|
|
4953
|
+
tone: "amber",
|
|
4954
|
+
value: formatCurrency(project.costUSD)
|
|
4955
|
+
})).sort((a, b) => b.costUSD - a.costUSD);
|
|
4956
|
+
}
|
|
4957
|
+
function mergeDailyTokenUsage(items) {
|
|
4958
|
+
var _a, _b, _c, _d, _e;
|
|
4959
|
+
const groups = /* @__PURE__ */ new Map();
|
|
4960
|
+
for (const item of items) {
|
|
4961
|
+
const dateKey = getDateKeyFromLabel(item.date);
|
|
4962
|
+
const group = (_a = groups.get(dateKey)) != null ? _a : {
|
|
4963
|
+
cachedInputTokens: 0,
|
|
4964
|
+
costUSD: 0,
|
|
4965
|
+
date: formatDateLabelFromDateKey(dateKey, item.date),
|
|
4966
|
+
inputTokens: 0,
|
|
4967
|
+
models: /* @__PURE__ */ new Map(),
|
|
4968
|
+
outputTokens: 0,
|
|
4969
|
+
platforms: /* @__PURE__ */ new Map(),
|
|
4970
|
+
reasoningOutputTokens: 0,
|
|
4971
|
+
totalTokens: 0
|
|
4972
|
+
};
|
|
4973
|
+
group.cachedInputTokens += item.cachedInputTokens;
|
|
4974
|
+
group.costUSD += item.costUSD;
|
|
4975
|
+
group.inputTokens += item.inputTokens;
|
|
4976
|
+
group.outputTokens += item.outputTokens;
|
|
4977
|
+
group.reasoningOutputTokens += item.reasoningOutputTokens;
|
|
4978
|
+
group.totalTokens += item.totalTokens;
|
|
4979
|
+
for (const [modelName, usage] of Object.entries(item.models)) {
|
|
4980
|
+
const model = (_b = group.models.get(modelName)) != null ? _b : createEmptyModelUsage();
|
|
4981
|
+
model.cachedInputTokens += usage.cachedInputTokens;
|
|
4982
|
+
model.costUSD += usage.costUSD;
|
|
4983
|
+
model.inputTokens += usage.inputTokens;
|
|
4984
|
+
model.isFallback = model.isFallback || usage.isFallback;
|
|
4985
|
+
model.outputTokens += usage.outputTokens;
|
|
4986
|
+
model.reasoningOutputTokens += usage.reasoningOutputTokens;
|
|
4987
|
+
model.totalTokens += usage.totalTokens;
|
|
4988
|
+
group.models.set(modelName, model);
|
|
4989
|
+
}
|
|
4990
|
+
for (const [platform, platformUsage] of Object.entries((_c = item.platforms) != null ? _c : {})) {
|
|
4991
|
+
const currentPlatformUsage = (_d = group.platforms.get(platform)) != null ? _d : createEmptyDailyPlatformTokenUsage();
|
|
4992
|
+
currentPlatformUsage.cachedInputTokens += platformUsage.cachedInputTokens;
|
|
4993
|
+
currentPlatformUsage.costUSD += platformUsage.costUSD;
|
|
4994
|
+
currentPlatformUsage.inputTokens += platformUsage.inputTokens;
|
|
4995
|
+
currentPlatformUsage.outputTokens += platformUsage.outputTokens;
|
|
4996
|
+
currentPlatformUsage.reasoningOutputTokens += platformUsage.reasoningOutputTokens;
|
|
4997
|
+
currentPlatformUsage.totalTokens += platformUsage.totalTokens;
|
|
4998
|
+
for (const [modelName, usage] of Object.entries(platformUsage.models)) {
|
|
4999
|
+
const model = (_e = currentPlatformUsage.models[modelName]) != null ? _e : createEmptyModelUsage();
|
|
5000
|
+
model.cachedInputTokens += usage.cachedInputTokens;
|
|
5001
|
+
model.costUSD += usage.costUSD;
|
|
5002
|
+
model.inputTokens += usage.inputTokens;
|
|
5003
|
+
model.isFallback = model.isFallback || usage.isFallback;
|
|
5004
|
+
model.outputTokens += usage.outputTokens;
|
|
5005
|
+
model.reasoningOutputTokens += usage.reasoningOutputTokens;
|
|
5006
|
+
model.totalTokens += usage.totalTokens;
|
|
5007
|
+
currentPlatformUsage.models[modelName] = model;
|
|
5008
|
+
}
|
|
5009
|
+
group.platforms.set(platform, currentPlatformUsage);
|
|
5010
|
+
}
|
|
5011
|
+
groups.set(dateKey, group);
|
|
5012
|
+
}
|
|
5013
|
+
return Array.from(groups.entries()).sort((a, b) => b[0].localeCompare(a[0])).map(([, group]) => ({
|
|
5014
|
+
cachedInputTokens: group.cachedInputTokens,
|
|
5015
|
+
costUSD: roundCurrency(group.costUSD),
|
|
5016
|
+
date: group.date,
|
|
5017
|
+
inputTokens: group.inputTokens,
|
|
5018
|
+
models: Object.fromEntries(group.models.entries()),
|
|
5019
|
+
outputTokens: group.outputTokens,
|
|
5020
|
+
platforms: group.platforms.size > 0 ? Object.fromEntries(Array.from(group.platforms.entries()).map(([platform, usage]) => [platform, {
|
|
5021
|
+
...usage,
|
|
5022
|
+
costUSD: roundCurrency(usage.costUSD),
|
|
5023
|
+
models: Object.fromEntries(Object.entries(usage.models).map(([modelName, modelUsage]) => [modelName, {
|
|
5024
|
+
...modelUsage,
|
|
5025
|
+
costUSD: roundCurrency(modelUsage.costUSD)
|
|
5026
|
+
}]))
|
|
5027
|
+
}])) : void 0,
|
|
5028
|
+
reasoningOutputTokens: group.reasoningOutputTokens,
|
|
5029
|
+
totalTokens: group.totalTokens
|
|
5030
|
+
}));
|
|
5031
|
+
}
|
|
5032
|
+
function mergeMonthlyModelUsage(items) {
|
|
5033
|
+
var _a;
|
|
5034
|
+
const groups = /* @__PURE__ */ new Map();
|
|
5035
|
+
for (const item of items) {
|
|
5036
|
+
const key = `${item.month}__${item.model}`;
|
|
5037
|
+
const group = (_a = groups.get(key)) != null ? _a : {
|
|
5038
|
+
model: item.model,
|
|
5039
|
+
month: item.month,
|
|
5040
|
+
tokenTotal: 0
|
|
5041
|
+
};
|
|
5042
|
+
group.tokenTotal += item.tokenTotal;
|
|
5043
|
+
groups.set(key, group);
|
|
5044
|
+
}
|
|
5045
|
+
return Array.from(groups.values()).sort((a, b) => a.month.localeCompare(b.month) || a.model.localeCompare(b.model));
|
|
5046
|
+
}
|
|
5047
|
+
function formatSignedPercent(value) {
|
|
5048
|
+
const prefix = value > 0 ? "+" : "";
|
|
5049
|
+
return `${prefix}${formatPercent(value)}`;
|
|
5050
|
+
}
|
|
5051
|
+
function getTrendTone(value) {
|
|
5052
|
+
if (value > 0) {
|
|
5053
|
+
return "up";
|
|
5054
|
+
}
|
|
5055
|
+
if (value < 0) {
|
|
5056
|
+
return "down";
|
|
5057
|
+
}
|
|
5058
|
+
return "neutral";
|
|
5059
|
+
}
|
|
5060
|
+
function createEmptyModelUsage() {
|
|
5061
|
+
return {
|
|
5062
|
+
cachedInputTokens: 0,
|
|
5063
|
+
costUSD: 0,
|
|
5064
|
+
inputTokens: 0,
|
|
5065
|
+
isFallback: false,
|
|
5066
|
+
outputTokens: 0,
|
|
5067
|
+
reasoningOutputTokens: 0,
|
|
5068
|
+
totalTokens: 0
|
|
5069
|
+
};
|
|
5070
|
+
}
|
|
5071
|
+
function createEmptyDailyPlatformTokenUsage() {
|
|
5072
|
+
return {
|
|
5073
|
+
cachedInputTokens: 0,
|
|
5074
|
+
costUSD: 0,
|
|
5075
|
+
inputTokens: 0,
|
|
5076
|
+
models: {},
|
|
5077
|
+
outputTokens: 0,
|
|
5078
|
+
reasoningOutputTokens: 0,
|
|
5079
|
+
totalTokens: 0
|
|
5080
|
+
};
|
|
5081
|
+
}
|
|
5082
|
+
|
|
4783
5083
|
var __defProp$1 = Object.defineProperty;
|
|
4784
5084
|
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4785
5085
|
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, key + "" , value);
|
|
4786
|
-
const CACHE_SCHEMA_VERSION =
|
|
5086
|
+
const CACHE_SCHEMA_VERSION = 9;
|
|
4787
5087
|
const ROW_KEY_SEPARATOR = "";
|
|
4788
5088
|
const CACHE_SCHEMA_SQL = `
|
|
4789
5089
|
CREATE TABLE IF NOT EXISTS cache_schema_meta (
|
|
@@ -4800,7 +5100,8 @@ const CACHE_SCHEMA_SQL = `
|
|
|
4800
5100
|
|
|
4801
5101
|
CREATE TABLE IF NOT EXISTS project_catalog_entries (
|
|
4802
5102
|
label TEXT PRIMARY KEY,
|
|
4803
|
-
|
|
5103
|
+
platforms_json TEXT NOT NULL,
|
|
5104
|
+
total_tokens INTEGER NOT NULL,
|
|
4804
5105
|
updated_at TEXT NOT NULL
|
|
4805
5106
|
);
|
|
4806
5107
|
|
|
@@ -4845,6 +5146,7 @@ const CACHE_SCHEMA_SQL = `
|
|
|
4845
5146
|
name TEXT NOT NULL,
|
|
4846
5147
|
value TEXT NOT NULL,
|
|
4847
5148
|
detail TEXT,
|
|
5149
|
+
subvalue_json TEXT,
|
|
4848
5150
|
trend TEXT NOT NULL,
|
|
4849
5151
|
trend_tone TEXT NOT NULL,
|
|
4850
5152
|
PRIMARY KEY (scope_key, position),
|
|
@@ -4923,6 +5225,7 @@ const CACHE_SCHEMA_SQL = `
|
|
|
4923
5225
|
output_tokens INTEGER NOT NULL,
|
|
4924
5226
|
reasoning_output_tokens INTEGER NOT NULL,
|
|
4925
5227
|
total_tokens INTEGER NOT NULL,
|
|
5228
|
+
cost_usd REAL NOT NULL,
|
|
4926
5229
|
is_fallback INTEGER NOT NULL,
|
|
4927
5230
|
PRIMARY KEY (scope_key, date, model),
|
|
4928
5231
|
FOREIGN KEY (scope_key, date)
|
|
@@ -4991,6 +5294,8 @@ const CACHE_SCHEMA_SQL = `
|
|
|
4991
5294
|
|
|
4992
5295
|
CREATE INDEX IF NOT EXISTS idx_usage_scope_sessions_order
|
|
4993
5296
|
ON usage_scope_sessions(scope_key, session_order);
|
|
5297
|
+
CREATE INDEX IF NOT EXISTS idx_usage_scope_sessions_started_at
|
|
5298
|
+
ON usage_scope_sessions(scope_key, started_at);
|
|
4994
5299
|
|
|
4995
5300
|
CREATE TABLE IF NOT EXISTS usage_scope_session_models (
|
|
4996
5301
|
scope_key TEXT NOT NULL,
|
|
@@ -5018,6 +5323,7 @@ const CACHE_SCHEMA_SQL = `
|
|
|
5018
5323
|
cached_input_tokens INTEGER,
|
|
5019
5324
|
output_tokens INTEGER,
|
|
5020
5325
|
reasoning_output_tokens INTEGER,
|
|
5326
|
+
extra_total_tokens INTEGER,
|
|
5021
5327
|
total_tokens INTEGER,
|
|
5022
5328
|
usage_cost_usd REAL,
|
|
5023
5329
|
cache_creation_tokens INTEGER,
|
|
@@ -5029,6 +5335,10 @@ const CACHE_SCHEMA_SQL = `
|
|
|
5029
5335
|
REFERENCES usage_scope_sessions(scope_key, session_key)
|
|
5030
5336
|
ON DELETE CASCADE
|
|
5031
5337
|
);
|
|
5338
|
+
CREATE INDEX IF NOT EXISTS idx_usage_scope_interactions_role_timestamp
|
|
5339
|
+
ON usage_scope_interactions(scope_key, role, timestamp);
|
|
5340
|
+
CREATE INDEX IF NOT EXISTS idx_usage_scope_interactions_timestamp
|
|
5341
|
+
ON usage_scope_interactions(scope_key, timestamp);
|
|
5032
5342
|
|
|
5033
5343
|
CREATE TABLE IF NOT EXISTS indexed_files (
|
|
5034
5344
|
path TEXT PRIMARY KEY,
|
|
@@ -5080,6 +5390,7 @@ const CACHE_SCHEMA_SQL = `
|
|
|
5080
5390
|
cached_input_tokens INTEGER,
|
|
5081
5391
|
output_tokens INTEGER,
|
|
5082
5392
|
reasoning_output_tokens INTEGER,
|
|
5393
|
+
extra_total_tokens INTEGER,
|
|
5083
5394
|
total_tokens INTEGER,
|
|
5084
5395
|
usage_cost_usd REAL,
|
|
5085
5396
|
cache_creation_tokens INTEGER,
|
|
@@ -5104,7 +5415,7 @@ class UsageCacheRepository {
|
|
|
5104
5415
|
if (!meta) {
|
|
5105
5416
|
return null;
|
|
5106
5417
|
}
|
|
5107
|
-
const scopes = this.loadHydratedUsageScopes("bootstrap");
|
|
5418
|
+
const scopes = this.loadHydratedUsageScopes("bootstrap", false);
|
|
5108
5419
|
const payload = Object.fromEntries(
|
|
5109
5420
|
PROJECT_USAGE_PLATFORMS.map((platform) => {
|
|
5110
5421
|
var _a2;
|
|
@@ -5126,20 +5437,76 @@ class UsageCacheRepository {
|
|
|
5126
5437
|
saveBootstrap(payload) {
|
|
5127
5438
|
this.persistBootstrap(payload);
|
|
5128
5439
|
}
|
|
5440
|
+
loadHomeDashboardTodayInsights() {
|
|
5441
|
+
const { previousDayStartAt, todayStartAt, tomorrowStartAt } = getHomeInsightRange();
|
|
5442
|
+
const promptCount = groupTodayInsightCounts(this.database.prepare(`
|
|
5443
|
+
SELECT
|
|
5444
|
+
CASE
|
|
5445
|
+
WHEN interaction.timestamp >= ? AND interaction.timestamp < ? THEN 'today'
|
|
5446
|
+
ELSE 'previous'
|
|
5447
|
+
END AS period,
|
|
5448
|
+
COUNT(*) AS total
|
|
5449
|
+
FROM usage_scope_interactions AS interaction
|
|
5450
|
+
JOIN usage_scopes AS scope ON scope.scope_key = interaction.scope_key
|
|
5451
|
+
WHERE scope.scope_kind = 'bootstrap'
|
|
5452
|
+
AND interaction.role = 'user'
|
|
5453
|
+
AND interaction.timestamp IS NOT NULL
|
|
5454
|
+
AND interaction.timestamp >= ?
|
|
5455
|
+
AND interaction.timestamp < ?
|
|
5456
|
+
GROUP BY period
|
|
5457
|
+
`).all(todayStartAt, tomorrowStartAt, previousDayStartAt, tomorrowStartAt));
|
|
5458
|
+
const sessionCount = groupTodayInsightCounts(this.database.prepare(`
|
|
5459
|
+
SELECT
|
|
5460
|
+
CASE
|
|
5461
|
+
WHEN session.started_at >= ? AND session.started_at < ? THEN 'today'
|
|
5462
|
+
ELSE 'previous'
|
|
5463
|
+
END AS period,
|
|
5464
|
+
COUNT(*) AS total
|
|
5465
|
+
FROM usage_scope_sessions AS session
|
|
5466
|
+
JOIN usage_scopes AS scope ON scope.scope_key = session.scope_key
|
|
5467
|
+
WHERE scope.scope_kind = 'bootstrap'
|
|
5468
|
+
AND session.started_at >= ?
|
|
5469
|
+
AND session.started_at < ?
|
|
5470
|
+
GROUP BY period
|
|
5471
|
+
`).all(todayStartAt, tomorrowStartAt, previousDayStartAt, tomorrowStartAt));
|
|
5472
|
+
return {
|
|
5473
|
+
previousPromptCount: promptCount.previous,
|
|
5474
|
+
previousSessionCount: sessionCount.previous,
|
|
5475
|
+
promptCount: promptCount.today,
|
|
5476
|
+
sessionCount: sessionCount.today,
|
|
5477
|
+
todayHourlyUsage: buildTodayHourlyUsage(this.database.prepare(`
|
|
5478
|
+
SELECT
|
|
5479
|
+
scope.platform AS platform,
|
|
5480
|
+
CAST(strftime('%H', interaction.timestamp, 'localtime') AS INTEGER) AS hour,
|
|
5481
|
+
ROUND(SUM(COALESCE(interaction.usage_cost_usd, 0)), 6) AS cost_usd,
|
|
5482
|
+
SUM(COALESCE(interaction.total_tokens, 0)) AS total_tokens
|
|
5483
|
+
FROM usage_scope_interactions AS interaction
|
|
5484
|
+
JOIN usage_scopes AS scope ON scope.scope_key = interaction.scope_key
|
|
5485
|
+
WHERE scope.scope_kind = 'bootstrap'
|
|
5486
|
+
AND interaction.timestamp IS NOT NULL
|
|
5487
|
+
AND interaction.total_tokens IS NOT NULL
|
|
5488
|
+
AND interaction.timestamp >= ?
|
|
5489
|
+
AND interaction.timestamp < ?
|
|
5490
|
+
GROUP BY scope.platform, hour
|
|
5491
|
+
ORDER BY hour ASC, scope.platform ASC
|
|
5492
|
+
`).all(todayStartAt, tomorrowStartAt))
|
|
5493
|
+
};
|
|
5494
|
+
}
|
|
5129
5495
|
loadProjectCatalog() {
|
|
5130
5496
|
const meta = this.getCacheState("project_catalog");
|
|
5131
5497
|
if (!meta) {
|
|
5132
5498
|
return null;
|
|
5133
5499
|
}
|
|
5134
5500
|
const rows = this.database.prepare(`
|
|
5135
|
-
SELECT label,
|
|
5501
|
+
SELECT label, platforms_json, total_tokens
|
|
5136
5502
|
FROM project_catalog_entries
|
|
5137
5503
|
ORDER BY label ASC
|
|
5138
5504
|
`).all();
|
|
5139
5505
|
return {
|
|
5140
5506
|
payload: rows.map((row) => ({
|
|
5141
5507
|
label: row.label,
|
|
5142
|
-
|
|
5508
|
+
platforms: parseProjectCatalogPlatforms(row.platforms_json),
|
|
5509
|
+
totalTokens: row.total_tokens
|
|
5143
5510
|
})),
|
|
5144
5511
|
payloadHash: meta.payload_hash,
|
|
5145
5512
|
updatedAt: meta.updated_at
|
|
@@ -5235,6 +5602,7 @@ class UsageCacheRepository {
|
|
|
5235
5602
|
cached_input_tokens,
|
|
5236
5603
|
output_tokens,
|
|
5237
5604
|
reasoning_output_tokens,
|
|
5605
|
+
extra_total_tokens,
|
|
5238
5606
|
total_tokens,
|
|
5239
5607
|
usage_cost_usd,
|
|
5240
5608
|
cache_creation_tokens,
|
|
@@ -5275,7 +5643,7 @@ class UsageCacheRepository {
|
|
|
5275
5643
|
});
|
|
5276
5644
|
}
|
|
5277
5645
|
upsertIndexedSourceFiles(files) {
|
|
5278
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t;
|
|
5646
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v;
|
|
5279
5647
|
if (files.length === 0) {
|
|
5280
5648
|
return;
|
|
5281
5649
|
}
|
|
@@ -5318,6 +5686,7 @@ class UsageCacheRepository {
|
|
|
5318
5686
|
cached_input_tokens,
|
|
5319
5687
|
output_tokens,
|
|
5320
5688
|
reasoning_output_tokens,
|
|
5689
|
+
extra_total_tokens,
|
|
5321
5690
|
total_tokens,
|
|
5322
5691
|
usage_cost_usd,
|
|
5323
5692
|
cache_creation_tokens,
|
|
@@ -5325,7 +5694,7 @@ class UsageCacheRepository {
|
|
|
5325
5694
|
tool_tokens,
|
|
5326
5695
|
is_fallback_model
|
|
5327
5696
|
)
|
|
5328
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
5697
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
5329
5698
|
`);
|
|
5330
5699
|
this.database.exec("BEGIN");
|
|
5331
5700
|
try {
|
|
@@ -5364,12 +5733,13 @@ class UsageCacheRepository {
|
|
|
5364
5733
|
(_e = (_d = interaction.usage) == null ? void 0 : _d.cachedInputTokens) != null ? _e : null,
|
|
5365
5734
|
(_g = (_f = interaction.usage) == null ? void 0 : _f.outputTokens) != null ? _g : null,
|
|
5366
5735
|
(_i = (_h = interaction.usage) == null ? void 0 : _h.reasoningOutputTokens) != null ? _i : null,
|
|
5367
|
-
(_k = (_j = interaction.usage) == null ? void 0 : _j.
|
|
5368
|
-
(_m = (_l = interaction.usage) == null ? void 0 : _l.
|
|
5369
|
-
(_o = (_n = interaction.usage) == null ? void 0 : _n.
|
|
5370
|
-
(_q = (_p = interaction.usage) == null ? void 0 : _p.
|
|
5371
|
-
(_s = (_r = interaction.usage) == null ? void 0 : _r.
|
|
5372
|
-
((_t = interaction.usage) == null ? void 0 : _t.
|
|
5736
|
+
(_k = (_j = interaction.usage) == null ? void 0 : _j.extraTotalTokens) != null ? _k : null,
|
|
5737
|
+
(_m = (_l = interaction.usage) == null ? void 0 : _l.totalTokens) != null ? _m : null,
|
|
5738
|
+
(_o = (_n = interaction.usage) == null ? void 0 : _n.costUSD) != null ? _o : null,
|
|
5739
|
+
(_q = (_p = interaction.usage) == null ? void 0 : _p.cacheCreationTokens) != null ? _q : null,
|
|
5740
|
+
(_s = (_r = interaction.usage) == null ? void 0 : _r.cacheReadTokens) != null ? _s : null,
|
|
5741
|
+
(_u = (_t = interaction.usage) == null ? void 0 : _t.toolTokens) != null ? _u : null,
|
|
5742
|
+
((_v = interaction.usage) == null ? void 0 : _v.isFallbackModel) ? 1 : 0
|
|
5373
5743
|
);
|
|
5374
5744
|
}
|
|
5375
5745
|
}
|
|
@@ -5442,6 +5812,10 @@ class UsageCacheRepository {
|
|
|
5442
5812
|
initializeSchema() {
|
|
5443
5813
|
this.database.exec(CACHE_SCHEMA_SQL);
|
|
5444
5814
|
this.ensureIndexedFilesCacheSignatureColumn();
|
|
5815
|
+
this.ensureDailyUsageModelCostColumn();
|
|
5816
|
+
this.ensureOverviewCardSubvalueColumn();
|
|
5817
|
+
this.ensureProjectCatalogColumns();
|
|
5818
|
+
this.ensureInteractionExtraTotalTokenColumns();
|
|
5445
5819
|
const currentSchemaVersion = this.getCurrentSchemaVersion();
|
|
5446
5820
|
if (currentSchemaVersion >= CACHE_SCHEMA_VERSION) {
|
|
5447
5821
|
return;
|
|
@@ -5511,9 +5885,71 @@ class UsageCacheRepository {
|
|
|
5511
5885
|
}
|
|
5512
5886
|
this.database.exec("ALTER TABLE indexed_files ADD COLUMN cache_signature TEXT NOT NULL DEFAULT ''");
|
|
5513
5887
|
}
|
|
5514
|
-
|
|
5515
|
-
this.
|
|
5516
|
-
|
|
5888
|
+
ensureProjectCatalogColumns() {
|
|
5889
|
+
if (!this.hasTable("project_catalog_entries")) {
|
|
5890
|
+
return;
|
|
5891
|
+
}
|
|
5892
|
+
const columns = this.database.prepare("PRAGMA table_info(project_catalog_entries)").all();
|
|
5893
|
+
if (!columns.some((column) => column.name === "platforms_json")) {
|
|
5894
|
+
this.database.exec("ALTER TABLE project_catalog_entries ADD COLUMN platforms_json TEXT NOT NULL DEFAULT '[]'");
|
|
5895
|
+
}
|
|
5896
|
+
if (!columns.some((column) => column.name === "total_tokens")) {
|
|
5897
|
+
this.database.exec("ALTER TABLE project_catalog_entries ADD COLUMN total_tokens INTEGER NOT NULL DEFAULT 0");
|
|
5898
|
+
}
|
|
5899
|
+
if (!columns.some((column) => column.name === "type")) {
|
|
5900
|
+
return;
|
|
5901
|
+
}
|
|
5902
|
+
const legacyRows = this.database.prepare(`
|
|
5903
|
+
SELECT label, type
|
|
5904
|
+
FROM project_catalog_entries
|
|
5905
|
+
`).all();
|
|
5906
|
+
const updateStatement = this.database.prepare(`
|
|
5907
|
+
UPDATE project_catalog_entries
|
|
5908
|
+
SET platforms_json = ?, total_tokens = 0
|
|
5909
|
+
WHERE label = ?
|
|
5910
|
+
`);
|
|
5911
|
+
for (const row of legacyRows) {
|
|
5912
|
+
const platforms = row.type === "mixed" ? [] : [row.type];
|
|
5913
|
+
updateStatement.run(JSON.stringify(platforms), row.label);
|
|
5914
|
+
}
|
|
5915
|
+
}
|
|
5916
|
+
ensureDailyUsageModelCostColumn() {
|
|
5917
|
+
if (!this.hasTable("usage_scope_daily_usage_models")) {
|
|
5918
|
+
return;
|
|
5919
|
+
}
|
|
5920
|
+
const columns = this.database.prepare("PRAGMA table_info(usage_scope_daily_usage_models)").all();
|
|
5921
|
+
if (columns.some((column) => column.name === "cost_usd")) {
|
|
5922
|
+
return;
|
|
5923
|
+
}
|
|
5924
|
+
this.database.exec("ALTER TABLE usage_scope_daily_usage_models ADD COLUMN cost_usd REAL NOT NULL DEFAULT 0");
|
|
5925
|
+
}
|
|
5926
|
+
ensureOverviewCardSubvalueColumn() {
|
|
5927
|
+
if (!this.hasTable("usage_scope_overview_cards")) {
|
|
5928
|
+
return;
|
|
5929
|
+
}
|
|
5930
|
+
const columns = this.database.prepare("PRAGMA table_info(usage_scope_overview_cards)").all();
|
|
5931
|
+
if (columns.some((column) => column.name === "subvalue_json")) {
|
|
5932
|
+
return;
|
|
5933
|
+
}
|
|
5934
|
+
this.database.exec("ALTER TABLE usage_scope_overview_cards ADD COLUMN subvalue_json TEXT");
|
|
5935
|
+
}
|
|
5936
|
+
ensureInteractionExtraTotalTokenColumns() {
|
|
5937
|
+
if (this.hasTable("usage_scope_interactions")) {
|
|
5938
|
+
const usageScopeInteractionColumns = this.database.prepare("PRAGMA table_info(usage_scope_interactions)").all();
|
|
5939
|
+
if (!usageScopeInteractionColumns.some((column) => column.name === "extra_total_tokens")) {
|
|
5940
|
+
this.database.exec("ALTER TABLE usage_scope_interactions ADD COLUMN extra_total_tokens INTEGER");
|
|
5941
|
+
}
|
|
5942
|
+
}
|
|
5943
|
+
if (this.hasTable("indexed_fragment_interactions")) {
|
|
5944
|
+
const indexedInteractionColumns = this.database.prepare("PRAGMA table_info(indexed_fragment_interactions)").all();
|
|
5945
|
+
if (!indexedInteractionColumns.some((column) => column.name === "extra_total_tokens")) {
|
|
5946
|
+
this.database.exec("ALTER TABLE indexed_fragment_interactions ADD COLUMN extra_total_tokens INTEGER");
|
|
5947
|
+
}
|
|
5948
|
+
}
|
|
5949
|
+
}
|
|
5950
|
+
clearNormalizedTables() {
|
|
5951
|
+
this.database.exec("BEGIN");
|
|
5952
|
+
try {
|
|
5517
5953
|
this.database.prepare("DELETE FROM cache_state").run();
|
|
5518
5954
|
this.database.prepare("DELETE FROM project_catalog_entries").run();
|
|
5519
5955
|
this.database.prepare("DELETE FROM projects").run();
|
|
@@ -5576,14 +6012,14 @@ class UsageCacheRepository {
|
|
|
5576
6012
|
const payloadHash = (_b = options.payloadHash) != null ? _b : createPayloadHash(JSON.stringify(payload));
|
|
5577
6013
|
const deleteStatement = this.database.prepare("DELETE FROM project_catalog_entries");
|
|
5578
6014
|
const insertStatement = this.database.prepare(`
|
|
5579
|
-
INSERT INTO project_catalog_entries (label,
|
|
5580
|
-
VALUES (?, ?, ?)
|
|
6015
|
+
INSERT INTO project_catalog_entries (label, platforms_json, total_tokens, updated_at)
|
|
6016
|
+
VALUES (?, ?, ?, ?)
|
|
5581
6017
|
`);
|
|
5582
6018
|
this.database.exec("BEGIN");
|
|
5583
6019
|
try {
|
|
5584
6020
|
deleteStatement.run();
|
|
5585
6021
|
for (const item of payload) {
|
|
5586
|
-
insertStatement.run(item.label, item.
|
|
6022
|
+
insertStatement.run(item.label, JSON.stringify(item.platforms), item.totalTokens, updatedAt);
|
|
5587
6023
|
}
|
|
5588
6024
|
this.upsertCacheState("project_catalog", payloadHash, updatedAt);
|
|
5589
6025
|
this.database.exec("COMMIT");
|
|
@@ -5603,7 +6039,7 @@ class UsageCacheRepository {
|
|
|
5603
6039
|
`).run(key, payloadHash, updatedAt, version != null ? version : null);
|
|
5604
6040
|
}
|
|
5605
6041
|
insertUsageScope(options) {
|
|
5606
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D;
|
|
6042
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F;
|
|
5607
6043
|
const scopeKey = createUsageScopeKey(options.kind, options.platform, options.projectLabel);
|
|
5608
6044
|
const payloadHash = createPayloadHash(JSON.stringify(options.usage));
|
|
5609
6045
|
const insertScopeStatement = this.database.prepare(`
|
|
@@ -5631,10 +6067,11 @@ class UsageCacheRepository {
|
|
|
5631
6067
|
name,
|
|
5632
6068
|
value,
|
|
5633
6069
|
detail,
|
|
6070
|
+
subvalue_json,
|
|
5634
6071
|
trend,
|
|
5635
6072
|
trend_tone
|
|
5636
6073
|
)
|
|
5637
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
6074
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
5638
6075
|
`);
|
|
5639
6076
|
const insertTokenRowStatement = this.database.prepare(`
|
|
5640
6077
|
INSERT INTO usage_scope_token_rows (
|
|
@@ -5699,9 +6136,10 @@ class UsageCacheRepository {
|
|
|
5699
6136
|
output_tokens,
|
|
5700
6137
|
reasoning_output_tokens,
|
|
5701
6138
|
total_tokens,
|
|
6139
|
+
cost_usd,
|
|
5702
6140
|
is_fallback
|
|
5703
6141
|
)
|
|
5704
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
6142
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
5705
6143
|
`);
|
|
5706
6144
|
const insertMonthlyModelStatement = this.database.prepare(`
|
|
5707
6145
|
INSERT INTO usage_scope_monthly_model_usage (
|
|
@@ -5781,6 +6219,7 @@ class UsageCacheRepository {
|
|
|
5781
6219
|
cached_input_tokens,
|
|
5782
6220
|
output_tokens,
|
|
5783
6221
|
reasoning_output_tokens,
|
|
6222
|
+
extra_total_tokens,
|
|
5784
6223
|
total_tokens,
|
|
5785
6224
|
usage_cost_usd,
|
|
5786
6225
|
cache_creation_tokens,
|
|
@@ -5788,7 +6227,7 @@ class UsageCacheRepository {
|
|
|
5788
6227
|
tool_tokens,
|
|
5789
6228
|
is_fallback_model
|
|
5790
6229
|
)
|
|
5791
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
6230
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
5792
6231
|
`);
|
|
5793
6232
|
insertScopeStatement.run(
|
|
5794
6233
|
scopeKey,
|
|
@@ -5812,6 +6251,7 @@ class UsageCacheRepository {
|
|
|
5812
6251
|
card.name,
|
|
5813
6252
|
card.value,
|
|
5814
6253
|
(_j = card.detail) != null ? _j : null,
|
|
6254
|
+
card.subvalue ? JSON.stringify(card.subvalue) : null,
|
|
5815
6255
|
card.trend,
|
|
5816
6256
|
card.trendTone
|
|
5817
6257
|
);
|
|
@@ -5865,6 +6305,7 @@ class UsageCacheRepository {
|
|
|
5865
6305
|
usage.outputTokens,
|
|
5866
6306
|
usage.reasoningOutputTokens,
|
|
5867
6307
|
usage.totalTokens,
|
|
6308
|
+
usage.costUSD,
|
|
5868
6309
|
usage.isFallback ? 1 : 0
|
|
5869
6310
|
);
|
|
5870
6311
|
}
|
|
@@ -5937,17 +6378,18 @@ class UsageCacheRepository {
|
|
|
5937
6378
|
(_o = (_n = interaction.usage) == null ? void 0 : _n.cachedInputTokens) != null ? _o : null,
|
|
5938
6379
|
(_q = (_p = interaction.usage) == null ? void 0 : _p.outputTokens) != null ? _q : null,
|
|
5939
6380
|
(_s = (_r = interaction.usage) == null ? void 0 : _r.reasoningOutputTokens) != null ? _s : null,
|
|
5940
|
-
(_u = (_t = interaction.usage) == null ? void 0 : _t.
|
|
5941
|
-
(_w = (_v = interaction.usage) == null ? void 0 : _v.
|
|
5942
|
-
(_y = (_x = interaction.usage) == null ? void 0 : _x.
|
|
5943
|
-
(_A = (_z = interaction.usage) == null ? void 0 : _z.
|
|
5944
|
-
(_C = (_B = interaction.usage) == null ? void 0 : _B.
|
|
5945
|
-
((_D = interaction.usage) == null ? void 0 : _D.
|
|
6381
|
+
(_u = (_t = interaction.usage) == null ? void 0 : _t.extraTotalTokens) != null ? _u : null,
|
|
6382
|
+
(_w = (_v = interaction.usage) == null ? void 0 : _v.totalTokens) != null ? _w : null,
|
|
6383
|
+
(_y = (_x = interaction.usage) == null ? void 0 : _x.costUSD) != null ? _y : null,
|
|
6384
|
+
(_A = (_z = interaction.usage) == null ? void 0 : _z.cacheCreationTokens) != null ? _A : null,
|
|
6385
|
+
(_C = (_B = interaction.usage) == null ? void 0 : _B.cacheReadTokens) != null ? _C : null,
|
|
6386
|
+
(_E = (_D = interaction.usage) == null ? void 0 : _D.toolTokens) != null ? _E : null,
|
|
6387
|
+
((_F = interaction.usage) == null ? void 0 : _F.isFallbackModel) ? 1 : 0
|
|
5946
6388
|
);
|
|
5947
6389
|
}
|
|
5948
6390
|
}
|
|
5949
6391
|
}
|
|
5950
|
-
loadHydratedUsageScopes(kind) {
|
|
6392
|
+
loadHydratedUsageScopes(kind, includeInteractions = true) {
|
|
5951
6393
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
5952
6394
|
const scopes = this.database.prepare(`
|
|
5953
6395
|
SELECT
|
|
@@ -5972,7 +6414,7 @@ class UsageCacheRepository {
|
|
|
5972
6414
|
}
|
|
5973
6415
|
const scopeSet = new Set(scopes.map((scope) => scope.scope_key));
|
|
5974
6416
|
const overviewCards = groupOverviewCards(this.database.prepare(`
|
|
5975
|
-
SELECT card.scope_key, card.position, card.icon, card.name, card.value, card.detail, card.trend, card.trend_tone
|
|
6417
|
+
SELECT card.scope_key, card.position, card.icon, card.name, card.value, card.detail, card.subvalue_json, card.trend, card.trend_tone
|
|
5976
6418
|
FROM usage_scope_overview_cards AS card
|
|
5977
6419
|
JOIN usage_scopes AS scope ON scope.scope_key = card.scope_key
|
|
5978
6420
|
WHERE scope.scope_kind = ?
|
|
@@ -6042,6 +6484,7 @@ class UsageCacheRepository {
|
|
|
6042
6484
|
model.output_tokens,
|
|
6043
6485
|
model.reasoning_output_tokens,
|
|
6044
6486
|
model.total_tokens,
|
|
6487
|
+
model.cost_usd,
|
|
6045
6488
|
model.is_fallback
|
|
6046
6489
|
FROM usage_scope_daily_usage_models AS model
|
|
6047
6490
|
JOIN usage_scopes AS scope ON scope.scope_key = model.scope_key
|
|
@@ -6111,33 +6554,34 @@ class UsageCacheRepository {
|
|
|
6111
6554
|
WHERE scope.scope_kind = ?
|
|
6112
6555
|
ORDER BY model.scope_key ASC, model.session_key ASC, model.model_order ASC
|
|
6113
6556
|
`).all(kind),
|
|
6114
|
-
this.database.prepare(`
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
|
|
6127
|
-
|
|
6128
|
-
|
|
6129
|
-
|
|
6130
|
-
|
|
6131
|
-
|
|
6132
|
-
|
|
6133
|
-
|
|
6134
|
-
|
|
6135
|
-
|
|
6136
|
-
|
|
6137
|
-
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
|
|
6557
|
+
includeInteractions ? this.database.prepare(`
|
|
6558
|
+
SELECT
|
|
6559
|
+
interaction.scope_key,
|
|
6560
|
+
interaction.session_key,
|
|
6561
|
+
interaction.interaction_order,
|
|
6562
|
+
interaction.interaction_index,
|
|
6563
|
+
interaction.content,
|
|
6564
|
+
interaction.cost_usd,
|
|
6565
|
+
interaction.model,
|
|
6566
|
+
interaction.role,
|
|
6567
|
+
interaction.timestamp,
|
|
6568
|
+
interaction.type,
|
|
6569
|
+
interaction.input_tokens,
|
|
6570
|
+
interaction.cached_input_tokens,
|
|
6571
|
+
interaction.output_tokens,
|
|
6572
|
+
interaction.reasoning_output_tokens,
|
|
6573
|
+
interaction.extra_total_tokens,
|
|
6574
|
+
interaction.total_tokens,
|
|
6575
|
+
interaction.usage_cost_usd,
|
|
6576
|
+
interaction.cache_creation_tokens,
|
|
6577
|
+
interaction.cache_read_tokens,
|
|
6578
|
+
interaction.tool_tokens,
|
|
6579
|
+
interaction.is_fallback_model
|
|
6580
|
+
FROM usage_scope_interactions AS interaction
|
|
6581
|
+
JOIN usage_scopes AS scope ON scope.scope_key = interaction.scope_key
|
|
6582
|
+
WHERE scope.scope_kind = ?
|
|
6583
|
+
ORDER BY interaction.scope_key ASC, interaction.session_key ASC, interaction.interaction_order ASC
|
|
6584
|
+
`).all(kind) : []
|
|
6141
6585
|
);
|
|
6142
6586
|
const hydrated = /* @__PURE__ */ new Map();
|
|
6143
6587
|
for (const scope of scopes) {
|
|
@@ -6195,7 +6639,7 @@ class UsageCacheRepository {
|
|
|
6195
6639
|
return null;
|
|
6196
6640
|
}
|
|
6197
6641
|
return {
|
|
6198
|
-
payload: JSON.parse(row.payload),
|
|
6642
|
+
payload: normalizeProjectCatalogItems(JSON.parse(row.payload)),
|
|
6199
6643
|
payloadHash: row.payload_hash,
|
|
6200
6644
|
updatedAt: row.updated_at
|
|
6201
6645
|
};
|
|
@@ -6242,6 +6686,54 @@ function getTokenRowsByBucket(usage, bucket) {
|
|
|
6242
6686
|
return usage.weeklyRows;
|
|
6243
6687
|
}
|
|
6244
6688
|
}
|
|
6689
|
+
function buildTodayHourlyUsage(rows) {
|
|
6690
|
+
var _a;
|
|
6691
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
6692
|
+
for (const row of rows) {
|
|
6693
|
+
const item = (_a = grouped.get(row.hour)) != null ? _a : {
|
|
6694
|
+
agents: {},
|
|
6695
|
+
costUSD: 0,
|
|
6696
|
+
hour: row.hour,
|
|
6697
|
+
label: `${String(row.hour).padStart(2, "0")}:00`,
|
|
6698
|
+
totalTokens: 0
|
|
6699
|
+
};
|
|
6700
|
+
item.agents[row.platform] = {
|
|
6701
|
+
costUSD: row.cost_usd,
|
|
6702
|
+
totalTokens: row.total_tokens
|
|
6703
|
+
};
|
|
6704
|
+
item.costUSD = roundCurrency(item.costUSD + row.cost_usd);
|
|
6705
|
+
item.totalTokens += row.total_tokens;
|
|
6706
|
+
grouped.set(row.hour, item);
|
|
6707
|
+
}
|
|
6708
|
+
return Array.from({ length: 24 }, (_, hour) => {
|
|
6709
|
+
var _a2;
|
|
6710
|
+
return (_a2 = grouped.get(hour)) != null ? _a2 : {
|
|
6711
|
+
agents: {},
|
|
6712
|
+
costUSD: 0,
|
|
6713
|
+
hour,
|
|
6714
|
+
label: `${String(hour).padStart(2, "0")}:00`,
|
|
6715
|
+
totalTokens: 0
|
|
6716
|
+
};
|
|
6717
|
+
});
|
|
6718
|
+
}
|
|
6719
|
+
function groupTodayInsightCounts(rows) {
|
|
6720
|
+
return rows.reduce((result, row) => {
|
|
6721
|
+
result[row.period] = row.total;
|
|
6722
|
+
return result;
|
|
6723
|
+
}, {
|
|
6724
|
+
previous: 0,
|
|
6725
|
+
today: 0
|
|
6726
|
+
});
|
|
6727
|
+
}
|
|
6728
|
+
function getHomeInsightRange() {
|
|
6729
|
+
const today = /* @__PURE__ */ new Date();
|
|
6730
|
+
today.setHours(0, 0, 0, 0);
|
|
6731
|
+
return {
|
|
6732
|
+
previousDayStartAt: new Date(today.getTime() - 24 * 60 * 60 * 1e3).toISOString(),
|
|
6733
|
+
todayStartAt: today.toISOString(),
|
|
6734
|
+
tomorrowStartAt: new Date(today.getTime() + 24 * 60 * 60 * 1e3).toISOString()
|
|
6735
|
+
};
|
|
6736
|
+
}
|
|
6245
6737
|
function groupProjectModels(rows) {
|
|
6246
6738
|
var _a;
|
|
6247
6739
|
const grouped = /* @__PURE__ */ new Map();
|
|
@@ -6291,6 +6783,7 @@ function groupOverviewCards(rows) {
|
|
|
6291
6783
|
detail: (_b = row.detail) != null ? _b : void 0,
|
|
6292
6784
|
icon: row.icon,
|
|
6293
6785
|
name: row.name,
|
|
6786
|
+
subvalue: parseOverviewCardSubvalue(row.subvalue_json),
|
|
6294
6787
|
trend: row.trend,
|
|
6295
6788
|
trendTone: row.trend_tone,
|
|
6296
6789
|
value: row.value
|
|
@@ -6299,6 +6792,17 @@ function groupOverviewCards(rows) {
|
|
|
6299
6792
|
}
|
|
6300
6793
|
return grouped;
|
|
6301
6794
|
}
|
|
6795
|
+
function parseOverviewCardSubvalue(value) {
|
|
6796
|
+
if (!value) {
|
|
6797
|
+
return void 0;
|
|
6798
|
+
}
|
|
6799
|
+
try {
|
|
6800
|
+
const subvalue = JSON.parse(value);
|
|
6801
|
+
return Array.isArray(subvalue == null ? void 0 : subvalue.items) ? subvalue : void 0;
|
|
6802
|
+
} catch {
|
|
6803
|
+
return void 0;
|
|
6804
|
+
}
|
|
6805
|
+
}
|
|
6302
6806
|
function groupTokenRows(rows, modelRows, projectRows) {
|
|
6303
6807
|
var _a, _b, _c, _d, _e;
|
|
6304
6808
|
const modelsByRow = /* @__PURE__ */ new Map();
|
|
@@ -6350,6 +6854,7 @@ function groupDailyUsage(rows, modelRows) {
|
|
|
6350
6854
|
const models = (_a = modelsByRow.get(key)) != null ? _a : {};
|
|
6351
6855
|
models[row.model] = {
|
|
6352
6856
|
cachedInputTokens: row.cached_input_tokens,
|
|
6857
|
+
costUSD: row.cost_usd,
|
|
6353
6858
|
inputTokens: row.input_tokens,
|
|
6354
6859
|
isFallback: Boolean(row.is_fallback),
|
|
6355
6860
|
outputTokens: row.output_tokens,
|
|
@@ -6479,6 +6984,9 @@ function buildInteractionUsage(row) {
|
|
|
6479
6984
|
reasoningOutputTokens: row.reasoning_output_tokens,
|
|
6480
6985
|
totalTokens: row.total_tokens
|
|
6481
6986
|
};
|
|
6987
|
+
if (row.extra_total_tokens !== null) {
|
|
6988
|
+
usage.extraTotalTokens = row.extra_total_tokens;
|
|
6989
|
+
}
|
|
6482
6990
|
if (row.cache_creation_tokens !== null) {
|
|
6483
6991
|
usage.cacheCreationTokens = row.cache_creation_tokens;
|
|
6484
6992
|
}
|
|
@@ -6532,6 +7040,53 @@ function createCompositeKey(...parts) {
|
|
|
6532
7040
|
function createPayloadHash(value) {
|
|
6533
7041
|
return createHash("sha1").update(value).digest("hex");
|
|
6534
7042
|
}
|
|
7043
|
+
function normalizeProjectCatalogItems(value) {
|
|
7044
|
+
if (!Array.isArray(value)) {
|
|
7045
|
+
return [];
|
|
7046
|
+
}
|
|
7047
|
+
return value.flatMap((item) => {
|
|
7048
|
+
if (!item || typeof item !== "object") {
|
|
7049
|
+
return [];
|
|
7050
|
+
}
|
|
7051
|
+
const record = item;
|
|
7052
|
+
if (typeof record.label !== "string") {
|
|
7053
|
+
return [];
|
|
7054
|
+
}
|
|
7055
|
+
if (Array.isArray(record.platforms)) {
|
|
7056
|
+
return [{
|
|
7057
|
+
label: record.label,
|
|
7058
|
+
platforms: normalizeProjectCatalogPlatforms(record.platforms),
|
|
7059
|
+
totalTokens: normalizeProjectCatalogTotalTokens(record.totalTokens)
|
|
7060
|
+
}];
|
|
7061
|
+
}
|
|
7062
|
+
if (typeof record.type === "string") {
|
|
7063
|
+
return [{
|
|
7064
|
+
label: record.label,
|
|
7065
|
+
platforms: normalizeProjectCatalogPlatforms(record.type === "mixed" ? [] : [record.type]),
|
|
7066
|
+
totalTokens: normalizeProjectCatalogTotalTokens(record.totalTokens)
|
|
7067
|
+
}];
|
|
7068
|
+
}
|
|
7069
|
+
return [];
|
|
7070
|
+
});
|
|
7071
|
+
}
|
|
7072
|
+
function parseProjectCatalogPlatforms(value) {
|
|
7073
|
+
try {
|
|
7074
|
+
return normalizeProjectCatalogPlatforms(JSON.parse(value));
|
|
7075
|
+
} catch {
|
|
7076
|
+
return [];
|
|
7077
|
+
}
|
|
7078
|
+
}
|
|
7079
|
+
function normalizeProjectCatalogPlatforms(value) {
|
|
7080
|
+
if (!Array.isArray(value)) {
|
|
7081
|
+
return [];
|
|
7082
|
+
}
|
|
7083
|
+
return value.filter(
|
|
7084
|
+
(platform) => typeof platform === "string" && PROJECT_USAGE_PLATFORMS.includes(platform)
|
|
7085
|
+
);
|
|
7086
|
+
}
|
|
7087
|
+
function normalizeProjectCatalogTotalTokens(value) {
|
|
7088
|
+
return typeof value === "number" && Number.isFinite(value) ? Math.max(0, value) : 0;
|
|
7089
|
+
}
|
|
6535
7090
|
function mkdirParentDirectory(filePath) {
|
|
6536
7091
|
const directory = dirname$1(filePath);
|
|
6537
7092
|
if (!existsSync(directory)) {
|
|
@@ -6539,234 +7094,389 @@ function mkdirParentDirectory(filePath) {
|
|
|
6539
7094
|
}
|
|
6540
7095
|
}
|
|
6541
7096
|
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
|
|
6545
|
-
|
|
6546
|
-
|
|
6547
|
-
|
|
7097
|
+
const MILLION = 1e6;
|
|
7098
|
+
const DEFAULT_PRICING_CACHE_TTL_MS = 1e3 * 60 * 5;
|
|
7099
|
+
const DEFAULT_LITELLM_PRICING_URL = "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json";
|
|
7100
|
+
const FAST_MULTIPLIER_EXACT_OVERRIDES = {
|
|
7101
|
+
"gpt-5.3-codex": 2,
|
|
7102
|
+
"gpt-5.4": 2,
|
|
7103
|
+
"gpt-5.5": 2.5
|
|
7104
|
+
};
|
|
7105
|
+
const FAST_MULTIPLIER_PREFIX_OVERRIDES = {
|
|
7106
|
+
"claude-opus-4-6": 6,
|
|
7107
|
+
"claude-opus-4-7": 6
|
|
7108
|
+
};
|
|
7109
|
+
const DEFAULT_FALLBACK_PRICING_TABLE = {
|
|
7110
|
+
"gpt-5": {
|
|
7111
|
+
cachedInputCostPerMTokens: 0.125,
|
|
7112
|
+
cacheCreationInputCostPerMTokens: 1.25,
|
|
7113
|
+
inputCostPerMTokens: 1.25,
|
|
7114
|
+
outputCostPerMTokens: 10
|
|
7115
|
+
},
|
|
7116
|
+
"gpt-5.2-codex": {
|
|
7117
|
+
cachedInputCostPerMTokens: 0.175,
|
|
7118
|
+
cacheCreationInputCostPerMTokens: 1.75,
|
|
7119
|
+
inputCostPerMTokens: 1.75,
|
|
7120
|
+
outputCostPerMTokens: 14
|
|
7121
|
+
},
|
|
7122
|
+
"gpt-5.4": {
|
|
7123
|
+
cachedInputCostPerMTokens: 0.25,
|
|
7124
|
+
cacheCreationInputCostPerMTokens: 2.5,
|
|
7125
|
+
inputCostPerMTokens: 2.5,
|
|
7126
|
+
outputCostPerMTokens: 15
|
|
7127
|
+
},
|
|
7128
|
+
"gpt-5.5": {
|
|
7129
|
+
cachedInputCostPerMTokens: 0.5,
|
|
7130
|
+
cacheCreationInputCostPerMTokens: 5,
|
|
7131
|
+
fastMultiplier: FAST_MULTIPLIER_EXACT_OVERRIDES["gpt-5.5"],
|
|
7132
|
+
inputCostPerMTokens: 5,
|
|
7133
|
+
outputCostPerMTokens: 30
|
|
7134
|
+
},
|
|
7135
|
+
"claude-haiku-4-5": {
|
|
7136
|
+
cachedInputCostPerMTokens: 0.1,
|
|
7137
|
+
cacheCreationInputCostPerMTokens: 1.25,
|
|
7138
|
+
inputCostPerMTokens: 1,
|
|
7139
|
+
outputCostPerMTokens: 5
|
|
7140
|
+
},
|
|
7141
|
+
"claude-opus-4-1": {
|
|
7142
|
+
cachedInputCostPerMTokens: 1.5,
|
|
7143
|
+
cachedInputCostPerMTokensAbove200K: 3,
|
|
7144
|
+
cacheCreationInputCostPerMTokens: 18.75,
|
|
7145
|
+
cacheCreationInputCostPerMTokensAbove200K: 37.5,
|
|
7146
|
+
inputCostPerMTokens: 15,
|
|
7147
|
+
inputCostPerMTokensAbove200K: 30,
|
|
7148
|
+
outputCostPerMTokens: 75,
|
|
7149
|
+
outputCostPerMTokensAbove200K: 112.5
|
|
7150
|
+
},
|
|
7151
|
+
"claude-opus-4-6": {
|
|
7152
|
+
cachedInputCostPerMTokens: 0.5,
|
|
7153
|
+
cacheCreationInputCostPerMTokens: 6.25,
|
|
7154
|
+
fastMultiplier: FAST_MULTIPLIER_PREFIX_OVERRIDES["claude-opus-4-6"],
|
|
7155
|
+
inputCostPerMTokens: 5,
|
|
7156
|
+
outputCostPerMTokens: 25
|
|
7157
|
+
},
|
|
7158
|
+
"claude-opus-4-7": {
|
|
7159
|
+
cachedInputCostPerMTokens: 0.5,
|
|
7160
|
+
cacheCreationInputCostPerMTokens: 6.25,
|
|
7161
|
+
fastMultiplier: FAST_MULTIPLIER_PREFIX_OVERRIDES["claude-opus-4-7"],
|
|
7162
|
+
inputCostPerMTokens: 5,
|
|
7163
|
+
outputCostPerMTokens: 25
|
|
7164
|
+
},
|
|
7165
|
+
"claude-sonnet-4-5": {
|
|
7166
|
+
cachedInputCostPerMTokens: 0.3,
|
|
7167
|
+
cachedInputCostPerMTokensAbove200K: 0.6,
|
|
7168
|
+
cacheCreationInputCostPerMTokens: 3.75,
|
|
7169
|
+
cacheCreationInputCostPerMTokensAbove200K: 7.5,
|
|
7170
|
+
inputCostPerMTokens: 3,
|
|
7171
|
+
inputCostPerMTokensAbove200K: 6,
|
|
7172
|
+
outputCostPerMTokens: 15,
|
|
7173
|
+
outputCostPerMTokensAbove200K: 22.5
|
|
6548
7174
|
}
|
|
6549
|
-
|
|
6550
|
-
|
|
7175
|
+
};
|
|
7176
|
+
const pricingCache = /* @__PURE__ */ new Map();
|
|
7177
|
+
async function fetchLiteLLMPricingDataset(options = {}) {
|
|
7178
|
+
var _a, _b, _c, _d;
|
|
7179
|
+
const url = (_a = options.url) != null ? _a : DEFAULT_LITELLM_PRICING_URL;
|
|
7180
|
+
const cacheTtlMs = (_b = options.cacheTtlMs) != null ? _b : DEFAULT_PRICING_CACHE_TTL_MS;
|
|
7181
|
+
const now = Date.now();
|
|
7182
|
+
const cacheEntry = pricingCache.get(url);
|
|
7183
|
+
if (!options.forceRefresh && (cacheEntry == null ? void 0 : cacheEntry.value) && now - cacheEntry.fetchedAt < cacheTtlMs) {
|
|
7184
|
+
return cacheEntry.value;
|
|
6551
7185
|
}
|
|
6552
|
-
|
|
6553
|
-
|
|
6554
|
-
|
|
6555
|
-
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
|
|
6560
|
-
|
|
6561
|
-
|
|
6562
|
-
|
|
6563
|
-
|
|
6564
|
-
|
|
6565
|
-
|
|
7186
|
+
if (!options.forceRefresh && (cacheEntry == null ? void 0 : cacheEntry.promise)) {
|
|
7187
|
+
return cacheEntry.promise;
|
|
7188
|
+
}
|
|
7189
|
+
const fetcher = (_c = options.fetcher) != null ? _c : globalThis.fetch;
|
|
7190
|
+
if (typeof fetcher !== "function") {
|
|
7191
|
+
return createFallbackLiteLLMPricingDataset();
|
|
7192
|
+
}
|
|
7193
|
+
const promise = fetcher(url).then(async (response) => {
|
|
7194
|
+
if (!response.ok) {
|
|
7195
|
+
throw new Error(`Failed to fetch LiteLLM pricing dataset: ${response.status} ${response.statusText}`);
|
|
7196
|
+
}
|
|
7197
|
+
const data = await response.json();
|
|
7198
|
+
if (!isLiteLLMPricingDataset(data)) {
|
|
7199
|
+
throw new Error("Invalid LiteLLM pricing dataset payload.");
|
|
7200
|
+
}
|
|
7201
|
+
const dataset = {
|
|
7202
|
+
...createFallbackLiteLLMPricingDataset(),
|
|
7203
|
+
...data
|
|
7204
|
+
};
|
|
7205
|
+
pricingCache.set(url, {
|
|
7206
|
+
fetchedAt: Date.now(),
|
|
7207
|
+
value: dataset
|
|
7208
|
+
});
|
|
7209
|
+
return dataset;
|
|
7210
|
+
}).catch(() => {
|
|
7211
|
+
const fallback = createFallbackLiteLLMPricingDataset();
|
|
7212
|
+
pricingCache.set(url, {
|
|
7213
|
+
fetchedAt: Date.now(),
|
|
7214
|
+
value: fallback
|
|
7215
|
+
});
|
|
7216
|
+
return fallback;
|
|
7217
|
+
});
|
|
7218
|
+
pricingCache.set(url, {
|
|
7219
|
+
fetchedAt: (_d = cacheEntry == null ? void 0 : cacheEntry.fetchedAt) != null ? _d : 0,
|
|
7220
|
+
promise,
|
|
7221
|
+
value: cacheEntry == null ? void 0 : cacheEntry.value
|
|
7222
|
+
});
|
|
7223
|
+
return promise;
|
|
6566
7224
|
}
|
|
6567
|
-
|
|
6568
|
-
|
|
6569
|
-
|
|
6570
|
-
|
|
6571
|
-
|
|
6572
|
-
|
|
6573
|
-
|
|
6574
|
-
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
}
|
|
6583
|
-
const
|
|
6584
|
-
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
}
|
|
6588
|
-
const
|
|
6589
|
-
|
|
6590
|
-
|
|
6591
|
-
|
|
6592
|
-
|
|
6593
|
-
|
|
6594
|
-
|
|
6595
|
-
|
|
6596
|
-
|
|
6597
|
-
|
|
6598
|
-
return Math.round(value * 1e6) / 1e6;
|
|
7225
|
+
async function createLiteLLMPricingResolver(options = {}) {
|
|
7226
|
+
var _a, _b, _c, _d;
|
|
7227
|
+
const dataset = await fetchLiteLLMPricingDataset(options);
|
|
7228
|
+
const aliases = (_a = options.aliases) != null ? _a : {};
|
|
7229
|
+
const fallbackPricingTable = {
|
|
7230
|
+
...DEFAULT_FALLBACK_PRICING_TABLE,
|
|
7231
|
+
...(_b = options.fallbackPricingTable) != null ? _b : {}
|
|
7232
|
+
};
|
|
7233
|
+
const getLookupCandidates = (_c = options.getLookupCandidates) != null ? _c : defaultLookupCandidates;
|
|
7234
|
+
const fallbackModel = options.fallbackModel;
|
|
7235
|
+
const isZeroCostModel = (_d = options.isZeroCostModel) != null ? _d : (() => false);
|
|
7236
|
+
return (model) => {
|
|
7237
|
+
var _a2, _b2;
|
|
7238
|
+
if (isZeroCostModel(model)) {
|
|
7239
|
+
return createZeroPricing();
|
|
7240
|
+
}
|
|
7241
|
+
const lookupCandidates = uniqueItems(expandLookupCandidates(model, aliases, getLookupCandidates).filter(Boolean));
|
|
7242
|
+
const datasetPricing = resolveDatasetPricing(dataset, lookupCandidates);
|
|
7243
|
+
if (datasetPricing) {
|
|
7244
|
+
return datasetPricing;
|
|
7245
|
+
}
|
|
7246
|
+
const fallbackPricing = resolveFallbackPricing(fallbackPricingTable, lookupCandidates);
|
|
7247
|
+
if (fallbackPricing) {
|
|
7248
|
+
return fallbackPricing;
|
|
7249
|
+
}
|
|
7250
|
+
if (fallbackModel) {
|
|
7251
|
+
const fallbackCandidates = uniqueItems(expandLookupCandidates(fallbackModel, aliases, getLookupCandidates).filter(Boolean));
|
|
7252
|
+
return (_b2 = (_a2 = resolveDatasetPricing(dataset, fallbackCandidates)) != null ? _a2 : resolveFallbackPricing(fallbackPricingTable, fallbackCandidates)) != null ? _b2 : createZeroPricing();
|
|
7253
|
+
}
|
|
7254
|
+
return createZeroPricing();
|
|
7255
|
+
};
|
|
6599
7256
|
}
|
|
6600
|
-
function
|
|
6601
|
-
|
|
7257
|
+
function calculateUsageCostUSD(usage, pricing, options = {}) {
|
|
7258
|
+
var _a, _b, _c;
|
|
7259
|
+
const multiplier = options.speed === "fast" ? (_b = (_a = pricing.fastMultiplier) != null ? _a : options.defaultFastMultiplier) != null ? _b : 1 : 1;
|
|
7260
|
+
const inputCost = calculateTieredCost(usage.inputTokens, pricing.inputCostPerMTokens, pricing.inputCostPerMTokensAbove200K);
|
|
7261
|
+
const cachedCost = calculateTieredCost(usage.cachedInputTokens, pricing.cachedInputCostPerMTokens, pricing.cachedInputCostPerMTokensAbove200K);
|
|
7262
|
+
const cacheCreationCost = calculateTieredCost((_c = usage.cacheCreationTokens) != null ? _c : 0, pricing.cacheCreationInputCostPerMTokens, pricing.cacheCreationInputCostPerMTokensAbove200K);
|
|
7263
|
+
const outputCost = calculateTieredCost(usage.outputTokens, pricing.outputCostPerMTokens, pricing.outputCostPerMTokensAbove200K);
|
|
7264
|
+
return (inputCost + cachedCost + cacheCreationCost + outputCost) * multiplier;
|
|
6602
7265
|
}
|
|
6603
|
-
function
|
|
6604
|
-
return
|
|
7266
|
+
function createFallbackLiteLLMPricingDataset() {
|
|
7267
|
+
return {
|
|
7268
|
+
"gpt-5": {
|
|
7269
|
+
input_cost_per_token: 125e-8,
|
|
7270
|
+
output_cost_per_token: 1e-5,
|
|
7271
|
+
cache_creation_input_token_cost: 125e-8,
|
|
7272
|
+
cache_read_input_token_cost: 125e-9
|
|
7273
|
+
},
|
|
7274
|
+
"gpt-5.2-codex": {
|
|
7275
|
+
input_cost_per_token: 175e-8,
|
|
7276
|
+
output_cost_per_token: 14e-6,
|
|
7277
|
+
cache_creation_input_token_cost: 175e-8,
|
|
7278
|
+
cache_read_input_token_cost: 175e-9
|
|
7279
|
+
},
|
|
7280
|
+
"gpt-5.4": {
|
|
7281
|
+
input_cost_per_token: 25e-7,
|
|
7282
|
+
output_cost_per_token: 15e-6,
|
|
7283
|
+
cache_creation_input_token_cost: 25e-7,
|
|
7284
|
+
cache_read_input_token_cost: 25e-8
|
|
7285
|
+
},
|
|
7286
|
+
"gpt-5.5": {
|
|
7287
|
+
input_cost_per_token: 5e-6,
|
|
7288
|
+
output_cost_per_token: 3e-5,
|
|
7289
|
+
cache_creation_input_token_cost: 5e-6,
|
|
7290
|
+
cache_read_input_token_cost: 5e-7,
|
|
7291
|
+
provider_specific_entry: {
|
|
7292
|
+
fast: 2.5
|
|
7293
|
+
}
|
|
7294
|
+
},
|
|
7295
|
+
"claude-haiku-4-5": {
|
|
7296
|
+
input_cost_per_token: 1e-6,
|
|
7297
|
+
output_cost_per_token: 5e-6,
|
|
7298
|
+
cache_creation_input_token_cost: 125e-8,
|
|
7299
|
+
cache_read_input_token_cost: 1e-7
|
|
7300
|
+
},
|
|
7301
|
+
"claude-opus-4-1": {
|
|
7302
|
+
input_cost_per_token: 15e-6,
|
|
7303
|
+
output_cost_per_token: 75e-6,
|
|
7304
|
+
cache_creation_input_token_cost: 1875e-8,
|
|
7305
|
+
cache_read_input_token_cost: 15e-7,
|
|
7306
|
+
input_cost_per_token_above_200k_tokens: 3e-5,
|
|
7307
|
+
output_cost_per_token_above_200k_tokens: 1125e-7,
|
|
7308
|
+
cache_creation_input_token_cost_above_200k_tokens: 375e-7,
|
|
7309
|
+
cache_read_input_token_cost_above_200k_tokens: 3e-6
|
|
7310
|
+
},
|
|
7311
|
+
"claude-opus-4-6": {
|
|
7312
|
+
input_cost_per_token: 5e-6,
|
|
7313
|
+
output_cost_per_token: 25e-6,
|
|
7314
|
+
cache_creation_input_token_cost: 625e-8,
|
|
7315
|
+
cache_read_input_token_cost: 5e-7,
|
|
7316
|
+
provider_specific_entry: {
|
|
7317
|
+
fast: 6
|
|
7318
|
+
}
|
|
7319
|
+
},
|
|
7320
|
+
"claude-opus-4-7": {
|
|
7321
|
+
input_cost_per_token: 5e-6,
|
|
7322
|
+
output_cost_per_token: 25e-6,
|
|
7323
|
+
cache_creation_input_token_cost: 625e-8,
|
|
7324
|
+
cache_read_input_token_cost: 5e-7,
|
|
7325
|
+
provider_specific_entry: {
|
|
7326
|
+
fast: 6
|
|
7327
|
+
}
|
|
7328
|
+
},
|
|
7329
|
+
"claude-sonnet-4-5": {
|
|
7330
|
+
input_cost_per_token: 3e-6,
|
|
7331
|
+
output_cost_per_token: 15e-6,
|
|
7332
|
+
cache_creation_input_token_cost: 375e-8,
|
|
7333
|
+
cache_read_input_token_cost: 3e-7,
|
|
7334
|
+
input_cost_per_token_above_200k_tokens: 6e-6,
|
|
7335
|
+
output_cost_per_token_above_200k_tokens: 225e-7,
|
|
7336
|
+
cache_creation_input_token_cost_above_200k_tokens: 75e-7,
|
|
7337
|
+
cache_read_input_token_cost_above_200k_tokens: 6e-7
|
|
7338
|
+
}
|
|
7339
|
+
};
|
|
6605
7340
|
}
|
|
6606
|
-
function
|
|
6607
|
-
|
|
7341
|
+
function isLiteLLMPricingDataset(value) {
|
|
7342
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
7343
|
+
return false;
|
|
7344
|
+
}
|
|
7345
|
+
return true;
|
|
6608
7346
|
}
|
|
6609
|
-
function
|
|
6610
|
-
|
|
7347
|
+
function defaultLookupCandidates(model) {
|
|
7348
|
+
const normalizedModel = model.trim();
|
|
7349
|
+
return [
|
|
7350
|
+
normalizedModel,
|
|
7351
|
+
normalizedModel.replace(/^openai\//u, ""),
|
|
7352
|
+
normalizedModel.replace(/^azure\//u, ""),
|
|
7353
|
+
normalizedModel.replace(/^openrouter\/openai\//u, "")
|
|
7354
|
+
];
|
|
6611
7355
|
}
|
|
6612
|
-
function
|
|
6613
|
-
const
|
|
6614
|
-
const
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
trendTone: "neutral"
|
|
6620
|
-
};
|
|
7356
|
+
function expandLookupCandidates(model, aliases, getLookupCandidates) {
|
|
7357
|
+
const candidates = getLookupCandidates(model);
|
|
7358
|
+
const expanded = [...candidates];
|
|
7359
|
+
for (const candidate of candidates) {
|
|
7360
|
+
const alias = aliases[candidate];
|
|
7361
|
+
if (alias) {
|
|
7362
|
+
expanded.push(...getLookupCandidates(alias));
|
|
6621
7363
|
}
|
|
6622
|
-
return {
|
|
6623
|
-
trend: `+${formatValue(current)}`,
|
|
6624
|
-
trendTone: "up"
|
|
6625
|
-
};
|
|
6626
7364
|
}
|
|
6627
|
-
|
|
6628
|
-
return {
|
|
6629
|
-
trend: formatSignedPercent(ratio),
|
|
6630
|
-
trendTone: getTrendTone(ratio)
|
|
6631
|
-
};
|
|
7365
|
+
return expanded;
|
|
6632
7366
|
}
|
|
6633
|
-
function
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
7367
|
+
function resolveDatasetPricing(dataset, candidates) {
|
|
7368
|
+
for (const candidate of candidates) {
|
|
7369
|
+
const pricing = dataset[candidate];
|
|
7370
|
+
if (!pricing || !hasNonZeroTokenPricing(pricing)) {
|
|
7371
|
+
continue;
|
|
7372
|
+
}
|
|
7373
|
+
return toModelPricing(pricing, candidates);
|
|
7374
|
+
}
|
|
7375
|
+
return null;
|
|
6640
7376
|
}
|
|
6641
|
-
function
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
7377
|
+
function resolveFallbackPricing(fallbackPricingTable, candidates) {
|
|
7378
|
+
var _a;
|
|
7379
|
+
for (const candidate of candidates) {
|
|
7380
|
+
const pricing = fallbackPricingTable[candidate];
|
|
7381
|
+
if (pricing) {
|
|
7382
|
+
const fastMultiplier = (_a = pricing.fastMultiplier) != null ? _a : resolveFastMultiplierOverride(candidates);
|
|
7383
|
+
return fastMultiplier == null ? pricing : { ...pricing, fastMultiplier };
|
|
7384
|
+
}
|
|
6645
7385
|
}
|
|
6646
|
-
return
|
|
7386
|
+
return null;
|
|
6647
7387
|
}
|
|
6648
|
-
function
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
date.setDate(date.getDate() - 1);
|
|
6652
|
-
return getDateKey(date);
|
|
7388
|
+
function hasNonZeroTokenPricing(pricing) {
|
|
7389
|
+
var _a, _b, _c, _d;
|
|
7390
|
+
return ((_a = pricing.input_cost_per_token) != null ? _a : 0) > 0 || ((_b = pricing.output_cost_per_token) != null ? _b : 0) > 0 || ((_c = pricing.cache_creation_input_token_cost) != null ? _c : 0) > 0 || ((_d = pricing.cache_read_input_token_cost) != null ? _d : 0) > 0;
|
|
6653
7391
|
}
|
|
6654
|
-
function
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
7392
|
+
function toModelPricing(pricing, candidates) {
|
|
7393
|
+
var _a, _b, _c, _d, _e, _f;
|
|
7394
|
+
const inputCostPerToken = (_a = pricing.input_cost_per_token) != null ? _a : 0;
|
|
7395
|
+
const cachedInputCostPerToken = (_b = pricing.cache_read_input_token_cost) != null ? _b : inputCostPerToken;
|
|
7396
|
+
const cacheCreationInputCostPerToken = (_c = pricing.cache_creation_input_token_cost) != null ? _c : inputCostPerToken;
|
|
7397
|
+
const outputCostPerToken = (_d = pricing.output_cost_per_token) != null ? _d : 0;
|
|
7398
|
+
return {
|
|
7399
|
+
cachedInputCostPerMTokens: cachedInputCostPerToken * MILLION,
|
|
7400
|
+
cachedInputCostPerMTokensAbove200K: pricing.cache_read_input_token_cost_above_200k_tokens != null ? pricing.cache_read_input_token_cost_above_200k_tokens * MILLION : void 0,
|
|
7401
|
+
cacheCreationInputCostPerMTokens: cacheCreationInputCostPerToken * MILLION,
|
|
7402
|
+
cacheCreationInputCostPerMTokensAbove200K: pricing.cache_creation_input_token_cost_above_200k_tokens != null ? pricing.cache_creation_input_token_cost_above_200k_tokens * MILLION : void 0,
|
|
7403
|
+
fastMultiplier: (_f = (_e = pricing.provider_specific_entry) == null ? void 0 : _e.fast) != null ? _f : resolveFastMultiplierOverride(candidates),
|
|
7404
|
+
inputCostPerMTokens: inputCostPerToken * MILLION,
|
|
7405
|
+
inputCostPerMTokensAbove200K: pricing.input_cost_per_token_above_200k_tokens != null ? pricing.input_cost_per_token_above_200k_tokens * MILLION : void 0,
|
|
7406
|
+
outputCostPerMTokens: outputCostPerToken * MILLION,
|
|
7407
|
+
outputCostPerMTokensAbove200K: pricing.output_cost_per_token_above_200k_tokens != null ? pricing.output_cost_per_token_above_200k_tokens * MILLION : void 0
|
|
7408
|
+
};
|
|
7409
|
+
}
|
|
7410
|
+
function resolveFastMultiplierOverride(candidates) {
|
|
7411
|
+
for (const candidate of candidates) {
|
|
7412
|
+
const multiplier = FAST_MULTIPLIER_EXACT_OVERRIDES[candidate];
|
|
7413
|
+
if (multiplier != null) {
|
|
7414
|
+
return multiplier;
|
|
7415
|
+
}
|
|
6658
7416
|
}
|
|
6659
|
-
|
|
7417
|
+
for (const candidate of candidates) {
|
|
7418
|
+
const normalized = candidate.replace(/[.@]/gu, "-");
|
|
7419
|
+
for (const part of normalized.split(/[/:]/u)) {
|
|
7420
|
+
for (const [base, multiplier] of Object.entries(FAST_MULTIPLIER_PREFIX_OVERRIDES)) {
|
|
7421
|
+
if (matchesModelSuffix(part, base)) {
|
|
7422
|
+
return multiplier;
|
|
7423
|
+
}
|
|
7424
|
+
}
|
|
7425
|
+
}
|
|
7426
|
+
}
|
|
7427
|
+
return void 0;
|
|
6660
7428
|
}
|
|
6661
|
-
function
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
const project = (_a = projects.get(session.project)) != null ? _a : {
|
|
6666
|
-
costUSD: 0,
|
|
6667
|
-
repository: session.repository,
|
|
6668
|
-
sessions: 0,
|
|
6669
|
-
tokenTotal: 0
|
|
6670
|
-
};
|
|
6671
|
-
project.costUSD += session.costUSD;
|
|
6672
|
-
project.sessions += 1;
|
|
6673
|
-
project.tokenTotal += session.tokenTotal;
|
|
6674
|
-
projects.set(session.project, project);
|
|
7429
|
+
function matchesModelSuffix(part, base) {
|
|
7430
|
+
const index = part.lastIndexOf(base);
|
|
7431
|
+
if (index < 0) {
|
|
7432
|
+
return false;
|
|
6675
7433
|
}
|
|
6676
|
-
const
|
|
6677
|
-
return
|
|
6678
|
-
costUSD: project.costUSD,
|
|
6679
|
-
detail: `${project.sessions} sessions / ${formatCompactNumber(project.tokenTotal)} tokens`,
|
|
6680
|
-
label,
|
|
6681
|
-
percent: maxCost > 0 ? project.costUSD / maxCost * 100 : 0,
|
|
6682
|
-
repository: project.repository,
|
|
6683
|
-
sessions: project.sessions,
|
|
6684
|
-
tokenTotal: project.tokenTotal,
|
|
6685
|
-
tone: "amber",
|
|
6686
|
-
value: formatCurrency(project.costUSD)
|
|
6687
|
-
})).sort((a, b) => b.costUSD - a.costUSD);
|
|
7434
|
+
const suffix = part.slice(index);
|
|
7435
|
+
return suffix === base || suffix[base.length] === "-";
|
|
6688
7436
|
}
|
|
6689
|
-
function
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
costUSD: 0,
|
|
6697
|
-
date: formatDateLabelFromDateKey(dateKey, item.date),
|
|
6698
|
-
inputTokens: 0,
|
|
6699
|
-
models: /* @__PURE__ */ new Map(),
|
|
6700
|
-
outputTokens: 0,
|
|
6701
|
-
reasoningOutputTokens: 0,
|
|
6702
|
-
totalTokens: 0
|
|
6703
|
-
};
|
|
6704
|
-
group.cachedInputTokens += item.cachedInputTokens;
|
|
6705
|
-
group.costUSD += item.costUSD;
|
|
6706
|
-
group.inputTokens += item.inputTokens;
|
|
6707
|
-
group.outputTokens += item.outputTokens;
|
|
6708
|
-
group.reasoningOutputTokens += item.reasoningOutputTokens;
|
|
6709
|
-
group.totalTokens += item.totalTokens;
|
|
6710
|
-
for (const [modelName, usage] of Object.entries(item.models)) {
|
|
6711
|
-
const model = (_b = group.models.get(modelName)) != null ? _b : createEmptyModelUsage();
|
|
6712
|
-
model.cachedInputTokens += usage.cachedInputTokens;
|
|
6713
|
-
model.inputTokens += usage.inputTokens;
|
|
6714
|
-
model.isFallback = model.isFallback || usage.isFallback;
|
|
6715
|
-
model.outputTokens += usage.outputTokens;
|
|
6716
|
-
model.reasoningOutputTokens += usage.reasoningOutputTokens;
|
|
6717
|
-
model.totalTokens += usage.totalTokens;
|
|
6718
|
-
group.models.set(modelName, model);
|
|
6719
|
-
}
|
|
6720
|
-
groups.set(dateKey, group);
|
|
6721
|
-
}
|
|
6722
|
-
return Array.from(groups.entries()).sort((a, b) => b[0].localeCompare(a[0])).map(([, group]) => ({
|
|
6723
|
-
cachedInputTokens: group.cachedInputTokens,
|
|
6724
|
-
costUSD: roundCurrency(group.costUSD),
|
|
6725
|
-
date: group.date,
|
|
6726
|
-
inputTokens: group.inputTokens,
|
|
6727
|
-
models: Object.fromEntries(group.models.entries()),
|
|
6728
|
-
outputTokens: group.outputTokens,
|
|
6729
|
-
reasoningOutputTokens: group.reasoningOutputTokens,
|
|
6730
|
-
totalTokens: group.totalTokens
|
|
6731
|
-
}));
|
|
7437
|
+
function createZeroPricing() {
|
|
7438
|
+
return {
|
|
7439
|
+
cachedInputCostPerMTokens: 0,
|
|
7440
|
+
cacheCreationInputCostPerMTokens: 0,
|
|
7441
|
+
inputCostPerMTokens: 0,
|
|
7442
|
+
outputCostPerMTokens: 0
|
|
7443
|
+
};
|
|
6732
7444
|
}
|
|
6733
|
-
function
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
const key = `${item.month}__${item.model}`;
|
|
6738
|
-
const group = (_a = groups.get(key)) != null ? _a : {
|
|
6739
|
-
model: item.model,
|
|
6740
|
-
month: item.month,
|
|
6741
|
-
tokenTotal: 0
|
|
6742
|
-
};
|
|
6743
|
-
group.tokenTotal += item.tokenTotal;
|
|
6744
|
-
groups.set(key, group);
|
|
7445
|
+
function calculateTieredCost(tokens, baseCostPerMTokens, above200KCostPerMTokens) {
|
|
7446
|
+
const safeTokens = Math.max(tokens != null ? tokens : 0, 0);
|
|
7447
|
+
if (safeTokens === 0) {
|
|
7448
|
+
return 0;
|
|
6745
7449
|
}
|
|
6746
|
-
|
|
7450
|
+
if (safeTokens > 2e5 && above200KCostPerMTokens != null) {
|
|
7451
|
+
return 2e5 / MILLION * baseCostPerMTokens + (safeTokens - 2e5) / MILLION * above200KCostPerMTokens;
|
|
7452
|
+
}
|
|
7453
|
+
return safeTokens / MILLION * baseCostPerMTokens;
|
|
6747
7454
|
}
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
return
|
|
7455
|
+
|
|
7456
|
+
function normalizeStringValue(value) {
|
|
7457
|
+
return typeof value === "string" ? value.trim() : void 0;
|
|
6751
7458
|
}
|
|
6752
|
-
function
|
|
6753
|
-
if (value
|
|
6754
|
-
return "
|
|
7459
|
+
function normalizeStringList(value) {
|
|
7460
|
+
if (Array.isArray(value)) {
|
|
7461
|
+
return value.flatMap((item) => typeof item === "string" ? splitCommaValues(item) : []);
|
|
6755
7462
|
}
|
|
6756
|
-
if (value
|
|
6757
|
-
return
|
|
7463
|
+
if (typeof value === "string") {
|
|
7464
|
+
return splitCommaValues(value);
|
|
6758
7465
|
}
|
|
6759
|
-
return
|
|
7466
|
+
return void 0;
|
|
6760
7467
|
}
|
|
6761
|
-
function
|
|
6762
|
-
return
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
7468
|
+
function normalizeUnknownRecord(value) {
|
|
7469
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
7470
|
+
}
|
|
7471
|
+
function normalizeFiniteNumberOrNull(value) {
|
|
7472
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
7473
|
+
}
|
|
7474
|
+
function normalizeTimestampValue(value) {
|
|
7475
|
+
const normalizedValue = normalizeStringValue(value);
|
|
7476
|
+
return normalizedValue && Number.isFinite(Date.parse(normalizedValue)) ? normalizedValue : null;
|
|
7477
|
+
}
|
|
7478
|
+
function splitCommaValues(value) {
|
|
7479
|
+
return value.split(",").map((item) => item.trim()).filter(Boolean);
|
|
6770
7480
|
}
|
|
6771
7481
|
|
|
6772
7482
|
function parseJsonlFile(filePath) {
|
|
@@ -6813,9 +7523,11 @@ function buildDailyUsageGroups(events, options = {}) {
|
|
|
6813
7523
|
if (shouldIncludeModel(event, options)) {
|
|
6814
7524
|
const modelUsage = (_b = group.modelUsage.get(event.model)) != null ? _b : {
|
|
6815
7525
|
...createEmptyUsage(),
|
|
7526
|
+
costUSD: 0,
|
|
6816
7527
|
isFallback: false
|
|
6817
7528
|
};
|
|
6818
7529
|
addUsage(modelUsage, event);
|
|
7530
|
+
modelUsage.costUSD += getEventCostUSD(event, options);
|
|
6819
7531
|
if (event.isFallbackModel) {
|
|
6820
7532
|
modelUsage.isFallback = true;
|
|
6821
7533
|
}
|
|
@@ -6833,6 +7545,7 @@ function buildDailyTokenUsage(dailyGroups) {
|
|
|
6833
7545
|
inputTokens: group.inputTokens,
|
|
6834
7546
|
models: Object.fromEntries(Array.from(group.modelUsage.entries()).map(([model, usage]) => [model, {
|
|
6835
7547
|
cachedInputTokens: usage.cachedInputTokens,
|
|
7548
|
+
costUSD: roundCurrency(usage.costUSD),
|
|
6836
7549
|
inputTokens: usage.inputTokens,
|
|
6837
7550
|
isFallback: usage.isFallback,
|
|
6838
7551
|
outputTokens: usage.outputTokens,
|
|
@@ -6973,6 +7686,10 @@ function buildOverviewCards(options) {
|
|
|
6973
7686
|
detail: `${formatNumber(options.todayTotalTokens)} tokens used today`,
|
|
6974
7687
|
icon: "solar:cpu-line-duotone",
|
|
6975
7688
|
name: "Today Tokens",
|
|
7689
|
+
subvalue: buildInputOutputTokenSubvalue({
|
|
7690
|
+
inputTokens: options.todayInputTokens,
|
|
7691
|
+
outputTokens: options.todayOutputTokens
|
|
7692
|
+
}),
|
|
6976
7693
|
trend: tokenTrend.trend,
|
|
6977
7694
|
trendTone: tokenTrend.trendTone,
|
|
6978
7695
|
value: formatCompactNumber(options.todayTotalTokens)
|
|
@@ -7004,7 +7721,7 @@ function buildOverviewCards(options) {
|
|
|
7004
7721
|
];
|
|
7005
7722
|
}
|
|
7006
7723
|
function buildLoadUsageResult(events, sessions, options = {}) {
|
|
7007
|
-
var _a, _b, _c, _d, _e, _f;
|
|
7724
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
7008
7725
|
const aggregateOptions = (_a = options.aggregateOptions) != null ? _a : {};
|
|
7009
7726
|
const sessionOptions = (_b = options.sessionOptions) != null ? _b : {};
|
|
7010
7727
|
const sortedSessions = [...sessions].sort((a, b) => getSessionSortTimestamp(b) - getSessionSortTimestamp(a));
|
|
@@ -7027,6 +7744,8 @@ function buildLoadUsageResult(events, sessions, options = {}) {
|
|
|
7027
7744
|
overviewCards: buildOverviewCards({
|
|
7028
7745
|
previousDayCost: roundCurrency((_e = previousDayDailyGroup == null ? void 0 : previousDayDailyGroup.costUSD) != null ? _e : 0),
|
|
7029
7746
|
previousDayTokens: (_f = previousDayDailyGroup == null ? void 0 : previousDayDailyGroup.totalTokens) != null ? _f : 0,
|
|
7747
|
+
todayInputTokens: (_g = todayDailyGroup == null ? void 0 : todayDailyGroup.inputTokens) != null ? _g : 0,
|
|
7748
|
+
todayOutputTokens: (_h = todayDailyGroup == null ? void 0 : todayDailyGroup.outputTokens) != null ? _h : 0,
|
|
7030
7749
|
todayTopModel,
|
|
7031
7750
|
todayTopProject,
|
|
7032
7751
|
todayTotalCost,
|
|
@@ -7045,769 +7764,421 @@ function buildLoadUsageResult(events, sessions, options = {}) {
|
|
|
7045
7764
|
function getTopProjectForDate(events) {
|
|
7046
7765
|
var _a;
|
|
7047
7766
|
const projects = /* @__PURE__ */ new Map();
|
|
7048
|
-
for (const event of events) {
|
|
7049
|
-
const sessions = (_a = projects.get(event.project)) != null ? _a : /* @__PURE__ */ new Set();
|
|
7050
|
-
sessions.add(event.sessionId);
|
|
7051
|
-
projects.set(event.project, sessions);
|
|
7052
|
-
}
|
|
7053
|
-
const topProject = Array.from(projects.entries()).map(([project, sessions]) => ({ project, sessionCount: sessions.size })).sort((a, b) => b.sessionCount - a.sessionCount || a.project.localeCompare(b.project))[0];
|
|
7054
|
-
return topProject != null ? topProject : null;
|
|
7055
|
-
}
|
|
7056
|
-
function getTopModelForDate(events, options = {}) {
|
|
7057
|
-
var _a;
|
|
7058
|
-
const models = /* @__PURE__ */ new Map();
|
|
7059
|
-
for (const event of events) {
|
|
7060
|
-
if (!shouldIncludeModel(event, options)) {
|
|
7061
|
-
continue;
|
|
7062
|
-
}
|
|
7063
|
-
models.set(event.model, ((_a = models.get(event.model)) != null ? _a : 0) + event.totalTokens);
|
|
7064
|
-
}
|
|
7065
|
-
const topModel = Array.from(models.entries()).sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))[0];
|
|
7066
|
-
return topModel ? {
|
|
7067
|
-
model: topModel[0],
|
|
7068
|
-
totalTokens: topModel[1]
|
|
7069
|
-
} : null;
|
|
7070
|
-
}
|
|
7071
|
-
function createAggregateGroup(label) {
|
|
7072
|
-
return {
|
|
7073
|
-
cachedInputTokens: 0,
|
|
7074
|
-
costUSD: 0,
|
|
7075
|
-
inputTokens: 0,
|
|
7076
|
-
label,
|
|
7077
|
-
models: [],
|
|
7078
|
-
outputTokens: 0,
|
|
7079
|
-
projects: [],
|
|
7080
|
-
reasoningOutputTokens: 0,
|
|
7081
|
-
sessionCount: 0,
|
|
7082
|
-
totalTokens: 0
|
|
7083
|
-
};
|
|
7084
|
-
}
|
|
7085
|
-
function createEmptyUsage() {
|
|
7086
|
-
return {
|
|
7087
|
-
cachedInputTokens: 0,
|
|
7088
|
-
inputTokens: 0,
|
|
7089
|
-
outputTokens: 0,
|
|
7090
|
-
reasoningOutputTokens: 0,
|
|
7091
|
-
totalTokens: 0
|
|
7092
|
-
};
|
|
7093
|
-
}
|
|
7094
|
-
function addUsage(target, usage) {
|
|
7095
|
-
target.inputTokens += usage.inputTokens;
|
|
7096
|
-
target.cachedInputTokens += usage.cachedInputTokens;
|
|
7097
|
-
target.outputTokens += usage.outputTokens;
|
|
7098
|
-
target.reasoningOutputTokens += usage.reasoningOutputTokens;
|
|
7099
|
-
target.totalTokens += usage.totalTokens;
|
|
7100
|
-
}
|
|
7101
|
-
function isZeroUsage(usage) {
|
|
7102
|
-
return usage.inputTokens === 0 && usage.cachedInputTokens === 0 && usage.outputTokens === 0 && usage.reasoningOutputTokens === 0 && usage.totalTokens === 0;
|
|
7103
|
-
}
|
|
7104
|
-
function getProjectName(path, fallback = "unknown") {
|
|
7105
|
-
var _a;
|
|
7106
|
-
if (!path) {
|
|
7107
|
-
return fallback;
|
|
7108
|
-
}
|
|
7109
|
-
const parts = path.split("/").filter(Boolean);
|
|
7110
|
-
return (_a = parts.at(-1)) != null ? _a : fallback;
|
|
7111
|
-
}
|
|
7112
|
-
function normalizeRepositoryUrl(repositoryUrl) {
|
|
7113
|
-
if (!repositoryUrl) {
|
|
7114
|
-
return "";
|
|
7115
|
-
}
|
|
7116
|
-
return repositoryUrl.replace(/^git@[^:]+:/u, "").replace(/^https?:\/\/[^/]+\//u, "").replace(/\.git$/u, "");
|
|
7117
|
-
}
|
|
7118
|
-
function getDurationMinutes(startedAt, endedAt) {
|
|
7119
|
-
if (!endedAt) {
|
|
7120
|
-
return 0;
|
|
7121
|
-
}
|
|
7122
|
-
const durationMs = Date.parse(endedAt) - Date.parse(startedAt);
|
|
7123
|
-
if (!Number.isFinite(durationMs) || durationMs <= 0) {
|
|
7124
|
-
return 0;
|
|
7125
|
-
}
|
|
7126
|
-
return Math.round(durationMs / 6e4);
|
|
7127
|
-
}
|
|
7128
|
-
function toIsoString(value) {
|
|
7129
|
-
if (typeof value !== "string") {
|
|
7130
|
-
return null;
|
|
7131
|
-
}
|
|
7132
|
-
const timestamp = Date.parse(value);
|
|
7133
|
-
return Number.isFinite(timestamp) ? new Date(timestamp).toISOString() : null;
|
|
7134
|
-
}
|
|
7135
|
-
function getMonthKey(date) {
|
|
7136
|
-
return getDateKey(date).slice(0, 7);
|
|
7137
|
-
}
|
|
7138
|
-
function getWeekLabel(date) {
|
|
7139
|
-
const weekStart = cloneDate(date);
|
|
7140
|
-
const day = weekStart.getDay();
|
|
7141
|
-
const diff = day === 0 ? -6 : 1 - day;
|
|
7142
|
-
weekStart.setDate(weekStart.getDate() + diff);
|
|
7143
|
-
const weekEnd = cloneDate(weekStart);
|
|
7144
|
-
weekEnd.setDate(weekEnd.getDate() + 6);
|
|
7145
|
-
return `${getDateKey(weekStart)} - ${getDateKey(weekEnd)}`;
|
|
7146
|
-
}
|
|
7147
|
-
function formatMonthLabel(monthKey) {
|
|
7148
|
-
const [year, month] = monthKey.split("-").map((value) => Number.parseInt(value, 10));
|
|
7149
|
-
const date = new Date(Date.UTC(year || 0, (month || 1) - 1, 1));
|
|
7150
|
-
return new Intl.DateTimeFormat("en-US", {
|
|
7151
|
-
month: "short",
|
|
7152
|
-
timeZone: "UTC",
|
|
7153
|
-
year: "numeric"
|
|
7154
|
-
}).format(date);
|
|
7155
|
-
}
|
|
7156
|
-
function formatDuration(minutes) {
|
|
7157
|
-
const hours = Math.floor(minutes / 60);
|
|
7158
|
-
const remainingMinutes = minutes % 60;
|
|
7159
|
-
if (hours === 0) {
|
|
7160
|
-
return `${remainingMinutes}m`;
|
|
7161
|
-
}
|
|
7162
|
-
if (remainingMinutes === 0) {
|
|
7163
|
-
return `${hours}h`;
|
|
7164
|
-
}
|
|
7165
|
-
return `${hours}h ${remainingMinutes}m`;
|
|
7166
|
-
}
|
|
7167
|
-
function normalizeRawUsage(usage) {
|
|
7168
|
-
var _a;
|
|
7169
|
-
if (!usage) {
|
|
7170
|
-
return null;
|
|
7171
|
-
}
|
|
7172
|
-
const input = normalizeNumber(usage.input_tokens);
|
|
7173
|
-
const cachedInput = normalizeNumber((_a = usage.cached_input_tokens) != null ? _a : usage.cache_read_input_tokens);
|
|
7174
|
-
const output = normalizeNumber(usage.output_tokens);
|
|
7175
|
-
const reasoning = normalizeNumber(usage.reasoning_output_tokens);
|
|
7176
|
-
const total = normalizeNumber(usage.total_tokens);
|
|
7177
|
-
return {
|
|
7178
|
-
cached_input_tokens: cachedInput,
|
|
7179
|
-
input_tokens: input,
|
|
7180
|
-
output_tokens: output,
|
|
7181
|
-
reasoning_output_tokens: reasoning,
|
|
7182
|
-
total_tokens: total > 0 ? total : input + output
|
|
7183
|
-
};
|
|
7184
|
-
}
|
|
7185
|
-
function subtractRawUsage(current, previous) {
|
|
7186
|
-
var _a, _b, _c, _d, _e;
|
|
7187
|
-
return {
|
|
7188
|
-
cached_input_tokens: Math.max(current.cached_input_tokens - ((_a = previous == null ? void 0 : previous.cached_input_tokens) != null ? _a : 0), 0),
|
|
7189
|
-
input_tokens: Math.max(current.input_tokens - ((_b = previous == null ? void 0 : previous.input_tokens) != null ? _b : 0), 0),
|
|
7190
|
-
output_tokens: Math.max(current.output_tokens - ((_c = previous == null ? void 0 : previous.output_tokens) != null ? _c : 0), 0),
|
|
7191
|
-
reasoning_output_tokens: Math.max(current.reasoning_output_tokens - ((_d = previous == null ? void 0 : previous.reasoning_output_tokens) != null ? _d : 0), 0),
|
|
7192
|
-
total_tokens: Math.max(current.total_tokens - ((_e = previous == null ? void 0 : previous.total_tokens) != null ? _e : 0), 0)
|
|
7193
|
-
};
|
|
7194
|
-
}
|
|
7195
|
-
function convertCodexRawUsage(rawUsage) {
|
|
7196
|
-
const cachedInputTokens = Math.min(rawUsage.cached_input_tokens, rawUsage.input_tokens);
|
|
7197
|
-
const inputTokens = Math.max(rawUsage.input_tokens - cachedInputTokens, 0);
|
|
7198
|
-
const outputTokens = Math.max(rawUsage.output_tokens, 0);
|
|
7199
|
-
return {
|
|
7200
|
-
cachedInputTokens,
|
|
7201
|
-
inputTokens,
|
|
7202
|
-
outputTokens,
|
|
7203
|
-
reasoningOutputTokens: Math.max(rawUsage.reasoning_output_tokens, 0),
|
|
7204
|
-
totalTokens: rawUsage.total_tokens > 0 ? rawUsage.total_tokens : inputTokens + outputTokens
|
|
7205
|
-
};
|
|
7206
|
-
}
|
|
7207
|
-
function convertGeminiTokenUsage(tokens) {
|
|
7208
|
-
const rawInputTokens = normalizeNumber(tokens.input);
|
|
7209
|
-
const cachedInputTokens = Math.min(normalizeNumber(tokens.cached), rawInputTokens);
|
|
7210
|
-
const outputTokens = normalizeNumber(tokens.output);
|
|
7211
|
-
const reasoningOutputTokens = normalizeNumber(tokens.thoughts);
|
|
7212
|
-
const toolTokens = normalizeNumber(tokens.tool);
|
|
7213
|
-
const totalTokens = normalizeNumber(tokens.total);
|
|
7214
|
-
return {
|
|
7215
|
-
cachedInputTokens,
|
|
7216
|
-
inputTokens: Math.max(rawInputTokens - cachedInputTokens, 0),
|
|
7217
|
-
outputTokens,
|
|
7218
|
-
reasoningOutputTokens,
|
|
7219
|
-
totalTokens: totalTokens > 0 ? totalTokens : rawInputTokens + outputTokens + reasoningOutputTokens + toolTokens
|
|
7220
|
-
};
|
|
7221
|
-
}
|
|
7222
|
-
function extractModelName(value) {
|
|
7223
|
-
if (!value || typeof value !== "object") {
|
|
7224
|
-
return void 0;
|
|
7225
|
-
}
|
|
7226
|
-
const record = value;
|
|
7227
|
-
const info = normalizeUnknownRecord(record.info);
|
|
7228
|
-
const metadata = normalizeUnknownRecord(record.metadata);
|
|
7229
|
-
const infoMetadata = normalizeUnknownRecord(info == null ? void 0 : info.metadata);
|
|
7230
|
-
const candidates = [
|
|
7231
|
-
record.model,
|
|
7232
|
-
record.model_name,
|
|
7233
|
-
info == null ? void 0 : info.model,
|
|
7234
|
-
info == null ? void 0 : info.model_name,
|
|
7235
|
-
infoMetadata == null ? void 0 : infoMetadata.model,
|
|
7236
|
-
metadata == null ? void 0 : metadata.model
|
|
7237
|
-
];
|
|
7238
|
-
for (const candidate of candidates) {
|
|
7239
|
-
if (typeof candidate === "string" && candidate.trim() !== "") {
|
|
7240
|
-
return candidate.trim();
|
|
7241
|
-
}
|
|
7242
|
-
}
|
|
7243
|
-
return void 0;
|
|
7244
|
-
}
|
|
7245
|
-
function extractClaudeProjectFromPath(jsonlPath) {
|
|
7246
|
-
var _a;
|
|
7247
|
-
const normalizedPath = jsonlPath.replace(/[/\\]/g, sep);
|
|
7248
|
-
const segments = normalizedPath.split(sep);
|
|
7249
|
-
const projectsIndex = segments.findIndex((segment) => segment === "projects");
|
|
7250
|
-
if (projectsIndex === -1 || projectsIndex + 1 >= segments.length) {
|
|
7251
|
-
return "unknown";
|
|
7252
|
-
}
|
|
7253
|
-
return ((_a = segments[projectsIndex + 1]) == null ? void 0 : _a.trim()) || "unknown";
|
|
7254
|
-
}
|
|
7255
|
-
function decodeClaudeProjectPath(projectPath) {
|
|
7256
|
-
var _a;
|
|
7257
|
-
const normalized = projectPath.replace(/^-/, "").replace(/-/g, "/");
|
|
7258
|
-
const parts = normalized.split("/").filter(Boolean);
|
|
7259
|
-
return (_a = parts.at(-1)) != null ? _a : projectPath;
|
|
7260
|
-
}
|
|
7261
|
-
function getClaudeLookupCandidates(model) {
|
|
7262
|
-
var _a;
|
|
7263
|
-
const normalizedModel = model.trim();
|
|
7264
|
-
const withoutFastSuffix = normalizedModel.replace(/-fast$/u, "");
|
|
7265
|
-
const baseModel = (_a = withoutFastSuffix.split("/").at(-1)) != null ? _a : withoutFastSuffix;
|
|
7266
|
-
const normalizedBaseModel = baseModel.replace(/[.@]/gu, "-");
|
|
7267
|
-
const baseModelWithoutDate = normalizedBaseModel.replace(/-\d{8}$/u, "");
|
|
7268
|
-
return [
|
|
7269
|
-
normalizedModel,
|
|
7270
|
-
withoutFastSuffix,
|
|
7271
|
-
withoutFastSuffix.replace(/^anthropic\//u, ""),
|
|
7272
|
-
`anthropic/${normalizedModel}`,
|
|
7273
|
-
baseModel,
|
|
7274
|
-
normalizedBaseModel,
|
|
7275
|
-
baseModelWithoutDate,
|
|
7276
|
-
`anthropic/${baseModelWithoutDate}`,
|
|
7277
|
-
baseModelWithoutDate.replace(/^claude-3-5-/u, "claude-"),
|
|
7278
|
-
baseModelWithoutDate.replace(/^claude-3-7-/u, "claude-")
|
|
7279
|
-
];
|
|
7280
|
-
}
|
|
7281
|
-
function getGeminiLookupCandidates(model) {
|
|
7282
|
-
const normalizedModel = model.trim();
|
|
7283
|
-
return [
|
|
7284
|
-
normalizedModel,
|
|
7285
|
-
normalizedModel.replace(/^gemini\//u, ""),
|
|
7286
|
-
normalizedModel.replace(/^google\//u, ""),
|
|
7287
|
-
`gemini/${normalizedModel}`,
|
|
7288
|
-
`google/${normalizedModel}`
|
|
7289
|
-
];
|
|
7290
|
-
}
|
|
7291
|
-
function isOpenRouterFreeModel(model) {
|
|
7292
|
-
const normalizedModel = model.trim().toLowerCase();
|
|
7293
|
-
return normalizedModel === "openrouter/free" || normalizedModel.startsWith("openrouter/") && normalizedModel.endsWith(":free");
|
|
7294
|
-
}
|
|
7295
|
-
function getGeminiProjectRoot(filePath) {
|
|
7296
|
-
const projectDir = dirname$1(dirname$1(filePath));
|
|
7297
|
-
const projectRootFile = `${projectDir}/.project_root`;
|
|
7298
|
-
if (!existsSync(projectRootFile)) {
|
|
7299
|
-
return "";
|
|
7300
|
-
}
|
|
7301
|
-
try {
|
|
7302
|
-
return readFileSync(projectRootFile, "utf8").trim();
|
|
7303
|
-
} catch {
|
|
7304
|
-
return "";
|
|
7305
|
-
}
|
|
7306
|
-
}
|
|
7307
|
-
function getGeminiProjectKeyFromPath(filePath) {
|
|
7308
|
-
var _a;
|
|
7309
|
-
const normalizedPath = filePath.replace(/[/\\]/g, sep);
|
|
7310
|
-
const segments = normalizedPath.split(sep);
|
|
7311
|
-
const tmpIndex = segments.findIndex((segment) => segment === "tmp");
|
|
7312
|
-
if (tmpIndex === -1 || tmpIndex + 1 >= segments.length) {
|
|
7313
|
-
return "unknown";
|
|
7314
|
-
}
|
|
7315
|
-
return ((_a = segments[tmpIndex + 1]) == null ? void 0 : _a.trim()) || "unknown";
|
|
7316
|
-
}
|
|
7317
|
-
function getRepositoryNameFromProjectRoot(projectRoot) {
|
|
7318
|
-
if (!projectRoot) {
|
|
7319
|
-
return "";
|
|
7320
|
-
}
|
|
7321
|
-
const gitConfigPath = `${projectRoot}/.git/config`;
|
|
7322
|
-
if (!existsSync(gitConfigPath)) {
|
|
7323
|
-
return "";
|
|
7324
|
-
}
|
|
7325
|
-
try {
|
|
7326
|
-
return normalizeRepositoryUrl(getOriginUrlFromGitConfig(readFileSync(gitConfigPath, "utf8")));
|
|
7327
|
-
} catch {
|
|
7328
|
-
return "";
|
|
7329
|
-
}
|
|
7330
|
-
}
|
|
7331
|
-
function getOriginUrlFromGitConfig(config) {
|
|
7332
|
-
let isOriginBlock = false;
|
|
7333
|
-
for (const rawLine of config.split("\n")) {
|
|
7334
|
-
const line = rawLine.trim();
|
|
7335
|
-
if (line.startsWith("[")) {
|
|
7336
|
-
isOriginBlock = line === '[remote "origin"]';
|
|
7337
|
-
continue;
|
|
7338
|
-
}
|
|
7339
|
-
if (!isOriginBlock || !line.startsWith("url =")) {
|
|
7340
|
-
continue;
|
|
7341
|
-
}
|
|
7342
|
-
return line.slice("url =".length).trim();
|
|
7343
|
-
}
|
|
7344
|
-
return "";
|
|
7345
|
-
}
|
|
7346
|
-
function extractGeminiMessageText(content) {
|
|
7347
|
-
if (typeof content === "string") {
|
|
7348
|
-
return content;
|
|
7349
|
-
}
|
|
7350
|
-
if (!Array.isArray(content)) {
|
|
7351
|
-
return "";
|
|
7352
|
-
}
|
|
7353
|
-
return content.map((item) => {
|
|
7354
|
-
var _a;
|
|
7355
|
-
return (_a = item.text) == null ? void 0 : _a.trim();
|
|
7356
|
-
}).filter(Boolean).join("\n");
|
|
7357
|
-
}
|
|
7358
|
-
function addEventToAggregateGroup(group, event, options) {
|
|
7359
|
-
group.inputTokens += event.inputTokens;
|
|
7360
|
-
group.cachedInputTokens += event.cachedInputTokens;
|
|
7361
|
-
group.outputTokens += event.outputTokens;
|
|
7362
|
-
group.reasoningOutputTokens += event.reasoningOutputTokens;
|
|
7363
|
-
group.totalTokens += event.totalTokens;
|
|
7364
|
-
group.costUSD += getEventCostUSD(event, options);
|
|
7365
|
-
group.models = shouldIncludeModel(event, options) ? uniqueItems([...group.models, event.model]) : group.models;
|
|
7366
|
-
group.projects = uniqueItems([...group.projects, event.project]);
|
|
7367
|
-
}
|
|
7368
|
-
function getEventCostUSD(event, options) {
|
|
7369
|
-
var _a, _b, _c;
|
|
7370
|
-
return (_c = (_b = (_a = options.getCostUSD) == null ? void 0 : _a.call(options, event)) != null ? _b : event.costUSD) != null ? _c : 0;
|
|
7371
|
-
}
|
|
7372
|
-
function shouldIncludeModel(event, options) {
|
|
7373
|
-
var _a, _b;
|
|
7374
|
-
return (_b = (_a = options.includeModel) == null ? void 0 : _a.call(options, event)) != null ? _b : true;
|
|
7375
|
-
}
|
|
7376
|
-
function getCachedInputTokens(session, options) {
|
|
7377
|
-
var _a, _b;
|
|
7378
|
-
return (_b = (_a = options.getCachedInputTokens) == null ? void 0 : _a.call(options, session)) != null ? _b : getNumericProperty(session, "cachedInputTokens");
|
|
7379
|
-
}
|
|
7380
|
-
function getReasoningOutputTokens(session, options) {
|
|
7381
|
-
var _a, _b;
|
|
7382
|
-
return (_b = (_a = options.getReasoningOutputTokens) == null ? void 0 : _a.call(options, session)) != null ? _b : getNumericProperty(session, "reasoningOutputTokens");
|
|
7383
|
-
}
|
|
7384
|
-
function getNumericProperty(value, key) {
|
|
7385
|
-
const record = value;
|
|
7386
|
-
const property = record[key];
|
|
7387
|
-
return typeof property === "number" && Number.isFinite(property) ? property : 0;
|
|
7388
|
-
}
|
|
7389
|
-
function cloneDate(date) {
|
|
7390
|
-
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
7391
|
-
}
|
|
7392
|
-
|
|
7393
|
-
function toDiscoveredUsageFile(filePath, platform, cacheSignature = "") {
|
|
7394
|
-
try {
|
|
7395
|
-
const stats = statSync(filePath);
|
|
7396
|
-
return [{
|
|
7397
|
-
cacheSignature,
|
|
7398
|
-
mtimeMs: stats.mtimeMs,
|
|
7399
|
-
path: filePath,
|
|
7400
|
-
platform,
|
|
7401
|
-
size: stats.size
|
|
7402
|
-
}];
|
|
7403
|
-
} catch {
|
|
7404
|
-
return [];
|
|
7767
|
+
for (const event of events) {
|
|
7768
|
+
const sessions = (_a = projects.get(event.project)) != null ? _a : /* @__PURE__ */ new Set();
|
|
7769
|
+
sessions.add(event.sessionId);
|
|
7770
|
+
projects.set(event.project, sessions);
|
|
7405
7771
|
}
|
|
7772
|
+
const topProject = Array.from(projects.entries()).map(([project, sessions]) => ({ project, sessionCount: sessions.size })).sort((a, b) => b.sessionCount - a.sessionCount || a.project.localeCompare(b.project))[0];
|
|
7773
|
+
return topProject != null ? topProject : null;
|
|
7406
7774
|
}
|
|
7407
|
-
function
|
|
7775
|
+
function getTopModelForDate(events, options = {}) {
|
|
7776
|
+
var _a;
|
|
7777
|
+
const models = /* @__PURE__ */ new Map();
|
|
7778
|
+
for (const event of events) {
|
|
7779
|
+
if (!shouldIncludeModel(event, options)) {
|
|
7780
|
+
continue;
|
|
7781
|
+
}
|
|
7782
|
+
models.set(event.model, ((_a = models.get(event.model)) != null ? _a : 0) + event.totalTokens);
|
|
7783
|
+
}
|
|
7784
|
+
const topModel = Array.from(models.entries()).sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))[0];
|
|
7785
|
+
return topModel ? {
|
|
7786
|
+
model: topModel[0],
|
|
7787
|
+
totalTokens: topModel[1]
|
|
7788
|
+
} : null;
|
|
7789
|
+
}
|
|
7790
|
+
function createAggregateGroup(label) {
|
|
7408
7791
|
return {
|
|
7409
|
-
|
|
7410
|
-
|
|
7411
|
-
|
|
7412
|
-
|
|
7413
|
-
|
|
7414
|
-
|
|
7415
|
-
|
|
7416
|
-
|
|
7792
|
+
cachedInputTokens: 0,
|
|
7793
|
+
costUSD: 0,
|
|
7794
|
+
inputTokens: 0,
|
|
7795
|
+
label,
|
|
7796
|
+
models: [],
|
|
7797
|
+
outputTokens: 0,
|
|
7798
|
+
projects: [],
|
|
7799
|
+
reasoningOutputTokens: 0,
|
|
7800
|
+
sessionCount: 0,
|
|
7801
|
+
totalTokens: 0
|
|
7417
7802
|
};
|
|
7418
7803
|
}
|
|
7419
|
-
function
|
|
7420
|
-
|
|
7421
|
-
|
|
7422
|
-
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
|
|
7426
|
-
}
|
|
7427
|
-
if (!fragment.durationEndAt || Date.parse(interaction.timestamp) > Date.parse(fragment.durationEndAt)) {
|
|
7428
|
-
fragment.durationEndAt = interaction.timestamp;
|
|
7429
|
-
}
|
|
7804
|
+
function createEmptyUsage() {
|
|
7805
|
+
return {
|
|
7806
|
+
cachedInputTokens: 0,
|
|
7807
|
+
inputTokens: 0,
|
|
7808
|
+
outputTokens: 0,
|
|
7809
|
+
reasoningOutputTokens: 0,
|
|
7810
|
+
totalTokens: 0
|
|
7811
|
+
};
|
|
7430
7812
|
}
|
|
7431
|
-
function
|
|
7432
|
-
|
|
7813
|
+
function addUsage(target, usage) {
|
|
7814
|
+
target.inputTokens += usage.inputTokens;
|
|
7815
|
+
target.cachedInputTokens += usage.cachedInputTokens;
|
|
7816
|
+
target.outputTokens += usage.outputTokens;
|
|
7817
|
+
target.reasoningOutputTokens += usage.reasoningOutputTokens;
|
|
7818
|
+
target.totalTokens += usage.totalTokens;
|
|
7433
7819
|
}
|
|
7434
|
-
function
|
|
7435
|
-
|
|
7436
|
-
|
|
7437
|
-
|
|
7438
|
-
|
|
7439
|
-
if (
|
|
7440
|
-
return
|
|
7820
|
+
function isZeroUsage(usage) {
|
|
7821
|
+
return usage.inputTokens === 0 && usage.cachedInputTokens === 0 && usage.outputTokens === 0 && usage.reasoningOutputTokens === 0 && usage.totalTokens === 0;
|
|
7822
|
+
}
|
|
7823
|
+
function getProjectName(path, fallback = "unknown") {
|
|
7824
|
+
var _a;
|
|
7825
|
+
if (!path) {
|
|
7826
|
+
return fallback;
|
|
7441
7827
|
}
|
|
7442
|
-
|
|
7443
|
-
|
|
7828
|
+
const parts = path.split("/").filter(Boolean);
|
|
7829
|
+
return (_a = parts.at(-1)) != null ? _a : fallback;
|
|
7830
|
+
}
|
|
7831
|
+
function normalizeRepositoryUrl(repositoryUrl) {
|
|
7832
|
+
if (!repositoryUrl) {
|
|
7833
|
+
return "";
|
|
7444
7834
|
}
|
|
7445
|
-
|
|
7446
|
-
|
|
7835
|
+
return repositoryUrl.replace(/^git@[^:]+:/u, "").replace(/^https?:\/\/[^/]+\//u, "").replace(/\.git$/u, "");
|
|
7836
|
+
}
|
|
7837
|
+
function getDurationMinutes(startedAt, endedAt) {
|
|
7838
|
+
if (!endedAt) {
|
|
7839
|
+
return 0;
|
|
7447
7840
|
}
|
|
7448
|
-
|
|
7449
|
-
|
|
7841
|
+
const durationMs = Date.parse(endedAt) - Date.parse(startedAt);
|
|
7842
|
+
if (!Number.isFinite(durationMs) || durationMs <= 0) {
|
|
7843
|
+
return 0;
|
|
7450
7844
|
}
|
|
7451
|
-
return
|
|
7845
|
+
return Math.round(durationMs / 6e4);
|
|
7452
7846
|
}
|
|
7453
|
-
|
|
7454
|
-
|
|
7455
|
-
const
|
|
7456
|
-
|
|
7457
|
-
const FAST_MULTIPLIER_EXACT_OVERRIDES = {
|
|
7458
|
-
"gpt-5.3-codex": 2,
|
|
7459
|
-
"gpt-5.4": 2,
|
|
7460
|
-
"gpt-5.5": 2.5
|
|
7461
|
-
};
|
|
7462
|
-
const FAST_MULTIPLIER_PREFIX_OVERRIDES = {
|
|
7463
|
-
"claude-opus-4-6": 6,
|
|
7464
|
-
"claude-opus-4-7": 6
|
|
7465
|
-
};
|
|
7466
|
-
const DEFAULT_FALLBACK_PRICING_TABLE = {
|
|
7467
|
-
"gpt-5": {
|
|
7468
|
-
cachedInputCostPerMTokens: 0.125,
|
|
7469
|
-
cacheCreationInputCostPerMTokens: 1.25,
|
|
7470
|
-
inputCostPerMTokens: 1.25,
|
|
7471
|
-
outputCostPerMTokens: 10
|
|
7472
|
-
},
|
|
7473
|
-
"gpt-5.2-codex": {
|
|
7474
|
-
cachedInputCostPerMTokens: 0.175,
|
|
7475
|
-
cacheCreationInputCostPerMTokens: 1.75,
|
|
7476
|
-
inputCostPerMTokens: 1.75,
|
|
7477
|
-
outputCostPerMTokens: 14
|
|
7478
|
-
},
|
|
7479
|
-
"gpt-5.4": {
|
|
7480
|
-
cachedInputCostPerMTokens: 0.25,
|
|
7481
|
-
cacheCreationInputCostPerMTokens: 2.5,
|
|
7482
|
-
inputCostPerMTokens: 2.5,
|
|
7483
|
-
outputCostPerMTokens: 15
|
|
7484
|
-
},
|
|
7485
|
-
"gpt-5.5": {
|
|
7486
|
-
cachedInputCostPerMTokens: 0.5,
|
|
7487
|
-
cacheCreationInputCostPerMTokens: 5,
|
|
7488
|
-
fastMultiplier: FAST_MULTIPLIER_EXACT_OVERRIDES["gpt-5.5"],
|
|
7489
|
-
inputCostPerMTokens: 5,
|
|
7490
|
-
outputCostPerMTokens: 30
|
|
7491
|
-
},
|
|
7492
|
-
"claude-haiku-4-5": {
|
|
7493
|
-
cachedInputCostPerMTokens: 0.1,
|
|
7494
|
-
cacheCreationInputCostPerMTokens: 1.25,
|
|
7495
|
-
inputCostPerMTokens: 1,
|
|
7496
|
-
outputCostPerMTokens: 5
|
|
7497
|
-
},
|
|
7498
|
-
"claude-opus-4-1": {
|
|
7499
|
-
cachedInputCostPerMTokens: 1.5,
|
|
7500
|
-
cachedInputCostPerMTokensAbove200K: 3,
|
|
7501
|
-
cacheCreationInputCostPerMTokens: 18.75,
|
|
7502
|
-
cacheCreationInputCostPerMTokensAbove200K: 37.5,
|
|
7503
|
-
inputCostPerMTokens: 15,
|
|
7504
|
-
inputCostPerMTokensAbove200K: 30,
|
|
7505
|
-
outputCostPerMTokens: 75,
|
|
7506
|
-
outputCostPerMTokensAbove200K: 112.5
|
|
7507
|
-
},
|
|
7508
|
-
"claude-opus-4-6": {
|
|
7509
|
-
cachedInputCostPerMTokens: 0.5,
|
|
7510
|
-
cacheCreationInputCostPerMTokens: 6.25,
|
|
7511
|
-
fastMultiplier: FAST_MULTIPLIER_PREFIX_OVERRIDES["claude-opus-4-6"],
|
|
7512
|
-
inputCostPerMTokens: 5,
|
|
7513
|
-
outputCostPerMTokens: 25
|
|
7514
|
-
},
|
|
7515
|
-
"claude-opus-4-7": {
|
|
7516
|
-
cachedInputCostPerMTokens: 0.5,
|
|
7517
|
-
cacheCreationInputCostPerMTokens: 6.25,
|
|
7518
|
-
fastMultiplier: FAST_MULTIPLIER_PREFIX_OVERRIDES["claude-opus-4-7"],
|
|
7519
|
-
inputCostPerMTokens: 5,
|
|
7520
|
-
outputCostPerMTokens: 25
|
|
7521
|
-
},
|
|
7522
|
-
"claude-sonnet-4-5": {
|
|
7523
|
-
cachedInputCostPerMTokens: 0.3,
|
|
7524
|
-
cachedInputCostPerMTokensAbove200K: 0.6,
|
|
7525
|
-
cacheCreationInputCostPerMTokens: 3.75,
|
|
7526
|
-
cacheCreationInputCostPerMTokensAbove200K: 7.5,
|
|
7527
|
-
inputCostPerMTokens: 3,
|
|
7528
|
-
inputCostPerMTokensAbove200K: 6,
|
|
7529
|
-
outputCostPerMTokens: 15,
|
|
7530
|
-
outputCostPerMTokensAbove200K: 22.5
|
|
7847
|
+
function toIsoString(value) {
|
|
7848
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
7849
|
+
const timestamp2 = value > 1e10 ? value : value * 1e3;
|
|
7850
|
+
return new Date(timestamp2).toISOString();
|
|
7531
7851
|
}
|
|
7532
|
-
|
|
7533
|
-
|
|
7534
|
-
async function fetchLiteLLMPricingDataset(options = {}) {
|
|
7535
|
-
var _a, _b, _c, _d;
|
|
7536
|
-
const url = (_a = options.url) != null ? _a : DEFAULT_LITELLM_PRICING_URL;
|
|
7537
|
-
const cacheTtlMs = (_b = options.cacheTtlMs) != null ? _b : DEFAULT_PRICING_CACHE_TTL_MS;
|
|
7538
|
-
const now = Date.now();
|
|
7539
|
-
const cacheEntry = pricingCache.get(url);
|
|
7540
|
-
if (!options.forceRefresh && (cacheEntry == null ? void 0 : cacheEntry.value) && now - cacheEntry.fetchedAt < cacheTtlMs) {
|
|
7541
|
-
return cacheEntry.value;
|
|
7852
|
+
if (value instanceof Date) {
|
|
7853
|
+
return Number.isFinite(value.getTime()) ? value.toISOString() : null;
|
|
7542
7854
|
}
|
|
7543
|
-
if (
|
|
7544
|
-
return
|
|
7855
|
+
if (typeof value !== "string") {
|
|
7856
|
+
return null;
|
|
7545
7857
|
}
|
|
7546
|
-
const
|
|
7547
|
-
if (
|
|
7548
|
-
return
|
|
7858
|
+
const normalizedValue = value.trim();
|
|
7859
|
+
if (!normalizedValue) {
|
|
7860
|
+
return null;
|
|
7549
7861
|
}
|
|
7550
|
-
const
|
|
7551
|
-
|
|
7552
|
-
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
|
|
7560
|
-
|
|
7561
|
-
|
|
7562
|
-
|
|
7563
|
-
|
|
7564
|
-
|
|
7565
|
-
|
|
7566
|
-
|
|
7567
|
-
|
|
7568
|
-
|
|
7569
|
-
|
|
7570
|
-
|
|
7571
|
-
|
|
7572
|
-
|
|
7573
|
-
return fallback;
|
|
7574
|
-
});
|
|
7575
|
-
pricingCache.set(url, {
|
|
7576
|
-
fetchedAt: (_d = cacheEntry == null ? void 0 : cacheEntry.fetchedAt) != null ? _d : 0,
|
|
7577
|
-
promise,
|
|
7578
|
-
value: cacheEntry == null ? void 0 : cacheEntry.value
|
|
7579
|
-
});
|
|
7580
|
-
return promise;
|
|
7862
|
+
const timestamp = Date.parse(normalizedValue);
|
|
7863
|
+
return Number.isFinite(timestamp) ? new Date(timestamp).toISOString() : null;
|
|
7864
|
+
}
|
|
7865
|
+
function getMonthKey(date) {
|
|
7866
|
+
return getDateKey(date).slice(0, 7);
|
|
7867
|
+
}
|
|
7868
|
+
function getWeekLabel(date) {
|
|
7869
|
+
const weekStart = cloneDate(date);
|
|
7870
|
+
const day = weekStart.getDay();
|
|
7871
|
+
const diff = day === 0 ? -6 : 1 - day;
|
|
7872
|
+
weekStart.setDate(weekStart.getDate() + diff);
|
|
7873
|
+
const weekEnd = cloneDate(weekStart);
|
|
7874
|
+
weekEnd.setDate(weekEnd.getDate() + 6);
|
|
7875
|
+
return `${getDateKey(weekStart)} - ${getDateKey(weekEnd)}`;
|
|
7876
|
+
}
|
|
7877
|
+
function formatMonthLabel(monthKey) {
|
|
7878
|
+
const [year, month] = monthKey.split("-").map((value) => Number.parseInt(value, 10));
|
|
7879
|
+
const date = new Date(Date.UTC(year || 0, (month || 1) - 1, 1));
|
|
7880
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
7881
|
+
month: "short",
|
|
7882
|
+
timeZone: "UTC",
|
|
7883
|
+
year: "numeric"
|
|
7884
|
+
}).format(date);
|
|
7581
7885
|
}
|
|
7582
|
-
|
|
7583
|
-
|
|
7584
|
-
const
|
|
7585
|
-
|
|
7586
|
-
|
|
7587
|
-
|
|
7588
|
-
|
|
7886
|
+
function formatDuration(minutes) {
|
|
7887
|
+
const hours = Math.floor(minutes / 60);
|
|
7888
|
+
const remainingMinutes = minutes % 60;
|
|
7889
|
+
if (hours === 0) {
|
|
7890
|
+
return `${remainingMinutes}m`;
|
|
7891
|
+
}
|
|
7892
|
+
if (remainingMinutes === 0) {
|
|
7893
|
+
return `${hours}h`;
|
|
7894
|
+
}
|
|
7895
|
+
return `${hours}h ${remainingMinutes}m`;
|
|
7896
|
+
}
|
|
7897
|
+
function normalizeRawUsage(usage) {
|
|
7898
|
+
var _a;
|
|
7899
|
+
if (!usage) {
|
|
7900
|
+
return null;
|
|
7901
|
+
}
|
|
7902
|
+
const input = normalizeNumber(usage.input_tokens);
|
|
7903
|
+
const cachedInput = normalizeNumber((_a = usage.cached_input_tokens) != null ? _a : usage.cache_read_input_tokens);
|
|
7904
|
+
const output = normalizeNumber(usage.output_tokens);
|
|
7905
|
+
const reasoning = normalizeNumber(usage.reasoning_output_tokens);
|
|
7906
|
+
const total = normalizeNumber(usage.total_tokens);
|
|
7907
|
+
return {
|
|
7908
|
+
cached_input_tokens: cachedInput,
|
|
7909
|
+
input_tokens: input,
|
|
7910
|
+
output_tokens: output,
|
|
7911
|
+
reasoning_output_tokens: reasoning,
|
|
7912
|
+
total_tokens: total > 0 ? total : input + output + reasoning
|
|
7589
7913
|
};
|
|
7590
|
-
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
return
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
|
|
7597
|
-
|
|
7598
|
-
|
|
7599
|
-
const datasetPricing = resolveDatasetPricing(dataset, lookupCandidates);
|
|
7600
|
-
if (datasetPricing) {
|
|
7601
|
-
return datasetPricing;
|
|
7602
|
-
}
|
|
7603
|
-
const fallbackPricing = resolveFallbackPricing(fallbackPricingTable, lookupCandidates);
|
|
7604
|
-
if (fallbackPricing) {
|
|
7605
|
-
return fallbackPricing;
|
|
7606
|
-
}
|
|
7607
|
-
if (fallbackModel) {
|
|
7608
|
-
const fallbackCandidates = uniqueItems(expandLookupCandidates(fallbackModel, aliases, getLookupCandidates).filter(Boolean));
|
|
7609
|
-
return (_b2 = (_a2 = resolveDatasetPricing(dataset, fallbackCandidates)) != null ? _a2 : resolveFallbackPricing(fallbackPricingTable, fallbackCandidates)) != null ? _b2 : createZeroPricing();
|
|
7610
|
-
}
|
|
7611
|
-
return createZeroPricing();
|
|
7914
|
+
}
|
|
7915
|
+
function subtractRawUsage(current, previous) {
|
|
7916
|
+
var _a, _b, _c, _d, _e;
|
|
7917
|
+
return {
|
|
7918
|
+
cached_input_tokens: Math.max(current.cached_input_tokens - ((_a = previous == null ? void 0 : previous.cached_input_tokens) != null ? _a : 0), 0),
|
|
7919
|
+
input_tokens: Math.max(current.input_tokens - ((_b = previous == null ? void 0 : previous.input_tokens) != null ? _b : 0), 0),
|
|
7920
|
+
output_tokens: Math.max(current.output_tokens - ((_c = previous == null ? void 0 : previous.output_tokens) != null ? _c : 0), 0),
|
|
7921
|
+
reasoning_output_tokens: Math.max(current.reasoning_output_tokens - ((_d = previous == null ? void 0 : previous.reasoning_output_tokens) != null ? _d : 0), 0),
|
|
7922
|
+
total_tokens: Math.max(current.total_tokens - ((_e = previous == null ? void 0 : previous.total_tokens) != null ? _e : 0), 0)
|
|
7612
7923
|
};
|
|
7613
7924
|
}
|
|
7614
|
-
function
|
|
7615
|
-
|
|
7616
|
-
const
|
|
7617
|
-
const
|
|
7618
|
-
|
|
7619
|
-
|
|
7620
|
-
|
|
7621
|
-
|
|
7925
|
+
function convertCodexRawUsage(rawUsage) {
|
|
7926
|
+
const cachedInputTokens = Math.min(rawUsage.cached_input_tokens, rawUsage.input_tokens);
|
|
7927
|
+
const inputTokens = Math.max(rawUsage.input_tokens - cachedInputTokens, 0);
|
|
7928
|
+
const outputTokens = Math.max(rawUsage.output_tokens, 0);
|
|
7929
|
+
return {
|
|
7930
|
+
cachedInputTokens,
|
|
7931
|
+
inputTokens,
|
|
7932
|
+
outputTokens,
|
|
7933
|
+
reasoningOutputTokens: Math.max(rawUsage.reasoning_output_tokens, 0),
|
|
7934
|
+
totalTokens: rawUsage.total_tokens > 0 ? rawUsage.total_tokens : inputTokens + outputTokens
|
|
7935
|
+
};
|
|
7622
7936
|
}
|
|
7623
|
-
function
|
|
7937
|
+
function convertGeminiTokenUsage(tokens) {
|
|
7938
|
+
const rawInputTokens = normalizeNumber(tokens.input);
|
|
7939
|
+
const cachedInputTokens = Math.min(normalizeNumber(tokens.cached), rawInputTokens);
|
|
7940
|
+
const outputTokens = normalizeNumber(tokens.output);
|
|
7941
|
+
const reasoningOutputTokens = normalizeNumber(tokens.thoughts);
|
|
7942
|
+
const toolTokens = normalizeNumber(tokens.tool);
|
|
7943
|
+
const totalTokens = normalizeNumber(tokens.total);
|
|
7624
7944
|
return {
|
|
7625
|
-
|
|
7626
|
-
|
|
7627
|
-
|
|
7628
|
-
|
|
7629
|
-
|
|
7630
|
-
},
|
|
7631
|
-
"gpt-5.2-codex": {
|
|
7632
|
-
input_cost_per_token: 175e-8,
|
|
7633
|
-
output_cost_per_token: 14e-6,
|
|
7634
|
-
cache_creation_input_token_cost: 175e-8,
|
|
7635
|
-
cache_read_input_token_cost: 175e-9
|
|
7636
|
-
},
|
|
7637
|
-
"gpt-5.4": {
|
|
7638
|
-
input_cost_per_token: 25e-7,
|
|
7639
|
-
output_cost_per_token: 15e-6,
|
|
7640
|
-
cache_creation_input_token_cost: 25e-7,
|
|
7641
|
-
cache_read_input_token_cost: 25e-8
|
|
7642
|
-
},
|
|
7643
|
-
"gpt-5.5": {
|
|
7644
|
-
input_cost_per_token: 5e-6,
|
|
7645
|
-
output_cost_per_token: 3e-5,
|
|
7646
|
-
cache_creation_input_token_cost: 5e-6,
|
|
7647
|
-
cache_read_input_token_cost: 5e-7,
|
|
7648
|
-
provider_specific_entry: {
|
|
7649
|
-
fast: 2.5
|
|
7650
|
-
}
|
|
7651
|
-
},
|
|
7652
|
-
"claude-haiku-4-5": {
|
|
7653
|
-
input_cost_per_token: 1e-6,
|
|
7654
|
-
output_cost_per_token: 5e-6,
|
|
7655
|
-
cache_creation_input_token_cost: 125e-8,
|
|
7656
|
-
cache_read_input_token_cost: 1e-7
|
|
7657
|
-
},
|
|
7658
|
-
"claude-opus-4-1": {
|
|
7659
|
-
input_cost_per_token: 15e-6,
|
|
7660
|
-
output_cost_per_token: 75e-6,
|
|
7661
|
-
cache_creation_input_token_cost: 1875e-8,
|
|
7662
|
-
cache_read_input_token_cost: 15e-7,
|
|
7663
|
-
input_cost_per_token_above_200k_tokens: 3e-5,
|
|
7664
|
-
output_cost_per_token_above_200k_tokens: 1125e-7,
|
|
7665
|
-
cache_creation_input_token_cost_above_200k_tokens: 375e-7,
|
|
7666
|
-
cache_read_input_token_cost_above_200k_tokens: 3e-6
|
|
7667
|
-
},
|
|
7668
|
-
"claude-opus-4-6": {
|
|
7669
|
-
input_cost_per_token: 5e-6,
|
|
7670
|
-
output_cost_per_token: 25e-6,
|
|
7671
|
-
cache_creation_input_token_cost: 625e-8,
|
|
7672
|
-
cache_read_input_token_cost: 5e-7,
|
|
7673
|
-
provider_specific_entry: {
|
|
7674
|
-
fast: 6
|
|
7675
|
-
}
|
|
7676
|
-
},
|
|
7677
|
-
"claude-opus-4-7": {
|
|
7678
|
-
input_cost_per_token: 5e-6,
|
|
7679
|
-
output_cost_per_token: 25e-6,
|
|
7680
|
-
cache_creation_input_token_cost: 625e-8,
|
|
7681
|
-
cache_read_input_token_cost: 5e-7,
|
|
7682
|
-
provider_specific_entry: {
|
|
7683
|
-
fast: 6
|
|
7684
|
-
}
|
|
7685
|
-
},
|
|
7686
|
-
"claude-sonnet-4-5": {
|
|
7687
|
-
input_cost_per_token: 3e-6,
|
|
7688
|
-
output_cost_per_token: 15e-6,
|
|
7689
|
-
cache_creation_input_token_cost: 375e-8,
|
|
7690
|
-
cache_read_input_token_cost: 3e-7,
|
|
7691
|
-
input_cost_per_token_above_200k_tokens: 6e-6,
|
|
7692
|
-
output_cost_per_token_above_200k_tokens: 225e-7,
|
|
7693
|
-
cache_creation_input_token_cost_above_200k_tokens: 75e-7,
|
|
7694
|
-
cache_read_input_token_cost_above_200k_tokens: 6e-7
|
|
7695
|
-
}
|
|
7945
|
+
cachedInputTokens,
|
|
7946
|
+
inputTokens: Math.max(rawInputTokens - cachedInputTokens, 0),
|
|
7947
|
+
outputTokens,
|
|
7948
|
+
reasoningOutputTokens,
|
|
7949
|
+
totalTokens: totalTokens > 0 ? totalTokens : rawInputTokens + outputTokens + reasoningOutputTokens + toolTokens
|
|
7696
7950
|
};
|
|
7697
7951
|
}
|
|
7698
|
-
function
|
|
7699
|
-
if (!value || typeof value !== "object"
|
|
7700
|
-
return
|
|
7952
|
+
function extractModelName(value) {
|
|
7953
|
+
if (!value || typeof value !== "object") {
|
|
7954
|
+
return void 0;
|
|
7701
7955
|
}
|
|
7702
|
-
|
|
7956
|
+
const record = value;
|
|
7957
|
+
const info = normalizeUnknownRecord(record.info);
|
|
7958
|
+
const metadata = normalizeUnknownRecord(record.metadata);
|
|
7959
|
+
const infoMetadata = normalizeUnknownRecord(info == null ? void 0 : info.metadata);
|
|
7960
|
+
const candidates = [
|
|
7961
|
+
record.model,
|
|
7962
|
+
record.model_name,
|
|
7963
|
+
info == null ? void 0 : info.model,
|
|
7964
|
+
info == null ? void 0 : info.model_name,
|
|
7965
|
+
infoMetadata == null ? void 0 : infoMetadata.model,
|
|
7966
|
+
metadata == null ? void 0 : metadata.model
|
|
7967
|
+
];
|
|
7968
|
+
for (const candidate of candidates) {
|
|
7969
|
+
if (typeof candidate === "string" && candidate.trim() !== "") {
|
|
7970
|
+
return candidate.trim();
|
|
7971
|
+
}
|
|
7972
|
+
}
|
|
7973
|
+
return void 0;
|
|
7703
7974
|
}
|
|
7704
|
-
function
|
|
7975
|
+
function extractClaudeProjectFromPath(jsonlPath) {
|
|
7976
|
+
var _a;
|
|
7977
|
+
const normalizedPath = jsonlPath.replace(/[/\\]/g, sep);
|
|
7978
|
+
const segments = normalizedPath.split(sep);
|
|
7979
|
+
const projectsIndex = segments.findIndex((segment) => segment === "projects");
|
|
7980
|
+
if (projectsIndex === -1 || projectsIndex + 1 >= segments.length) {
|
|
7981
|
+
return "unknown";
|
|
7982
|
+
}
|
|
7983
|
+
return ((_a = segments[projectsIndex + 1]) == null ? void 0 : _a.trim()) || "unknown";
|
|
7984
|
+
}
|
|
7985
|
+
function decodeClaudeProjectPath(projectPath) {
|
|
7986
|
+
var _a;
|
|
7987
|
+
const normalized = projectPath.replace(/^-/, "").replace(/-/g, "/");
|
|
7988
|
+
const parts = normalized.split("/").filter(Boolean);
|
|
7989
|
+
return (_a = parts.at(-1)) != null ? _a : projectPath;
|
|
7990
|
+
}
|
|
7991
|
+
function getClaudeLookupCandidates(model) {
|
|
7992
|
+
var _a;
|
|
7705
7993
|
const normalizedModel = model.trim();
|
|
7994
|
+
const withoutFastSuffix = normalizedModel.replace(/-fast$/u, "");
|
|
7995
|
+
const baseModel = (_a = withoutFastSuffix.split("/").at(-1)) != null ? _a : withoutFastSuffix;
|
|
7996
|
+
const normalizedBaseModel = baseModel.replace(/[.@]/gu, "-");
|
|
7997
|
+
const baseModelWithoutDate = normalizedBaseModel.replace(/-\d{8}$/u, "");
|
|
7706
7998
|
return [
|
|
7707
7999
|
normalizedModel,
|
|
7708
|
-
|
|
7709
|
-
|
|
7710
|
-
normalizedModel
|
|
8000
|
+
withoutFastSuffix,
|
|
8001
|
+
withoutFastSuffix.replace(/^anthropic\//u, ""),
|
|
8002
|
+
`anthropic/${normalizedModel}`,
|
|
8003
|
+
baseModel,
|
|
8004
|
+
normalizedBaseModel,
|
|
8005
|
+
baseModelWithoutDate,
|
|
8006
|
+
`anthropic/${baseModelWithoutDate}`,
|
|
8007
|
+
baseModelWithoutDate.replace(/^claude-3-5-/u, "claude-"),
|
|
8008
|
+
baseModelWithoutDate.replace(/^claude-3-7-/u, "claude-")
|
|
8009
|
+
];
|
|
8010
|
+
}
|
|
8011
|
+
function getGeminiLookupCandidates(model) {
|
|
8012
|
+
const normalizedModel = model.trim();
|
|
8013
|
+
return [
|
|
8014
|
+
normalizedModel,
|
|
8015
|
+
normalizedModel.replace(/^gemini\//u, ""),
|
|
8016
|
+
normalizedModel.replace(/^google\//u, ""),
|
|
8017
|
+
`gemini/${normalizedModel}`,
|
|
8018
|
+
`google/${normalizedModel}`
|
|
7711
8019
|
];
|
|
7712
8020
|
}
|
|
7713
|
-
function
|
|
7714
|
-
const
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
|
|
7718
|
-
|
|
7719
|
-
|
|
7720
|
-
|
|
8021
|
+
function isOpenRouterFreeModel(model) {
|
|
8022
|
+
const normalizedModel = model.trim().toLowerCase();
|
|
8023
|
+
return normalizedModel === "openrouter/free" || normalizedModel.startsWith("openrouter/") && normalizedModel.endsWith(":free");
|
|
8024
|
+
}
|
|
8025
|
+
function getGeminiProjectRoot(filePath) {
|
|
8026
|
+
const projectDir = dirname$1(dirname$1(filePath));
|
|
8027
|
+
const projectRootFile = `${projectDir}/.project_root`;
|
|
8028
|
+
if (!existsSync(projectRootFile)) {
|
|
8029
|
+
return "";
|
|
8030
|
+
}
|
|
8031
|
+
try {
|
|
8032
|
+
return readFileSync(projectRootFile, "utf8").trim();
|
|
8033
|
+
} catch {
|
|
8034
|
+
return "";
|
|
8035
|
+
}
|
|
8036
|
+
}
|
|
8037
|
+
function getGeminiProjectKeyFromPath(filePath) {
|
|
8038
|
+
var _a;
|
|
8039
|
+
const normalizedPath = filePath.replace(/[/\\]/g, sep);
|
|
8040
|
+
const segments = normalizedPath.split(sep);
|
|
8041
|
+
const tmpIndex = segments.findIndex((segment) => segment === "tmp");
|
|
8042
|
+
if (tmpIndex === -1 || tmpIndex + 1 >= segments.length) {
|
|
8043
|
+
return "unknown";
|
|
8044
|
+
}
|
|
8045
|
+
return ((_a = segments[tmpIndex + 1]) == null ? void 0 : _a.trim()) || "unknown";
|
|
8046
|
+
}
|
|
8047
|
+
function getRepositoryNameFromProjectRoot(projectRoot) {
|
|
8048
|
+
if (!projectRoot) {
|
|
8049
|
+
return "";
|
|
8050
|
+
}
|
|
8051
|
+
const gitConfigPath = `${projectRoot}/.git/config`;
|
|
8052
|
+
if (!existsSync(gitConfigPath)) {
|
|
8053
|
+
return "";
|
|
8054
|
+
}
|
|
8055
|
+
try {
|
|
8056
|
+
return normalizeRepositoryUrl(getOriginUrlFromGitConfig(readFileSync(gitConfigPath, "utf8")));
|
|
8057
|
+
} catch {
|
|
8058
|
+
return "";
|
|
7721
8059
|
}
|
|
7722
|
-
return expanded;
|
|
7723
8060
|
}
|
|
7724
|
-
function
|
|
7725
|
-
|
|
7726
|
-
|
|
7727
|
-
|
|
8061
|
+
function getOriginUrlFromGitConfig(config) {
|
|
8062
|
+
let isOriginBlock = false;
|
|
8063
|
+
for (const rawLine of config.split("\n")) {
|
|
8064
|
+
const line = rawLine.trim();
|
|
8065
|
+
if (line.startsWith("[")) {
|
|
8066
|
+
isOriginBlock = line === '[remote "origin"]';
|
|
7728
8067
|
continue;
|
|
7729
8068
|
}
|
|
7730
|
-
|
|
8069
|
+
if (!isOriginBlock || !line.startsWith("url =")) {
|
|
8070
|
+
continue;
|
|
8071
|
+
}
|
|
8072
|
+
return line.slice("url =".length).trim();
|
|
7731
8073
|
}
|
|
7732
|
-
return
|
|
8074
|
+
return "";
|
|
7733
8075
|
}
|
|
7734
|
-
function
|
|
7735
|
-
|
|
7736
|
-
|
|
7737
|
-
const pricing = fallbackPricingTable[candidate];
|
|
7738
|
-
if (pricing) {
|
|
7739
|
-
const fastMultiplier = (_a = pricing.fastMultiplier) != null ? _a : resolveFastMultiplierOverride(candidates);
|
|
7740
|
-
return fastMultiplier == null ? pricing : { ...pricing, fastMultiplier };
|
|
7741
|
-
}
|
|
8076
|
+
function extractGeminiMessageText(content) {
|
|
8077
|
+
if (typeof content === "string") {
|
|
8078
|
+
return content;
|
|
7742
8079
|
}
|
|
7743
|
-
|
|
8080
|
+
if (!Array.isArray(content)) {
|
|
8081
|
+
return "";
|
|
8082
|
+
}
|
|
8083
|
+
return content.map((item) => {
|
|
8084
|
+
var _a;
|
|
8085
|
+
return (_a = item.text) == null ? void 0 : _a.trim();
|
|
8086
|
+
}).filter(Boolean).join("\n");
|
|
7744
8087
|
}
|
|
7745
|
-
function
|
|
7746
|
-
|
|
7747
|
-
|
|
8088
|
+
function addEventToAggregateGroup(group, event, options) {
|
|
8089
|
+
group.inputTokens += event.inputTokens;
|
|
8090
|
+
group.cachedInputTokens += event.cachedInputTokens;
|
|
8091
|
+
group.outputTokens += event.outputTokens;
|
|
8092
|
+
group.reasoningOutputTokens += event.reasoningOutputTokens;
|
|
8093
|
+
group.totalTokens += event.totalTokens;
|
|
8094
|
+
group.costUSD += getEventCostUSD(event, options);
|
|
8095
|
+
group.models = shouldIncludeModel(event, options) ? uniqueItems([...group.models, event.model]) : group.models;
|
|
8096
|
+
group.projects = uniqueItems([...group.projects, event.project]);
|
|
7748
8097
|
}
|
|
7749
|
-
function
|
|
7750
|
-
var _a, _b, _c
|
|
7751
|
-
|
|
7752
|
-
|
|
7753
|
-
|
|
7754
|
-
|
|
8098
|
+
function getEventCostUSD(event, options) {
|
|
8099
|
+
var _a, _b, _c;
|
|
8100
|
+
return (_c = (_b = (_a = options.getCostUSD) == null ? void 0 : _a.call(options, event)) != null ? _b : event.costUSD) != null ? _c : 0;
|
|
8101
|
+
}
|
|
8102
|
+
function shouldIncludeModel(event, options) {
|
|
8103
|
+
var _a, _b;
|
|
8104
|
+
return (_b = (_a = options.includeModel) == null ? void 0 : _a.call(options, event)) != null ? _b : true;
|
|
8105
|
+
}
|
|
8106
|
+
function getCachedInputTokens(session, options) {
|
|
8107
|
+
var _a, _b;
|
|
8108
|
+
return (_b = (_a = options.getCachedInputTokens) == null ? void 0 : _a.call(options, session)) != null ? _b : getNumericProperty(session, "cachedInputTokens");
|
|
8109
|
+
}
|
|
8110
|
+
function getReasoningOutputTokens(session, options) {
|
|
8111
|
+
var _a, _b;
|
|
8112
|
+
return (_b = (_a = options.getReasoningOutputTokens) == null ? void 0 : _a.call(options, session)) != null ? _b : getNumericProperty(session, "reasoningOutputTokens");
|
|
8113
|
+
}
|
|
8114
|
+
function getNumericProperty(value, key) {
|
|
8115
|
+
const record = value;
|
|
8116
|
+
const property = record[key];
|
|
8117
|
+
return typeof property === "number" && Number.isFinite(property) ? property : 0;
|
|
8118
|
+
}
|
|
8119
|
+
function cloneDate(date) {
|
|
8120
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
8121
|
+
}
|
|
8122
|
+
|
|
8123
|
+
function toDiscoveredUsageFile(filePath, platform, cacheSignature = "") {
|
|
8124
|
+
try {
|
|
8125
|
+
const stats = statSync(filePath);
|
|
8126
|
+
return [{
|
|
8127
|
+
cacheSignature,
|
|
8128
|
+
mtimeMs: stats.mtimeMs,
|
|
8129
|
+
path: filePath,
|
|
8130
|
+
platform,
|
|
8131
|
+
size: stats.size
|
|
8132
|
+
}];
|
|
8133
|
+
} catch {
|
|
8134
|
+
return [];
|
|
8135
|
+
}
|
|
8136
|
+
}
|
|
8137
|
+
function createSessionFragment(options) {
|
|
7755
8138
|
return {
|
|
7756
|
-
|
|
7757
|
-
|
|
7758
|
-
|
|
7759
|
-
|
|
7760
|
-
|
|
7761
|
-
|
|
7762
|
-
|
|
7763
|
-
|
|
7764
|
-
outputCostPerMTokensAbove200K: pricing.output_cost_per_token_above_200k_tokens != null ? pricing.output_cost_per_token_above_200k_tokens * MILLION : void 0
|
|
8139
|
+
durationEndAt: "",
|
|
8140
|
+
interactions: [],
|
|
8141
|
+
key: getSessionLookupKey(options.repository, options.sessionId),
|
|
8142
|
+
project: options.project,
|
|
8143
|
+
repository: options.repository,
|
|
8144
|
+
sessionId: options.sessionId,
|
|
8145
|
+
startedAt: options.startedAt,
|
|
8146
|
+
threadName: options.threadName
|
|
7765
8147
|
};
|
|
7766
8148
|
}
|
|
7767
|
-
function
|
|
7768
|
-
|
|
7769
|
-
|
|
7770
|
-
|
|
7771
|
-
return multiplier;
|
|
7772
|
-
}
|
|
8149
|
+
function addFragmentInteraction(fragment, interaction) {
|
|
8150
|
+
fragment.interactions.push(interaction);
|
|
8151
|
+
if (!interaction.timestamp) {
|
|
8152
|
+
return;
|
|
7773
8153
|
}
|
|
7774
|
-
|
|
7775
|
-
|
|
7776
|
-
for (const part of normalized.split(/[/:]/u)) {
|
|
7777
|
-
for (const [base, multiplier] of Object.entries(FAST_MULTIPLIER_PREFIX_OVERRIDES)) {
|
|
7778
|
-
if (matchesModelSuffix(part, base)) {
|
|
7779
|
-
return multiplier;
|
|
7780
|
-
}
|
|
7781
|
-
}
|
|
7782
|
-
}
|
|
8154
|
+
if (!fragment.startedAt || Date.parse(interaction.timestamp) < Date.parse(fragment.startedAt)) {
|
|
8155
|
+
fragment.startedAt = interaction.timestamp;
|
|
7783
8156
|
}
|
|
7784
|
-
|
|
7785
|
-
|
|
7786
|
-
function matchesModelSuffix(part, base) {
|
|
7787
|
-
const index = part.lastIndexOf(base);
|
|
7788
|
-
if (index < 0) {
|
|
7789
|
-
return false;
|
|
8157
|
+
if (!fragment.durationEndAt || Date.parse(interaction.timestamp) > Date.parse(fragment.durationEndAt)) {
|
|
8158
|
+
fragment.durationEndAt = interaction.timestamp;
|
|
7790
8159
|
}
|
|
7791
|
-
const suffix = part.slice(index);
|
|
7792
|
-
return suffix === base || suffix[base.length] === "-";
|
|
7793
8160
|
}
|
|
7794
|
-
function
|
|
7795
|
-
return {
|
|
7796
|
-
cachedInputCostPerMTokens: 0,
|
|
7797
|
-
cacheCreationInputCostPerMTokens: 0,
|
|
7798
|
-
inputCostPerMTokens: 0,
|
|
7799
|
-
outputCostPerMTokens: 0
|
|
7800
|
-
};
|
|
8161
|
+
function getSessionLookupKey(project, sessionId) {
|
|
8162
|
+
return `${project}:${sessionId}`;
|
|
7801
8163
|
}
|
|
7802
|
-
function
|
|
7803
|
-
const
|
|
7804
|
-
if (
|
|
7805
|
-
return
|
|
8164
|
+
function normalizeRole(value) {
|
|
8165
|
+
const normalized = value.toLowerCase();
|
|
8166
|
+
if (normalized.includes("user")) {
|
|
8167
|
+
return "user";
|
|
7806
8168
|
}
|
|
7807
|
-
if (
|
|
7808
|
-
return
|
|
8169
|
+
if (normalized.includes("assistant") || normalized.includes("agent") || normalized.includes("gemini")) {
|
|
8170
|
+
return "assistant";
|
|
7809
8171
|
}
|
|
7810
|
-
|
|
8172
|
+
if (normalized.includes("system")) {
|
|
8173
|
+
return "system";
|
|
8174
|
+
}
|
|
8175
|
+
if (normalized.includes("tool")) {
|
|
8176
|
+
return "tool";
|
|
8177
|
+
}
|
|
8178
|
+
if (normalized.includes("token") || normalized.includes("usage")) {
|
|
8179
|
+
return "usage";
|
|
8180
|
+
}
|
|
8181
|
+
return "unknown";
|
|
7811
8182
|
}
|
|
7812
8183
|
|
|
7813
8184
|
const ZERO_PRICING = {
|
|
@@ -7820,12 +8191,7 @@ async function createZeroPricingResolver() {
|
|
|
7820
8191
|
return () => ZERO_PRICING;
|
|
7821
8192
|
}
|
|
7822
8193
|
function applyTotalUsageFallback(usage) {
|
|
7823
|
-
const cacheCreationTokens =
|
|
7824
|
-
const cacheReadTokens = normalizeUsageNumber(usage.cacheReadTokens);
|
|
7825
|
-
const inputTokens = normalizeUsageNumber(usage.inputTokens);
|
|
7826
|
-
const outputTokens = normalizeUsageNumber(usage.outputTokens);
|
|
7827
|
-
const totalTokens = normalizeUsageNumber(usage.totalTokens);
|
|
7828
|
-
const baseTokens = inputTokens + outputTokens + cacheCreationTokens + cacheReadTokens;
|
|
8194
|
+
const { baseTokens, cacheCreationTokens, cacheReadTokens, inputTokens, outputTokens, totalTokens } = readUsageParts(usage);
|
|
7829
8195
|
if (baseTokens === 0 && totalTokens > 0) {
|
|
7830
8196
|
return {
|
|
7831
8197
|
cacheCreationTokens,
|
|
@@ -7847,6 +8213,29 @@ function applyTotalUsageFallback(usage) {
|
|
|
7847
8213
|
reasoningOutputTokens
|
|
7848
8214
|
};
|
|
7849
8215
|
}
|
|
8216
|
+
function applyTotalUsageAsExtra(usage) {
|
|
8217
|
+
const { baseTokens, cacheCreationTokens, cacheReadTokens, inputTokens, outputTokens, totalTokens } = readUsageParts(usage);
|
|
8218
|
+
if (baseTokens === 0 && totalTokens > 0) {
|
|
8219
|
+
return {
|
|
8220
|
+
cacheCreationTokens,
|
|
8221
|
+
cacheReadTokens,
|
|
8222
|
+
inputTokens,
|
|
8223
|
+
outputTokens: totalTokens,
|
|
8224
|
+
extraTotalTokens: 0
|
|
8225
|
+
};
|
|
8226
|
+
}
|
|
8227
|
+
const extraTotalTokens = Math.max(
|
|
8228
|
+
normalizeUsageNumber(usage.extraTotalTokens),
|
|
8229
|
+
totalTokens > baseTokens ? totalTokens - baseTokens : 0
|
|
8230
|
+
);
|
|
8231
|
+
return {
|
|
8232
|
+
cacheCreationTokens,
|
|
8233
|
+
cacheReadTokens,
|
|
8234
|
+
inputTokens,
|
|
8235
|
+
outputTokens,
|
|
8236
|
+
extraTotalTokens
|
|
8237
|
+
};
|
|
8238
|
+
}
|
|
7850
8239
|
function toInteractionUsage(usage) {
|
|
7851
8240
|
var _a;
|
|
7852
8241
|
const cacheCreationTokens = normalizeUsageNumber(usage.cacheCreationTokens);
|
|
@@ -7854,13 +8243,15 @@ function toInteractionUsage(usage) {
|
|
|
7854
8243
|
const inputTokens = normalizeUsageNumber(usage.inputTokens);
|
|
7855
8244
|
const outputTokens = normalizeUsageNumber(usage.outputTokens);
|
|
7856
8245
|
const reasoningOutputTokens = normalizeUsageNumber(usage.reasoningOutputTokens);
|
|
8246
|
+
const extraTotalTokens = normalizeUsageNumber(usage.extraTotalTokens);
|
|
7857
8247
|
const toolTokens = normalizeUsageNumber(usage.toolTokens);
|
|
7858
|
-
const totalTokens = inputTokens + outputTokens + cacheCreationTokens + cacheReadTokens + reasoningOutputTokens + toolTokens;
|
|
8248
|
+
const totalTokens = inputTokens + outputTokens + cacheCreationTokens + cacheReadTokens + reasoningOutputTokens + extraTotalTokens + toolTokens;
|
|
7859
8249
|
return {
|
|
7860
8250
|
cacheCreationTokens,
|
|
7861
8251
|
cacheReadTokens,
|
|
7862
8252
|
cachedInputTokens: cacheCreationTokens + cacheReadTokens,
|
|
7863
8253
|
costUSD: (_a = usage.costUSD) != null ? _a : 0,
|
|
8254
|
+
extraTotalTokens: extraTotalTokens > 0 ? extraTotalTokens : void 0,
|
|
7864
8255
|
inputTokens,
|
|
7865
8256
|
isFallbackModel: usage.isFallbackModel,
|
|
7866
8257
|
outputTokens,
|
|
@@ -7870,15 +8261,15 @@ function toInteractionUsage(usage) {
|
|
|
7870
8261
|
};
|
|
7871
8262
|
}
|
|
7872
8263
|
function isZeroInteractionUsage(usage) {
|
|
7873
|
-
var _a;
|
|
7874
|
-
return usage.totalTokens <= 0 && usage.inputTokens <= 0 && usage.cachedInputTokens <= 0 && usage.outputTokens <= 0 && usage.reasoningOutputTokens <= 0 && ((_a = usage.
|
|
8264
|
+
var _a, _b;
|
|
8265
|
+
return usage.totalTokens <= 0 && usage.inputTokens <= 0 && usage.cachedInputTokens <= 0 && usage.outputTokens <= 0 && usage.reasoningOutputTokens <= 0 && ((_a = usage.extraTotalTokens) != null ? _a : 0) <= 0 && ((_b = usage.toolTokens) != null ? _b : 0) <= 0;
|
|
7875
8266
|
}
|
|
7876
8267
|
function calculateUsageCostFromCandidates(usage, candidates, resolvePricing, options = {}) {
|
|
7877
|
-
var _a, _b;
|
|
7878
|
-
const outputTokens = usage.outputTokens + ((_a = usage.
|
|
8268
|
+
var _a, _b, _c;
|
|
8269
|
+
const outputTokens = usage.outputTokens + (options.includeExtraTotalAsOutput === false ? 0 : (_a = usage.extraTotalTokens) != null ? _a : 0) + ((_b = usage.toolTokens) != null ? _b : 0) + (options.includeReasoningAsOutput === false ? 0 : usage.reasoningOutputTokens);
|
|
7879
8270
|
for (const candidate of uniqueItems(candidates.map((candidate2) => candidate2.trim()).filter(Boolean))) {
|
|
7880
8271
|
const costUSD = calculateUsageCostUSD({
|
|
7881
|
-
cacheCreationTokens: (
|
|
8272
|
+
cacheCreationTokens: (_c = usage.cacheCreationTokens) != null ? _c : 0,
|
|
7882
8273
|
cachedInputTokens: usage.cachedInputTokens,
|
|
7883
8274
|
inputTokens: usage.inputTokens,
|
|
7884
8275
|
outputTokens
|
|
@@ -7899,17 +8290,34 @@ function getFileModifiedAtIso(filePath) {
|
|
|
7899
8290
|
function normalizeUsageNumber(value) {
|
|
7900
8291
|
return Number.isFinite(value) && value > 0 ? Math.trunc(value) : 0;
|
|
7901
8292
|
}
|
|
8293
|
+
function readUsageParts(usage) {
|
|
8294
|
+
const cacheCreationTokens = normalizeUsageNumber(usage.cacheCreationTokens);
|
|
8295
|
+
const cacheReadTokens = normalizeUsageNumber(usage.cacheReadTokens);
|
|
8296
|
+
const inputTokens = normalizeUsageNumber(usage.inputTokens);
|
|
8297
|
+
const outputTokens = normalizeUsageNumber(usage.outputTokens);
|
|
8298
|
+
const totalTokens = normalizeUsageNumber(usage.totalTokens);
|
|
8299
|
+
return {
|
|
8300
|
+
baseTokens: inputTokens + outputTokens + cacheCreationTokens + cacheReadTokens,
|
|
8301
|
+
cacheCreationTokens,
|
|
8302
|
+
cacheReadTokens,
|
|
8303
|
+
inputTokens,
|
|
8304
|
+
outputTokens,
|
|
8305
|
+
totalTokens
|
|
8306
|
+
};
|
|
8307
|
+
}
|
|
7902
8308
|
|
|
7903
8309
|
const ampUsageAdapter = {
|
|
7904
|
-
createPricingResolver
|
|
8310
|
+
async createPricingResolver() {
|
|
8311
|
+
return createLiteLLMPricingResolver();
|
|
8312
|
+
},
|
|
7905
8313
|
async discoverFiles(config) {
|
|
7906
8314
|
const groups = await Promise.all(config.ampPaths.map((path) => glob(join(path, "threads", "**", "*.json"), {
|
|
7907
8315
|
absolute: true
|
|
7908
8316
|
}).catch(() => [])));
|
|
7909
8317
|
return groups.flat().flatMap((filePath) => toDiscoveredUsageFile(filePath, "amp"));
|
|
7910
8318
|
},
|
|
7911
|
-
parseFile(filePath) {
|
|
7912
|
-
var _a, _b
|
|
8319
|
+
parseFile(filePath, resolvePricing) {
|
|
8320
|
+
var _a, _b;
|
|
7913
8321
|
const data = parseJsonFile(filePath);
|
|
7914
8322
|
const record = normalizeUnknownRecord(data);
|
|
7915
8323
|
const sessionId = normalizeStringValue(record == null ? void 0 : record.id) || basename$1(filePath, ".json");
|
|
@@ -7938,27 +8346,32 @@ const ampUsageAdapter = {
|
|
|
7938
8346
|
const messageId = Number.isFinite(event.toMessageId) ? Number(event.toMessageId) : null;
|
|
7939
8347
|
const [cacheCreationTokens = 0, cacheReadTokens = 0] = messageId != null ? (_b = cacheTokensByMessageId.get(messageId)) != null ? _b : [0, 0] : [0, 0];
|
|
7940
8348
|
const usage = toInteractionUsage({
|
|
7941
|
-
...
|
|
8349
|
+
...applyTotalUsageAsExtra({
|
|
7942
8350
|
cacheCreationTokens,
|
|
7943
8351
|
cacheReadTokens,
|
|
7944
8352
|
inputTokens: getNumber$8(tokens.input),
|
|
7945
8353
|
outputTokens: getNumber$8(tokens.output),
|
|
7946
8354
|
totalTokens: getNumber$8(tokens.total)
|
|
7947
|
-
})
|
|
7948
|
-
costUSD: (_c = normalizeFiniteNumberOrNull(event.credits)) != null ? _c : 0
|
|
8355
|
+
})
|
|
7949
8356
|
});
|
|
7950
8357
|
if (isZeroInteractionUsage(usage)) {
|
|
7951
8358
|
continue;
|
|
7952
8359
|
}
|
|
8360
|
+
const costUSD = calculateUsageCostFromCandidates(usage, [model], resolvePricing, {
|
|
8361
|
+
includeExtraTotalAsOutput: true
|
|
8362
|
+
});
|
|
7953
8363
|
addFragmentInteraction(fragment, {
|
|
7954
8364
|
content: "",
|
|
7955
|
-
costUSD
|
|
8365
|
+
costUSD,
|
|
7956
8366
|
index,
|
|
7957
8367
|
model,
|
|
7958
8368
|
role: "usage",
|
|
7959
8369
|
timestamp,
|
|
7960
8370
|
type: "usage_ledger",
|
|
7961
|
-
usage
|
|
8371
|
+
usage: toInteractionUsage({
|
|
8372
|
+
...usage,
|
|
8373
|
+
costUSD
|
|
8374
|
+
})
|
|
7962
8375
|
});
|
|
7963
8376
|
}
|
|
7964
8377
|
return fragment.interactions.length > 0 ? [fragment] : [];
|
|
@@ -7989,7 +8402,6 @@ function getNumber$8(value) {
|
|
|
7989
8402
|
return typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.trunc(value)) : 0;
|
|
7990
8403
|
}
|
|
7991
8404
|
|
|
7992
|
-
const CLAUDE_FALLBACK_MODEL = "claude-sonnet-4-5";
|
|
7993
8405
|
const CODEX_FALLBACK_MODEL = "gpt-5";
|
|
7994
8406
|
const GEMINI_FALLBACK_MODEL = "gemini-2.5-flash";
|
|
7995
8407
|
const CLAUDE_MODEL_ALIASES = {
|
|
@@ -8052,7 +8464,6 @@ const claudeCodeUsageAdapter = {
|
|
|
8052
8464
|
async createPricingResolver() {
|
|
8053
8465
|
return createLiteLLMPricingResolver({
|
|
8054
8466
|
aliases: CLAUDE_MODEL_ALIASES,
|
|
8055
|
-
fallbackModel: CLAUDE_FALLBACK_MODEL,
|
|
8056
8467
|
getLookupCandidates: getClaudeLookupCandidates
|
|
8057
8468
|
});
|
|
8058
8469
|
},
|
|
@@ -8078,6 +8489,9 @@ const claudeCodeUsageAdapter = {
|
|
|
8078
8489
|
const fragments = /* @__PURE__ */ new Map();
|
|
8079
8490
|
for (let index = 0; index < lines.length; index += 1) {
|
|
8080
8491
|
const line = lines[index];
|
|
8492
|
+
if (!isSupportedClaudeUsageLine(line)) {
|
|
8493
|
+
continue;
|
|
8494
|
+
}
|
|
8081
8495
|
const sessionId = normalizeStringValue(line.sessionId) || fallbackSessionId;
|
|
8082
8496
|
const cwd = (_a = normalizeStringValue(line.cwd)) != null ? _a : "";
|
|
8083
8497
|
const project = getProjectName(cwd, "") || decodeClaudeProjectPath(projectPath);
|
|
@@ -8169,6 +8583,31 @@ function getInteractionRole(line, message) {
|
|
|
8169
8583
|
const role = normalizeStringValue(line.type) || normalizeStringValue(message == null ? void 0 : message.role) || normalizeStringValue(message == null ? void 0 : message.type) || "";
|
|
8170
8584
|
return normalizeRole(role);
|
|
8171
8585
|
}
|
|
8586
|
+
function isSupportedClaudeUsageLine(line) {
|
|
8587
|
+
const message = normalizeUnknownRecord(line.message);
|
|
8588
|
+
const usage = normalizeUnknownRecord(message == null ? void 0 : message.usage);
|
|
8589
|
+
if (hasUnsupportedClaudeNullField(line, message, usage)) {
|
|
8590
|
+
return false;
|
|
8591
|
+
}
|
|
8592
|
+
const version = normalizeStringValue(line.version);
|
|
8593
|
+
if (version && !/^\d+\.\d+\.\d+/u.test(version)) {
|
|
8594
|
+
return false;
|
|
8595
|
+
}
|
|
8596
|
+
return !hasEmptyClaudeField(line, message);
|
|
8597
|
+
}
|
|
8598
|
+
function hasUnsupportedClaudeNullField(line, message, usage) {
|
|
8599
|
+
return line.cwd === null || line.costUSD === null || line.version === null || line.sessionId === null || line.requestId === null || line.isApiErrorMessage === null || (message == null ? void 0 : message.id) === null || (message == null ? void 0 : message.model) === null || (usage == null ? void 0 : usage.speed) === null || (usage == null ? void 0 : usage.cache_read_input_tokens) === null || (usage == null ? void 0 : usage.cache_creation_input_tokens) === null;
|
|
8600
|
+
}
|
|
8601
|
+
function hasEmptyClaudeField(line, message) {
|
|
8602
|
+
const candidates = [
|
|
8603
|
+
line.sessionId,
|
|
8604
|
+
line.requestId,
|
|
8605
|
+
line.version,
|
|
8606
|
+
message == null ? void 0 : message.id,
|
|
8607
|
+
message == null ? void 0 : message.model
|
|
8608
|
+
];
|
|
8609
|
+
return candidates.some((value) => typeof value === "string" && value.trim() === "");
|
|
8610
|
+
}
|
|
8172
8611
|
|
|
8173
8612
|
const CODEBUFF_DEFAULT_MODEL = "codebuff-unknown";
|
|
8174
8613
|
const codebuffUsageAdapter = {
|
|
@@ -8209,41 +8648,38 @@ const codebuffUsageAdapter = {
|
|
|
8209
8648
|
}
|
|
8210
8649
|
const model = extracted.model || CODEBUFF_DEFAULT_MODEL;
|
|
8211
8650
|
const usage = toInteractionUsage({
|
|
8212
|
-
...
|
|
8651
|
+
...applyTotalUsageAsExtra({
|
|
8213
8652
|
cacheCreationTokens: extracted.cacheCreationTokens,
|
|
8214
8653
|
cacheReadTokens: extracted.cacheReadTokens,
|
|
8654
|
+
extraTotalTokens: extracted.extraTotalTokens,
|
|
8215
8655
|
inputTokens: extracted.inputTokens,
|
|
8216
8656
|
outputTokens: extracted.outputTokens,
|
|
8217
8657
|
totalTokens: extracted.totalTokens
|
|
8218
|
-
})
|
|
8219
|
-
costUSD: extracted.credits > 0 ? extracted.credits : calculateUsageCostFromCandidates(
|
|
8220
|
-
toInteractionUsage({
|
|
8221
|
-
...applyTotalUsageFallback({
|
|
8222
|
-
cacheCreationTokens: extracted.cacheCreationTokens,
|
|
8223
|
-
cacheReadTokens: extracted.cacheReadTokens,
|
|
8224
|
-
inputTokens: extracted.inputTokens,
|
|
8225
|
-
outputTokens: extracted.outputTokens,
|
|
8226
|
-
totalTokens: extracted.totalTokens
|
|
8227
|
-
})
|
|
8228
|
-
}),
|
|
8229
|
-
getCodebuffCandidates(model, inferCodebuffProvider(model)),
|
|
8230
|
-
resolvePricing
|
|
8231
|
-
)
|
|
8658
|
+
})
|
|
8232
8659
|
});
|
|
8233
8660
|
if (isZeroInteractionUsage(usage)) {
|
|
8234
8661
|
continue;
|
|
8235
8662
|
}
|
|
8663
|
+
const costUSD = calculateUsageCostFromCandidates(
|
|
8664
|
+
usage,
|
|
8665
|
+
getCodebuffCandidates(model, inferCodebuffProvider(model)),
|
|
8666
|
+
resolvePricing,
|
|
8667
|
+
{ includeExtraTotalAsOutput: true, includeReasoningAsOutput: false }
|
|
8668
|
+
);
|
|
8236
8669
|
const timestamp = (_a = getCodebuffMessageTimestamp(message)) != null ? _a : fallbackTimestamp;
|
|
8237
8670
|
addFragmentInteraction(fragment, {
|
|
8238
8671
|
content: "",
|
|
8239
|
-
costUSD
|
|
8672
|
+
costUSD,
|
|
8240
8673
|
dedupeKey: getCodebuffDedupeKey(message, sessionId, timestamp != null ? timestamp : "", model, usage, index),
|
|
8241
8674
|
index,
|
|
8242
8675
|
model,
|
|
8243
8676
|
role: "assistant",
|
|
8244
8677
|
timestamp,
|
|
8245
8678
|
type: normalizeStringValue(message.variant) || normalizeStringValue(message.role) || "assistant",
|
|
8246
|
-
usage
|
|
8679
|
+
usage: toInteractionUsage({
|
|
8680
|
+
...usage,
|
|
8681
|
+
costUSD
|
|
8682
|
+
})
|
|
8247
8683
|
});
|
|
8248
8684
|
}
|
|
8249
8685
|
return fragment.interactions.length > 0 ? [fragment] : [];
|
|
@@ -8314,7 +8750,7 @@ function parseCodebuffUsageRecord(value) {
|
|
|
8314
8750
|
if (!record) {
|
|
8315
8751
|
return null;
|
|
8316
8752
|
}
|
|
8317
|
-
const raw =
|
|
8753
|
+
const raw = applyTotalUsageAsExtra({
|
|
8318
8754
|
cacheCreationTokens: pickUsageNumber(record, ["cacheCreationInputTokens", "cache_creation_input_tokens", "cacheCreationTokens", "cache_creation_tokens", "cachedTokensCreated", "cached_tokens_created"]),
|
|
8319
8755
|
cacheReadTokens: Math.max(
|
|
8320
8756
|
pickUsageNumber(record, ["cacheReadInputTokens", "cache_read_input_tokens"]),
|
|
@@ -8329,10 +8765,11 @@ function parseCodebuffUsageRecord(value) {
|
|
|
8329
8765
|
cacheCreationTokens: raw.cacheCreationTokens,
|
|
8330
8766
|
cacheReadTokens: raw.cacheReadTokens,
|
|
8331
8767
|
credits: getFiniteNumber(record.credits),
|
|
8768
|
+
extraTotalTokens: raw.extraTotalTokens,
|
|
8332
8769
|
inputTokens: raw.inputTokens,
|
|
8333
8770
|
model: (_a = normalizeStringValue(record.model)) != null ? _a : null,
|
|
8334
8771
|
outputTokens: raw.outputTokens,
|
|
8335
|
-
totalTokens: raw.inputTokens + raw.outputTokens + raw.cacheCreationTokens + raw.cacheReadTokens + raw.
|
|
8772
|
+
totalTokens: raw.inputTokens + raw.outputTokens + raw.cacheCreationTokens + raw.cacheReadTokens + raw.extraTotalTokens
|
|
8336
8773
|
};
|
|
8337
8774
|
}
|
|
8338
8775
|
function emptyCodebuffUsage() {
|
|
@@ -8340,6 +8777,7 @@ function emptyCodebuffUsage() {
|
|
|
8340
8777
|
cacheCreationTokens: 0,
|
|
8341
8778
|
cacheReadTokens: 0,
|
|
8342
8779
|
credits: 0,
|
|
8780
|
+
extraTotalTokens: 0,
|
|
8343
8781
|
inputTokens: 0,
|
|
8344
8782
|
model: null,
|
|
8345
8783
|
outputTokens: 0,
|
|
@@ -8362,6 +8800,9 @@ function mergeCodebuffUsage(target, fallback) {
|
|
|
8362
8800
|
if (target.cacheReadTokens === 0) {
|
|
8363
8801
|
target.cacheReadTokens = fallback.cacheReadTokens;
|
|
8364
8802
|
}
|
|
8803
|
+
if (target.extraTotalTokens === 0) {
|
|
8804
|
+
target.extraTotalTokens = fallback.extraTotalTokens;
|
|
8805
|
+
}
|
|
8365
8806
|
if (target.totalTokens === 0) {
|
|
8366
8807
|
target.totalTokens = fallback.totalTokens;
|
|
8367
8808
|
}
|
|
@@ -8373,7 +8814,7 @@ function mergeCodebuffUsage(target, fallback) {
|
|
|
8373
8814
|
}
|
|
8374
8815
|
}
|
|
8375
8816
|
function hasCodebuffSignal(usage) {
|
|
8376
|
-
return usage.inputTokens > 0 || usage.outputTokens > 0 || usage.cacheCreationTokens > 0 || usage.cacheReadTokens > 0 || usage.totalTokens > 0 || usage.credits > 0;
|
|
8817
|
+
return usage.inputTokens > 0 || usage.outputTokens > 0 || usage.cacheCreationTokens > 0 || usage.cacheReadTokens > 0 || usage.extraTotalTokens > 0 || usage.totalTokens > 0 || usage.credits > 0;
|
|
8377
8818
|
}
|
|
8378
8819
|
function getCodebuffMessageTimestamp(message) {
|
|
8379
8820
|
var _a;
|
|
@@ -8413,6 +8854,7 @@ function getCodebuffCandidates(model, provider) {
|
|
|
8413
8854
|
return provider !== "unknown" && !model.startsWith(`${provider}/`) ? [model, `${provider}/${model}`] : [model];
|
|
8414
8855
|
}
|
|
8415
8856
|
function getCodebuffDedupeKey(message, sessionId, timestamp, model, usage, index) {
|
|
8857
|
+
var _a, _b, _c;
|
|
8416
8858
|
const messageId = normalizeStringValue(message.id);
|
|
8417
8859
|
if (messageId) {
|
|
8418
8860
|
return `codebuff:${sessionId}:${messageId}`;
|
|
@@ -8425,8 +8867,9 @@ function getCodebuffDedupeKey(message, sessionId, timestamp, model, usage, index
|
|
|
8425
8867
|
String(index),
|
|
8426
8868
|
String(usage.inputTokens),
|
|
8427
8869
|
String(usage.outputTokens),
|
|
8428
|
-
String(usage.
|
|
8429
|
-
String(usage.
|
|
8870
|
+
String((_a = usage.cacheReadTokens) != null ? _a : 0),
|
|
8871
|
+
String((_b = usage.cacheCreationTokens) != null ? _b : 0),
|
|
8872
|
+
String((_c = usage.extraTotalTokens) != null ? _c : 0)
|
|
8430
8873
|
].join(":");
|
|
8431
8874
|
}
|
|
8432
8875
|
function pickUsageNumber(record, keys) {
|
|
@@ -8446,7 +8889,6 @@ const codexUsageAdapter = {
|
|
|
8446
8889
|
async createPricingResolver() {
|
|
8447
8890
|
return createLiteLLMPricingResolver({
|
|
8448
8891
|
aliases: CODEX_MODEL_ALIASES,
|
|
8449
|
-
fallbackModel: CODEX_FALLBACK_MODEL,
|
|
8450
8892
|
isZeroCostModel: isOpenRouterFreeModel
|
|
8451
8893
|
});
|
|
8452
8894
|
},
|
|
@@ -8463,13 +8905,13 @@ const codexUsageAdapter = {
|
|
|
8463
8905
|
return files.flatMap((filePath) => toDiscoveredUsageFile(filePath, "codex", cacheSignature));
|
|
8464
8906
|
},
|
|
8465
8907
|
parseFile(filePath, resolvePricing, file) {
|
|
8466
|
-
var _a, _b, _c, _d, _e, _f, _g, _h
|
|
8908
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
8467
8909
|
const lines = parseJsonlFile(filePath);
|
|
8468
|
-
const sessionMeta = (_a = lines.find((line) => line.type === "session_meta")) == null ? void 0 : _a.payload;
|
|
8910
|
+
const sessionMeta = normalizeUnknownRecord((_a = lines.find((line) => normalizeStringValue(line.type) === "session_meta")) == null ? void 0 : _a.payload);
|
|
8469
8911
|
const sessionId = getSessionId(filePath, normalizeStringValue(sessionMeta == null ? void 0 : sessionMeta.id));
|
|
8470
|
-
const startedAt = (_c =
|
|
8912
|
+
const startedAt = (_c = (_b = getCodexTimestamp(sessionMeta)) != null ? _b : lines.map((line) => getCodexTimestamp(line)).find(Boolean)) != null ? _c : getFileModifiedAtIso(filePath);
|
|
8471
8913
|
const project = getProjectName((_d = normalizeStringValue(sessionMeta == null ? void 0 : sessionMeta.cwd)) != null ? _d : "");
|
|
8472
|
-
const repository = normalizeRepositoryUrl((_e = sessionMeta == null ? void 0 : sessionMeta.git) == null ? void 0 : _e.repository_url) || `local/${project}`;
|
|
8914
|
+
const repository = normalizeRepositoryUrl(normalizeStringValue((_e = normalizeUnknownRecord(sessionMeta == null ? void 0 : sessionMeta.git)) == null ? void 0 : _e.repository_url)) || `local/${project}`;
|
|
8473
8915
|
const fragment = createSessionFragment({
|
|
8474
8916
|
project,
|
|
8475
8917
|
repository,
|
|
@@ -8483,21 +8925,22 @@ const codexUsageAdapter = {
|
|
|
8483
8925
|
let currentModelIsFallback = false;
|
|
8484
8926
|
for (let index = 0; index < lines.length; index += 1) {
|
|
8485
8927
|
const line = lines[index];
|
|
8486
|
-
|
|
8487
|
-
|
|
8928
|
+
const payload = normalizeUnknownRecord(line.payload);
|
|
8929
|
+
if (normalizeStringValue(line.type) === "turn_context") {
|
|
8930
|
+
const contextModel = extractModelName(payload);
|
|
8488
8931
|
if (contextModel) {
|
|
8489
8932
|
currentModel = contextModel;
|
|
8490
8933
|
currentModelIsFallback = false;
|
|
8491
8934
|
}
|
|
8492
8935
|
}
|
|
8493
|
-
const timestamp = (
|
|
8494
|
-
const extractedModel =
|
|
8936
|
+
const timestamp = (_f = getCodexTimestamp(line)) != null ? _f : getFileModifiedAtIso(filePath);
|
|
8937
|
+
const extractedModel = extractCodexModel(line);
|
|
8495
8938
|
if (extractedModel) {
|
|
8496
8939
|
currentModel = extractedModel;
|
|
8497
8940
|
currentModelIsFallback = false;
|
|
8498
8941
|
}
|
|
8499
8942
|
const rawUsage = getCodexRawUsage(line, previousTotals);
|
|
8500
|
-
const totalUsage = normalizeRawUsage((
|
|
8943
|
+
const totalUsage = normalizeRawUsage((_g = normalizeUnknownRecord(payload == null ? void 0 : payload.info)) == null ? void 0 : _g.total_token_usage);
|
|
8501
8944
|
if (totalUsage) {
|
|
8502
8945
|
previousTotals = totalUsage;
|
|
8503
8946
|
}
|
|
@@ -8514,12 +8957,13 @@ const codexUsageAdapter = {
|
|
|
8514
8957
|
const usage = rawUsage ? getCodexInteractionUsage(rawUsage, model != null ? model : CODEX_FALLBACK_MODEL, resolvePricing, speed) : null;
|
|
8515
8958
|
addFragmentInteraction(fragment, {
|
|
8516
8959
|
content: extractCodexContent(line),
|
|
8517
|
-
costUSD: (
|
|
8960
|
+
costUSD: (_h = usage == null ? void 0 : usage.costUSD) != null ? _h : 0,
|
|
8961
|
+
dedupeKey: usage && timestamp ? getCodexDedupeKey(timestamp, model != null ? model : CODEX_FALLBACK_MODEL, usage) : null,
|
|
8518
8962
|
index,
|
|
8519
8963
|
model: model != null ? model : null,
|
|
8520
|
-
role: getCodexRole(line),
|
|
8964
|
+
role: getCodexRole(line, rawUsage !== null),
|
|
8521
8965
|
timestamp,
|
|
8522
|
-
type: (
|
|
8966
|
+
type: normalizeStringValue(payload == null ? void 0 : payload.type) || normalizeStringValue(line.type) || "event",
|
|
8523
8967
|
usage: usage ? { ...usage, isFallbackModel } : null
|
|
8524
8968
|
});
|
|
8525
8969
|
}
|
|
@@ -8533,14 +8977,14 @@ const codexUsageAdapter = {
|
|
|
8533
8977
|
}
|
|
8534
8978
|
};
|
|
8535
8979
|
function getCodexRawUsage(line, previousTotals) {
|
|
8536
|
-
|
|
8537
|
-
if (line.type
|
|
8538
|
-
|
|
8980
|
+
const payload = normalizeUnknownRecord(line.payload);
|
|
8981
|
+
if (normalizeStringValue(line.type) === "event_msg" && normalizeStringValue(payload == null ? void 0 : payload.type) === "token_count") {
|
|
8982
|
+
const info = normalizeUnknownRecord(payload == null ? void 0 : payload.info);
|
|
8983
|
+
const lastUsage = normalizeRawUsage(info == null ? void 0 : info.last_token_usage);
|
|
8984
|
+
const totalUsage = normalizeRawUsage(info == null ? void 0 : info.total_token_usage);
|
|
8985
|
+
return lastUsage != null ? lastUsage : totalUsage ? subtractRawUsage(totalUsage, previousTotals) : null;
|
|
8539
8986
|
}
|
|
8540
|
-
|
|
8541
|
-
const lastUsage = normalizeRawUsage(info == null ? void 0 : info.last_token_usage);
|
|
8542
|
-
const totalUsage = normalizeRawUsage(info == null ? void 0 : info.total_token_usage);
|
|
8543
|
-
return lastUsage != null ? lastUsage : totalUsage ? subtractRawUsage(totalUsage, previousTotals) : null;
|
|
8987
|
+
return getHeadlessCodexRawUsage(line);
|
|
8544
8988
|
}
|
|
8545
8989
|
function getCodexInteractionUsage(rawUsage, model, resolvePricing, speed) {
|
|
8546
8990
|
const usage = convertCodexRawUsage(rawUsage);
|
|
@@ -8622,20 +9066,20 @@ function toCodexSpeed(value) {
|
|
|
8622
9066
|
return normalized === "priority" || normalized === "fast" ? "fast" : "standard";
|
|
8623
9067
|
}
|
|
8624
9068
|
function extractCodexContent(line) {
|
|
8625
|
-
const payload = line.payload;
|
|
8626
|
-
|
|
8627
|
-
|
|
8628
|
-
|
|
8629
|
-
const message = payload.message;
|
|
9069
|
+
const payload = normalizeUnknownRecord(line.payload);
|
|
9070
|
+
const data = normalizeUnknownRecord(line.data);
|
|
9071
|
+
const result = normalizeUnknownRecord(line.result);
|
|
9072
|
+
const response = normalizeUnknownRecord(line.response);
|
|
9073
|
+
const message = payload == null ? void 0 : payload.message;
|
|
8630
9074
|
if (typeof message === "string") {
|
|
8631
9075
|
return message;
|
|
8632
9076
|
}
|
|
8633
|
-
return normalizeStringValue(payload.text) || normalizeStringValue(payload.output) || normalizeStringValue(payload.content) || "";
|
|
9077
|
+
return normalizeStringValue(payload == null ? void 0 : payload.text) || normalizeStringValue(payload == null ? void 0 : payload.output) || normalizeStringValue(payload == null ? void 0 : payload.content) || normalizeStringValue(line.content) || normalizeStringValue(data == null ? void 0 : data.content) || normalizeStringValue(result == null ? void 0 : result.content) || normalizeStringValue(response == null ? void 0 : response.content) || "";
|
|
8634
9078
|
}
|
|
8635
|
-
function getCodexRole(line) {
|
|
8636
|
-
var _a
|
|
8637
|
-
const type = (
|
|
8638
|
-
if (type === "token_count") {
|
|
9079
|
+
function getCodexRole(line, hasUsage) {
|
|
9080
|
+
var _a;
|
|
9081
|
+
const type = normalizeStringValue((_a = normalizeUnknownRecord(line.payload)) == null ? void 0 : _a.type) || normalizeStringValue(line.type) || "";
|
|
9082
|
+
if (type === "token_count" || hasUsage) {
|
|
8639
9083
|
return "usage";
|
|
8640
9084
|
}
|
|
8641
9085
|
return normalizeRole(type);
|
|
@@ -8643,6 +9087,102 @@ function getCodexRole(line) {
|
|
|
8643
9087
|
function getSessionId(filePath, sessionMetaId) {
|
|
8644
9088
|
return (sessionMetaId == null ? void 0 : sessionMetaId.trim()) || basename$1(filePath, ".jsonl");
|
|
8645
9089
|
}
|
|
9090
|
+
function getHeadlessCodexRawUsage(line) {
|
|
9091
|
+
const usage = getHeadlessUsageRecord(line);
|
|
9092
|
+
if (!usage) {
|
|
9093
|
+
return null;
|
|
9094
|
+
}
|
|
9095
|
+
const normalizedUsage = readHeadlessCodexUsage(usage);
|
|
9096
|
+
return normalizedUsage && normalizedUsage.total_tokens > 0 ? normalizedUsage : normalizedUsage && (normalizedUsage.input_tokens > 0 || normalizedUsage.cached_input_tokens > 0 || normalizedUsage.output_tokens > 0 || normalizedUsage.reasoning_output_tokens > 0) ? normalizedUsage : null;
|
|
9097
|
+
}
|
|
9098
|
+
function getHeadlessUsageRecord(line) {
|
|
9099
|
+
var _a, _b, _c, _d;
|
|
9100
|
+
const candidates = [
|
|
9101
|
+
normalizeUnknownRecord(line.usage),
|
|
9102
|
+
normalizeUnknownRecord((_a = normalizeUnknownRecord(line.data)) == null ? void 0 : _a.usage),
|
|
9103
|
+
normalizeUnknownRecord((_b = normalizeUnknownRecord(line.result)) == null ? void 0 : _b.usage),
|
|
9104
|
+
normalizeUnknownRecord((_c = normalizeUnknownRecord(line.response)) == null ? void 0 : _c.usage)
|
|
9105
|
+
];
|
|
9106
|
+
return (_d = candidates.find(Boolean)) != null ? _d : null;
|
|
9107
|
+
}
|
|
9108
|
+
function readHeadlessCodexUsage(usage) {
|
|
9109
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
9110
|
+
const hasStandardUsageField = [
|
|
9111
|
+
"input_tokens",
|
|
9112
|
+
"cached_input_tokens",
|
|
9113
|
+
"cache_read_input_tokens",
|
|
9114
|
+
"output_tokens",
|
|
9115
|
+
"reasoning_output_tokens",
|
|
9116
|
+
"total_tokens"
|
|
9117
|
+
].some((key) => usage[key] !== void 0 && usage[key] !== null);
|
|
9118
|
+
if (hasStandardUsageField) {
|
|
9119
|
+
const normalized = normalizeRawUsage(usage);
|
|
9120
|
+
if (normalized) {
|
|
9121
|
+
return normalized;
|
|
9122
|
+
}
|
|
9123
|
+
}
|
|
9124
|
+
const inputTokens = Math.max(
|
|
9125
|
+
0,
|
|
9126
|
+
Math.trunc((_b = (_a = normalizeFiniteNumberOrNull(usage.input_tokens)) != null ? _a : normalizeFiniteNumberOrNull(usage.prompt_tokens)) != null ? _b : 0)
|
|
9127
|
+
);
|
|
9128
|
+
const cachedInputTokens = Math.max(
|
|
9129
|
+
0,
|
|
9130
|
+
Math.trunc((_d = (_c = normalizeFiniteNumberOrNull(usage.cached_input_tokens)) != null ? _c : normalizeFiniteNumberOrNull(usage.cached_tokens)) != null ? _d : 0)
|
|
9131
|
+
);
|
|
9132
|
+
const outputTokens = Math.max(
|
|
9133
|
+
0,
|
|
9134
|
+
Math.trunc((_f = (_e = normalizeFiniteNumberOrNull(usage.output_tokens)) != null ? _e : normalizeFiniteNumberOrNull(usage.completion_tokens)) != null ? _f : 0)
|
|
9135
|
+
);
|
|
9136
|
+
const reasoningOutputTokens = Math.max(0, Math.trunc((_g = normalizeFiniteNumberOrNull(usage.reasoning_output_tokens)) != null ? _g : 0));
|
|
9137
|
+
const totalTokens = Math.max(0, Math.trunc((_h = normalizeFiniteNumberOrNull(usage.total_tokens)) != null ? _h : 0));
|
|
9138
|
+
return {
|
|
9139
|
+
cached_input_tokens: cachedInputTokens,
|
|
9140
|
+
input_tokens: inputTokens,
|
|
9141
|
+
output_tokens: outputTokens,
|
|
9142
|
+
reasoning_output_tokens: reasoningOutputTokens,
|
|
9143
|
+
total_tokens: totalTokens > 0 ? totalTokens : inputTokens + outputTokens + reasoningOutputTokens
|
|
9144
|
+
};
|
|
9145
|
+
}
|
|
9146
|
+
function extractCodexModel(line) {
|
|
9147
|
+
const payload = normalizeUnknownRecord(line.payload);
|
|
9148
|
+
const candidates = [
|
|
9149
|
+
payload,
|
|
9150
|
+
line,
|
|
9151
|
+
normalizeUnknownRecord(line.data),
|
|
9152
|
+
normalizeUnknownRecord(line.result),
|
|
9153
|
+
normalizeUnknownRecord(line.response)
|
|
9154
|
+
];
|
|
9155
|
+
for (const candidate of candidates) {
|
|
9156
|
+
const model = extractModelName(candidate);
|
|
9157
|
+
if (model) {
|
|
9158
|
+
return model;
|
|
9159
|
+
}
|
|
9160
|
+
}
|
|
9161
|
+
return void 0;
|
|
9162
|
+
}
|
|
9163
|
+
function getCodexTimestamp(line) {
|
|
9164
|
+
if (!line) {
|
|
9165
|
+
return null;
|
|
9166
|
+
}
|
|
9167
|
+
const data = normalizeUnknownRecord(line.data);
|
|
9168
|
+
const result = normalizeUnknownRecord(line.result);
|
|
9169
|
+
const response = normalizeUnknownRecord(line.response);
|
|
9170
|
+
const payload = normalizeUnknownRecord(line.payload);
|
|
9171
|
+
return toIsoString(line.timestamp) || toIsoString(line.created_at) || toIsoString(line.createdAt) || toIsoString(payload == null ? void 0 : payload.timestamp) || toIsoString(data == null ? void 0 : data.timestamp) || toIsoString(data == null ? void 0 : data.created_at) || toIsoString(data == null ? void 0 : data.createdAt) || toIsoString(result == null ? void 0 : result.timestamp) || toIsoString(result == null ? void 0 : result.created_at) || toIsoString(result == null ? void 0 : result.createdAt) || toIsoString(response == null ? void 0 : response.timestamp) || toIsoString(response == null ? void 0 : response.created_at) || toIsoString(response == null ? void 0 : response.createdAt);
|
|
9172
|
+
}
|
|
9173
|
+
function getCodexDedupeKey(timestamp, model, usage) {
|
|
9174
|
+
const rawInputTokens = usage.inputTokens + usage.cachedInputTokens;
|
|
9175
|
+
return [
|
|
9176
|
+
"codex",
|
|
9177
|
+
timestamp,
|
|
9178
|
+
model,
|
|
9179
|
+
String(rawInputTokens),
|
|
9180
|
+
String(usage.cachedInputTokens),
|
|
9181
|
+
String(usage.outputTokens),
|
|
9182
|
+
String(usage.reasoningOutputTokens),
|
|
9183
|
+
String(usage.totalTokens)
|
|
9184
|
+
].join(":");
|
|
9185
|
+
}
|
|
8646
9186
|
|
|
8647
9187
|
const COPILOT_MODEL_ATTRS = ["gen_ai.response.model", "gen_ai.request.model"];
|
|
8648
9188
|
const COPILOT_SESSION_ATTRS = [
|
|
@@ -8679,7 +9219,10 @@ const copilotUsageAdapter = {
|
|
|
8679
9219
|
const selectedCandidates = filterCopilotCandidates(candidates);
|
|
8680
9220
|
const fragments = /* @__PURE__ */ new Map();
|
|
8681
9221
|
for (const candidate of selectedCandidates) {
|
|
8682
|
-
const costUSD = calculateUsageCostFromCandidates(candidate.usage, [candidate.model], resolvePricing
|
|
9222
|
+
const costUSD = calculateUsageCostFromCandidates(candidate.usage, [candidate.model], resolvePricing, {
|
|
9223
|
+
includeExtraTotalAsOutput: true,
|
|
9224
|
+
includeReasoningAsOutput: false
|
|
9225
|
+
});
|
|
8683
9226
|
const fragment = (_a = fragments.get(candidate.sessionId)) != null ? _a : createSessionFragment({
|
|
8684
9227
|
project: "copilot",
|
|
8685
9228
|
repository: "local/copilot",
|
|
@@ -8746,21 +9289,22 @@ function getCopilotCandidate(record, index, fallbackTimestamp, traceContexts) {
|
|
|
8746
9289
|
if (!source) {
|
|
8747
9290
|
return null;
|
|
8748
9291
|
}
|
|
8749
|
-
const
|
|
8750
|
-
|
|
8751
|
-
|
|
8752
|
-
|
|
8753
|
-
|
|
8754
|
-
|
|
8755
|
-
|
|
8756
|
-
getCopilotAttributeNumber(attributes, "gen_ai.usage.
|
|
8757
|
-
|
|
8758
|
-
|
|
8759
|
-
|
|
8760
|
-
|
|
8761
|
-
|
|
9292
|
+
const usage = toInteractionUsage({
|
|
9293
|
+
...applyTotalUsageAsExtra({
|
|
9294
|
+
cacheCreationTokens: getCopilotAttributeNumberFirst(attributes, ["gen_ai.usage.cache_write.input_tokens", "gen_ai.usage.cache_creation.input_tokens"]),
|
|
9295
|
+
cacheReadTokens: getCopilotAttributeNumber(attributes, "gen_ai.usage.cache_read.input_tokens"),
|
|
9296
|
+
extraTotalTokens: getCopilotAttributeNumberFirst(attributes, ["gen_ai.usage.reasoning.output_tokens", "gen_ai.usage.reasoning_tokens"]),
|
|
9297
|
+
inputTokens: Math.max(
|
|
9298
|
+
0,
|
|
9299
|
+
getCopilotAttributeNumber(attributes, "gen_ai.usage.input_tokens") - Math.min(
|
|
9300
|
+
getCopilotAttributeNumber(attributes, "gen_ai.usage.input_tokens"),
|
|
9301
|
+
getCopilotAttributeNumber(attributes, "gen_ai.usage.cache_read.input_tokens")
|
|
9302
|
+
)
|
|
9303
|
+
),
|
|
9304
|
+
outputTokens: getCopilotAttributeNumber(attributes, "gen_ai.usage.output_tokens"),
|
|
9305
|
+
totalTokens: getCopilotAttributeNumberFirst(attributes, ["gen_ai.usage.total_tokens", "gen_ai.usage.total.token_count"])
|
|
9306
|
+
})
|
|
8762
9307
|
});
|
|
8763
|
-
const usage = toInteractionUsage(rawUsage);
|
|
8764
9308
|
if (isZeroInteractionUsage(usage)) {
|
|
8765
9309
|
return null;
|
|
8766
9310
|
}
|
|
@@ -8778,7 +9322,6 @@ function getCopilotCandidate(record, index, fallbackTimestamp, traceContexts) {
|
|
|
8778
9322
|
inputTokens: usage.inputTokens,
|
|
8779
9323
|
model,
|
|
8780
9324
|
outputTokens: usage.outputTokens,
|
|
8781
|
-
reasoningOutputTokens: usage.reasoningOutputTokens,
|
|
8782
9325
|
responseId,
|
|
8783
9326
|
sessionId,
|
|
8784
9327
|
source,
|
|
@@ -8905,7 +9448,7 @@ const droidUsageAdapter = {
|
|
|
8905
9448
|
const groups = await Promise.all(config.droidPaths.map((path) => glob(join(path, "**", "*.settings.json"), {
|
|
8906
9449
|
absolute: true
|
|
8907
9450
|
}).catch(() => [])));
|
|
8908
|
-
return groups.flat().flatMap((filePath) => toDiscoveredUsageFile(filePath, "droid"));
|
|
9451
|
+
return selectLatestDroidSettingsFiles(groups.flat()).flatMap((filePath) => toDiscoveredUsageFile(filePath, "droid"));
|
|
8909
9452
|
},
|
|
8910
9453
|
parseFile(filePath, resolvePricing) {
|
|
8911
9454
|
var _a, _b;
|
|
@@ -8915,15 +9458,16 @@ const droidUsageAdapter = {
|
|
|
8915
9458
|
if (!settings || !tokenUsage) {
|
|
8916
9459
|
return [];
|
|
8917
9460
|
}
|
|
9461
|
+
const extraTotalTokens = getNumber$7(tokenUsage.thinkingTokens);
|
|
8918
9462
|
const usage = toInteractionUsage({
|
|
8919
9463
|
...applyTotalUsageFallback({
|
|
8920
9464
|
cacheCreationTokens: getNumber$7(tokenUsage.cacheCreationTokens),
|
|
8921
9465
|
cacheReadTokens: getNumber$7(tokenUsage.cacheReadTokens),
|
|
8922
9466
|
inputTokens: getNumber$7(tokenUsage.inputTokens),
|
|
8923
9467
|
outputTokens: getNumber$7(tokenUsage.outputTokens),
|
|
8924
|
-
|
|
8925
|
-
|
|
8926
|
-
|
|
9468
|
+
totalTokens: Math.max(getNumber$7(tokenUsage.totalTokens) - extraTotalTokens, 0)
|
|
9469
|
+
}),
|
|
9470
|
+
extraTotalTokens
|
|
8927
9471
|
});
|
|
8928
9472
|
if (isZeroInteractionUsage(usage)) {
|
|
8929
9473
|
return [];
|
|
@@ -9071,12 +9615,29 @@ function extractDroidModelFromSidecar(settingsPath) {
|
|
|
9071
9615
|
function getNumber$7(value) {
|
|
9072
9616
|
return typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.trunc(value)) : 0;
|
|
9073
9617
|
}
|
|
9618
|
+
function selectLatestDroidSettingsFiles(filePaths) {
|
|
9619
|
+
const latestBySession = /* @__PURE__ */ new Map();
|
|
9620
|
+
for (const filePath of filePaths) {
|
|
9621
|
+
const sessionId = basename$1(filePath, ".settings.json");
|
|
9622
|
+
const timestamp = getDroidSnapshotTimestamp(filePath);
|
|
9623
|
+
const current = latestBySession.get(sessionId);
|
|
9624
|
+
if (!current || timestamp > current.timestamp) {
|
|
9625
|
+
latestBySession.set(sessionId, { filePath, timestamp });
|
|
9626
|
+
}
|
|
9627
|
+
}
|
|
9628
|
+
return Array.from(latestBySession.values()).map((item) => item.filePath).sort((a, b) => a.localeCompare(b));
|
|
9629
|
+
}
|
|
9630
|
+
function getDroidSnapshotTimestamp(filePath) {
|
|
9631
|
+
var _a;
|
|
9632
|
+
const settings = normalizeUnknownRecord(parseJsonFile(filePath));
|
|
9633
|
+
const timestamp = toIsoString(settings == null ? void 0 : settings.providerLockTimestamp);
|
|
9634
|
+
return timestamp ? Date.parse(timestamp) : Date.parse((_a = getFileModifiedAtIso(filePath)) != null ? _a : "") || 0;
|
|
9635
|
+
}
|
|
9074
9636
|
|
|
9075
9637
|
const geminiUsageAdapter = {
|
|
9076
9638
|
async createPricingResolver() {
|
|
9077
9639
|
return createLiteLLMPricingResolver({
|
|
9078
9640
|
aliases: GEMINI_MODEL_ALIASES,
|
|
9079
|
-
fallbackModel: GEMINI_FALLBACK_MODEL,
|
|
9080
9641
|
fallbackPricingTable: GEMINI_FALLBACK_PRICING_TABLE,
|
|
9081
9642
|
getLookupCandidates: getGeminiLookupCandidates
|
|
9082
9643
|
});
|
|
@@ -9139,20 +9700,25 @@ const geminiUsageAdapter = {
|
|
|
9139
9700
|
}
|
|
9140
9701
|
};
|
|
9141
9702
|
function getGeminiInteractionUsage(tokens, model, resolvePricing) {
|
|
9142
|
-
const
|
|
9703
|
+
const baseUsage = convertGeminiTokenUsage(tokens);
|
|
9704
|
+
const extraTotalTokens = normalizeNumber(tokens.thoughts);
|
|
9705
|
+
const usage = {
|
|
9706
|
+
...baseUsage,
|
|
9707
|
+
inputTokens: baseUsage.inputTokens + normalizeNumber(tokens.tool),
|
|
9708
|
+
reasoningOutputTokens: 0
|
|
9709
|
+
};
|
|
9143
9710
|
if (isZeroUsage(usage)) {
|
|
9144
9711
|
return null;
|
|
9145
9712
|
}
|
|
9146
|
-
const toolTokens = normalizeNumber(tokens.tool);
|
|
9147
9713
|
const costUSD = calculateUsageCostUSD({
|
|
9148
9714
|
cachedInputTokens: usage.cachedInputTokens,
|
|
9149
9715
|
inputTokens: usage.inputTokens,
|
|
9150
|
-
outputTokens: usage.outputTokens
|
|
9716
|
+
outputTokens: usage.outputTokens
|
|
9151
9717
|
}, resolvePricing(model));
|
|
9152
9718
|
return {
|
|
9153
9719
|
...usage,
|
|
9154
9720
|
costUSD,
|
|
9155
|
-
|
|
9721
|
+
extraTotalTokens
|
|
9156
9722
|
};
|
|
9157
9723
|
}
|
|
9158
9724
|
function getGeminiRole(message) {
|
|
@@ -9217,7 +9783,7 @@ const gooseUsageAdapter = {
|
|
|
9217
9783
|
addFragmentInteraction(fragment, {
|
|
9218
9784
|
content: "",
|
|
9219
9785
|
costUSD: entry.usage.costUSD,
|
|
9220
|
-
dedupeKey: `goose:${entry.sessionId}`,
|
|
9786
|
+
dedupeKey: `goose:${filePath}:${entry.sessionId}`,
|
|
9221
9787
|
index: 0,
|
|
9222
9788
|
model: entry.model,
|
|
9223
9789
|
role: "usage",
|
|
@@ -9248,11 +9814,11 @@ function parseGooseRow(row, resolvePricing) {
|
|
|
9248
9814
|
const inputTokens = getNumber$6(row.accumulated_input_tokens) || getNumber$6(row.input_tokens);
|
|
9249
9815
|
const outputTokens = getNumber$6(row.accumulated_output_tokens) || getNumber$6(row.output_tokens);
|
|
9250
9816
|
const totalTokens = getNumber$6(row.accumulated_total_tokens) || getNumber$6(row.total_tokens) || inputTokens + outputTokens;
|
|
9251
|
-
const
|
|
9817
|
+
const extraTotalTokens = Math.max(0, totalTokens - inputTokens - outputTokens);
|
|
9252
9818
|
const usage = toInteractionUsage({
|
|
9819
|
+
extraTotalTokens,
|
|
9253
9820
|
inputTokens,
|
|
9254
|
-
outputTokens
|
|
9255
|
-
reasoningOutputTokens
|
|
9821
|
+
outputTokens
|
|
9256
9822
|
});
|
|
9257
9823
|
if (isZeroInteractionUsage(usage)) {
|
|
9258
9824
|
return null;
|
|
@@ -9370,9 +9936,9 @@ function parseHermesRow(row, resolvePricing) {
|
|
|
9370
9936
|
const usage = toInteractionUsage({
|
|
9371
9937
|
cacheCreationTokens: toNumber(row.cache_write_tokens),
|
|
9372
9938
|
cacheReadTokens: toNumber(row.cache_read_tokens),
|
|
9939
|
+
extraTotalTokens: toNumber(row.reasoning_tokens),
|
|
9373
9940
|
inputTokens: toNumber(row.input_tokens),
|
|
9374
|
-
outputTokens: toNumber(row.output_tokens)
|
|
9375
|
-
reasoningOutputTokens: toNumber(row.reasoning_tokens)
|
|
9941
|
+
outputTokens: toNumber(row.output_tokens)
|
|
9376
9942
|
});
|
|
9377
9943
|
if (isZeroInteractionUsage(usage) && !toOptionalNumber(row.actual_cost_usd) && !toOptionalNumber(row.estimated_cost_usd)) {
|
|
9378
9944
|
return null;
|
|
@@ -9497,15 +10063,16 @@ function parseKiloMessage(value, row, filePath, resolvePricing) {
|
|
|
9497
10063
|
if (!tokens || !model || !timestamp) {
|
|
9498
10064
|
return null;
|
|
9499
10065
|
}
|
|
10066
|
+
const extraTotalTokens = getNumber$5(tokens.reasoning);
|
|
9500
10067
|
const usage = toInteractionUsage({
|
|
9501
10068
|
...applyTotalUsageFallback({
|
|
9502
10069
|
cacheCreationTokens: getNumber$5((_b = normalizeUnknownRecord(tokens.cache)) == null ? void 0 : _b.write),
|
|
9503
10070
|
cacheReadTokens: getNumber$5((_c = normalizeUnknownRecord(tokens.cache)) == null ? void 0 : _c.read),
|
|
9504
10071
|
inputTokens: getNumber$5(tokens.input),
|
|
9505
10072
|
outputTokens: getNumber$5(tokens.output),
|
|
9506
|
-
|
|
9507
|
-
|
|
9508
|
-
|
|
10073
|
+
totalTokens: Math.max(getNumber$5(tokens.total) - extraTotalTokens, 0)
|
|
10074
|
+
}),
|
|
10075
|
+
extraTotalTokens
|
|
9509
10076
|
});
|
|
9510
10077
|
if (isZeroInteractionUsage(usage)) {
|
|
9511
10078
|
return null;
|
|
@@ -9554,7 +10121,7 @@ const kimiUsageAdapter = {
|
|
|
9554
10121
|
return groups.flat().filter((filePath) => isKimiWireFile(join(dirname$1(dirname$1(dirname$1(filePath))), "sessions"), filePath)).flatMap((filePath) => toDiscoveredUsageFile(filePath, "kimi"));
|
|
9555
10122
|
},
|
|
9556
10123
|
parseFile(filePath, resolvePricing) {
|
|
9557
|
-
var _a;
|
|
10124
|
+
var _a, _b, _c, _d;
|
|
9558
10125
|
const sessionId = getKimiSessionId(filePath);
|
|
9559
10126
|
const model = getKimiModel(filePath);
|
|
9560
10127
|
const fallbackTimestamp = getFileModifiedAtIso(filePath);
|
|
@@ -9575,7 +10142,7 @@ const kimiUsageAdapter = {
|
|
|
9575
10142
|
continue;
|
|
9576
10143
|
}
|
|
9577
10144
|
const usage = toInteractionUsage({
|
|
9578
|
-
...
|
|
10145
|
+
...applyTotalUsageAsExtra({
|
|
9579
10146
|
cacheCreationTokens: getNumber$4(tokenUsage.input_cache_creation),
|
|
9580
10147
|
cacheReadTokens: getNumber$4(tokenUsage.input_cache_read),
|
|
9581
10148
|
inputTokens: getNumber$4(tokenUsage.input_other),
|
|
@@ -9596,7 +10163,11 @@ const kimiUsageAdapter = {
|
|
|
9596
10163
|
normalizeStringValue(payload.message_id) || "",
|
|
9597
10164
|
timestamp || "",
|
|
9598
10165
|
model,
|
|
9599
|
-
String(usage.
|
|
10166
|
+
String(usage.inputTokens),
|
|
10167
|
+
String(usage.outputTokens),
|
|
10168
|
+
String((_b = usage.cacheCreationTokens) != null ? _b : 0),
|
|
10169
|
+
String((_c = usage.cacheReadTokens) != null ? _c : 0),
|
|
10170
|
+
String((_d = usage.extraTotalTokens) != null ? _d : 0)
|
|
9600
10171
|
].join(":"),
|
|
9601
10172
|
index,
|
|
9602
10173
|
model,
|
|
@@ -9652,7 +10223,7 @@ const openClawUsageAdapter = {
|
|
|
9652
10223
|
return groups.flat().filter((filePath) => isOpenClawSessionFile(basename$1(filePath))).flatMap((filePath) => toDiscoveredUsageFile(filePath, "openclaw"));
|
|
9653
10224
|
},
|
|
9654
10225
|
parseFile(filePath) {
|
|
9655
|
-
var _a, _b, _c, _d, _e;
|
|
10226
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
9656
10227
|
const lines = readFileSync(filePath, "utf8").split("\n").map((line) => line.trim()).filter(Boolean);
|
|
9657
10228
|
const sessionId = getOpenClawSessionId(filePath);
|
|
9658
10229
|
const fragment = createSessionFragment({
|
|
@@ -9686,7 +10257,7 @@ const openClawUsageAdapter = {
|
|
|
9686
10257
|
continue;
|
|
9687
10258
|
}
|
|
9688
10259
|
const usage = toInteractionUsage({
|
|
9689
|
-
...
|
|
10260
|
+
...applyTotalUsageAsExtra({
|
|
9690
10261
|
cacheCreationTokens: getNumber$3(usageRecord.cacheWrite),
|
|
9691
10262
|
cacheReadTokens: getNumber$3(usageRecord.cacheRead),
|
|
9692
10263
|
inputTokens: getNumber$3(usageRecord.input),
|
|
@@ -9711,8 +10282,9 @@ const openClawUsageAdapter = {
|
|
|
9711
10282
|
rawModel,
|
|
9712
10283
|
String(usage.inputTokens),
|
|
9713
10284
|
String(usage.outputTokens),
|
|
9714
|
-
String(usage.
|
|
9715
|
-
String(usage.
|
|
10285
|
+
String((_f = usage.cacheCreationTokens) != null ? _f : 0),
|
|
10286
|
+
String((_g = usage.cacheReadTokens) != null ? _g : 0),
|
|
10287
|
+
String((_h = usage.extraTotalTokens) != null ? _h : 0),
|
|
9716
10288
|
String(usage.costUSD)
|
|
9717
10289
|
].join(":"),
|
|
9718
10290
|
index,
|
|
@@ -9820,8 +10392,12 @@ const openCodeUsageAdapter = {
|
|
|
9820
10392
|
}
|
|
9821
10393
|
const value = parseJsonFile(filePath);
|
|
9822
10394
|
const record = normalizeUnknownRecord(value);
|
|
10395
|
+
const interactionId = normalizeStringValue(record == null ? void 0 : record.id);
|
|
10396
|
+
if (interactionId && isDuplicatedByOpenCodeDatabase(filePath, interactionId)) {
|
|
10397
|
+
return [];
|
|
10398
|
+
}
|
|
9823
10399
|
const entry = record ? getOpenCodeMessageEntry(record, resolvePricing, {
|
|
9824
|
-
interactionId
|
|
10400
|
+
interactionId,
|
|
9825
10401
|
sessionId: normalizeStringValue(record.sessionID)
|
|
9826
10402
|
}) : null;
|
|
9827
10403
|
if (!entry) {
|
|
@@ -9874,7 +10450,7 @@ function getOpenCodeMessageEntry(value, resolvePricing, options = {}) {
|
|
|
9874
10450
|
return null;
|
|
9875
10451
|
}
|
|
9876
10452
|
const usage = toInteractionUsage({
|
|
9877
|
-
...
|
|
10453
|
+
...applyTotalUsageAsExtra({
|
|
9878
10454
|
cacheCreationTokens: getNumber$2((_b = normalizeUnknownRecord(tokens.cache)) == null ? void 0 : _b.write),
|
|
9879
10455
|
cacheReadTokens: getNumber$2((_c = normalizeUnknownRecord(tokens.cache)) == null ? void 0 : _c.read),
|
|
9880
10456
|
inputTokens: getNumber$2(tokens.input),
|
|
@@ -9891,7 +10467,10 @@ function getOpenCodeMessageEntry(value, resolvePricing, options = {}) {
|
|
|
9891
10467
|
}
|
|
9892
10468
|
const sessionId = options.sessionId || "unknown";
|
|
9893
10469
|
const directCost = normalizeFiniteNumberOrNull(value.cost);
|
|
9894
|
-
const costUSD = directCost && directCost > 0 ? directCost : calculateUsageCostFromCandidates(usage, getOpenCodeModelCandidates(model, provider), resolvePricing
|
|
10470
|
+
const costUSD = directCost && directCost > 0 ? directCost : calculateUsageCostFromCandidates(usage, getOpenCodeModelCandidates(model, provider), resolvePricing, {
|
|
10471
|
+
includeExtraTotalAsOutput: true,
|
|
10472
|
+
includeReasoningAsOutput: false
|
|
10473
|
+
});
|
|
9895
10474
|
return {
|
|
9896
10475
|
interactionId: options.interactionId || normalizeStringValue(value.id) || `${sessionId}:${timestamp}:${model}`,
|
|
9897
10476
|
model,
|
|
@@ -9907,6 +10486,25 @@ function getOpenCodeLookupCandidates(model) {
|
|
|
9907
10486
|
const normalizedModel = normalizeOpenCodeModelName(resolveOpenCodeModelName(model.trim()));
|
|
9908
10487
|
return [model.trim(), normalizedModel];
|
|
9909
10488
|
}
|
|
10489
|
+
function isDuplicatedByOpenCodeDatabase(filePath, interactionId) {
|
|
10490
|
+
const root = getOpenCodeRootFromMessageFile(filePath);
|
|
10491
|
+
if (!root) {
|
|
10492
|
+
return false;
|
|
10493
|
+
}
|
|
10494
|
+
const databaseFile = getOpenCodeDatabaseFileSync(root);
|
|
10495
|
+
if (!databaseFile) {
|
|
10496
|
+
return false;
|
|
10497
|
+
}
|
|
10498
|
+
const database = openSqliteDatabase(databaseFile, { readOnly: true });
|
|
10499
|
+
try {
|
|
10500
|
+
const row = database.prepare("SELECT id FROM message WHERE id = ? LIMIT 1").get(interactionId);
|
|
10501
|
+
return Boolean(row == null ? void 0 : row.id);
|
|
10502
|
+
} catch {
|
|
10503
|
+
return false;
|
|
10504
|
+
} finally {
|
|
10505
|
+
database.close();
|
|
10506
|
+
}
|
|
10507
|
+
}
|
|
9910
10508
|
function getOpenCodeModelCandidates(model, provider) {
|
|
9911
10509
|
const normalizedModel = normalizeOpenCodeModelName(resolveOpenCodeModelName(model));
|
|
9912
10510
|
const candidates = [model, normalizedModel];
|
|
@@ -9945,6 +10543,22 @@ function parseUnknownJson(value) {
|
|
|
9945
10543
|
return null;
|
|
9946
10544
|
}
|
|
9947
10545
|
}
|
|
10546
|
+
function getOpenCodeDatabaseFileSync(root) {
|
|
10547
|
+
var _a;
|
|
10548
|
+
const defaultPath = join(root, "opencode.db");
|
|
10549
|
+
if (existsSync(defaultPath)) {
|
|
10550
|
+
return defaultPath;
|
|
10551
|
+
}
|
|
10552
|
+
return (_a = readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isFile() && isOpenCodeChannelDatabase(entry.name)).map((entry) => join(root, entry.name)).sort((left, right) => left.localeCompare(right))[0]) != null ? _a : null;
|
|
10553
|
+
}
|
|
10554
|
+
function getOpenCodeRootFromMessageFile(filePath) {
|
|
10555
|
+
const marker = `${join("storage", "message")}/`;
|
|
10556
|
+
const index = filePath.lastIndexOf(marker);
|
|
10557
|
+
return index >= 0 ? filePath.slice(0, index) : null;
|
|
10558
|
+
}
|
|
10559
|
+
function isOpenCodeChannelDatabase(name) {
|
|
10560
|
+
return /^opencode-[\w-]+\.db$/u.test(name);
|
|
10561
|
+
}
|
|
9948
10562
|
|
|
9949
10563
|
const piUsageAdapter = {
|
|
9950
10564
|
createPricingResolver: createZeroPricingResolver,
|
|
@@ -9955,7 +10569,7 @@ const piUsageAdapter = {
|
|
|
9955
10569
|
return groups.flat().flatMap((filePath) => toDiscoveredUsageFile(filePath, "pi"));
|
|
9956
10570
|
},
|
|
9957
10571
|
parseFile(filePath) {
|
|
9958
|
-
var _a, _b, _c;
|
|
10572
|
+
var _a, _b, _c, _d, _e, _f;
|
|
9959
10573
|
const lines = parseJsonlFile(filePath);
|
|
9960
10574
|
const sessionId = getPiSessionId(filePath);
|
|
9961
10575
|
const project = getPiProject(filePath);
|
|
@@ -9978,7 +10592,7 @@ const piUsageAdapter = {
|
|
|
9978
10592
|
continue;
|
|
9979
10593
|
}
|
|
9980
10594
|
const usage = toInteractionUsage({
|
|
9981
|
-
...
|
|
10595
|
+
...applyTotalUsageAsExtra({
|
|
9982
10596
|
cacheCreationTokens: getNumber$1(usageRecord.cacheWrite),
|
|
9983
10597
|
cacheReadTokens: getNumber$1(usageRecord.cacheRead),
|
|
9984
10598
|
inputTokens: getNumber$1(usageRecord.input),
|
|
@@ -9994,6 +10608,19 @@ const piUsageAdapter = {
|
|
|
9994
10608
|
addFragmentInteraction(fragment, {
|
|
9995
10609
|
content: "",
|
|
9996
10610
|
costUSD: usage.costUSD,
|
|
10611
|
+
dedupeKey: [
|
|
10612
|
+
"pi",
|
|
10613
|
+
project,
|
|
10614
|
+
sessionId,
|
|
10615
|
+
timestamp,
|
|
10616
|
+
rawModel || "",
|
|
10617
|
+
String(usage.inputTokens),
|
|
10618
|
+
String(usage.outputTokens),
|
|
10619
|
+
String((_d = usage.cacheCreationTokens) != null ? _d : 0),
|
|
10620
|
+
String((_e = usage.cacheReadTokens) != null ? _e : 0),
|
|
10621
|
+
String((_f = usage.extraTotalTokens) != null ? _f : 0),
|
|
10622
|
+
String(usage.costUSD)
|
|
10623
|
+
].join(":"),
|
|
9997
10624
|
index,
|
|
9998
10625
|
model: rawModel ? `[pi] ${rawModel}` : null,
|
|
9999
10626
|
role: "assistant",
|
|
@@ -10057,14 +10684,15 @@ const qwenUsageAdapter = {
|
|
|
10057
10684
|
if (!record || normalizeStringValue(record.type) !== "assistant" || !usageRecord) {
|
|
10058
10685
|
continue;
|
|
10059
10686
|
}
|
|
10687
|
+
const extraTotalTokens = getNumber(usageRecord.thoughtsTokenCount);
|
|
10060
10688
|
const usage = toInteractionUsage({
|
|
10061
10689
|
...applyTotalUsageFallback({
|
|
10062
10690
|
cacheReadTokens: getNumber(usageRecord.cachedContentTokenCount),
|
|
10063
10691
|
inputTokens: getNumber(usageRecord.promptTokenCount),
|
|
10064
10692
|
outputTokens: getNumber(usageRecord.candidatesTokenCount),
|
|
10065
|
-
|
|
10066
|
-
|
|
10067
|
-
|
|
10693
|
+
totalTokens: Math.max(getNumber(usageRecord.totalTokenCount) - extraTotalTokens, 0)
|
|
10694
|
+
}),
|
|
10695
|
+
extraTotalTokens
|
|
10068
10696
|
});
|
|
10069
10697
|
if (isZeroInteractionUsage(usage)) {
|
|
10070
10698
|
continue;
|
|
@@ -10451,7 +11079,8 @@ function buildProjectUsageCatalogItemsFromDetails(details) {
|
|
|
10451
11079
|
return Array.from(details).map(([label, detail]) => {
|
|
10452
11080
|
return {
|
|
10453
11081
|
label,
|
|
10454
|
-
|
|
11082
|
+
platforms: getProjectDetailPlatforms(detail),
|
|
11083
|
+
totalTokens: getProjectDetailTotalTokens(detail)
|
|
10455
11084
|
};
|
|
10456
11085
|
}).sort((a, b) => a.label.localeCompare(b.label));
|
|
10457
11086
|
}
|
|
@@ -10527,8 +11156,8 @@ function getProjectDetailPlatforms(detail) {
|
|
|
10527
11156
|
return ((_a = detail.analyzing[platform]) != null ? _a : createEmptyProjectPlatformUsage()).sessions.length > 0;
|
|
10528
11157
|
});
|
|
10529
11158
|
}
|
|
10530
|
-
function
|
|
10531
|
-
return
|
|
11159
|
+
function getProjectDetailTotalTokens(detail) {
|
|
11160
|
+
return getProjectDetailSessions(detail).reduce((sum, session) => sum + session.tokenTotal, 0);
|
|
10532
11161
|
}
|
|
10533
11162
|
function buildSessionListModulePayload(sessionRows, sessions) {
|
|
10534
11163
|
const sessionList = sessions.map(({ interactions: _interactions, ...session }) => session);
|
|
@@ -10549,45 +11178,318 @@ function buildProjectPlatformPayloadMap(detail, module) {
|
|
|
10549
11178
|
})
|
|
10550
11179
|
);
|
|
10551
11180
|
}
|
|
10552
|
-
function buildProjectLoadUsageResult(sessions, platform = "all") {
|
|
10553
|
-
const usage = buildLoadUsageResult(getProjectAggregateEvents(sessions), sessions, {
|
|
10554
|
-
aggregateOptions: {
|
|
10555
|
-
includeModel: (event) => platform !== "claudeCode" || event.model !== "<synthetic>"
|
|
11181
|
+
function buildProjectLoadUsageResult(sessions, platform = "all") {
|
|
11182
|
+
const usage = buildLoadUsageResult(getProjectAggregateEvents(sessions), sessions, {
|
|
11183
|
+
aggregateOptions: {
|
|
11184
|
+
includeModel: (event) => platform !== "claudeCode" || event.model !== "<synthetic>"
|
|
11185
|
+
}
|
|
11186
|
+
});
|
|
11187
|
+
return {
|
|
11188
|
+
...usage,
|
|
11189
|
+
sessionUsage: sessions
|
|
11190
|
+
};
|
|
11191
|
+
}
|
|
11192
|
+
function getProjectAggregateEvents(sessions) {
|
|
11193
|
+
return sessions.flatMap((session) => session.interactions.filter((interaction) => interaction.usage && interaction.timestamp && hasBillableUsage(interaction.usage)).map((interaction) => {
|
|
11194
|
+
var _a, _b;
|
|
11195
|
+
return {
|
|
11196
|
+
cachedInputTokens: interaction.usage.cachedInputTokens,
|
|
11197
|
+
costUSD: interaction.usage.costUSD,
|
|
11198
|
+
inputTokens: interaction.usage.inputTokens,
|
|
11199
|
+
isFallbackModel: (_a = interaction.usage.isFallbackModel) != null ? _a : false,
|
|
11200
|
+
model: (_b = interaction.model) != null ? _b : session.model,
|
|
11201
|
+
outputTokens: interaction.usage.outputTokens,
|
|
11202
|
+
project: session.project,
|
|
11203
|
+
reasoningOutputTokens: interaction.usage.reasoningOutputTokens,
|
|
11204
|
+
repository: session.repository,
|
|
11205
|
+
sessionId: session.id,
|
|
11206
|
+
timestamp: interaction.timestamp,
|
|
11207
|
+
totalTokens: interaction.usage.totalTokens
|
|
11208
|
+
};
|
|
11209
|
+
})).sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
|
|
11210
|
+
}
|
|
11211
|
+
function hasBillableUsage(usage) {
|
|
11212
|
+
return usage.totalTokens > 0 || usage.costUSD > 0;
|
|
11213
|
+
}
|
|
11214
|
+
function collectSessionModels(sessions) {
|
|
11215
|
+
return uniqueItems(sessions.flatMap((session) => session.models)).sort((a, b) => a.localeCompare(b));
|
|
11216
|
+
}
|
|
11217
|
+
function getEarliestStartedAt(sessions) {
|
|
11218
|
+
var _a;
|
|
11219
|
+
return (_a = sessions.map((session) => session.startedAt).filter((timestamp) => Number.isFinite(Date.parse(timestamp))).sort((a, b) => Date.parse(a) - Date.parse(b))[0]) != null ? _a : null;
|
|
11220
|
+
}
|
|
11221
|
+
|
|
11222
|
+
function buildHomeDashboardModules(dashboardsByPlatform, todayInsights = void 0) {
|
|
11223
|
+
const sessionUsage = buildSessionUsage(dashboardsByPlatform);
|
|
11224
|
+
const dailyTokenUsage = mergeDailyTokenUsage(
|
|
11225
|
+
PROJECT_USAGE_PLATFORMS.flatMap(
|
|
11226
|
+
(platform) => dashboardsByPlatform[platform].dailyTokenUsage.map((item) => {
|
|
11227
|
+
return {
|
|
11228
|
+
...item,
|
|
11229
|
+
platforms: {
|
|
11230
|
+
[platform]: {
|
|
11231
|
+
cachedInputTokens: item.cachedInputTokens,
|
|
11232
|
+
costUSD: item.costUSD,
|
|
11233
|
+
inputTokens: item.inputTokens,
|
|
11234
|
+
models: item.models,
|
|
11235
|
+
outputTokens: item.outputTokens,
|
|
11236
|
+
reasoningOutputTokens: item.reasoningOutputTokens,
|
|
11237
|
+
totalTokens: item.totalTokens
|
|
11238
|
+
}
|
|
11239
|
+
}
|
|
11240
|
+
};
|
|
11241
|
+
})
|
|
11242
|
+
)
|
|
11243
|
+
);
|
|
11244
|
+
const monthlyModelUsage = mergeMonthlyModelUsage(
|
|
11245
|
+
PROJECT_USAGE_PLATFORMS.flatMap((platform) => dashboardsByPlatform[platform].monthlyModelUsage)
|
|
11246
|
+
);
|
|
11247
|
+
const projectUsage = buildProjectUsage(sessionUsage);
|
|
11248
|
+
const totalCost = dailyTokenUsage.reduce((sum, item) => sum + item.costUSD, 0);
|
|
11249
|
+
const totalTokens = dailyTokenUsage.reduce((sum, item) => sum + item.totalTokens, 0);
|
|
11250
|
+
const inputTokens = dailyTokenUsage.reduce((sum, item) => sum + item.inputTokens, 0);
|
|
11251
|
+
const cachedInputTokens = dailyTokenUsage.reduce((sum, item) => sum + item.cachedInputTokens, 0);
|
|
11252
|
+
const outputTokens = dailyTokenUsage.reduce((sum, item) => sum + item.outputTokens, 0);
|
|
11253
|
+
const reasoningOutputTokens = dailyTokenUsage.reduce((sum, item) => sum + item.reasoningOutputTokens, 0);
|
|
11254
|
+
const totalSessions = sessionUsage.length;
|
|
11255
|
+
const efficiencyMetrics = buildEfficiencyMetrics({
|
|
11256
|
+
cachedInputTokens,
|
|
11257
|
+
inputTokens,
|
|
11258
|
+
outputTokens,
|
|
11259
|
+
reasoningOutputTokens,
|
|
11260
|
+
totalTokens
|
|
11261
|
+
});
|
|
11262
|
+
const homeTodayInsights = todayInsights != null ? todayInsights : buildHomeTodayInsights(dashboardsByPlatform);
|
|
11263
|
+
const todayDateKey = getDateKey(/* @__PURE__ */ new Date());
|
|
11264
|
+
const previousDayDateKey = getPreviousDateKey(todayDateKey);
|
|
11265
|
+
const todayUsage = dailyTokenUsage.find((item) => getDateKeyFromLabel(item.date) === todayDateKey);
|
|
11266
|
+
const previousUsage = dailyTokenUsage.find((item) => getDateKeyFromLabel(item.date) === previousDayDateKey);
|
|
11267
|
+
return {
|
|
11268
|
+
dailyTokenUsage,
|
|
11269
|
+
efficiencyMetrics,
|
|
11270
|
+
hotProjects: projectUsage,
|
|
11271
|
+
modelUsage: monthlyModelUsage,
|
|
11272
|
+
overviewCards: buildHomeOverviewCards({
|
|
11273
|
+
cachedInputTokens,
|
|
11274
|
+
inputTokens,
|
|
11275
|
+
previousPromptCount: homeTodayInsights.previousPromptCount,
|
|
11276
|
+
previousSessionCount: homeTodayInsights.previousSessionCount,
|
|
11277
|
+
previousUsage,
|
|
11278
|
+
promptCount: homeTodayInsights.promptCount,
|
|
11279
|
+
sessionCount: homeTodayInsights.sessionCount,
|
|
11280
|
+
todayHourlyUsage: homeTodayInsights.todayHourlyUsage,
|
|
11281
|
+
todayUsage,
|
|
11282
|
+
totalCost,
|
|
11283
|
+
totalSessions,
|
|
11284
|
+
totalTokens
|
|
11285
|
+
}),
|
|
11286
|
+
sessionAnalysis: {
|
|
11287
|
+
items: sessionUsage,
|
|
11288
|
+
totalSessions
|
|
11289
|
+
},
|
|
11290
|
+
todayHourlyUsage: homeTodayInsights.todayHourlyUsage
|
|
11291
|
+
};
|
|
11292
|
+
}
|
|
11293
|
+
function buildSessionUsage(dashboardsByPlatform) {
|
|
11294
|
+
return PROJECT_USAGE_PLATFORMS.flatMap((platform) => dashboardsByPlatform[platform].sessionUsage.map((session) => ({
|
|
11295
|
+
...session,
|
|
11296
|
+
id: `${platform}:${session.id}`,
|
|
11297
|
+
sessionId: `${platform}:${session.sessionId}`
|
|
11298
|
+
}))).sort((a, b) => Date.parse(b.startedAt) - Date.parse(a.startedAt));
|
|
11299
|
+
}
|
|
11300
|
+
function buildHomeOverviewCards(options) {
|
|
11301
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t;
|
|
11302
|
+
const tokenTrend = buildGrowthTrend(
|
|
11303
|
+
(_b = (_a = options.todayUsage) == null ? void 0 : _a.totalTokens) != null ? _b : 0,
|
|
11304
|
+
(_d = (_c = options.previousUsage) == null ? void 0 : _c.totalTokens) != null ? _d : 0,
|
|
11305
|
+
formatCompactNumber
|
|
11306
|
+
);
|
|
11307
|
+
const costTrend = buildGrowthTrend(
|
|
11308
|
+
(_f = (_e = options.todayUsage) == null ? void 0 : _e.costUSD) != null ? _f : 0,
|
|
11309
|
+
(_h = (_g = options.previousUsage) == null ? void 0 : _g.costUSD) != null ? _h : 0,
|
|
11310
|
+
formatCurrency
|
|
11311
|
+
);
|
|
11312
|
+
const sessionTrend = buildPercentTrend(options.sessionCount, options.previousSessionCount);
|
|
11313
|
+
const promptTrend = buildPercentTrend(options.promptCount, options.previousPromptCount);
|
|
11314
|
+
return [
|
|
11315
|
+
{
|
|
11316
|
+
detail: `${formatNumber((_j = (_i = options.todayUsage) == null ? void 0 : _i.totalTokens) != null ? _j : 0)} tokens today. Yesterday: ${formatNumber((_l = (_k = options.previousUsage) == null ? void 0 : _k.totalTokens) != null ? _l : 0)}.`,
|
|
11317
|
+
icon: "solar:cpu-line-duotone",
|
|
11318
|
+
name: "Today Tokens",
|
|
11319
|
+
subvalue: buildInputOutputTokenSubvalue(options.todayUsage),
|
|
11320
|
+
trend: tokenTrend.trend,
|
|
11321
|
+
trendTone: tokenTrend.trendTone,
|
|
11322
|
+
value: formatCompactNumber((_n = (_m = options.todayUsage) == null ? void 0 : _m.totalTokens) != null ? _n : 0)
|
|
11323
|
+
},
|
|
11324
|
+
{
|
|
11325
|
+
detail: `${formatCurrency((_p = (_o = options.todayUsage) == null ? void 0 : _o.costUSD) != null ? _p : 0)} spent today. Yesterday: ${formatCurrency((_r = (_q = options.previousUsage) == null ? void 0 : _q.costUSD) != null ? _r : 0)}.`,
|
|
11326
|
+
icon: "lucide:wallet",
|
|
11327
|
+
name: "Today Spend",
|
|
11328
|
+
subvalue: {
|
|
11329
|
+
items: [
|
|
11330
|
+
{
|
|
11331
|
+
value: `${options.todayHourlyUsage.filter((item) => item.totalTokens > 0).length} active hours`
|
|
11332
|
+
}
|
|
11333
|
+
]
|
|
11334
|
+
},
|
|
11335
|
+
trend: costTrend.trend,
|
|
11336
|
+
trendTone: costTrend.trendTone,
|
|
11337
|
+
value: formatCurrency((_t = (_s = options.todayUsage) == null ? void 0 : _s.costUSD) != null ? _t : 0)
|
|
11338
|
+
},
|
|
11339
|
+
{
|
|
11340
|
+
detail: `${formatNumber(options.sessionCount)} sessions started today. Yesterday: ${formatNumber(options.previousSessionCount)}.`,
|
|
11341
|
+
icon: "lucide:messages-square",
|
|
11342
|
+
name: "Today Sessions",
|
|
11343
|
+
trend: sessionTrend.label,
|
|
11344
|
+
trendTone: sessionTrend.tone,
|
|
11345
|
+
value: formatNumber(options.sessionCount)
|
|
11346
|
+
},
|
|
11347
|
+
{
|
|
11348
|
+
detail: `${formatNumber(options.promptCount)} prompts sent today. Yesterday: ${formatNumber(options.previousPromptCount)}.`,
|
|
11349
|
+
icon: "lucide:square-pen",
|
|
11350
|
+
name: "Prompt Count",
|
|
11351
|
+
trend: promptTrend.label,
|
|
11352
|
+
trendTone: promptTrend.tone,
|
|
11353
|
+
value: formatNumber(options.promptCount)
|
|
11354
|
+
},
|
|
11355
|
+
{
|
|
11356
|
+
detail: `${formatCurrency(options.totalCost)} total spend across all tools`,
|
|
11357
|
+
icon: "lucide:wallet",
|
|
11358
|
+
name: "Total Spend",
|
|
11359
|
+
trend: costTrend.trend,
|
|
11360
|
+
trendTone: costTrend.trendTone,
|
|
11361
|
+
value: formatCurrency(options.totalCost)
|
|
11362
|
+
},
|
|
11363
|
+
{
|
|
11364
|
+
detail: `${formatNumber(options.totalTokens)} total tokens across all tools`,
|
|
11365
|
+
icon: "solar:cpu-line-duotone",
|
|
11366
|
+
name: "Token Usage",
|
|
11367
|
+
trend: tokenTrend.trend,
|
|
11368
|
+
trendTone: tokenTrend.trendTone,
|
|
11369
|
+
value: formatCompactNumber(options.totalTokens)
|
|
11370
|
+
},
|
|
11371
|
+
{
|
|
11372
|
+
detail: `${formatNumber(options.cachedInputTokens)} of ${formatNumber(options.inputTokens)} input tokens were served from cache`,
|
|
11373
|
+
icon: "lucide:database-zap",
|
|
11374
|
+
name: "Cache Hit Rate",
|
|
11375
|
+
trend: `${formatCompactNumber(options.cachedInputTokens)} cached`,
|
|
11376
|
+
trendTone: "neutral",
|
|
11377
|
+
value: formatPercent(options.inputTokens > 0 ? options.cachedInputTokens / options.inputTokens : 0)
|
|
11378
|
+
},
|
|
11379
|
+
{
|
|
11380
|
+
detail: `${formatCurrency(options.totalCost)} across ${formatNumber(options.totalSessions)} sessions`,
|
|
11381
|
+
icon: "lucide:receipt-text",
|
|
11382
|
+
name: "Avg Session Cost",
|
|
11383
|
+
trend: "across all tools",
|
|
11384
|
+
trendTone: "neutral",
|
|
11385
|
+
value: formatCurrency(options.totalSessions > 0 ? options.totalCost / options.totalSessions : 0)
|
|
11386
|
+
}
|
|
11387
|
+
];
|
|
11388
|
+
}
|
|
11389
|
+
function buildHomeTodayInsights(dashboardsByPlatform) {
|
|
11390
|
+
var _a, _b;
|
|
11391
|
+
const todayDateKey = getDateKey(/* @__PURE__ */ new Date());
|
|
11392
|
+
const previousDayDateKey = getPreviousDateKey(todayDateKey);
|
|
11393
|
+
const hourlyUsage = /* @__PURE__ */ new Map();
|
|
11394
|
+
let promptCount = 0;
|
|
11395
|
+
let previousPromptCount = 0;
|
|
11396
|
+
let sessionCount = 0;
|
|
11397
|
+
let previousSessionCount = 0;
|
|
11398
|
+
for (const platform of PROJECT_USAGE_PLATFORMS) {
|
|
11399
|
+
for (const session of dashboardsByPlatform[platform].sessionUsage) {
|
|
11400
|
+
const startedAtDateKey = getDateKeyFromTimestamp(session.startedAt);
|
|
11401
|
+
if (startedAtDateKey === todayDateKey) {
|
|
11402
|
+
sessionCount += 1;
|
|
11403
|
+
} else if (startedAtDateKey === previousDayDateKey) {
|
|
11404
|
+
previousSessionCount += 1;
|
|
11405
|
+
}
|
|
11406
|
+
for (const interaction of session.interactions) {
|
|
11407
|
+
const interactionDateKey = getDateKeyFromTimestamp(interaction.timestamp);
|
|
11408
|
+
if (interaction.role === "user") {
|
|
11409
|
+
if (interactionDateKey === todayDateKey) {
|
|
11410
|
+
promptCount += 1;
|
|
11411
|
+
} else if (interactionDateKey === previousDayDateKey) {
|
|
11412
|
+
previousPromptCount += 1;
|
|
11413
|
+
}
|
|
11414
|
+
}
|
|
11415
|
+
if (!interaction.usage || interactionDateKey !== todayDateKey) {
|
|
11416
|
+
continue;
|
|
11417
|
+
}
|
|
11418
|
+
const interactionDate = new Date(interaction.timestamp);
|
|
11419
|
+
if (!Number.isFinite(interactionDate.getTime())) {
|
|
11420
|
+
continue;
|
|
11421
|
+
}
|
|
11422
|
+
const hour = interactionDate.getHours();
|
|
11423
|
+
const bucket = (_a = hourlyUsage.get(hour)) != null ? _a : {
|
|
11424
|
+
agents: /* @__PURE__ */ new Map(),
|
|
11425
|
+
costUSD: 0,
|
|
11426
|
+
totalTokens: 0
|
|
11427
|
+
};
|
|
11428
|
+
const agentUsage = (_b = bucket.agents.get(platform)) != null ? _b : {
|
|
11429
|
+
costUSD: 0,
|
|
11430
|
+
totalTokens: 0
|
|
11431
|
+
};
|
|
11432
|
+
bucket.costUSD = roundCurrency(bucket.costUSD + interaction.usage.costUSD);
|
|
11433
|
+
bucket.totalTokens += interaction.usage.totalTokens;
|
|
11434
|
+
agentUsage.costUSD = roundCurrency(agentUsage.costUSD + interaction.usage.costUSD);
|
|
11435
|
+
agentUsage.totalTokens += interaction.usage.totalTokens;
|
|
11436
|
+
bucket.agents.set(platform, agentUsage);
|
|
11437
|
+
hourlyUsage.set(hour, bucket);
|
|
11438
|
+
}
|
|
10556
11439
|
}
|
|
11440
|
+
}
|
|
11441
|
+
const todayHourlyUsage = Array.from({ length: 24 }, (_, hour) => {
|
|
11442
|
+
var _a2, _b2, _c, _d, _e, _f;
|
|
11443
|
+
return {
|
|
11444
|
+
agents: Object.fromEntries((_b2 = (_a2 = hourlyUsage.get(hour)) == null ? void 0 : _a2.agents.entries()) != null ? _b2 : []),
|
|
11445
|
+
costUSD: (_d = (_c = hourlyUsage.get(hour)) == null ? void 0 : _c.costUSD) != null ? _d : 0,
|
|
11446
|
+
hour,
|
|
11447
|
+
label: `${String(hour).padStart(2, "0")}:00`,
|
|
11448
|
+
totalTokens: (_f = (_e = hourlyUsage.get(hour)) == null ? void 0 : _e.totalTokens) != null ? _f : 0
|
|
11449
|
+
};
|
|
10557
11450
|
});
|
|
10558
11451
|
return {
|
|
10559
|
-
|
|
10560
|
-
|
|
11452
|
+
previousPromptCount,
|
|
11453
|
+
previousSessionCount,
|
|
11454
|
+
promptCount,
|
|
11455
|
+
sessionCount,
|
|
11456
|
+
todayHourlyUsage
|
|
10561
11457
|
};
|
|
10562
11458
|
}
|
|
10563
|
-
function
|
|
10564
|
-
|
|
10565
|
-
|
|
10566
|
-
|
|
10567
|
-
|
|
10568
|
-
|
|
10569
|
-
inputTokens: interaction.usage.inputTokens,
|
|
10570
|
-
isFallbackModel: (_a = interaction.usage.isFallbackModel) != null ? _a : false,
|
|
10571
|
-
model: (_b = interaction.model) != null ? _b : session.model,
|
|
10572
|
-
outputTokens: interaction.usage.outputTokens,
|
|
10573
|
-
project: session.project,
|
|
10574
|
-
reasoningOutputTokens: interaction.usage.reasoningOutputTokens,
|
|
10575
|
-
repository: session.repository,
|
|
10576
|
-
sessionId: session.id,
|
|
10577
|
-
timestamp: interaction.timestamp,
|
|
10578
|
-
totalTokens: interaction.usage.totalTokens
|
|
10579
|
-
};
|
|
10580
|
-
})).sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
|
|
10581
|
-
}
|
|
10582
|
-
function hasBillableUsage(usage) {
|
|
10583
|
-
return usage.totalTokens > 0 || usage.costUSD > 0;
|
|
10584
|
-
}
|
|
10585
|
-
function collectSessionModels(sessions) {
|
|
10586
|
-
return uniqueItems(sessions.flatMap((session) => session.models)).sort((a, b) => a.localeCompare(b));
|
|
11459
|
+
function getDateKeyFromTimestamp(value) {
|
|
11460
|
+
if (!value) {
|
|
11461
|
+
return null;
|
|
11462
|
+
}
|
|
11463
|
+
const date = new Date(value);
|
|
11464
|
+
return Number.isFinite(date.getTime()) ? getDateKey(date) : null;
|
|
10587
11465
|
}
|
|
10588
|
-
function
|
|
10589
|
-
|
|
10590
|
-
|
|
11466
|
+
function buildEfficiencyMetrics(options) {
|
|
11467
|
+
const cacheHitRate = options.cachedInputTokens > 0 ? options.inputTokens / options.cachedInputTokens : 0;
|
|
11468
|
+
const reasoningShare = options.reasoningOutputTokens > 0 ? options.totalTokens / options.reasoningOutputTokens : 0;
|
|
11469
|
+
const outputShare = options.outputTokens > 0 ? options.totalTokens / options.outputTokens : 0;
|
|
11470
|
+
return [
|
|
11471
|
+
{
|
|
11472
|
+
detail: `${formatCompactNumber(options.cachedInputTokens)} cached input tokens`,
|
|
11473
|
+
label: "Cache Hit Rate",
|
|
11474
|
+
percent: cacheHitRate * 100,
|
|
11475
|
+
tone: "green",
|
|
11476
|
+
value: formatPercent(cacheHitRate)
|
|
11477
|
+
},
|
|
11478
|
+
{
|
|
11479
|
+
detail: `${formatCompactNumber(options.reasoningOutputTokens)} reasoning output tokens`,
|
|
11480
|
+
label: "Reasoning Token Share",
|
|
11481
|
+
percent: reasoningShare * 100,
|
|
11482
|
+
tone: "amber",
|
|
11483
|
+
value: formatPercent(reasoningShare)
|
|
11484
|
+
},
|
|
11485
|
+
{
|
|
11486
|
+
detail: `${formatCompactNumber(options.outputTokens)} output tokens`,
|
|
11487
|
+
label: "Output Token Share",
|
|
11488
|
+
percent: outputShare * 100,
|
|
11489
|
+
tone: "sky",
|
|
11490
|
+
value: formatPercent(outputShare)
|
|
11491
|
+
}
|
|
11492
|
+
];
|
|
10591
11493
|
}
|
|
10592
11494
|
|
|
10593
11495
|
var __defProp = Object.defineProperty;
|
|
@@ -10603,7 +11505,7 @@ class UsageDataRuntime {
|
|
|
10603
11505
|
bootstrap: null,
|
|
10604
11506
|
hydratedAt: 0,
|
|
10605
11507
|
projectCatalog: [],
|
|
10606
|
-
projectDetails:
|
|
11508
|
+
projectDetails: null,
|
|
10607
11509
|
refreshStartedAt: 0
|
|
10608
11510
|
});
|
|
10609
11511
|
__publicField(this, "initializePromise", null);
|
|
@@ -10618,7 +11520,6 @@ class UsageDataRuntime {
|
|
|
10618
11520
|
if (!this.initializePromise) {
|
|
10619
11521
|
this.initializePromise = this.hydrateFromRepository().finally(() => {
|
|
10620
11522
|
this.startWatcher();
|
|
10621
|
-
void this.refreshInBackground();
|
|
10622
11523
|
});
|
|
10623
11524
|
}
|
|
10624
11525
|
return this.initializePromise;
|
|
@@ -10634,7 +11535,7 @@ class UsageDataRuntime {
|
|
|
10634
11535
|
}
|
|
10635
11536
|
async getProjectCatalog() {
|
|
10636
11537
|
await this.initialize();
|
|
10637
|
-
if (this.state.projectCatalog.length === 0
|
|
11538
|
+
if (this.state.projectCatalog.length === 0) {
|
|
10638
11539
|
await this.refreshNow();
|
|
10639
11540
|
} else {
|
|
10640
11541
|
this.scheduleRefreshIfStale();
|
|
@@ -10646,12 +11547,18 @@ class UsageDataRuntime {
|
|
|
10646
11547
|
const bootstrap = await this.getBootstrap();
|
|
10647
11548
|
return (_a = bootstrap[platform]) != null ? _a : createEmptyLoadUsageResult();
|
|
10648
11549
|
}
|
|
11550
|
+
async getHomeDashboardModules() {
|
|
11551
|
+
return buildHomeDashboardModules(await this.getBootstrap(), this.repository.loadHomeDashboardTodayInsights());
|
|
11552
|
+
}
|
|
10649
11553
|
async getProjectDataModules(request) {
|
|
10650
11554
|
await this.initialize();
|
|
10651
11555
|
const projectLabel = (request.project || "").trim();
|
|
10652
11556
|
if (!projectLabel) {
|
|
10653
11557
|
throw new Error("Missing project name for project data request.");
|
|
10654
11558
|
}
|
|
11559
|
+
if (this.state.projectDetails === null) {
|
|
11560
|
+
this.state.projectDetails = this.repository.loadProjectDetails();
|
|
11561
|
+
}
|
|
10655
11562
|
const detail = this.state.projectDetails.get(projectLabel);
|
|
10656
11563
|
if (!detail) {
|
|
10657
11564
|
await this.refreshNow();
|
|
@@ -10672,10 +11579,8 @@ class UsageDataRuntime {
|
|
|
10672
11579
|
var _a, _b;
|
|
10673
11580
|
const bootstrap = this.repository.loadBootstrap();
|
|
10674
11581
|
const projectCatalog = this.repository.loadProjectCatalog();
|
|
10675
|
-
const projectDetails = this.repository.loadProjectDetails();
|
|
10676
11582
|
this.state.bootstrap = (_a = bootstrap == null ? void 0 : bootstrap.payload) != null ? _a : null;
|
|
10677
11583
|
this.state.projectCatalog = (_b = projectCatalog == null ? void 0 : projectCatalog.payload) != null ? _b : [];
|
|
10678
|
-
this.state.projectDetails = projectDetails;
|
|
10679
11584
|
this.state.hydratedAt = Math.max(
|
|
10680
11585
|
bootstrap ? Date.parse(bootstrap.updatedAt) : 0,
|
|
10681
11586
|
projectCatalog ? Date.parse(projectCatalog.updatedAt) : 0
|
|
@@ -10720,14 +11625,16 @@ class UsageDataRuntime {
|
|
|
10720
11625
|
),
|
|
10721
11626
|
version: this.config.version
|
|
10722
11627
|
};
|
|
10723
|
-
const projectDetails = this.state.projectDetails
|
|
11628
|
+
const projectDetails = this.state.projectDetails ? patchProjectDetails(this.state.projectDetails, indexed.removedProjects, indexed.affectedProjects, bootstrapByPlatform) : buildAllProjectDetails(bootstrapByPlatform);
|
|
10724
11629
|
const projectCatalog = buildProjectUsageCatalogItemsFromDetails(projectDetails.entries());
|
|
10725
11630
|
this.repository.saveBootstrap(bootstrap);
|
|
10726
11631
|
this.repository.saveProjectCatalog(projectCatalog);
|
|
10727
11632
|
this.repository.replaceProjectDetails(projectDetails);
|
|
10728
11633
|
this.state.bootstrap = bootstrap;
|
|
10729
11634
|
this.state.projectCatalog = projectCatalog;
|
|
10730
|
-
this.state.projectDetails
|
|
11635
|
+
if (this.state.projectDetails) {
|
|
11636
|
+
this.state.projectDetails = projectDetails;
|
|
11637
|
+
}
|
|
10731
11638
|
this.state.hydratedAt = Date.now();
|
|
10732
11639
|
}
|
|
10733
11640
|
dispose() {
|
|
@@ -11025,159 +11932,166 @@ const plugins = [
|
|
|
11025
11932
|
];
|
|
11026
11933
|
|
|
11027
11934
|
const assets = {
|
|
11028
|
-
"/favicon.ico": {
|
|
11029
|
-
"type": "image/vnd.microsoft.icon",
|
|
11030
|
-
"etag": "\"1083e-LfyFZ+1JmdianDqe/sQN2Ou0IzQ\"",
|
|
11031
|
-
"mtime": "2026-05-23T14:23:38.580Z",
|
|
11032
|
-
"size": 67646,
|
|
11033
|
-
"path": "../public/favicon.ico"
|
|
11034
|
-
},
|
|
11035
11935
|
"/logo.svg": {
|
|
11036
11936
|
"type": "image/svg+xml",
|
|
11037
11937
|
"etag": "\"1550-fwYFdULdJ83Qp0FjnnX31iQz9oI\"",
|
|
11038
|
-
"mtime": "2026-05-
|
|
11938
|
+
"mtime": "2026-05-26T08:31:48.218Z",
|
|
11039
11939
|
"size": 5456,
|
|
11040
11940
|
"path": "../public/logo.svg"
|
|
11041
11941
|
},
|
|
11042
11942
|
"/robots.txt": {
|
|
11043
11943
|
"type": "text/plain; charset=utf-8",
|
|
11044
11944
|
"etag": "\"18-j8OIsL9qGDmNZ+lHhp2tyH4XtaE\"",
|
|
11045
|
-
"mtime": "2026-05-
|
|
11945
|
+
"mtime": "2026-05-26T08:31:48.218Z",
|
|
11046
11946
|
"size": 24,
|
|
11047
11947
|
"path": "../public/robots.txt"
|
|
11048
11948
|
},
|
|
11049
|
-
"/_nuxt/
|
|
11949
|
+
"/_nuxt/37OOe3RF.js": {
|
|
11050
11950
|
"type": "text/javascript; charset=utf-8",
|
|
11051
|
-
"etag": "\"
|
|
11052
|
-
"mtime": "2026-05-
|
|
11053
|
-
"size":
|
|
11054
|
-
"path": "../public/_nuxt/
|
|
11951
|
+
"etag": "\"433-9g1fS7jC4SfhMOz/zYtzEkjj3l4\"",
|
|
11952
|
+
"mtime": "2026-05-26T08:31:48.215Z",
|
|
11953
|
+
"size": 1075,
|
|
11954
|
+
"path": "../public/_nuxt/37OOe3RF.js"
|
|
11055
11955
|
},
|
|
11056
|
-
"/
|
|
11057
|
-
"type": "
|
|
11058
|
-
"etag": "\"
|
|
11059
|
-
"mtime": "2026-05-
|
|
11060
|
-
"size":
|
|
11061
|
-
"path": "../public/
|
|
11956
|
+
"/favicon.ico": {
|
|
11957
|
+
"type": "image/vnd.microsoft.icon",
|
|
11958
|
+
"etag": "\"1083e-LfyFZ+1JmdianDqe/sQN2Ou0IzQ\"",
|
|
11959
|
+
"mtime": "2026-05-26T08:31:48.218Z",
|
|
11960
|
+
"size": 67646,
|
|
11961
|
+
"path": "../public/favicon.ico"
|
|
11062
11962
|
},
|
|
11063
|
-
"/_nuxt/
|
|
11963
|
+
"/_nuxt/65Ayv2XK.js": {
|
|
11064
11964
|
"type": "text/javascript; charset=utf-8",
|
|
11065
|
-
"etag": "\"
|
|
11066
|
-
"mtime": "2026-05-
|
|
11067
|
-
"size":
|
|
11068
|
-
"path": "../public/_nuxt/
|
|
11965
|
+
"etag": "\"bb0d-ldbgmGlpc1qx4bYEx4cXkSFSCg8\"",
|
|
11966
|
+
"mtime": "2026-05-26T08:31:48.215Z",
|
|
11967
|
+
"size": 47885,
|
|
11968
|
+
"path": "../public/_nuxt/65Ayv2XK.js"
|
|
11069
11969
|
},
|
|
11070
|
-
"/_nuxt/
|
|
11970
|
+
"/_nuxt/BOWwkrCY.js": {
|
|
11071
11971
|
"type": "text/javascript; charset=utf-8",
|
|
11072
|
-
"etag": "\"
|
|
11073
|
-
"mtime": "2026-05-
|
|
11074
|
-
"size":
|
|
11075
|
-
"path": "../public/_nuxt/
|
|
11972
|
+
"etag": "\"540a-Q/6WhDpXkujbyVqTxKp+MDIjyN8\"",
|
|
11973
|
+
"mtime": "2026-05-26T08:31:48.215Z",
|
|
11974
|
+
"size": 21514,
|
|
11975
|
+
"path": "../public/_nuxt/BOWwkrCY.js"
|
|
11076
11976
|
},
|
|
11077
|
-
"/_nuxt/
|
|
11977
|
+
"/_nuxt/D7qEPtpx.js": {
|
|
11078
11978
|
"type": "text/javascript; charset=utf-8",
|
|
11079
|
-
"etag": "\"eb4-
|
|
11080
|
-
"mtime": "2026-05-
|
|
11979
|
+
"etag": "\"eb4-cYfHtGVwvBnjUla1c7r6p8WQ+fU\"",
|
|
11980
|
+
"mtime": "2026-05-26T08:31:48.215Z",
|
|
11081
11981
|
"size": 3764,
|
|
11082
|
-
"path": "../public/_nuxt/
|
|
11982
|
+
"path": "../public/_nuxt/D7qEPtpx.js"
|
|
11983
|
+
},
|
|
11984
|
+
"/_nuxt/D9-Yw1TR.js": {
|
|
11985
|
+
"type": "text/javascript; charset=utf-8",
|
|
11986
|
+
"etag": "\"42dc-z2VCBVgr0YDv874MuLF5LmD+w6g\"",
|
|
11987
|
+
"mtime": "2026-05-26T08:31:48.215Z",
|
|
11988
|
+
"size": 17116,
|
|
11989
|
+
"path": "../public/_nuxt/D9-Yw1TR.js"
|
|
11990
|
+
},
|
|
11991
|
+
"/_nuxt/DF2WsXH3.js": {
|
|
11992
|
+
"type": "text/javascript; charset=utf-8",
|
|
11993
|
+
"etag": "\"101-2rfNy5z/IaUQM5ONN45oT3dPyOw\"",
|
|
11994
|
+
"mtime": "2026-05-26T08:31:48.215Z",
|
|
11995
|
+
"size": 257,
|
|
11996
|
+
"path": "../public/_nuxt/DF2WsXH3.js"
|
|
11997
|
+
},
|
|
11998
|
+
"/_nuxt/C0GhHHgI.js": {
|
|
11999
|
+
"type": "text/javascript; charset=utf-8",
|
|
12000
|
+
"etag": "\"cf91-HNazofOinHCfSBf403LLacaEnfc\"",
|
|
12001
|
+
"mtime": "2026-05-26T08:31:48.215Z",
|
|
12002
|
+
"size": 53137,
|
|
12003
|
+
"path": "../public/_nuxt/C0GhHHgI.js"
|
|
11083
12004
|
},
|
|
11084
|
-
"/_nuxt/
|
|
12005
|
+
"/_nuxt/DXWxIyGU.js": {
|
|
11085
12006
|
"type": "text/javascript; charset=utf-8",
|
|
11086
|
-
"etag": "\"
|
|
11087
|
-
"mtime": "2026-05-
|
|
11088
|
-
"size":
|
|
11089
|
-
"path": "../public/_nuxt/
|
|
12007
|
+
"etag": "\"d7b-TUo4s2vJwQ7SvlmJq8Lc5JpszPo\"",
|
|
12008
|
+
"mtime": "2026-05-26T08:31:48.216Z",
|
|
12009
|
+
"size": 3451,
|
|
12010
|
+
"path": "../public/_nuxt/DXWxIyGU.js"
|
|
11090
12011
|
},
|
|
11091
|
-
"/_nuxt/
|
|
12012
|
+
"/_nuxt/De8DvPWL.js": {
|
|
11092
12013
|
"type": "text/javascript; charset=utf-8",
|
|
11093
|
-
"etag": "\"
|
|
11094
|
-
"mtime": "2026-05-
|
|
11095
|
-
"size":
|
|
11096
|
-
"path": "../public/_nuxt/
|
|
12014
|
+
"etag": "\"14f9-ru/D4lCOWqCP3lvQM3EWGPMYRaw\"",
|
|
12015
|
+
"mtime": "2026-05-26T08:31:48.215Z",
|
|
12016
|
+
"size": 5369,
|
|
12017
|
+
"path": "../public/_nuxt/De8DvPWL.js"
|
|
11097
12018
|
},
|
|
11098
|
-
"/_nuxt/
|
|
12019
|
+
"/_nuxt/DKaPq50Z.js": {
|
|
11099
12020
|
"type": "text/javascript; charset=utf-8",
|
|
11100
|
-
"etag": "\"
|
|
11101
|
-
"mtime": "2026-05-
|
|
11102
|
-
"size":
|
|
11103
|
-
"path": "../public/_nuxt/
|
|
12021
|
+
"etag": "\"f34c-URgC7Dz0Xf+JUUuL4yo1mSHnYmQ\"",
|
|
12022
|
+
"mtime": "2026-05-26T08:31:48.216Z",
|
|
12023
|
+
"size": 62284,
|
|
12024
|
+
"path": "../public/_nuxt/DKaPq50Z.js"
|
|
11104
12025
|
},
|
|
11105
|
-
"/_nuxt/
|
|
12026
|
+
"/_nuxt/DxvuOJRP.js": {
|
|
11106
12027
|
"type": "text/javascript; charset=utf-8",
|
|
11107
|
-
"etag": "\"
|
|
11108
|
-
"mtime": "2026-05-
|
|
11109
|
-
"size":
|
|
11110
|
-
"path": "../public/_nuxt/
|
|
12028
|
+
"etag": "\"10890-8PgC64ZUxoVro0//XJbLva3lqK0\"",
|
|
12029
|
+
"mtime": "2026-05-26T08:31:48.216Z",
|
|
12030
|
+
"size": 67728,
|
|
12031
|
+
"path": "../public/_nuxt/DxvuOJRP.js"
|
|
11111
12032
|
},
|
|
11112
|
-
"/_nuxt/
|
|
12033
|
+
"/_nuxt/DgMMKsPE.js": {
|
|
11113
12034
|
"type": "text/javascript; charset=utf-8",
|
|
11114
|
-
"etag": "\"
|
|
11115
|
-
"mtime": "2026-05-
|
|
11116
|
-
"size":
|
|
11117
|
-
"path": "../public/_nuxt/
|
|
12035
|
+
"etag": "\"35763-ZIXCcb7yuHkNvDqXH2EEhwlcyV4\"",
|
|
12036
|
+
"mtime": "2026-05-26T08:31:48.216Z",
|
|
12037
|
+
"size": 218979,
|
|
12038
|
+
"path": "../public/_nuxt/DgMMKsPE.js"
|
|
11118
12039
|
},
|
|
11119
|
-
"/_nuxt/
|
|
12040
|
+
"/_nuxt/Jp5cgQZi.js": {
|
|
11120
12041
|
"type": "text/javascript; charset=utf-8",
|
|
11121
|
-
"etag": "\"
|
|
11122
|
-
"mtime": "2026-05-
|
|
11123
|
-
"size":
|
|
11124
|
-
"path": "../public/_nuxt/
|
|
12042
|
+
"etag": "\"3c6da-89AEgPN5OI/3SCYBdFqSxRLSihE\"",
|
|
12043
|
+
"mtime": "2026-05-26T08:31:48.216Z",
|
|
12044
|
+
"size": 247514,
|
|
12045
|
+
"path": "../public/_nuxt/Jp5cgQZi.js"
|
|
11125
12046
|
},
|
|
11126
12047
|
"/_nuxt/error-404.CFBEg71j.css": {
|
|
11127
12048
|
"type": "text/css; charset=utf-8",
|
|
11128
12049
|
"etag": "\"97e-GvhaEAryQvrSXyDcP4RiHXzYb5o\"",
|
|
11129
|
-
"mtime": "2026-05-
|
|
12050
|
+
"mtime": "2026-05-26T08:31:48.216Z",
|
|
11130
12051
|
"size": 2430,
|
|
11131
12052
|
"path": "../public/_nuxt/error-404.CFBEg71j.css"
|
|
11132
12053
|
},
|
|
11133
12054
|
"/_nuxt/error-500.BqCnH31G.css": {
|
|
11134
12055
|
"type": "text/css; charset=utf-8",
|
|
11135
12056
|
"etag": "\"773-Tpf6lA6A2FEDtjLyWUXKolBZ3hM\"",
|
|
11136
|
-
"mtime": "2026-05-
|
|
12057
|
+
"mtime": "2026-05-26T08:31:48.216Z",
|
|
11137
12058
|
"size": 1907,
|
|
11138
12059
|
"path": "../public/_nuxt/error-500.BqCnH31G.css"
|
|
11139
12060
|
},
|
|
11140
|
-
"/_nuxt/
|
|
12061
|
+
"/_nuxt/qXgLTL_3.js": {
|
|
11141
12062
|
"type": "text/javascript; charset=utf-8",
|
|
11142
|
-
"etag": "\"
|
|
11143
|
-
"mtime": "2026-05-
|
|
11144
|
-
"size":
|
|
11145
|
-
"path": "../public/_nuxt/
|
|
12063
|
+
"etag": "\"993e-F6dGXZ77Rf6Afn6RLLvwifZFe5Q\"",
|
|
12064
|
+
"mtime": "2026-05-26T08:31:48.216Z",
|
|
12065
|
+
"size": 39230,
|
|
12066
|
+
"path": "../public/_nuxt/qXgLTL_3.js"
|
|
11146
12067
|
},
|
|
11147
|
-
"/_nuxt/
|
|
12068
|
+
"/_nuxt/y6mAKUDU.js": {
|
|
11148
12069
|
"type": "text/javascript; charset=utf-8",
|
|
11149
|
-
"etag": "\"
|
|
11150
|
-
"mtime": "2026-05-
|
|
11151
|
-
"size":
|
|
11152
|
-
"path": "../public/_nuxt/
|
|
11153
|
-
},
|
|
11154
|
-
"/_nuxt/entry.vHfFzkyD.css": {
|
|
11155
|
-
"type": "text/css; charset=utf-8",
|
|
11156
|
-
"etag": "\"1d217-AX0vUIWFE2kL17zPKjOPcQBxadQ\"",
|
|
11157
|
-
"mtime": "2026-05-23T14:23:38.578Z",
|
|
11158
|
-
"size": 119319,
|
|
11159
|
-
"path": "../public/_nuxt/entry.vHfFzkyD.css"
|
|
12070
|
+
"etag": "\"2c57-7lVqV+qTY/Dqb4M0PdxYAItocQw\"",
|
|
12071
|
+
"mtime": "2026-05-26T08:31:48.216Z",
|
|
12072
|
+
"size": 11351,
|
|
12073
|
+
"path": "../public/_nuxt/y6mAKUDU.js"
|
|
11160
12074
|
},
|
|
11161
12075
|
"/_nuxt/builds/latest.json": {
|
|
11162
12076
|
"type": "application/json",
|
|
11163
|
-
"etag": "\"47-
|
|
11164
|
-
"mtime": "2026-05-
|
|
12077
|
+
"etag": "\"47-yneWhd0H1nYqEdMbDKqzhQJ6sxE\"",
|
|
12078
|
+
"mtime": "2026-05-26T08:31:48.213Z",
|
|
11165
12079
|
"size": 71,
|
|
11166
12080
|
"path": "../public/_nuxt/builds/latest.json"
|
|
11167
12081
|
},
|
|
11168
|
-
"/_nuxt/builds/meta/
|
|
12082
|
+
"/_nuxt/builds/meta/7ce9c611-6071-4cbd-8926-1e53d9ef21bd.json": {
|
|
11169
12083
|
"type": "application/json",
|
|
11170
|
-
"etag": "\"58-
|
|
11171
|
-
"mtime": "2026-05-
|
|
12084
|
+
"etag": "\"58-ozcqeghbP4BbYZVRtP6bwTCHhN8\"",
|
|
12085
|
+
"mtime": "2026-05-26T08:31:48.211Z",
|
|
11172
12086
|
"size": 88,
|
|
11173
|
-
"path": "../public/_nuxt/builds/meta/
|
|
12087
|
+
"path": "../public/_nuxt/builds/meta/7ce9c611-6071-4cbd-8926-1e53d9ef21bd.json"
|
|
11174
12088
|
},
|
|
11175
|
-
"/_nuxt/
|
|
11176
|
-
"type": "text/
|
|
11177
|
-
"etag": "\"
|
|
11178
|
-
"mtime": "2026-05-
|
|
11179
|
-
"size":
|
|
11180
|
-
"path": "../public/_nuxt/
|
|
12089
|
+
"/_nuxt/entry.DnkKc-6G.css": {
|
|
12090
|
+
"type": "text/css; charset=utf-8",
|
|
12091
|
+
"etag": "\"1d8a6-KK9a3JMzAwbSGw5SnlSiODNKxHg\"",
|
|
12092
|
+
"mtime": "2026-05-26T08:31:48.216Z",
|
|
12093
|
+
"size": 120998,
|
|
12094
|
+
"path": "../public/_nuxt/entry.DnkKc-6G.css"
|
|
11181
12095
|
}
|
|
11182
12096
|
};
|
|
11183
12097
|
|
|
@@ -11673,9 +12587,13 @@ const inlineConfig = {
|
|
|
11673
12587
|
"wi",
|
|
11674
12588
|
"wpf",
|
|
11675
12589
|
"zmdi",
|
|
11676
|
-
"zondicons"
|
|
12590
|
+
"zondicons",
|
|
12591
|
+
"ai"
|
|
11677
12592
|
],
|
|
11678
|
-
"fetchTimeout": 1500
|
|
12593
|
+
"fetchTimeout": 1500,
|
|
12594
|
+
"customCollections": [
|
|
12595
|
+
"ai"
|
|
12596
|
+
]
|
|
11679
12597
|
}
|
|
11680
12598
|
};
|
|
11681
12599
|
|
|
@@ -11701,239 +12619,110 @@ function _deepFreeze(object) {
|
|
|
11701
12619
|
return Object.freeze(object);
|
|
11702
12620
|
}
|
|
11703
12621
|
|
|
11704
|
-
|
|
11705
|
-
|
|
11706
|
-
|
|
11707
|
-
|
|
11708
|
-
|
|
11709
|
-
|
|
11710
|
-
|
|
11711
|
-
PROJECT_USAGE_PLATFORMS.flatMap((platform) => getPlatformDashboard(dashboardsByPlatform, platform).monthlyModelUsage)
|
|
11712
|
-
);
|
|
11713
|
-
const projectUsage = buildProjectUsage(sessionUsage);
|
|
11714
|
-
const totalCost = dailyTokenUsage.reduce((sum, item) => sum + item.costUSD, 0);
|
|
11715
|
-
const totalTokens = dailyTokenUsage.reduce((sum, item) => sum + item.totalTokens, 0);
|
|
11716
|
-
const inputTokens = dailyTokenUsage.reduce((sum, item) => sum + item.inputTokens, 0);
|
|
11717
|
-
const cachedInputTokens = dailyTokenUsage.reduce((sum, item) => sum + item.cachedInputTokens, 0);
|
|
11718
|
-
const outputTokens = dailyTokenUsage.reduce((sum, item) => sum + item.outputTokens, 0);
|
|
11719
|
-
const reasoningOutputTokens = dailyTokenUsage.reduce((sum, item) => sum + item.reasoningOutputTokens, 0);
|
|
11720
|
-
const totalSessions = sessionUsage.length;
|
|
11721
|
-
const todayDateKey = getDateKey(/* @__PURE__ */ new Date());
|
|
11722
|
-
const previousDayDateKey = getPreviousDateKey(todayDateKey);
|
|
11723
|
-
const todayDailyUsage = dailyTokenUsage.find((item) => getDateKeyFromLabel(item.date) === todayDateKey);
|
|
11724
|
-
const previousDayDailyUsage = dailyTokenUsage.find((item) => getDateKeyFromLabel(item.date) === previousDayDateKey);
|
|
11725
|
-
const costGrowthTrend = buildGrowthTrend(
|
|
11726
|
-
(_a = todayDailyUsage == null ? void 0 : todayDailyUsage.costUSD) != null ? _a : 0,
|
|
11727
|
-
(_b = previousDayDailyUsage == null ? void 0 : previousDayDailyUsage.costUSD) != null ? _b : 0,
|
|
11728
|
-
formatCurrency
|
|
11729
|
-
);
|
|
11730
|
-
const tokenGrowthTrend = buildGrowthTrend(
|
|
11731
|
-
(_c = todayDailyUsage == null ? void 0 : todayDailyUsage.totalTokens) != null ? _c : 0,
|
|
11732
|
-
(_d = previousDayDailyUsage == null ? void 0 : previousDayDailyUsage.totalTokens) != null ? _d : 0,
|
|
11733
|
-
formatCompactNumber
|
|
11734
|
-
);
|
|
11735
|
-
const efficiencyMetrics = buildEfficiencyMetrics({
|
|
11736
|
-
cachedInputTokens,
|
|
11737
|
-
inputTokens,
|
|
11738
|
-
outputTokens,
|
|
11739
|
-
reasoningOutputTokens,
|
|
11740
|
-
totalTokens
|
|
11741
|
-
});
|
|
11742
|
-
return {
|
|
11743
|
-
dailyTokenUsage,
|
|
11744
|
-
efficiencyMetrics,
|
|
11745
|
-
hotProjects: projectUsage,
|
|
11746
|
-
modelUsage: monthlyModelUsage,
|
|
11747
|
-
overviewCards: buildHomeOverviewCards({
|
|
11748
|
-
cachedInputTokens,
|
|
11749
|
-
costGrowthTrend,
|
|
11750
|
-
inputTokens,
|
|
11751
|
-
tokenGrowthTrend,
|
|
11752
|
-
totalCost,
|
|
11753
|
-
totalSessions,
|
|
11754
|
-
totalTokens
|
|
11755
|
-
}),
|
|
11756
|
-
sessionAnalysis: {
|
|
11757
|
-
items: sessionUsage,
|
|
11758
|
-
totalSessions
|
|
11759
|
-
}
|
|
11760
|
-
};
|
|
11761
|
-
}
|
|
11762
|
-
function getPlatformDashboard(dashboardsByPlatform, platform) {
|
|
11763
|
-
return dashboardsByPlatform[platform];
|
|
11764
|
-
}
|
|
11765
|
-
function buildSessionUsage(dashboardsByPlatform) {
|
|
11766
|
-
return PROJECT_USAGE_PLATFORMS.flatMap((platform) => getPlatformDashboard(dashboardsByPlatform, platform).sessionUsage.map((session) => ({
|
|
11767
|
-
...session,
|
|
11768
|
-
id: `${platform}:${session.id}`,
|
|
11769
|
-
sessionId: `${platform}:${session.sessionId}`
|
|
11770
|
-
}))).sort((a, b) => Date.parse(b.startedAt) - Date.parse(a.startedAt));
|
|
11771
|
-
}
|
|
11772
|
-
function buildHomeOverviewCards(options) {
|
|
11773
|
-
return [
|
|
11774
|
-
{
|
|
11775
|
-
detail: `${formatCurrency(options.totalCost)} total spend across all tools`,
|
|
11776
|
-
icon: "lucide:wallet",
|
|
11777
|
-
name: "Total Spend",
|
|
11778
|
-
trend: options.costGrowthTrend.trend,
|
|
11779
|
-
trendTone: options.costGrowthTrend.trendTone,
|
|
11780
|
-
value: formatCurrency(options.totalCost)
|
|
11781
|
-
},
|
|
11782
|
-
{
|
|
11783
|
-
detail: `${formatNumber(options.totalTokens)} total tokens across all tools`,
|
|
11784
|
-
icon: "solar:cpu-line-duotone",
|
|
11785
|
-
name: "Token Usage",
|
|
11786
|
-
trend: options.tokenGrowthTrend.trend,
|
|
11787
|
-
trendTone: options.tokenGrowthTrend.trendTone,
|
|
11788
|
-
value: formatCompactNumber(options.totalTokens)
|
|
11789
|
-
},
|
|
11790
|
-
{
|
|
11791
|
-
detail: `${formatNumber(options.cachedInputTokens)} of ${formatNumber(options.inputTokens)} input tokens were served from cache`,
|
|
11792
|
-
icon: "lucide:database-zap",
|
|
11793
|
-
name: "Cache Hit Rate",
|
|
11794
|
-
trend: `${formatCompactNumber(options.cachedInputTokens)} cached`,
|
|
11795
|
-
trendTone: "neutral",
|
|
11796
|
-
value: formatPercent(options.inputTokens > 0 ? options.cachedInputTokens / options.inputTokens : 0)
|
|
11797
|
-
},
|
|
11798
|
-
{
|
|
11799
|
-
detail: `${formatCurrency(options.totalCost)} across ${formatNumber(options.totalSessions)} sessions`,
|
|
11800
|
-
icon: "lucide:receipt-text",
|
|
11801
|
-
name: "Avg Session Cost",
|
|
11802
|
-
trend: "across all tools",
|
|
11803
|
-
trendTone: "neutral",
|
|
11804
|
-
value: formatCurrency(options.totalSessions > 0 ? options.totalCost / options.totalSessions : 0)
|
|
11805
|
-
}
|
|
11806
|
-
];
|
|
11807
|
-
}
|
|
11808
|
-
function buildEfficiencyMetrics(options) {
|
|
11809
|
-
const cacheHitRate = safeRatio(options.cachedInputTokens, options.inputTokens);
|
|
11810
|
-
const reasoningShare = safeRatio(options.reasoningOutputTokens, options.totalTokens);
|
|
11811
|
-
const outputShare = safeRatio(options.outputTokens, options.totalTokens);
|
|
11812
|
-
return [
|
|
11813
|
-
{
|
|
11814
|
-
detail: `${formatCompactNumber(options.cachedInputTokens)} cached input tokens`,
|
|
11815
|
-
label: "Cache Hit Rate",
|
|
11816
|
-
percent: cacheHitRate * 100,
|
|
11817
|
-
tone: "green",
|
|
11818
|
-
value: formatPercent(cacheHitRate)
|
|
11819
|
-
},
|
|
11820
|
-
{
|
|
11821
|
-
detail: `${formatCompactNumber(options.reasoningOutputTokens)} reasoning output tokens`,
|
|
11822
|
-
label: "Reasoning Token Share",
|
|
11823
|
-
percent: reasoningShare * 100,
|
|
11824
|
-
tone: "amber",
|
|
11825
|
-
value: formatPercent(reasoningShare)
|
|
11826
|
-
},
|
|
11827
|
-
{
|
|
11828
|
-
detail: `${formatCompactNumber(options.outputTokens)} output tokens`,
|
|
11829
|
-
label: "Output Token Share",
|
|
11830
|
-
percent: outputShare * 100,
|
|
11831
|
-
tone: "sky",
|
|
11832
|
-
value: formatPercent(outputShare)
|
|
11833
|
-
}
|
|
11834
|
-
];
|
|
11835
|
-
}
|
|
11836
|
-
function safeRatio(numerator, denominator) {
|
|
11837
|
-
return denominator > 0 ? numerator / denominator : 0;
|
|
11838
|
-
}
|
|
12622
|
+
const ANALYSIS_AGENT_TOKEN_TYPES = ["day", "week", "month", "session"];
|
|
12623
|
+
const ANALYSIS_AGENT_TOKEN_ROW_KEYS = {
|
|
12624
|
+
day: "dailyRows",
|
|
12625
|
+
month: "monthlyRows",
|
|
12626
|
+
session: "sessionRows",
|
|
12627
|
+
week: "weeklyRows"
|
|
12628
|
+
};
|
|
11839
12629
|
|
|
11840
12630
|
const PROJECT_USAGE_PLATFORM_META = {
|
|
11841
12631
|
amp: {
|
|
11842
|
-
aiIcon: "amp",
|
|
12632
|
+
aiIcon: "ai:amp",
|
|
11843
12633
|
color: "#f34e3f",
|
|
11844
12634
|
label: "Amp",
|
|
11845
12635
|
slug: "amp"
|
|
11846
12636
|
},
|
|
11847
12637
|
claudeCode: {
|
|
11848
|
-
aiIcon: "
|
|
12638
|
+
aiIcon: "ai:claude-code",
|
|
11849
12639
|
color: "#d97757",
|
|
11850
12640
|
label: "Claude Code",
|
|
11851
12641
|
slug: "claude_code"
|
|
11852
12642
|
},
|
|
11853
12643
|
codebuff: {
|
|
11854
|
-
aiIcon: "codebuff",
|
|
12644
|
+
aiIcon: "ai:codebuff",
|
|
11855
12645
|
color: "#14b8a6",
|
|
11856
12646
|
label: "Codebuff",
|
|
11857
12647
|
slug: "codebuff"
|
|
11858
12648
|
},
|
|
11859
12649
|
codex: {
|
|
11860
|
-
aiIcon: "codex",
|
|
12650
|
+
aiIcon: "ai:codex",
|
|
11861
12651
|
color: "#111827",
|
|
11862
12652
|
label: "Codex",
|
|
11863
12653
|
slug: "codex"
|
|
11864
12654
|
},
|
|
11865
12655
|
copilot: {
|
|
11866
|
-
aiIcon: "copilot",
|
|
12656
|
+
aiIcon: "ai:copilot",
|
|
11867
12657
|
color: "#0f766e",
|
|
11868
12658
|
label: "GitHub Copilot",
|
|
11869
12659
|
slug: "copilot"
|
|
11870
12660
|
},
|
|
11871
12661
|
droid: {
|
|
11872
|
-
aiIcon: "droid",
|
|
12662
|
+
aiIcon: "ai:droid",
|
|
11873
12663
|
color: "#06b6d4",
|
|
11874
12664
|
label: "Droid",
|
|
11875
12665
|
slug: "droid"
|
|
11876
12666
|
},
|
|
11877
12667
|
gemini: {
|
|
11878
|
-
aiIcon: "gemini",
|
|
12668
|
+
aiIcon: "ai:gemini",
|
|
11879
12669
|
color: "#0ea5e9",
|
|
11880
12670
|
label: "Gemini",
|
|
11881
12671
|
slug: "gemini"
|
|
11882
12672
|
},
|
|
11883
12673
|
goose: {
|
|
11884
|
-
aiIcon: "goose",
|
|
12674
|
+
aiIcon: "ai:goose",
|
|
11885
12675
|
color: "#22c55e",
|
|
11886
12676
|
label: "Goose",
|
|
11887
12677
|
slug: "goose"
|
|
11888
12678
|
},
|
|
11889
12679
|
hermes: {
|
|
11890
|
-
aiIcon: "
|
|
12680
|
+
aiIcon: "ai:hermesagent",
|
|
11891
12681
|
color: "#8b5cf6",
|
|
11892
12682
|
label: "Hermes",
|
|
11893
12683
|
slug: "hermes"
|
|
11894
12684
|
},
|
|
11895
12685
|
kilo: {
|
|
11896
|
-
aiIcon: "kilo",
|
|
12686
|
+
aiIcon: "ai:kilo",
|
|
11897
12687
|
color: "#f97316",
|
|
11898
12688
|
label: "Kilo",
|
|
11899
12689
|
slug: "kilo"
|
|
11900
12690
|
},
|
|
11901
12691
|
kimi: {
|
|
11902
|
-
aiIcon: "
|
|
12692
|
+
aiIcon: "ai:kimi",
|
|
11903
12693
|
color: "#2563eb",
|
|
11904
12694
|
label: "Kimi",
|
|
11905
12695
|
slug: "kimi"
|
|
11906
12696
|
},
|
|
11907
12697
|
openclaw: {
|
|
11908
|
-
aiIcon: "openclaw",
|
|
12698
|
+
aiIcon: "ai:openclaw",
|
|
11909
12699
|
color: "#ec4899",
|
|
11910
12700
|
label: "OpenClaw",
|
|
11911
12701
|
slug: "openclaw"
|
|
11912
12702
|
},
|
|
11913
12703
|
opencode: {
|
|
11914
|
-
aiIcon: "
|
|
12704
|
+
aiIcon: "ai:open-code",
|
|
11915
12705
|
color: "#4f46e5",
|
|
11916
12706
|
label: "OpenCode",
|
|
11917
12707
|
slug: "opencode"
|
|
11918
12708
|
},
|
|
11919
12709
|
pi: {
|
|
11920
|
-
aiIcon: "pi",
|
|
12710
|
+
aiIcon: "ai:pi",
|
|
11921
12711
|
color: "#a855f7",
|
|
11922
12712
|
label: "Pi",
|
|
11923
12713
|
slug: "pi"
|
|
11924
12714
|
},
|
|
11925
12715
|
qwen: {
|
|
11926
|
-
aiIcon: "
|
|
12716
|
+
aiIcon: "ai:qwen",
|
|
11927
12717
|
color: "#623ae7",
|
|
11928
12718
|
label: "Qwen",
|
|
11929
12719
|
slug: "qwen"
|
|
11930
12720
|
}
|
|
11931
12721
|
};
|
|
11932
|
-
const
|
|
12722
|
+
const platformBySlug = new Map(PROJECT_USAGE_PLATFORMS.map((platform) => [
|
|
11933
12723
|
PROJECT_USAGE_PLATFORM_META[platform].slug,
|
|
11934
12724
|
platform
|
|
11935
|
-
]);
|
|
11936
|
-
const platformBySlug = new Map(platformSlugEntries);
|
|
12725
|
+
]));
|
|
11937
12726
|
function resolveProjectUsagePlatform(value) {
|
|
11938
12727
|
var _a;
|
|
11939
12728
|
const normalizedValue = value == null ? void 0 : value.trim();
|
|
@@ -11946,14 +12735,6 @@ function resolveProjectUsagePlatform(value) {
|
|
|
11946
12735
|
return (_a = platformBySlug.get(normalizedValue)) != null ? _a : null;
|
|
11947
12736
|
}
|
|
11948
12737
|
|
|
11949
|
-
const ANALYSIS_AGENT_TOKEN_TYPES = ["day", "week", "month", "session"];
|
|
11950
|
-
const ANALYSIS_AGENT_TOKEN_ROW_KEYS = {
|
|
11951
|
-
day: "dailyRows",
|
|
11952
|
-
month: "monthlyRows",
|
|
11953
|
-
session: "sessionRows",
|
|
11954
|
-
week: "weeklyRows"
|
|
11955
|
-
};
|
|
11956
|
-
|
|
11957
12738
|
function getAnalysisRuntime(event) {
|
|
11958
12739
|
const runtimeConfig = useRuntimeConfig(event);
|
|
11959
12740
|
const config = resolveConfig(runtimeConfig.public);
|
|
@@ -12020,7 +12801,7 @@ function defineRequiredAgentAnalysisHandler(select) {
|
|
|
12020
12801
|
});
|
|
12021
12802
|
}
|
|
12022
12803
|
async function getHomeAnalysisModules(event) {
|
|
12023
|
-
return
|
|
12804
|
+
return getAnalysisRuntime(event).getHomeDashboardModules();
|
|
12024
12805
|
}
|
|
12025
12806
|
function normalizeQueryString(value) {
|
|
12026
12807
|
if (Array.isArray(value)) {
|
|
@@ -12096,6 +12877,7 @@ const _lazy_NXGH0G = () => import('../routes/api/analysis/overview-cards.json.mj
|
|
|
12096
12877
|
const _lazy_FZJ5Wh = () => import('../routes/api/analysis/session.json.mjs');
|
|
12097
12878
|
const _lazy_k5j8NN = () => import('../routes/api/analysis/token.json.mjs');
|
|
12098
12879
|
const _lazy_wkSLy3 = () => import('../routes/api/analysis/token/daily.json.mjs');
|
|
12880
|
+
const _lazy_Vzep2h = () => import('../routes/api/analysis/token/today-hourly.json.mjs');
|
|
12099
12881
|
const _lazy_x_4o7G = () => import('../routes/api/payload.json.mjs');
|
|
12100
12882
|
const _lazy_slsjW6 = () => import('../routes/api/projects/_project/modules.get.mjs');
|
|
12101
12883
|
const _lazy_K00scR = () => import('../routes/api/projects/catalog.get.mjs');
|
|
@@ -12113,6 +12895,7 @@ const handlers = [
|
|
|
12113
12895
|
{ route: '/api/analysis/session.json', handler: _lazy_FZJ5Wh, lazy: true, middleware: false, method: undefined },
|
|
12114
12896
|
{ route: '/api/analysis/token.json', handler: _lazy_k5j8NN, lazy: true, middleware: false, method: undefined },
|
|
12115
12897
|
{ route: '/api/analysis/token/daily.json', handler: _lazy_wkSLy3, lazy: true, middleware: false, method: undefined },
|
|
12898
|
+
{ route: '/api/analysis/token/today-hourly.json', handler: _lazy_Vzep2h, lazy: true, middleware: false, method: undefined },
|
|
12116
12899
|
{ route: '/api/payload.json', handler: _lazy_x_4o7G, lazy: true, middleware: false, method: undefined },
|
|
12117
12900
|
{ route: '/api/projects/:project/modules', handler: _lazy_slsjW6, lazy: true, middleware: false, method: "get" },
|
|
12118
12901
|
{ route: '/api/projects/catalog', handler: _lazy_K00scR, lazy: true, middleware: false, method: "get" },
|
|
@@ -12270,4 +13053,4 @@ const websocket = nitroApp.h3App.websocket ;
|
|
|
12270
13053
|
const handler = listener;
|
|
12271
13054
|
trapUnhandledNodeErrors();
|
|
12272
13055
|
|
|
12273
|
-
export { ANALYSIS_AGENT_TOKEN_ROW_KEYS as A, defineHomeAnalysisHandler as a, defineScopedAnalysisHandler as b,
|
|
13056
|
+
export { ANALYSIS_AGENT_TOKEN_ROW_KEYS as A, websocket as B, defineHomeAnalysisHandler as a, defineScopedAnalysisHandler as b, buildOverviewCardsWithTodayTokenBreakdown as c, defineRequiredAgentAnalysisHandler as d, defineEventHandler as e, getUsageDataRuntime as f, getRequiredAnalysisAgentTokenType as g, getRouterParam as h, getQuery as i, normalizeStringList as j, defineWebSocketHandler as k, buildAssetsURL as l, getResponseStatusText as m, normalizeStringValue as n, getResponseStatus as o, defineRenderHandler as p, publicAssetsURL as q, resolveConfig as r, createError$1 as s, destr as t, useRuntimeConfig as u, getRouteRules as v, joinURL as w, useNitroApp as x, handler as y, listener as z };
|