tokentracker-cli 1.5.1 → 1.5.2
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/dashboard/dist/assets/{AchievementBadge-mB7HZSGE.js → AchievementBadge-B5kmt0VD.js} +1 -1
- package/dashboard/dist/assets/{AchievementsPage-DLzeq_eo.js → AchievementsPage-C0FlkOo0.js} +2 -2
- package/dashboard/dist/assets/{AchievementsSection-DrXQyDns.js → AchievementsSection-CRcp80Pp.js} +1 -1
- package/dashboard/dist/assets/{BadgeDetailModal-WrgKRybi.js → BadgeDetailModal-DAFjGbKW.js} +1 -1
- package/dashboard/dist/assets/{BotAnimated-DFRaixVK.js → BotAnimated-CO0bbimB.js} +1 -1
- package/dashboard/dist/assets/{Card-bFq2tlO8.js → Card-Xhr5exz8.js} +1 -1
- package/dashboard/dist/assets/{CloudCheckoutPage-gwhGxavy.js → CloudCheckoutPage-DsQ7FmsI.js} +1 -1
- package/dashboard/dist/assets/{CloudPage-BD4iBYeZ.js → CloudPage-DkSexu5V.js} +2 -2
- package/dashboard/dist/assets/{CommandPalette-C_KlPl0U.js → CommandPalette-Bm0huQdj.js} +1 -1
- package/dashboard/dist/assets/{CommunityStatsModal-Cl1Bgv8M.js → CommunityStatsModal-BsL8GN8Q.js} +1 -1
- package/dashboard/dist/assets/{ConfirmModal-NWoYevYC.js → ConfirmModal-_WPp292g.js} +1 -1
- package/dashboard/dist/assets/{Controls-D2-D2cfA.js → Controls-ktzn68KM.js} +1 -1
- package/dashboard/dist/assets/{DashboardPage-vITMnPXx.js → DashboardPage-CdNXi3Im.js} +1 -1
- package/dashboard/dist/assets/{DateRangePopover-8EMVXuH6.js → DateRangePopover-DWr4zIzF.js} +1 -1
- package/dashboard/dist/assets/{DevicePage-DbP8d6bM.js → DevicePage-CBa8Mk47.js} +1 -1
- package/dashboard/dist/assets/{DialogClose-CEstgLa1.js → DialogClose-CZ5jzgtb.js} +1 -1
- package/dashboard/dist/assets/DialogDescription-kCZ4gN09.js +1 -0
- package/dashboard/dist/assets/{DialogTitle-DP5TLLbz.js → DialogTitle-Dr0N6q15.js} +1 -1
- package/dashboard/dist/assets/{ElectricLogo-Uvi3yMum.js → ElectricLogo-sYqgrO6-.js} +1 -1
- package/dashboard/dist/assets/{FadeIn-Dpzihg6f.js → FadeIn-Qq-hcrZW.js} +1 -1
- package/dashboard/dist/assets/{HeaderGithubStar-DllqemKr.js → HeaderGithubStar-B77zSv7i.js} +1 -1
- package/dashboard/dist/assets/{HoverTooltip-Dc-TAH6l.js → HoverTooltip-lRDaUmoW.js} +1 -1
- package/dashboard/dist/assets/{IpCheckPage-jd1D5ZKX.js → IpCheckPage-B6AvHZjA.js} +1 -1
- package/dashboard/dist/assets/{LandingPage-CB1ZVw-a.js → LandingPage-DgzOjf3x.js} +2 -2
- package/dashboard/dist/assets/{LeaderboardPage-Bt2cRRmE.js → LeaderboardPage-BtjjtDMC.js} +2 -2
- package/dashboard/dist/assets/{LeaderboardProBadge-BVlyVOFf.js → LeaderboardProBadge-B2wNTUTU.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardProfileModal-CwQFRJg_.js → LeaderboardProfileModal-DJJckwHh.js} +3 -3
- package/dashboard/dist/assets/{LeaderboardProfilePage-CeqcTbUG.js → LeaderboardProfilePage-DJdxByl2.js} +1 -1
- package/dashboard/dist/assets/LimitsPage-gSBHSBi_.js +6 -0
- package/dashboard/dist/assets/{LocalOnlyNotice-B2_HoCVD.js → LocalOnlyNotice-B2lVqf_H.js} +1 -1
- package/dashboard/dist/assets/{LoginCard-nw9JOc2d.js → LoginCard-i0gg1yby.js} +1 -1
- package/dashboard/dist/assets/{LoginModal-BHNLTK1D.js → LoginModal-B-loLNZM.js} +1 -1
- package/dashboard/dist/assets/{LoginPage-LI2GZKhM.js → LoginPage-D_swI75j.js} +1 -1
- package/dashboard/dist/assets/{PetPage-CK6sPeI0.js → PetPage-DDpKvpjG.js} +2 -2
- package/dashboard/dist/assets/{PopoverPopup-BsXchEVa.js → PopoverPopup-Gja4MyEK.js} +1 -1
- package/dashboard/dist/assets/{ProviderIcon-vgCEy0dh.js → ProviderIcon-DOPj7tAZ.js} +1 -1
- package/dashboard/dist/assets/{ResetPasswordPage-B4CPj2vX.js → ResetPasswordPage-BVADLk89.js} +1 -1
- package/dashboard/dist/assets/{Select-BkAy6P2r.js → Select-D-38tN-E.js} +1 -1
- package/dashboard/dist/assets/{SelectItemText-C0RNqDrD.js → SelectItemText-jN61ukxk.js} +1 -1
- package/dashboard/dist/assets/{SelfHostPage-B-_w-Z-a.js → SelfHostPage-k7AkGpl1.js} +1 -1
- package/dashboard/dist/assets/ServiceStatusPage-D_Fa_pYz.js +1 -0
- package/dashboard/dist/assets/{SessionsPage-CmWXBqD2.js → SessionsPage-BymccEEz.js} +1 -1
- package/dashboard/dist/assets/{SettingsPage-CA70zP-t.js → SettingsPage-DfnMCAuA.js} +3 -3
- package/dashboard/dist/assets/{SkillsPage-CNamhfzU.js → SkillsPage-YyIHIaHN.js} +1 -1
- package/dashboard/dist/assets/{TokenGalaxy-CXrVBSk6.js → TokenGalaxy-BLcvZuQ9.js} +1 -1
- package/dashboard/dist/assets/{TooltipPopup-CR4MqElX.js → TooltipPopup-3E8kyVzz.js} +1 -1
- package/dashboard/dist/assets/{TrendMonitor-DQfcrEve.js → TrendMonitor-ByKAdXSF.js} +1 -1
- package/dashboard/dist/assets/{WidgetsPage-BBXxtZbP.js → WidgetsPage-BgEVIIzL.js} +1 -1
- package/dashboard/dist/assets/{WrappedPage-C8i2KlMF.js → WrappedPage-HjbX8QaA.js} +1 -1
- package/dashboard/dist/assets/__vite-browser-external-D_cMeuqI.js +45 -0
- package/dashboard/dist/assets/{agent-logos-CxQb8vir.js → agent-logos-BVF2siPQ.js} +1 -1
- package/dashboard/dist/assets/{arrow-left-D6zkcLVt.js → arrow-left-CYO24PGP.js} +1 -1
- package/dashboard/dist/assets/{arrow-right-BGb-XVn_.js → arrow-right-Xg9PZYhw.js} +1 -1
- package/dashboard/dist/assets/{arrow-up-right-XTStagDJ.js → arrow-up-right-B7ah6Qv-.js} +1 -1
- package/dashboard/dist/assets/{calendar-days-Cz3NGZiS.js → calendar-days-BV_iG938.js} +1 -1
- package/dashboard/dist/assets/{check-1z_vmHPD.js → check--EZH8RTp.js} +1 -1
- package/dashboard/dist/assets/{chevron-down-CkSBY3bE.js → chevron-down-BzGTlk0-.js} +1 -1
- package/dashboard/dist/assets/{cloud-checkout-pD5C4r_S.js → cloud-checkout-BgyxPHEh.js} +1 -1
- package/dashboard/dist/assets/{composite-BtDzx3a2.js → composite-C0KrmLEK.js} +1 -1
- package/dashboard/dist/assets/{copy-Ctv_wxuD.js → copy-BtucSK2U.js} +1 -1
- package/dashboard/dist/assets/{download-DKbKMGSR.js → download-CWHq03Y2.js} +1 -1
- package/dashboard/dist/assets/{external-link-g9cU017t.js → external-link-DCTXF5VZ.js} +1 -1
- package/dashboard/dist/assets/{flame-DZq3kXUt.js → flame-BE5TsqVF.js} +1 -1
- package/dashboard/dist/assets/{format-tokens-CXQfx0PC.js → format-tokens-ThNIMWnZ.js} +1 -1
- package/dashboard/dist/assets/{gift-CKlKjGP6.js → gift-DgaN9s4-.js} +1 -1
- package/dashboard/dist/assets/{icons-xPGMnBjl.js → icons-B4r5EiDC.js} +1 -1
- package/dashboard/dist/assets/{index-fVbP5wOv.js → index-CKhcCLNC.js} +1 -1
- package/dashboard/dist/assets/{index-BwOjMtB2.js → index-DFF9xo6f.js} +1 -1
- package/dashboard/dist/assets/{index-CDBOKcDh.js → index-DqCtgU0G.js} +1 -1
- package/dashboard/dist/assets/{index-Dl0oFLNr.js → index-fNKH4U7j.js} +1 -1
- package/dashboard/dist/assets/{info-D9xNIuGh.js → info-B4YzRR4y.js} +1 -1
- package/dashboard/dist/assets/{link-2-Bk5wYt2n.js → link-2-DzbUbaBw.js} +1 -1
- package/dashboard/dist/assets/{loader-circle-CcN3pHWb.js → loader-circle-B9c7D-7v.js} +1 -1
- package/dashboard/dist/assets/{local-usage-transfer-CYcy1ici.js → local-usage-transfer-btuk_b0Y.js} +1 -1
- package/dashboard/dist/assets/{modifiers.esm-DbpEzkJe.js → modifiers.esm-BjrU-Xz7.js} +1 -1
- package/dashboard/dist/assets/{monitor-smartphone-WkWv1qIS.js → monitor-smartphone-Bwn4tb4q.js} +1 -1
- package/dashboard/dist/assets/{play-2yZGWMes.js → play-DIFOwGIQ.js} +1 -1
- package/dashboard/dist/assets/{plus-mOF8tG1F.js → plus-BpBqnwVg.js} +1 -1
- package/dashboard/dist/assets/{provider-display-7gaOvgMp.js → provider-display-DSrs4u7T.js} +1 -1
- package/dashboard/dist/assets/{react-CdPiPDhk.js → react-BgG7_MY0.js} +1 -1
- package/dashboard/dist/assets/{safePolygon-C7FJLAlh.js → safePolygon-BUGWIDOM.js} +1 -1
- package/dashboard/dist/assets/{search-C63nCrjo.js → search-aHrmBmtZ.js} +1 -1
- package/dashboard/dist/assets/{server-BaG1rnuv.js → server-DOEvwlEU.js} +1 -1
- package/dashboard/dist/assets/{shield-check-D_4-Cm6L.js → shield-check-BPTnLhsT.js} +1 -1
- package/dashboard/dist/assets/{skills-api-DfbzwpDv.js → skills-api-C052Mwez.js} +1 -1
- package/dashboard/dist/assets/{sortable.esm-D-v8FRX5.js → sortable.esm-DaZKhjhu.js} +1 -1
- package/dashboard/dist/assets/{store-Dv_FYrXK.js → store-Cq30Pofw.js} +1 -1
- package/dashboard/dist/assets/{terminal-FQi6MaYt.js → terminal-CoSDSkE7.js} +1 -1
- package/dashboard/dist/assets/{trash-TbK96dEz.js → trash-BAmt-kPj.js} +1 -1
- package/dashboard/dist/assets/{use-community-stats-DGoWVZuk.js → use-community-stats-Bxq0kBhm.js} +1 -1
- package/dashboard/dist/assets/{use-latest-request-guard-Dg6uSaYt.js → use-latest-request-guard-DmIQDlvk.js} +1 -1
- package/dashboard/dist/assets/use-limits-display-prefs-CyAn1fme.js +1 -0
- package/dashboard/dist/assets/{use-native-settings-DIk0AF3b.js → use-native-settings-s_CIC8Bb.js} +1 -1
- package/dashboard/dist/assets/{use-ordered-list-CUqV3Zgl.js → use-ordered-list-BHhykAbt.js} +1 -1
- package/dashboard/dist/assets/use-reduced-motion-BmFyFE3S.js +1 -0
- package/dashboard/dist/assets/{use-transform-D_-w22c8.js → use-transform-CVeMFlS6.js} +1 -1
- package/dashboard/dist/assets/use-usage-limits-DRZMI20u.js +1 -0
- package/dashboard/dist/assets/{useCurrency-B_AuLCsL.js → useCurrency-DilqL2Iv.js} +1 -1
- package/dashboard/dist/assets/{usePositioner-DfxvIif8.js → usePositioner-BcnySw8a.js} +1 -1
- package/dashboard/dist/assets/{useTokenFormat-bbO13V4s.js → useTokenFormat-CvKW46WP.js} +1 -1
- package/dashboard/dist/assets/{zap-k07-EXTK.js → zap-D7VRNTwk.js} +1 -1
- package/dashboard/dist/index.html +5 -1
- package/dashboard/dist/ip-check.html +1 -1
- package/dashboard/dist/leaderboard.html +1 -1
- package/dashboard/dist/share.html +1 -1
- package/package.json +1 -1
- package/src/lib/codex-rollout-parser.js +43 -6
- package/src/lib/codex-usage-record.js +21 -0
- package/src/lib/pricing/curated-overrides.json +94 -0
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/src/lib/qoder-limits.js +78 -21
- package/src/lib/rollout.js +68 -14
- package/src/lib/session-analytics.js +10 -3
- package/src/lib/usage-limits.js +6 -4
- package/src/lib/workbuddy-limits.js +101 -9
- package/src/lib/zcode-limits.js +350 -43
- package/dashboard/dist/assets/DialogDescription-0wcygxtH.js +0 -1
- package/dashboard/dist/assets/LimitsPage-Bp4ZORmR.js +0 -6
- package/dashboard/dist/assets/ServiceStatusPage-5YevsGGD.js +0 -1
- package/dashboard/dist/assets/__vite-browser-external-BEEzY7mq.js +0 -45
- package/dashboard/dist/assets/use-limits-display-prefs-Djbdp7fi.js +0 -1
- package/dashboard/dist/assets/use-reduced-motion-DMCok-vZ.js +0 -1
- package/dashboard/dist/assets/use-usage-limits-h7aGsIQr.js +0 -1
|
@@ -34,6 +34,7 @@ const { readCodexServiceTier, isPriorityServiceTier, isUltrafastServiceTier } =
|
|
|
34
34
|
const {
|
|
35
35
|
createUsageRecordState,
|
|
36
36
|
extractTokenUsageRecord,
|
|
37
|
+
isCodexTotalOnlyResetSentinel,
|
|
37
38
|
noteLineAfterUsageRecord,
|
|
38
39
|
noteTokenCount,
|
|
39
40
|
noteUsageRecord,
|
|
@@ -72,6 +73,11 @@ const CODEX_RESUME_INVALIDATED = "TOKENTRACKER_CODEX_RESUME_INVALIDATED";
|
|
|
72
73
|
// input (including cache), not the accumulated session or day totals.
|
|
73
74
|
const OPENAI_LONG_CONTEXT_INPUT_THRESHOLD = 272_000;
|
|
74
75
|
|
|
76
|
+
// Session token summaries use the same fork-prefix rules as rollout.js; the
|
|
77
|
+
// reset-sentinel predicate is shared verbatim from codex-usage-record.js.
|
|
78
|
+
// Context/performance callers retain their existing event view.
|
|
79
|
+
const LEDGER_FORK_REPLAY_GAP_MS = 500;
|
|
80
|
+
|
|
75
81
|
// ---------------------------------------------------------------------------
|
|
76
82
|
// Timezone helpers
|
|
77
83
|
// ---------------------------------------------------------------------------
|
|
@@ -461,7 +467,7 @@ function formatToolDisplayName(name) {
|
|
|
461
467
|
// Usage normalization
|
|
462
468
|
// ---------------------------------------------------------------------------
|
|
463
469
|
|
|
464
|
-
function normalizeUsage(u) {
|
|
470
|
+
function normalizeUsage(u, { preserveReportedTotal = false } = {}) {
|
|
465
471
|
const out = {};
|
|
466
472
|
for (const k of [
|
|
467
473
|
"input_tokens",
|
|
@@ -477,7 +483,7 @@ function normalizeUsage(u) {
|
|
|
477
483
|
// Codex reports input inclusive of cached_input_tokens; keep our schema
|
|
478
484
|
// convention: non-cached input and cached input tracked separately.
|
|
479
485
|
out.input_tokens = Math.max(0, out.input_tokens - out.cached_input_tokens);
|
|
480
|
-
out.total_tokens =
|
|
486
|
+
if (!preserveReportedTotal) out.total_tokens =
|
|
481
487
|
out.input_tokens +
|
|
482
488
|
out.cached_input_tokens +
|
|
483
489
|
out.cache_creation_input_tokens +
|
|
@@ -596,6 +602,7 @@ async function parseCodexRolloutFile(filePath, {
|
|
|
596
602
|
sourceHandle = null,
|
|
597
603
|
collectBreakdowns = true,
|
|
598
604
|
collectModelUsage = false,
|
|
605
|
+
ledgerUsage = false,
|
|
599
606
|
onObject = null,
|
|
600
607
|
onUsage = null,
|
|
601
608
|
} = {}) {
|
|
@@ -638,6 +645,12 @@ async function parseCodexRolloutFile(filePath, {
|
|
|
638
645
|
let provider = isResuming ? resumeState.provider || null : null;
|
|
639
646
|
let cliVersion = isResuming ? resumeState.cliVersion || null : null;
|
|
640
647
|
let forkedFromId = isResuming ? resumeState.forkedFromId || null : null;
|
|
648
|
+
const ledgerRolloutDate = path.basename(primaryFilePath).match(/^rollout-(\d{4}-\d{2}-\d{2})T/)?.[1] || null;
|
|
649
|
+
let ledgerCurrentDate = null;
|
|
650
|
+
// Same gating as rollout.js: the replay prefix only ever sits at the head of
|
|
651
|
+
// a freshly-forked file, so only a scan from offset 0 can see it.
|
|
652
|
+
let ledgerReplayActive = initialOffset === 0;
|
|
653
|
+
let ledgerPreviousTokenMs = null;
|
|
641
654
|
let parentThreadId = isResuming ? resumeState.parentThreadId || null : null;
|
|
642
655
|
let threadSource = isResuming ? resumeState.threadSource || null : null;
|
|
643
656
|
let agentNickname = isResuming ? resumeState.agentNickname || null : null;
|
|
@@ -1050,6 +1063,9 @@ async function parseCodexRolloutFile(filePath, {
|
|
|
1050
1063
|
contentHasher,
|
|
1051
1064
|
sourceHandle,
|
|
1052
1065
|
})) {
|
|
1066
|
+
if (ledgerUsage && obj?.type === "turn_context" && typeof obj?.payload?.current_date === "string") {
|
|
1067
|
+
ledgerCurrentDate = obj.payload.current_date.trim().match(/^(\d{4}-\d{2}-\d{2})/)?.[1] || null;
|
|
1068
|
+
}
|
|
1053
1069
|
const modelEvent = applyCodexModelEvent(modelAttributionState, obj);
|
|
1054
1070
|
const attributedModel = currentCodexModel(modelAttributionState);
|
|
1055
1071
|
model = attributedModel || model;
|
|
@@ -1114,7 +1130,7 @@ async function parseCodexRolloutFile(filePath, {
|
|
|
1114
1130
|
}
|
|
1115
1131
|
|
|
1116
1132
|
if (usageRecord) {
|
|
1117
|
-
const delta = normalizeUsage(usageRecord.usage);
|
|
1133
|
+
const delta = normalizeUsage(usageRecord.usage, { preserveReportedTotal: ledgerUsage });
|
|
1118
1134
|
noteUsageRecord(
|
|
1119
1135
|
usageRecordState,
|
|
1120
1136
|
// Without a response_id a compaction cannot be deduplicated.
|
|
@@ -1147,15 +1163,36 @@ async function parseCodexRolloutFile(filePath, {
|
|
|
1147
1163
|
);
|
|
1148
1164
|
}
|
|
1149
1165
|
const rawDelta = consumeUsageDelta(usageDeltaState, lastUsage, totalUsage);
|
|
1150
|
-
const delta = rawDelta
|
|
1166
|
+
const delta = rawDelta && !(ledgerUsage && isCodexTotalOnlyResetSentinel(lastUsage, totalUsage))
|
|
1167
|
+
? normalizeUsage(rawDelta, { preserveReportedTotal: ledgerUsage }) : null;
|
|
1151
1168
|
// Timing consumers receive canonical, deduplicated usage below. A null
|
|
1152
1169
|
// delta is a snapshot, not another model response.
|
|
1153
1170
|
if (compaction) countCompactionRecord(compaction);
|
|
1154
1171
|
const isNewResumeEvent = noteTokenEvent(ts, lastUsage, totalUsage);
|
|
1155
1172
|
if (inRequestedRange) {
|
|
1156
1173
|
const eventSessionId = sessionId || rolloutSessionIdFromPath(primaryFilePath) || primaryFilePath;
|
|
1157
|
-
const eventKey = `${eventSessionId}:${ts}
|
|
1158
|
-
|
|
1174
|
+
const eventKey = ledgerUsage ? `${eventSessionId}:${ts}`
|
|
1175
|
+
: `${eventSessionId}:${ts}:${usageEventSignature(lastUsage, totalUsage)}`;
|
|
1176
|
+
const alreadySeen = seenTokenEvents && seenTokenEvents.has(eventKey);
|
|
1177
|
+
let replayed = false;
|
|
1178
|
+
if (ledgerUsage && forkedFromId && delta?.total_tokens > 0) {
|
|
1179
|
+
if (ledgerReplayActive) {
|
|
1180
|
+
const tokenMs = Date.parse(ts);
|
|
1181
|
+
if (!Number.isFinite(tokenMs) || (ledgerPreviousTokenMs !== null && tokenMs < ledgerPreviousTokenMs)) {
|
|
1182
|
+
ledgerReplayActive = false;
|
|
1183
|
+
} else {
|
|
1184
|
+
if (ledgerPreviousTokenMs !== null && tokenMs - ledgerPreviousTokenMs >= LEDGER_FORK_REPLAY_GAP_MS) ledgerReplayActive = false;
|
|
1185
|
+
replayed = ledgerReplayActive && ledgerPreviousTokenMs !== null
|
|
1186
|
+
&& tokenMs - ledgerPreviousTokenMs < LEDGER_FORK_REPLAY_GAP_MS;
|
|
1187
|
+
ledgerPreviousTokenMs = tokenMs;
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
replayed ||= Boolean(ledgerRolloutDate && ledgerCurrentDate && ledgerCurrentDate < ledgerRolloutDate);
|
|
1191
|
+
}
|
|
1192
|
+
// Remember skipped inherited rows too: another readable copy of the
|
|
1193
|
+
// same session must not reintroduce its prefix after the first live turn.
|
|
1194
|
+
if (ledgerUsage && seenTokenEvents && delta?.total_tokens > 0) seenTokenEvents.add(eventKey);
|
|
1195
|
+
if (!isNewResumeEvent || alreadySeen || replayed) {
|
|
1159
1196
|
if (typeof onUsage === "function") onUsage({ timestamp: ts, delta: null, rawUsage: lastUsage, model: attributedModel });
|
|
1160
1197
|
attributeTurn(null);
|
|
1161
1198
|
} else {
|
|
@@ -176,6 +176,26 @@ function formatRecordOnlyWarning(count) {
|
|
|
176
176
|
return `${count} Codex session(s) report usage only via token_usage_record; not counted yet (see #652)`;
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
+
// A reset sentinel is a token_count whose total drops to exact zero while the
|
|
180
|
+
// previous total was positive and every component of both snapshots is zero —
|
|
181
|
+
// Codex restarting a session's cumulative counters, not a real response. Both
|
|
182
|
+
// the hourly ledger (rollout.js) and the session ledger mode
|
|
183
|
+
// (codex-rollout-parser.js) must reject it identically, so the predicate lives
|
|
184
|
+
// here as the single copy of the rule.
|
|
185
|
+
function isCodexTotalOnlyResetSentinel(lastUsage, totalUsage) {
|
|
186
|
+
const componentTotal = (usage) => [
|
|
187
|
+
usage?.input_tokens,
|
|
188
|
+
usage?.cached_input_tokens,
|
|
189
|
+
usage?.cache_creation_input_tokens ?? usage?.cache_write_input_tokens,
|
|
190
|
+
usage?.output_tokens,
|
|
191
|
+
usage?.reasoning_output_tokens,
|
|
192
|
+
].reduce((sum, value) => sum + Math.max(0, Number(value) || 0), 0);
|
|
193
|
+
return Number(lastUsage?.total_tokens || 0) > 0
|
|
194
|
+
&& Number(totalUsage?.total_tokens || 0) === 0
|
|
195
|
+
&& componentTotal(lastUsage) === 0
|
|
196
|
+
&& componentTotal(totalUsage) === 0;
|
|
197
|
+
}
|
|
198
|
+
|
|
179
199
|
module.exports = {
|
|
180
200
|
MAX_COMPACTION_RESPONSE_IDS,
|
|
181
201
|
createCompactionResponseIds,
|
|
@@ -184,6 +204,7 @@ module.exports = {
|
|
|
184
204
|
awaitsCompactedLine,
|
|
185
205
|
createUsageRecordState,
|
|
186
206
|
extractTokenUsageRecord,
|
|
207
|
+
isCodexTotalOnlyResetSentinel,
|
|
187
208
|
isCodexTurnEndEvent,
|
|
188
209
|
isRecordOnly,
|
|
189
210
|
noteLineAfterUsageRecord,
|
|
@@ -75,6 +75,27 @@
|
|
|
75
75
|
"cache_write": 6.25,
|
|
76
76
|
"note": "Opus 4.8 not yet in LiteLLM. Pin to the standard Opus tier (same as 4.6/4.7); remove once LiteLLM carries it."
|
|
77
77
|
},
|
|
78
|
+
"claude-opus-4-5": {
|
|
79
|
+
"input": 5,
|
|
80
|
+
"output": 25,
|
|
81
|
+
"cache_read": 0.5,
|
|
82
|
+
"cache_write": 6.25,
|
|
83
|
+
"note": "Canonical undated Opus 4.5 alias (LiteLLM bare key, sourced from https://platform.claude.com/docs/en/about-claude/pricing, cached 2026-10-31): standard Opus tier $5/$25 per MTok, cache_read 0.1x, cache_write 1.25x — same rates as claude-opus-4-5-20250414. Previously LiteLLM-only; promoted so cloud account views price the bare id (issue #929)."
|
|
84
|
+
},
|
|
85
|
+
"claude-opus-4-6": {
|
|
86
|
+
"input": 5,
|
|
87
|
+
"output": 25,
|
|
88
|
+
"cache_read": 0.5,
|
|
89
|
+
"cache_write": 6.25,
|
|
90
|
+
"note": "Opus 4.6 standard tier (LiteLLM entry sourced from https://platform.claude.com/docs/en/about-claude/pricing, cached 2026-10-31): $5/$25 per MTok, cache_read 0.1x, cache_write 1.25x. The edge table pins the same rate; curated pins it so local billing and -thinking variants no longer depend on LiteLLM fuzzy matching (issue #929)."
|
|
91
|
+
},
|
|
92
|
+
"claude-sonnet-4-6": {
|
|
93
|
+
"input": 3,
|
|
94
|
+
"output": 15,
|
|
95
|
+
"cache_read": 0.3,
|
|
96
|
+
"cache_write": 3.75,
|
|
97
|
+
"note": "Sonnet 4.6 standard tier (LiteLLM entry sourced from https://platform.claude.com/docs/en/about-claude/pricing, cached 2026-10-31): $3/$15 per MTok, cache_read 0.1x, cache_write 1.25x. The edge table pins the same rate; curated pins it so local billing no longer depends on the LiteLLM cache (issue #929)."
|
|
98
|
+
},
|
|
78
99
|
"claude-sonnet-5": {
|
|
79
100
|
"input": 2,
|
|
80
101
|
"output": 10,
|
|
@@ -137,6 +158,13 @@
|
|
|
137
158
|
"priority_multiplier": 2,
|
|
138
159
|
"note": "Official Standard USD/MTok rates verified 2026-09-24: https://developers.openai.com/api/docs/models/gpt-6-sol. Same rules as gpt-6-astra: requests above 272K input tokens use 2x input/cache and 1.5x output for the full request, applied only to observed long-context request subsets; Fast mode is published as 2x the applicable rates (priority_multiplier). Reasoning-effort suffixes use the same base rates."
|
|
139
160
|
},
|
|
161
|
+
"gpt-6-luna": {
|
|
162
|
+
"input": 0.1,
|
|
163
|
+
"output": 0.5,
|
|
164
|
+
"cache_read": 0.01,
|
|
165
|
+
"cache_write": 0.125,
|
|
166
|
+
"note": "GPT-6 Luna lightweight tier, Standard USD/MTok (LiteLLM entry sourced from https://developers.openai.com/api/docs/pricing, cached 2026-10-31): $0.10/$0.50 per MTok, $0.01 cache read, $0.125 cache write. Distinct from gpt-5.6-luna. Previously LiteLLM-only, so cloud account views showed it unpriced; promoted so cloud prices it and curated/edge parity guards the key (issue #929)."
|
|
167
|
+
},
|
|
140
168
|
"gpt-5.6-sol": {
|
|
141
169
|
"input": 4,
|
|
142
170
|
"output": 20,
|
|
@@ -158,6 +186,42 @@
|
|
|
158
186
|
"cache_write": 0.25,
|
|
159
187
|
"note": "GPT-5.6 lightweight tier. Official short-context rates: $0.20/$1.20 per MTok (previous curated values $1/$6 overcounted 5x). See gpt-5.6-sol."
|
|
160
188
|
},
|
|
189
|
+
"gpt-5.5": {
|
|
190
|
+
"input": 5,
|
|
191
|
+
"output": 30,
|
|
192
|
+
"cache_read": 0.5,
|
|
193
|
+
"note": "Official Standard USD/MTok rates (LiteLLM entry sourced from https://developers.openai.com/api/docs/pricing, cached 2026-10-31): $5/$30 per MTok, $0.50 cache read, no published cache-write rate. The largest production LiteLLM-only model — codex's primary SKU ($1,118 of cloud account usage showed unpriced between 2026-01-01 and 2026-10-31); promoted so cloud account views price it and curated/edge parity guards the key (issue #929)."
|
|
194
|
+
},
|
|
195
|
+
"gpt-5.4": {
|
|
196
|
+
"input": 2.5,
|
|
197
|
+
"output": 15,
|
|
198
|
+
"cache_read": 0.25,
|
|
199
|
+
"note": "Official Standard USD/MTok rates (LiteLLM entry sourced from https://developers.openai.com/api/docs/pricing, cached 2026-10-31): $2.50/$15 per MTok, $0.25 cache read. The edge table has pinned this rate since before v1.5.1; curated pins the same value so local billing no longer depends on the LiteLLM cache (issue #929). -pro/-nano/-mini keep their own SKUs."
|
|
200
|
+
},
|
|
201
|
+
"gpt-5.4-pro": {
|
|
202
|
+
"input": 30,
|
|
203
|
+
"output": 180,
|
|
204
|
+
"cache_read": 3,
|
|
205
|
+
"note": "Official Pro USD/MTok rates, matching the edge table's gpt-5.4-pro entry ($30/$180, $3 cache read; https://developers.openai.com/api/docs/pricing). Companion pin for the gpt-5.4 promotion: without a curated Pro entry, the curated contained match captures provider-qualified dated snapshots (openai/gpt-5.4-pro-2026-03-05) at the base $2.50/$15 rate before the LiteLLM reverse lookup reaches the Pro SKU — 12x under local vs edge (issue #929)."
|
|
206
|
+
},
|
|
207
|
+
"gpt-5.4-mini": {
|
|
208
|
+
"input": 0.75,
|
|
209
|
+
"output": 4.5,
|
|
210
|
+
"cache_read": 0.075,
|
|
211
|
+
"note": "Official Standard USD/MTok rates (LiteLLM entry sourced from https://developers.openai.com/api/docs/pricing, cached 2026-10-31): $0.75/$4.50 per MTok, $0.075 cache read. Same promotion rationale as gpt-5.4 (issue #929)."
|
|
212
|
+
},
|
|
213
|
+
"gpt-5.2": {
|
|
214
|
+
"input": 1.75,
|
|
215
|
+
"output": 14,
|
|
216
|
+
"cache_read": 0.175,
|
|
217
|
+
"note": "Official Standard USD/MTok rates (LiteLLM entry sourced from https://developers.openai.com/api/docs/pricing, cached 2026-10-31): $1.75/$14 per MTok, $0.175 cache read. Same promotion rationale as gpt-5.4 (issue #929); -pro stays on its own 10x LiteLLM SKU."
|
|
218
|
+
},
|
|
219
|
+
"gpt-5.3-codex-spark": {
|
|
220
|
+
"input": 1.75,
|
|
221
|
+
"output": 14,
|
|
222
|
+
"cache_read": 0.175,
|
|
223
|
+
"note": "Codex spark capacity tier; not a separate LiteLLM key. Local (LiteLLM reverse-substring) and the edge matcher both bill it at the base gpt-5.3-codex rate ($1.75/$14, $0.175 cache read, https://developers.openai.com/api/docs/pricing); the exact entry pins that resolution on both sides (issue #929)."
|
|
224
|
+
},
|
|
161
225
|
"kiro-agent": {
|
|
162
226
|
"input": 3,
|
|
163
227
|
"output": 15,
|
|
@@ -265,6 +329,12 @@
|
|
|
265
329
|
"cache_write": 0,
|
|
266
330
|
"note": "Google Gemini 4 Argon introductory list rate (through 2026-11-30) matching Cursor Other Models pool: $2/M input, $0.10/M cached input, $10/M output. Effort suffixes (-high/-medium/-low/-minimal) are stripped by normalizeCursorModel. Sources: https://cursor.com/docs/models-and-pricing and https://ai.google.dev/gemini-api/docs/pricing"
|
|
267
331
|
},
|
|
332
|
+
"gemini-3-flash-preview": {
|
|
333
|
+
"input": 0.5,
|
|
334
|
+
"output": 3,
|
|
335
|
+
"cache_read": 0.05,
|
|
336
|
+
"note": "LiteLLM entry (sourced from https://cloud.google.com/gemini-enterprise-agent-platform/generative-ai/pricing, cached 2026-10-31): $0.50/$3 per MTok, $0.05 cache read, no published cache-write rate. Same rate the edge table already pins; promoted so curated/edge parity guards the key (issue #929)."
|
|
337
|
+
},
|
|
268
338
|
"MiniMax-M2.7": {
|
|
269
339
|
"input": 0.3,
|
|
270
340
|
"output": 1.2,
|
|
@@ -579,6 +649,30 @@
|
|
|
579
649
|
"output": 0,
|
|
580
650
|
"cache_read": 0
|
|
581
651
|
},
|
|
652
|
+
"mimo-v2.5": {
|
|
653
|
+
"input": 0.4,
|
|
654
|
+
"output": 2,
|
|
655
|
+
"cache_read": 0.08,
|
|
656
|
+
"note": "Xiaomi MiMo v2.5 (queue rows report the bare id; LiteLLM keys are provider-qualified). Rates match the deepinfra entry — the lexicographically smallest provider key the matcher deterministically picks: $0.40/$2 per MTok, $0.08 cache read, no published cache-write rate. The edge table pinned this exact rate after the kimi-k2.6/mimo profile-modal incident; curated pins the same value so local billing no longer depends on LiteLLM prefix-strip (issue #929)."
|
|
657
|
+
},
|
|
658
|
+
"mimo-v2.5-pro": {
|
|
659
|
+
"input": 1,
|
|
660
|
+
"output": 3,
|
|
661
|
+
"cache_read": 0.2,
|
|
662
|
+
"note": "Xiaomi MiMo v2.5 Pro (deepinfra is the lexicographically smallest LiteLLM provider key, matching the edge table): $1/$3 per MTok, $0.20 cache read. Exact entry required alongside mimo-v2.5 so the contained-exact fallback cannot bill -pro at the base v2.5 rate (issue #929)."
|
|
663
|
+
},
|
|
664
|
+
"muse-spark-1.2-contributor": {
|
|
665
|
+
"input": 0.1,
|
|
666
|
+
"output": 0.2,
|
|
667
|
+
"cache_read": 0.002,
|
|
668
|
+
"note": "Paid Muse contributor SKU. LiteLLM provider-qualified entries agree on $0.10/$0.20 per MTok, $0.002 cache read (meta and opencode_go both list these rates, cached 2026-10-31). Previously LiteLLM prefix-strip-only, so cloud account views showed it unpriced; promoted so cloud prices it and curated/edge parity guards the key (issue #929). The -free SKU below stays $0."
|
|
669
|
+
},
|
|
670
|
+
"muse-spark-1.3-contributor": {
|
|
671
|
+
"input": 0.1,
|
|
672
|
+
"output": 0.2,
|
|
673
|
+
"cache_read": 0.002,
|
|
674
|
+
"note": "See muse-spark-1.2-contributor — same paid contributor SKU at the same verified rates (issue #929)."
|
|
675
|
+
},
|
|
582
676
|
"muse-spark-1.2-contributor-free": {
|
|
583
677
|
"input": 0,
|
|
584
678
|
"output": 0,
|