tokentracker-cli 0.79.4 → 0.79.5

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 (72) hide show
  1. package/README.de.md +8 -6
  2. package/README.ja.md +7 -5
  3. package/README.ko.md +7 -5
  4. package/README.md +42 -9
  5. package/README.zh-CN.md +7 -5
  6. package/dashboard/dist/assets/{AchievementBadge-wQQwzQYv.js → AchievementBadge-X9JssV2N.js} +1 -1
  7. package/dashboard/dist/assets/{AchievementsPage-rBd_ycOo.js → AchievementsPage-CssvfAV-.js} +2 -2
  8. package/dashboard/dist/assets/{AchievementsSection-Cwgr4N8D.js → AchievementsSection-dPW0TScn.js} +1 -1
  9. package/dashboard/dist/assets/{BadgeDetailModal-bKdQ_Pls.js → BadgeDetailModal-DP3yGm6-.js} +1 -1
  10. package/dashboard/dist/assets/{Card-DKUa4bFg.js → Card-B7GE82Qk.js} +1 -1
  11. package/dashboard/dist/assets/{ClawdAnimated-DaG3163q.js → ClawdAnimated-CJG_njBC.js} +1 -1
  12. package/dashboard/dist/assets/{CommunityStatsModal-BrlwrUmW.js → CommunityStatsModal-Cc0GiiyW.js} +1 -1
  13. package/dashboard/dist/assets/{ConfirmModal-CIujdHbF.js → ConfirmModal-92Ziiyxx.js} +1 -1
  14. package/dashboard/dist/assets/{Controls-Dzx021Tf.js → Controls-BpxVzX3h.js} +1 -1
  15. package/dashboard/dist/assets/{DashboardPage-DgTwlptV.js → DashboardPage-Bnjn8Ex2.js} +1 -1
  16. package/dashboard/dist/assets/{DevicePage-BycFzKD5.js → DevicePage-BKfl10sn.js} +1 -1
  17. package/dashboard/dist/assets/{DialogClose-ucUXpI-0.js → DialogClose-DCirvrZU.js} +1 -1
  18. package/dashboard/dist/assets/DialogDescription-jBrEf8aM.js +1 -0
  19. package/dashboard/dist/assets/{DialogTitle-B-NMBFgN.js → DialogTitle-D_V-kvKQ.js} +1 -1
  20. package/dashboard/dist/assets/{FadeIn-DR-LZSMh.js → FadeIn-BFTyxx03.js} +1 -1
  21. package/dashboard/dist/assets/{HeaderGithubStar-C6oriixE.js → HeaderGithubStar-CGD7Puhz.js} +1 -1
  22. package/dashboard/dist/assets/{IpCheckPage-I6ebSTLU.js → IpCheckPage-C16_KzJL.js} +1 -1
  23. package/dashboard/dist/assets/{LandingPage-BARuXijI.js → LandingPage-CpE4jxwA.js} +2 -2
  24. package/dashboard/dist/assets/{LeaderboardAvatar-BP9WMoUP.js → LeaderboardAvatar-C52RWl5g.js} +1 -1
  25. package/dashboard/dist/assets/{LeaderboardPage-BTL-rN1o.js → LeaderboardPage-CBXWyA93.js} +2 -2
  26. package/dashboard/dist/assets/{LeaderboardProfileModal-BeHrOZex.js → LeaderboardProfileModal-bUNw2YqM.js} +3 -3
  27. package/dashboard/dist/assets/{LeaderboardProfilePage-D2YPwVju.js → LeaderboardProfilePage-BEnE6sBT.js} +1 -1
  28. package/dashboard/dist/assets/{LimitsPage-D_31y9iz.js → LimitsPage-DYhjPmMR.js} +1 -1
  29. package/dashboard/dist/assets/{LocalOnlyNotice-Bsme9V7_.js → LocalOnlyNotice-CvoYW8Nb.js} +1 -1
  30. package/dashboard/dist/assets/{LoginPage-ChdsOwnZ.js → LoginPage-9DRGFctn.js} +1 -1
  31. package/dashboard/dist/assets/{PetPage-DHZP64Lh.js → PetPage-56ckCKFL.js} +1 -1
  32. package/dashboard/dist/assets/{PopoverPopup-1Apd7Z6A.js → PopoverPopup-4QvodQsq.js} +1 -1
  33. package/dashboard/dist/assets/{ResetPasswordPage-GchnBNwn.js → ResetPasswordPage-BQKylJ-c.js} +1 -1
  34. package/dashboard/dist/assets/{Select-BBR4yWcP.js → Select-o7SEvK5-.js} +1 -1
  35. package/dashboard/dist/assets/{SelectItemText-GIvwOKIn.js → SelectItemText-BtLejIsu.js} +1 -1
  36. package/dashboard/dist/assets/{SettingsPage-CbDU59OB.js → SettingsPage-CppbkBJD.js} +1 -1
  37. package/dashboard/dist/assets/{SkillsPage-C3caxrhI.js → SkillsPage-Bn6zE95k.js} +1 -1
  38. package/dashboard/dist/assets/{WidgetsPage-wYGZUIP8.js → WidgetsPage-D0iUSnth.js} +1 -1
  39. package/dashboard/dist/assets/{WrappedPage-D9WkTJww.js → WrappedPage-DCVMc482.js} +1 -1
  40. package/dashboard/dist/assets/agent-logos-Cx5AdtpO.js +1 -0
  41. package/dashboard/dist/assets/{arrow-up-right-BGl1XMiR.js → arrow-up-right-QzEKV7iZ.js} +1 -1
  42. package/dashboard/dist/assets/check-CW8teWnj.js +1 -0
  43. package/dashboard/dist/assets/{copy-DoCkcIHR.js → copy-hCsV5-0m.js} +1 -1
  44. package/dashboard/dist/assets/{download-C8qHTN6n.js → download-CbV9ZyMG.js} +1 -1
  45. package/dashboard/dist/assets/{flame-B27yR7Au.js → flame-Wz7IYxjy.js} +1 -1
  46. package/dashboard/dist/assets/{format-tokens-B8_mvUxn.js → format-tokens-Cy-5MGHS.js} +1 -1
  47. package/dashboard/dist/assets/{info-BpTZWFEB.js → info-Cl7_VZlw.js} +1 -1
  48. package/dashboard/dist/assets/{link-2-DDjliaUB.js → link-2-ClEAZJ8b.js} +1 -1
  49. package/dashboard/dist/assets/{loader-circle-DkNHiiwy.js → loader-circle-D6ODh6t1.js} +1 -1
  50. package/dashboard/dist/assets/{main-CvkyGV2H.js → main-BbxPEfc4.js} +19 -18
  51. package/dashboard/dist/assets/main-ilWqzAfD.css +1 -0
  52. package/dashboard/dist/assets/{provider-display-CPhtfhmX.js → provider-display-DUyaW5An.js} +1 -1
  53. package/dashboard/dist/assets/{trash-2-CVIlLnop.js → trash-2-DlZYYQMT.js} +1 -1
  54. package/dashboard/dist/assets/{use-community-stats-C8PN46hK.js → use-community-stats-Bbb9v23-.js} +1 -1
  55. package/dashboard/dist/assets/{use-limits-display-prefs-D7vWwHbD.js → use-limits-display-prefs-D72_Vnm_.js} +1 -1
  56. package/dashboard/dist/assets/{use-native-settings-Bh4ls-JF.js → use-native-settings-CWqf5Ev7.js} +1 -1
  57. package/dashboard/dist/assets/{use-ordered-list-BHptHQDT.js → use-ordered-list-CiWmbaiL.js} +1 -1
  58. package/dashboard/dist/assets/{use-quality-per-dollar-pref-C3EXtrc1.js → use-quality-per-dollar-pref-BxjiK7wi.js} +1 -1
  59. package/dashboard/dist/assets/{use-transform-BW36bKb3.js → use-transform-YviydTql.js} +1 -1
  60. package/dashboard/dist/assets/{use-usage-limits-BY-RA1uz.js → use-usage-limits-BWYM8Bj-.js} +1 -1
  61. package/dashboard/dist/assets/{useCurrency-nB0kdYwU.js → useCurrency-DEAShUT7.js} +1 -1
  62. package/dashboard/dist/assets/{useScrollLock-juP-sEAK.js → useScrollLock-h9pnSauU.js} +1 -1
  63. package/dashboard/dist/assets/{zap-Blccuc-z.js → zap-CnEr_e6T.js} +1 -1
  64. package/dashboard/dist/index.html +61 -31
  65. package/dashboard/dist/llms.txt +56 -31
  66. package/dashboard/dist/share.html +2 -2
  67. package/package.json +9 -3
  68. package/src/lib/pricing/seed-snapshot.json +1 -1
  69. package/dashboard/dist/assets/DialogDescription-CIldLoYo.js +0 -1
  70. package/dashboard/dist/assets/agent-logos-z6m7ILhw.js +0 -1
  71. package/dashboard/dist/assets/check-Bj3UnGFX.js +0 -1
  72. package/dashboard/dist/assets/main-C6V_dFqw.css +0 -1
package/README.de.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  ### Sieh genau, was du für KI ausgibst – über jedes CLI hinweg
8
8
 
9
- Sammle automatisch Token-Zahlen von **25 KI-Coding-Tools**, aggregiere sie lokal und sieh echte Kostentrends in einem schönen Dashboard. Kein Cloud-Konto, keine API-Keys, kein Setup – nur ein Befehl.
9
+ Sammle automatisch Token-Zahlen von **27 KI-Coding-Tools**, aggregiere sie lokal und sieh echte Kostentrends in einem schönen Dashboard. Kein Cloud-Konto, keine API-Keys, kein Setup – nur ein Befehl.
10
10
 
11
11
  [![npm version](https://img.shields.io/npm/v/tokentracker-cli.svg?color=blue)](https://www.npmjs.com/package/tokentracker-cli)
12
12
  [![npm downloads](https://img.shields.io/npm/dm/tokentracker-cli.svg?color=brightgreen)](https://www.npmjs.com/package/tokentracker-cli)
@@ -87,7 +87,7 @@ Aktualisieren mit `brew upgrade --cask mm7894215/tokentracker/tokentracker`. Der
87
87
 
88
88
  ## ✨ Features
89
89
 
90
- - 🔌 **25 KI-Tools out of the box** — Claude Code, Codex CLI, Cursor, Gemini CLI, Antigravity, Kiro, OpenCode, OpenClaw, Every Code, Hermes Agent, GitHub Copilot, Kimi Code, CodeBuddy, WorkBuddy, Grok Build, oh-my-pi, pi, Craft Agents, Kilo CLI, Kilo Code, Roo Code, Zed Agent, Goose, Mimo Code, ZCode
90
+ - 🔌 **27 KI-Tools out of the box** — Claude Code, Codex CLI, Cursor, Gemini CLI, Antigravity, Kiro, OpenCode, OpenClaw, Every Code, Hermes Agent, GitHub Copilot, Kimi Code, CodeBuddy, WorkBuddy, Grok Build, oh-my-pi, pi, Craft Agents, Kilo CLI, Kilo Code, Roo Code, Zed Agent, Goose, Droid, Mimo Code, ZCode, AnythingLLM Desktop
91
91
  - 🏠 **100 % lokal** — Token-Daten verlassen nie deinen Rechner. Kein Konto, keine API-Keys.
92
92
  - 🚀 **Zero Config** — Hooks installieren sich beim ersten Start automatisch. Von null zum Dashboard in 30 Sekunden.
93
93
  - 📊 **Schönes Dashboard** — Nutzungstrends, Kostenaufschlüsselung nach Modell, GitHub-ähnliche Aktivitäts-Heatmap, Projektzuordnung
@@ -186,13 +186,15 @@ Aktualisieren mit `brew upgrade --cask mm7894215/tokentracker/tokentracker`. Der
186
186
  | **Roo Code** (VS Code Extension) | ✅ Auto | Passiver `ui_messages.json`-Reader (`rooveterinaryinc.roo-cline`) |
187
187
  | **Zed Agent** | ✅ Auto | Passiver SQLite-Reader (`threads.db`, nur `zed.dev`-Modelle) |
188
188
  | **Goose** (Block) | ✅ Auto | Passiver SQLite-Reader (`sessions.db`, kumulative Deltas) |
189
+ | **Droid** (Factory) | ✅ Auto | Passiver Session-Reader (`~/.factory/sessions/**/settings.json`, kumulative Deltas) |
189
190
  | **Mimo Code** (mimocode) | ✅ Auto | Passiver SQLite-Reader (`~/.local/share/mimocode/mimocode.db`, OpenCode-Fork-Schema; zählt nur mimo-native Turns – gespiegelte Claude/claude-mem-Verläufe werden ausgeschlossen) |
190
191
  | **ZCode** (Z.ai) | ✅ Auto | Passiver SQLite-Reader (`~/.zcode/cli/db/db.sqlite`, OpenCode-Fork-Schema; zählt nur Z.ai/BigModel-GLM-Turns – gebündelte Claude/Codex/Gemini-Sub-Agenten werden ausgeschlossen) |
192
+ | **AnythingLLM Desktop** | ✅ Auto | Passiver SQLite-Reader (`anythingllm-desktop/storage/anythingllm.db`, nur Token-Metriken pro Nachricht) |
191
193
 
192
194
  > **Muss ich Plugins oder Hooks manuell installieren?** Nein. `tokentracker` (oder `tokentracker init`) erledigt alles beim ersten Start:
193
195
  > - **Hook-basiert** (Claude Code, Codex, Gemini, Every Code, CodeBuddy, WorkBuddy, Grok Build) — wir schreiben einen SessionEnd-Hook oder TOML-Notify-Eintrag in die Konfiguration des Tools.
194
196
  > - **Plugin-basiert** (OpenCode, OpenClaw) — das Plugin ist im npm-Paket enthalten (`~/.tokentracker/app/openclaw-plugin/`). Wir verlinken es per CLI (`openclaw plugins install --link …` + `enable`). Kein Download, kein Drag-and-Drop.
195
- > - **Passive Reader** (Cursor, Kiro, Hermes, Kimi Code, Copilot, Grok Build, oh-my-pi, pi, Craft Agents, Kilo CLI, Kilo Code, Roo Code, Antigravity, Zed Agent, Goose, Mimo Code, ZCode) — wir installieren nichts in diesen Tools. Wir lesen nur Dateien, die sie bereits produzieren (SQLite-DB, JSONL, OTEL-Export, Session-Logs). Die Nutzung von Copilot App / CLI wird pro Anfrage aus `~/.copilot/session-store.db` gelesen; `data.db` liefert einmalig die Legacy-Migrationsbasis und bleibt nach der kanonischen Übernahme des Stores schreibgeschützt im Beobachtungsmodus, während Chat-Erweiterung und ältere CLI-Versionen weiterhin OTEL verwenden. TokenTracker koordiniert diese Quellen, damit überlappende Anfragen nur einmal gezählt werden. Gemischte App/CLI-Historie vor der Übernahme bleibt als `github-copilot-legacy`-Aggregat erhalten, statt einem geratenen Anfrage-Modell zugeordnet zu werden.
197
+ > - **Passive Reader** (Cursor, Kiro, Hermes, Kimi Code, Copilot, Grok Build, oh-my-pi, pi, Craft Agents, Kilo CLI, Kilo Code, Roo Code, Antigravity, Zed Agent, Goose, Droid, Mimo Code, ZCode, AnythingLLM Desktop) — wir installieren nichts in diesen Tools. Wir lesen nur Dateien, die sie bereits produzieren (SQLite-DB, JSONL, OTEL-Export, Session-Logs). Die Nutzung von Copilot App / CLI wird pro Anfrage aus `~/.copilot/session-store.db` gelesen; `data.db` liefert einmalig die Legacy-Migrationsbasis und bleibt nach der kanonischen Übernahme des Stores schreibgeschützt im Beobachtungsmodus, während Chat-Erweiterung und ältere CLI-Versionen weiterhin OTEL verwenden. TokenTracker koordiniert diese Quellen, damit überlappende Anfragen nur einmal gezählt werden. Gemischte App/CLI-Historie vor der Übernahme bleibt als `github-copilot-legacy`-Aggregat erhalten, statt einem geratenen Anfrage-Modell zugeordnet zu werden.
196
198
  >
197
199
  > Führe `tokentracker status` aus, um den Status jeder Integration zu prüfen. Zeigt ein Tool `skipped`, erklärt die `detail`-Spalte warum.
198
200
  >
@@ -204,11 +206,11 @@ Fehlt dein Tool? [Erstelle ein Issue](https://github.com/mm7894215/TokenTracker/
204
206
 
205
207
  ## 🆚 Warum TokenTracker?
206
208
 
207
- > **Suchst du eine ccusage-Alternative mit GUI?** TokenTracker unterstützt 25 Tools (nicht nur Claude Code), bietet eine native macOS-Menüleisten-App + Desktop-Widgets und dedupliziert Token-Datensätze korrekt über alle Provider hinweg – damit deine Zahlen mit dem Billing der Provider übereinstimmen.
209
+ > **Suchst du eine ccusage-Alternative mit GUI?** TokenTracker unterstützt 27 Tools (nicht nur Claude Code), bietet native macOS- und Windows-Apps + Desktop-Widgets und dedupliziert Token-Datensätze korrekt über alle Provider hinweg – damit deine Zahlen mit dem Billing der Provider übereinstimmen.
208
210
 
209
211
  | | **TokenTracker** | ccusage | Cursor Stats |
210
212
  |---|---|---|---|
211
- | **Unterstützte KI-Tools** | **25** | 1 (Claude) | 1 (Cursor) |
213
+ | **Unterstützte KI-Tools** | **27** | 1 (Claude) | 1 (Cursor) |
212
214
  | **Lokal, kein Konto** | ✅ | ✅ | ❌ |
213
215
  | **Native Desktop-App** | ✅ macOS + Windows | ❌ | ❌ |
214
216
  | **Desktop-Widgets** | ✅ 4 Widgets | ❌ | ❌ |
@@ -223,7 +225,7 @@ Fehlt dein Tool? [Erstelle ein Issue](https://github.com/mm7894215/TokenTracker/
223
225
 
224
226
  ```mermaid
225
227
  flowchart LR
226
- A["KI-CLI-Tools<br/>Claude · Codex · Cursor · Gemini · Kiro<br/>OpenCode · OpenClaw · Every Code · Hermes · Copilot<br/>Kimi Code · CodeBuddy · WorkBuddy · Grok Build · Kilo CLI · Kilo Code<br/>Antigravity · oh-my-pi · pi · Craft · Roo Code · Zed · Goose · Mimo · ZCode"]
228
+ A["KI-Coding-Tools<br/>Claude · Codex · Cursor · Gemini · Kiro<br/>OpenCode · OpenClaw · Every Code · Hermes · Copilot<br/>Kimi · CodeBuddy · WorkBuddy · Grok · Kilo · Roo · Zed · Goose<br/>Antigravity · oh-my-pi · pi · Craft · Droid · Mimo · ZCode · AnythingLLM"]
227
229
  A -->|Hooks lösen aus| B[Token Tracker]
228
230
  B -->|Logs parsen<br/>30-Min-UTC-Buckets| C[(Lokales SQLite)]
229
231
  C --> D[Web-Dashboard]
package/README.ja.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  ### AI に使ったコストを正確に把握 — すべての CLI を横断して
8
8
 
9
- **25 種類の AI コーディングツール**からトークン数を自動収集し、ローカルで集計、美しいダッシュボードで本当のコスト推移を可視化します。クラウドアカウント不要、API キー不要、セットアップ不要 — コマンド 1 つで完了です。
9
+ **27 種類の AI コーディングツール**からトークン数を自動収集し、ローカルで集計、美しいダッシュボードで本当のコスト推移を可視化します。クラウドアカウント不要、API キー不要、セットアップ不要 — コマンド 1 つで完了です。
10
10
 
11
11
  [![npm version](https://img.shields.io/npm/v/tokentracker-cli.svg?color=blue)](https://www.npmjs.com/package/tokentracker-cli)
12
12
  [![npm downloads](https://img.shields.io/npm/dm/tokentracker-cli.svg?color=brightgreen)](https://www.npmjs.com/package/tokentracker-cli)
@@ -87,7 +87,7 @@ brew install mm7894215/tokentracker/tokentracker
87
87
 
88
88
  ## ✨ 機能
89
89
 
90
- - 🔌 **25 種類の AI ツールを標準対応** — Claude Code、Codex CLI、Cursor、Gemini CLI、Antigravity、Kiro、OpenCode、OpenClaw、Every Code、Hermes Agent、GitHub Copilot、Kimi Code、CodeBuddy、WorkBuddy、Grok Build、oh-my-pi、pi、Craft Agents、Kilo CLI、Kilo Code、Roo Code、Zed Agent、Goose、Mimo Code、ZCode
90
+ - 🔌 **27 種類の AI ツールを標準対応** — Claude Code、Codex CLI、Cursor、Gemini CLI、Antigravity、Kiro、OpenCode、OpenClaw、Every Code、Hermes Agent、GitHub Copilot、Kimi Code、CodeBuddy、WorkBuddy、Grok Build、oh-my-pi、pi、Craft Agents、Kilo CLI、Kilo Code、Roo Code、Zed Agent、Goose、Droid、Mimo Code、ZCode、AnythingLLM Desktop
91
91
  - 🏠 **100% ローカル** — トークンデータがマシンから外に出ることはありません。アカウント不要、API キー不要。
92
92
  - 🚀 **ゼロコンフィグ** — Hook は初回実行で自動インストール。0 からダッシュボードまで 30 秒。
93
93
  - 📊 **美しいダッシュボード** — 使用トレンド、モデル別コスト内訳、GitHub スタイルのアクティビティヒートマップ、プロジェクト別の帰属表示
@@ -187,13 +187,15 @@ brew install mm7894215/tokentracker/tokentracker
187
187
  | **Roo Code** (VS Code 拡張) | ✅ 自動 | パッシブな `ui_messages.json` リーダー (`rooveterinaryinc.roo-cline`) |
188
188
  | **Zed Agent** | ✅ 自動 | パッシブな SQLite リーダー (`threads.db`、hosted `zed.dev` models only) |
189
189
  | **Goose** (Block) | ✅ 自動 | パッシブな SQLite リーダー (`sessions.db`、cumulative deltas) |
190
+ | **Droid** (Factory) | ✅ 自動 | パッシブなセッションリーダー (`~/.factory/sessions/**/settings.json`、cumulative deltas) |
190
191
  | **Mimo Code** (mimocode) | ✅ 自動 | パッシブな SQLite リーダー (`~/.local/share/mimocode/mimocode.db`、OpenCode-fork schema; mimo ネイティブのターンのみ集計 — ミラーされた Claude/claude-mem 履歴は除外) |
191
192
  | **ZCode** (Z.ai) | ✅ 自動 | パッシブな SQLite リーダー (`~/.zcode/cli/db/db.sqlite`、OpenCode-fork schema; Z.ai/BigModel の GLM ターンのみ集計 — 同梱の Claude/Codex/Gemini サブエージェントは除外) |
193
+ | **AnythingLLM Desktop** | ✅ 自動 | パッシブな SQLite リーダー (`anythingllm-desktop/storage/anythingllm.db`、メッセージごとの token 指標のみ) |
192
194
 
193
195
  > **プラグインや hook を手動でインストールする必要はありますか?** いいえ。`tokentracker`(または `tokentracker init`)が初回実行ですべて処理します:
194
196
  > - **Hook ベース**のツール (Claude Code、Codex、Gemini、Every Code、**CodeBuddy**、**WorkBuddy**、**Grok Build**) — ツール自身の設定に SessionEnd hook または TOML notify エントリーを書き込みます。
195
197
  > - **プラグインベース**のツール (OpenCode、**OpenClaw**) — プラグインは npm パッケージ内に同梱されています。OpenClaw のセッションプラグインは `~/.tokentracker/tracker/openclaw-plugin/openclaw-session-sync/` にあり、OpenClaw 自身の CLI でリンクして有効化したうえで、同期を起動するセッション終了イベントを許可するために `hooks.allowConversationAccess=true` を設定します。ダウンロードもドラッグ&ドロップも不要です。
196
- > - **パッシブリーダー** (Cursor、Kiro、Hermes、Kimi Code、Copilot、**Grok Build**、**oh-my-pi**、**pi**、**Craft Agents**、**Kilo CLI**、**Kilo Code**、**Roo Code**、**Antigravity**、**Zed Agent**、**Goose**、**Mimo Code**、**ZCode**) — これらのツールには何もインストールしません。ツールがすでに出力しているファイル (SQLite DB、JSONL、OTEL エクスポート、session logs) を読むだけです。Copilot App / CLI の使用量は `~/.copilot/session-store.db` からリクエスト単位で読み取ります。`data.db` は旧データ移行時のベースラインとして一度だけ使い、store が正規ソースになった後は監視専用です。Chat 拡張と旧 CLI は引き続き OTEL を使用し、重複するリクエストは TokenTracker が一度だけ集計します。移行前の混在 App/CLI 履歴でモデルを安全に分離できない残量は、推測したリクエストモデルではなく `github-copilot-legacy` の集計値として保持します。
198
+ > - **パッシブリーダー** (Cursor、Kiro、Hermes、Kimi Code、Copilot、**Grok Build**、**oh-my-pi**、**pi**、**Craft Agents**、**Kilo CLI**、**Kilo Code**、**Roo Code**、**Antigravity**、**Zed Agent**、**Goose**、**Droid**、**Mimo Code**、**ZCode**、**AnythingLLM Desktop**) — これらのツールには何もインストールしません。ツールがすでに出力しているファイル (SQLite DB、JSONL、OTEL エクスポート、session logs) を読むだけです。Copilot App / CLI の使用量は `~/.copilot/session-store.db` からリクエスト単位で読み取ります。`data.db` は旧データ移行時のベースラインとして一度だけ使い、store が正規ソースになった後は監視専用です。Chat 拡張と旧 CLI は引き続き OTEL を使用し、重複するリクエストは TokenTracker が一度だけ集計します。移行前の混在 App/CLI 履歴でモデルを安全に分離できない残量は、推測したリクエストモデルではなく `github-copilot-legacy` の集計値として保持します。
197
199
  > - **Grok Build の推定** — 現在のローカルテレメトリは `updates.jsonl` の累積 `totalTokens` を公開していますが、安定したプロンプト/出力/キャッシュの内訳はありません。`signals.json` は `contextTokensUsed` のスナップショットを使ったフォールバックとして残っています。コールごとの利用詳細が利用可能になるまで、TokenTracker は Grok のコストを推定します。
198
200
  >
199
201
  > いつでも `tokentracker status` を実行すれば、各統合の状態を確認できます。`skipped` と表示されている場合、`detail` 列にその理由が示されます(例: ツール CLI が `PATH` にない、設定が読めない)。
@@ -208,7 +210,7 @@ brew install mm7894215/tokentracker/tokentracker
208
210
 
209
211
  | | **TokenTracker** | ccusage | Cursor stats |
210
212
  |--------------------------|:---:|:---:|:---:|
211
- | **対応 AI ツール数** | **25** | 1 (Claude) | 1 (Cursor) |
213
+ | **対応 AI ツール数** | **27** | 1 (Claude) | 1 (Cursor) |
212
214
  | **ローカルファースト、アカウント不要** | ✅ | ✅ | ❌ |
213
215
  | **ネイティブデスクトップアプリ** | ✅ macOS + Windows | ❌ | ❌ |
214
216
  | **デスクトップウィジェット** | ✅ 4 種類 | ❌ | ❌ |
@@ -220,7 +222,7 @@ brew install mm7894215/tokentracker/tokentracker
220
222
 
221
223
  ```mermaid
222
224
  flowchart LR
223
- A["AI CLI Tools<br/>Claude Code · Codex · Cursor · Gemini · Kiro<br/>OpenCode · OpenClaw · Every Code · Hermes · Copilot<br/>Kimi Code · CodeBuddy · WorkBuddy · Grok Build · Kilo CLI · Kilo Code · <br/>Antigravity · oh-my-pi · pi · Craft Agents · Roo Code · Zed · Goose · Mimo · ZCode"]
225
+ A["AI coding tools<br/>Claude Code · Codex · Cursor · Gemini · Kiro<br/>OpenCode · OpenClaw · Every Code · Hermes · Copilot<br/>Kimi · CodeBuddy · WorkBuddy · Grok · Kilo · Roo · Zed · Goose<br/>Antigravity · oh-my-pi · pi · Craft · Droid · Mimo · ZCode · AnythingLLM"]
224
226
  A -->|hooks trigger| B[Token Tracker]
225
227
  B -->|parse logs<br/>30-min UTC buckets| C[(Local SQLite)]
226
228
  C --> D[Web Dashboard]
package/README.ko.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  ### 모든 CLI에서 AI에 쓰는 비용을 정확히 파악
8
8
 
9
- **25개의 AI 코딩 도구**에서 토큰 수치를 자동으로 수집하고 로컬에서 집계해, 실제 비용 추세를 아름다운 대시보드에서 확인. 클라우드 계정 불필요, API Key 불필요, 셋업 불필요 — 명령 한 줄이면 끝.
9
+ **27개의 AI 코딩 도구**에서 토큰 수치를 자동으로 수집하고 로컬에서 집계해, 실제 비용 추세를 아름다운 대시보드에서 확인. 클라우드 계정 불필요, API Key 불필요, 셋업 불필요 — 명령 한 줄이면 끝.
10
10
 
11
11
  [![npm version](https://img.shields.io/npm/v/tokentracker-cli.svg?color=blue)](https://www.npmjs.com/package/tokentracker-cli)
12
12
  [![npm downloads](https://img.shields.io/npm/dm/tokentracker-cli.svg?color=brightgreen)](https://www.npmjs.com/package/tokentracker-cli)
@@ -87,7 +87,7 @@ brew install mm7894215/tokentracker/tokentracker
87
87
 
88
88
  ## ✨ 기능
89
89
 
90
- - 🔌 **25개의 AI 도구 기본 지원** — Claude Code, Codex CLI, Cursor, Gemini CLI, Antigravity, Kiro, OpenCode, OpenClaw, Every Code, Hermes Agent, GitHub Copilot, Kimi Code, CodeBuddy, WorkBuddy, Grok Build, oh-my-pi, pi, Craft Agents, Kilo CLI, Kilo Code, Roo Code, Zed Agent, Goose, Mimo Code, ZCode
90
+ - 🔌 **27개의 AI 도구 기본 지원** — Claude Code, Codex CLI, Cursor, Gemini CLI, Antigravity, Kiro, OpenCode, OpenClaw, Every Code, Hermes Agent, GitHub Copilot, Kimi Code, CodeBuddy, WorkBuddy, Grok Build, oh-my-pi, pi, Craft Agents, Kilo CLI, Kilo Code, Roo Code, Zed Agent, Goose, Droid, Mimo Code, ZCode, AnythingLLM Desktop
91
91
  - 🏠 **100% 로컬** — 토큰 데이터가 기기를 떠나지 않습니다. 계정 없음, API Key 없음.
92
92
  - 🚀 **제로 설정** — 첫 실행 시 Hook 자동 설치. 0에서 대시보드까지 30초.
93
93
  - 📊 **아름다운 대시보드** — 사용 추세, 모델별 비용 분석, GitHub 스타일 활동 히트맵, 프로젝트 귀속 정보
@@ -187,13 +187,15 @@ brew install mm7894215/tokentracker/tokentracker
187
187
  | **Roo Code** (VS Code 확장) | ✅ 자동 | 패시브 `ui_messages.json` 리더 (`rooveterinaryinc.roo-cline`) |
188
188
  | **Zed Agent** | ✅ 자동 | 패시브 SQLite 리더 (`threads.db`, hosted `zed.dev` models only) |
189
189
  | **Goose** (Block) | ✅ 자동 | 패시브 SQLite 리더 (`sessions.db`, cumulative deltas) |
190
+ | **Droid** (Factory) | ✅ 자동 | 패시브 세션 리더 (`~/.factory/sessions/**/settings.json`, cumulative deltas) |
190
191
  | **Mimo Code** (mimocode) | ✅ 자동 | 패시브 SQLite 리더 (`~/.local/share/mimocode/mimocode.db`, OpenCode-fork schema; mimo 네이티브 턴만 집계 — 미러링된 Claude/claude-mem 기록은 제외) |
191
192
  | **ZCode** (Z.ai) | ✅ 자동 | 패시브 SQLite 리더 (`~/.zcode/cli/db/db.sqlite`, OpenCode-fork schema; Z.ai/BigModel GLM 턴만 집계 — 번들된 Claude/Codex/Gemini 서브에이전트는 제외) |
193
+ | **AnythingLLM Desktop** | ✅ 자동 | 패시브 SQLite 리더 (`anythingllm-desktop/storage/anythingllm.db`, 메시지별 token 지표만 읽음) |
192
194
 
193
195
  > **플러그인이나 hook을 수동으로 설치해야 하나요?** 아니요. `tokentracker` (또는 `tokentracker init`)가 첫 실행에서 모든 것을 처리합니다:
194
196
  > - **Hook 기반** 도구 (Claude Code, Codex, Gemini, Every Code, **CodeBuddy**, **WorkBuddy**, **Grok Build**) — 도구 자체의 설정에 SessionEnd hook 또는 TOML notify 엔트리를 작성합니다.
195
197
  > - **플러그인 기반** 도구 (OpenCode, **OpenClaw**) — 플러그인은 npm 패키지 안에 포함되어 있습니다. OpenClaw 세션 플러그인은 `~/.tokentracker/tracker/openclaw-plugin/openclaw-session-sync/`에 있으며, OpenClaw 자체 CLI로 링크하고 활성화한 뒤 동기화를 트리거하는 세션 종료 이벤트를 허용하도록 `hooks.allowConversationAccess=true`를 설정합니다. 다운로드, 드래그 앤 드롭 불필요.
196
- > - **패시브 리더** (Cursor, Kiro, Hermes, Kimi Code, Copilot, **Grok Build**, **oh-my-pi**, **pi**, **Craft Agents**, **Kilo CLI**, **Kilo Code**, **Roo Code**, **Antigravity**, **Zed Agent**, **Goose**, **Mimo Code**, **ZCode**) — 이들 도구에는 아무것도 설치하지 않습니다. 도구가 이미 생성하는 파일 (SQLite DB, JSONL, OTEL export, session logs)만 읽습니다. Copilot App / CLI 사용량은 `~/.copilot/session-store.db`에서 요청별로 읽습니다. `data.db`는 레거시 마이그레이션 기준선으로 한 번만 사용하며 store가 정식 소스가 된 뒤에는 관찰 전용으로 유지됩니다. Chat 확장과 이전 CLI는 계속 OTEL을 사용하며, TokenTracker가 겹치는 요청을 한 번만 집계합니다. 마이그레이션 전 혼합 App/CLI 기록에서 모델을 안전하게 분리할 수 없는 잔여분은 추정 모델 대신 `github-copilot-legacy` 집계로 보존합니다.
198
+ > - **패시브 리더** (Cursor, Kiro, Hermes, Kimi Code, Copilot, **Grok Build**, **oh-my-pi**, **pi**, **Craft Agents**, **Kilo CLI**, **Kilo Code**, **Roo Code**, **Antigravity**, **Zed Agent**, **Goose**, **Droid**, **Mimo Code**, **ZCode**, **AnythingLLM Desktop**) — 이들 도구에는 아무것도 설치하지 않습니다. 도구가 이미 생성하는 파일 (SQLite DB, JSONL, OTEL export, session logs)만 읽습니다. Copilot App / CLI 사용량은 `~/.copilot/session-store.db`에서 요청별로 읽습니다. `data.db`는 레거시 마이그레이션 기준선으로 한 번만 사용하며 store가 정식 소스가 된 뒤에는 관찰 전용으로 유지됩니다. Chat 확장과 이전 CLI는 계속 OTEL을 사용하며, TokenTracker가 겹치는 요청을 한 번만 집계합니다. 마이그레이션 전 혼합 App/CLI 기록에서 모델을 안전하게 분리할 수 없는 잔여분은 추정 모델 대신 `github-copilot-legacy` 집계로 보존합니다.
197
199
  > - **Grok Build 추정** — 현재 로컬 텔레메트리는 `updates.jsonl`의 누적 `totalTokens`를 노출하지만, 안정적인 프롬프트/출력/캐시 분할은 제공하지 않습니다; `signals.json`은 `contextTokensUsed` 스냅샷을 사용한 폴백으로 남아 있습니다. 호출별 사용 상세 정보가 제공될 때까지 TokenTracker는 Grok 비용을 추정합니다.
198
200
  >
199
201
  > 언제든 `tokentracker status`로 각 통합의 상태를 확인할 수 있습니다. `skipped`로 표시되면 `detail` 컬럼이 이유를 설명합니다 (예: 도구 CLI가 `PATH`에 없음, 설정 읽기 불가).
@@ -208,7 +210,7 @@ brew install mm7894215/tokentracker/tokentracker
208
210
 
209
211
  | | **TokenTracker** | ccusage | Cursor stats |
210
212
  |--------------------------|:---:|:---:|:---:|
211
- | **지원 AI 도구** | **25** | 1 (Claude) | 1 (Cursor) |
213
+ | **지원 AI 도구** | **27** | 1 (Claude) | 1 (Cursor) |
212
214
  | **로컬 우선, 계정 불필요** | ✅ | ✅ | ❌ |
213
215
  | **네이티브 데스크톱 앱** | ✅ macOS + Windows | ❌ | ❌ |
214
216
  | **데스크톱 위젯** | ✅ 4종 | ❌ | ❌ |
@@ -220,7 +222,7 @@ brew install mm7894215/tokentracker/tokentracker
220
222
 
221
223
  ```mermaid
222
224
  flowchart LR
223
- A["AI CLI Tools<br/>Claude Code · Codex · Cursor · Gemini · Kiro<br/>OpenCode · OpenClaw · Every Code · Hermes · Copilot<br/>Kimi Code · CodeBuddy · WorkBuddy · Grok Build · Kilo CLI · Kilo Code · <br/>Antigravity · oh-my-pi · pi · Craft Agents · Roo Code · Zed · Goose · Mimo · ZCode"]
225
+ A["AI coding tools<br/>Claude Code · Codex · Cursor · Gemini · Kiro<br/>OpenCode · OpenClaw · Every Code · Hermes · Copilot<br/>Kimi · CodeBuddy · WorkBuddy · Grok · Kilo · Roo · Zed · Goose<br/>Antigravity · oh-my-pi · pi · Craft · Droid · Mimo · ZCode · AnythingLLM"]
224
226
  A -->|hooks trigger| B[Token Tracker]
225
227
  B -->|parse logs<br/>30-min UTC buckets| C[(Local SQLite)]
226
228
  C --> D[Web Dashboard]
package/README.md CHANGED
@@ -4,9 +4,9 @@
4
4
 
5
5
  **English** · [简体中文](./README.zh-CN.md) · [日本語](./README.ja.md) · [한국어](./README.ko.md) · [Deutsch](./README.de.md)
6
6
 
7
- ### Know exactly what you're spending on AI — across every CLI
7
+ ### Your AI usage, brought to life on your desktop
8
8
 
9
- Auto-collect token counts from **25 AI coding tools**, aggregate them locally, and see real cost trends in a beautiful dashboard. No cloud account, no API keys, no setup — just one command.
9
+ A desktop pet that reacts to your real token activity, **4 native widgets**, and **15 achievement tracks** powered by accurate, local usage data from **27 AI coding tools**. No cloud account, no API keys, no setup.
10
10
 
11
11
  [![npm version](https://img.shields.io/npm/v/tokentracker-cli.svg?color=blue)](https://www.npmjs.com/package/tokentracker-cli)
12
12
  [![npm downloads](https://img.shields.io/npm/dm/tokentracker-cli.svg?color=brightgreen)](https://www.npmjs.com/package/tokentracker-cli)
@@ -21,12 +21,33 @@ Auto-collect token counts from **25 AI coding tools**, aggregate them locally, a
21
21
 
22
22
  <br/>
23
23
 
24
+ <table>
25
+ <tr>
26
+ <td width="58%"><img src="docs/screenshots/pet.png" alt="TokenTracker desktop pet powered by real AI coding activity" /></td>
27
+ <td width="42%"><img src="docs/screenshots/widgets-overview.png" alt="TokenTracker desktop widgets for usage, heatmap, models, and limits" /></td>
28
+ </tr>
29
+ <tr>
30
+ <td><strong>🐾 A living desktop companion</strong><br/>Codes, celebrates streaks, follows your cursor, and rests when you do.</td>
31
+ <td><strong>🧩 Four native widgets</strong><br/>Usage, activity heatmap, top models, and rate limits at a glance.</td>
32
+ </tr>
33
+ </table>
34
+
35
+ <p>
36
+ <img src="dashboard/public/achievements/token-titan.png" alt="Token Titan achievement" width="64" />
37
+ <img src="dashboard/public/achievements/streak.png" alt="Streak achievement" width="64" />
38
+ <img src="dashboard/public/achievements/multitool.png" alt="Multitool achievement" width="64" />
39
+ <img src="dashboard/public/achievements/night-owl.png" alt="Night Owl achievement" width="64" />
40
+ <img src="dashboard/public/achievements/project-devotion.png" alt="Project Devotion achievement" width="64" />
41
+ </p>
42
+
43
+ <strong>🏆 Unlock achievements from the way you actually code.</strong>
44
+
45
+ <br/><br/>
46
+
24
47
  <video src="https://github.com/user-attachments/assets/5e709422-5af8-4e4c-8109-f5bb711eb3f8" controls muted playsinline poster="https://raw.githubusercontent.com/mm7894215/tokentracker/main/docs/screenshots/dashboard-dark.png" width="820">
25
48
  <img src="https://raw.githubusercontent.com/mm7894215/tokentracker/main/docs/screenshots/dashboard-dark.png" alt="Token Tracker Dashboard" width="820" />
26
49
  </video>
27
50
 
28
- <video src="https://github.com/user-attachments/assets/3275979d-bbed-4639-83e2-8b7d83bed6af" controls muted playsinline poster="https://raw.githubusercontent.com/mm7894215/tokentracker/main/docs/screenshots/dashboard-light.png" width="820"></video>
29
-
30
51
  <br/><br/>
31
52
 
32
53
  ⭐ **If TokenTracker saves you time, please [star it on GitHub](https://github.com/mm7894215/TokenTracker) — it helps other developers find it.**
@@ -91,12 +112,14 @@ Upgrade with `brew upgrade --cask mm7894215/tokentracker/tokentracker`. The tap
91
112
 
92
113
  ## ✨ Features
93
114
 
94
- - 🔌 **25 AI tools out of the box** — Claude Code, Codex CLI, Cursor, Gemini CLI, Antigravity, Kiro, OpenCode, OpenClaw, Every Code, Hermes Agent, GitHub Copilot, Kimi Code, CodeBuddy, WorkBuddy, Grok Build, oh-my-pi, pi, Craft Agents, Kilo CLI, Kilo Code, Roo Code, Zed Agent, Goose, Mimo Code, ZCode
115
+ - 🔌 **27 AI tools out of the box** — Claude Code, Codex CLI, Cursor, Gemini CLI, Antigravity, Kiro, OpenCode, OpenClaw, Every Code, Hermes Agent, GitHub Copilot, Kimi Code, CodeBuddy, WorkBuddy, Grok Build, oh-my-pi, pi, Craft Agents, Kilo CLI, Kilo Code, Roo Code, Zed Agent, Goose, Droid, Mimo Code, ZCode, AnythingLLM Desktop
95
116
  - 🏠 **100% local** — Token data never leaves your machine. No account, no API keys.
96
117
  - 🚀 **Zero config** — Hooks auto-install on first run. From zero to dashboard in 30 seconds.
97
118
  - 📊 **Beautiful dashboard** — Usage trends, cost breakdowns by model, GitHub-style activity heatmap, project attribution
98
119
  - 🖥️ **Native desktop app** — macOS menu bar (+ widgets) and Windows system tray, each with an embedded server and the dashboard in a native webview
120
+ - 🐾 **Desktop pet** — A pixel companion powered by real coding activity: it works when you work, celebrates streaks, and sleeps when you rest
99
121
  - 🎨 **4 desktop widgets** — Pin Usage / Activity Heatmap / Top Models / Usage Limits to your desktop
122
+ - 🏆 **15 achievement tracks** — Turn daily usage, streaks, tools, models, and milestones into collectible badges worth sharing
100
123
  - 📈 **Real-time rate limit tracking** — Claude / Codex / Cursor / Gemini / Kiro / Copilot / Antigravity quota windows with reset countdowns
101
124
  - 💰 **Cost engine** — 2,200+ models priced via [LiteLLM](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json) (auto-refreshed daily) + curated overrides for niche tools (Kiro, Cursor Composer, Kimi, CodeBuddy hy3); 24h disk cache + bundled offline snapshot mean accurate USD without an internet connection. Models without published vendor pricing (e.g. Tencent hy3-preview) are tracked by tokens but show $0 cost until the vendor publishes a rate.
102
125
  - 🌐 **Optional leaderboard** — Compare with developers worldwide; drag-to-reorder columns to focus on the providers you care about (opt-in, sign in to participate)
@@ -157,6 +180,15 @@ Upgrade with `brew upgrade --cask mm7894215/tokentracker/tokentracker`. The tap
157
180
 
158
181
  <img src="https://raw.githubusercontent.com/mm7894215/tokentracker/main/docs/screenshots/pet.png" alt="Desktop Pet" />
159
182
 
183
+ </td>
184
+ </tr>
185
+ <tr>
186
+ <td colspan="2">
187
+
188
+ **Achievements** — 15 tracks turn usage milestones, streaks, tools, and models into collectible badges — with progress visible before each unlock.
189
+
190
+ <img src="https://raw.githubusercontent.com/mm7894215/tokentracker/main/docs/screenshots/achievements.png" alt="TokenTracker Achievements" />
191
+
160
192
  </td>
161
193
  </tr>
162
194
  </table>
@@ -191,6 +223,7 @@ Upgrade with `brew upgrade --cask mm7894215/tokentracker/tokentracker`. The tap
191
223
  | **Roo Code** (VS Code extension) | ✅ Auto | Passive `ui_messages.json` reader (`rooveterinaryinc.roo-cline`) |
192
224
  | **Zed Agent** | ✅ Auto | Passive SQLite reader (`threads.db`, all providers — hosted `zed.dev` + bring-your-own) |
193
225
  | **Goose** (Block) | ✅ Auto | Passive SQLite reader (`sessions.db`, cumulative deltas) |
226
+ | **Droid** (Factory) | ✅ Auto | Passive session reader (`~/.factory/sessions/**/settings.json`, cumulative deltas) |
194
227
  | **Mimo Code** (mimocode) | ✅ Auto | Passive SQLite reader (`~/.local/share/mimocode/mimocode.db`, OpenCode-fork schema; counts only mimo-native turns — mirrored Claude/claude-mem history is excluded) |
195
228
  | **ZCode** (Z.ai) | ✅ Auto | Passive SQLite reader (`~/.zcode/cli/db/db.sqlite`, OpenCode-fork schema; counts only Z.ai/BigModel GLM turns — bundled Claude/Codex/Gemini sub-agents are excluded) |
196
229
  | **AnythingLLM Desktop** | ✅ Auto | Passive SQLite reader (`anythingllm-desktop/storage/anythingllm.db`; reads per-message token metrics only, never prompts or responses) |
@@ -198,7 +231,7 @@ Upgrade with `brew upgrade --cask mm7894215/tokentracker/tokentracker`. The tap
198
231
  > **Do I need to install any plugin or hook manually?** No. `tokentracker` (or `tokentracker init`) handles everything on first run:
199
232
  > - **Hook-based** tools (Claude Code, Codex, Gemini, Every Code, **CodeBuddy**, **WorkBuddy**, **Grok Build**) — we write a SessionEnd hook or TOML notify entry into the tool's own config.
200
233
  > - **Plugin-based** tools (OpenCode, **OpenClaw**) — plugins ship inside the npm package. OpenClaw's session plugin lives at `~/.tokentracker/tracker/openclaw-plugin/openclaw-session-sync/`; we link and enable it via OpenClaw's own CLI, then set `hooks.allowConversationAccess=true` so OpenClaw permits the session-finished event that triggers sync. No download, no drag-and-drop.
201
- > - **Passive readers** (Cursor, Kiro, Hermes, Kimi Code, Copilot, **Grok Build**, **oh-my-pi**, **pi**, **Craft Agents**, **Kilo CLI**, **Kilo Code**, **Roo Code**, **Antigravity**, **Zed Agent**, **Goose**, **Mimo Code**, **ZCode**, **AnythingLLM Desktop**) — nothing is installed into those tools. We only read files they already produce (SQLite DB, JSONL, OTEL export, session logs). Copilot App / CLI usage is read per request from `~/.copilot/session-store.db`; `data.db` provides the one-time legacy adoption baseline and stays observe-only after the store becomes canonical, while the Chat extension and legacy CLI continue using OTEL. TokenTracker coordinates the sources so overlapping requests are counted once. Mixed App/CLI usage that predates adoption is retained as a `github-copilot-legacy` aggregate rather than assigned to a guessed request model.
234
+ > - **Passive readers** (Cursor, Kiro, Hermes, Kimi Code, Copilot, **Grok Build**, **oh-my-pi**, **pi**, **Craft Agents**, **Kilo CLI**, **Kilo Code**, **Roo Code**, **Antigravity**, **Zed Agent**, **Goose**, **Droid**, **Mimo Code**, **ZCode**, **AnythingLLM Desktop**) — nothing is installed into those tools. We only read files they already produce (SQLite DB, JSONL, OTEL export, session logs). Copilot App / CLI usage is read per request from `~/.copilot/session-store.db`; `data.db` provides the one-time legacy adoption baseline and stays observe-only after the store becomes canonical, while the Chat extension and legacy CLI continue using OTEL. TokenTracker coordinates the sources so overlapping requests are counted once. Mixed App/CLI usage that predates adoption is retained as a `github-copilot-legacy` aggregate rather than assigned to a guessed request model.
202
235
  > - **Grok Build estimate** — current local telemetry exposes cumulative `updates.jsonl` `totalTokens`, but not a stable prompt/output/cache split; `signals.json` remains a fallback with `contextTokensUsed` snapshots. TokenTracker estimates Grok cost until per-call usage details are available.
203
236
  >
204
237
  > Run `tokentracker status` anytime to verify every integration's state. If something shows `skipped`, the `detail` column explains why (e.g. tool CLI not on `PATH`, config unreadable).
@@ -211,11 +244,11 @@ Missing your tool? [Open an issue](https://github.com/mm7894215/TokenTracker/iss
211
244
 
212
245
  ## 🆚 Why TokenTracker? <a id="ccusage-alternative"></a>
213
246
 
214
- > **Looking for a ccusage alternative with a GUI?** TokenTracker covers 25 tools (not just Claude Code), adds a native macOS menu bar app + desktop widgets, and de-duplicates token records correctly across providers — so your numbers match the providers' own billing.
247
+ > **Looking for a ccusage alternative with a GUI?** TokenTracker covers 27 tools (not just Claude Code), adds native macOS and Windows apps + desktop widgets, and de-duplicates token records correctly across providers — so your numbers match the providers' own billing.
215
248
 
216
249
  | | **TokenTracker** | ccusage | Cursor stats |
217
250
  |--------------------------|:---:|:---:|:---:|
218
- | **AI tools supported** | **25** | 1 (Claude) | 1 (Cursor) |
251
+ | **AI tools supported** | **27** | 1 (Claude) | 1 (Cursor) |
219
252
  | **Local-first, no account** | ✅ | ✅ | ❌ |
220
253
  | **Native desktop app** | ✅ macOS + Windows | ❌ | ❌ |
221
254
  | **Desktop widgets** | ✅ 4 widgets | ❌ | ❌ |
@@ -230,7 +263,7 @@ Missing your tool? [Open an issue](https://github.com/mm7894215/TokenTracker/iss
230
263
 
231
264
  ```mermaid
232
265
  flowchart LR
233
- A["AI CLI Tools<br/>Claude Code · Codex · Cursor · Gemini · Kiro<br/>OpenCode · OpenClaw · Every Code · Hermes · Copilot<br/>Kimi Code · CodeBuddy · WorkBuddy · Grok Build · Kilo CLI · Kilo Code · <br/>Antigravity · oh-my-pi · pi · Craft Agents · Roo Code · Zed · Goose · Mimo · ZCode"]
266
+ A["AI coding tools<br/>Claude Code · Codex · Cursor · Gemini · Kiro<br/>OpenCode · OpenClaw · Every Code · Hermes · Copilot<br/>Kimi Code · CodeBuddy · WorkBuddy · Grok Build · Kilo CLI · Kilo Code<br/>Antigravity · oh-my-pi · pi · Craft · Roo · Zed · Goose · Droid · Mimo · ZCode · AnythingLLM"]
234
267
  A -->|hooks trigger| B[Token Tracker]
235
268
  B -->|parse logs<br/>30-min UTC buckets| C[(Local SQLite)]
236
269
  C --> D[Web Dashboard]
package/README.zh-CN.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  ### 跨所有 CLI,看清你到底在 AI 上花了多少钱
8
8
 
9
- 自动采集 **25 款 AI 编码工具** 的 token 用量,全程本地聚合,用一套漂亮的 Dashboard 看真实成本与趋势。不需要云账号、不需要 API Key、不需要任何配置 —— 一条命令搞定。
9
+ 自动采集 **27 款 AI 编码工具** 的 token 用量,全程本地聚合,用一套漂亮的 Dashboard 看真实成本与趋势。不需要云账号、不需要 API Key、不需要任何配置 —— 一条命令搞定。
10
10
 
11
11
  [![npm version](https://img.shields.io/npm/v/tokentracker-cli.svg?color=blue)](https://www.npmjs.com/package/tokentracker-cli)
12
12
  [![npm downloads](https://img.shields.io/npm/dm/tokentracker-cli.svg?color=brightgreen)](https://www.npmjs.com/package/tokentracker-cli)
@@ -89,7 +89,7 @@ brew install mm7894215/tokentracker/tokentracker
89
89
 
90
90
  ## ✨ 特性
91
91
 
92
- - 🔌 **开箱即用支持 25 款 AI 工具** —— Claude Code、Codex CLI、Cursor、Gemini CLI、Kiro、OpenCode、OpenClaw、Every Code、Hermes Agent、GitHub Copilot、Kimi Code、CodeBuddy、WorkBuddy、Grok Build、oh-my-pi、pi、Craft Agents、Kilo CLI、Kilo Code、Roo Code、Antigravity、Zed Agent、Goose、Mimo Code、ZCode
92
+ - 🔌 **开箱即用支持 27 款 AI 工具** —— Claude Code、Codex CLI、Cursor、Gemini CLI、Kiro、OpenCode、OpenClaw、Every Code、Hermes Agent、GitHub Copilot、Kimi Code、CodeBuddy、WorkBuddy、Grok Build、oh-my-pi、pi、Craft Agents、Kilo CLI、Kilo Code、Roo Code、Antigravity、Zed Agent、Goose、Droid、Mimo Code、ZCode、AnythingLLM Desktop
93
93
  - 🏠 **100% 本地** —— Token 数据绝不离开你的机器。无账号、无 API Key
94
94
  - 🚀 **零配置** —— 首次运行自动安装所有 hook。30 秒从零到 Dashboard
95
95
  - 📊 **漂亮的 Dashboard** —— 用量趋势、按模型的成本分解、GitHub 风格活跃度热力图、按项目归因
@@ -189,13 +189,15 @@ brew install mm7894215/tokentracker/tokentracker
189
189
  | **Roo Code** (VS Code 扩展) | ✅ 自动 | 被动读取 `ui_messages.json`(`rooveterinaryinc.roo-cline`) |
190
190
  | **Zed Agent** | ✅ 自动 | 被动 SQLite 读取(`threads.db`,仅统计托管的 `zed.dev` 模型) |
191
191
  | **Goose** (Block) | ✅ 自动 | 被动 SQLite 读取(`sessions.db`,累计量 delta) |
192
+ | **Droid** (Factory) | ✅ 自动 | 被动读取 session(`~/.factory/sessions/**/settings.json`,累计量 delta) |
192
193
  | **Mimo Code** (mimocode) | ✅ 自动 | 被动 SQLite 读取(`~/.local/share/mimocode/mimocode.db`,OpenCode-fork schema;仅统计 mimo 原生轮次——镜像进来的 Claude/claude-mem 历史已排除) |
193
194
  | **ZCode** (Z.ai) | ✅ 自动 | 被动 SQLite 读取(`~/.zcode/cli/db/db.sqlite`,OpenCode-fork schema;仅统计 Z.ai/BigModel 的 GLM 轮次——内置的 Claude/Codex/Gemini 子 agent 已排除) |
195
+ | **AnythingLLM Desktop** | ✅ 自动 | 被动 SQLite 读取(`anythingllm-desktop/storage/anythingllm.db`;只读取每条消息的 token 指标,不读取 prompt 或回复) |
194
196
 
195
197
  > **需要手动装什么插件 / hook 吗?** 不需要。`tokentracker`(或 `tokentracker init`)第一次跑的时候会全部搞定:
196
198
  > - **基于 hook 的工具**(Claude Code、Codex、Gemini、Every Code、**CodeBuddy**、**WorkBuddy**、**Grok Build**)—— 我们把 SessionEnd hook 或 TOML notify 条目写入它们自己的配置文件
197
199
  > - **基于插件的工具**(OpenCode、**OpenClaw**)—— 插件随 npm 包一起分发。OpenClaw 的 session plugin 位于 `~/.tokentracker/tracker/openclaw-plugin/openclaw-session-sync/`;TokenTracker 会通过 OpenClaw 自己的 CLI 挂接并启用它,然后写入 `hooks.allowConversationAccess=true`,让 OpenClaw 放行触发同步的会话结束事件。无需下载、无需拖拽
198
- > - **被动读取类**(Cursor、Kiro、Hermes、Kimi Code、Copilot、**Grok Build**、**oh-my-pi**、**pi**、**Craft Agents**、**Kilo CLI**、**Kilo Code**、**Roo Code**、**Antigravity**、**Zed Agent**、**Goose**、**Mimo Code**、**ZCode**)—— 完全不往它们里面塞东西,只读取它们自己产生的文件(SQLite DB、JSONL、OTEL 导出、会话轨迹日志)。Copilot App / CLI 的用量按请求读取 `~/.copilot/session-store.db`;`data.db` 只提供一次旧数据迁移基线,并在 store 成为主源后保持仅观察,Chat 扩展和旧版 CLI 继续使用 OTEL。TokenTracker 会协调这些数据源,使重叠请求只统计一次。迁移前无法无损拆分模型的 App/CLI 混合历史会保留为 `github-copilot-legacy` 聚合量,而不会猜测请求模型
200
+ > - **被动读取类**(Cursor、Kiro、Hermes、Kimi Code、Copilot、**Grok Build**、**oh-my-pi**、**pi**、**Craft Agents**、**Kilo CLI**、**Kilo Code**、**Roo Code**、**Antigravity**、**Zed Agent**、**Goose**、**Droid**、**Mimo Code**、**ZCode**、**AnythingLLM Desktop**)—— 完全不往它们里面塞东西,只读取它们自己产生的文件(SQLite DB、JSONL、OTEL 导出、会话轨迹日志)。Copilot App / CLI 的用量按请求读取 `~/.copilot/session-store.db`;`data.db` 只提供一次旧数据迁移基线,并在 store 成为主源后保持仅观察,Chat 扩展和旧版 CLI 继续使用 OTEL。TokenTracker 会协调这些数据源,使重叠请求只统计一次。迁移前无法无损拆分模型的 App/CLI 混合历史会保留为 `github-copilot-legacy` 聚合量,而不会猜测请求模型
199
201
  > - **Grok Build 估算说明** —— Grok 当前本地遥测提供 `updates.jsonl` 里的累计 `totalTokens`,但还没有稳定的输入/输出/cache 拆分;`signals.json` 仍作为 `contextTokensUsed` 快照兜底。所以在 Grok 提供按调用粒度的用量明细之前,TokenTracker 对 Grok 成本仍是估算值
200
202
  >
201
203
  > 任何时候都可以用 `tokentracker status` 查看每个集成的状态。如果显示 `skipped`,`detail` 列会解释原因(例如某工具 CLI 不在 `PATH` 上、config 不可读等)。
@@ -210,7 +212,7 @@ brew install mm7894215/tokentracker/tokentracker
210
212
 
211
213
  | | **TokenTracker** | ccusage | Cursor 自带统计 |
212
214
  |--------------------------|:---:|:---:|:---:|
213
- | **支持的 AI 工具数** | **25** | 1(Claude) | 1(Cursor) |
215
+ | **支持的 AI 工具数** | **27** | 1(Claude) | 1(Cursor) |
214
216
  | **本地优先,无需账号** | ✅ | ✅ | ❌ |
215
217
  | **原生桌面 App** | ✅ macOS + Windows | ❌ | ❌ |
216
218
  | **桌面小组件** | ✅ 4 个小组件 | ❌ | ❌ |
@@ -222,7 +224,7 @@ brew install mm7894215/tokentracker/tokentracker
222
224
 
223
225
  ```mermaid
224
226
  flowchart LR
225
- A["AI CLI 工具<br/>Claude Code · Codex · Cursor · Gemini · Kiro<br/>OpenCode · OpenClaw · Every Code · Hermes · Copilot<br/>Kimi Code · CodeBuddy · WorkBuddy · Grok Build · Kilo CLI · Kilo Code · <br/>Antigravity · oh-my-pi · pi · Craft Agents · Roo Code · Zed · Goose · Mimo · ZCode"]
227
+ A["AI 编码工具<br/>Claude Code · Codex · Cursor · Gemini · Kiro<br/>OpenCode · OpenClaw · Every Code · Hermes · Copilot<br/>Kimi · CodeBuddy · WorkBuddy · Grok · Kilo · Roo · Zed · Goose<br/>Antigravity · oh-my-pi · pi · Craft · Droid · Mimo · ZCode · AnythingLLM"]
226
228
  A -->|hook 触发| B[Token Tracker]
227
229
  B -->|解析日志<br/>30 分钟 UTC 桶| C[(本地 SQLite)]
228
230
  C --> D[Web Dashboard]
@@ -1 +1 @@
1
- import{c as o,R as N,j as r}from"./main-CvkyGV2H.js";import{Z as $}from"./zap-Blccuc-z.js";import{F as A}from"./flame-B27yR7Au.js";const j=[["path",{d:"M10 22V7a1 1 0 0 0-1-1H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-5a1 1 0 0 0-1-1H2",key:"1ah6g2"}],["rect",{x:"14",y:"2",width:"8",height:"8",rx:"1",key:"88lufb"}]],E=o("blocks",j);const L=[["path",{d:"M12 18V5",key:"adv99a"}],["path",{d:"M15 13a4.17 4.17 0 0 1-3-4 4.17 4.17 0 0 1-3 4",key:"1e3is1"}],["path",{d:"M17.598 6.5A3 3 0 1 0 12 5a3 3 0 1 0-5.598 1.5",key:"1gqd8o"}],["path",{d:"M17.997 5.125a4 4 0 0 1 2.526 5.77",key:"iwvgf7"}],["path",{d:"M18 18a4 4 0 0 0 2-7.464",key:"efp6ie"}],["path",{d:"M19.967 17.483A4 4 0 1 1 12 18a4 4 0 1 1-7.967-.517",key:"1gq6am"}],["path",{d:"M6 18a4 4 0 0 1-2-7.464",key:"k1g0md"}],["path",{d:"M6.003 5.125a4 4 0 0 0-2.526 5.77",key:"q97ue3"}]],C=o("brain",L);const T=[["path",{d:"M8 2v4",key:"1cmpym"}],["path",{d:"M16 2v4",key:"4m81vk"}],["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2",key:"1hopcy"}],["path",{d:"M3 10h18",key:"8toen8"}],["path",{d:"M8 14h.01",key:"6423bh"}],["path",{d:"M12 14h.01",key:"1etili"}],["path",{d:"M16 14h.01",key:"1gbofw"}],["path",{d:"M8 18h.01",key:"lrp35t"}],["path",{d:"M12 18h.01",key:"mhygvu"}],["path",{d:"M16 18h.01",key:"kzsmim"}]],z=o("calendar-days",T);const B=[["path",{d:"M11.562 3.266a.5.5 0 0 1 .876 0L15.39 8.87a1 1 0 0 0 1.516.294L21.183 5.5a.5.5 0 0 1 .798.519l-2.834 10.246a1 1 0 0 1-.956.734H5.81a1 1 0 0 1-.957-.734L2.02 6.02a.5.5 0 0 1 .798-.519l4.276 3.664a1 1 0 0 0 1.516-.294z",key:"1vdc57"}],["path",{d:"M5 21h14",key:"11awu3"}]],R=o("crown",B);const q=[["path",{d:"M12.67 19a2 2 0 0 0 1.416-.588l6.154-6.172a6 6 0 0 0-8.49-8.49L5.586 9.914A2 2 0 0 0 5 11.328V18a1 1 0 0 0 1 1z",key:"18jl4k"}],["path",{d:"M16 8 2 22",key:"vp34q"}],["path",{d:"M17.5 15H9",key:"1oz8nu"}]],H=o("feather",q);const D=[["path",{d:"M18 19a5 5 0 0 1-5-5v8",key:"sz5oeg"}],["path",{d:"M9 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v5",key:"1w6njk"}],["circle",{cx:"13",cy:"12",r:"2",key:"1j92g6"}],["circle",{cx:"20",cy:"19",r:"2",key:"1obnsp"}]],F=o("folder-git-2",D);const I=[["path",{d:"M4 16v-2.38C4 11.5 2.97 10.5 3 8c.03-2.72 1.49-6 4.5-6C9.37 2 10 3.8 10 5.5c0 3.11-2 5.66-2 8.68V16a2 2 0 1 1-4 0Z",key:"1dudjm"}],["path",{d:"M20 20v-2.38c0-2.12 1.03-3.12 1-5.62-.03-2.72-1.49-6-4.5-6C14.63 6 14 7.8 14 9.5c0 3.11 2 5.66 2 8.68V20a2 2 0 1 0 4 0Z",key:"l2t8xc"}],["path",{d:"M16 17h4",key:"1dejxt"}],["path",{d:"M4 13h4",key:"1bwh8b"}]],G=o("footprints",I);const V=[["path",{d:"M2 9.5a5.5 5.5 0 0 1 9.591-3.676.56.56 0 0 0 .818 0A5.49 5.49 0 0 1 22 9.5c0 2.29-1.5 4-3 5.5l-5.492 5.313a2 2 0 0 1-3 .019L5 15c-1.5-1.5-3-3.2-3-5.5",key:"mvr1a0"}]],S=o("heart",V);const Z=[["path",{d:"M7.21 15 2.66 7.14a2 2 0 0 1 .13-2.2L4.4 2.8A2 2 0 0 1 6 2h12a2 2 0 0 1 1.6.8l1.6 2.14a2 2 0 0 1 .14 2.2L16.79 15",key:"143lza"}],["path",{d:"M11 12 5.12 2.2",key:"qhuxz6"}],["path",{d:"m13 12 5.88-9.8",key:"hbye0f"}],["path",{d:"M8 7h8",key:"i86dvs"}],["circle",{cx:"12",cy:"17",r:"5",key:"qbz8iq"}],["path",{d:"M12 18v-2h-.5",key:"fawc4q"}]],O=o("medal",Z);const P=[["path",{d:"M18 5h4",key:"1lhgn2"}],["path",{d:"M20 3v4",key:"1olli1"}],["path",{d:"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401",key:"kfwtm"}]],X=o("moon-star",P);const K=[["path",{d:"M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5",key:"qeys4"}],["path",{d:"M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09",key:"u4xsad"}],["path",{d:"M9 12a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.4 22.4 0 0 1-4 2z",key:"676m9"}],["path",{d:"M9 12H4s.55-3.03 2-4c1.62-1.08 5 .05 5 .05",key:"92ym6u"}]],U=o("rocket",K);const W=[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],Y=o("shield-check",W);const J=[["path",{d:"M16 7h6v6",key:"box55l"}],["path",{d:"m22 7-8.5 8.5-5-5L2 17",key:"1t1m79"}]],Q=o("trending-up",J),k=[{id:"token_titan",scope:"cloud",icon:R,format:"tokens",art:"/achievements/token-titan.png"},{id:"big_day",scope:"cloud",icon:$,format:"tokens",art:"/achievements/big-day.png"},{id:"wordsmith",scope:"cloud",icon:H,format:"tokens",art:"/achievements/wordsmith.png"},{id:"marathoner",scope:"cloud",icon:G,format:"days",art:"/achievements/marathoner.png"},{id:"streak",scope:"cloud",icon:A,format:"days",art:"/achievements/streak.png"},{id:"weekend_warrior",scope:"cloud",icon:z,format:"days",art:"/achievements/weekend-warrior.png"},{id:"momentum",scope:"cloud",icon:Q,format:"multiplier",art:"/achievements/momentum.png"},{id:"polyglot",scope:"cloud",icon:C,format:"count",art:"/achievements/polyglot.png"},{id:"trendsetter",scope:"cloud",icon:U,format:"count",art:"/achievements/trendsetter.png"},{id:"multitool",scope:"cloud",icon:E,format:"count",art:"/achievements/multitool.png"},{id:"podium",scope:"cloud",icon:O,format:"rank",art:"/achievements/podium.png"},{id:"veteran",scope:"cloud",icon:Y,format:"days",art:"/achievements/veteran.png"},{id:"project_hopper",scope:"local",icon:F,format:"count",art:"/achievements/project-hopper.png"},{id:"project_devotion",scope:"local",icon:S,format:"tokens",art:"/achievements/project-devotion.png"},{id:"night_owl",scope:"local",icon:X,format:"count",art:"/achievements/night-owl.png"}],u=new Map(k.map(e=>[e.id,e])),m=new Map(k.map((e,a)=>[e.id,a]));function de(e,a){return`achievements.badge.${e}.${a}`}function ee(e){return[...e||[]].sort((a,t)=>{const c=(t?.tier||0)-(a?.tier||0);return c!==0?c:(m.get(a?.id)??99)-(m.get(t?.id)??99)})}function re(e){const a=(e||[]).filter(t=>t&&(t.tier||0)>=1&&u.has(t.id));return a.length===0?null:ee(a)[0]}const v={1:"bronze",2:"silver",3:"gold",4:"diamond"},ie=["bronze","silver","gold","diamond"],ae={bronze:{rim:["#a06a44","#5c3a22"],face:["#d29a6c","#96602f"],glyph:"#3f2817",ring:"#e8c3a0",sheen:"rgba(255, 236, 220, 0.45)",label:"#a06a44"},silver:{rim:["#aab3bb","#67707b"],face:["#dde2e7","#9ba5ae"],glyph:"#39424b",ring:"#f2f5f7",sheen:"rgba(255, 255, 255, 0.55)",label:"#8b959f"},gold:{rim:["#c9971c","#8a6508"],face:["#f2ca52","#cf9c26"],glyph:"#5c430e",ring:"#ffe9a8",sheen:"rgba(255, 248, 214, 0.55)",label:"#b8860b"},diamond:{rim:["#62b1e0","#7c6fd9"],face:["#c8ecf6","#84b4ea"],glyph:"#27496d",ring:"#eafcff",sheen:"rgba(255, 255, 255, 0.65)",label:"#5a9bd8"}},y={rim:["#a8ada9","#7c817d"],face:["#cdd2ce","#a3a8a4"],glyph:"#6a706c",ring:"#dde1de",sheen:"rgba(255, 255, 255, 0.25)",label:"#8b908c"};function te(e,a=!1){return a||!e||e<1?y:ae[v[Math.min(e,4)]]||y}function se(e){return v[e]||null}const g={xs:18,sm:24,md:44,xl:88,lg:108},f={xs:.75,sm:1,md:1.5,xl:2,lg:2};function le({badgeId:e,tier:a=0,size:t="md",locked:c=!1,label:i,className:M=""}){const s=u.get(e),h=c||!a||a<1,n=te(a,h),d=t==="fill",l=d?"100%":g[t]||g.md,b=d?4:f[t]||f.md,[_,x]=N.useState(!1),p=s?.icon||null,w=!!s?.art&&!_;return r.jsx("span",{role:i?"img":void 0,"aria-label":i||void 0,"aria-hidden":i?void 0:!0,className:`inline-flex shrink-0 rounded-full ${M}`,style:{width:l,height:l,padding:b,background:`linear-gradient(135deg, ${n.rim[0]} 0%, ${n.ring} 42%, ${n.rim[1]} 100%)`,boxShadow:d||t==="md"||t==="xl"||t==="lg"?"0 0 0 1px rgba(10, 15, 12, 0.06), 0 1px 2px rgba(10, 15, 12, 0.08)":void 0},children:w?r.jsx("img",{src:s.art,alt:"",draggable:!1,loading:"lazy",onError:()=>x(!0),className:"h-full w-full rounded-full object-cover",style:h?{filter:"grayscale(1)",opacity:.55}:void 0}):r.jsx("span",{className:"flex h-full w-full items-center justify-center rounded-full",style:{background:`linear-gradient(145deg, ${n.face[0]}, ${n.face[1]})`},children:p?r.jsx(p,{size:d?64:Math.round(l*.5),color:n.glyph,strokeWidth:2}):null})})}export{le as A,k as B,S as H,ae as T,u as a,de as b,ie as c,re as h,te as p,ee as s,se as t};
1
+ import{c as o,R as N,j as r}from"./main-BbxPEfc4.js";import{Z as $}from"./zap-CnEr_e6T.js";import{F as A}from"./flame-Wz7IYxjy.js";const j=[["path",{d:"M10 22V7a1 1 0 0 0-1-1H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-5a1 1 0 0 0-1-1H2",key:"1ah6g2"}],["rect",{x:"14",y:"2",width:"8",height:"8",rx:"1",key:"88lufb"}]],E=o("blocks",j);const L=[["path",{d:"M12 18V5",key:"adv99a"}],["path",{d:"M15 13a4.17 4.17 0 0 1-3-4 4.17 4.17 0 0 1-3 4",key:"1e3is1"}],["path",{d:"M17.598 6.5A3 3 0 1 0 12 5a3 3 0 1 0-5.598 1.5",key:"1gqd8o"}],["path",{d:"M17.997 5.125a4 4 0 0 1 2.526 5.77",key:"iwvgf7"}],["path",{d:"M18 18a4 4 0 0 0 2-7.464",key:"efp6ie"}],["path",{d:"M19.967 17.483A4 4 0 1 1 12 18a4 4 0 1 1-7.967-.517",key:"1gq6am"}],["path",{d:"M6 18a4 4 0 0 1-2-7.464",key:"k1g0md"}],["path",{d:"M6.003 5.125a4 4 0 0 0-2.526 5.77",key:"q97ue3"}]],C=o("brain",L);const T=[["path",{d:"M8 2v4",key:"1cmpym"}],["path",{d:"M16 2v4",key:"4m81vk"}],["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2",key:"1hopcy"}],["path",{d:"M3 10h18",key:"8toen8"}],["path",{d:"M8 14h.01",key:"6423bh"}],["path",{d:"M12 14h.01",key:"1etili"}],["path",{d:"M16 14h.01",key:"1gbofw"}],["path",{d:"M8 18h.01",key:"lrp35t"}],["path",{d:"M12 18h.01",key:"mhygvu"}],["path",{d:"M16 18h.01",key:"kzsmim"}]],z=o("calendar-days",T);const B=[["path",{d:"M11.562 3.266a.5.5 0 0 1 .876 0L15.39 8.87a1 1 0 0 0 1.516.294L21.183 5.5a.5.5 0 0 1 .798.519l-2.834 10.246a1 1 0 0 1-.956.734H5.81a1 1 0 0 1-.957-.734L2.02 6.02a.5.5 0 0 1 .798-.519l4.276 3.664a1 1 0 0 0 1.516-.294z",key:"1vdc57"}],["path",{d:"M5 21h14",key:"11awu3"}]],R=o("crown",B);const q=[["path",{d:"M12.67 19a2 2 0 0 0 1.416-.588l6.154-6.172a6 6 0 0 0-8.49-8.49L5.586 9.914A2 2 0 0 0 5 11.328V18a1 1 0 0 0 1 1z",key:"18jl4k"}],["path",{d:"M16 8 2 22",key:"vp34q"}],["path",{d:"M17.5 15H9",key:"1oz8nu"}]],H=o("feather",q);const D=[["path",{d:"M18 19a5 5 0 0 1-5-5v8",key:"sz5oeg"}],["path",{d:"M9 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v5",key:"1w6njk"}],["circle",{cx:"13",cy:"12",r:"2",key:"1j92g6"}],["circle",{cx:"20",cy:"19",r:"2",key:"1obnsp"}]],F=o("folder-git-2",D);const I=[["path",{d:"M4 16v-2.38C4 11.5 2.97 10.5 3 8c.03-2.72 1.49-6 4.5-6C9.37 2 10 3.8 10 5.5c0 3.11-2 5.66-2 8.68V16a2 2 0 1 1-4 0Z",key:"1dudjm"}],["path",{d:"M20 20v-2.38c0-2.12 1.03-3.12 1-5.62-.03-2.72-1.49-6-4.5-6C14.63 6 14 7.8 14 9.5c0 3.11 2 5.66 2 8.68V20a2 2 0 1 0 4 0Z",key:"l2t8xc"}],["path",{d:"M16 17h4",key:"1dejxt"}],["path",{d:"M4 13h4",key:"1bwh8b"}]],G=o("footprints",I);const V=[["path",{d:"M2 9.5a5.5 5.5 0 0 1 9.591-3.676.56.56 0 0 0 .818 0A5.49 5.49 0 0 1 22 9.5c0 2.29-1.5 4-3 5.5l-5.492 5.313a2 2 0 0 1-3 .019L5 15c-1.5-1.5-3-3.2-3-5.5",key:"mvr1a0"}]],S=o("heart",V);const Z=[["path",{d:"M7.21 15 2.66 7.14a2 2 0 0 1 .13-2.2L4.4 2.8A2 2 0 0 1 6 2h12a2 2 0 0 1 1.6.8l1.6 2.14a2 2 0 0 1 .14 2.2L16.79 15",key:"143lza"}],["path",{d:"M11 12 5.12 2.2",key:"qhuxz6"}],["path",{d:"m13 12 5.88-9.8",key:"hbye0f"}],["path",{d:"M8 7h8",key:"i86dvs"}],["circle",{cx:"12",cy:"17",r:"5",key:"qbz8iq"}],["path",{d:"M12 18v-2h-.5",key:"fawc4q"}]],O=o("medal",Z);const P=[["path",{d:"M18 5h4",key:"1lhgn2"}],["path",{d:"M20 3v4",key:"1olli1"}],["path",{d:"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401",key:"kfwtm"}]],X=o("moon-star",P);const K=[["path",{d:"M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5",key:"qeys4"}],["path",{d:"M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09",key:"u4xsad"}],["path",{d:"M9 12a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.4 22.4 0 0 1-4 2z",key:"676m9"}],["path",{d:"M9 12H4s.55-3.03 2-4c1.62-1.08 5 .05 5 .05",key:"92ym6u"}]],U=o("rocket",K);const W=[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],Y=o("shield-check",W);const J=[["path",{d:"M16 7h6v6",key:"box55l"}],["path",{d:"m22 7-8.5 8.5-5-5L2 17",key:"1t1m79"}]],Q=o("trending-up",J),k=[{id:"token_titan",scope:"cloud",icon:R,format:"tokens",art:"/achievements/token-titan.png"},{id:"big_day",scope:"cloud",icon:$,format:"tokens",art:"/achievements/big-day.png"},{id:"wordsmith",scope:"cloud",icon:H,format:"tokens",art:"/achievements/wordsmith.png"},{id:"marathoner",scope:"cloud",icon:G,format:"days",art:"/achievements/marathoner.png"},{id:"streak",scope:"cloud",icon:A,format:"days",art:"/achievements/streak.png"},{id:"weekend_warrior",scope:"cloud",icon:z,format:"days",art:"/achievements/weekend-warrior.png"},{id:"momentum",scope:"cloud",icon:Q,format:"multiplier",art:"/achievements/momentum.png"},{id:"polyglot",scope:"cloud",icon:C,format:"count",art:"/achievements/polyglot.png"},{id:"trendsetter",scope:"cloud",icon:U,format:"count",art:"/achievements/trendsetter.png"},{id:"multitool",scope:"cloud",icon:E,format:"count",art:"/achievements/multitool.png"},{id:"podium",scope:"cloud",icon:O,format:"rank",art:"/achievements/podium.png"},{id:"veteran",scope:"cloud",icon:Y,format:"days",art:"/achievements/veteran.png"},{id:"project_hopper",scope:"local",icon:F,format:"count",art:"/achievements/project-hopper.png"},{id:"project_devotion",scope:"local",icon:S,format:"tokens",art:"/achievements/project-devotion.png"},{id:"night_owl",scope:"local",icon:X,format:"count",art:"/achievements/night-owl.png"}],u=new Map(k.map(e=>[e.id,e])),m=new Map(k.map((e,a)=>[e.id,a]));function de(e,a){return`achievements.badge.${e}.${a}`}function ee(e){return[...e||[]].sort((a,t)=>{const c=(t?.tier||0)-(a?.tier||0);return c!==0?c:(m.get(a?.id)??99)-(m.get(t?.id)??99)})}function re(e){const a=(e||[]).filter(t=>t&&(t.tier||0)>=1&&u.has(t.id));return a.length===0?null:ee(a)[0]}const v={1:"bronze",2:"silver",3:"gold",4:"diamond"},ie=["bronze","silver","gold","diamond"],ae={bronze:{rim:["#a06a44","#5c3a22"],face:["#d29a6c","#96602f"],glyph:"#3f2817",ring:"#e8c3a0",sheen:"rgba(255, 236, 220, 0.45)",label:"#a06a44"},silver:{rim:["#aab3bb","#67707b"],face:["#dde2e7","#9ba5ae"],glyph:"#39424b",ring:"#f2f5f7",sheen:"rgba(255, 255, 255, 0.55)",label:"#8b959f"},gold:{rim:["#c9971c","#8a6508"],face:["#f2ca52","#cf9c26"],glyph:"#5c430e",ring:"#ffe9a8",sheen:"rgba(255, 248, 214, 0.55)",label:"#b8860b"},diamond:{rim:["#62b1e0","#7c6fd9"],face:["#c8ecf6","#84b4ea"],glyph:"#27496d",ring:"#eafcff",sheen:"rgba(255, 255, 255, 0.65)",label:"#5a9bd8"}},y={rim:["#a8ada9","#7c817d"],face:["#cdd2ce","#a3a8a4"],glyph:"#6a706c",ring:"#dde1de",sheen:"rgba(255, 255, 255, 0.25)",label:"#8b908c"};function te(e,a=!1){return a||!e||e<1?y:ae[v[Math.min(e,4)]]||y}function se(e){return v[e]||null}const g={xs:18,sm:24,md:44,xl:88,lg:108},f={xs:.75,sm:1,md:1.5,xl:2,lg:2};function le({badgeId:e,tier:a=0,size:t="md",locked:c=!1,label:i,className:M=""}){const s=u.get(e),h=c||!a||a<1,n=te(a,h),d=t==="fill",l=d?"100%":g[t]||g.md,b=d?4:f[t]||f.md,[_,x]=N.useState(!1),p=s?.icon||null,w=!!s?.art&&!_;return r.jsx("span",{role:i?"img":void 0,"aria-label":i||void 0,"aria-hidden":i?void 0:!0,className:`inline-flex shrink-0 rounded-full ${M}`,style:{width:l,height:l,padding:b,background:`linear-gradient(135deg, ${n.rim[0]} 0%, ${n.ring} 42%, ${n.rim[1]} 100%)`,boxShadow:d||t==="md"||t==="xl"||t==="lg"?"0 0 0 1px rgba(10, 15, 12, 0.06), 0 1px 2px rgba(10, 15, 12, 0.08)":void 0},children:w?r.jsx("img",{src:s.art,alt:"",draggable:!1,loading:"lazy",onError:()=>x(!0),className:"h-full w-full rounded-full object-cover",style:h?{filter:"grayscale(1)",opacity:.55}:void 0}):r.jsx("span",{className:"flex h-full w-full items-center justify-center rounded-full",style:{background:`linear-gradient(145deg, ${n.face[0]}, ${n.face[1]})`},children:p?r.jsx(p,{size:d?64:Math.round(l*.5),color:n.glyph,strokeWidth:2}):null})})}export{le as A,k as B,S as H,ae as T,u as a,de as b,ie as c,re as h,te as p,ee as s,se as t};
@@ -1,2 +1,2 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/BadgeDetailModal-bKdQ_Pls.js","assets/main-CvkyGV2H.js","assets/main-C6V_dFqw.css","assets/AchievementBadge-wQQwzQYv.js","assets/zap-Blccuc-z.js","assets/flame-B27yR7Au.js","assets/use-transform-BW36bKb3.js","assets/AchievementsSection-Cwgr4N8D.js","assets/format-tokens-B8_mvUxn.js","assets/DialogTitle-B-NMBFgN.js","assets/useScrollLock-juP-sEAK.js"])))=>i.map(i=>d[i]);
2
- import{r as l,V as x,ak as f,U as v,j as e,E as c,L as p,R as g,_ as y,a as b,al as k,a4 as j}from"./main-CvkyGV2H.js";import{A as w}from"./AchievementsSection-Cwgr4N8D.js";import{B as h}from"./AchievementBadge-wQQwzQYv.js";import"./format-tokens-B8_mvUxn.js";import"./zap-Blccuc-z.js";import"./flame-B27yR7Au.js";function N({enabled:a=!0}={}){const[n,t]=l.useState({status:"loading",achievements:[],error:null}),s=l.useMemo(()=>x(),[]);return l.useEffect(()=>{if(!a){t({status:"disabled",achievements:[],error:null});return}let i=!1;return t(r=>({...r,status:"loading"})),f({timeZone:s,tzOffsetMinutes:v()}).then(r=>{i||t({status:"ready",achievements:Array.isArray(r?.achievements)?r.achievements:[],error:null})}).catch(r=>{i||t({status:"error",achievements:[],error:r})}),()=>{i=!0}},[a,s]),n}const A=g.lazy(()=>j(()=>import("./BadgeDetailModal-bKdQ_Pls.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10])));function I({authLoading:a,authEnabled:n,authUserId:t,mockEnabled:s}){if(s)return{authLoading:!1,signedIn:!0,userId:"mock-user"};const i=!!(n&&t);return{authLoading:!!a,signedIn:i,userId:i?t:null}}function B(){const a=y(),[n,t]=l.useState({status:"loading",achievements:[],userId:null}),s=b(),{authLoading:i,signedIn:r,userId:o}=I({authLoading:a?.loading,authEnabled:a?.enabled,authUserId:a?.user?.id,mockEnabled:s});return l.useEffect(()=>{if(i){t({status:"loading",achievements:[],userId:null});return}if(!r){t({status:"signed-out",achievements:[],userId:null});return}let d=!1;return t({status:"loading",achievements:[],userId:o}),(async()=>{try{const u=s?null:await a.getAccessToken?.(),m=await k({accessToken:u,userId:o});if(d)return;t({status:"ready",achievements:Array.isArray(m?.badges)?m.badges:[],userId:o})}catch{d||t({status:"error",achievements:[],userId:o})}})(),()=>{d=!0}},[i,s,r,o]),{...n,signedIn:r,settled:_({authLoading:i,signedIn:r,userId:o,state:n})}}function _({authLoading:a,signedIn:n,userId:t,state:s}){return a?!1:n?s.userId===t&&(s.status==="ready"||s.status==="error"):s.status==="signed-out"}function E(){return e.jsx("div",{className:"mx-0 grid animate-pulse grid-cols-[repeat(3,max-content)] justify-between gap-y-7 sm:-mx-2 sm:grid-cols-[repeat(4,max-content)] lg:grid-cols-[repeat(5,max-content)]","aria-hidden":!0,children:Array.from({length:h.length}).map((a,n)=>e.jsxs("div",{className:"flex w-[6.75rem] flex-col items-center px-0 pb-3 pt-4 sm:w-[7.75rem]",children:[e.jsx("div",{className:"h-[108px] w-[108px] rounded-full bg-oai-gray-200 dark:bg-oai-gray-800"}),e.jsx("div",{className:"mt-3 h-3 w-16 rounded bg-oai-gray-200 dark:bg-oai-gray-800"}),e.jsx("div",{className:"mt-2 h-2 w-10 rounded bg-oai-gray-100 dark:bg-oai-gray-800/60"})]},n))})}function R(){const a=N(),n=B(),[t,s]=l.useState(null),i=a.status==="loading"||!n.settled,r=l.useMemo(()=>[...n.achievements||[],...a.achievements||[]],[n.achievements,a.achievements]),o=l.useMemo(()=>r.filter(u=>(u?.tier||0)>=1).length,[r]),d=h.length;return e.jsxs("div",{className:"flex flex-1 flex-col font-oai text-oai-black antialiased dark:text-oai-white",children:[e.jsx("main",{className:"flex-1 pb-12 pt-8 sm:pb-16 sm:pt-10",children:e.jsxs("div",{className:"mx-auto max-w-4xl px-4 sm:px-6",children:[e.jsxs("div",{className:"mb-7 flex items-baseline justify-between gap-4",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("h1",{className:"text-3xl font-semibold tracking-tight text-oai-black dark:text-white sm:text-4xl",children:c("achievements.page.title")}),e.jsx("p",{className:"mt-1.5 text-sm text-oai-gray-500 dark:text-oai-gray-400",children:c("achievements.page.local_note")})]}),!i&&e.jsxs("div",{className:"shrink-0 text-right",children:[e.jsxs("div",{className:"font-mono text-2xl font-semibold leading-none tabular-nums text-oai-black dark:text-white",children:[o,e.jsxs("span",{className:"text-oai-gray-400 dark:text-oai-gray-600",children:["/",d]})]}),e.jsx("div",{className:"mt-2 h-1 w-24 overflow-hidden rounded-full bg-oai-gray-200 dark:bg-oai-gray-800",children:e.jsx("div",{className:"h-full rounded-full bg-oai-brand-600 transition-[width] duration-500",style:{width:`${Math.round(o/d*100)}%`}})})]})]}),!n.signedIn&&!i&&e.jsxs("div",{className:"mb-6 flex flex-wrap items-center justify-between gap-x-4 gap-y-2 rounded-xl border border-oai-gray-200 bg-oai-gray-50 px-4 py-3 dark:border-oai-gray-800 dark:bg-oai-gray-900/60",children:[e.jsx("p",{className:"text-sm text-oai-gray-600 dark:text-oai-gray-300",children:c("achievements.signin.prompt")}),e.jsx(p,{to:"/login",className:"shrink-0 rounded-lg bg-oai-brand-600 px-3 py-1.5 text-sm font-medium text-white transition-colors duration-200 hover:bg-oai-brand-700 active:scale-[0.98]",children:c("achievements.signin.action")})]}),i?e.jsx(E,{}):e.jsxs(e.Fragment,{children:[e.jsx(w,{achievements:r,isOwn:!0,columns:"wide",size:"lg",animateIn:!0,onSelect:s}),e.jsxs("p",{className:"mt-10 text-center text-xs text-oai-gray-400 dark:text-oai-gray-500",children:[c("achievements.page.suggest")," ",e.jsx("a",{href:"https://github.com/mm7894215/TokenTracker/issues",target:"_blank",rel:"noopener noreferrer",className:"underline decoration-oai-gray-300 underline-offset-2 transition-colors hover:text-oai-gray-700 hover:decoration-oai-gray-500 dark:decoration-oai-gray-600 dark:hover:text-oai-gray-300",children:c("achievements.page.suggest_link")})]})]})]})}),t&&e.jsx(g.Suspense,{fallback:null,children:e.jsx(A,{badge:t,onClose:()=>s(null)})})]})}export{_ as cloudBadgesSettled,R as default,I as resolveCloudBadgeIdentity};
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/BadgeDetailModal-DP3yGm6-.js","assets/main-BbxPEfc4.js","assets/main-ilWqzAfD.css","assets/AchievementBadge-X9JssV2N.js","assets/zap-CnEr_e6T.js","assets/flame-Wz7IYxjy.js","assets/use-transform-YviydTql.js","assets/AchievementsSection-dPW0TScn.js","assets/format-tokens-Cy-5MGHS.js","assets/DialogTitle-D_V-kvKQ.js","assets/useScrollLock-h9pnSauU.js"])))=>i.map(i=>d[i]);
2
+ import{r as l,V as x,ak as f,U as v,j as e,E as c,L as p,R as g,_ as y,a as b,al as k,a4 as j}from"./main-BbxPEfc4.js";import{A as w}from"./AchievementsSection-dPW0TScn.js";import{B as h}from"./AchievementBadge-X9JssV2N.js";import"./format-tokens-Cy-5MGHS.js";import"./zap-CnEr_e6T.js";import"./flame-Wz7IYxjy.js";function N({enabled:a=!0}={}){const[n,t]=l.useState({status:"loading",achievements:[],error:null}),s=l.useMemo(()=>x(),[]);return l.useEffect(()=>{if(!a){t({status:"disabled",achievements:[],error:null});return}let i=!1;return t(r=>({...r,status:"loading"})),f({timeZone:s,tzOffsetMinutes:v()}).then(r=>{i||t({status:"ready",achievements:Array.isArray(r?.achievements)?r.achievements:[],error:null})}).catch(r=>{i||t({status:"error",achievements:[],error:r})}),()=>{i=!0}},[a,s]),n}const A=g.lazy(()=>j(()=>import("./BadgeDetailModal-DP3yGm6-.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10])));function I({authLoading:a,authEnabled:n,authUserId:t,mockEnabled:s}){if(s)return{authLoading:!1,signedIn:!0,userId:"mock-user"};const i=!!(n&&t);return{authLoading:!!a,signedIn:i,userId:i?t:null}}function B(){const a=y(),[n,t]=l.useState({status:"loading",achievements:[],userId:null}),s=b(),{authLoading:i,signedIn:r,userId:o}=I({authLoading:a?.loading,authEnabled:a?.enabled,authUserId:a?.user?.id,mockEnabled:s});return l.useEffect(()=>{if(i){t({status:"loading",achievements:[],userId:null});return}if(!r){t({status:"signed-out",achievements:[],userId:null});return}let d=!1;return t({status:"loading",achievements:[],userId:o}),(async()=>{try{const u=s?null:await a.getAccessToken?.(),m=await k({accessToken:u,userId:o});if(d)return;t({status:"ready",achievements:Array.isArray(m?.badges)?m.badges:[],userId:o})}catch{d||t({status:"error",achievements:[],userId:o})}})(),()=>{d=!0}},[i,s,r,o]),{...n,signedIn:r,settled:_({authLoading:i,signedIn:r,userId:o,state:n})}}function _({authLoading:a,signedIn:n,userId:t,state:s}){return a?!1:n?s.userId===t&&(s.status==="ready"||s.status==="error"):s.status==="signed-out"}function E(){return e.jsx("div",{className:"mx-0 grid animate-pulse grid-cols-[repeat(3,max-content)] justify-between gap-y-7 sm:-mx-2 sm:grid-cols-[repeat(4,max-content)] lg:grid-cols-[repeat(5,max-content)]","aria-hidden":!0,children:Array.from({length:h.length}).map((a,n)=>e.jsxs("div",{className:"flex w-[6.75rem] flex-col items-center px-0 pb-3 pt-4 sm:w-[7.75rem]",children:[e.jsx("div",{className:"h-[108px] w-[108px] rounded-full bg-oai-gray-200 dark:bg-oai-gray-800"}),e.jsx("div",{className:"mt-3 h-3 w-16 rounded bg-oai-gray-200 dark:bg-oai-gray-800"}),e.jsx("div",{className:"mt-2 h-2 w-10 rounded bg-oai-gray-100 dark:bg-oai-gray-800/60"})]},n))})}function R(){const a=N(),n=B(),[t,s]=l.useState(null),i=a.status==="loading"||!n.settled,r=l.useMemo(()=>[...n.achievements||[],...a.achievements||[]],[n.achievements,a.achievements]),o=l.useMemo(()=>r.filter(u=>(u?.tier||0)>=1).length,[r]),d=h.length;return e.jsxs("div",{className:"flex flex-1 flex-col font-oai text-oai-black antialiased dark:text-oai-white",children:[e.jsx("main",{className:"flex-1 pb-12 pt-8 sm:pb-16 sm:pt-10",children:e.jsxs("div",{className:"mx-auto max-w-4xl px-4 sm:px-6",children:[e.jsxs("div",{className:"mb-7 flex items-baseline justify-between gap-4",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("h1",{className:"text-3xl font-semibold tracking-tight text-oai-black dark:text-white sm:text-4xl",children:c("achievements.page.title")}),e.jsx("p",{className:"mt-1.5 text-sm text-oai-gray-500 dark:text-oai-gray-400",children:c("achievements.page.local_note")})]}),!i&&e.jsxs("div",{className:"shrink-0 text-right",children:[e.jsxs("div",{className:"font-mono text-2xl font-semibold leading-none tabular-nums text-oai-black dark:text-white",children:[o,e.jsxs("span",{className:"text-oai-gray-400 dark:text-oai-gray-600",children:["/",d]})]}),e.jsx("div",{className:"mt-2 h-1 w-24 overflow-hidden rounded-full bg-oai-gray-200 dark:bg-oai-gray-800",children:e.jsx("div",{className:"h-full rounded-full bg-oai-brand-600 transition-[width] duration-500",style:{width:`${Math.round(o/d*100)}%`}})})]})]}),!n.signedIn&&!i&&e.jsxs("div",{className:"mb-6 flex flex-wrap items-center justify-between gap-x-4 gap-y-2 rounded-xl border border-oai-gray-200 bg-oai-gray-50 px-4 py-3 dark:border-oai-gray-800 dark:bg-oai-gray-900/60",children:[e.jsx("p",{className:"text-sm text-oai-gray-600 dark:text-oai-gray-300",children:c("achievements.signin.prompt")}),e.jsx(p,{to:"/login",className:"shrink-0 rounded-lg bg-oai-brand-600 px-3 py-1.5 text-sm font-medium text-white transition-colors duration-200 hover:bg-oai-brand-700 active:scale-[0.98]",children:c("achievements.signin.action")})]}),i?e.jsx(E,{}):e.jsxs(e.Fragment,{children:[e.jsx(w,{achievements:r,isOwn:!0,columns:"wide",size:"lg",animateIn:!0,onSelect:s}),e.jsxs("p",{className:"mt-10 text-center text-xs text-oai-gray-400 dark:text-oai-gray-500",children:[c("achievements.page.suggest")," ",e.jsx("a",{href:"https://github.com/mm7894215/TokenTracker/issues",target:"_blank",rel:"noopener noreferrer",className:"underline decoration-oai-gray-300 underline-offset-2 transition-colors hover:text-oai-gray-700 hover:decoration-oai-gray-500 dark:decoration-oai-gray-600 dark:hover:text-oai-gray-300",children:c("achievements.page.suggest_link")})]})]})]})}),t&&e.jsx(g.Suspense,{fallback:null,children:e.jsx(A,{badge:t,onClose:()=>s(null)})})]})}export{_ as cloudBadgesSettled,R as default,I as resolveCloudBadgeIdentity};
@@ -1 +1 @@
1
- import{c as _,u as $,j as s,E as l,m as C}from"./main-CvkyGV2H.js";import{B as x,s as b,b as T,t as E,A as B,T as L}from"./AchievementBadge-wQQwzQYv.js";import{f as I}from"./format-tokens-B8_mvUxn.js";const D=[["path",{d:"M10 16h.01",key:"1bzywj"}],["path",{d:"M2.212 11.577a2 2 0 0 0-.212.896V18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-5.527a2 2 0 0 0-.212-.896L18.55 5.11A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z",key:"18tbho"}],["path",{d:"M21.946 12.013H2.054",key:"zqlbp7"}],["path",{d:"M6 16h.01",key:"1pmjb7"}]],F=_("hard-drive",D);function G(r,i){const t=Number(i)||0;switch(r){case"tokens":return I(t);case"rank":return`#${Math.round(t)}`;case"multiplier":return`${(Math.round(t*10)/10).toString()}×`;default:return Math.round(t).toLocaleString()}}function H(r){if(!r)return 0;const i=Number(r.next_threshold),t=Number(r.metric_value??r.value);if(!Number.isFinite(i)||i<=0)return r.tier>=4?1:0;if(!Number.isFinite(t)||t<=0)return 0;const n=r.lower_is_better?i/t:t/i;return Math.max(0,Math.min(1,n))}function S(r){const i=r?.achieved||{},t=Object.values(i).map(n=>n?Date.parse(n):NaN).filter(n=>Number.isFinite(n));return t.length>0?Math.max(...t):null}function V({achievements:r,isOwn:i=!1,scope:t,onSelect:n,size:m="xl",columns:v="default",animateIn:y=!1,className:N=""}){const k=$(),u=y&&!k,p=new Map;for(const e of Array.isArray(r)?r:[])e&&e.id&&p.set(e.id,e);const g=t?x.filter(e=>e.scope===t):x;let c;if(i){const e=g.map(a=>({entry:a,record:p.get(a.id)||{id:a.id,tier:0}})),o=b(e.filter(a=>(a.record.tier||0)>=1).map(a=>({...a,id:a.entry.id,tier:a.record.tier}))),h=e.filter(a=>(a.record.tier||0)<1);c=[...o,...h]}else c=b(g.map(e=>({entry:e,record:p.get(e.id)})).filter(e=>e.record&&(e.record.tier||0)>=1).map(e=>({...e,id:e.entry.id,tier:e.record.tier}))).map(({entry:e,record:o})=>({entry:e,record:o}));if(c.length===0)return null;const j=v==="wide"?"grid-cols-[repeat(3,max-content)] sm:grid-cols-[repeat(4,max-content)] lg:grid-cols-[repeat(5,max-content)]":"grid-cols-[repeat(3,max-content)] sm:grid-cols-[repeat(4,max-content)]",w=m==="lg"?"mx-0 sm:-mx-2":"-mx-2 sm:-mx-4",M=m==="lg"?"px-0":"px-1";return s.jsx("div",{className:`${w} grid justify-between gap-y-7 ${j} ${N}`,children:c.map(({entry:e,record:o},h)=>{const a=(o.tier||0)>=1,f=l(T(e.id,"name")),d=a?E(o.tier):null,A=H(o);return s.jsxs(C.button,{type:"button",initial:u?{opacity:0,y:16,scale:.9}:!1,animate:u?{opacity:1,y:0,scale:1}:void 0,whileTap:u?{scale:.97}:void 0,transition:{delay:.05+h*.035,duration:.45,ease:[.16,1,.3,1]},onClick:n?()=>n({...o,id:e.id}):void 0,className:`group flex w-[6.75rem] flex-col items-center rounded-xl ${M} pb-3 pt-4 text-center transition-[background-color,transform] duration-200 ease-out hover:bg-oai-gray-50 active:scale-[0.97] dark:hover:bg-oai-gray-900/70 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-oai-brand/60 sm:w-[7.75rem]`,"aria-label":l("achievements.badge.aria",{name:f,tier:d?l(`achievements.tier.${d}`):l("achievements.modal.locked")}),children:[s.jsx(B,{badgeId:e.id,tier:o.tier,locked:!a,size:m,className:"transition-transform duration-200 ease-out group-hover:-translate-y-0.5 group-hover:scale-105"}),s.jsxs("span",{className:"mt-2.5 flex w-full items-center justify-center gap-1",children:[s.jsx("span",{title:f,className:"min-w-0 truncate text-xs font-medium leading-tight text-oai-gray-800 dark:text-oai-gray-200",children:f}),e.scope==="local"&&s.jsx("span",{title:l("achievements.page.local_note"),"aria-label":l("achievements.scope.local"),className:"inline-flex shrink-0 text-oai-gray-400 dark:text-oai-gray-500",children:s.jsx(F,{size:11,strokeWidth:2,"aria-hidden":!0})})]}),s.jsx("span",{className:"mt-1 flex h-4 w-full items-center justify-center",children:a?s.jsx("span",{className:"text-[10px] font-semibold uppercase tracking-[0.08em]",style:{color:L[d]?.label},children:l(`achievements.tier.${d}`)}):i?s.jsx("span",{className:"h-[3px] w-14 overflow-hidden rounded-full bg-oai-gray-200 dark:bg-oai-gray-800",children:s.jsx("span",{className:"block h-full rounded-full bg-oai-brand/70",style:{width:`${Math.round(A*100)}%`}})}):null})]},e.id)})})}export{V as A,H as b,G as f,S as l};
1
+ import{c as _,u as $,j as s,E as l,m as C}from"./main-BbxPEfc4.js";import{B as x,s as b,b as T,t as E,A as B,T as L}from"./AchievementBadge-X9JssV2N.js";import{f as I}from"./format-tokens-Cy-5MGHS.js";const D=[["path",{d:"M10 16h.01",key:"1bzywj"}],["path",{d:"M2.212 11.577a2 2 0 0 0-.212.896V18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-5.527a2 2 0 0 0-.212-.896L18.55 5.11A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z",key:"18tbho"}],["path",{d:"M21.946 12.013H2.054",key:"zqlbp7"}],["path",{d:"M6 16h.01",key:"1pmjb7"}]],F=_("hard-drive",D);function G(r,i){const t=Number(i)||0;switch(r){case"tokens":return I(t);case"rank":return`#${Math.round(t)}`;case"multiplier":return`${(Math.round(t*10)/10).toString()}×`;default:return Math.round(t).toLocaleString()}}function H(r){if(!r)return 0;const i=Number(r.next_threshold),t=Number(r.metric_value??r.value);if(!Number.isFinite(i)||i<=0)return r.tier>=4?1:0;if(!Number.isFinite(t)||t<=0)return 0;const n=r.lower_is_better?i/t:t/i;return Math.max(0,Math.min(1,n))}function S(r){const i=r?.achieved||{},t=Object.values(i).map(n=>n?Date.parse(n):NaN).filter(n=>Number.isFinite(n));return t.length>0?Math.max(...t):null}function V({achievements:r,isOwn:i=!1,scope:t,onSelect:n,size:m="xl",columns:v="default",animateIn:y=!1,className:N=""}){const k=$(),u=y&&!k,p=new Map;for(const e of Array.isArray(r)?r:[])e&&e.id&&p.set(e.id,e);const g=t?x.filter(e=>e.scope===t):x;let c;if(i){const e=g.map(a=>({entry:a,record:p.get(a.id)||{id:a.id,tier:0}})),o=b(e.filter(a=>(a.record.tier||0)>=1).map(a=>({...a,id:a.entry.id,tier:a.record.tier}))),h=e.filter(a=>(a.record.tier||0)<1);c=[...o,...h]}else c=b(g.map(e=>({entry:e,record:p.get(e.id)})).filter(e=>e.record&&(e.record.tier||0)>=1).map(e=>({...e,id:e.entry.id,tier:e.record.tier}))).map(({entry:e,record:o})=>({entry:e,record:o}));if(c.length===0)return null;const j=v==="wide"?"grid-cols-[repeat(3,max-content)] sm:grid-cols-[repeat(4,max-content)] lg:grid-cols-[repeat(5,max-content)]":"grid-cols-[repeat(3,max-content)] sm:grid-cols-[repeat(4,max-content)]",w=m==="lg"?"mx-0 sm:-mx-2":"-mx-2 sm:-mx-4",M=m==="lg"?"px-0":"px-1";return s.jsx("div",{className:`${w} grid justify-between gap-y-7 ${j} ${N}`,children:c.map(({entry:e,record:o},h)=>{const a=(o.tier||0)>=1,f=l(T(e.id,"name")),d=a?E(o.tier):null,A=H(o);return s.jsxs(C.button,{type:"button",initial:u?{opacity:0,y:16,scale:.9}:!1,animate:u?{opacity:1,y:0,scale:1}:void 0,whileTap:u?{scale:.97}:void 0,transition:{delay:.05+h*.035,duration:.45,ease:[.16,1,.3,1]},onClick:n?()=>n({...o,id:e.id}):void 0,className:`group flex w-[6.75rem] flex-col items-center rounded-xl ${M} pb-3 pt-4 text-center transition-[background-color,transform] duration-200 ease-out hover:bg-oai-gray-50 active:scale-[0.97] dark:hover:bg-oai-gray-900/70 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-oai-brand/60 sm:w-[7.75rem]`,"aria-label":l("achievements.badge.aria",{name:f,tier:d?l(`achievements.tier.${d}`):l("achievements.modal.locked")}),children:[s.jsx(B,{badgeId:e.id,tier:o.tier,locked:!a,size:m,className:"transition-transform duration-200 ease-out group-hover:-translate-y-0.5 group-hover:scale-105"}),s.jsxs("span",{className:"mt-2.5 flex w-full items-center justify-center gap-1",children:[s.jsx("span",{title:f,className:"min-w-0 truncate text-xs font-medium leading-tight text-oai-gray-800 dark:text-oai-gray-200",children:f}),e.scope==="local"&&s.jsx("span",{title:l("achievements.page.local_note"),"aria-label":l("achievements.scope.local"),className:"inline-flex shrink-0 text-oai-gray-400 dark:text-oai-gray-500",children:s.jsx(F,{size:11,strokeWidth:2,"aria-hidden":!0})})]}),s.jsx("span",{className:"mt-1 flex h-4 w-full items-center justify-center",children:a?s.jsx("span",{className:"text-[10px] font-semibold uppercase tracking-[0.08em]",style:{color:L[d]?.label},children:l(`achievements.tier.${d}`)}):i?s.jsx("span",{className:"h-[3px] w-14 overflow-hidden rounded-full bg-oai-gray-200 dark:bg-oai-gray-800",children:s.jsx("span",{className:"block h-full rounded-full bg-oai-brand/70",style:{width:`${Math.round(A*100)}%`}})}):null})]},e.id)})})}export{V as A,H as b,G as f,S as l};
@@ -1 +1 @@
1
- import{cW as De,cX as _e,cY as Ie,cZ as Me,c_ as Te,c$ as ye,i as be,d0 as $e,d1 as Ve,d2 as Oe,d3 as Re,d4 as Pe,d5 as Be,d6 as Ke,d7 as Xe,d8 as Le,d9 as Ce,da as Fe,db as G,dc as Ge,dd as We,de as ze,df as Ye,u as Ue,r as C,j as a,m as X,$ as Ze,E as h,P as ve,X as He}from"./main-CvkyGV2H.js";import{a as je,A as qe,p as Je,b as Y,t as le,T as $,c as Qe}from"./AchievementBadge-wQQwzQYv.js";import{a as et,u as z}from"./use-transform-BW36bKb3.js";import{l as ce,f as ue,b as tt}from"./AchievementsSection-Cwgr4N8D.js";import{D as nt,a as rt,b as at,c as st,d as it,e as ot}from"./DialogTitle-B-NMBFgN.js";import"./zap-Blccuc-z.js";import"./flame-B27yR7Au.js";import"./format-tokens-B8_mvUxn.js";import"./useScrollLock-juP-sEAK.js";const lt=(e,t,n)=>{const r=t-e;return((n-e)%r+r)%r+e};function Ne(e,t){return De(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 ft extends _e{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 Ie()}build(t,n){Object.assign(t.output,n)}renderInstance(t,{output:n}){Object.assign(t,n)}sortInstanceNodePosition(){return 0}}function U(e){return typeof e=="object"&&!Array.isArray(e)}function ke(e,t,n,r){return e==null?[]:typeof e=="string"&&U(t)?Me(e,n,r):e instanceof NodeList?Array.from(e):Array.isArray(e)?e.filter(s=>s!=null):[e]}function mt(e,t,n){return e*(t+1)+n*t}function fe(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&&(ye(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:Te(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,m=new Map,f={},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,fe(u,k.at,g,p));continue}let[E,b,v={}]=k;v.at!==void 0&&(u=fe(u,v.at,g,p));let j=0;const I=(w,M,A,o=0,l=0)=>{const d=jt(w),{delay:D=0,times:y=$e(d),type:R=t.type||"keyframes",repeat:P,repeatType:W,repeatDelay:Z=0,...Se}=M;let{ease:_=t.ease||"easeOut",duration:S}=M;const H=typeof D=="function"?D(o,l):D,q=d.length,J=Pe(R)?R:s?.[R||"keyframes"];if(q<=2&&J){let V=100;if(q===2&&wt(d)){const B=d[1]-d[0];V=Math.abs(B)}const O={...t,...Se};S!==void 0&&(O.duration=Be(S));const F=Ve(O,V,J);_=F.ease,S=F.duration}S??(S=c);const Q=u+H;y.length===1&&y[0]===0&&(y[1]=1);const ee=y.length-d.length;if(ee>0&&Oe(y,ee),d.length===1&&d.unshift(null),P&&P<bt){const V=S>0?Z/S:0;S=mt(S,P,Z);const O=[...d],F=[...y];_=Array.isArray(_)?[..._]:[_];const B=[..._],ne=W==="reverse"||W==="mirror";let re=O,ae=B;ne&&(re=[...O].reverse(),W==="reverse"&&(ae=[...B].reverse().map(T=>typeof T=="function"?Re(T):T)));for(let T=0;T<P;T++){const se=ne&&T%2===0,ie=se?re:O,Ee=se?ae:B,oe=(T+1)*(1+V);V>0&&(d.push(d[d.length-1]),y.push(oe),_.push("linear")),d.push(...ie);for(let K=0;K<ie.length;K++)y.push(F[K]+oe),_.push(K===0?"linear":Ne(Ee,K-1))}gt(y,P,V)}const te=Q+S;ht(A,d,_,y,Q,te),j=Math.max(H+S,j),x=Math.max(te,x)};if(be(E)){const w=me(E,m);I(b,v,pe("default",w))}else{const w=ke(E,b,r,f),M=w.length;for(let A=0;A<M;A++){b=b,v=v;const o=w[A],l=me(o,m);for(const d in b)I(b[d],Nt(v,d),pe(d,l),A,M)}}g=u,u+=j}return m.forEach((N,k)=>{for(const E in N){const b=N[E];b.sort(xt);const v=[],j=[],I=[];for(let o=0;o<b.length;o++){const{at:l,value:d,easing:D}=b[o];v.push(d),j.push(Ke(0,x,l)),I.push(D||"easeOut")}j[0]!==0&&(j.unshift(0),v.unshift(v[0]),I.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:I,times:j,...n}}}),i}function me(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=Xe(e)&&!Le(e)?new Ce(t):new Fe(t);n.mount(e),G.set(e,n)}function St(e){const t={presenceContext:null,props:{},visualState:{renderState:{output:{}},latestValues:{}}},n=new ft(t);n.mount(e),G.set(e,n)}function Et(e,t){return be(e)||typeof e=="number"||typeof e=="string"&&!U(t)}function we(e,t,n,r){const s=[];if(Et(e,t))s.push(Ge(e,U(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 m=0;m<i;m++){const f=c[m],p=f instanceof Element?At:St;G.has(f)||p(f);const g=G.get(f),u={...n};"delay"in u&&typeof u.delay=="function"&&(u.delay=u.delay(m,i)),s.push(...We(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 m=i[0],f=ze(0);return f.on("change",m),i.length===1?[f,[0,1]]:i.length===2?[f,[0,1],i[1]]:[f,i[1],i[2]]}return i});return vt(s,t,n,{spring:Ye}).forEach(({keyframes:i,transition:m},f)=>{r.push(...we(f,i,m))}),r}function _t(e){return Array.isArray(e)&&e.some(Array.isArray)}function It(e={}){const{scope:t,reduceMotion:n,skipAnimations:r}=e;function s(c,i,m){let f=[],p;const g={};if(n!==void 0&&(g.reduceMotion=n),r!==void 0&&(g.skipAnimations=r),_t(c)){const{onComplete:x,...N}=i||{};typeof x=="function"&&(p=x),f=Dt(c,{...g,...N},t)}else{const{onComplete:x,...N}=m||{};typeof x=="function"&&(p=x),f=we(c,i,{...g,...N},t)}const u=new ut(f);return p&&u.finished.then(p),t&&(t.animations.push(u),u.finished.then(()=>{ye(t.animations,u)})),u}return s}const L=It(),he=8;function Mt({badgeId:e,tier:t,locked:n=!1,size:r=176,backLines:s=[],label:c}){const i=et(0),m=Ue(),f=C.useRef(null),p=C.useRef(null),g=C.useRef(!1),u=Je(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};C.useEffect(()=>{if(m||g.current)return;let o=!1;i.set(-360);const l=L(i,0,{duration:.9,ease:[.16,1,.3,1]});return p.current=l,l.then(()=>{o||g.current||(p.current=L(i,[0,-14,14,0],{duration:4.5,repeat:1/0,ease:"easeInOut"}))}),()=>{o=!0,b()}},[m,i]);const v=o=>{const l=i.get();if(m){const y=Math.round(l/180)*180;p.current=L(i,y,{duration:.2,ease:"easeOut"});return}const d=l+o*.35,D=Math.round(d/180)*180;p.current=L(i,D,{type:"spring",velocity:o,stiffness:58,damping:13.5,mass:1})},j=o=>{g.current=!0,b(),o.currentTarget.setPointerCapture?.(o.pointerId),f.current={pointerId:o.pointerId,startX:o.clientX,startRot:i.get(),samples:[{t:o.timeStamp,x:o.clientX}]}},I=o=>{const l=f.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=f.current;if(!l||l.pointerId!==o.pointerId)return;f.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=L(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:I,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(X.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(qe,{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(X.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(X.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(X.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(X.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 Tt(e){const t=Number(e);return!Number.isSafeInteger(t)||t<1?null:String(t).padStart(6,"0")}function $t(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 Vt({badge:e}){return a.jsx("div",{className:"flex items-center gap-1",children:Qe.map((t,n)=>{const r=(e.tier||0)>=n+1,s=Ae(e.achieved?.[t]),c=$[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(Y(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),m=ue(n?.format,e.metric_value),f=tt(e),p=e.tier<4?le((e.tier||0)+1):null,g=$t(e,n,c),u=Tt(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?m:"···",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(Y(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(He,{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, ${$[c].rim[0]} 0%, ${$[c].ring} 55%, ${$[c].rim[1]} 100%)`,color:$[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:m})]}),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:[m," ",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:f)*100)}%`,background:s?`linear-gradient(90deg, ${$[c].rim[0]} 0%, ${$[c].ring} 55%, ${$[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(Vt,{badge:e})]})]})]})}const xe=ve("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 Gt({badge:e,onClose:t}){const n=Ze(),r=!!e;return C.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:ve("cost-modal-popup",xe),children:[a.jsx(ot,{render:a.jsx("h2",{className:"sr-only"}),children:h(Y(e.id,"name"))}),a.jsx(ge,{badge:e,onClose:t})]})})]})}):null}export{Gt as BadgeDetailModal,$t as currentBadgeIssueNumber,Gt as default,Tt as formatIssueNumber};
1
+ import{cW as De,cX as _e,cY as Ie,cZ as Me,c_ as Te,c$ as ye,i as be,d0 as $e,d1 as Ve,d2 as Oe,d3 as Re,d4 as Pe,d5 as Be,d6 as Ke,d7 as Xe,d8 as Le,d9 as Ce,da as Fe,db as G,dc as Ge,dd as We,de as ze,df as Ye,u as Ue,r as C,j as a,m as X,$ as Ze,E as h,P as ve,X as He}from"./main-BbxPEfc4.js";import{a as je,A as qe,p as Je,b as Y,t as le,T as $,c as Qe}from"./AchievementBadge-X9JssV2N.js";import{a as et,u as z}from"./use-transform-YviydTql.js";import{l as ce,f as ue,b as tt}from"./AchievementsSection-dPW0TScn.js";import{D as nt,a as rt,b as at,c as st,d as it,e as ot}from"./DialogTitle-D_V-kvKQ.js";import"./zap-CnEr_e6T.js";import"./flame-Wz7IYxjy.js";import"./format-tokens-Cy-5MGHS.js";import"./useScrollLock-h9pnSauU.js";const lt=(e,t,n)=>{const r=t-e;return((n-e)%r+r)%r+e};function Ne(e,t){return De(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 ft extends _e{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 Ie()}build(t,n){Object.assign(t.output,n)}renderInstance(t,{output:n}){Object.assign(t,n)}sortInstanceNodePosition(){return 0}}function U(e){return typeof e=="object"&&!Array.isArray(e)}function ke(e,t,n,r){return e==null?[]:typeof e=="string"&&U(t)?Me(e,n,r):e instanceof NodeList?Array.from(e):Array.isArray(e)?e.filter(s=>s!=null):[e]}function mt(e,t,n){return e*(t+1)+n*t}function fe(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&&(ye(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:Te(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,m=new Map,f={},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,fe(u,k.at,g,p));continue}let[E,b,v={}]=k;v.at!==void 0&&(u=fe(u,v.at,g,p));let j=0;const I=(w,M,A,o=0,l=0)=>{const d=jt(w),{delay:D=0,times:y=$e(d),type:R=t.type||"keyframes",repeat:P,repeatType:W,repeatDelay:Z=0,...Se}=M;let{ease:_=t.ease||"easeOut",duration:S}=M;const H=typeof D=="function"?D(o,l):D,q=d.length,J=Pe(R)?R:s?.[R||"keyframes"];if(q<=2&&J){let V=100;if(q===2&&wt(d)){const B=d[1]-d[0];V=Math.abs(B)}const O={...t,...Se};S!==void 0&&(O.duration=Be(S));const F=Ve(O,V,J);_=F.ease,S=F.duration}S??(S=c);const Q=u+H;y.length===1&&y[0]===0&&(y[1]=1);const ee=y.length-d.length;if(ee>0&&Oe(y,ee),d.length===1&&d.unshift(null),P&&P<bt){const V=S>0?Z/S:0;S=mt(S,P,Z);const O=[...d],F=[...y];_=Array.isArray(_)?[..._]:[_];const B=[..._],ne=W==="reverse"||W==="mirror";let re=O,ae=B;ne&&(re=[...O].reverse(),W==="reverse"&&(ae=[...B].reverse().map(T=>typeof T=="function"?Re(T):T)));for(let T=0;T<P;T++){const se=ne&&T%2===0,ie=se?re:O,Ee=se?ae:B,oe=(T+1)*(1+V);V>0&&(d.push(d[d.length-1]),y.push(oe),_.push("linear")),d.push(...ie);for(let K=0;K<ie.length;K++)y.push(F[K]+oe),_.push(K===0?"linear":Ne(Ee,K-1))}gt(y,P,V)}const te=Q+S;ht(A,d,_,y,Q,te),j=Math.max(H+S,j),x=Math.max(te,x)};if(be(E)){const w=me(E,m);I(b,v,pe("default",w))}else{const w=ke(E,b,r,f),M=w.length;for(let A=0;A<M;A++){b=b,v=v;const o=w[A],l=me(o,m);for(const d in b)I(b[d],Nt(v,d),pe(d,l),A,M)}}g=u,u+=j}return m.forEach((N,k)=>{for(const E in N){const b=N[E];b.sort(xt);const v=[],j=[],I=[];for(let o=0;o<b.length;o++){const{at:l,value:d,easing:D}=b[o];v.push(d),j.push(Ke(0,x,l)),I.push(D||"easeOut")}j[0]!==0&&(j.unshift(0),v.unshift(v[0]),I.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:I,times:j,...n}}}),i}function me(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=Xe(e)&&!Le(e)?new Ce(t):new Fe(t);n.mount(e),G.set(e,n)}function St(e){const t={presenceContext:null,props:{},visualState:{renderState:{output:{}},latestValues:{}}},n=new ft(t);n.mount(e),G.set(e,n)}function Et(e,t){return be(e)||typeof e=="number"||typeof e=="string"&&!U(t)}function we(e,t,n,r){const s=[];if(Et(e,t))s.push(Ge(e,U(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 m=0;m<i;m++){const f=c[m],p=f instanceof Element?At:St;G.has(f)||p(f);const g=G.get(f),u={...n};"delay"in u&&typeof u.delay=="function"&&(u.delay=u.delay(m,i)),s.push(...We(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 m=i[0],f=ze(0);return f.on("change",m),i.length===1?[f,[0,1]]:i.length===2?[f,[0,1],i[1]]:[f,i[1],i[2]]}return i});return vt(s,t,n,{spring:Ye}).forEach(({keyframes:i,transition:m},f)=>{r.push(...we(f,i,m))}),r}function _t(e){return Array.isArray(e)&&e.some(Array.isArray)}function It(e={}){const{scope:t,reduceMotion:n,skipAnimations:r}=e;function s(c,i,m){let f=[],p;const g={};if(n!==void 0&&(g.reduceMotion=n),r!==void 0&&(g.skipAnimations=r),_t(c)){const{onComplete:x,...N}=i||{};typeof x=="function"&&(p=x),f=Dt(c,{...g,...N},t)}else{const{onComplete:x,...N}=m||{};typeof x=="function"&&(p=x),f=we(c,i,{...g,...N},t)}const u=new ut(f);return p&&u.finished.then(p),t&&(t.animations.push(u),u.finished.then(()=>{ye(t.animations,u)})),u}return s}const L=It(),he=8;function Mt({badgeId:e,tier:t,locked:n=!1,size:r=176,backLines:s=[],label:c}){const i=et(0),m=Ue(),f=C.useRef(null),p=C.useRef(null),g=C.useRef(!1),u=Je(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};C.useEffect(()=>{if(m||g.current)return;let o=!1;i.set(-360);const l=L(i,0,{duration:.9,ease:[.16,1,.3,1]});return p.current=l,l.then(()=>{o||g.current||(p.current=L(i,[0,-14,14,0],{duration:4.5,repeat:1/0,ease:"easeInOut"}))}),()=>{o=!0,b()}},[m,i]);const v=o=>{const l=i.get();if(m){const y=Math.round(l/180)*180;p.current=L(i,y,{duration:.2,ease:"easeOut"});return}const d=l+o*.35,D=Math.round(d/180)*180;p.current=L(i,D,{type:"spring",velocity:o,stiffness:58,damping:13.5,mass:1})},j=o=>{g.current=!0,b(),o.currentTarget.setPointerCapture?.(o.pointerId),f.current={pointerId:o.pointerId,startX:o.clientX,startRot:i.get(),samples:[{t:o.timeStamp,x:o.clientX}]}},I=o=>{const l=f.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=f.current;if(!l||l.pointerId!==o.pointerId)return;f.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=L(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:I,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(X.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(qe,{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(X.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(X.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(X.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(X.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 Tt(e){const t=Number(e);return!Number.isSafeInteger(t)||t<1?null:String(t).padStart(6,"0")}function $t(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 Vt({badge:e}){return a.jsx("div",{className:"flex items-center gap-1",children:Qe.map((t,n)=>{const r=(e.tier||0)>=n+1,s=Ae(e.achieved?.[t]),c=$[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(Y(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),m=ue(n?.format,e.metric_value),f=tt(e),p=e.tier<4?le((e.tier||0)+1):null,g=$t(e,n,c),u=Tt(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?m:"···",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(Y(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(He,{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, ${$[c].rim[0]} 0%, ${$[c].ring} 55%, ${$[c].rim[1]} 100%)`,color:$[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:m})]}),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:[m," ",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:f)*100)}%`,background:s?`linear-gradient(90deg, ${$[c].rim[0]} 0%, ${$[c].ring} 55%, ${$[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(Vt,{badge:e})]})]})]})}const xe=ve("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 Gt({badge:e,onClose:t}){const n=Ze(),r=!!e;return C.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:ve("cost-modal-popup",xe),children:[a.jsx(ot,{render:a.jsx("h2",{className:"sr-only"}),children:h(Y(e.id,"name"))}),a.jsx(ge,{badge:e,onClose:t})]})})]})}):null}export{Gt as BadgeDetailModal,$t as currentBadgeIssueNumber,Gt as default,Tt as formatIssueNumber};