tokentracker-cli 0.44.0 → 0.45.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 (41) hide show
  1. package/dashboard/dist/assets/{ActivityHeatmap-C2y1lgOo.js → ActivityHeatmap-wlmadSUA.js} +1 -1
  2. package/dashboard/dist/assets/{Card-BJVoMVdB.js → Card-CK6OpUIW.js} +1 -1
  3. package/dashboard/dist/assets/{DashboardPage-NcjsaIbt.js → DashboardPage-ps2AXAKO.js} +1 -1
  4. package/dashboard/dist/assets/{DevicePage-EHZwN0AA.js → DevicePage-DB_mig-T.js} +1 -1
  5. package/dashboard/dist/assets/{DialogTitle-DVWJF7Sh.js → DialogTitle-CtaQVM8M.js} +1 -1
  6. package/dashboard/dist/assets/{FadeIn-DtXdVuFa.js → FadeIn-DfzGe4N4.js} +1 -1
  7. package/dashboard/dist/assets/{HeaderGithubStar-Cj_NuY82.js → HeaderGithubStar-y0yvef_C.js} +1 -1
  8. package/dashboard/dist/assets/{IpCheckPage-DZ4te6Pi.js → IpCheckPage-sVOOm10k.js} +1 -1
  9. package/dashboard/dist/assets/{LandingPage-CR9hpOA8.js → LandingPage-CjQgv7zi.js} +1 -1
  10. package/dashboard/dist/assets/{LeaderboardAvatar-DsQv0oYJ.js → LeaderboardAvatar-sdzTrleb.js} +1 -1
  11. package/dashboard/dist/assets/{LeaderboardPage-C6pR-fls.js → LeaderboardPage-DXvBEjG4.js} +3 -3
  12. package/dashboard/dist/assets/{LeaderboardProfileModal-DrAB9Pof.js → LeaderboardProfileModal-D1a65plB.js} +1 -1
  13. package/dashboard/dist/assets/{LeaderboardProfilePage-CMBVCK_9.js → LeaderboardProfilePage-DzjN7fxW.js} +1 -1
  14. package/dashboard/dist/assets/LimitsPage-DwBFiaav.js +2 -0
  15. package/dashboard/dist/assets/{LocalOnlyNotice-DysLhDFE.js → LocalOnlyNotice-LhhqHNKr.js} +1 -1
  16. package/dashboard/dist/assets/{LoginPage-jh8YcJtZ.js → LoginPage-DWRTQC0B.js} +1 -1
  17. package/dashboard/dist/assets/{PopoverPopup-DJt7HnL-.js → PopoverPopup-BRZ10YDe.js} +1 -1
  18. package/dashboard/dist/assets/{Select-16iq_C1U.js → Select-XpgQ4GWg.js} +1 -1
  19. package/dashboard/dist/assets/{SelectItemText-Bwctpnf1.js → SelectItemText-DgBDHxFj.js} +1 -1
  20. package/dashboard/dist/assets/{SettingsPage-BvA-0-6K.js → SettingsPage-CVk9jLOL.js} +1 -1
  21. package/dashboard/dist/assets/{SkillsPage-BCgd79rI.js → SkillsPage-Mk89JSte.js} +1 -1
  22. package/dashboard/dist/assets/WidgetsPage-D7y2Izbf.js +1 -0
  23. package/dashboard/dist/assets/{WrappedPage-CzyRJXb4.js → WrappedPage-DHLnWW3p.js} +1 -1
  24. package/dashboard/dist/assets/{agent-logos-3S7JvH_A.js → agent-logos-DZa_UVL5.js} +1 -1
  25. package/dashboard/dist/assets/{arrow-up-right-SUDWxkx-.js → arrow-up-right-9Yp14B47.js} +1 -1
  26. package/dashboard/dist/assets/{download-B06KpWLb.js → download-C4A4OPj1.js} +1 -1
  27. package/dashboard/dist/assets/{info-BYuw8wyW.js → info-4BytsGkj.js} +1 -1
  28. package/dashboard/dist/assets/{main-CZ7INQ5C.js → main-DdrbbegY.js} +7 -3
  29. package/dashboard/dist/assets/{use-limits-display-prefs-5el6WphI.js → use-limits-display-prefs-D8judXnf.js} +1 -1
  30. package/dashboard/dist/assets/{use-native-settings-BsOpSNnV.js → use-native-settings-q_6Jzz-U.js} +1 -1
  31. package/dashboard/dist/assets/use-usage-limits-yoVhgTFR.js +1 -0
  32. package/dashboard/dist/assets/{useCurrency-CjB3wfFx.js → useCurrency-Bid8-eMU.js} +1 -1
  33. package/dashboard/dist/assets/{useScrollLock-Dyho5BJU.js → useScrollLock-D2Y5Bu51.js} +1 -1
  34. package/dashboard/dist/index.html +1 -1
  35. package/dashboard/dist/share.html +1 -1
  36. package/package.json +1 -1
  37. package/src/lib/pricing/seed-snapshot.json +1 -1
  38. package/src/lib/usage-limits.js +263 -14
  39. package/dashboard/dist/assets/LimitsPage-CMAgr4sd.js +0 -2
  40. package/dashboard/dist/assets/WidgetsPage-DecKPwRh.js +0 -1
  41. package/dashboard/dist/assets/use-usage-limits-BgRs0aJ1.js +0 -1
@@ -30,6 +30,19 @@ const DEFAULT_PROVIDER_TIMEOUT_MS = 15_000;
30
30
  const ANTIGRAVITY_LIMITS_CACHE_FILE = "usage-limits-cache.json";
31
31
  const ANTIGRAVITY_LIMITS_CACHE_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
32
32
  const ANTIGRAVITY_LIMITS_CACHE_UNKNOWN_RESET_TTL_MS = 12 * 60 * 60 * 1000;
33
+ // Claude shares its OAuth usage endpoint budget with Claude Code itself, so a transient
34
+ // 429 is common. Persist the last successful read so the panel can keep showing it instead
35
+ // of flashing a red error. Separate file from Antigravity's (whose writer rewrites the whole
36
+ // file with only its own key, so a shared file would clobber).
37
+ const CLAUDE_LIMITS_CACHE_FILE = "claude-usage-limits-cache.json";
38
+ const CLAUDE_LIMITS_CACHE_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
39
+ // A 429 from the usage endpoint carries a long `retry-after` (often 20+ minutes). Persist
40
+ // the cooldown so every surface — this process, the menu bar app's embedded server, a later
41
+ // restart — stops calling until it expires. Hammering during the cooldown just renews the
42
+ // penalty, which is what kept the panel stuck on the error.
43
+ const CLAUDE_RATE_LIMIT_FILE = "claude-usage-rate-limit.json";
44
+ const CLAUDE_RATE_LIMIT_DEFAULT_COOLDOWN_SEC = 5 * 60;
45
+ const CLAUDE_RATE_LIMIT_MAX_COOLDOWN_SEC = 60 * 60;
33
46
 
34
47
  function clampPercent(value) {
35
48
  if (value === null || value === undefined || value === "") return null;
@@ -99,6 +112,20 @@ function withProviderTimeout(promise, label, timeoutMs) {
99
112
  return Promise.race([promise, timeout]).finally(() => clearTimeout(timer));
100
113
  }
101
114
 
115
+ function parseRetryAfterSeconds(headers) {
116
+ const ra = headers?.get ? headers.get("retry-after") : null;
117
+ const sec = ra ? Number.parseInt(ra, 10) : NaN;
118
+ return Number.isFinite(sec) && sec > 0 ? sec : null;
119
+ }
120
+
121
+ function formatClaudeRateLimitMessage(retryAfterSec) {
122
+ if (Number.isFinite(retryAfterSec) && retryAfterSec > 0) {
123
+ const mins = Math.ceil(retryAfterSec / 60);
124
+ return `Claude API rate limited (429) — retry in ~${mins}m.`;
125
+ }
126
+ return "Claude API rate limited (429) — retry shortly.";
127
+ }
128
+
102
129
  async function fetchClaudeUsageLimits(accessToken, { fetchImpl = fetch, maxAttempts = 3 } = {}) {
103
130
  const url = "https://api.anthropic.com/api/oauth/usage";
104
131
  const headers = {
@@ -120,9 +147,11 @@ async function fetchClaudeUsageLimits(accessToken, { fetchImpl = fetch, maxAttem
120
147
  }
121
148
  if (!res.ok) {
122
149
  if (res.status === 429) {
123
- throw new Error(
124
- "Claude API rate limited (429) — wait ~1 minute and refresh.",
125
- );
150
+ const retryAfterSec = parseRetryAfterSeconds(res.headers);
151
+ const err = new Error(formatClaudeRateLimitMessage(retryAfterSec));
152
+ err.code = "RATE_LIMITED";
153
+ err.retryAfterSec = retryAfterSec;
154
+ throw err;
126
155
  }
127
156
  throw new Error(`Claude API returned ${res.status}`);
128
157
  }
@@ -152,10 +181,20 @@ function classifyCodexWindow(window) {
152
181
  return null;
153
182
  }
154
183
 
184
+ function normalizeCodexRateWindow(window) {
185
+ if (!window || typeof window !== "object" || Array.isArray(window)) return null;
186
+ const usedPercent = clampPercent(window.used_percent);
187
+ if (usedPercent === null) return null;
188
+ return {
189
+ ...window,
190
+ used_percent: Math.round(usedPercent),
191
+ };
192
+ }
193
+
155
194
  function normalizeCodexRateWindows(rateLimit) {
156
- const candidates = [rateLimit?.primary_window, rateLimit?.secondary_window].filter(
157
- (w) => w && typeof w === "object",
158
- );
195
+ const primary = normalizeCodexRateWindow(rateLimit?.primary_window);
196
+ const secondary = normalizeCodexRateWindow(rateLimit?.secondary_window);
197
+ const candidates = [primary, secondary].filter(Boolean);
159
198
  let session = null;
160
199
  let weekly = null;
161
200
  for (const w of candidates) {
@@ -167,13 +206,88 @@ function normalizeCodexRateWindows(rateLimit) {
167
206
  // from unexpected window durations rather than dropping it silently.
168
207
  if (!session && !weekly && candidates.length > 0) {
169
208
  return {
170
- primary_window: candidates[0] ?? null,
171
- secondary_window: candidates[1] ?? null,
209
+ primary_window: primary,
210
+ secondary_window: secondary,
172
211
  };
173
212
  }
174
213
  return { primary_window: session, secondary_window: weekly };
175
214
  }
176
215
 
216
+ function isCodexSparkLimit(entry) {
217
+ if (!entry || typeof entry !== "object") return false;
218
+ return [entry.limit_name, entry.metered_feature].some((value) => (
219
+ typeof value === "string" && value.trim().toLowerCase().includes("spark")
220
+ ));
221
+ }
222
+
223
+ function codexSparkFallbackCandidates(primary, secondary) {
224
+ const primaryKind = classifyCodexWindow(primary);
225
+ const secondaryKind = classifyCodexWindow(secondary);
226
+ const out = [];
227
+ const primaryDurationMissing = primary
228
+ && (primary.limit_window_seconds === undefined
229
+ || primary.limit_window_seconds === null
230
+ || primary.limit_window_seconds === "");
231
+
232
+ if (primaryKind || secondaryKind) {
233
+ if (!primaryKind && primary && secondaryKind === "weekly") {
234
+ out.push({ kind: "session", window: primary });
235
+ }
236
+ if (!primaryKind && primaryDurationMissing && secondaryKind === "session") {
237
+ out.push({ kind: "weekly", window: primary });
238
+ }
239
+ if (!secondaryKind && secondary && primaryKind === "weekly") {
240
+ out.push({ kind: "session", window: secondary });
241
+ }
242
+ if (!secondaryKind && secondary && primaryKind === "session") {
243
+ out.push({ kind: "weekly", window: secondary });
244
+ }
245
+ return out;
246
+ }
247
+
248
+ if (primary) out.push({ kind: "session", window: primary });
249
+ if (secondary) out.push({ kind: "weekly", window: secondary });
250
+ return out;
251
+ }
252
+
253
+ function normalizeCodexSparkRateWindows(additionalRateLimits) {
254
+ let session = null;
255
+ let weekly = null;
256
+ if (!Array.isArray(additionalRateLimits)) {
257
+ return { spark_primary_window: null, spark_secondary_window: null };
258
+ }
259
+
260
+ const classifiedCandidates = [];
261
+ const fallbackCandidates = [];
262
+ for (const entry of additionalRateLimits) {
263
+ if (!isCodexSparkLimit(entry)) continue;
264
+ const rateLimit = entry.rate_limit;
265
+ if (!rateLimit || typeof rateLimit !== "object") continue;
266
+
267
+ const primary = normalizeCodexRateWindow(rateLimit.primary_window);
268
+ const secondary = normalizeCodexRateWindow(rateLimit.secondary_window);
269
+ for (const window of [primary, secondary]) {
270
+ const kind = classifyCodexWindow(window);
271
+ if (kind) classifiedCandidates.push({ kind, window });
272
+ }
273
+ fallbackCandidates.push(...codexSparkFallbackCandidates(primary, secondary));
274
+ }
275
+
276
+ for (const candidate of classifiedCandidates) {
277
+ if (candidate.kind === "session" && !session) session = candidate.window;
278
+ else if (candidate.kind === "weekly" && !weekly) weekly = candidate.window;
279
+ }
280
+ for (const candidate of fallbackCandidates) {
281
+ if (candidate.kind === "session" && !session) session = candidate.window;
282
+ else if (candidate.kind === "weekly" && !weekly) weekly = candidate.window;
283
+ }
284
+
285
+ return {
286
+ spark_primary_window: session,
287
+ spark_secondary_window: weekly,
288
+ };
289
+ }
290
+
177
291
  async function fetchCodexUsageLimits(
178
292
  accessToken,
179
293
  { fetchImpl = fetch, accountId = null } = {},
@@ -195,13 +309,21 @@ async function fetchCodexUsageLimits(
195
309
  // 401/403/404 from wham means "no usage data available for this auth state" — render
196
310
  // a neutral empty state instead of a red "Fetch failed" error.
197
311
  if (res.status === 401 || res.status === 403 || res.status === 404) {
198
- return { primary_window: null, secondary_window: null };
312
+ return {
313
+ primary_window: null,
314
+ secondary_window: null,
315
+ spark_primary_window: null,
316
+ spark_secondary_window: null,
317
+ };
199
318
  }
200
319
  if (!res.ok) {
201
320
  throw new Error(`Codex API returned ${res.status}`);
202
321
  }
203
322
  const body = await res.json();
204
- return normalizeCodexRateWindows(body.rate_limit || {});
323
+ return {
324
+ ...normalizeCodexRateWindows(body.rate_limit || {}),
325
+ ...normalizeCodexSparkRateWindows(body.additional_rate_limits),
326
+ };
205
327
  }
206
328
 
207
329
  function cursorPercentFromCentsUsedLimit(usedRaw, limitRaw) {
@@ -1271,6 +1393,107 @@ function writeAntigravityLimitsCache(limits, { home, nowMs = Date.now() } = {})
1271
1393
  } catch (_error) {}
1272
1394
  }
1273
1395
 
1396
+ function resolveClaudeLimitsCachePath({ home } = {}) {
1397
+ return path.join(home || os.homedir(), ".tokentracker", "tracker", CLAUDE_LIMITS_CACHE_FILE);
1398
+ }
1399
+
1400
+ // Claude windows carry their own `resets_at`; a window whose reset has already passed is
1401
+ // stale data, not a usable fallback, so drop it. Windows without a reset stamp are kept
1402
+ // (the overall cached_at max-age gate already bounds them).
1403
+ function isClaudeCacheWindowUsable(window, { nowMs } = {}) {
1404
+ if (!window || typeof window !== "object") return false;
1405
+ const resetAtMs = parseTimeMs(window.resets_at);
1406
+ if (resetAtMs === null) return true;
1407
+ return resetAtMs > nowMs;
1408
+ }
1409
+
1410
+ function hasClaudeWindow(limits) {
1411
+ return Boolean(limits?.five_hour || limits?.seven_day || limits?.seven_day_opus);
1412
+ }
1413
+
1414
+ function normalizeClaudeCachedLimits(raw, { nowMs = Date.now() } = {}) {
1415
+ const cachedAtMs = parseTimeMs(raw?.cached_at);
1416
+ if (!Number.isFinite(cachedAtMs)) return null;
1417
+ if (cachedAtMs > nowMs + 60_000) return null;
1418
+ if (nowMs - cachedAtMs > CLAUDE_LIMITS_CACHE_MAX_AGE_MS) return null;
1419
+
1420
+ const cached = {
1421
+ configured: true,
1422
+ error: null,
1423
+ five_hour: isClaudeCacheWindowUsable(raw?.five_hour, { nowMs }) ? raw.five_hour : null,
1424
+ seven_day: isClaudeCacheWindowUsable(raw?.seven_day, { nowMs }) ? raw.seven_day : null,
1425
+ seven_day_opus: isClaudeCacheWindowUsable(raw?.seven_day_opus, { nowMs }) ? raw.seven_day_opus : null,
1426
+ extra_usage: raw?.extra_usage ?? null,
1427
+ stale: true,
1428
+ cached_at: raw.cached_at,
1429
+ };
1430
+ return hasClaudeWindow(cached) ? cached : null;
1431
+ }
1432
+
1433
+ function readClaudeLimitsCache({ home, nowMs = Date.now() } = {}) {
1434
+ const cachePath = resolveClaudeLimitsCachePath({ home });
1435
+ try {
1436
+ const parsed = JSON.parse(fs.readFileSync(cachePath, "utf8"));
1437
+ return normalizeClaudeCachedLimits(parsed?.claude, { nowMs });
1438
+ } catch (_error) {
1439
+ return null;
1440
+ }
1441
+ }
1442
+
1443
+ function writeClaudeLimitsCache(limits, { home, nowMs = Date.now() } = {}) {
1444
+ if (!limits?.configured || limits.error || !hasClaudeWindow(limits)) return;
1445
+ const cachePath = resolveClaudeLimitsCachePath({ home });
1446
+ const payload = {
1447
+ claude: {
1448
+ five_hour: limits.five_hour || null,
1449
+ seven_day: limits.seven_day || null,
1450
+ seven_day_opus: limits.seven_day_opus || null,
1451
+ extra_usage: limits.extra_usage || null,
1452
+ cached_at: new Date(nowMs).toISOString(),
1453
+ },
1454
+ };
1455
+ try {
1456
+ fs.mkdirSync(path.dirname(cachePath), { recursive: true });
1457
+ const tmpPath = `${cachePath}.${process.pid}.tmp`;
1458
+ fs.writeFileSync(tmpPath, JSON.stringify(payload, null, 2), { encoding: "utf8", mode: 0o600 });
1459
+ fs.renameSync(tmpPath, cachePath);
1460
+ } catch (_error) {}
1461
+ }
1462
+
1463
+ function resolveClaudeRateLimitPath({ home } = {}) {
1464
+ return path.join(home || os.homedir(), ".tokentracker", "tracker", CLAUDE_RATE_LIMIT_FILE);
1465
+ }
1466
+
1467
+ // Returns the cooldown expiry in ms if a 429 cooldown is still active, else null.
1468
+ function readClaudeRateLimitRetryAtMs({ home, nowMs = Date.now() } = {}) {
1469
+ try {
1470
+ const parsed = JSON.parse(fs.readFileSync(resolveClaudeRateLimitPath({ home }), "utf8"));
1471
+ const retryAtMs = parseTimeMs(parsed?.retry_at);
1472
+ if (retryAtMs !== null && retryAtMs > nowMs) return retryAtMs;
1473
+ } catch (_error) {}
1474
+ return null;
1475
+ }
1476
+
1477
+ function writeClaudeRateLimitCooldown(retryAfterSec, { home, nowMs = Date.now() } = {}) {
1478
+ const sec = Number.isFinite(retryAfterSec) && retryAfterSec > 0
1479
+ ? Math.min(retryAfterSec, CLAUDE_RATE_LIMIT_MAX_COOLDOWN_SEC)
1480
+ : CLAUDE_RATE_LIMIT_DEFAULT_COOLDOWN_SEC;
1481
+ const cachePath = resolveClaudeRateLimitPath({ home });
1482
+ const payload = { retry_at: new Date(nowMs + sec * 1000).toISOString() };
1483
+ try {
1484
+ fs.mkdirSync(path.dirname(cachePath), { recursive: true });
1485
+ const tmpPath = `${cachePath}.${process.pid}.tmp`;
1486
+ fs.writeFileSync(tmpPath, JSON.stringify(payload, null, 2), { encoding: "utf8", mode: 0o600 });
1487
+ fs.renameSync(tmpPath, cachePath);
1488
+ } catch (_error) {}
1489
+ }
1490
+
1491
+ function clearClaudeRateLimitCooldown({ home } = {}) {
1492
+ try {
1493
+ fs.unlinkSync(resolveClaudeRateLimitPath({ home }));
1494
+ } catch (_error) {}
1495
+ }
1496
+
1274
1497
  function resolveLsofBinary({ commandRunner } = {}) {
1275
1498
  for (const candidate of ["/usr/sbin/lsof", "/usr/bin/lsof"]) {
1276
1499
  if (fs.existsSync(candidate)) return candidate;
@@ -1698,9 +1921,13 @@ async function getUsageLimits({
1698
1921
  const codexAccountId = codexAuthRefreshed?.accountId || null;
1699
1922
  const codexPlanType = codexAuthRefreshed?.planType || null;
1700
1923
 
1924
+ // Skip the upstream Claude call entirely while a 429 cooldown is active — calling again
1925
+ // just renews the penalty. The result handling below serves cache or a cooldown message.
1926
+ const claudeRetryAtMs = claudeToken ? readClaudeRateLimitRetryAtMs({ home, nowMs }) : null;
1927
+
1701
1928
  const providerFetch = withFetchTimeout(fetchImpl, providerTimeoutMs);
1702
1929
  const [claudeResult, codexResult, cursor, kimi, gemini, kiro, antigravity, copilot, grok] = await Promise.all([
1703
- claudeToken
1930
+ claudeToken && !claudeRetryAtMs
1704
1931
  ? withProviderTimeout(fetchClaudeUsageLimits(claudeToken, { fetchImpl: providerFetch, maxAttempts: 1 }), "Claude", providerTimeoutMs).then(
1705
1932
  (value) => ({ status: "fulfilled", value }),
1706
1933
  (reason) => ({ status: "rejected", reason }),
@@ -1733,9 +1960,7 @@ async function getUsageLimits({
1733
1960
  let claude;
1734
1961
  if (!claudeToken) {
1735
1962
  claude = { configured: false };
1736
- } else if (!claudeResult || claudeResult.status === "rejected") {
1737
- claude = { configured: true, error: claudeResult?.reason?.message || "Unknown error" };
1738
- } else {
1963
+ } else if (claudeResult && claudeResult.status === "fulfilled") {
1739
1964
  claude = {
1740
1965
  configured: true,
1741
1966
  error: null,
@@ -1744,6 +1969,28 @@ async function getUsageLimits({
1744
1969
  seven_day_opus: claudeResult.value.seven_day_opus,
1745
1970
  extra_usage: claudeResult.value.extra_usage,
1746
1971
  };
1972
+ writeClaudeLimitsCache(claude, { home, nowMs });
1973
+ clearClaudeRateLimitCooldown({ home });
1974
+ } else {
1975
+ // Either a fresh 429 (record its cooldown) or a call we skipped because a cooldown was
1976
+ // already active. Serve the last successful read so the bars stay visible; otherwise
1977
+ // surface an accurate "retry in ~Nm" message rather than the misleading hardcoded one.
1978
+ const reason = claudeResult?.reason;
1979
+ if (reason?.code === "RATE_LIMITED") {
1980
+ writeClaudeRateLimitCooldown(reason.retryAfterSec, { home, nowMs });
1981
+ }
1982
+ const cached = readClaudeLimitsCache({ home, nowMs });
1983
+ if (cached) {
1984
+ claude = cached;
1985
+ } else {
1986
+ const retryAtMs = readClaudeRateLimitRetryAtMs({ home, nowMs }) || claudeRetryAtMs;
1987
+ claude = {
1988
+ configured: true,
1989
+ error: retryAtMs
1990
+ ? formatClaudeRateLimitMessage(Math.round((retryAtMs - nowMs) / 1000))
1991
+ : reason?.message || "Unknown error",
1992
+ };
1993
+ }
1747
1994
  }
1748
1995
 
1749
1996
  let codex;
@@ -1766,6 +2013,8 @@ async function getUsageLimits({
1766
2013
  plan_type: codexPlanType || null,
1767
2014
  primary_window: codexResult.value.primary_window,
1768
2015
  secondary_window: codexResult.value.secondary_window,
2016
+ spark_primary_window: codexResult.value.spark_primary_window,
2017
+ spark_secondary_window: codexResult.value.spark_secondary_window,
1769
2018
  };
1770
2019
  }
1771
2020
 
@@ -1,2 +0,0 @@
1
- import{j as i,V as _,G as o,U as E,r as P,aG as K,i as R,L as S,aH as M}from"./main-CZ7INQ5C.js";import{u as O}from"./use-usage-limits-BgRs0aJ1.js";import{L as s,a as T,l as y,b as C,u as D}from"./use-limits-display-prefs-5el6WphI.js";import{C as k}from"./Card-BJVoMVdB.js";import{F as A}from"./FadeIn-DtXdVuFa.js";import{L as F}from"./LocalOnlyNotice-DysLhDFE.js";import"./arrow-up-right-SUDWxkx-.js";import"./download-B06KpWLb.js";const $=[3,2,3,3,2,2,3];function d({className:e}){return i.jsx("div",{className:_("rounded bg-oai-gray-200/70 dark:bg-oai-gray-800/70 animate-pulse",e)})}function G(){return i.jsxs("div",{className:"flex items-center gap-2",children:[i.jsx(d,{className:"h-3 w-12 shrink-0"}),i.jsx(d,{className:"flex-1 h-1.5 rounded-full min-w-0"}),i.jsx(d,{className:"h-3 w-[30px] shrink-0"}),i.jsx(d,{className:"h-3 w-6 shrink-0"})]})}function H({bars:e,index:t}){const r=t%3===0?"w-24":t%3===1?"w-20":"w-[4.5rem]";return i.jsxs("div",{className:"flex flex-col gap-1.5",children:[i.jsxs("div",{className:"flex items-center gap-1.5",children:[i.jsx(d,{className:"h-[14px] w-[14px] rounded shrink-0"}),i.jsx(d,{className:_("h-4",r)})]}),Array.from({length:e},(l,a)=>i.jsx(G,{},a))]})}function B(){return i.jsx(k,{children:i.jsxs("div",{className:"flex flex-col gap-3",children:[i.jsx(d,{className:"h-3.5 w-28"}),$.map((e,t)=>i.jsx(H,{bars:e,index:t},t))]})})}const j={claude:{windows(e){return[{key:"5h",labelKey:"limits.label.claude_5h",window:e.five_hour,pctField:"utilization",resetField:"resets_at"},{key:"7d",labelKey:"limits.label.claude_7d",window:e.seven_day,pctField:"utilization",resetField:"resets_at"},{key:"opus",labelKey:"limits.label.claude_opus",window:e.seven_day_opus,pctField:"utilization",resetField:"resets_at"}]}},codex:{windows(e){return[{key:"5h",labelKey:"limits.label.codex_5h",window:e.primary_window},{key:"7d",labelKey:"limits.label.codex_7d",window:e.secondary_window}]}},cursor:{windows(e){return[{key:"plan",labelKey:"limits.label.cursor_plan",window:e.primary_window},{key:"auto",labelKey:"limits.label.cursor_auto",window:e.secondary_window},{key:"api",labelKey:"limits.label.cursor_api",window:e.tertiary_window}]}},gemini:{windows(e){return[{key:"pro",labelKey:"limits.label.gemini_pro",window:e.primary_window},{key:"flash",labelKey:"limits.label.gemini_flash",window:e.secondary_window},{key:"lite",labelKey:"limits.label.gemini_lite",window:e.tertiary_window}]}},kimi:{extra:"kimi_parallel",windows(e){return[{key:"weekly",labelKey:"limits.label.kimi_weekly",window:e.primary_window},{key:"5h",labelKey:"limits.label.kimi_5h",window:e.secondary_window},{key:"total",labelKey:"limits.label.kimi_total",window:e.tertiary_window}]}},kiro:{windows(e){return[{key:"month",labelKey:"limits.label.kiro_month",window:e.primary_window},{key:"bonus",labelKey:"limits.label.kiro_bonus",window:e.secondary_window}]}},grok:{windows(e){return[{key:"month",labelKey:"limits.label.grok_month",window:e.primary_window},{key:"ondemand",labelKey:"limits.label.grok_ondemand",window:e.secondary_window}]}},antigravity:{windows(e){return[{key:"claude",labelKey:"limits.label.antigravity_claude",window:e.primary_window},{key:"gpro",labelKey:"limits.label.antigravity_gpro",window:e.secondary_window},{key:"flash",labelKey:"limits.label.antigravity_flash",window:e.tertiary_window}]}},copilot:{extra:"copilot_otel",windows(e){return[{key:"premium",labelKey:"limits.label.copilot_premium",window:e.primary_window},{key:"chat",labelKey:"limits.label.copilot_chat",window:e.secondary_window}]}}},U="shrink-0 text-oai-black dark:text-oai-white";function z(e){if(!e)return null;const t=typeof e=="number"?e*1e3:Date.parse(e);if(!Number.isFinite(t))return null;const r=t-Date.now();if(r<=0)return o("shared.time.now");const l=Math.floor(r/6e4);if(l<60)return`${l}m`;const a=Math.floor(l/60);return a<24?`${a}h`:`${Math.floor(a/24)}d`}function W(e,t){const r=t===s.REMAINING?100-e:e;return r>=90?"bg-red-500":r>=70?"bg-amber-500":"bg-emerald-500"}function V({label:e,pct:t,reset:r,mode:l=s.USED}){const a=Math.max(0,Math.min(100,Number(t)||0)),n=l===s.REMAINING?100-a:a,c=Math.round(n),w=n>0&&c===0?Math.max(n,.35):n;let u=String(c);return n>0&&c===0&&(u=o("limits.bar.sub_one_percent")),i.jsxs("div",{className:"flex items-center gap-2",children:[i.jsx("span",{className:"text-[11px] text-oai-gray-500 dark:text-oai-gray-400 w-12 shrink-0",children:e}),i.jsx("div",{className:"flex-1 bg-oai-gray-100 dark:bg-oai-gray-700/50 rounded-full h-1.5 overflow-hidden",children:i.jsx("div",{className:`${W(n,l)} rounded-full h-full transition-[width] duration-500 ease-out`,style:{width:`${w}%`,minWidth:n>0?"3px":0}})}),i.jsxs("span",{className:"text-[11px] tabular-nums text-oai-gray-500 dark:text-oai-gray-400 w-9 text-right shrink-0 whitespace-nowrap",children:[u,"%"]}),r&&i.jsx("span",{className:"text-[10px] text-oai-gray-400 dark:text-oai-gray-500 w-6 text-right shrink-0",children:r})]})}function h({name:e,providerId:t,children:r}){const l=C(t);return i.jsxs("div",{className:"flex flex-col gap-1.5",children:[i.jsxs("div",{className:"flex items-center gap-1.5",children:[l?i.jsx(E,{provider:l,size:14,className:U}):null,i.jsx("span",{className:"text-sm font-medium text-oai-black dark:text-oai-white",children:e})]}),r]})}const Y=T;function m({children:e,tone:t="neutral"}){const r=t==="error"?"text-red-600 dark:text-red-400":"text-oai-gray-500 dark:text-oai-gray-400";return i.jsx("div",{className:`text-[11px] leading-snug ${r}`,children:e})}function X(e,t="used_percent"){return e?t==="utilization"?e.utilization:e.used_percent:null}function q(e,t="reset_at"){return e?t==="resets_at"?e.resets_at:e.reset_at:null}function J(e,t){return e.filter(r=>r.window).map(r=>i.jsx(V,{label:o(r.labelKey),pct:X(r.window,r.pctField),reset:z(q(r.window,r.resetField)),mode:t},r.key))}function Q({specs:e,mode:t,extra:r=null}){const l=J(e,t),a=l.length===0&&!r;return i.jsxs(i.Fragment,{children:[l,a?i.jsx(m,{children:o("limits.status.no_data")}):null,r]})}function Z(e,t,r,l,a=null){return i.jsx(h,{name:t,providerId:e,children:i.jsx(Q,{mode:r,specs:l,extra:a})},e)}function ee(e,t){return e==="kimi_parallel"&&t.parallel_limit?i.jsx(m,{children:o("limits.label.kimi_parallel",{count:t.parallel_limit})}):e==="copilot_otel"&&!t.otel_has_files&&!t.otel_enabled?i.jsx(re,{defaultDir:t.otel_default_dir}):null}function ie(e,t,r,l){const a=j[e];return a?Z(e,r,l,a.windows(t),ee(a.extra,t)):null}function te(e,t,r){if(!j[e])return null;if(!t?.configured)return i.jsx(h,{name:y(e),providerId:e,children:i.jsx(m,{children:o("limits.status.not_connected")})},e);if(t.error)return i.jsx(h,{name:y(e),providerId:e,children:i.jsx(m,{tone:"error",children:o("shared.error.prefix",{error:t.error})})},e);const l=y(e),a=t.plan_label?`${l} ${t.plan_label}`:l;return ie(e,t,a,r)}function re({defaultDir:e}){const[t,r]=P.useState(!1),a=["export COPILOT_OTEL_ENABLED=true","export COPILOT_OTEL_EXPORTER_TYPE=file",`export COPILOT_OTEL_FILE_EXPORTER_PATH="${e||"$HOME/.copilot/otel"}/copilot-otel-$(date +%Y%m%d).jsonl"`].join(`
2
- `),n=async()=>{try{await navigator.clipboard.writeText(a),r(!0),setTimeout(()=>r(!1),1600)}catch{}};return i.jsxs("div",{className:"mt-1 rounded-md border border-amber-300/60 dark:border-amber-700/40 bg-amber-50/50 dark:bg-amber-900/10 px-2.5 py-2 text-[11px] text-oai-gray-600 dark:text-oai-gray-300",children:[i.jsx("div",{className:"font-medium text-oai-gray-700 dark:text-oai-gray-200",children:o("limits.copilot.otelHint.title")}),i.jsx("div",{className:"mt-0.5 leading-snug",children:o("limits.copilot.otelHint.body")}),i.jsx("pre",{className:"mt-1.5 overflow-x-auto rounded bg-oai-gray-100 dark:bg-oai-gray-900/60 px-2 py-1.5 font-mono text-[10.5px] leading-tight whitespace-pre",children:a}),i.jsx("button",{type:"button",onClick:n,className:"mt-1 inline-flex items-center gap-1 rounded border border-oai-gray-300 dark:border-oai-gray-700 px-1.5 py-0.5 text-[10.5px] text-oai-gray-700 dark:text-oai-gray-200 hover:bg-oai-gray-100 dark:hover:bg-oai-gray-800 transition-colors",children:t?o("limits.copilot.otelHint.copied"):o("limits.copilot.otelHint.copy")})]})}function ae({claude:e,codex:t,cursor:r,gemini:l,kimi:a,kiro:n,grok:c,antigravity:w,copilot:u,order:p,visibility:f,displayMode:N}){const v={claude:e,codex:t,cursor:r,gemini:l,kimi:a,kiro:n,grok:c,antigravity:w,copilot:u},I=Array.isArray(p)&&p.length>0?p:Y,b=N===s.REMAINING?s.REMAINING:s.USED,L=b===s.REMAINING?o("limits.settings.display_mode_remaining"):o("limits.settings.display_mode_used"),g=I.filter(x=>!f||f[x]!==!1).map(x=>te(x,v[x],b)).filter(Boolean);return i.jsx(A,{delay:.15,children:i.jsx(k,{children:i.jsxs("div",{className:"flex flex-col gap-3",children:[i.jsxs("h3",{className:"text-sm font-medium text-oai-gray-500 dark:text-oai-gray-300 uppercase tracking-wide",children:[o("limits.panel.title"),o("limits.panel.mode_separator"),L]}),g.length>0?g:i.jsx(m,{children:o("limits.status.all_hidden")})]})})})}const le=typeof window<"u"&&(window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1");function we(){const e=K(),{data:t,error:r,isLoading:l}=O(e?{initialRefresh:!0,initialState:e,publishToPreloadCache:!0}:{initialRefresh:!0,publishToPreloadCache:!0}),a=D();return!le&&!R()?i.jsx("div",{className:"flex flex-col flex-1 text-oai-black dark:text-oai-white font-oai antialiased",children:i.jsx(F,{})}):i.jsx("div",{className:"flex flex-col flex-1 text-oai-black dark:text-oai-white font-oai antialiased",children:i.jsx("main",{className:"flex-1 pt-8 sm:pt-10 pb-12 sm:pb-16",children:i.jsxs("div",{className:"mx-auto max-w-6xl px-4 sm:px-6",children:[i.jsxs("div",{className:"flex flex-row items-start justify-between gap-4 mb-8",children:[i.jsxs("div",{className:"min-w-0",children:[i.jsx("h1",{className:"text-3xl sm:text-4xl font-semibold tracking-tight text-oai-black dark:text-white mb-3",children:o("nav.limits")}),i.jsx("p",{className:"text-oai-gray-500 dark:text-oai-gray-400 text-sm sm:text-base",children:o("limits.page.subtitle")})]}),i.jsx(S,{to:"/settings","aria-label":o("limits.page.openSettings"),title:o("limits.page.openSettings"),className:"shrink-0 inline-flex h-9 w-9 items-center justify-center rounded-lg border border-oai-gray-200 dark:border-oai-gray-800 text-oai-gray-600 dark:text-oai-gray-400 hover:bg-oai-gray-100 dark:hover:bg-oai-gray-800 hover:text-oai-black dark:hover:text-white transition-colors no-underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-oai-brand-500",children:i.jsx(M,{className:"h-4 w-4","aria-hidden":!0})})]}),l?i.jsx(B,{}):i.jsxs(i.Fragment,{children:[r?i.jsx("p",{className:"mb-4 text-sm text-red-500 dark:text-red-400",children:o("shared.error.prefix",{error:r})}):null,i.jsx(ae,{claude:t?.claude,codex:t?.codex,cursor:t?.cursor,gemini:t?.gemini,kimi:t?.kimi,kiro:t?.kiro,grok:t?.grok,antigravity:t?.antigravity,copilot:t?.copilot,order:a.order,visibility:a.visibility,displayMode:a.displayMode})]})]})})})}export{we as LimitsPage};
@@ -1 +0,0 @@
1
- import{j as e,G as o,c3 as _,aR as P,r as u,a_ as I,R as B,V as M}from"./main-CZ7INQ5C.js";import{S as D}from"./Select-16iq_C1U.js";import{u as E,T as K}from"./use-native-settings-BsOpSNnV.js";import{F as j,S as G,a as $}from"./FadeIn-DtXdVuFa.js";import{A as z}from"./arrow-up-right-SUDWxkx-.js";import{D as R}from"./download-B06KpWLb.js";import"./SelectItemText-Bwctpnf1.js";import"./useScrollLock-Dyho5BJU.js";import"./Card-BJVoMVdB.js";const H=["todayTokens","todayCost"],F=[{id:"todayTokens",label:"Today Tokens",shortLabel:"Tokens",category:"tokens"},{id:"todayCost",label:"Today Cost",shortLabel:"Cost",category:"cost"},{id:"last7dTokens",label:"Last 7 Days",shortLabel:"7d",category:"tokens"},{id:"totalTokens",label:"Total Tokens",shortLabel:"Total",category:"tokens"},{id:"totalCost",label:"Total Cost",shortLabel:"All $",category:"cost"},{id:"claude5h",label:"Claude 5h Limit",shortLabel:"Cl 5h",category:"limits"},{id:"claude7d",label:"Claude 7d Limit",shortLabel:"Cl 7d",category:"limits"},{id:"codex5h",label:"Codex 5h Limit",shortLabel:"Cx 5h",category:"limits"},{id:"codex7d",label:"Codex 7d Limit",shortLabel:"Cx 7d",category:"limits"},{id:"cursorPlan",label:"Cursor Plan Limit",shortLabel:"Cu Plan",category:"limits"},{id:"cursorAuto",label:"Cursor Auto Limit",shortLabel:"Cu Auto",category:"limits"},{id:"cursorAPI",label:"Cursor API Limit",shortLabel:"Cu API",category:"limits"},{id:"geminiPro",label:"Gemini Pro Limit",shortLabel:"Gm Pro",category:"limits"},{id:"geminiFlash",label:"Gemini Flash Limit",shortLabel:"Gm Flash",category:"limits"},{id:"geminiLite",label:"Gemini Lite Limit",shortLabel:"Gm Lite",category:"limits"},{id:"kimiWeekly",label:"Kimi Weekly Limit",shortLabel:"Km Wk",category:"limits"},{id:"kimi5h",label:"Kimi 5h Limit",shortLabel:"Km 5h",category:"limits"},{id:"kimiTotal",label:"Kimi Total Limit",shortLabel:"Km Tot",category:"limits"},{id:"kiroMonth",label:"Kiro Monthly Limit",shortLabel:"Kr Mo",category:"limits"},{id:"kiroBonus",label:"Kiro Bonus Limit",shortLabel:"Kr Bn",category:"limits"},{id:"copilotPremium",label:"Copilot Premium Limit",shortLabel:"Co Prem",category:"limits"},{id:"copilotChat",label:"Copilot Chat Limit",shortLabel:"Co Chat",category:"limits"},{id:"antigravityClaude",label:"Antigravity Claude Limit",shortLabel:"Ag Cl",category:"limits"},{id:"antigravityGPro",label:"Antigravity Gemini Pro Limit",shortLabel:"Ag GPro",category:"limits"},{id:"antigravityFlash",label:"Antigravity Flash Limit",shortLabel:"Ag Fl",category:"limits"}];function v(t,i=F,r=2){const a=new Set(i.map(n=>n.id)),l=new Set,s=Array.isArray(t)?t.filter(n=>!a.has(n)||l.has(n)?!1:(l.add(n),!0)):[];return(s.length>0?s:H).slice(0,Math.max(1,Number(r)||2))}const O=264,U=124,g="ui-rounded, -apple-system, system-ui",L=["#5A8CF2","#9973E6","#4DB8A6","#E68C59"],V={claude:"#C77DFF",codex:"#34C759",cursor:"#FFCC00",gemini:"#0A84FF"};function X(t){return t>=.9?"#E64D4D":t>=.7?"#D9A633":"#33B866"}function b({size:t="sm",children:i}){const r=t==="lg",a=r?560:264,l=r?32:22;return e.jsx("div",{className:M("flex w-full items-center justify-center rounded-xl bg-oai-gray-100 dark:bg-oai-gray-950/60",r?"py-10 sm:py-14 px-6":"py-6 px-4"),children:e.jsx("div",{className:"overflow-hidden bg-white dark:bg-oai-gray-800 shadow-oai-md dark:shadow-[0_2px_4px_rgba(0,0,0,0.4),0_8px_24px_rgba(0,0,0,0.5)]",style:{width:"100%",maxWidth:a,aspectRatio:`${O} / ${U}`,borderRadius:l},children:i})})}function Y({size:t="sm"}){const i="M0,104 L14,104 C26,98 34,100 44,96 S58,88 68,92 80,100 90,94 102,80 112,82 126,92 136,88 150,74 162,76 178,88 188,86 204,72 216,74 236,84 250,80 L264,80",r=`${i} L264,124 L0,124 Z`,a=`sparkArea-${t}`;return e.jsx(b,{size:t,children:e.jsxs("svg",{viewBox:"0 0 264 124",className:"h-full w-full","aria-hidden":"true",children:[e.jsx("defs",{children:e.jsxs("linearGradient",{id:a,x1:"0",y1:"0",x2:"0",y2:"1",children:[e.jsx("stop",{offset:"0%",stopColor:"#0A84FF",stopOpacity:"0.18"}),e.jsx("stop",{offset:"100%",stopColor:"#0A84FF",stopOpacity:"0"})]})}),e.jsx("text",{x:"14",y:"20",className:"fill-oai-gray-500 dark:fill-oai-gray-400",fontSize:"8",fontWeight:"700",letterSpacing:"0.6",children:"TODAY"}),e.jsx("text",{x:"14",y:"46",className:"fill-oai-black dark:fill-white",fontSize:"22",fontWeight:"700",fontFamily:g,children:"203.2M"}),e.jsx("text",{x:"14",y:"60",className:"fill-oai-gray-500 dark:fill-oai-gray-400",fontSize:"8",fontWeight:"500",fontFamily:g,children:"$129.56 ±0%"}),e.jsx("text",{x:"134",y:"20",className:"fill-oai-gray-500 dark:fill-oai-gray-400",fontSize:"8",fontWeight:"700",letterSpacing:"0.6",children:"7 DAYS"}),e.jsx("text",{x:"134",y:"46",className:"fill-oai-black dark:fill-white",fontSize:"22",fontWeight:"700",fontFamily:g,children:"880.9M"}),e.jsx("text",{x:"134",y:"60",className:"fill-oai-gray-500 dark:fill-oai-gray-400",fontSize:"8",fontWeight:"500",fontFamily:g,children:"$673.61"}),e.jsx("path",{d:r,fill:`url(#${a})`,stroke:"none"}),e.jsx("path",{d:i,fill:"none",stroke:"#0A84FF",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round"})]})})}const N=(()=>{const r=[];for(let a=0;a<26;a++)for(let l=0;l<7;l++){const s=Math.sin((a+1)*12.9898+(l+1)*78.233+17)*43758.5453,c=Math.floor(Math.abs(s-Math.floor(s))*100);r.push({w:a,d:l,v:c})}return r})();function C(t,i){return t<18?i?"#262626":"#e5e5e5":t<38?"rgba(10, 132, 255, 0.28)":t<58?"rgba(10, 132, 255, 0.50)":t<80?"rgba(10, 132, 255, 0.75)":"#0A84FF"}function Z(){return e.jsx(b,{children:e.jsxs("svg",{viewBox:"0 0 264 124",className:"h-full w-full","aria-hidden":"true",children:[e.jsx("g",{transform:`translate(${19.5}, 10)`,className:"hidden dark:inline",children:N.map(s=>e.jsx("rect",{x:s.w*(7.5+1.2),y:s.d*(8+1.2),width:7.5,height:8,rx:"1.3",fill:C(s.v,!0)},`d-${s.w}-${s.d}`))}),e.jsx("g",{transform:`translate(${19.5}, 10)`,className:"dark:hidden",children:N.map(s=>e.jsx("rect",{x:s.w*(7.5+1.2),y:s.d*(8+1.2),width:7.5,height:8,rx:"1.3",fill:C(s.v,!1)},`l-${s.w}-${s.d}`))}),e.jsx("text",{x:19.5,y:"102",className:"fill-oai-black dark:fill-white",fontSize:"10",fontWeight:"700",fontFamily:g,children:"10.3B"}),e.jsx("text",{x:19.5+30,y:"102",className:"fill-oai-gray-500 dark:fill-oai-gray-400",fontSize:"9",fontWeight:"500",children:"tokens · 202 active days"})]})})}function q(){const t=[{name:"claude-opus-4-6",value:"586.4M",pct:59},{name:"claude-sonnet-4-5-20250929",value:"218.7M",pct:22},{name:"gpt-5.4",value:"80.6M",pct:8},{name:"composer-2-fast",value:"52.1M",pct:5}],i=22,r=28,a=14,l=236;return e.jsx(b,{children:e.jsx("svg",{viewBox:"0 0 264 124",className:"h-full w-full","aria-hidden":"true",children:t.map((s,c)=>{const n=r+c*i,h=L[c%L.length];return e.jsxs("g",{children:[e.jsx("circle",{cx:"18",cy:n-3,r:"2.5",fill:h}),e.jsx("text",{x:"26",y:n,className:"fill-oai-black dark:fill-white",fontSize:"9",fontWeight:"500",children:s.name}),e.jsx("text",{x:"218",y:n,textAnchor:"end",className:"fill-oai-gray-500 dark:fill-oai-gray-400",fontSize:"9",fontWeight:"600",fontFamily:g,children:s.value}),e.jsxs("text",{x:"250",y:n,textAnchor:"end",className:"fill-oai-gray-500 dark:fill-oai-gray-400",fontSize:"8",fontWeight:"600",fontFamily:g,children:[s.pct,"%"]}),e.jsx("rect",{x:a,y:n+4,width:l,height:"2.8",rx:"1.4",className:"fill-oai-gray-200 dark:fill-oai-gray-700"}),e.jsx("rect",{x:a,y:n+4,width:Math.max(l*(s.pct/100),4),height:"2.8",rx:"1.4",fill:h})]},s.name)})})})}function J(){const t=[{label:"Claude · 7d",source:"claude",reset:"in 1d",pct:61},{label:"Claude · 5h",source:"claude",reset:"in 4h 28m",pct:4},{label:"Cursor",source:"cursor",reset:"in 25d",pct:51},{label:"Codex · weekly",source:"codex",reset:"in 1d",pct:32}],i=22,r=28,a=14,l=236;return e.jsx(b,{children:e.jsx("svg",{viewBox:"0 0 264 124",className:"h-full w-full","aria-hidden":"true",children:t.map((s,c)=>{const n=r+c*i,h=V[s.source],y=X(s.pct/100);return e.jsxs("g",{children:[e.jsx("circle",{cx:"18",cy:n-3,r:"2.5",fill:h}),e.jsx("text",{x:"26",y:n,className:"fill-oai-black dark:fill-white",fontSize:"9",fontWeight:"500",children:s.label}),e.jsx("text",{x:"218",y:n,textAnchor:"end",className:"fill-oai-gray-500 dark:fill-oai-gray-400",fontSize:"8",fontWeight:"500",fontFamily:g,children:s.reset}),e.jsxs("text",{x:"250",y:n,textAnchor:"end",className:"fill-oai-black dark:fill-white",fontSize:"9",fontWeight:"700",fontFamily:g,children:[s.pct,"%"]}),e.jsx("rect",{x:a,y:n+4,width:l,height:"2.8",rx:"1.4",className:"fill-oai-gray-200 dark:fill-oai-gray-700"}),e.jsx("rect",{x:a,y:n+4,width:Math.max(l*(s.pct/100),4),height:"2.8",rx:"1.4",fill:y})]},s.label)})})})}function Q(t){switch(t.category){case"cost":return"$8.42";case"limits":return"62%";default:return t.id==="last7dTokens"?"1.8B":"203M"}}function ee(t,i){switch(t){case"todayTokens":return o("menubar.metric.today_tokens");case"todayCost":return o("menubar.metric.today_cost");case"last7dTokens":return o("menubar.metric.last_7d_tokens");case"totalTokens":return o("menubar.metric.total_tokens");case"totalCost":return o("menubar.metric.total_cost");case"claude5h":return o("menubar.metric.claude_5h");case"claude7d":return o("menubar.metric.claude_7d");case"codex5h":return o("menubar.metric.codex_5h");case"codex7d":return o("menubar.metric.codex_7d");default:return i}}function te(t,i){const r=new Set(i.map(l=>l.id)),a=t.filter(l=>r.has(l));for(const l of i){if(a.length>=2)break;a.includes(l.id)||a.push(l.id)}return a.slice(0,2)}function ae({slotConfigs:t,showStats:i}){return e.jsx("div",{className:"flex justify-center rounded-xl bg-gradient-to-b from-oai-gray-100 to-oai-gray-200 px-6 py-8 dark:from-oai-gray-950/80 dark:to-oai-gray-900/80",children:e.jsxs("div",{className:"inline-flex items-stretch rounded-md shadow-[0_1px_3px_rgba(0,0,0,0.18)] ring-1 ring-black/10 dark:ring-white/10 px-3",style:{background:"linear-gradient(180deg, #2c2c2e 0%, #1c1c1e 100%)"},children:[e.jsx("div",{className:"flex items-center pl-2 pr-1 py-2.5",children:e.jsx("img",{src:"/clawd/mini/idle-tight.svg",alt:"","aria-hidden":"true",className:"block shrink-0",style:{height:22,width:"auto"},draggable:"false"})}),i?t.map(({slot:r,item:a},l)=>e.jsxs(B.Fragment,{children:[l>0?e.jsx("span",{className:"my-1 w-px bg-white/20","aria-hidden":"true"}):null,e.jsxs("div",{className:M("flex min-w-[52px] flex-col items-center justify-center py-1.5",l===0?"pl-1 pr-2":"px-2"),children:[e.jsx("span",{className:"text-[13px] font-semibold leading-none tabular-nums text-white",children:a?.previewValue||"--"}),e.jsx("span",{className:"mt-[2px] text-[6px] font-semibold uppercase leading-none text-white/75",children:a?.shortLabel||"Metric"})]})]},r)):null]})})}function ie({slot:t,value:i,options:r,disabled:a,onChange:l}){const s=t===0?o("menubar.slot.primary"):o("menubar.slot.secondary");return e.jsxs("div",{className:"flex min-w-0 flex-col gap-1.5",children:[e.jsx("span",{className:"text-[11px] font-semibold uppercase tracking-[0.08em] text-oai-gray-500 dark:text-oai-gray-400",children:s}),e.jsx(D,{value:i,disabled:a,ariaLabel:s,onValueChange:c=>l(t,c),options:r.map(c=>({value:c.id,label:c.displayLabel})),matchTriggerWidth:!0,className:"w-full px-3 py-2 text-sm font-medium"})]})}function S({label:t,hint:i,checked:r,disabled:a,onChange:l}){return e.jsxs("div",{className:"flex items-center justify-between gap-3 py-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"text-sm font-medium text-oai-black dark:text-white",children:t}),i?e.jsx("p",{className:"mt-0.5 text-xs text-oai-gray-500 dark:text-oai-gray-400",children:i}):null]}),e.jsx(K,{checked:r,disabled:a,onChange:l,ariaLabel:t})]})}function se(){const{available:t,settings:i,setSetting:r}=E(),a=u.useMemo(()=>(Array.isArray(i?.menuBarAvailableItems)?i.menuBarAvailableItems:F).map(m=>({...m,displayLabel:ee(m.id,m.label),previewValue:Q(m)})),[i?.menuBarAvailableItems]),l=Number(i?.menuBarMaxItems)||2,s=u.useMemo(()=>v(i?.menuBarItems,a,l),[a,l,i?.menuBarItems]),c=u.useMemo(()=>te(s,a),[a,s]),n=i?.showStats!==!1,h=d=>{r("menuBarItems",v(d,a,l))},y=(d,m)=>{const x=[...c];x[d===0?1:0]!==m&&(x[d]=m,h(x))},p=[0,1].map(d=>{const m=c[d]||a[d]?.id||"",k=c[d===0?1:0],W=a.filter(f=>f.id===m||f.id!==k),T=a.find(f=>f.id===m);return{slot:d,currentValue:m,options:W,item:T}}),w=i?.animatedIcon!==!1;return e.jsxs("article",{className:"rounded-xl border border-oai-gray-200 bg-white p-5 transition-colors duration-200 dark:border-oai-gray-800 dark:bg-oai-gray-900 sm:p-6",children:[e.jsx(ae,{slotConfigs:p,showStats:n}),e.jsx("div",{className:"mt-5 grid grid-cols-1 gap-3 sm:grid-cols-2 sm:gap-4",children:p.map(({slot:d,currentValue:m,options:x})=>e.jsx(ie,{slot:d,value:m,options:x,disabled:!t||!n,onChange:y},d))}),e.jsxs("div",{className:"mt-5 divide-y divide-oai-gray-100 border-t border-oai-gray-100 dark:divide-oai-gray-800 dark:border-oai-gray-800",children:[e.jsx(S,{label:o("settings.menubar.showStats"),hint:t?o("settings.menubar.showStatsHint"):o("menubar.native_only"),checked:n,disabled:!t,onChange:()=>r("showStats",!n)}),e.jsx(S,{label:o("settings.menubar.animatedIcon"),hint:o("settings.menubar.animatedIconHint"),checked:w,disabled:!t,onChange:()=>r("animatedIcon",!w)})]})]})}function re(){const[t,i]=u.useState("loading");return u.useEffect(()=>{if(typeof window>"u")return;if(I()){i("native");return}const r=(navigator.userAgent||"").toLowerCase(),a=/mac/.test(r)&&!/iphone|ipad/.test(r);i(a?"mac-web":"other")},[]),t}function le(){const t=re();return t==="loading"?e.jsx("div",{className:"h-10 w-40","aria-hidden":"true"}):t==="native"?e.jsxs("button",{type:"button",onClick:()=>_("openWidgetGallery"),className:"inline-flex h-10 items-center gap-2 rounded-lg bg-oai-black px-4 text-sm font-medium text-white transition-colors hover:bg-oai-gray-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-oai-brand-500 focus-visible:ring-offset-2 dark:bg-white dark:text-oai-black dark:hover:bg-oai-gray-200",children:[o("widgets.cta.open_gallery"),e.jsx(z,{className:"h-4 w-4","aria-hidden":"true"})]}):t==="mac-web"?e.jsxs("a",{href:"https://github.com/mm7894215/TokenTracker/releases/latest",target:"_blank",rel:"noopener noreferrer",className:"inline-flex h-10 items-center gap-2 rounded-lg bg-oai-black px-4 text-sm font-medium text-white no-underline transition-colors hover:bg-oai-gray-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-oai-brand-500 focus-visible:ring-offset-2 dark:bg-white dark:text-oai-black dark:hover:bg-oai-gray-200",children:[e.jsx(R,{className:"h-4 w-4","aria-hidden":"true"}),o("widgets.cta.download")]}):e.jsxs("span",{className:"inline-flex h-10 items-center gap-2 rounded-lg border border-oai-gray-200 bg-oai-gray-50 px-4 text-sm font-medium text-oai-gray-500 dark:border-oai-gray-800 dark:bg-oai-gray-900 dark:text-oai-gray-400",children:[e.jsx(P,{className:"h-4 w-4","aria-hidden":"true"}),o("widgets.cta.macos_only")]})}const oe=[{id:"summary",Preview:Y,nameKey:"widgets.summary.name",descKey:"widgets.summary.description"},{id:"heatmap",Preview:Z,nameKey:"widgets.heatmap.name",descKey:"widgets.heatmap.description"},{id:"topModels",Preview:q,nameKey:"widgets.topModels.name",descKey:"widgets.topModels.description"},{id:"limits",Preview:J,nameKey:"widgets.limits.name",descKey:"widgets.limits.description"}];function ne({Preview:t,nameKey:i,descKey:r}){return e.jsxs("article",{className:"flex h-full flex-col rounded-xl border border-oai-gray-200 bg-white p-4 transition-colors duration-200 dark:border-oai-gray-800 dark:bg-oai-gray-900 sm:p-5",children:[e.jsx(t,{}),e.jsxs("div",{className:"mt-4",children:[e.jsx("h3",{className:"text-[15px] font-semibold text-oai-black dark:text-white",children:o(i)}),e.jsx("p",{className:"mt-1.5 text-sm leading-relaxed text-oai-gray-500 dark:text-oai-gray-400",children:o(r)})]})]})}function A({titleKey:t}){return e.jsx("h2",{className:"mb-4 text-xl font-semibold tracking-tight text-oai-black dark:text-white sm:mb-5 sm:text-2xl",children:o(t)})}function ye(){return e.jsx("div",{className:"flex flex-col flex-1 text-oai-black dark:text-oai-white font-oai antialiased",children:e.jsx("main",{className:"flex-1 pt-8 sm:pt-10 pb-12 sm:pb-16",children:e.jsxs("div",{className:"mx-auto max-w-5xl px-4 sm:px-6",children:[e.jsx(j,{y:12,children:e.jsxs("header",{className:"mb-10 flex items-start justify-between gap-4 sm:mb-12",children:[e.jsx("h1",{className:"text-3xl font-semibold tracking-tight text-oai-black dark:text-white sm:text-4xl",children:o("widgets.page.title")}),e.jsx("div",{className:"shrink-0",children:e.jsx(le,{})})]})}),e.jsx(j,{y:12,delay:.06,children:e.jsxs("section",{"aria-label":o("widgets.menubar.section.title"),className:"mb-12 sm:mb-14",children:[e.jsx(A,{titleKey:"widgets.menubar.section.title"}),e.jsx(se,{})]})}),e.jsxs("section",{"aria-label":o("widgets.gallery.section.title"),children:[e.jsx(A,{titleKey:"widgets.gallery.section.title"}),e.jsx(G,{staggerDelay:.08,initialDelay:.04,children:e.jsx("div",{className:"grid grid-cols-1 gap-4 lg:grid-cols-2 lg:gap-5",children:oe.map(({id:t,Preview:i,nameKey:r,descKey:a})=>e.jsx($,{children:e.jsx(ne,{Preview:i,nameKey:r,descKey:a})},t))})})]})]})})})}export{ye as WidgetsPage};
@@ -1 +0,0 @@
1
- import{r as a,ab as m,aI as f}from"./main-CZ7INQ5C.js";function p(s){const r=!!s?.initialState,[h,c]=a.useState(()=>r?s?.initialState?.data??null:null),[S,l]=a.useState(()=>r?s?.initialState?.error??null:null),[g,b]=a.useState(!r),i=!!s?.initialRefresh,o=!!s?.publishToPreloadCache,n=a.useCallback((e,t)=>{!o||!e||typeof e!="object"||m(e,{source:t})},[o]),d=a.useCallback(async()=>{try{const e=await f({refresh:!0}),t=e&&typeof e=="object"?e:null;c(t),l(null),n(t,"manual-refresh")}catch(e){l(e?.message||String(e))}},[n]);return a.useEffect(()=>{if(r&&!i)return;let e=!1;return(async()=>{try{const t=await f(i?{refresh:!0}:{});if(e)return;const u=t&&typeof t=="object"?t:null;c(u),l(null),n(u,"page-load")}catch(t){if(e)return;l(t?.message||String(t))}finally{e||b(!1)}})(),()=>{e=!0}},[r,i,n]),{data:h,error:S,isLoading:g,refresh:d}}export{p as u};