@ipv9/tokentracker-cli 0.39.56 → 0.39.57
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/{Card-DqlTs4bX.js → Card-ci17PdAV.js} +1 -1
- package/dashboard/dist/assets/DashboardPage-7tVtPxb8.js +60 -0
- package/dashboard/dist/assets/{IpCheckPage-M13-Ws2A.js → IpCheckPage-DNA0Q23M.js} +1 -1
- package/dashboard/dist/assets/{LimitsPage-G2Fys5yE.js → LimitsPage-BpjYvnWF.js} +1 -1
- package/dashboard/dist/assets/{LocalOnlyNotice-DhRn6ocA.js → LocalOnlyNotice-B5JmBabh.js} +1 -1
- package/dashboard/dist/assets/{PopoverPopup-bb-KJHxL.js → PopoverPopup-CcfJZMpE.js} +1 -1
- package/dashboard/dist/assets/{Select-CM-mkp28.js → Select-DkdVUiwm.js} +1 -1
- package/dashboard/dist/assets/{SettingsPage-DKQb2n41.js → SettingsPage-B3KR1Y9S.js} +1 -1
- package/dashboard/dist/assets/{SkillsPage-CdNJE3jQ.js → SkillsPage-ced5E6ai.js} +1 -1
- package/dashboard/dist/assets/{WrappedPage-DyfHVPDk.js → WrappedPage-BMgJxQLZ.js} +1 -1
- package/dashboard/dist/assets/{format-5-hK-Lf9.js → format-wJPB8ygX.js} +1 -1
- package/dashboard/dist/assets/{limitDisplay-ypD5--So.js → limitDisplay-BWIfB8aR.js} +1 -1
- package/dashboard/dist/assets/{main-BhUdEGPa.js → main-DFczPkAN.js} +3 -3
- package/dashboard/dist/assets/{mock-data-DZbvGOJz.js → mock-data-BQNbqt40.js} +1 -1
- package/dashboard/dist/assets/{use-limits-display-prefs-UcKuzN2-.js → use-limits-display-prefs-fr-_DlHb.js} +1 -1
- package/dashboard/dist/assets/{useCurrency-SDO8fpsi.js → useCurrency-CRUry3mm.js} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/package.json +1 -1
- package/src/lib/pricing/index.js +72 -2
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/dashboard/dist/assets/DashboardPage-CIRoAF9d.js +0 -60
package/src/lib/pricing/index.js
CHANGED
|
@@ -49,7 +49,12 @@ const RELOAD_COOLDOWN_MS = 5 * 60 * 1000;
|
|
|
49
49
|
// curated fuzzy rule rather than an exact id, so the price is plausible but may
|
|
50
50
|
// belong to a different model. Worth surfacing — a wrong price never looks
|
|
51
51
|
// wrong, unlike a $0 one.
|
|
52
|
-
const FUZZY_SOURCES = new Set([
|
|
52
|
+
const FUZZY_SOURCES = new Set([
|
|
53
|
+
"curated:fuzzy",
|
|
54
|
+
"litellm:fuzzy",
|
|
55
|
+
"litellm:prefix-strip",
|
|
56
|
+
"routed-estimated",
|
|
57
|
+
]);
|
|
53
58
|
|
|
54
59
|
// Placeholder ids that stand in for "this row has no model", so they resolve to
|
|
55
60
|
// the "unattributed" tier instead of being looked up and recorded as a miss.
|
|
@@ -67,6 +72,62 @@ const UNRESOLVED_LOGICAL_ROUTE_IDS = new Set([
|
|
|
67
72
|
]);
|
|
68
73
|
const UNPRICED_TIERS = new Set(["miss", "routed-unresolved"]);
|
|
69
74
|
|
|
75
|
+
// Owner-approved route mix estimates. The child-model ratios are a pricing
|
|
76
|
+
// policy, not routing telemetry: callers must surface `routed-estimated` as a
|
|
77
|
+
// non-exact price. Any configured child whose current price cannot be resolved
|
|
78
|
+
// makes the route unpriced rather than silently using a partial blend.
|
|
79
|
+
const ROUTED_ESTIMATE_POLICIES = new Map([
|
|
80
|
+
["claude-auto-pilot-fable-v1-canary", [
|
|
81
|
+
{ model: "anthropic/claude-sonnet-5", pricingModel: "claude-sonnet-5", weight: 0.6 },
|
|
82
|
+
{ model: "anthropic/claude-opus-5", pricingModel: "claude-opus-5", weight: 0.4 },
|
|
83
|
+
]],
|
|
84
|
+
["gpt-5.6-auto-pilot", [
|
|
85
|
+
{ model: "gpt-5.6-terra", weight: 0.6 },
|
|
86
|
+
{ model: "gpt-5.6-sol", weight: 0.4 },
|
|
87
|
+
]],
|
|
88
|
+
["gpt-5.6-auto-pilot-045-canary", [
|
|
89
|
+
{ model: "gpt-5.6-terra", weight: 0.6 },
|
|
90
|
+
{ model: "gpt-5.6-sol", weight: 0.4 },
|
|
91
|
+
]],
|
|
92
|
+
["gpt-5.6-auto-pilot-055-v2", [
|
|
93
|
+
{ model: "gpt-5.6-terra", weight: 0.6 },
|
|
94
|
+
{ model: "gpt-5.6-sol", weight: 0.4 },
|
|
95
|
+
]],
|
|
96
|
+
["gpt-5.6-auto-pilot-056-claude-reasoning-canary", [
|
|
97
|
+
{ model: "gpt-5.6-terra", weight: 0.6 },
|
|
98
|
+
{ model: "gpt-5.6-sol", weight: 0.4 },
|
|
99
|
+
]],
|
|
100
|
+
]);
|
|
101
|
+
const ROUTE_CHILD_EXACT_TIERS = new Set([
|
|
102
|
+
"curated:exact",
|
|
103
|
+
"curated:exact-dot",
|
|
104
|
+
"litellm:exact",
|
|
105
|
+
"litellm:exact-dot",
|
|
106
|
+
]);
|
|
107
|
+
|
|
108
|
+
function isPotentialGptAutoRoute(model) {
|
|
109
|
+
return /^gpt-5\.6-auto/i.test(String(model || "").trim());
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function resolveRoutedEstimate(model, lookupSource) {
|
|
113
|
+
const policy = ROUTED_ESTIMATE_POLICIES.get(String(model || "").trim());
|
|
114
|
+
if (!policy) return null;
|
|
115
|
+
const mixed = { input: 0, output: 0, cache_read: 0, cache_write: 0 };
|
|
116
|
+
for (const child of policy) {
|
|
117
|
+
const result = lookupPricing(child.pricingModel || child.model, {
|
|
118
|
+
curated: curatedOverrides,
|
|
119
|
+
litellm: state.litellmPerMillionMap,
|
|
120
|
+
source: lookupSource,
|
|
121
|
+
});
|
|
122
|
+
if (!result.hit || !result.value || !ROUTE_CHILD_EXACT_TIERS.has(result.source)) return null;
|
|
123
|
+
for (const field of Object.keys(mixed)) {
|
|
124
|
+
if (!Number.isFinite(result.value[field])) return null;
|
|
125
|
+
mixed[field] += child.weight * result.value[field];
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return mixed;
|
|
129
|
+
}
|
|
130
|
+
|
|
70
131
|
// `last_refresh_error` is served over HTTP to the dashboard, so it is built
|
|
71
132
|
// from CLOSED sets, never from an arbitrary value. A previous version accepted
|
|
72
133
|
// anything symbol-shaped, which a QA pass broke immediately: a 32-character
|
|
@@ -246,7 +307,16 @@ function getModelPricingMeta(model, opts = {}) {
|
|
|
246
307
|
const lookupSource = resolveLookupSource(opts);
|
|
247
308
|
const cacheKey = lookupSource ? `${lookupSource}\0${model}` : model;
|
|
248
309
|
|
|
249
|
-
|
|
310
|
+
const routedEstimate = resolveRoutedEstimate(model, lookupSource);
|
|
311
|
+
if (routedEstimate) {
|
|
312
|
+
state.tiers.set(cacheKey, { model, source: lookupSource, tier: "routed-estimated" });
|
|
313
|
+
return { pricing: routedEstimate, tier: "routed-estimated" };
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (
|
|
317
|
+
UNRESOLVED_LOGICAL_ROUTE_IDS.has(String(model || "").trim())
|
|
318
|
+
|| isPotentialGptAutoRoute(model)
|
|
319
|
+
) {
|
|
250
320
|
state.tiers.set(cacheKey, { model, source: lookupSource, tier: "routed-unresolved" });
|
|
251
321
|
return { pricing: ZERO_PRICING, tier: "routed-unresolved" };
|
|
252
322
|
}
|