tokentracker-cli 0.64.3 → 0.65.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.
Files changed (43) hide show
  1. package/dashboard/dist/assets/{ActivityHeatmap-BSA4KPkJ.js → ActivityHeatmap-Ccf0I3uP.js} +1 -1
  2. package/dashboard/dist/assets/{Card-BniOg7K8.js → Card-BSF8dYEt.js} +1 -1
  3. package/dashboard/dist/assets/{ConfirmModal-CxThrcXK.js → ConfirmModal-Bjp6eg2f.js} +1 -1
  4. package/dashboard/dist/assets/{DashboardPage-DygQTlzO.js → DashboardPage-BInQkoDe.js} +1 -1
  5. package/dashboard/dist/assets/{DevicePage-BfRGbds7.js → DevicePage-B0yxbDDR.js} +1 -1
  6. package/dashboard/dist/assets/{DialogTitle-Cd0Nw0hW.js → DialogTitle-uw-Oa5Qv.js} +1 -1
  7. package/dashboard/dist/assets/{FadeIn-DxDHmb9-.js → FadeIn-DPIBqXRl.js} +1 -1
  8. package/dashboard/dist/assets/{HeaderGithubStar-2aQXPupt.js → HeaderGithubStar-DDXfJ1uC.js} +1 -1
  9. package/dashboard/dist/assets/{IpCheckPage-m_W_l5Xa.js → IpCheckPage-KC93tPlt.js} +1 -1
  10. package/dashboard/dist/assets/LandingPage-Itx2uPWI.js +4415 -0
  11. package/dashboard/dist/assets/{LeaderboardAvatar-BmpmwHwD.js → LeaderboardAvatar-Bv44b_Kl.js} +1 -1
  12. package/dashboard/dist/assets/{LeaderboardPage-B6wWBsUW.js → LeaderboardPage-DDq5gzyz.js} +2 -2
  13. package/dashboard/dist/assets/{LeaderboardProfileModal-CLlbxbZQ.js → LeaderboardProfileModal-LQyYrCf1.js} +1 -1
  14. package/dashboard/dist/assets/{LeaderboardProfilePage-en0u_bG-.js → LeaderboardProfilePage-3you3mbA.js} +1 -1
  15. package/dashboard/dist/assets/LimitsPage-CrLvR8vE.js +3 -0
  16. package/dashboard/dist/assets/{LocalOnlyNotice-DNHw_KVs.js → LocalOnlyNotice-Di1gnfIi.js} +1 -1
  17. package/dashboard/dist/assets/{LoginPage-D38KpNMd.js → LoginPage-f9QHz_uZ.js} +1 -1
  18. package/dashboard/dist/assets/{PopoverPopup-C4Ndfprc.js → PopoverPopup-7rjAxAqk.js} +1 -1
  19. package/dashboard/dist/assets/{ResetPasswordPage-DYF1Iz64.js → ResetPasswordPage-DKA7HGpJ.js} +1 -1
  20. package/dashboard/dist/assets/{Select-6qFjabMe.js → Select-2gikPo1a.js} +1 -1
  21. package/dashboard/dist/assets/{SelectItemText-B234IuCW.js → SelectItemText-DZx33XF1.js} +1 -1
  22. package/dashboard/dist/assets/{SettingsPage-C-2m2LzE.js → SettingsPage-CwHPmuZV.js} +1 -1
  23. package/dashboard/dist/assets/{SkillsPage-37lQlleG.js → SkillsPage-B6BJ9UZp.js} +1 -1
  24. package/dashboard/dist/assets/{WidgetsPage-D9ANC2dF.js → WidgetsPage-D8p3Tx7E.js} +1 -1
  25. package/dashboard/dist/assets/{WrappedPage-hjymf4DR.js → WrappedPage-cXEfhti9.js} +1 -1
  26. package/dashboard/dist/assets/{agent-logos-B-NxiwlS.js → agent-logos-D3iFlaWg.js} +1 -1
  27. package/dashboard/dist/assets/{arrow-up-right-B_iC7jeO.js → arrow-up-right-D87Aw_ZN.js} +1 -1
  28. package/dashboard/dist/assets/{download-DSBqpgG5.js → download-BtcEs1OB.js} +1 -1
  29. package/dashboard/dist/assets/{main-DEwjlMQP.js → main-DqnXui98.js} +14 -14
  30. package/dashboard/dist/assets/{use-limits-display-prefs-OhLCvWa8.js → use-limits-display-prefs-DAxlRSu2.js} +1 -1
  31. package/dashboard/dist/assets/{use-native-settings-BOQcPSo9.js → use-native-settings-CgvB_B6W.js} +1 -1
  32. package/dashboard/dist/assets/{use-ordered-list-DKOLCb2L.js → use-ordered-list-DOfX6aSy.js} +1 -1
  33. package/dashboard/dist/assets/{use-quality-per-dollar-pref-EzQkuFZg.js → use-quality-per-dollar-pref-kEbwQwk2.js} +1 -1
  34. package/dashboard/dist/assets/{use-usage-limits-DD8zzK6Q.js → use-usage-limits-la-KPfJj.js} +1 -1
  35. package/dashboard/dist/assets/{useCurrency-D1ldsRAh.js → useCurrency-LDRg7ST0.js} +1 -1
  36. package/dashboard/dist/assets/{useScrollLock-eUzPJJ4w.js → useScrollLock-lP1Is9IY.js} +1 -1
  37. package/dashboard/dist/index.html +1 -1
  38. package/dashboard/dist/share.html +1 -1
  39. package/package.json +1 -1
  40. package/src/lib/pricing/seed-snapshot.json +1 -1
  41. package/src/lib/usage-limits.js +49 -1
  42. package/dashboard/dist/assets/LandingPage-BkusMtg4.js +0 -4411
  43. package/dashboard/dist/assets/LimitsPage-CZXzDyPl.js +0 -3
@@ -144,6 +144,34 @@ function formatClaudeRateLimitMessage(retryAfterSec) {
144
144
  return "Claude API rate limited (429) — retry shortly.";
145
145
  }
146
146
 
147
+ // Model-scoped weekly windows (e.g. Fable) arrive only in the newer generic `limits`
148
+ // array (`kind: "weekly_scoped"` + `scope.model.display_name`) — the legacy top-level
149
+ // fields (`seven_day_opus` etc.) stay null for them. Extract them into
150
+ // `weekly_scoped: [{ label, utilization, resets_at }]`. Entries that duplicate a
151
+ // populated legacy field (an "Opus" scoped entry alongside `seven_day_opus`) are
152
+ // dropped so the same window never renders twice.
153
+ function extractClaudeScopedWeekly(body) {
154
+ if (!Array.isArray(body?.limits)) return null;
155
+ const out = [];
156
+ for (const entry of body.limits) {
157
+ if (!entry || typeof entry !== "object" || entry.kind !== "weekly_scoped") continue;
158
+ const model = entry.scope?.model;
159
+ const label = typeof model?.display_name === "string" && model.display_name.trim()
160
+ ? model.display_name.trim()
161
+ : typeof model?.id === "string" && model.id.trim() ? model.id.trim() : null;
162
+ if (!label) continue;
163
+ if (body.seven_day_opus && label.toLowerCase() === "opus") continue;
164
+ const utilization = Number(entry.percent);
165
+ if (!Number.isFinite(utilization)) continue;
166
+ out.push({
167
+ label,
168
+ utilization,
169
+ resets_at: typeof entry.resets_at === "string" ? entry.resets_at : null,
170
+ });
171
+ }
172
+ return out.length > 0 ? out : null;
173
+ }
174
+
147
175
  async function fetchClaudeUsageLimits(accessToken, { fetchImpl = fetch, maxAttempts = 3 } = {}) {
148
176
  const url = "https://api.anthropic.com/api/oauth/usage";
149
177
  const headers = {
@@ -178,6 +206,7 @@ async function fetchClaudeUsageLimits(accessToken, { fetchImpl = fetch, maxAttem
178
206
  five_hour: body.five_hour ?? null,
179
207
  seven_day: body.seven_day ?? null,
180
208
  seven_day_opus: body.seven_day_opus ?? null,
209
+ weekly_scoped: extractClaudeScopedWeekly(body),
181
210
  extra_usage: body.extra_usage ?? null,
182
211
  };
183
212
  }
@@ -1848,7 +1877,21 @@ function isClaudeCacheWindowUsable(window, { nowMs } = {}) {
1848
1877
  }
1849
1878
 
1850
1879
  function hasClaudeWindow(limits) {
1851
- return Boolean(limits?.five_hour || limits?.seven_day || limits?.seven_day_opus);
1880
+ return Boolean(
1881
+ limits?.five_hour || limits?.seven_day || limits?.seven_day_opus ||
1882
+ (Array.isArray(limits?.weekly_scoped) && limits.weekly_scoped.length > 0),
1883
+ );
1884
+ }
1885
+
1886
+ // Cached scoped windows are filtered per-entry like the fixed windows: a scoped
1887
+ // window whose reset has passed is stale data, not a usable fallback.
1888
+ function normalizeClaudeCachedScopedWeekly(raw, { nowMs } = {}) {
1889
+ if (!Array.isArray(raw)) return null;
1890
+ const usable = raw.filter(
1891
+ (w) => w && typeof w.label === "string" && Number.isFinite(Number(w.utilization)) &&
1892
+ isClaudeCacheWindowUsable(w, { nowMs }),
1893
+ );
1894
+ return usable.length > 0 ? usable : null;
1852
1895
  }
1853
1896
 
1854
1897
  function normalizeClaudeCachedLimits(
@@ -1870,6 +1913,7 @@ function normalizeClaudeCachedLimits(
1870
1913
  five_hour: isClaudeCacheWindowUsable(raw?.five_hour, { nowMs }) ? raw.five_hour : null,
1871
1914
  seven_day: isClaudeCacheWindowUsable(raw?.seven_day, { nowMs }) ? raw.seven_day : null,
1872
1915
  seven_day_opus: isClaudeCacheWindowUsable(raw?.seven_day_opus, { nowMs }) ? raw.seven_day_opus : null,
1916
+ weekly_scoped: normalizeClaudeCachedScopedWeekly(raw?.weekly_scoped, { nowMs }),
1873
1917
  extra_usage: raw?.extra_usage ?? null,
1874
1918
  stale,
1875
1919
  cached_at: raw.cached_at,
@@ -1909,6 +1953,9 @@ function writeClaudeLimitsCache(limits, { home, nowMs = Date.now() } = {}) {
1909
1953
  five_hour: limits.five_hour || null,
1910
1954
  seven_day: limits.seven_day || null,
1911
1955
  seven_day_opus: limits.seven_day_opus || null,
1956
+ weekly_scoped: Array.isArray(limits.weekly_scoped) && limits.weekly_scoped.length > 0
1957
+ ? limits.weekly_scoped
1958
+ : null,
1912
1959
  extra_usage: limits.extra_usage || null,
1913
1960
  cached_at: new Date(nowMs).toISOString(),
1914
1961
  },
@@ -2646,6 +2693,7 @@ async function fetchUsageLimitsUncached({
2646
2693
  five_hour: claudeResult.value.five_hour,
2647
2694
  seven_day: claudeResult.value.seven_day,
2648
2695
  seven_day_opus: claudeResult.value.seven_day_opus,
2696
+ weekly_scoped: claudeResult.value.weekly_scoped,
2649
2697
  extra_usage: claudeResult.value.extra_usage,
2650
2698
  };
2651
2699
  writeClaudeLimitsCache(claude, { home, nowMs });