tokentracker-cli 0.93.6 → 0.93.7

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 (120) hide show
  1. package/dashboard/dist/assets/{AchievementBadge-DsAclDw6.js → AchievementBadge-DqvblIQY.js} +1 -1
  2. package/dashboard/dist/assets/{AchievementsPage-D__EwC45.js → AchievementsPage-C-xm27pB.js} +2 -2
  3. package/dashboard/dist/assets/{AchievementsSection-BAZNM3Cn.js → AchievementsSection-D8Oe2FGJ.js} +1 -1
  4. package/dashboard/dist/assets/BadgeDetailModal-BJOcOnHo.js +1 -0
  5. package/dashboard/dist/assets/{BotAnimated-CwrScgrI.js → BotAnimated-6fB046ld.js} +1 -1
  6. package/dashboard/dist/assets/{Card-D7GmLoqP.js → Card-BKbWtBaL.js} +1 -1
  7. package/dashboard/dist/assets/{ClawdAnimated-BEXgb5J_.js → ClawdAnimated-DbpeAldp.js} +2 -2
  8. package/dashboard/dist/assets/{CommandPalette-B9Mn3Qt2.js → CommandPalette-Jte7TBon.js} +1 -1
  9. package/dashboard/dist/assets/CommunityStatsModal-DDm7tCXO.js +1 -0
  10. package/dashboard/dist/assets/ConfirmModal-CrIjcrpZ.js +1 -0
  11. package/dashboard/dist/assets/{Controls-DxnaHBzv.js → Controls-BWJtMkIy.js} +1 -1
  12. package/dashboard/dist/assets/DashboardPage-Bcq4EwG5.js +1 -0
  13. package/dashboard/dist/assets/{DevicePage-4yTYf29M.js → DevicePage-C9NcPZGX.js} +1 -1
  14. package/dashboard/dist/assets/{DialogClose-BbderFCY.js → DialogClose-CY-LguUG.js} +1 -1
  15. package/dashboard/dist/assets/DialogDescription-DPyhpdeR.js +1 -0
  16. package/dashboard/dist/assets/DialogTitle-BkAmJrQ_.js +1 -0
  17. package/dashboard/dist/assets/{FadeIn-BFLojPGG.js → FadeIn-U-bxcM-y.js} +1 -1
  18. package/dashboard/dist/assets/{HeaderGithubStar-CPBNn61n.js → HeaderGithubStar-4HUCxVhg.js} +1 -1
  19. package/dashboard/dist/assets/{HoverTooltip-DbxnLj8e.js → HoverTooltip-BXcXOCs8.js} +1 -1
  20. package/dashboard/dist/assets/{IpCheckPage-CfPtXAAF.js → IpCheckPage-Cppkc-gE.js} +1 -1
  21. package/dashboard/dist/assets/{LandingPage-CocswfFj.js → LandingPage-D3KXfYKE.js} +2 -2
  22. package/dashboard/dist/assets/{LeaderboardAvatar-iZLxxZX-.js → LeaderboardAvatar-CdsHg6L0.js} +1 -1
  23. package/dashboard/dist/assets/LeaderboardPage-niat0TZW.js +2 -0
  24. package/dashboard/dist/assets/{LeaderboardProfileModal-BWu8jbBW.js → LeaderboardProfileModal-DgjhhEbB.js} +3 -3
  25. package/dashboard/dist/assets/{LeaderboardProfilePage-B77gOTzr.js → LeaderboardProfilePage-CZej8gpc.js} +1 -1
  26. package/dashboard/dist/assets/LimitsPage-BXzzX87I.js +5 -0
  27. package/dashboard/dist/assets/LocalOnlyNotice-DQswDMSD.js +1 -0
  28. package/dashboard/dist/assets/{LoginCard-D592L-fh.js → LoginCard-glPyVqYh.js} +1 -1
  29. package/dashboard/dist/assets/{LoginModal-C7Qm7CVf.js → LoginModal-slsdEXC7.js} +1 -1
  30. package/dashboard/dist/assets/{LoginPage-DkYw5ZQK.js → LoginPage-DX5QT917.js} +1 -1
  31. package/dashboard/dist/assets/PetPage-B8U3CJwt.js +1 -0
  32. package/dashboard/dist/assets/PopoverPopup-BVPcQAio.js +1 -0
  33. package/dashboard/dist/assets/{ProviderIcon-d0_vhIkS.js → ProviderIcon-CljIacVj.js} +1 -1
  34. package/dashboard/dist/assets/{ResetPasswordPage-UDNlpFVu.js → ResetPasswordPage-DTBmQk2y.js} +1 -1
  35. package/dashboard/dist/assets/SegmentedControl-C6npelCT.js +1 -0
  36. package/dashboard/dist/assets/{Select-Z2xTQ55f.js → Select-D1elkRBG.js} +1 -1
  37. package/dashboard/dist/assets/SelectItemText-3N-hvYuD.js +1 -0
  38. package/dashboard/dist/assets/{ServiceStatusPage-Cfr-QDZ7.js → ServiceStatusPage-C5ZK9X2o.js} +1 -1
  39. package/dashboard/dist/assets/{SessionsPage-nHPj6IAt.js → SessionsPage-CJ0JvE8-.js} +2 -2
  40. package/dashboard/dist/assets/SettingsPage-C32uYzqG.js +2 -0
  41. package/dashboard/dist/assets/SkillsPage-Cwkevv29.js +1 -0
  42. package/dashboard/dist/assets/{TokenGalaxy-CjAY6rey.js → TokenGalaxy-a1-E6_jp.js} +1 -1
  43. package/dashboard/dist/assets/ToolbarRootContext-Cm5cQb9Z.js +1 -0
  44. package/dashboard/dist/assets/{TrendMonitor-DAAlILwJ.js → TrendMonitor-DoNDyarF.js} +1 -1
  45. package/dashboard/dist/assets/WidgetsPage-QMTmKnRl.js +1 -0
  46. package/dashboard/dist/assets/{WrappedPage-ByYzOeZ-.js → WrappedPage-C9rJcY2o.js} +1 -1
  47. package/dashboard/dist/assets/{__vite-browser-external-HdCplPKs.js → __vite-browser-external-CsbVaBbw.js} +3 -3
  48. package/dashboard/dist/assets/__vite-browser-external-D95WhsZe.css +1 -0
  49. package/dashboard/dist/assets/{agent-logos-BW-ajJ7p.js → agent-logos-B39DKy3X.js} +1 -1
  50. package/dashboard/dist/assets/{arrow-up-right-CA5IJkqo.js → arrow-up-right-Cw5mMBik.js} +1 -1
  51. package/dashboard/dist/assets/{check-BBjF3bSm.js → check-DrQztnq1.js} +1 -1
  52. package/dashboard/dist/assets/{chevron-right-DCvGp9iJ.js → chevron-right-CEelysET.js} +1 -1
  53. package/dashboard/dist/assets/{useScrollLock-BUVUIPTX.js → composite-MhgOkYfv.js} +1 -1
  54. package/dashboard/dist/assets/{copy-ahF8LGeu.js → copy-Bouz-qQR.js} +1 -1
  55. package/dashboard/dist/assets/{download-DBm8dmvt.js → download-BugS2cl5.js} +1 -1
  56. package/dashboard/dist/assets/{external-link-C1sJSL7J.js → external-link-Ceqto-f4.js} +1 -1
  57. package/dashboard/dist/assets/{flame-B6xukEYd.js → flame-B67y0kLz.js} +1 -1
  58. package/dashboard/dist/assets/{format-tokens-6TqXlT3q.js → format-tokens-CR8njNJs.js} +1 -1
  59. package/dashboard/dist/assets/{icons-pGe_pInY.js → icons-DFj5ctTx.js} +1 -1
  60. package/dashboard/dist/assets/{index-Chb8mb2X.js → index-Bx6EP36K.js} +1 -1
  61. package/dashboard/dist/assets/{index-I9O8xChC.js → index-CrymIhtC.js} +1 -1
  62. package/dashboard/dist/assets/{index-RPV0zdZ9.js → index-ZGfRrxuq.js} +1 -1
  63. package/dashboard/dist/assets/{info-DBfJv0yu.js → info-C6XoktLa.js} +1 -1
  64. package/dashboard/dist/assets/{limits-providers-DPQsdVq5.js → limits-providers-B9L6hIZT.js} +1 -1
  65. package/dashboard/dist/assets/{link-2-DNEARrPY.js → link-2-DKG2j43e.js} +1 -1
  66. package/dashboard/dist/assets/{loader-circle-BCFHUr8X.js → loader-circle-DB2txq05.js} +1 -1
  67. package/dashboard/dist/assets/{maximize-2-1EmlA2R-.js → maximize-2-3-dz0brp.js} +1 -1
  68. package/dashboard/dist/assets/{modifiers.esm-DGXFSuEq.js → modifiers.esm-D0KjKi1o.js} +1 -1
  69. package/dashboard/dist/assets/{monitor-smartphone-DsPPhvsT.js → monitor-smartphone-Ds8H_QW9.js} +1 -1
  70. package/dashboard/dist/assets/plus-BDsmAe4Z.js +1 -0
  71. package/dashboard/dist/assets/{provider-display-C20LtBC5.js → provider-display-DRz643iD.js} +1 -1
  72. package/dashboard/dist/assets/{react-B4FPJgs_.js → react-D3Afmy9b.js} +1 -1
  73. package/dashboard/dist/assets/{search-mkIFPKzW.js → search-CO2Xf-Kg.js} +1 -1
  74. package/dashboard/dist/assets/{skills-api-D24vlu2H.js → skills-api-C1BZuUIq.js} +1 -1
  75. package/dashboard/dist/assets/{sortable.esm-BNDcP0sW.js → sortable.esm-DutNEc4F.js} +1 -1
  76. package/dashboard/dist/assets/store-a-oUpY-g.js +1 -0
  77. package/dashboard/dist/assets/{terminal-BxVMmvEx.js → terminal-DAePk67T.js} +1 -1
  78. package/dashboard/dist/assets/{trash-2-crt9lDvj.js → trash-2-bnFmtRSG.js} +1 -1
  79. package/dashboard/dist/assets/{use-community-stats-CTB_uHWV.js → use-community-stats-PJBeXyek.js} +1 -1
  80. package/dashboard/dist/assets/{use-limits-display-prefs-DXXZpjGY.js → use-limits-display-prefs-Blvn-7CB.js} +1 -1
  81. package/dashboard/dist/assets/{use-ordered-list-BVNb5QWU.js → use-ordered-list-BaVvCzZ9.js} +1 -1
  82. package/dashboard/dist/assets/use-reduced-motion-f51jgK_S.js +1 -0
  83. package/dashboard/dist/assets/{use-session-efficiency-pref-Di8nY6Lr.js → use-session-efficiency-pref-COTG-zJs.js} +1 -1
  84. package/dashboard/dist/assets/{use-transform-Dx9C2nBC.js → use-transform-BQEPyChL.js} +1 -1
  85. package/dashboard/dist/assets/use-usage-limits-LR2gHJJn.js +1 -0
  86. package/dashboard/dist/assets/{useCurrency-7dkDciam.js → useCurrency-CeqKrzFz.js} +1 -1
  87. package/dashboard/dist/assets/{useTokenFormat-DFSIAsAb.js → useTokenFormat-D0IMlZlO.js} +1 -1
  88. package/dashboard/dist/assets/{zap-Png-VJSP.js → zap-BBn6G5_E.js} +1 -1
  89. package/dashboard/dist/index.html +2 -2
  90. package/dashboard/dist/ip-check.html +2 -2
  91. package/dashboard/dist/leaderboard.html +2 -2
  92. package/dashboard/dist/share.html +2 -2
  93. package/package.json +1 -1
  94. package/src/lib/cursor-config.js +182 -1
  95. package/src/lib/fs.js +12 -3
  96. package/src/lib/local-api.js +57 -0
  97. package/src/lib/pricing/seed-snapshot.json +1 -1
  98. package/src/lib/subscription-manager.js +293 -0
  99. package/src/lib/usage-limits.js +35 -4
  100. package/dashboard/dist/assets/BadgeDetailModal-Dgeer5oB.js +0 -1
  101. package/dashboard/dist/assets/CommunityStatsModal-eJ_a1FMd.js +0 -1
  102. package/dashboard/dist/assets/ConfirmModal-CumOr2J1.js +0 -1
  103. package/dashboard/dist/assets/DashboardPage-BpRRXCRr.js +0 -1
  104. package/dashboard/dist/assets/DialogDescription-C5Ujj254.js +0 -1
  105. package/dashboard/dist/assets/DialogTitle-6epeLIn0.js +0 -1
  106. package/dashboard/dist/assets/LeaderboardPage-yqauB4Q1.js +0 -2
  107. package/dashboard/dist/assets/LimitsPage-C9NeIcft.js +0 -5
  108. package/dashboard/dist/assets/LocalOnlyNotice-HPXWU8TT.js +0 -1
  109. package/dashboard/dist/assets/PetPage-BOhvAJp4.js +0 -1
  110. package/dashboard/dist/assets/PopoverPopup-BK9aqQn1.js +0 -1
  111. package/dashboard/dist/assets/SegmentedControl-DE5m1pTf.js +0 -1
  112. package/dashboard/dist/assets/SelectItemText-Daq-XRZg.js +0 -1
  113. package/dashboard/dist/assets/SettingsPage-NvxUG_9m.js +0 -2
  114. package/dashboard/dist/assets/SkillsPage-zFbZa42f.js +0 -1
  115. package/dashboard/dist/assets/ToolbarRootContext-DnC8LT_8.js +0 -1
  116. package/dashboard/dist/assets/WidgetsPage-CXsfi-mq.js +0 -1
  117. package/dashboard/dist/assets/__vite-browser-external-CiR9-j4L.css +0 -1
  118. package/dashboard/dist/assets/store-B2nqaAqP.js +0 -1
  119. package/dashboard/dist/assets/use-reduced-motion-aSaQtoJu.js +0 -1
  120. package/dashboard/dist/assets/use-usage-limits-D9vQFB1H.js +0 -1
@@ -0,0 +1,293 @@
1
+ const path = require("node:path");
2
+ const fs = require("node:fs/promises");
3
+ const crypto = require("node:crypto");
4
+
5
+ const { readJsonStrict, writeFileAtomic, chmod600IfPossible } = require("./fs");
6
+
7
+ // Manual subscription manager: user-entered billing plans (service, plan,
8
+ // auto-renew flag, next renewal/expiry timestamp). Distinct from
9
+ // subscriptions.js (auto-detected local plan tiers) and usage-limits.js
10
+ // (rate-limit window resets) — see issue #460.
11
+ const STORE_FILE = "subscription-manager.json";
12
+ const STORE_VERSION = 1;
13
+ const MAX_TEXT_LENGTH = 120;
14
+ const CYCLE_UNITS = new Set(["weekly", "monthly", "yearly"]);
15
+
16
+ function resolveSubscriptionsPath(trackerDir) {
17
+ return path.join(trackerDir, STORE_FILE);
18
+ }
19
+
20
+ function normalizeText(value, { required, field, maxLength = MAX_TEXT_LENGTH } = {}) {
21
+ if (value === null || value === undefined) {
22
+ if (required) throw new Error(`${field} is required`);
23
+ return null;
24
+ }
25
+ if (typeof value !== "string") throw new Error(`${field} must be a string`);
26
+ const trimmed = value.trim();
27
+ if (!trimmed) {
28
+ if (required) throw new Error(`${field} is required`);
29
+ return null;
30
+ }
31
+ if (trimmed.length > maxLength) {
32
+ throw new Error(`${field} must be at most ${maxLength} characters`);
33
+ }
34
+ return trimmed;
35
+ }
36
+
37
+ // Accepts epoch milliseconds or any Date-parseable string. Stored values are
38
+ // UTC ISO strings truncated to whole minutes so comparisons stay clean and a
39
+ // second-level drift between input formats never changes the billed minute.
40
+ function normalizeBillingTime(value, { field = "nextBillingAt", required = true } = {}) {
41
+ let ms;
42
+ if (value === null || value === undefined) {
43
+ if (required) throw new Error(`${field} is required`);
44
+ return null;
45
+ }
46
+ if (typeof value === "number") {
47
+ ms = value;
48
+ } else if (typeof value === "string") {
49
+ const trimmed = value.trim();
50
+ if (!trimmed) {
51
+ if (required) throw new Error(`${field} is required`);
52
+ return null;
53
+ }
54
+ ms = new Date(trimmed).getTime();
55
+ } else {
56
+ throw new Error(`${field} is required`);
57
+ }
58
+ if (!Number.isFinite(ms)) throw new Error(`${field} must be a valid date`);
59
+ return new Date(Math.floor(ms / 60000) * 60000).toISOString();
60
+ }
61
+
62
+ // Billing cycle length. Drives the progress bar span and how far an
63
+ // auto-renew subscription rolls forward after a recorded renewal passes.
64
+ // Defaults to monthly so pre-cycle records keep their original semantics.
65
+ function normalizeCycle(value) {
66
+ if (value === null || value === undefined) return "monthly";
67
+ if (typeof value !== "string" || !CYCLE_UNITS.has(value)) {
68
+ throw new Error("cycle must be one of: weekly, monthly, yearly");
69
+ }
70
+ return value;
71
+ }
72
+
73
+ function normalizeSubscriptionFields(fields) {
74
+ if (!fields || typeof fields !== "object" || Array.isArray(fields)) {
75
+ throw new Error("subscription must be an object");
76
+ }
77
+ if (typeof fields.autoRenew !== "boolean") {
78
+ throw new Error("autoRenew must be a boolean");
79
+ }
80
+ return {
81
+ service: normalizeText(fields.service, { required: true, field: "service" }),
82
+ plan: normalizeText(fields.plan ?? null, { required: false, field: "plan" }),
83
+ // Optional link to a usage-limits provider row (e.g. "codex"). The value
84
+ // is a limits provider id but is not validated against the canonical list
85
+ // here — the backend stays lenient, the dropdown constrains it in the UI.
86
+ provider: normalizeText(fields.provider ?? null, {
87
+ required: false,
88
+ field: "provider",
89
+ maxLength: 64,
90
+ }),
91
+ autoRenew: fields.autoRenew,
92
+ cycle: normalizeCycle(fields.cycle),
93
+ nextBillingAt: normalizeBillingTime(fields.nextBillingAt),
94
+ // Billing anchor: the day the subscription started. The dashboard derives
95
+ // every cycle boundary from this date, so month-end anchors (Jan 31) stay
96
+ // stable instead of drifting after the first clamped month. Optional:
97
+ // records created before the field existed fall back to a derived anchor.
98
+ startedAt:
99
+ fields.startedAt === undefined
100
+ ? null
101
+ : normalizeBillingTime(fields.startedAt, { field: "startedAt", required: false }),
102
+ };
103
+ }
104
+
105
+ function isValidStoredRecord(record) {
106
+ if (!record || typeof record !== "object" || Array.isArray(record)) return false;
107
+ if (typeof record.id !== "string" || !record.id) return false;
108
+ if (typeof record.service !== "string" || !record.service) return false;
109
+ if (typeof record.autoRenew !== "boolean") return false;
110
+ if (typeof record.nextBillingAt !== "string") return false;
111
+ return Number.isFinite(new Date(record.nextBillingAt).getTime());
112
+ }
113
+
114
+ // Read the store. Any state other than a clean file or a plainly missing one
115
+ // must never collapse into an empty store on its own: the next write would
116
+ // silently destroy every stored subscription (user-entered data that cannot
117
+ // be rebuilt from logs). Reads surface the damage as an error; only the write
118
+ // path may recover, and only after backing the original file up.
119
+ async function readStore(filePath, { forWrite = false } = {}) {
120
+ const { status, value, error } = await readJsonStrict(filePath);
121
+ if (status === "missing") {
122
+ return { store: { version: STORE_VERSION, items: [] }, needsBackup: false };
123
+ }
124
+ if (status === "error") {
125
+ // Unreadable (permissions, I/O error): refuse — a blind overwrite would
126
+ // destroy data we were never able to see.
127
+ throw new Error(`Cannot read subscription store: ${error?.message || String(error)}`);
128
+ }
129
+ if (status === "invalid" || !value || typeof value !== "object" || Array.isArray(value)) {
130
+ if (!forWrite) {
131
+ throw new Error("Subscription store is corrupted (invalid JSON)");
132
+ }
133
+ return { store: { version: STORE_VERSION, items: [] }, needsBackup: true };
134
+ }
135
+ if (!Array.isArray(value.items)) {
136
+ // Valid JSON object without a usable items array: nothing recoverable
137
+ // inside, so an empty store is honest. If the key exists with a wrong
138
+ // type, keep the file backed up before a write replaces it.
139
+ return {
140
+ store: { version: STORE_VERSION, items: [] },
141
+ needsBackup: value.items !== undefined,
142
+ };
143
+ }
144
+ const items = [];
145
+ let dropped = false;
146
+ for (const item of value.items) {
147
+ if (isValidStoredRecord(item)) {
148
+ items.push(item);
149
+ } else {
150
+ dropped = true;
151
+ }
152
+ }
153
+ const version = Number.isFinite(value.version) ? value.version : STORE_VERSION;
154
+ return { store: { version, items }, needsBackup: dropped };
155
+ }
156
+
157
+ // A write is about to replace a store that contained unreadable data — keep
158
+ // a copy around first so nothing is lost without a trace. Copy (not rename):
159
+ // if the replacement write then fails, the canonical path must still hold the
160
+ // damaged original, otherwise the next write would treat it as missing and
161
+ // start from an empty store.
162
+ async function backupDamagedStore(filePath) {
163
+ const stamp = new Date().toISOString().replace(/[:.]/g, "-");
164
+ try {
165
+ await fs.copyFile(filePath, `${filePath}.corrupt-${stamp}`);
166
+ } catch (e) {
167
+ if (e?.code !== "ENOENT") {
168
+ throw new Error(`Cannot back up the damaged subscription store: ${e?.message || String(e)}`);
169
+ }
170
+ }
171
+ }
172
+
173
+ async function loadStoreForWrite(filePath) {
174
+ const { store, needsBackup } = await readStore(filePath, { forWrite: true });
175
+ if (needsBackup) await backupDamagedStore(filePath);
176
+ return store;
177
+ }
178
+
179
+ async function writeStore(filePath, store) {
180
+ // Private from creation: the 0o600 applies to the tmp file before the
181
+ // rename, so a crash before the fallback chmod cannot leave a
182
+ // world-readable store behind.
183
+ await writeFileAtomic(filePath, JSON.stringify(store, null, 2) + "\n", { mode: 0o600 });
184
+ await chmod600IfPossible(filePath);
185
+ }
186
+
187
+ function sortByNextBillingAt(items) {
188
+ return [...items].sort((a, b) =>
189
+ new Date(a.nextBillingAt).getTime() - new Date(b.nextBillingAt).getTime(),
190
+ );
191
+ }
192
+
193
+ // One subscription per tool: the dashboard derives the subscription's name
194
+ // and inline progress row from the linked provider, so two records sharing a
195
+ // provider cannot be displayed. Enforced inside the store lock's
196
+ // read-modify-write transaction — the frontend picker cannot cover concurrent
197
+ // requests, stale pages, or direct API calls. `excludeId` lets an update
198
+ // re-save its own provider.
199
+ function assertProviderAvailable(items, provider, excludeId = null) {
200
+ if (!provider) return;
201
+ const conflict = items.find(
202
+ (item) => item.provider === provider && item.id !== excludeId,
203
+ );
204
+ if (conflict) {
205
+ throw new Error(
206
+ `Provider "${provider}" already has a subscription (${conflict.id})`,
207
+ );
208
+ }
209
+ }
210
+
211
+ // In-process FIFO queue per store file. Every mutation is a full
212
+ // read-modify-write transaction; without serialization two concurrent writes
213
+ // read the same snapshot and the later one silently drops the earlier change
214
+ // (issue: 30 concurrent creates survived as a single record). The queue keeps
215
+ // independent store files unblocked while ordering operations on the same one.
216
+ const storeLocks = new Map();
217
+
218
+ function withStoreLock(filePath, operation) {
219
+ const previous = storeLocks.get(filePath) || Promise.resolve();
220
+ // Run even if the previous transaction rejected; its error already reached
221
+ // its own caller and must not wedge the queue.
222
+ const run = previous.then(operation, operation);
223
+ storeLocks.set(filePath, run.then(() => undefined, () => undefined));
224
+ return run;
225
+ }
226
+
227
+ async function listSubscriptions({ trackerDir }) {
228
+ const { store } = await readStore(resolveSubscriptionsPath(trackerDir));
229
+ return sortByNextBillingAt(store.items);
230
+ }
231
+
232
+ async function createSubscription({ trackerDir, fields }) {
233
+ // Validate before taking the lock so a bad payload never queues a write.
234
+ const normalized = normalizeSubscriptionFields(fields);
235
+ const filePath = resolveSubscriptionsPath(trackerDir);
236
+ return withStoreLock(filePath, async () => {
237
+ const now = new Date().toISOString();
238
+ const record = {
239
+ id: crypto.randomUUID(),
240
+ ...normalized,
241
+ createdAt: now,
242
+ updatedAt: now,
243
+ };
244
+ const store = await loadStoreForWrite(filePath);
245
+ assertProviderAvailable(store.items, normalized.provider);
246
+ store.items.push(record);
247
+ await writeStore(filePath, store);
248
+ return record;
249
+ });
250
+ }
251
+
252
+ async function updateSubscription({ trackerDir, id, fields }) {
253
+ if (typeof id !== "string" || !id) throw new Error("id is required");
254
+ const filePath = resolveSubscriptionsPath(trackerDir);
255
+ return withStoreLock(filePath, async () => {
256
+ const store = await loadStoreForWrite(filePath);
257
+ const index = store.items.findIndex((item) => item.id === id);
258
+ if (index === -1) throw new Error("Subscription not found");
259
+ const existing = store.items[index];
260
+ // Merge over the existing record so callers may send only changed fields.
261
+ const merged = normalizeSubscriptionFields({ ...existing, ...(fields || {}) });
262
+ assertProviderAvailable(store.items, merged.provider, id);
263
+ const record = {
264
+ ...existing,
265
+ ...merged,
266
+ updatedAt: new Date().toISOString(),
267
+ };
268
+ store.items[index] = record;
269
+ await writeStore(filePath, store);
270
+ return record;
271
+ });
272
+ }
273
+
274
+ async function deleteSubscription({ trackerDir, id }) {
275
+ if (typeof id !== "string" || !id) throw new Error("id is required");
276
+ const filePath = resolveSubscriptionsPath(trackerDir);
277
+ return withStoreLock(filePath, async () => {
278
+ const store = await loadStoreForWrite(filePath);
279
+ const index = store.items.findIndex((item) => item.id === id);
280
+ if (index === -1) throw new Error("Subscription not found");
281
+ store.items.splice(index, 1);
282
+ await writeStore(filePath, store);
283
+ return { removed: true };
284
+ });
285
+ }
286
+
287
+ module.exports = {
288
+ listSubscriptions,
289
+ createSubscription,
290
+ updateSubscription,
291
+ deleteSubscription,
292
+ resolveSubscriptionsPath,
293
+ };
@@ -22,8 +22,10 @@ const {
22
22
  } = require("./codex-token-refresh");
23
23
  const {
24
24
  isCursorInstalled,
25
- extractCursorSessionToken,
25
+ extractCursorAuth,
26
26
  fetchCursorUsageSummary,
27
+ fetchCursorSandAccessStatus,
28
+ fetchCursorSandUsageStatus,
27
29
  } = require("./cursor-config");
28
30
  const { fetchGrokLimits } = require("./grok-limits");
29
31
  const { fetchZcodeLimits } = require("./zcode-limits");
@@ -678,20 +680,48 @@ function normalizeCursorUsageSummary(body) {
678
680
  };
679
681
  }
680
682
 
683
+ function normalizeCursorSandUsageStatus(body, { eligible = true } = {}) {
684
+ if (!eligible || !body || body.includedLimitZero === true) return null;
685
+ const usedPercent = clampPercent(body.usagePercent);
686
+ const resetAt = typeof body.nextResetAt === "string" ? body.nextResetAt : null;
687
+ if (usedPercent === null || !resetAt || !Number.isFinite(Date.parse(resetAt))) return null;
688
+
689
+ const periodStart = typeof body.currentPeriodStart === "string" ? body.currentPeriodStart : null;
690
+ const periodStartMs = Date.parse(periodStart || "");
691
+ const resetAtMs = Date.parse(resetAt);
692
+ const windowSeconds = Number.isFinite(periodStartMs) && resetAtMs > periodStartMs
693
+ ? Math.round((resetAtMs - periodStartMs) / 1000)
694
+ : null;
695
+ return buildWindow({ usedPercent, resetAt, windowSeconds });
696
+ }
697
+
681
698
  async function fetchCursorLimits({ home, fetchImpl = fetch } = {}) {
682
699
  if (!isCursorInstalled({ home })) {
683
700
  return { configured: false };
684
701
  }
685
- const auth = extractCursorSessionToken({ home });
686
- if (!auth?.cookie) {
702
+ const auth = extractCursorAuth({ home });
703
+ if (!auth?.cookie || !auth?.accessToken) {
687
704
  return { configured: false };
688
705
  }
689
706
  try {
690
- const body = await fetchCursorUsageSummary({ cookie: auth.cookie, fetchImpl });
707
+ // The web summary and Grok Bot (internally "Sand") RPCs are independent.
708
+ // Fetch them concurrently so the fourth window does not add two network
709
+ // round-trips to every LIMITS refresh. Sand failures are intentionally
710
+ // isolated: older Cursor accounts/servers must keep their existing three
711
+ // monthly windows instead of turning the whole provider red.
712
+ const [body, sandAccessResult, sandUsageResult] = await Promise.all([
713
+ fetchCursorUsageSummary({ cookie: auth.cookie, fetchImpl }),
714
+ fetchCursorSandAccessStatus({ accessToken: auth.accessToken, fetchImpl }).catch(() => null),
715
+ fetchCursorSandUsageStatus({ accessToken: auth.accessToken, fetchImpl }).catch(() => null),
716
+ ]);
717
+ const grokBotWindow = normalizeCursorSandUsageStatus(sandUsageResult, {
718
+ eligible: sandAccessResult?.granted === true,
719
+ });
691
720
  return {
692
721
  configured: true,
693
722
  error: null,
694
723
  ...normalizeCursorUsageSummary(body),
724
+ quaternary_window: grokBotWindow,
695
725
  };
696
726
  } catch (error) {
697
727
  return {
@@ -3454,6 +3484,7 @@ module.exports = {
3454
3484
  extractGeminiOauthClientCredentials,
3455
3485
  loadKimiCredentials,
3456
3486
  normalizeCursorUsageSummary,
3487
+ normalizeCursorSandUsageStatus,
3457
3488
  normalizeGeminiQuotaResponse,
3458
3489
  normalizeKimiUsageResponse,
3459
3490
  parseKiroUsageOutput,
@@ -1 +0,0 @@
1
- import{r as L,j as a,bP as De,c as h,e as ye,X as Ie}from"./__vite-browser-external-HdCplPKs.js";import{k as _e,V as Me,l as Ve,r as Te,n as $e,o as be,q as ve,s as Oe,t as Re,v as Be,w as Pe,x as Ke,y as Ce,z as Fe,A as Le,B as Xe,S as Ge,H as We,C as G,D as ze,E as Ue,e as Ye,F as He,m as C}from"./react-B4FPJgs_.js";import{c as je,A as Ze,p as qe,b as U,t as le,a as T,d as Je}from"./AchievementBadge-DsAclDw6.js";import{u as Qe,a as z}from"./use-transform-Dx9C2nBC.js";import{u as et}from"./use-reduced-motion-aSaQtoJu.js";import{l as ce,f as ue,b as tt}from"./AchievementsSection-BAZNM3Cn.js";import{D as nt,a as rt,b as at,c as st,d as it,e as ot}from"./DialogTitle-6epeLIn0.js";import"./zap-Png-VJSP.js";import"./flame-B6xukEYd.js";import"./format-tokens-6TqXlT3q.js";import"./useScrollLock-BUVUIPTX.js";import"./store-B2nqaAqP.js";const lt=(e,t,n)=>{const r=t-e;return((n-e)%r+r)%r+e};function Ne(e,t){return _e(e)?e[lt(0,e.length,t)]:e}class ct{constructor(t){this.stop=()=>this.runAll("stop"),this.animations=t.filter(Boolean)}get finished(){return Promise.all(this.animations.map(t=>t.finished))}getAll(t){return this.animations[0][t]}setAll(t,n){for(let r=0;r<this.animations.length;r++)this.animations[r][t]=n}attachTimeline(t){const n=this.animations.map(r=>r.attachTimeline(t));return()=>{n.forEach((r,s)=>{r&&r(),this.animations[s].stop()})}}get time(){return this.getAll("time")}set time(t){this.setAll("time",t)}get speed(){return this.getAll("speed")}set speed(t){this.setAll("speed",t)}get state(){return this.getAll("state")}get startTime(){return this.getAll("startTime")}get duration(){return de(this.animations,"duration")}get iterationDuration(){return de(this.animations,"iterationDuration")}runAll(t){this.animations.forEach(n=>n[t]())}play(){this.runAll("play")}pause(){this.runAll("pause")}cancel(){this.runAll("cancel")}complete(){this.runAll("complete")}}function de(e,t){let n=0;for(let r=0;r<e.length;r++){const s=e[r][t];s!==null&&s>n&&(n=s)}return n}class ut extends ct{then(t,n){return this.finished.finally(t).then(()=>{})}}function dt(e,t){return e in t}class mt extends Me{constructor(){super(...arguments),this.type="object"}readValueFromInstance(t,n){if(dt(n,t)){const r=t[n];if(typeof r=="string"||typeof r=="number")return r}}getBaseTargetFromProps(){}removeValueFromRenderState(t,n){delete n.output[t]}measureInstanceViewportBox(){return Ve()}build(t,n){Object.assign(t.output,n)}renderInstance(t,{output:n}){Object.assign(t,n)}sortInstanceNodePosition(){return 0}}function Y(e){return typeof e=="object"&&!Array.isArray(e)}function ke(e,t,n,r){return e==null?[]:typeof e=="string"&&Y(t)?Te(e,n,r):e instanceof NodeList?Array.from(e):Array.isArray(e)?e.filter(s=>s!=null):[e]}function ft(e,t,n){return e*(t+1)+n*t}function me(e,t,n,r){return typeof t=="number"?t:t.startsWith("-")||t.startsWith("+")?Math.max(0,e+parseFloat(t)):t==="<"?n:t.startsWith("<")?Math.max(0,n+parseFloat(t.slice(1))):r.get(t)??e}function pt(e,t,n){for(let r=0;r<e.length;r++){const s=e[r];s.at>t&&s.at<n&&(be(e,s),r--)}}function ht(e,t,n,r,s,c){pt(e,s,c);for(let i=0;i<t.length;i++)e.push({value:t[i],at:$e(s,c,r[i]),easing:Ne(n,i)})}function gt(e,t,n=0){const r=t+1+t*n;for(let s=0;s<e.length;s++)e[s]=e[s]/r}function xt(e,t){return e.at===t.at?e.value===null?1:t.value===null?-1:0:e.at-t.at}const yt="easeInOut",bt=20;function vt(e,{defaultTransition:t={},...n}={},r,s){const c=t.duration||.3,i=new Map,f=new Map,m={},p=new Map;let g=0,u=0,x=0;for(let N=0;N<e.length;N++){const k=e[N];if(typeof k=="string"){p.set(k,u);continue}else if(!Array.isArray(k)){p.set(k.name,me(u,k.at,g,p));continue}let[E,b,v={}]=k;v.at!==void 0&&(u=me(u,v.at,g,p));let j=0;const _=(w,M,A,o=0,l=0)=>{const d=jt(w),{delay:D=0,times:y=Oe(d),type:R=t.type||"keyframes",repeat:B,repeatType:W,repeatDelay:H=0,...Se}=M;let{ease:I=t.ease||"easeOut",duration:S}=M;const Z=typeof D=="function"?D(o,l):D,q=d.length,J=Ke(R)?R:s?.[R||"keyframes"];if(q<=2&&J){let $=100;if(q===2&&wt(d)){const P=d[1]-d[0];$=Math.abs(P)}const O={...t,...Se};S!==void 0&&(O.duration=Ce(S));const X=Re(O,$,J);I=X.ease,S=X.duration}S??(S=c);const Q=u+Z;y.length===1&&y[0]===0&&(y[1]=1);const ee=y.length-d.length;if(ee>0&&Be(y,ee),d.length===1&&d.unshift(null),B&&B<bt){const $=S>0?H/S:0;S=ft(S,B,H);const O=[...d],X=[...y];I=Array.isArray(I)?[...I]:[I];const P=[...I],ne=W==="reverse"||W==="mirror";let re=O,ae=P;ne&&(re=[...O].reverse(),W==="reverse"&&(ae=[...P].reverse().map(V=>typeof V=="function"?Pe(V):V)));for(let V=0;V<B;V++){const se=ne&&V%2===0,ie=se?re:O,Ee=se?ae:P,oe=(V+1)*(1+$);$>0&&(d.push(d[d.length-1]),y.push(oe),I.push("linear")),d.push(...ie);for(let K=0;K<ie.length;K++)y.push(X[K]+oe),I.push(K===0?"linear":Ne(Ee,K-1))}gt(y,B,$)}const te=Q+S;ht(A,d,I,y,Q,te),j=Math.max(Z+S,j),x=Math.max(te,x)};if(ve(E)){const w=fe(E,f);_(b,v,pe("default",w))}else{const w=ke(E,b,r,m),M=w.length;for(let A=0;A<M;A++){b=b,v=v;const o=w[A],l=fe(o,f);for(const d in b)_(b[d],Nt(v,d),pe(d,l),A,M)}}g=u,u+=j}return f.forEach((N,k)=>{for(const E in N){const b=N[E];b.sort(xt);const v=[],j=[],_=[];for(let o=0;o<b.length;o++){const{at:l,value:d,easing:D}=b[o];v.push(d),j.push(Fe(0,x,l)),_.push(D||"easeOut")}j[0]!==0&&(j.unshift(0),v.unshift(v[0]),_.unshift(yt)),j[j.length-1]!==1&&(j.push(1),v.push(null)),i.has(k)||i.set(k,{keyframes:{},transition:{}});const w=i.get(k);w.keyframes[E]=v;const{type:M,...A}=t;w.transition[E]={...A,duration:x,ease:_,times:j,...n}}}),i}function fe(e,t){return!t.has(e)&&t.set(e,{}),t.get(e)}function pe(e,t){return t[e]||(t[e]=[]),t[e]}function jt(e){return Array.isArray(e)?e:[e]}function Nt(e,t){return e&&e[t]?{...e,...e[t]}:{...e}}const kt=e=>typeof e=="number",wt=e=>e.every(kt);function At(e){const t={presenceContext:null,props:{},visualState:{renderState:{transform:{},transformOrigin:{},style:{},vars:{},attrs:{}},latestValues:{}}},n=Le(e)&&!Xe(e)?new Ge(t):new We(t);n.mount(e),G.set(e,n)}function St(e){const t={presenceContext:null,props:{},visualState:{renderState:{output:{}},latestValues:{}}},n=new mt(t);n.mount(e),G.set(e,n)}function Et(e,t){return ve(e)||typeof e=="number"||typeof e=="string"&&!Y(t)}function we(e,t,n,r){const s=[];if(Et(e,t))s.push(ze(e,Y(t)&&t.default||t,n&&(n.default||n)));else{if(e==null)return s;const c=ke(e,t,r),i=c.length;for(let f=0;f<i;f++){const m=c[f],p=m instanceof Element?At:St;G.has(m)||p(m);const g=G.get(m),u={...n};"delay"in u&&typeof u.delay=="function"&&(u.delay=u.delay(f,i)),s.push(...Ue(g,{...t,transition:u},{}))}}return s}function Dt(e,t,n){const r=[],s=e.map(i=>{if(Array.isArray(i)&&typeof i[0]=="function"){const f=i[0],m=Ye(0);return m.on("change",f),i.length===1?[m,[0,1]]:i.length===2?[m,[0,1],i[1]]:[m,i[1],i[2]]}return i});return vt(s,t,n,{spring:He}).forEach(({keyframes:i,transition:f},m)=>{r.push(...we(m,i,f))}),r}function It(e){return Array.isArray(e)&&e.some(Array.isArray)}function _t(e={}){const{scope:t,reduceMotion:n,skipAnimations:r}=e;function s(c,i,f){let m=[],p;const g={};if(n!==void 0&&(g.reduceMotion=n),r!==void 0&&(g.skipAnimations=r),It(c)){const{onComplete:x,...N}=i||{};typeof x=="function"&&(p=x),m=Dt(c,{...g,...N},t)}else{const{onComplete:x,...N}=f||{};typeof x=="function"&&(p=x),m=we(c,i,{...g,...N},t)}const u=new ut(m);return p&&u.finished.then(p),t&&(t.animations.push(u),u.finished.then(()=>{be(t.animations,u)})),u}return s}const F=_t(),he=8;function Mt({badgeId:e,tier:t,locked:n=!1,size:r=176,backLines:s=[],label:c}){const i=Qe(0),f=et(),m=L.useRef(null),p=L.useRef(null),g=L.useRef(!1),u=qe(t,n),x=je.get(e)?.icon||null,N=z(i,o=>`${(o%360+360)%360/360*160-80}%`),k=z(i,o=>`${80-(o%360+360)%360/360*160}%`),E=z(i,o=>{const l=Math.abs(Math.sin(o*Math.PI/180));return Math.max(0,(l-.35)/.65)*.3}),b=()=>{p.current?.stop?.(),p.current=null};L.useEffect(()=>{if(f||g.current)return;let o=!1;i.set(-360);const l=F(i,0,{duration:.9,ease:[.16,1,.3,1]});return p.current=l,l.then(()=>{o||g.current||(p.current=F(i,[0,-14,14,0],{duration:4.5,repeat:1/0,ease:"easeInOut"}))}),()=>{o=!0,b()}},[f,i]);const v=o=>{const l=i.get();if(f){const y=Math.round(l/180)*180;p.current=F(i,y,{duration:.2,ease:"easeOut"});return}const d=l+o*.35,D=Math.round(d/180)*180;p.current=F(i,D,{type:"spring",velocity:o,stiffness:58,damping:13.5,mass:1})},j=o=>{g.current=!0,b(),o.currentTarget.setPointerCapture?.(o.pointerId),m.current={pointerId:o.pointerId,startX:o.clientX,startRot:i.get(),samples:[{t:o.timeStamp,x:o.clientX}]}},_=o=>{const l=m.current;!l||l.pointerId!==o.pointerId||(i.set(l.startRot+(o.clientX-l.startX)*.55),l.samples.push({t:o.timeStamp,x:o.clientX}),l.samples.length>5&&l.samples.shift())},w=o=>{const l=m.current;if(!l||l.pointerId!==o.pointerId)return;m.current=null;const d=l.samples[0],D=l.samples[l.samples.length-1],y=D.t-d.t,R=y>0?(D.x-d.x)*.55*1e3/y:0;v(R)},M=o=>{if(o.key!=="ArrowLeft"&&o.key!=="ArrowRight")return;o.preventDefault(),g.current=!0,b();const l=o.key==="ArrowRight"?30:-30;p.current=F(i,i.get()+l,{duration:.15,ease:"easeOut"})},A={backfaceVisibility:"hidden",WebkitBackfaceVisibility:"hidden"};return a.jsx("div",{role:"img","aria-label":c,tabIndex:0,onPointerDown:j,onPointerMove:_,onPointerUp:w,onPointerCancel:w,onKeyDown:M,className:"inline-flex cursor-grab select-none items-center justify-center outline-none focus-visible:ring-2 focus-visible:ring-oai-brand/60 rounded-full active:cursor-grabbing",style:{perspective:900,touchAction:"pan-y"},children:a.jsxs("div",{className:"relative",style:{transform:"rotateX(-8deg)",transformStyle:"preserve-3d"},children:[a.jsxs(C.div,{className:"relative",style:{rotateY:i,transformStyle:"preserve-3d",width:r,height:r},children:[[-3,-1.5,0,1.5,3].map(o=>a.jsx("div",{"aria-hidden":!0,className:"absolute inset-0 rounded-full",style:{transform:`translateZ(${o}px)`,background:u.rim[1]}},o)),a.jsxs("div",{className:"absolute inset-0 overflow-hidden rounded-full",style:{...A,transform:`translateZ(${he/2}px)`},children:[a.jsx(Ze,{badgeId:e,tier:t,locked:n,size:"fill",className:"brightness-105 saturate-[1.08]"}),a.jsx("div",{"aria-hidden":!0,className:"pointer-events-none absolute inset-0 rounded-full",style:{background:"radial-gradient(circle at 30% 20%, rgba(255,255,255,0.45), rgba(255,255,255,0) 42%), linear-gradient(172deg, rgba(255,255,255,0.14) 0%, rgba(255,255,255,0) 38%, rgba(0,0,0,0.08) 100%)",boxShadow:"inset 0 3px 7px rgba(255,255,255,0.5), inset 0 -3px 8px rgba(0,0,0,0.15)"}}),a.jsx(C.div,{"aria-hidden":!0,className:"pointer-events-none absolute inset-0",style:{x:N,background:"linear-gradient(105deg, transparent 34%, rgba(255,255,255,0.5) 50%, transparent 66%)"}}),a.jsx(C.div,{"aria-hidden":!0,className:"pointer-events-none absolute inset-0 rounded-full",style:{opacity:E,background:"rgba(8, 12, 10, 0.9)"}})]}),a.jsxs("div",{className:"absolute inset-0 flex flex-col items-center justify-center gap-1 overflow-hidden rounded-full px-6 text-center",style:{...A,transform:`rotateY(180deg) translateZ(${he/2}px)`,background:`linear-gradient(145deg, ${u.face[0]}, ${u.face[1]})`,boxShadow:`inset 0 0 0 6px ${u.rim[1]}, inset 0 0 0 7.5px rgba(255,255,255,0.22), inset 0 3px 7px rgba(255,255,255,0.4), inset 0 -4px 12px rgba(0,0,0,0.22)`},children:[a.jsx("div",{"aria-hidden":!0,className:"pointer-events-none absolute inset-0 rounded-full",style:{background:"repeating-radial-gradient(circle at 50% 50%, rgba(255,255,255,0.06) 0px, rgba(255,255,255,0.06) 1px, transparent 1px, transparent 4px)"}}),x?a.jsx(x,{"aria-hidden":!0,size:Math.round(r*.62),strokeWidth:1.1,color:u.glyph,className:"pointer-events-none absolute opacity-[0.13]",style:{filter:"drop-shadow(0 1px 0 rgba(255,255,255,0.3)) drop-shadow(0 -1px 0 rgba(0,0,0,0.35))"}}):null,a.jsx("div",{"aria-hidden":!0,className:"pointer-events-none absolute inset-0 rounded-full",style:{background:"radial-gradient(circle at 70% 20%, rgba(255,255,255,0.4), rgba(255,255,255,0) 44%), linear-gradient(188deg, rgba(255,255,255,0.12) 0%, rgba(255,255,255,0) 38%, rgba(0,0,0,0.10) 100%)"}}),s.map((o,l)=>a.jsx("div",{className:`font-mono tabular-nums ${l===0?"text-[10px] uppercase tracking-[0.18em]":l===1?"text-lg font-bold":"text-[11px]"}`,style:{color:u.glyph,textShadow:"0 1px 0 rgba(255,255,255,0.28), 0 -1px 0 rgba(0,0,0,0.3)"},children:o},`${l}-${o}`)),a.jsx(C.div,{"aria-hidden":!0,className:"pointer-events-none absolute inset-0",style:{x:k,background:"linear-gradient(105deg, transparent 34%, rgba(255,255,255,0.45) 50%, transparent 66%)"}}),a.jsx(C.div,{"aria-hidden":!0,className:"pointer-events-none absolute inset-0 rounded-full",style:{opacity:E,background:"rgba(8, 12, 10, 0.9)"}})]})]}),a.jsx("div",{"aria-hidden":!0,className:"absolute left-1/2 h-3 w-3/5 rounded-[100%] bg-black/20 blur-md dark:bg-black/45",style:{bottom:-20,transform:"translateX(-50%)"}})]})})}function Ae(e){if(!e)return null;const t=Date.parse(e);return Number.isFinite(t)?new Date(t).toLocaleDateString():null}function Vt(e){const t=Number(e);return!Number.isSafeInteger(t)||t<1?null:String(t).padStart(6,"0")}function Tt(e,t,n){if(t?.scope!=="cloud"||!n)return null;const r=Number(e?.serials?.[n]);return Number.isSafeInteger(r)&&r>=1?r:null}function $t({badge:e}){return a.jsx("div",{className:"flex items-center gap-1",children:Je.map((t,n)=>{const r=(e.tier||0)>=n+1,s=Ae(e.achieved?.[t]),c=T[t];return a.jsx("span",{title:s?`${h(`achievements.tier.${t}`)} · ${s}`:h(`achievements.tier.${t}`),className:"inline-flex h-2 w-8 rounded-full",style:r?{background:`linear-gradient(120deg, ${c.rim[0]} 0%, ${c.ring} 55%, ${c.rim[1]} 100%)`,boxShadow:"inset 0 1px 1px rgba(255,255,255,0.4), 0 0 0 1px rgba(10,15,12,0.05)"}:void 0,children:!r&&a.jsx("span",{className:"h-full w-full rounded-full bg-oai-gray-200 dark:bg-oai-gray-800"})},t)})})}function ge({badge:e,onClose:t}){const n=je.get(e.id),r=h(U(e.id,"name")),s=(e.tier||0)>=1,c=s?le(e.tier):null,i=Ae(s?e.achieved?.[c]||(ce(e)?new Date(ce(e)).toISOString():null):null),f=ue(n?.format,e.metric_value),m=tt(e),p=e.tier<4?le((e.tier||0)+1):null,g=Tt(e,n,c),u=Vt(g),x=u?[h("achievements.modal.achieved_label"),h("achievements.modal.issue_number",{number:u}),i||r]:[s?h("achievements.modal.achieved_label"):h("achievements.modal.locked"),s?f:"···",s&&i?i:r];return a.jsxs("div",{className:"flex flex-col items-center px-6 pb-6 pt-5 text-center",children:[a.jsxs("div",{className:"flex w-full items-start justify-between gap-3",children:[a.jsxs("div",{className:"min-w-0 flex-1 text-left",children:[a.jsx("h2",{className:"truncate text-lg font-semibold tracking-tight text-oai-black dark:text-white",children:r}),a.jsx("p",{className:"mt-0.5 text-xs text-oai-gray-500 dark:text-oai-gray-400",children:h(U(e.id,"desc"))})]}),a.jsx("button",{type:"button",onClick:t,"aria-label":h("achievements.modal.close"),className:"shrink-0 rounded-md p-1.5 text-oai-gray-400 transition-colors hover:bg-oai-gray-100 hover:text-oai-gray-700 dark:hover:bg-oai-gray-900 dark:hover:text-oai-gray-200",children:a.jsx(Ie,{size:16})})]}),a.jsx("div",{className:"mt-5 mb-7",children:a.jsx(Mt,{badgeId:e.id,tier:e.tier,locked:!s,backLines:x,label:h("achievements.modal.coin_aria",{name:r})})}),a.jsxs("div",{className:"flex items-center gap-2",children:[a.jsx("span",{className:"rounded-full px-2.5 py-0.5 text-[11px] font-semibold uppercase tracking-wide",style:s?{background:`linear-gradient(120deg, ${T[c].rim[0]} 0%, ${T[c].ring} 55%, ${T[c].rim[1]} 100%)`,color:T[c].glyph,textShadow:"0 1px 0 rgba(255,255,255,0.35)",boxShadow:"inset 0 1px 1px rgba(255,255,255,0.4), 0 0 0 1px rgba(10,15,12,0.06)"}:{background:"rgba(128,134,130,0.75)",color:"rgba(250,250,250,0.95)"},children:s?h(`achievements.tier.${c}`):h("achievements.modal.locked")}),s&&i?a.jsx("span",{className:"text-xs tabular-nums text-oai-gray-500 dark:text-oai-gray-400",children:i}):null]}),a.jsxs("dl",{className:"mt-5 w-full space-y-3 border-t border-oai-gray-200/70 pt-4 text-left dark:border-oai-gray-800/60",children:[a.jsxs("div",{className:"flex items-baseline justify-between gap-3 text-sm",children:[a.jsx("dt",{className:"text-oai-gray-500 dark:text-oai-gray-400",children:h("achievements.modal.value_label")}),a.jsx("dd",{className:"font-mono font-semibold tabular-nums text-oai-black dark:text-white",children:f})]}),a.jsxs("div",{children:[a.jsxs("div",{className:"flex items-baseline justify-between gap-3 text-xs text-oai-gray-500 dark:text-oai-gray-400",children:[a.jsx("span",{children:e.tier>=4?h("achievements.modal.max_tier"):h("achievements.modal.progress_to_next",{tier:h(`achievements.tier.${p}`)})}),e.tier<4&&e.next_threshold!=null?a.jsxs("span",{className:"font-mono tabular-nums",children:[f," ",e.lower_is_better?"→":"/"," ",ue(n?.format,e.next_threshold)]}):null]}),a.jsx("div",{className:"mt-1.5 h-1.5 w-full overflow-hidden rounded-full bg-oai-gray-200 dark:bg-oai-gray-800",children:a.jsx("div",{className:"h-full rounded-full transition-[width] duration-500",style:{width:`${Math.round((e.tier>=4?1:m)*100)}%`,background:s?`linear-gradient(90deg, ${T[c].rim[0]} 0%, ${T[c].ring} 55%, ${T[c].rim[1]} 100%)`:"rgba(128,134,130,0.75)",boxShadow:s?"inset 0 1px 1px rgba(255,255,255,0.35)":void 0}})})]}),a.jsxs("div",{className:"flex items-center justify-between gap-3 text-xs text-oai-gray-500 dark:text-oai-gray-400",children:[a.jsx("span",{children:h("achievements.modal.tier_history")}),a.jsx($t,{badge:e})]})]})]})}const xe=ye("relative w-full max-w-[380px] flex flex-col","rounded-2xl bg-white dark:bg-oai-gray-950","shadow-[0_20px_60px_-20px_rgba(0,0,0,0.25)] dark:shadow-[0_20px_60px_-10px_rgba(0,0,0,0.65)]","ring-1 ring-oai-gray-200 dark:ring-oai-gray-800 overflow-hidden","dark:border-t dark:border-white/[0.08]");function Ut({badge:e,onClose:t}){const n=De(),r=!!e;return L.useEffect(()=>{if(!n||!r)return;const s=c=>{c.key==="Escape"&&(c.stopPropagation(),t?.())};return window.addEventListener("keydown",s,!0),()=>window.removeEventListener("keydown",s,!0)},[n,r,t]),r?n?a.jsxs("div",{className:"fixed inset-0 z-[120] flex items-center justify-center p-4",children:[a.jsx("div",{className:"absolute inset-0 bg-black/40 backdrop-blur-[2px]",onClick:t,"aria-hidden":!0}),a.jsx("div",{className:xe,children:a.jsx(ge,{badge:e,onClose:t})})]}):a.jsx(nt,{open:!0,onOpenChange:s=>{s||t?.()},children:a.jsxs(rt,{children:[a.jsx(at,{className:"cost-modal-backdrop z-[110]"}),a.jsx(st,{className:"fixed inset-0 z-[120] flex items-center justify-center p-4",children:a.jsxs(it,{className:ye("cost-modal-popup",xe),children:[a.jsx(ot,{render:a.jsx("h2",{className:"sr-only"}),children:h(U(e.id,"name"))}),a.jsx(ge,{badge:e,onClose:t})]})})]})}):null}export{Ut as BadgeDetailModal,Tt as currentBadgeIssueNumber,Ut as default,Vt as formatIssueNumber};
@@ -1 +0,0 @@
1
- import{m as L,j as e,$ as R,n as P,r as D,c as n,X as z,l as S}from"./__vite-browser-external-HdCplPKs.js";import{m as M}from"./react-B4FPJgs_.js";import{A as K,W as U}from"./icons-pGe_pInY.js";import{u as B}from"./useTokenFormat-DFSIAsAb.js";import{P as F}from"./ProviderIcon-d0_vhIkS.js";import{T as G}from"./TrendMonitor-DAAlILwJ.js";import{T as W}from"./AchievementBadge-DsAclDw6.js";import{T as V}from"./terminal-BxVMmvEx.js";import{D as X,a as Y,b as Z,c as H,d as q,e as J}from"./DialogTitle-6epeLIn0.js";import{D as Q}from"./DialogDescription-C5Ujj254.js";import{D as ee}from"./DialogClose-BbderFCY.js";import"./useCurrency-7dkDciam.js";import"./chevron-right-DCvGp9iJ.js";import"./PopoverPopup-BK9aqQn1.js";import"./useScrollLock-BUVUIPTX.js";import"./store-B2nqaAqP.js";import"./ToolbarRootContext-DnC8LT_8.js";import"./maximize-2-1EmlA2R-.js";import"./use-reduced-motion-aSaQtoJu.js";import"./zap-Png-VJSP.js";import"./flame-B6xukEYd.js";const ae=[["path",{d:"M16 17h6v-6",key:"t6n2it"}],["path",{d:"m22 17-8.5-8.5-5 5L2 7",key:"x473p"}]],te=L("trending-down",ae),O=10,_={input:"var(--community-token-input)",cache_read:"var(--community-token-cache-read)",cache_write:"var(--community-token-cache-write)",output:"var(--community-token-output)",reasoning:"var(--community-token-reasoning)"},re={CLAUDE:"var(--community-claude)",CODEX:"var(--community-codex)",GEMINI:"var(--community-gemini)",CURSOR:"var(--community-cursor)",OPENCODE:"var(--community-opencode)",HERMES:"var(--community-hermes)",KIMI:"var(--community-kimi)",MIMO:"var(--community-mimo)",COPILOT:"var(--community-copilot)",KIRO:"var(--community-kiro)",GROK:"var(--community-grok)",DEEPSEEK:"var(--community-deepseek)",ZCODE:"var(--community-zcode)",WORKBUDDY:"var(--community-workbuddy)",MINIMAX:"var(--community-minimax)",DROID:"var(--community-droid)"};function ie(t){return re[String(t||"").toUpperCase()]||"var(--community-muted)"}const se=[[/claude|fable|opus|sonnet|haiku/,"CLAUDE"],[/gpt|codex|o3|o4/,"CODEX"],[/gemini/,"GEMINI"],[/composer|cursor/,"CURSOR"],[/kimi/,"KIMI"],[/mimo/,"MIMO"],[/copilot/,"COPILOT"],[/kiro/,"KIRO"],[/grok/,"GROK"],[/deepseek/,"DEEPSEEK"],[/glm/,"ZCODE"],[/hy3/,"WORKBUDDY"],[/minimax/,"MINIMAX"]],g=["overview","providers","community","models"];function oe(t){const s=String(t||"").toLowerCase(),a=se.find(([i])=>i.test(s));return a?a[1]:""}function u(t){const s=Number(t);return Number.isFinite(s)?`${s.toFixed(1)}%`:"—"}function p(t){return S(Number(t)||0)}function ne(t){return t?new Date(`${t}T00:00:00Z`).toLocaleDateString(void 0,{month:"short",day:"numeric",timeZone:"UTC"}):""}function k(){return e.jsx("div",{className:"flex h-full min-h-40 items-center justify-center text-xs text-oai-gray-400",children:n("leaderboard.community.modal.no_data")})}function b({children:t,detail:s}){return e.jsxs("div",{className:"mb-3 flex items-baseline justify-between gap-4",children:[e.jsx("h3",{className:"text-xs font-medium uppercase tracking-wide text-oai-gray-500 dark:text-oai-gray-400",children:t}),s?e.jsx("span",{className:"text-xs text-oai-gray-400",children:s}):null]})}function C({value:t,label:s}){const a=Number(t);if(!Number.isFinite(a))return null;const i=Math.sign(a)!==-1,r=i?W:te;return e.jsxs("span",{className:`inline-flex items-center gap-1 text-xs font-medium tabular-nums ${i?"text-emerald-600 dark:text-emerald-400":"text-rose-600 dark:text-rose-400"}`,title:s,children:[e.jsx(r,{className:"size-3","aria-hidden":"true"}),i?"+":"",a.toFixed(1),"%"]})}function j({label:t,value:s,title:a,delta:i,deltaLabel:r}){return e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"truncate text-xs font-medium text-oai-gray-500 dark:text-oai-gray-400",children:t}),e.jsxs("div",{className:"mt-1 flex min-w-0 items-baseline gap-2",children:[e.jsx("span",{className:"truncate text-xl font-semibold leading-none tracking-tight text-oai-black tabular-nums dark:text-white",title:a,children:s}),e.jsx(C,{value:i,label:r})]})]})}function I({fillWidth:t,share:s,color:a="var(--oai-blue)",ariaLabel:i,dataAttrs:r,children:o}){return e.jsxs("div",{...r,className:"group relative grid min-h-11 grid-cols-[minmax(0,1fr)_auto] items-center gap-3 overflow-hidden px-2.5 transition-colors hover:bg-oai-gray-50 dark:hover:bg-oai-gray-900/60",children:[e.jsx("div",{className:"pointer-events-none absolute inset-y-0 left-0 opacity-[0.15] transition-opacity group-hover:opacity-[0.22] dark:opacity-[0.24] dark:group-hover:opacity-[0.32]",style:{width:`${t}%`,backgroundColor:a},role:"progressbar","aria-label":i,"aria-valuemin":"0","aria-valuemax":"100","aria-valuenow":Number(s)||0}),o]})}function A({rank:t,provider:s,name:a,fillWidth:i,share:r,tokens:o,tokensTitle:l,dataAttrs:c}){return e.jsxs(I,{fillWidth:i,share:r,color:ie(s),ariaLabel:`${a} ${u(r)}`,dataAttrs:c,children:[e.jsxs("div",{className:"relative flex min-w-0 items-center gap-2.5",children:[e.jsx("span",{className:`w-5 shrink-0 text-xs tabular-nums ${t<=3?"font-semibold text-oai-gray-700 dark:text-oai-gray-200":"text-oai-gray-400"}`,children:t}),e.jsx("span",{className:"grid size-6 shrink-0 place-items-center text-oai-gray-700 dark:text-oai-gray-200",children:e.jsx(F,{provider:s,size:15})}),e.jsx("span",{className:"truncate text-xs font-medium text-oai-gray-700 dark:text-oai-gray-200",title:a,children:a})]}),e.jsxs("div",{className:"relative min-w-[4.5rem] text-right",children:[e.jsx("div",{className:"text-xs font-semibold text-oai-black tabular-nums dark:text-white",title:l,children:o}),e.jsx("div",{className:"text-xs text-oai-gray-500 tabular-nums dark:text-oai-gray-400",children:u(r)})]})]})}function le({rows:t,formatTokensTooltip:s}){return t.length?e.jsxs("div",{className:"mt-7",children:[e.jsx(b,{children:n("leaderboard.community.modal.token_mix")}),e.jsx("div",{className:"flex h-1.5 overflow-hidden bg-oai-gray-100 dark:bg-oai-gray-800",children:t.map(a=>e.jsx("div",{style:{width:`${Math.max(Number(a.share)||0,0)}%`,backgroundColor:_[a.key]||"var(--community-muted)"},title:`${n(`leaderboard.community.modal.token_mix.${a.key}`)} · ${u(a.share)}`},a.key))}),e.jsx("div",{className:"mt-3 flex flex-wrap gap-x-5 gap-y-1.5",children:t.map(a=>e.jsxs("span",{className:"inline-flex items-center gap-1.5 text-xs text-oai-gray-500 dark:text-oai-gray-400",title:s(a.tokens),children:[e.jsx("span",{className:"size-2",style:{backgroundColor:_[a.key]||"var(--community-muted)"}}),n(`leaderboard.community.modal.token_mix.${a.key}`),e.jsx("span",{className:"tabular-nums text-oai-gray-700 dark:text-oai-gray-200",children:u(a.share)})]},a.key))})]}):null}function f({label:t,value:s,title:a,delta:i,deltaLabel:r,className:o=""}){return e.jsxs("div",{className:`min-w-0 ${o}`,children:[e.jsx("div",{className:"truncate text-xs text-oai-gray-500 dark:text-oai-gray-400",children:t}),e.jsxs("div",{className:"mt-1 flex min-w-0 items-baseline gap-2",children:[e.jsx("span",{className:"truncate text-base font-semibold leading-none tracking-tight tabular-nums text-oai-black dark:text-white",title:a,children:s}),e.jsx(C,{value:i,label:r})]})]})}function de({trendRows:t,activeDevelopers30d:s,developerGrowthPct:a,formatTokens:i,formatTokensTooltip:r}){if(!t.length)return null;const o=t.reduce((m,h)=>m+h.value,0),l=t.reduce((m,h)=>m.value<h.value?h:m,t[0]),c=o/t.length;return e.jsxs("div",{className:"mt-5 grid grid-cols-3 divide-x divide-oai-gray-100 border-y border-oai-gray-100 py-3.5 dark:divide-oai-gray-800/80 dark:border-oai-gray-800/80",children:[e.jsx(f,{className:"pr-4",label:n("leaderboard.community.modal.daily_average"),value:i(c),title:r(c)}),e.jsx(f,{className:"px-4",label:`${n("leaderboard.community.modal.peak_day")} · ${l.day}`,value:i(l.value),title:r(l.value)}),e.jsx(f,{className:"pl-4",label:n("leaderboard.community.modal.active_30d"),value:p(s),title:Number(s).toLocaleString(),delta:a,deltaLabel:n("leaderboard.community.modal.vs_previous_week")})]})}function me({trendRows:t,mix:s,activeDevelopers30d:a,developerGrowthPct:i,formatTokens:r,formatTokensTooltip:o}){return!t.length&&!s.length?e.jsx(k,{}):e.jsxs("div",{children:[e.jsx(b,{detail:n("leaderboard.community.modal.utc_note"),children:n("leaderboard.community.modal.community_activity")}),e.jsx(G,{embedded:!0,rows:t,from:t[0]?.day,to:t.at(-1)?.day,chartHeightClass:"h-44"}),e.jsx(de,{trendRows:t,activeDevelopers30d:a,developerGrowthPct:i,formatTokens:r,formatTokensTooltip:o}),e.jsx(le,{rows:s,formatTokensTooltip:o})]})}function ce({rows:t,maxShare:s,formatTokens:a,formatTokensTooltip:i}){return t.length?e.jsx("div",{className:"space-y-0.5",children:t.map((r,o)=>e.jsx(A,{rank:o+1,dataAttrs:{"data-provider-rank":o+1,"data-provider-name":r.name},provider:String(r.name).toUpperCase(),name:r.name,fillWidth:Math.max((Number(r.share)||0)/s*100,2),share:r.share,tokens:a(r.tokens),tokensTitle:i(r.tokens)},r.name))}):e.jsx(k,{})}function xe({rows:t,maxShare:s,formatTokens:a,formatTokensTooltip:i}){return t.length?e.jsx("div",{className:"space-y-0.5",children:t.map((r,o)=>{const l=Number(r.share)||0;return e.jsx(A,{rank:o+1,dataAttrs:{"data-model-rank":o+1,"data-model-name":r.name},provider:oe(r.name),name:r.name,fillWidth:Math.max(l/s*100,2),share:l,tokens:a(r.tokens),tokensTitle:i(r.tokens)},r.name)})}):e.jsx(k,{})}function ue({name:t}){const s=String(t||"").toLowerCase();return s==="darwin"?e.jsx(K,{className:"size-3.5"}):s==="win32"?e.jsx(U,{className:"size-3.5"}):e.jsx(V,{className:"size-4","aria-hidden":"true"})}const he=.175,ye=.3;function ge({bands:t,formatTokensTooltip:s}){const a=t.reduce((r,o)=>Math.max(r,Number(o.developer_share)||0),0)||1,i=r=>`${n(`leaderboard.community.modal.band.${r.key}`)} · ${n("leaderboard.community.modal.developer_count",{count:p(r.developers)})} (${s(r.tokens)})`;return e.jsxs("div",{children:[e.jsx("div",{className:"flex gap-2 border-b border-oai-gray-200 dark:border-oai-gray-800",children:t.map((r,o)=>{const l=Number(r.developer_share)||0,c=Math.max(l/a*80,2);return e.jsxs("div",{className:"relative h-32 min-w-0 flex-1",title:i(r),children:[e.jsx("div",{role:"progressbar","aria-label":n("leaderboard.community.modal.developer_share_title",{share:u(l)}),"aria-valuemin":"0","aria-valuemax":"100","aria-valuenow":l,className:"absolute inset-x-0 bottom-0",style:{height:`${c}%`,backgroundColor:"var(--oai-blue)",opacity:ye+o*he}}),e.jsx("div",{className:"absolute inset-x-0 text-center text-xs font-medium tabular-nums text-oai-gray-700 dark:text-oai-gray-200",style:{bottom:`calc(${c}% + 4px)`},children:u(l)})]},r.key)})}),e.jsx("div",{className:"mt-2 flex gap-2",children:t.map(r=>e.jsxs("div",{className:"min-w-0 flex-1 text-center",title:i(r),children:[e.jsx("div",{className:"truncate text-xs font-medium text-oai-gray-700 dark:text-oai-gray-200",children:n(`leaderboard.community.modal.band.${r.key}`)}),e.jsx("div",{className:"truncate text-xs tabular-nums text-oai-gray-500 dark:text-oai-gray-400",children:p(r.developers)})]},r.key))})]})}function pe({bands:t,platforms:s,formatTokensTooltip:a}){return!t.length&&!s.length?e.jsx(k,{}):e.jsxs("div",{className:"space-y-8",children:[t.length?e.jsxs("div",{children:[e.jsx(b,{children:n("leaderboard.community.modal.usage_distribution")}),e.jsx(ge,{bands:t,formatTokensTooltip:a})]}):null,s.length?e.jsxs("div",{children:[e.jsx(b,{children:n("leaderboard.community.modal.platforms")}),e.jsx("div",{className:"space-y-0.5",children:s.map(i=>e.jsxs(I,{fillWidth:Math.max(Number(i.share)||0,1),share:i.share,ariaLabel:`${n(`leaderboard.community.modal.platform.${i.name}`)} ${u(i.share)}`,children:[e.jsxs("div",{className:"relative flex min-w-0 items-center gap-2.5",children:[e.jsx("span",{className:"grid size-6 shrink-0 place-items-center text-oai-gray-700 dark:text-oai-gray-200",children:e.jsx(ue,{name:i.name})}),e.jsx("span",{className:"truncate text-xs font-medium text-oai-gray-700 dark:text-oai-gray-200",children:n(`leaderboard.community.modal.platform.${i.name}`)})]}),e.jsxs("div",{className:"relative min-w-[4.5rem] text-right",children:[e.jsx("div",{className:"text-xs font-semibold text-oai-black tabular-nums dark:text-white",children:u(i.share)}),e.jsx("div",{className:"text-xs text-oai-gray-500 tabular-nums dark:text-oai-gray-400",title:Number(i.machines||0).toLocaleString(),children:n("leaderboard.community.modal.machine_count",{count:p(i.machines)})})]})]},i.name))})]}):null]})}function ve({isOpen:t,onClose:s,communityStats:a}){const{formatTokens:i,formatTokensTooltip:r}=B(),[o,l]=D.useState("overview"),c=a?.status==="ready",m=D.useMemo(()=>{if(!c)return null;const d=(Array.isArray(a.providers)?a.providers:[]).slice(0,O),x=(Array.isArray(a.topModels)?a.topModels:[]).slice(0,O),y=v=>v.reduce((E,$)=>Math.max(E,Number($.share)||0),0)||1;return{providers:d,models:x,providersMaxShare:y(d),modelsMaxShare:y(x),trendRows:(Array.isArray(a.dailyGrowth)?a.dailyGrowth:[]).map(v=>({day:ne(v.day),value:Number(v.tokens)||0})),mix:Array.isArray(a.tokenMix)?a.tokenMix:[],bands:Array.isArray(a.userDistribution)?a.userDistribution:[],platforms:Array.isArray(a.platforms)?a.platforms:[]}},[c,a]);if(!m)return null;const h=Number(a.tokenFloor)||0,N=Number(a.activeDevelopersTotal)||Number(a.totalEntries)||0,w=Number(a.tokens30d)||0,T=d=>{if(d.key!=="ArrowRight"&&d.key!=="ArrowLeft")return;d.preventDefault();const x=d.key==="ArrowRight"?1:-1,y=g[(g.indexOf(o)+x+g.length)%g.length];l(y),d.currentTarget.querySelector(`[data-tab-id="${y}"]`)?.focus()};return e.jsx(X,{open:t,onOpenChange:d=>!d&&s(),children:e.jsxs(Y,{children:[e.jsx(Z,{className:"fixed inset-0 z-[100] bg-black/50 backdrop-blur-[3px] transition-opacity duration-200 ease-out data-[ending-style]:opacity-0 data-[starting-style]:opacity-0"}),e.jsx(H,{className:"fixed inset-0 z-[101] flex items-center justify-center p-2 sm:p-5",children:e.jsxs(q,{className:"relative flex h-[min(42rem,92vh)] w-full max-w-xl flex-col overflow-hidden rounded-2xl bg-white shadow-2xl ring-1 ring-black/10 transition-[opacity,transform] duration-[220ms] ease-[cubic-bezier(0.16,1,0.3,1)] data-[ending-style]:translate-y-3 data-[ending-style]:scale-[0.98] data-[ending-style]:opacity-0 data-[starting-style]:translate-y-3 data-[starting-style]:scale-[0.98] data-[starting-style]:opacity-0 dark:bg-oai-gray-950 dark:ring-white/10",children:[e.jsxs("header",{"data-testid":"community-metrics-header",className:"shrink-0 px-5 pt-5 sm:px-6",children:[e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx(J,{className:"text-lg font-semibold tracking-[-0.02em] text-oai-black dark:text-white",children:n("leaderboard.community.modal.title")}),e.jsx(Q,{className:"sr-only",children:n("leaderboard.community.modal.description")})]}),e.jsx(ee,{className:"-mr-1 -mt-1 grid size-8 place-items-center rounded-full text-oai-gray-400 transition-colors hover:bg-black/5 hover:text-oai-black dark:hover:bg-white/10 dark:hover:text-white","aria-label":n("shared.dialog.close"),children:e.jsx(z,{className:"size-4"})})]}),e.jsxs("div",{className:"mt-4 grid grid-cols-3 gap-x-5",children:[e.jsx(j,{label:n("leaderboard.community.modal.total_tokens"),value:i(h),title:r(h)}),e.jsx(j,{label:n("leaderboard.community.modal.tokens_30d"),value:i(w),title:r(w),delta:a.tokenGrowthPct,deltaLabel:n("leaderboard.community.modal.vs_previous_week")}),e.jsx(j,{label:n("leaderboard.community.modal.contributors"),value:p(N),title:N.toLocaleString()})]}),e.jsx("div",{className:"mt-4 flex items-end overflow-x-auto border-b border-oai-gray-100 dark:border-oai-gray-900",role:"tablist","aria-label":n("leaderboard.community.modal.views"),onKeyDown:T,children:g.map(d=>{const x=o===d;return e.jsxs("button",{type:"button",role:"tab","data-tab-id":d,"aria-selected":x,tabIndex:x?0:-1,onClick:()=>l(d),className:`relative mr-5 h-10 shrink-0 text-sm font-medium transition-colors last:mr-0 ${x?"text-oai-black dark:text-white":"text-oai-gray-500 hover:text-oai-gray-700 dark:text-oai-gray-400 dark:hover:text-oai-gray-200"}`,children:[n(`leaderboard.community.modal.tab.${d}`),x?e.jsx(M.span,{layoutId:"community-metrics-tab-underline",className:"absolute inset-x-0 -bottom-px h-0.5 rounded-full bg-oai-black dark:bg-white",transition:{type:"spring",stiffness:420,damping:34}}):null]},d)})})]}),e.jsx("div",{"data-testid":"community-metrics-content",className:"min-h-0 flex-1 overflow-y-auto px-5 py-5 sm:px-6",children:e.jsxs(M.div,{initial:{opacity:0,y:4},animate:{opacity:1,y:0},transition:{duration:.18,ease:[.16,1,.3,1]},className:"h-full",children:[o==="overview"?e.jsx(me,{trendRows:m.trendRows,mix:m.mix,activeDevelopers30d:Number(a.activeDevelopers30d)||0,developerGrowthPct:a.developerGrowthPct,formatTokens:i,formatTokensTooltip:r}):null,o==="providers"?e.jsx(ce,{rows:m.providers,maxShare:m.providersMaxShare,formatTokens:i,formatTokensTooltip:r}):null,o==="community"?e.jsx(pe,{bands:m.bands,platforms:m.platforms,formatTokensTooltip:r}):null,o==="models"?e.jsx(xe,{rows:m.models,maxShare:m.modelsMaxShare,formatTokens:i,formatTokensTooltip:r}):null]},o)})]})})]})})}function Ke(t){return e.jsx(R,{mode:P.COMPACT,children:e.jsx(ve,{...t})})}export{Ke as CommunityStatsModal};
@@ -1 +0,0 @@
1
- import{j as a,B as i,e as x}from"./__vite-browser-external-HdCplPKs.js";import{D as p,a as m,b as y,c as b,d as f,e as u}from"./DialogTitle-6epeLIn0.js";import{D as h}from"./DialogDescription-C5Ujj254.js";function _({open:r,title:l,description:t,confirmLabel:o,cancelLabel:n,destructive:d=!1,busy:e=!1,onConfirm:c,onCancel:s}){return a.jsx(p,{open:r,onOpenChange:g=>{!g&&!e&&s?.()},children:a.jsxs(m,{children:[a.jsx(y,{className:"fixed inset-0 z-[100] bg-black/40 backdrop-blur-[2px] transition-opacity duration-200 ease-out data-[ending-style]:opacity-0 data-[starting-style]:opacity-0"}),a.jsx(b,{className:"fixed inset-0 z-[101] flex items-center justify-center p-4",children:a.jsxs(f,{className:"relative w-full max-w-md rounded-2xl bg-white p-6 shadow-[0_20px_60px_-20px_rgba(0,0,0,0.25)] ring-1 ring-oai-gray-200 transition-[opacity,transform] duration-[220ms] ease-[cubic-bezier(0.16,1,0.3,1)] data-[ending-style]:translate-y-2 data-[ending-style]:scale-[0.96] data-[ending-style]:opacity-0 data-[starting-style]:translate-y-2 data-[starting-style]:scale-[0.96] data-[starting-style]:opacity-0 dark:bg-oai-gray-950 dark:shadow-[0_20px_60px_-10px_rgba(0,0,0,0.65)] dark:ring-oai-gray-800",children:[a.jsx(u,{className:"text-base font-semibold text-oai-black dark:text-white",children:l}),t?a.jsx(h,{className:"mt-2 text-sm leading-6 text-oai-gray-600 dark:text-oai-gray-300",children:t}):null,a.jsxs("div",{className:"mt-5 flex justify-end gap-2",children:[a.jsx(i,{type:"button",variant:"secondary",size:"sm",disabled:e,onClick:()=>s?.(),children:n}),a.jsx(i,{type:"button",size:"sm",disabled:e,onClick:()=>c?.(),className:x(d&&"!bg-red-600 hover:!bg-red-700 focus-visible:!outline-red-600 dark:!bg-red-600 dark:hover:!bg-red-500"),children:o})]})]})})]})})}export{_ as C};