tokentracker-cli 0.84.7 → 0.84.9

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 (95) hide show
  1. package/dashboard/dist/assets/{AchievementBadge-DAPsTMsx.js → AchievementBadge-BgBFpxmU.js} +1 -1
  2. package/dashboard/dist/assets/{AchievementsPage-B9oXfXvm.js → AchievementsPage-DHPD3Fnu.js} +2 -2
  3. package/dashboard/dist/assets/{AchievementsSection-DI_LTZb3.js → AchievementsSection-DouWVD-3.js} +1 -1
  4. package/dashboard/dist/assets/{BadgeDetailModal--WCrJWVa.js → BadgeDetailModal-Df9eQiA3.js} +1 -1
  5. package/dashboard/dist/assets/{Card-BzbSN3EC.js → Card-CQ9wBnz6.js} +1 -1
  6. package/dashboard/dist/assets/{ClawdAnimated-Dgxae1At.js → ClawdAnimated-XIO-I-5v.js} +1 -1
  7. package/dashboard/dist/assets/{CommandPalette-BiZBYV5A.js → CommandPalette-Cy1cJ91B.js} +1 -1
  8. package/dashboard/dist/assets/{CommunityStatsModal-C6jZx10_.js → CommunityStatsModal-CwKG4LQM.js} +1 -1
  9. package/dashboard/dist/assets/{ConfirmModal-lD-mHMvO.js → ConfirmModal-BNcWqick.js} +1 -1
  10. package/dashboard/dist/assets/{DashboardPage-DCPNoiRG.js → DashboardPage-Dns_1yXL.js} +1 -1
  11. package/dashboard/dist/assets/{DevicePage-DiF2IOjJ.js → DevicePage-pJ2jNkZV.js} +1 -1
  12. package/dashboard/dist/assets/{DialogClose-Crx2EFnI.js → DialogClose-C2SOtkJN.js} +1 -1
  13. package/dashboard/dist/assets/DialogDescription-Bhfqqmll.js +1 -0
  14. package/dashboard/dist/assets/{DialogTitle-amHXttsp.js → DialogTitle-CGSbB8G7.js} +1 -1
  15. package/dashboard/dist/assets/{FadeIn-CIhF_9PP.js → FadeIn-CZSiw7me.js} +1 -1
  16. package/dashboard/dist/assets/{HeaderGithubStar-D6Ph2GuY.js → HeaderGithubStar-ZmQhX_kR.js} +1 -1
  17. package/dashboard/dist/assets/{HoverTooltip-BS8eO6tj.js → HoverTooltip-D_YdG369.js} +1 -1
  18. package/dashboard/dist/assets/{IpCheckPage-Cz1Je6WS.js → IpCheckPage-du886dF0.js} +1 -1
  19. package/dashboard/dist/assets/{LandingPage-DqeXJfwn.js → LandingPage-BuAak8lU.js} +2 -2
  20. package/dashboard/dist/assets/{LeaderboardAvatar-D09yLoVA.js → LeaderboardAvatar-nU0ARYnN.js} +1 -1
  21. package/dashboard/dist/assets/{LeaderboardPage-BetpFetS.js → LeaderboardPage-CngwCvC7.js} +2 -2
  22. package/dashboard/dist/assets/{LeaderboardProfileModal-UW3KnANZ.js → LeaderboardProfileModal-CXZJ0e-T.js} +3 -3
  23. package/dashboard/dist/assets/{LeaderboardProfilePage-Chd_2AVY.js → LeaderboardProfilePage-CZve6s6b.js} +1 -1
  24. package/dashboard/dist/assets/LimitsPage-CWvoJPk8.js +4 -0
  25. package/dashboard/dist/assets/{LocalOnlyNotice-CpFFX8ro.js → LocalOnlyNotice-DyUAAyyE.js} +1 -1
  26. package/dashboard/dist/assets/{LoginCard-DkZpGnVu.js → LoginCard-eEiRfbdv.js} +1 -1
  27. package/dashboard/dist/assets/{LoginModal-CALv6jkD.js → LoginModal-C16WdIQm.js} +1 -1
  28. package/dashboard/dist/assets/{LoginPage-BZuXHYAT.js → LoginPage-B2WqpE1t.js} +1 -1
  29. package/dashboard/dist/assets/{PetPage-C1LuDyYr.js → PetPage-DtQWrGmI.js} +1 -1
  30. package/dashboard/dist/assets/{PopoverPopup-CluVhrMr.js → PopoverPopup-CRhqtFLB.js} +1 -1
  31. package/dashboard/dist/assets/{ProviderIcon-D3YKjVKb.js → ProviderIcon-DWNH_wYu.js} +1 -1
  32. package/dashboard/dist/assets/{ResetPasswordPage-CzN50nX5.js → ResetPasswordPage-DzCczcWZ.js} +1 -1
  33. package/dashboard/dist/assets/{SegmentedControl-DFOAcEKU.js → SegmentedControl-CV9ccq6R.js} +1 -1
  34. package/dashboard/dist/assets/{Select-B3W_ihs_.js → Select-BrogNNk0.js} +1 -1
  35. package/dashboard/dist/assets/{SelectItemText-FXRtXnFV.js → SelectItemText-Bpu3swt0.js} +1 -1
  36. package/dashboard/dist/assets/{ServiceStatusPage-BItZqH7q.js → ServiceStatusPage-D_FIrMJP.js} +1 -1
  37. package/dashboard/dist/assets/{SessionsPage-DVQU-hTH.js → SessionsPage-C8TvTy1o.js} +1 -1
  38. package/dashboard/dist/assets/{SettingsPage-ByvrwOi6.js → SettingsPage-Bd-tzJAR.js} +1 -1
  39. package/dashboard/dist/assets/{SkillsPage-DrGr5Qij.js → SkillsPage-CKGU9wQ4.js} +1 -1
  40. package/dashboard/dist/assets/{TokenGalaxy-ClF_n9od.js → TokenGalaxy-DhHW6L-U.js} +1 -1
  41. package/dashboard/dist/assets/{ToolbarRootContext-B82hGhAf.js → ToolbarRootContext-DQo-4pPB.js} +1 -1
  42. package/dashboard/dist/assets/{TrendMonitor-DkWm7_1z.js → TrendMonitor-Ejl8d45g.js} +1 -1
  43. package/dashboard/dist/assets/{WidgetsPage-DCY4pyR2.js → WidgetsPage-CY7f4wCD.js} +1 -1
  44. package/dashboard/dist/assets/{WrappedPage-yGQ4DLqj.js → WrappedPage-B4-B2v-v.js} +1 -1
  45. package/dashboard/dist/assets/{__vite-browser-external-BdRrPLk6.js → __vite-browser-external-BNUFXCfp.js} +4 -3
  46. package/dashboard/dist/assets/{agent-logos-D5SHGOxB.js → agent-logos-BRzutmeR.js} +1 -1
  47. package/dashboard/dist/assets/{arrow-up-right-CbMcAcss.js → arrow-up-right-BcrbPk8c.js} +1 -1
  48. package/dashboard/dist/assets/{check-Dyzh7lTz.js → check-BMxeFPfQ.js} +1 -1
  49. package/dashboard/dist/assets/{chevron-right-DT06ZIKC.js → chevron-right-DOstgiRf.js} +1 -1
  50. package/dashboard/dist/assets/{copy-B3Kt3Wrf.js → copy-BsKO524t.js} +1 -1
  51. package/dashboard/dist/assets/{download-B3rOytqI.js → download-dadqxej7.js} +1 -1
  52. package/dashboard/dist/assets/{external-link-BamTP0Ks.js → external-link-CTu3BMeU.js} +1 -1
  53. package/dashboard/dist/assets/{flame-msy2h1ms.js → flame-B_IvWcMn.js} +1 -1
  54. package/dashboard/dist/assets/{format-tokens-8b1OUM_8.js → format-tokens-DIT6hLSb.js} +1 -1
  55. package/dashboard/dist/assets/{icons-C2NR2_Tf.js → icons-mWku76bu.js} +1 -1
  56. package/dashboard/dist/assets/{index-CvTfpiCF.js → index-CboN9E82.js} +1 -1
  57. package/dashboard/dist/assets/{index-x3vFJQFt.js → index-D-gQV-hF.js} +1 -1
  58. package/dashboard/dist/assets/{index-C8sDJzUY.js → index-D5-w-aGy.js} +1 -1
  59. package/dashboard/dist/assets/{info-C9j23aGq.js → info-x6l352SW.js} +1 -1
  60. package/dashboard/dist/assets/{limits-providers-ySB9Ci5l.js → limits-providers-Bo12VlLJ.js} +1 -1
  61. package/dashboard/dist/assets/{link-2-rrcyTT6S.js → link-2-eo_xPxH1.js} +1 -1
  62. package/dashboard/dist/assets/{loader-circle-x9x9I8Hv.js → loader-circle-C4n1iGBv.js} +1 -1
  63. package/dashboard/dist/assets/{maximize-2-7TWFb2k7.js → maximize-2-pR8xwsI_.js} +1 -1
  64. package/dashboard/dist/assets/{provider-display-JbSwpvxU.js → provider-display-ErggQWu4.js} +1 -1
  65. package/dashboard/dist/assets/{react-DK5clHtY.js → react-DYKg02Aq.js} +1 -1
  66. package/dashboard/dist/assets/{search-DukXRvEV.js → search-B_jbUwPS.js} +1 -1
  67. package/dashboard/dist/assets/{skills-api-BUFJuwiR.js → skills-api-DY5ruGmw.js} +1 -1
  68. package/dashboard/dist/assets/{store-BTh7bv09.js → store-Cu8i1y26.js} +1 -1
  69. package/dashboard/dist/assets/{terminal-CcUqLtn1.js → terminal-D3j6X68s.js} +1 -1
  70. package/dashboard/dist/assets/{trash-2-Bq7hnvNq.js → trash-2-CFpwgJw5.js} +1 -1
  71. package/dashboard/dist/assets/{use-community-stats-qTpx6ugG.js → use-community-stats-C0fKq66G.js} +1 -1
  72. package/dashboard/dist/assets/{use-limits-display-prefs-Di_J4eVv.js → use-limits-display-prefs-TOp4UAnI.js} +1 -1
  73. package/dashboard/dist/assets/{use-native-settings-CIqpv9Z3.js → use-native-settings-BZie_7z1.js} +1 -1
  74. package/dashboard/dist/assets/{use-ordered-list-OwogSXT7.js → use-ordered-list-Bq92YyUp.js} +1 -1
  75. package/dashboard/dist/assets/use-reduced-motion-ZiVeOkvb.js +1 -0
  76. package/dashboard/dist/assets/{use-session-efficiency-pref-CjAvMh7u.js → use-session-efficiency-pref-BcpytkES.js} +1 -1
  77. package/dashboard/dist/assets/{use-transform-KZLdt-NZ.js → use-transform-Dmmrne2z.js} +1 -1
  78. package/dashboard/dist/assets/use-usage-limits-Cw0Z9Tew.js +1 -0
  79. package/dashboard/dist/assets/{useCurrency-D2td-bkn.js → useCurrency-DyyonINj.js} +1 -1
  80. package/dashboard/dist/assets/{useScrollLock-Cvyfyezc.js → useScrollLock-DvWw86lJ.js} +1 -1
  81. package/dashboard/dist/assets/{useTokenFormat-DYIUS6IH.js → useTokenFormat-CBkvGfJ1.js} +1 -1
  82. package/dashboard/dist/assets/{zap-B19mEed5.js → zap-CnYA39Ug.js} +1 -1
  83. package/dashboard/dist/index.html +1 -1
  84. package/dashboard/dist/ip-check.html +1 -1
  85. package/dashboard/dist/leaderboard.html +1 -1
  86. package/dashboard/dist/share.html +1 -1
  87. package/package.json +1 -1
  88. package/src/lib/pricing/seed-snapshot.json +1 -1
  89. package/src/lib/qoder-limits.js +2 -205
  90. package/src/lib/rollout.js +146 -12
  91. package/src/lib/usage-limits.js +47 -3
  92. package/dashboard/dist/assets/DialogDescription-CHsHo924.js +0 -1
  93. package/dashboard/dist/assets/LimitsPage-uhpNteXJ.js +0 -4
  94. package/dashboard/dist/assets/use-reduced-motion-5QGGPoom.js +0 -1
  95. package/dashboard/dist/assets/use-usage-limits-Tbifa037.js +0 -1
@@ -1,16 +1,10 @@
1
1
  "use strict";
2
2
 
3
- const cp = require("node:child_process");
4
3
  const crypto = require("node:crypto");
5
4
  const fs = require("node:fs");
6
5
  const net = require("node:net");
7
6
  const os = require("node:os");
8
7
  const path = require("node:path");
9
- const { promisify } = require("node:util");
10
-
11
- const { readSqliteJsonRowsAsync } = require("./sqlite-reader");
12
-
13
- const execFileAsync = promisify(cp.execFile);
14
8
 
15
9
  const QODER_SITES = {
16
10
  international: {
@@ -50,53 +44,6 @@ MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA8iMH5c02LilrsERw9t6Pv5Nc
50
44
  XcW+ML9FoCI6AOvOzwIDAQAB
51
45
  -----END PUBLIC KEY-----`;
52
46
 
53
- const MACOS_CHROMIUM_BROWSERS = [
54
- {
55
- name: "Google Chrome",
56
- root: ["Library", "Application Support", "Google", "Chrome"],
57
- service: "Chrome Safe Storage",
58
- account: "Chrome",
59
- },
60
- {
61
- name: "Brave",
62
- root: ["Library", "Application Support", "BraveSoftware", "Brave-Browser"],
63
- service: "Brave Safe Storage",
64
- account: "Brave",
65
- },
66
- {
67
- name: "Microsoft Edge",
68
- root: ["Library", "Application Support", "Microsoft Edge"],
69
- service: "Microsoft Edge Safe Storage",
70
- account: "Microsoft Edge",
71
- },
72
- {
73
- name: "Arc",
74
- root: ["Library", "Application Support", "Arc", "User Data"],
75
- service: "Arc Safe Storage",
76
- account: "Arc",
77
- },
78
- {
79
- name: "Chromium",
80
- root: ["Library", "Application Support", "Chromium"],
81
- service: "Chromium Safe Storage",
82
- account: "Chromium",
83
- },
84
- ];
85
-
86
- const CHROMIUM_COOKIE_SQL = `
87
- SELECT
88
- host_key,
89
- name,
90
- value,
91
- hex(encrypted_value) AS encrypted_hex
92
- FROM cookies
93
- WHERE lower(host_key) IN (
94
- '.qoder.com', 'qoder.com', 'www.qoder.com',
95
- '.qoder.com.cn', 'qoder.com.cn', 'www.qoder.com.cn'
96
- )
97
- ORDER BY host_key, name
98
- `;
99
-
100
47
  function finiteNumber(value, field) {
101
48
  const number = Number(value);
102
49
  if (!Number.isFinite(number)) {
@@ -550,147 +497,6 @@ async function fetchQoderActivity(authStatus, fetchImpl = fetch, options = {}) {
550
497
  return normalizeQoderActivityResponse(await response.json(), options);
551
498
  }
552
499
 
553
- function normalizeCookieDomain(hostKey) {
554
- return String(hostKey || "").trim().toLowerCase().replace(/^\./, "");
555
- }
556
-
557
- function decryptChromiumCookie({ encryptedHex, plaintextValue, hostKey, password }) {
558
- if (typeof plaintextValue === "string" && plaintextValue) return plaintextValue;
559
- if (!encryptedHex || !password) return null;
560
- let encrypted;
561
- try {
562
- encrypted = Buffer.from(encryptedHex, "hex");
563
- } catch (_error) {
564
- return null;
565
- }
566
- if (encrypted.length <= 3) return null;
567
- const version = encrypted.subarray(0, 3).toString("ascii");
568
- if (version !== "v10" && version !== "v11") return null;
569
-
570
- try {
571
- const key = crypto.pbkdf2Sync(password, "saltysalt", 1003, 16, "sha1");
572
- const decipher = crypto.createDecipheriv(
573
- "aes-128-cbc",
574
- key,
575
- Buffer.alloc(16, 0x20),
576
- );
577
- let decrypted = Buffer.concat([
578
- decipher.update(encrypted.subarray(3)),
579
- decipher.final(),
580
- ]);
581
- const hostDigest = crypto.createHash("sha256").update(String(hostKey || "")).digest();
582
- if (decrypted.length >= hostDigest.length && decrypted.subarray(0, 32).equals(hostDigest)) {
583
- decrypted = decrypted.subarray(32);
584
- }
585
- const value = decrypted.toString("utf8");
586
- return value || null;
587
- } catch (_error) {
588
- return null;
589
- }
590
- }
591
-
592
- async function readMacosSafeStoragePassword({
593
- service,
594
- account,
595
- securityRunner,
596
- } = {}) {
597
- const runner = securityRunner || (async (args) => {
598
- const result = await execFileAsync("/usr/bin/security", args, {
599
- timeout: 5000,
600
- maxBuffer: 1024 * 1024,
601
- });
602
- return result.stdout;
603
- });
604
- try {
605
- const output = await runner([
606
- "find-generic-password",
607
- "-w",
608
- "-s",
609
- service,
610
- "-a",
611
- account,
612
- ]);
613
- const password = String(output || "").trim();
614
- return password || null;
615
- } catch (_error) {
616
- return null;
617
- }
618
- }
619
-
620
- function chromiumProfileDirs(browserRoot) {
621
- if (!fs.existsSync(browserRoot)) return [];
622
- let entries = [];
623
- try {
624
- entries = fs.readdirSync(browserRoot, { withFileTypes: true });
625
- } catch (_error) {
626
- return [];
627
- }
628
- return entries
629
- .filter((entry) => entry.isDirectory() && (entry.name === "Default" || /^Profile \d+$/.test(entry.name)))
630
- .map((entry) => path.join(browserRoot, entry.name))
631
- .filter((profileDir) => fs.existsSync(path.join(profileDir, "Cookies")));
632
- }
633
-
634
- function cookieHeaderFromRows(rows, password, site) {
635
- const pairs = [];
636
- for (const row of Array.isArray(rows) ? rows : []) {
637
- const domain = normalizeCookieDomain(row?.host_key);
638
- if (!site.domains.has(domain)) continue;
639
- const name = typeof row?.name === "string" ? row.name.trim() : "";
640
- if (!name) continue;
641
- const value = decryptChromiumCookie({
642
- encryptedHex: row.encrypted_hex,
643
- plaintextValue: row.value,
644
- hostKey: row.host_key,
645
- password,
646
- });
647
- if (value) pairs.push(`${name}=${value}`);
648
- }
649
- return pairs.length > 0 ? pairs.join("; ") : null;
650
- }
651
-
652
- async function importMacosQoderSessions({
653
- home = os.homedir(),
654
- platform = process.platform,
655
- securityRunner,
656
- sqliteReader = readSqliteJsonRowsAsync,
657
- } = {}) {
658
- if (platform !== "darwin") return [];
659
- const sessions = [];
660
- for (const browser of MACOS_CHROMIUM_BROWSERS) {
661
- const browserRoot = path.join(home, ...browser.root);
662
- const profiles = chromiumProfileDirs(browserRoot);
663
- if (profiles.length === 0) continue;
664
- const password = await readMacosSafeStoragePassword({
665
- service: browser.service,
666
- account: browser.account,
667
- securityRunner,
668
- });
669
- if (!password) continue;
670
- for (const profileDir of profiles) {
671
- let rows;
672
- try {
673
- rows = await sqliteReader(path.join(profileDir, "Cookies"), CHROMIUM_COOKIE_SQL, {
674
- label: `${browser.name} cookies`,
675
- });
676
- } catch (_error) {
677
- continue;
678
- }
679
- for (const site of Object.values(QODER_SITES)) {
680
- const cookieHeader = cookieHeaderFromRows(rows, password, site);
681
- if (cookieHeader) {
682
- sessions.push({
683
- cookieHeader,
684
- site,
685
- sourceLabel: `${browser.name} ${path.basename(profileDir)}`,
686
- });
687
- }
688
- }
689
- }
690
- }
691
- return sessions;
692
- }
693
-
694
500
  function qoderRequestHeaders(cookieHeader, site) {
695
501
  return {
696
502
  Cookie: cookieHeader,
@@ -834,8 +640,6 @@ async function fetchQoderLimits({
834
640
  home = os.homedir(),
835
641
  env = process.env,
836
642
  platform = process.platform,
837
- securityRunner,
838
- sqliteReader,
839
643
  fetchImpl = fetch,
840
644
  rpcRequest = qoderRpcRequest,
841
645
  nowMs = Date.now(),
@@ -884,10 +688,7 @@ async function fetchQoderLimits({
884
688
  }
885
689
 
886
690
  // Match the Antigravity last-good behavior: once the local service is
887
- // unavailable, prefer a bounded disk snapshot before attempting the much
888
- // slower browser-cookie fallback. On macOS, probing Chromium profiles may
889
- // involve multiple Keychain reads; letting those run first can consume the
890
- // provider timeout and make a perfectly valid cache look intermittent.
691
+ // unavailable, prefer a bounded disk snapshot before any provider fallback.
891
692
  const cachedLimits = readQoderLimitsCache({ home, nowMs });
892
693
  if (cachedLimits) {
893
694
  if (activityWindow) cachedLimits.secondary_window = activityWindow;
@@ -897,7 +698,7 @@ async function fetchQoderLimits({
897
698
  const manualCookie = typeof env.QODER_COOKIE === "string" ? env.QODER_COOKIE.trim() : "";
898
699
  const sessions = manualCookie
899
700
  ? [{ cookieHeader: manualCookie, site: siteFromEnv(env.QODER_SITE), sourceLabel: "QODER_COOKIE" }]
900
- : await importMacosQoderSessions({ home, platform, securityRunner, sqliteReader });
701
+ : [];
901
702
 
902
703
  let lastError = null;
903
704
  for (const session of sessions) {
@@ -963,13 +764,9 @@ async function fetchQoderLimits({
963
764
 
964
765
  module.exports = {
965
766
  QODER_SITES,
966
- CHROMIUM_COOKIE_SQL,
967
767
  normalizeQoderUsageResponse,
968
768
  normalizeQoderRpcUsage,
969
769
  normalizeQoderActivityResponse,
970
- decryptChromiumCookie,
971
- cookieHeaderFromRows,
972
- importMacosQoderSessions,
973
770
  qoderRequestHeaders,
974
771
  fetchQoderUsage,
975
772
  qoderRpcRequest,
@@ -5,7 +5,7 @@ const path = require("node:path");
5
5
  const readline = require("node:readline");
6
6
 
7
7
  const crypto = require("node:crypto");
8
- const { ensureDir } = require("./fs");
8
+ const { ensureDir, writeJson, chmod600IfPossible } = require("./fs");
9
9
  const { readSqliteJsonRows, readSqliteJsonRowsAsync } = require("./sqlite-reader");
10
10
  const wsl = require("./wsl-probe");
11
11
  const { resolveInstallPaths } = require("./install-resolver");
@@ -5302,6 +5302,7 @@ function resolveKimiDefaultModel(env = process.env) {
5302
5302
  // ─────────────────────────────────────────────────────────────────────────────
5303
5303
 
5304
5304
  const KIRO_CLI_CHARS_PER_TOKEN = 4;
5305
+ const KIRO_CLI_CREDITS_SIDECAR = "kiro-credits.json";
5305
5306
 
5306
5307
  function resolveKiroCliDbPath(env = process.env) {
5307
5308
  if (env.KIRO_CLI_DB_PATH) return env.KIRO_CLI_DB_PATH;
@@ -5619,18 +5620,45 @@ function kiroCliV2ContentChars(value) {
5619
5620
  return 0;
5620
5621
  }
5621
5622
 
5623
+ function kiroCliV2UsageCredits(payload) {
5624
+ const summaries = Array.isArray(payload?.promptTurnSummaries)
5625
+ ? payload.promptTurnSummaries
5626
+ : [];
5627
+ let totalCredits = 0;
5628
+ let hasCreditEntry = false;
5629
+ for (const summary of summaries) {
5630
+ if (!summary || typeof summary !== "object") continue;
5631
+ const unit = String(summary.unit || "").trim().toLowerCase();
5632
+ if (unit !== "credit" && unit !== "credits") continue;
5633
+ const usage = Number(summary.usage);
5634
+ if (!Number.isFinite(usage) || usage < 0) continue;
5635
+ totalCredits += usage;
5636
+ hasCreditEntry = true;
5637
+ }
5638
+ return {
5639
+ totalCredits,
5640
+ recordCount: hasCreditEntry ? 1 : 0,
5641
+ };
5642
+ }
5643
+
5622
5644
  // Kiro CLI 2.13+ writes event-sourced sessions under
5623
5645
  // ~/.kiro/sessions/<workspaceHash>/sess_<uuid>/messages.jsonl. The records do
5624
- // not carry token counts, but user/assistant text, turn boundaries, timestamps,
5625
- // and assistant reasoningModelId are sufficient for the same 4 chars/token
5626
- // approximation used by the legacy CLI reader.
5646
+ // not carry token counts, but user/assistant text, tool_result payloads, turn
5647
+ // boundaries, timestamps, and assistant reasoningModelId are sufficient for
5648
+ // the same 4 chars/token approximation used by the legacy CLI reader.
5649
+ // tool_result content counts as INPUT: tool output (file reads, command
5650
+ // output, search results) is fed back to the model as context on the next
5651
+ // request — skipping it undercounted tool-heavy sessions by ~67% (#366).
5627
5652
  async function readKiroCliV2SessionTurns(messagesPath) {
5628
5653
  if (
5629
5654
  !messagesPath ||
5630
5655
  path.basename(messagesPath) !== "messages.jsonl" ||
5631
5656
  !fssync.existsSync(messagesPath)
5632
5657
  ) {
5633
- return [];
5658
+ return {
5659
+ turns: [],
5660
+ credits: { totalCredits: 0, recordCount: 0, latestAt: null },
5661
+ };
5634
5662
  }
5635
5663
 
5636
5664
  const sessionDir = path.dirname(messagesPath);
@@ -5658,7 +5686,10 @@ async function readKiroCliV2SessionTurns(messagesPath) {
5658
5686
  try {
5659
5687
  stream = fssync.createReadStream(messagesPath, { encoding: "utf8" });
5660
5688
  } catch {
5661
- return flat;
5689
+ return {
5690
+ turns: flat,
5691
+ credits: { totalCredits: 0, recordCount: 0, latestAt: null },
5692
+ };
5662
5693
  }
5663
5694
  const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
5664
5695
 
@@ -5666,6 +5697,10 @@ async function readKiroCliV2SessionTurns(messagesPath) {
5666
5697
  let pendingUserTimestampMs = NaN;
5667
5698
  let turn = null;
5668
5699
  let fallbackTurnIndex = 0;
5700
+ const seenCreditEvents = new Set();
5701
+ let totalCredits = 0;
5702
+ let creditRecordCount = 0;
5703
+ let latestCreditAt = null;
5669
5704
 
5670
5705
  const flushTurn = () => {
5671
5706
  if (!turn) return;
@@ -5747,8 +5782,35 @@ async function readKiroCliV2SessionTurns(messagesPath) {
5747
5782
  continue;
5748
5783
  }
5749
5784
 
5785
+ if (type === "usage_summary") {
5786
+ const creditEventKey =
5787
+ typeof event.id === "string" && event.id
5788
+ ? event.id
5789
+ : `${payload.executionId || ""}:${event.timestamp || ""}:${creditRecordCount}`;
5790
+ if (!seenCreditEvents.has(creditEventKey)) {
5791
+ seenCreditEvents.add(creditEventKey);
5792
+ const usage = kiroCliV2UsageCredits(payload);
5793
+ if (usage.recordCount > 0) {
5794
+ totalCredits += usage.totalCredits;
5795
+ creditRecordCount += usage.recordCount;
5796
+ if (
5797
+ Number.isFinite(timestampMs) &&
5798
+ (
5799
+ !latestCreditAt ||
5800
+ timestampMs > Date.parse(latestCreditAt)
5801
+ )
5802
+ ) {
5803
+ latestCreditAt = new Date(timestampMs).toISOString();
5804
+ }
5805
+ }
5806
+ }
5807
+ // Billing summaries are independent metadata. They can arrive after
5808
+ // turn_end, so they must not create or mutate token turns.
5809
+ continue;
5810
+ }
5811
+
5750
5812
  if (
5751
- ["assistant", "tool_call", "tool_result", "usage_summary"].includes(
5813
+ ["assistant", "tool_call", "tool_result"].includes(
5752
5814
  type,
5753
5815
  ) &&
5754
5816
  !turn
@@ -5784,6 +5846,10 @@ async function readKiroCliV2SessionTurns(messagesPath) {
5784
5846
  ) {
5785
5847
  turn.modelId = payload.reasoningModelId;
5786
5848
  }
5849
+ } else if (type === "tool_result") {
5850
+ // #366: tool output re-enters the model as input context on the
5851
+ // next request within the turn. Same ÷4 heuristic as user text.
5852
+ turn.inputChars += kiroCliV2ContentChars(payload.content);
5787
5853
  } else if (type === "turn_end") {
5788
5854
  flushTurn();
5789
5855
  }
@@ -5792,7 +5858,45 @@ async function readKiroCliV2SessionTurns(messagesPath) {
5792
5858
  // Return complete turns parsed before a concurrent truncate/delete.
5793
5859
  }
5794
5860
  flushTurn();
5795
- return flat;
5861
+ return {
5862
+ turns: flat,
5863
+ credits: {
5864
+ totalCredits,
5865
+ recordCount: creditRecordCount,
5866
+ latestAt: latestCreditAt,
5867
+ },
5868
+ };
5869
+ }
5870
+
5871
+ async function writeKiroCliCreditsSidecar({
5872
+ queuePath,
5873
+ totalCredits,
5874
+ recordCount,
5875
+ sessionCount,
5876
+ fileCount,
5877
+ latestAt,
5878
+ } = {}) {
5879
+ if (!queuePath || !(fileCount > 0)) return;
5880
+ const sidecarPath = path.join(
5881
+ path.dirname(queuePath),
5882
+ KIRO_CLI_CREDITS_SIDECAR,
5883
+ );
5884
+ try {
5885
+ await writeJson(sidecarPath, {
5886
+ version: 1,
5887
+ source: "kiro-cli-usage-summary",
5888
+ total_credits: Number(totalCredits.toFixed(12)),
5889
+ record_count: recordCount,
5890
+ session_count: sessionCount,
5891
+ file_count: fileCount,
5892
+ latest_at: latestAt,
5893
+ updated_at: new Date().toISOString(),
5894
+ });
5895
+ await chmod600IfPossible(sidecarPath);
5896
+ } catch {
5897
+ // Credits are supplemental billing metadata. A sidecar write failure must
5898
+ // never block the canonical token queue.
5899
+ }
5796
5900
  }
5797
5901
 
5798
5902
  // Canonicalize a Kiro-CLI-emitted model id so IDE and CLI rows collapse when
@@ -5923,13 +6027,43 @@ async function parseKiroCliIncremental({ sessionFiles, cursors, queuePath, onPro
5923
6027
  : [];
5924
6028
  const sessionFilesList = resolveKiroCliSessionFiles(resolvedEnv);
5925
6029
  let flatSessions = [];
6030
+ let kiroCreditTotal = 0;
6031
+ let kiroCreditRecords = 0;
6032
+ let kiroCreditSessions = 0;
6033
+ let kiroCreditFiles = 0;
6034
+ let latestKiroCreditAt = null;
5926
6035
  for (const sessionPath of sessionFilesList) {
5927
- const turns =
5928
- path.basename(sessionPath) === "messages.jsonl"
5929
- ? await readKiroCliV2SessionTurns(sessionPath)
5930
- : await readKiroCliSessionTurns(sessionPath);
6036
+ let turns;
6037
+ if (path.basename(sessionPath) === "messages.jsonl") {
6038
+ kiroCreditFiles++;
6039
+ const parsed = await readKiroCliV2SessionTurns(sessionPath);
6040
+ turns = parsed.turns;
6041
+ const credits = parsed.credits;
6042
+ kiroCreditTotal += credits.totalCredits;
6043
+ kiroCreditRecords += credits.recordCount;
6044
+ if (credits.recordCount > 0) kiroCreditSessions++;
6045
+ if (
6046
+ credits.latestAt &&
6047
+ (
6048
+ !latestKiroCreditAt ||
6049
+ Date.parse(credits.latestAt) > Date.parse(latestKiroCreditAt)
6050
+ )
6051
+ ) {
6052
+ latestKiroCreditAt = credits.latestAt;
6053
+ }
6054
+ } else {
6055
+ turns = await readKiroCliSessionTurns(sessionPath);
6056
+ }
5931
6057
  for (const turn of turns) flatSessions.push(turn);
5932
6058
  }
6059
+ await writeKiroCliCreditsSidecar({
6060
+ queuePath,
6061
+ totalCredits: kiroCreditTotal,
6062
+ recordCount: kiroCreditRecords,
6063
+ sessionCount: kiroCreditSessions,
6064
+ fileCount: kiroCreditFiles,
6065
+ latestAt: latestKiroCreditAt,
6066
+ });
5933
6067
  // Per-request state replaces the old seenIds set. Each entry captures
5934
6068
  // what we contributed for that request_id last time, so a later mutation
5935
6069
  // (same request_id, different fingerprint) can subtract-old/add-new
@@ -64,6 +64,7 @@ const CODEX_LIMITS_CACHE_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
64
64
  // restart — stops calling until it expires. Hammering during the cooldown just renews the
65
65
  // penalty, which is what kept the panel stuck on the error.
66
66
  const CLAUDE_RATE_LIMIT_FILE = "claude-usage-rate-limit.json";
67
+ const KIRO_CREDITS_SIDECAR_FILE = "kiro-credits.json";
67
68
  const CLAUDE_RATE_LIMIT_DEFAULT_COOLDOWN_SEC = 5 * 60;
68
69
  const CLAUDE_RATE_LIMIT_MAX_COOLDOWN_SEC = 60 * 60;
69
70
 
@@ -1553,6 +1554,43 @@ function parseKiroUsageOutput(output, { now = new Date() } = {}) {
1553
1554
  };
1554
1555
  }
1555
1556
 
1557
+ function readKiroCreditsSummary({ home = os.homedir() } = {}) {
1558
+ const sidecarPath = path.join(
1559
+ home,
1560
+ ".tokentracker",
1561
+ "tracker",
1562
+ KIRO_CREDITS_SIDECAR_FILE,
1563
+ );
1564
+ try {
1565
+ const parsed = JSON.parse(fs.readFileSync(sidecarPath, "utf8"));
1566
+ if (parsed?.version !== 1) return null;
1567
+ const totalCredits = Number(parsed.total_credits);
1568
+ const recordCount = Number(parsed.record_count);
1569
+ const sessionCount = Number(parsed.session_count);
1570
+ if (
1571
+ !Number.isFinite(totalCredits) ||
1572
+ totalCredits < 0 ||
1573
+ !Number.isSafeInteger(recordCount) ||
1574
+ recordCount <= 0 ||
1575
+ !Number.isSafeInteger(sessionCount) ||
1576
+ sessionCount <= 0
1577
+ ) {
1578
+ return null;
1579
+ }
1580
+ return {
1581
+ tracked_credits: totalCredits,
1582
+ tracked_credit_records: recordCount,
1583
+ tracked_credit_sessions: sessionCount,
1584
+ tracked_credits_latest_at:
1585
+ typeof parsed.latest_at === "string" ? parsed.latest_at : null,
1586
+ tracked_credits_updated_at:
1587
+ typeof parsed.updated_at === "string" ? parsed.updated_at : null,
1588
+ };
1589
+ } catch {
1590
+ return null;
1591
+ }
1592
+ }
1593
+
1556
1594
  // ─────────────────────────────────────────────────────────────────────────────
1557
1595
  // GitHub Copilot — `GET https://api.github.com/copilot_internal/user`
1558
1596
  // Reuses the OAuth token from the user's existing Copilot install. Older clients
@@ -1982,10 +2020,14 @@ async function fetchKiroLimits({
1982
2020
  commandRunner,
1983
2021
  now = new Date(),
1984
2022
  platform = process.platform,
2023
+ home = os.homedir(),
1985
2024
  } = {}) {
2025
+ const trackedCredits = readKiroCreditsSummary({ home });
1986
2026
  const binaryPath = await whichBinary("kiro-cli", { commandRunner });
1987
2027
  if (!binaryPath) {
1988
- return { configured: false };
2028
+ return trackedCredits
2029
+ ? { configured: true, error: null, ...trackedCredits }
2030
+ : { configured: false };
1989
2031
  }
1990
2032
 
1991
2033
  const versionResult = await runCommand(
@@ -2042,6 +2084,7 @@ async function fetchKiroLimits({
2042
2084
  configured: true,
2043
2085
  error: null,
2044
2086
  ...parseKiroCommandResult(result, { now }),
2087
+ ...(trackedCredits || {}),
2045
2088
  };
2046
2089
  } catch (error) {
2047
2090
  lastError = error;
@@ -2052,6 +2095,7 @@ async function fetchKiroLimits({
2052
2095
  return {
2053
2096
  configured: true,
2054
2097
  error: error?.message || "Unknown error",
2098
+ ...(trackedCredits || {}),
2055
2099
  };
2056
2100
  }
2057
2101
  }
@@ -3077,7 +3121,7 @@ async function fetchUsageLimitsUncached({
3077
3121
  .catch((reason) => ({ configured: true, error: reason?.message || "Unknown error" })),
3078
3122
  withProviderTimeout(fetchGeminiLimits({ home, env, fetchImpl: providerFetch, commandRunner }), "Gemini", providerTimeoutMs)
3079
3123
  .catch((reason) => ({ configured: true, error: reason?.message || "Unknown error" })),
3080
- fetchKiroLimits({ commandRunner, now, platform }),
3124
+ fetchKiroLimits({ commandRunner, now, platform, home }),
3081
3125
  fetchAntigravityLimits({ home, commandRunner, requestFn, fetchImpl: providerFetch, nowMs }),
3082
3126
  withProviderTimeout(fetchCopilotLimits({ home, env, fetchImpl: providerFetch, platform, securityRunner }), "GitHub Copilot", providerTimeoutMs)
3083
3127
  .catch((reason) => ({ configured: true, error: reason?.message || "Unknown error" })),
@@ -3095,7 +3139,6 @@ async function fetchUsageLimitsUncached({
3095
3139
  home,
3096
3140
  env,
3097
3141
  platform,
3098
- securityRunner,
3099
3142
  fetchImpl: providerFetch,
3100
3143
  }),
3101
3144
  "Qoder",
@@ -3284,6 +3327,7 @@ module.exports = {
3284
3327
  normalizeGeminiQuotaResponse,
3285
3328
  normalizeKimiUsageResponse,
3286
3329
  parseKiroUsageOutput,
3330
+ readKiroCreditsSummary,
3287
3331
  fetchKiroLimits,
3288
3332
  normalizeAntigravityResponse,
3289
3333
  parseListeningPorts,
@@ -1 +0,0 @@
1
- import{r as n,A as a}from"./__vite-browser-external-BdRrPLk6.js";import{u as p}from"./DialogTitle-amHXttsp.js";import{u as c}from"./useScrollLock-Cvyfyezc.js";const x=n.forwardRef(function(e,r){const{render:l,className:u,style:m,id:s,...t}=e,{store:i}=p(),o=c(s);return i.useSyncedValueWithCleanup("descriptionElementId",o),a("p",e,{ref:r,props:[{id:o},t]})});export{x as D};
@@ -1,4 +0,0 @@
1
- import{m as H,j as t,e as $,c as r,k as B,r as h,ac as te,d as ae,K as ie,L as re,ad as ne,q as oe,ae as se}from"./__vite-browser-external-BdRrPLk6.js";import{m as A}from"./react-DK5clHtY.js";import{P as W,c as le,r as N,a as de,u as ce,b as ue,s as me}from"./use-usage-limits-Tbifa037.js";import{L as m,u as xe}from"./use-limits-display-prefs-Di_J4eVv.js";import{C as U}from"./Card-BzbSN3EC.js";import{F as pe}from"./FadeIn-CIhF_9PP.js";import{L as ge,l as w,a as fe}from"./limits-providers-ySB9Ci5l.js";import{P as he}from"./ProviderIcon-D3YKjVKb.js";import{H as be}from"./HoverTooltip-BS8eO6tj.js";import{L as ye}from"./LocalOnlyNotice-CpFFX8ro.js";import{u as ve}from"./use-reduced-motion-5QGGPoom.js";import"./arrow-up-right-CbMcAcss.js";import"./download-B3rOytqI.js";const ke=[["path",{d:"M10.268 21a2 2 0 0 0 3.464 0",key:"vwvbt9"}],["path",{d:"M17 17H4a1 1 0 0 1-.74-1.673C4.59 13.956 6 12.499 6 8a6 6 0 0 1 .258-1.742",key:"178tsu"}],["path",{d:"m2 2 20 20",key:"1ooewy"}],["path",{d:"M8.668 3.01A6 6 0 0 1 18 8c0 2.687.77 4.653 1.707 6.05",key:"1hqiys"}]],je=H("bell-off",ke);const Ne=[["path",{d:"M10.268 21a2 2 0 0 0 3.464 0",key:"vwvbt9"}],["path",{d:"M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326",key:"11g9vi"}]],_e=H("bell",Ne),we=[3,2,3,3,2,2,3];function f({className:e}){return t.jsx("div",{className:$("rounded bg-oai-gray-200/70 dark:bg-oai-gray-800/70 animate-pulse",e)})}function Me(){return t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx(f,{className:"h-3 w-12 shrink-0"}),t.jsx(f,{className:"flex-1 h-1.5 rounded-full min-w-0"}),t.jsx(f,{className:"h-3 w-[30px] shrink-0"}),t.jsx(f,{className:"h-3 w-6 shrink-0"})]})}function Ee({bars:e,index:a}){const i=a%3===0?"w-24":a%3===1?"w-20":"w-[4.5rem]";return t.jsxs("div",{className:"flex flex-col gap-1.5",children:[t.jsxs("div",{className:"flex items-center gap-1.5",children:[t.jsx(f,{className:"h-[14px] w-[14px] rounded shrink-0"}),t.jsx(f,{className:$("h-4",i)})]}),Array.from({length:e},(o,n)=>t.jsx(Me,{},n))]})}function Ie(){return t.jsx(U,{children:t.jsxs("div",{className:"flex flex-col gap-3",children:[t.jsx(f,{className:"h-3.5 w-28"}),we.map((e,a)=>t.jsx(Ee,{bars:e,index:a},a))]})})}const L=100;function D(e){const a=Date.parse(e);return Number.isFinite(a)?a:null}function Le(e){return Math.max(0,Math.min(L,Math.round(e)))}function Pe(e){return new Intl.DateTimeFormat(B(),{month:"numeric",day:"numeric",hour:"2-digit",minute:"2-digit",hour12:!1}).format(new Date(e))}function Oe(e,a,i){if(e==null||e>=a)return L;const o=a-e,n=a-i;return Le(n/o*L)}function Se(e){const a=e.available_count;return a===null?null:Number.isInteger(a)&&a>=0?a:void 0}function Re(e,{now:a}={}){if(!e||typeof e!="object")return null;const i=Se(e);if(i===void 0)return null;const o=Array.isArray(e.credits)?e.credits:[],n=a instanceof Date?a.getTime():Number(a??Date.now()),s=[];for(const c of o){const d=D(c?.expires_at);if(d==null)continue;const l=s.length+1;s.push({key:`reset-${l}`,label:r("limits.codex_reset_bank.row_label",{index:l}),expiresAt:Pe(d),expiresMs:d,percent:Oe(D(c?.granted_at),d,n)})}return i===0?null:s.length>0?{kind:"rows",availableCount:i??s.length,rows:s}:i>0?{kind:"count_only",availableCount:i,rows:[]}:null}const Ce="shrink-0 text-oai-black dark:text-oai-white";function Te(e){const a=N(e);if(!Number.isFinite(a))return null;const i=a-Date.now();if(i<=0)return r("shared.time.now");const o=Math.floor(i/6e4);if(o<60)return`${o}m`;const n=Math.floor(o/60);return n<24?`${n}h`:`${Math.floor(n/24)}d`}function Ae(e,a){const i=a===m.REMAINING?100-e:e;return i>=90?"bg-red-500":i>=70?"bg-amber-500":"bg-emerald-500"}function j(e,a="used_percent"){return e?a==="utilization"?e.utilization:e.used_percent:null}function _(e,a="reset_at"){return e?a==="resets_at"?e.resets_at:e.reset_at:null}function M(e){const a=Math.max(0,Math.min(100,Number(e)||0)),i=Math.round(a);return a>0&&i===0?r("limits.bar.sub_one_percent"):String(i)}function E(e,{useGrouping:a=!0}={}){const i=Number(e);return Number.isFinite(i)?new Intl.NumberFormat(void 0,{minimumFractionDigits:0,maximumFractionDigits:i>=100?0:2,useGrouping:a}).format(i):null}function De(e){if(!e||typeof e!="object"||!(Number(e.limit_credits)>0))return null;const a={useGrouping:e.unit!=="calls"},i=E(e.used_credits,a),o=E(e.limit_credits,a),n=E(e.remaining_credits,a);if(!i||!o||!n)return null;const s=e.unit==="calls"?"limits.qoder_calls.detail":"limits.codex_credits.detail";return r(s,{used:i,limit:o,remaining:n})}function Fe(e,a){return le({usedPercent:j(e.window,e.pctField),windowSeconds:de(e,e.window),resetMs:N(_(e.window,e.resetField)),mode:a})}function q(e){return Number.isFinite(e)?new Intl.DateTimeFormat(B(),{month:"numeric",day:"numeric",hour:"2-digit",minute:"2-digit",hour12:!1}).format(new Date(e)):null}function Ge(e,a,i){const o=[z(e,a,i)],n=N(_(e.window,e.resetField)),s=q(n);s&&o.push(r(e.timeKind==="expiry"?"limits.hover.expires_at":"limits.hover.resets_at",{time:s}));const c=De(e.window);return c&&o.push(c),o.join(`
2
- `)}const K=be;function He({label:e,pct:a,reset:i,mode:o=m.USED,pacePercent:n=null,paceOver:s=!1,title:c=null}){const d=Math.max(0,Math.min(100,Number(a)||0)),l=o===m.REMAINING?100-d:d,u=Math.round(l),x=l>0&&u===0?Math.max(l,.35):l;let v=String(u);l>0&&u===0&&(v=r("limits.bar.sub_one_percent"));const p=n==null?null:Math.max(0,Math.min(100,n));return t.jsxs("div",{className:"group relative flex items-center gap-2",children:[t.jsx(K,{text:c}),t.jsx("span",{"data-limit-label":"",className:"text-[11px] text-oai-gray-500 dark:text-oai-gray-400 shrink-0 whitespace-nowrap",style:{width:"var(--tt-limits-label-w)"},children:e}),t.jsxs("div",{className:"relative flex-1 bg-oai-gray-100 dark:bg-oai-gray-700/50 rounded-full h-1.5 overflow-hidden",children:[t.jsx("div",{className:`${Ae(l,o)} rounded-full h-full transition-[width] duration-500 ease-out`,style:{width:`${x}%`,minWidth:l>0?"3px":0}}),p!=null&&t.jsxs(t.Fragment,{children:[t.jsx("div",{className:"absolute top-0 h-full bg-oai-gray-100 dark:bg-oai-gray-700/50",style:{left:`calc(${p}% - 3px)`,width:"6px"}}),t.jsx("div",{className:`absolute top-0 h-full ${s?"bg-red-500":"bg-emerald-500"}`,style:{left:`calc(${p}% - 1px)`,width:"2px"}})]})]}),t.jsxs("span",{className:"text-[11px] tabular-nums text-oai-gray-500 dark:text-oai-gray-400 w-9 text-right shrink-0 whitespace-nowrap",children:[v,"%"]}),i&&t.jsx("span",{className:"text-[10px] text-oai-gray-400 dark:text-oai-gray-500 w-6 text-right shrink-0",children:i})]})}function z(e,a,i){const o=e.label??r(e.labelKey),n=i===m.REMAINING,s=l=>n?100-l:l;if(a.expectedPercent==null){const l=Math.max(0,Math.min(100,Number(j(e.window,e.pctField))||0)),u=M(s(l));return n?r("limits.explain.remaining",{label:o,used:u}):r("limits.explain.used",{label:o,used:u})}if(a.paceOver){if(a.runsOutEta)return r("limits.explain.ahead_eta",{label:o,eta:a.runsOutEta});const l=M(s(a.projectedEnd??100));return r(n?"limits.explain.ahead_pct_remaining":"limits.explain.ahead_pct",{label:o,pct:l})}const c=Math.max(0,Math.min(100,Number(j(e.window,e.pctField))||0)),d=M(s(a.projectedEnd??c));return r(n?"limits.explain.on_track_remaining":"limits.explain.on_track",{label:o,pct:d})}function $e({rows:e,mode:a}){if(e.length===0)return null;const i=a===m.REMAINING;return t.jsxs("div",{className:"mt-1 flex flex-col gap-1",children:[e.map(({spec:o,pace:n})=>{const s=q(N(_(o.window,o.resetField)));return t.jsxs("div",{className:"text-[11px] leading-snug text-oai-gray-600 dark:text-oai-gray-300",children:[z(o,n,a),s?t.jsxs("span",{className:"text-oai-gray-400 dark:text-oai-gray-500",children:[" · ",r(o.timeKind==="expiry"?"limits.hover.expires_at":"limits.hover.resets_at",{time:s})]}):null]},o.key)}),t.jsx("div",{className:"mt-1 pt-1.5 border-t border-oai-gray-200/70 dark:border-oai-gray-700/50 text-[10.5px] leading-snug text-oai-gray-400 dark:text-oai-gray-500",children:r(i?"limits.explain.body_remaining":"limits.explain.body")})]})}function k(e){if(!e)return null;const a=Date.now()-new Date(e).getTime();if(a<0)return null;const i=Math.floor(a/6e4);if(i<1)return r("shared.time.now");if(i<60)return r("shared.time.m_ago",{n:i});const o=Math.floor(i/60);if(o<24)return r("shared.time.h_ago",{n:o});const n=Math.floor(o/24);return r("shared.time.d_ago",{n})}const F={live:{surface:"bg-oai-gray-50 dark:bg-oai-gray-800 border-oai-gray-200/60 dark:border-oai-gray-700/60 text-oai-gray-500 dark:text-oai-gray-400",dot:"bg-emerald-500",pulse:"bg-emerald-400"},stale:{surface:"bg-oai-gray-50 dark:bg-oai-gray-800 border-oai-gray-200/60 dark:border-oai-gray-700/60 text-oai-gray-500 dark:text-oai-gray-400",dot:"bg-amber-500",pulse:"bg-amber-400"},cached:{surface:"bg-oai-gray-50 dark:bg-oai-gray-800 border-oai-gray-200/60 dark:border-oai-gray-700/60 text-oai-gray-500 dark:text-oai-gray-400",dot:"bg-amber-500",pulse:"bg-amber-400"}},Be={claude:"claude",codex:"codex"};function b({label:e,age:a=null,tone:i="live",tooltip:o=null}){const n=F[i]||F.live,s=i==="live";return t.jsxs("div",{className:"relative inline-flex items-center group cursor-help ml-1",onClick:c=>c.stopPropagation(),children:[t.jsxs("span",{className:`inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[9px] font-semibold uppercase tracking-wider border leading-normal ${n.surface}`,children:[s?t.jsxs("span",{className:"relative flex h-1.5 w-1.5",children:[t.jsx("span",{className:`animate-ping absolute inline-flex h-full w-full rounded-full ${n.pulse} opacity-75`}),t.jsx("span",{className:`relative inline-flex rounded-full h-1.5 w-1.5 ${n.dot}`})]}):t.jsx("span",{className:`h-1.5 w-1.5 rounded-full ${n.dot}`}),e,a?t.jsxs(t.Fragment,{children:[" · ",a]}):null]}),o?t.jsxs("span",{className:"pointer-events-none absolute left-1/2 bottom-full z-20 mb-2 -translate-x-1/2 w-48 rounded-md bg-oai-gray-900 dark:bg-oai-gray-800 px-2.5 py-1.5 text-[10px] font-normal text-white text-center opacity-0 scale-95 translate-y-1 group-hover:opacity-100 group-hover:scale-100 group-hover:translate-y-0 transition-all duration-200 cubic-bezier(0.16, 1, 0.3, 1) leading-normal shadow-lg origin-bottom border border-oai-gray-800 dark:border-oai-gray-700",children:[o,t.jsx("span",{className:"absolute left-1/2 top-full -translate-x-1/2 border-4 border-transparent border-t-oai-gray-900 dark:border-t-oai-gray-800"})]}):null]})}function P({name:e,providerId:a,children:i,expandable:o=!1,expanded:n=!1,onToggle:s,badge:c=null}){const d=fe(a),l=t.jsxs("div",{className:"flex items-center gap-1.5",children:[d?t.jsx(he,{provider:d,size:14,className:Ce}):null,t.jsx("span",{className:"text-sm font-medium text-oai-black dark:text-oai-white",children:e}),c]});return o?t.jsxs("div",{role:"button",tabIndex:0,"aria-expanded":n,onClick:s,onKeyDown:u=>{(u.key==="Enter"||u.key===" ")&&(u.preventDefault(),s?.())},className:"flex flex-col gap-1.5 -mx-1.5 px-1.5 py-1 rounded-lg cursor-pointer transition-colors hover:bg-oai-gray-50 dark:hover:bg-oai-gray-800/40 aria-expanded:bg-oai-gray-50 dark:aria-expanded:bg-oai-gray-800/40",children:[l,i]}):t.jsxs("div",{className:"flex flex-col gap-1.5",children:[l,i]})}const We=ge;function y({children:e,tone:a="neutral"}){const i=a==="error"?"text-red-600 dark:text-red-400":"text-oai-gray-500 dark:text-oai-gray-400";return t.jsx("div",{className:`text-[11px] leading-snug ${i}`,children:e})}function Ue({rows:e,mode:a,extra:i=null}){const o=e.length===0&&!i;return t.jsxs(t.Fragment,{children:[e.map(({spec:n,pace:s})=>t.jsx(He,{label:n.label??r(n.labelKey),pct:j(n.window,n.pctField),reset:Te(_(n.window,n.resetField)),mode:a,pacePercent:s.pacePercent,paceOver:s.paceOver,title:Ge(n,s,a)},n.key)),o?t.jsx(y,{children:r("limits.status.no_data")}):null,i]})}function qe(e){if(!Number.isFinite(e.expiresMs))return null;const a=Math.floor((e.expiresMs-Date.now())/864e5);return a<0?null:a===0?r("limits.reset_bank.hover_detail_today",{date:e.expiresAt}):r("limits.reset_bank.hover_detail",{date:e.expiresAt,days:a})}function Ke({row:e}){const a=Math.max(0,Math.min(100,Number(e.percent)||0));return t.jsxs("div",{className:"group relative flex items-center gap-2","data-reset-bank-row":"",children:[t.jsx(K,{text:qe(e)}),t.jsx("span",{"data-limit-label":"",className:"text-[11px] text-oai-gray-500 dark:text-oai-gray-400 shrink-0 whitespace-nowrap",style:{width:"var(--tt-limits-label-w)"},children:e.label}),t.jsx("div",{className:"relative flex-1 bg-oai-gray-100 dark:bg-oai-gray-700/50 rounded-full h-1.5 overflow-hidden",children:t.jsx("div",{className:"bg-oai-gray-400 dark:bg-oai-gray-500 rounded-full h-full transition-[width] duration-500 ease-out",style:{width:`${a}%`,minWidth:a>0?"3px":0}})}),t.jsx("span",{className:"text-[10px] tabular-nums text-oai-gray-400 dark:text-oai-gray-500 w-[4.25rem] text-right shrink-0 whitespace-nowrap",children:e.expiresAt})]})}function ze({model:e}){const a=e.kind==="count_only"?r("limits.codex_reset_bank.count_only",{count:e.availableCount}):null;return t.jsxs("div",{className:"mt-1 flex flex-col gap-1","data-reset-bank-section":e.kind,children:[t.jsx("div",{className:"text-[10.5px] font-medium uppercase tracking-wide text-oai-gray-400 dark:text-oai-gray-500",children:r("limits.codex_reset_bank.title")}),a?t.jsx("div",{className:"text-[11px] leading-snug text-oai-gray-500 dark:text-oai-gray-400",children:a}):e.rows.map(i=>t.jsx(Ke,{row:i},i.key))]})}function Ve(e,a){if(e==="codex_meta"){const i=Re(a.reset_credits);return i?t.jsx(ze,{model:i}):null}return e==="kimi_parallel"&&a.parallel_limit?t.jsx(y,{children:r("limits.label.kimi_parallel",{count:a.parallel_limit})}):e==="copilot_otel"&&!a.otel_has_files&&!a.otel_enabled?t.jsx(Qe,{defaultDir:a.otel_default_dir}):null}function Xe(e,a,i,o,n,s,c=null){const d=W[e];if(!d)return null;const l=d.windows(a).filter(x=>x.window).map(x=>({spec:x,pace:Fe(x,o)})),u=Ve(d.extra,a);return t.jsxs(P,{name:i,providerId:e,expandable:l.length>0,expanded:n,onToggle:s,badge:c,children:[t.jsx(Ue,{mode:o,rows:l,extra:u}),n?t.jsx($e,{rows:l,mode:o}):null]},e)}function Ye(e,a,i,o,n){if(!W[e])return null;if(!a?.configured)return t.jsxs(P,{name:w(e),providerId:e,children:[t.jsx(y,{children:r("limits.status.not_connected")}),e==="opencodeGo"?t.jsx(G,{}):null]},e);if(a.error)return t.jsxs(P,{name:w(e),providerId:e,children:[t.jsx(y,{tone:"error",children:r("shared.error.prefix",{error:a.error})}),e==="opencodeGo"?t.jsx(G,{}):null]},e);const s=w(e),c=a.plan_label?`${s} ${a.plan_label}`:s;let d=null;if(e==="antigravity")if(a.cached){const u=k(a.cached_at);d=t.jsx(b,{label:r("limits.label.antigravity_cached"),age:u,tone:"cached",tooltip:r("limits.tooltip.antigravity_cached")})}else d=t.jsx(b,{label:r("limits.label.antigravity_live"),tone:"live",tooltip:r("limits.tooltip.antigravity_live")});if(e==="qoder"&&a.cached&&(d=t.jsx(b,{label:r("limits.label.antigravity_cached"),age:k(a.cached_at),tone:"cached",tooltip:r("limits.tooltip.qoder_cached")})),!d&&a.auth_action_required==="reauth"){const u=Be[e];d=t.jsx(b,{label:r("limits.reauth.badge"),age:k(a.cached_at),tone:"stale",tooltip:u?r("limits.reauth.tooltip",{command:u}):null})}const l=a.provenance;return l?.stale&&!d&&(d=t.jsx(b,{label:r("limits.provenance.stale"),age:k(l.captured_at),tone:"stale",tooltip:r("limits.provenance.tooltip",{source:l.source,confidence:l.confidence})})),Xe(e,a,c,i,o,n,d)}function Qe({defaultDir:e}){const[a,i]=h.useState(!1),n=["export COPILOT_OTEL_ENABLED=true","export COPILOT_OTEL_EXPORTER_TYPE=file",`export COPILOT_OTEL_FILE_EXPORTER_PATH="${e||"$HOME/.copilot/otel"}/copilot-otel-$(date +%Y%m%d).jsonl"`].join(`
3
- `),s=async c=>{c.stopPropagation();try{await navigator.clipboard.writeText(n),i(!0),setTimeout(()=>i(!1),1600)}catch{}};return t.jsxs("div",{className:"mt-1 rounded-md border border-amber-300/60 dark:border-amber-700/40 bg-amber-50/50 dark:bg-amber-900/10 px-2.5 py-2 text-[11px] text-oai-gray-600 dark:text-oai-gray-300",children:[t.jsx("div",{className:"font-medium text-oai-gray-700 dark:text-oai-gray-200",children:r("limits.copilot.otelHint.title")}),t.jsx("div",{className:"mt-0.5 leading-snug",children:r("limits.copilot.otelHint.body")}),t.jsx("pre",{className:"mt-1.5 overflow-x-auto rounded bg-oai-gray-100 dark:bg-oai-gray-900/60 px-2 py-1.5 font-mono text-[10.5px] leading-tight whitespace-pre",children:n}),t.jsx("button",{type:"button",onClick:s,className:"mt-1 inline-flex items-center gap-1 rounded border border-oai-gray-300 dark:border-oai-gray-700 px-1.5 py-0.5 text-[10.5px] text-oai-gray-700 dark:text-oai-gray-200 hover:bg-oai-gray-100 dark:hover:bg-oai-gray-800 transition-colors",children:a?r("limits.copilot.otelHint.copied"):r("limits.copilot.otelHint.copy")})]})}function I({n:e,children:a}){return t.jsxs("li",{className:"flex gap-2.5",children:[t.jsx("span",{className:"mt-[1px] flex h-4 w-4 shrink-0 items-center justify-center rounded-full bg-oai-brand/15 text-[9px] font-semibold text-oai-brand",children:e}),t.jsx("div",{className:"min-w-0 flex-1 leading-snug",children:a})]})}function Je(){return t.jsx("svg",{viewBox:"0 0 12 12","aria-hidden":"true",className:"h-2.5 w-2.5",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round",children:t.jsx("path",{d:"M4.5 2.75h4.75V7.5M9.25 2.75 3 9"})})}function G(){const[e,a]=h.useState(!1),i=['export OPENCODE_GO_AUTH_COOKIE="..."','# Optional: export OPENCODE_GO_WORKSPACE_ID="wrk_..." (Only if auto-discovery fails)'].join(`
4
- `),o=async n=>{n.stopPropagation();try{await navigator.clipboard.writeText(i),a(!0),setTimeout(()=>a(!1),1600)}catch{}};return t.jsxs("div",{className:"mt-1.5 rounded-lg border border-oai-gray-200 dark:border-oai-gray-700/60 bg-oai-gray-50/50 dark:bg-oai-gray-900/20 p-3 text-[11px] text-oai-gray-600 dark:text-oai-gray-300",children:[t.jsx("div",{className:"text-[12px] font-semibold text-oai-gray-800 dark:text-oai-gray-100",children:r("limits.opencodeGo.setupHint.title")}),t.jsx("div",{className:"mt-0.5 leading-snug text-oai-gray-500 dark:text-oai-gray-400",children:r("limits.opencodeGo.setupHint.subtitle")}),t.jsxs("ol",{className:"mt-2.5 space-y-2.5",children:[t.jsxs(I,{n:"1",children:[t.jsx("div",{children:r("limits.opencodeGo.setupHint.step1")}),t.jsxs("a",{href:"https://opencode.ai",target:"_blank",rel:"noreferrer",onClick:n=>n.stopPropagation(),className:"mt-1 inline-flex items-center gap-1 rounded-md bg-oai-brand/10 px-2 py-1 font-medium text-oai-brand hover:bg-oai-brand/15 transition-colors",children:[r("limits.opencodeGo.setupHint.cta"),t.jsx(Je,{})]})]}),t.jsxs(I,{n:"2",children:[t.jsx("div",{children:r("limits.opencodeGo.setupHint.step2")}),t.jsxs("ul",{className:"mt-1 space-y-0.5 text-oai-gray-500 dark:text-oai-gray-400",children:[t.jsx("li",{children:r("limits.opencodeGo.setupHint.step2_workspace")}),t.jsx("li",{children:r("limits.opencodeGo.setupHint.step2_cookie")})]})]}),t.jsxs(I,{n:"3",children:[t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx("span",{children:r("limits.opencodeGo.setupHint.step3")}),t.jsx("button",{type:"button",onClick:o,className:"shrink-0 rounded-md border border-oai-gray-300 dark:border-oai-gray-700 px-2 py-0.5 text-[10.5px] text-oai-gray-700 dark:text-oai-gray-200 hover:bg-oai-gray-100 dark:hover:bg-oai-gray-800 transition-colors",children:e?r("limits.opencodeGo.setupHint.copied"):r("limits.opencodeGo.setupHint.copy")})]}),t.jsx("pre",{className:"mt-1.5 overflow-x-auto rounded-md bg-oai-gray-100 dark:bg-oai-gray-900/60 px-2 py-1.5 font-mono text-[10.5px] leading-relaxed whitespace-pre",children:i}),t.jsx("div",{className:"mt-1 text-[10px] text-oai-gray-400 dark:text-oai-gray-500",children:r("limits.opencodeGo.setupHint.note_app")})]})]})]})}function Ze(e){const[a,i]=h.useState(0);return h.useLayoutEffect(()=>{const o=e.current;if(!o)return;const n=o.querySelectorAll("[data-limit-label]");let s=0,c=null;if(n.length>0)try{c=document.createElement("canvas").getContext("2d")}catch{c=null}if(c){const l=window.getComputedStyle(n[0]);c.font=`${l.fontStyle} ${l.fontWeight} ${l.fontSize} ${l.fontFamily}`;for(const u of n)s=Math.max(s,c.measureText(u.textContent).width)}const d=Math.ceil(s);i(l=>l===d?l:d)}),a}function et({claude:e,codex:a,cursor:i,gemini:o,kimi:n,kiro:s,grok:c,antigravity:d,copilot:l,zcode:u,opencodeGo:x,qoder:v,order:p,visibility:O,displayMode:V}){const X={claude:e,codex:a,cursor:i,gemini:o,kimi:n,kiro:s,grok:c,antigravity:d,copilot:l,zcode:u,opencodeGo:x,qoder:v},S=h.useRef(null),R=Ze(S),[Y,Q]=h.useState(null),J=Array.isArray(p)&&p.length>0?p:We,C=V===m.REMAINING?m.REMAINING:m.USED,Z=C===m.REMAINING?r("limits.settings.display_mode_remaining"):r("limits.settings.display_mode_used"),T=J.filter(g=>!O||O[g]!==!1).map(g=>Ye(g,X[g],C,Y===g,()=>Q(ee=>ee===g?null:g))).filter(Boolean);return t.jsx(pe,{delay:.15,children:t.jsx(U,{children:t.jsxs("div",{ref:S,className:"flex flex-col gap-3",style:R>0?{"--tt-limits-label-w":`${R}px`}:void 0,children:[t.jsxs("h3",{className:"text-sm font-medium text-oai-gray-500 dark:text-oai-gray-300 uppercase tracking-wide",children:[r("limits.panel.title"),r("limits.panel.mode_separator"),Z]}),T.length>0?T:t.jsx(y,{children:r("limits.status.all_hidden")})]})})})}const tt=typeof window<"u"&&(window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1"),at="x-apple.systempreferences:com.apple.preference.notifications";function it(){const e=ve(),a=oe(),i=r("limits.alert.blocked"),o=a?A.button:A.div;return t.jsxs(o,{type:a?"button":void 0,onClick:a?()=>se({type:"action",name:"openURL",value:at}):void 0,initial:e?!1:{opacity:0,x:14,scale:.9},animate:{opacity:1,x:0,scale:1},transition:{type:"spring",stiffness:320,damping:18},title:i,className:`relative hidden sm:inline-flex min-w-0 max-w-[360px] items-center gap-1.5 rounded-full border border-amber-300/70 bg-amber-50 px-3 py-1.5 text-xs text-amber-700 dark:border-amber-500/30 dark:bg-amber-500/10 dark:text-amber-300 ${a?"cursor-pointer transition-colors hover:bg-amber-100 dark:hover:bg-amber-500/20 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-amber-500/60":""}`,children:[t.jsxs("span",{className:"relative flex h-1.5 w-1.5 shrink-0",children:[t.jsx("span",{className:"absolute inline-flex h-full w-full animate-ping rounded-full bg-amber-400 opacity-75"}),t.jsx("span",{className:"relative inline-flex h-1.5 w-1.5 rounded-full bg-amber-500"})]}),t.jsx("span",{className:"truncate",children:i}),t.jsx("span",{"aria-hidden":!0,className:"absolute left-full top-1/2 -translate-y-1/2 border-[5px] border-transparent border-l-amber-300/80 dark:border-l-amber-500/40"})]})}function ht(){const e=te(),{data:a,error:i,isLoading:o}=ce(e?{initialRefresh:!0,initialState:e,publishToPreloadCache:!0}:{initialRefresh:!0,publishToPreloadCache:!0}),n=xe(),s=ue();return ae.useEffect(()=>{s.enabled&&a&&me(a)},[s.enabled,a]),!tt&&!ie()?t.jsx("div",{className:"flex flex-col flex-1 text-oai-black dark:text-oai-white font-oai antialiased",children:t.jsx(ye,{})}):t.jsx("div",{className:"flex flex-col flex-1 text-oai-black dark:text-oai-white font-oai antialiased",children:t.jsx("main",{className:"flex-1 pt-8 sm:pt-10 pb-12 sm:pb-16",children:t.jsxs("div",{className:"mx-auto max-w-6xl px-4 sm:px-6",children:[t.jsxs("div",{className:"flex flex-row items-start justify-between gap-4 mb-8",children:[t.jsxs("div",{className:"min-w-0",children:[t.jsx("h1",{className:"text-3xl sm:text-4xl font-semibold tracking-tight text-oai-black dark:text-white mb-3",children:r("nav.limits")}),t.jsx("p",{className:"text-oai-gray-500 dark:text-oai-gray-400 text-sm sm:text-base",children:r("limits.page.subtitle")})]}),t.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[s.enabled&&s.permissionBlocked?t.jsx(it,{}):null,t.jsx("button",{type:"button",onClick:()=>{s.setEnabled(!s.enabled)},"aria-label":s.enabled?r("limits.alert.disable"):r("limits.alert.enable"),title:s.enabled?r("limits.alert.disable"):r("limits.alert.enable"),className:`inline-flex h-9 w-9 items-center justify-center rounded-lg border border-oai-gray-200 dark:border-oai-gray-800 hover:bg-oai-gray-100 dark:hover:bg-oai-gray-800 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-oai-brand-500 ${s.enabled&&s.permissionBlocked?"text-amber-600 dark:text-amber-400":"text-oai-gray-600 dark:text-oai-gray-400 hover:text-oai-black dark:hover:text-white"}`,children:s.enabled?t.jsx(_e,{className:"h-4 w-4","aria-hidden":!0}):t.jsx(je,{className:"h-4 w-4","aria-hidden":!0})}),t.jsx(re,{to:"/settings?section=limits","aria-label":r("limits.page.openSettings"),title:r("limits.page.openSettings"),className:"shrink-0 inline-flex h-9 w-9 items-center justify-center rounded-lg border border-oai-gray-200 dark:border-oai-gray-800 text-oai-gray-600 dark:text-oai-gray-400 hover:bg-oai-gray-100 dark:hover:bg-oai-gray-800 hover:text-oai-black dark:hover:text-white transition-colors no-underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-oai-brand-500",children:t.jsx(ne,{className:"h-4 w-4","aria-hidden":!0})})]})]}),o?t.jsx(Ie,{}):t.jsxs(t.Fragment,{children:[i?t.jsx("p",{className:"mb-4 text-sm text-red-500 dark:text-red-400",children:r("shared.error.prefix",{error:i})}):null,t.jsx(et,{claude:a?.claude,codex:a?.codex,cursor:a?.cursor,gemini:a?.gemini,kimi:a?.kimi,kiro:a?.kiro,grok:a?.grok,antigravity:a?.antigravity,copilot:a?.copilot,zcode:a?.zcode,opencodeGo:a?.opencodeGo,qoder:a?.qoder,order:n.order,visibility:n.visibility,displayMode:n.displayMode})]})]})})})}export{ht as LimitsPage};
@@ -1 +0,0 @@
1
- import{r as o}from"./__vite-browser-external-BdRrPLk6.js";import{h as r,i as t,p as s}from"./react-DK5clHtY.js";function i(){!r.current&&t();const[e]=o.useState(s.current);return e}export{i as u};