tokentracker-cli 1.3.13 → 1.3.15

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 (121) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/dashboard/dist/assets/{AchievementBadge-DkNsd5tj.js → AchievementBadge-CSXb26DC.js} +1 -1
  4. package/dashboard/dist/assets/{AchievementsPage-Dr72Hcog.js → AchievementsPage-Bs6vIpd0.js} +2 -2
  5. package/dashboard/dist/assets/{AchievementsSection-CkOdGlnD.js → AchievementsSection-BO4u-574.js} +1 -1
  6. package/dashboard/dist/assets/{BadgeDetailModal-DADLfBsK.js → BadgeDetailModal-ic60vrZX.js} +1 -1
  7. package/dashboard/dist/assets/{BotAnimated-k6u1GRzw.js → BotAnimated-BHHAUEQL.js} +1 -1
  8. package/dashboard/dist/assets/{Card-Dk6s3h-P.js → Card-8t2FYLJV.js} +1 -1
  9. package/dashboard/dist/assets/{CloudCheckoutPage-DL0pvok0.js → CloudCheckoutPage-CXaDDial.js} +1 -1
  10. package/dashboard/dist/assets/{CloudPage-BizN1MZL.js → CloudPage-DN6s_UrT.js} +2 -2
  11. package/dashboard/dist/assets/{CommandPalette-B2crDNlV.js → CommandPalette-D7dHMpHK.js} +1 -1
  12. package/dashboard/dist/assets/{CommunityStatsModal-C6Rc5NME.js → CommunityStatsModal-C55r20Vb.js} +1 -1
  13. package/dashboard/dist/assets/{ConfirmModal-BrxBQn4n.js → ConfirmModal-jSEqSSnW.js} +1 -1
  14. package/dashboard/dist/assets/{Controls-C2mEPI72.js → Controls-CqmoR37l.js} +1 -1
  15. package/dashboard/dist/assets/{DashboardPage-BomPd7nt.js → DashboardPage-BLr2XmyZ.js} +1 -1
  16. package/dashboard/dist/assets/{DateRangePopover-Gz-N_D7O.js → DateRangePopover-z89rKqjK.js} +1 -1
  17. package/dashboard/dist/assets/{DevicePage-wmnNx9bd.js → DevicePage-Ddm5uKOw.js} +1 -1
  18. package/dashboard/dist/assets/{DialogClose-D1dzj_on.js → DialogClose-imfpTM8a.js} +1 -1
  19. package/dashboard/dist/assets/DialogDescription-BE5CNMW0.js +1 -0
  20. package/dashboard/dist/assets/{DialogTitle-BBxNf3O8.js → DialogTitle-Ca1-hka8.js} +1 -1
  21. package/dashboard/dist/assets/{ElectricLogo-DCopeDc8.js → ElectricLogo-CrnDjhtG.js} +1 -1
  22. package/dashboard/dist/assets/{FadeIn-DSndojVd.js → FadeIn-CAr2EMcK.js} +1 -1
  23. package/dashboard/dist/assets/{HeaderGithubStar-BBAGbevf.js → HeaderGithubStar-UK7qFFNh.js} +1 -1
  24. package/dashboard/dist/assets/{HoverTooltip-COD3xE9E.js → HoverTooltip-fs1HBOXB.js} +1 -1
  25. package/dashboard/dist/assets/{IpCheckPage-BtMWefop.js → IpCheckPage-Bk-MlPWf.js} +1 -1
  26. package/dashboard/dist/assets/{LandingPage-DN2IVBw7.js → LandingPage-DJnPCdqP.js} +2 -2
  27. package/dashboard/dist/assets/{LeaderboardPage-DkJowsRI.js → LeaderboardPage-wVjwsqyc.js} +2 -2
  28. package/dashboard/dist/assets/{LeaderboardProBadge-CRRphJNs.js → LeaderboardProBadge-BaQdHu06.js} +1 -1
  29. package/dashboard/dist/assets/{LeaderboardProfileModal-WmZAsZx5.js → LeaderboardProfileModal-D5ZZtIPl.js} +3 -3
  30. package/dashboard/dist/assets/{LeaderboardProfilePage-DWHu-eOp.js → LeaderboardProfilePage-BZsBL2jT.js} +1 -1
  31. package/dashboard/dist/assets/{LimitsPage-BRFAWm-1.js → LimitsPage-Cks_mKSL.js} +1 -1
  32. package/dashboard/dist/assets/{LocalOnlyNotice-BjJ8N4Zc.js → LocalOnlyNotice-DLnC_Tq4.js} +1 -1
  33. package/dashboard/dist/assets/{LoginCard-CYmjHoYK.js → LoginCard-FXZbjmOY.js} +1 -1
  34. package/dashboard/dist/assets/{LoginModal-DX1D9F8b.js → LoginModal-_R-0ZtpQ.js} +1 -1
  35. package/dashboard/dist/assets/{LoginPage-D7Ok7HiZ.js → LoginPage-MzDRyv1Q.js} +1 -1
  36. package/dashboard/dist/assets/{PetPage-BYISPev2.js → PetPage-DJ58EiPT.js} +2 -2
  37. package/dashboard/dist/assets/{PopoverPopup-BlzqlKqF.js → PopoverPopup-uQa7G-IO.js} +1 -1
  38. package/dashboard/dist/assets/{ProviderIcon-BuLwtYjj.js → ProviderIcon-xSNRuia-.js} +1 -1
  39. package/dashboard/dist/assets/{ResetPasswordPage-BJRKclq9.js → ResetPasswordPage-BcVcWbsW.js} +1 -1
  40. package/dashboard/dist/assets/{Select-0YyBw95W.js → Select-Dwix4ZFd.js} +1 -1
  41. package/dashboard/dist/assets/{SelectItemText-CZKyxUjE.js → SelectItemText-Bz5cn5Gk.js} +1 -1
  42. package/dashboard/dist/assets/{SelfHostPage-C_Afofs-.js → SelfHostPage-BLocCkUo.js} +1 -1
  43. package/dashboard/dist/assets/{ServiceStatusPage-0KpLdpon.js → ServiceStatusPage-CzMjS7EQ.js} +1 -1
  44. package/dashboard/dist/assets/{SessionsPage-YtSyWMd0.js → SessionsPage-Dqzuthrd.js} +1 -1
  45. package/dashboard/dist/assets/{SettingsPage-Bm641_AH.js → SettingsPage-DEdNhzKR.js} +3 -3
  46. package/dashboard/dist/assets/{SkillsPage-DNg-I2g_.js → SkillsPage-CqocOQID.js} +1 -1
  47. package/dashboard/dist/assets/{TokenGalaxy-BMN7WiRH.js → TokenGalaxy-B2sMNsM0.js} +1 -1
  48. package/dashboard/dist/assets/{TooltipPopup-BF56BHfc.js → TooltipPopup-LzbtjRSA.js} +1 -1
  49. package/dashboard/dist/assets/{TrendMonitor-D0ea5xMA.js → TrendMonitor-DpMcMWVh.js} +1 -1
  50. package/dashboard/dist/assets/{WidgetsPage-CIAoHmJG.js → WidgetsPage-aKfztwsk.js} +1 -1
  51. package/dashboard/dist/assets/{WrappedPage-CC_57Zr2.js → WrappedPage-NoY2hqbF.js} +1 -1
  52. package/dashboard/dist/assets/__vite-browser-external-BnGukaND.js +45 -0
  53. package/dashboard/dist/assets/{agent-logos-CcJUaB75.js → agent-logos-Oh8CLAYk.js} +1 -1
  54. package/dashboard/dist/assets/{arrow-left-CUiT31ZF.js → arrow-left-Mwggxctm.js} +1 -1
  55. package/dashboard/dist/assets/{arrow-right-Tds6Mert.js → arrow-right-Crx-kuck.js} +1 -1
  56. package/dashboard/dist/assets/{arrow-up-right-CGSxdyzM.js → arrow-up-right-uwoo8I0B.js} +1 -1
  57. package/dashboard/dist/assets/{calendar-days-Cc8AtMa3.js → calendar-days-C6MeKaqh.js} +1 -1
  58. package/dashboard/dist/assets/{check-CzJylQ9j.js → check-dsWQRYNj.js} +1 -1
  59. package/dashboard/dist/assets/{chevron-down-DyG9JVDO.js → chevron-down-BIf5bhyB.js} +1 -1
  60. package/dashboard/dist/assets/{cloud-checkout-DP5zddOq.js → cloud-checkout-GnFRQdnr.js} +1 -1
  61. package/dashboard/dist/assets/{composite-I_1t6PMI.js → composite-lINFdwLI.js} +1 -1
  62. package/dashboard/dist/assets/{download-B_LvkErh.js → download-B7eyvOxn.js} +1 -1
  63. package/dashboard/dist/assets/{external-link-DDA3ObBn.js → external-link-RNTsFDG4.js} +1 -1
  64. package/dashboard/dist/assets/{flame-BqpVWH_1.js → flame-uwCJ6brb.js} +1 -1
  65. package/dashboard/dist/assets/{format-tokens-D6QEOnGq.js → format-tokens-Bf7JxB4E.js} +1 -1
  66. package/dashboard/dist/assets/{gift-BxbKo3W6.js → gift-BY7kCGBK.js} +1 -1
  67. package/dashboard/dist/assets/{host-mode-o3qQY7tz.js → host-mode-Bs-UHw-7.js} +1 -1
  68. package/dashboard/dist/assets/{icons-oGPZPj2n.js → icons-CrLu8vlW.js} +1 -1
  69. package/dashboard/dist/assets/{index-DX--5z1g.js → index-CXQag63s.js} +1 -1
  70. package/dashboard/dist/assets/{index-BxtvQ1J7.js → index-DYIIk93n.js} +1 -1
  71. package/dashboard/dist/assets/{index-Byukv2Nu.js → index-DieuzFHA.js} +1 -1
  72. package/dashboard/dist/assets/{info-BoTz1AGZ.js → info-BteHQN_N.js} +1 -1
  73. package/dashboard/dist/assets/{link-2-C09a122s.js → link-2-C1RSbOHv.js} +1 -1
  74. package/dashboard/dist/assets/{loader-circle--9U0axVe.js → loader-circle-BM3x6_YL.js} +1 -1
  75. package/dashboard/dist/assets/{modifiers.esm-Cra0I6RP.js → modifiers.esm-BHzOJfH3.js} +1 -1
  76. package/dashboard/dist/assets/{monitor-smartphone-C1ENjmOu.js → monitor-smartphone-Ps3VptSt.js} +1 -1
  77. package/dashboard/dist/assets/{play-NqPqbW59.js → play-7MpFYU7a.js} +1 -1
  78. package/dashboard/dist/assets/{plus-DZP82JeP.js → plus-Dk-p9OaZ.js} +1 -1
  79. package/dashboard/dist/assets/{provider-display-BLo4k0bi.js → provider-display-Czwv4ClR.js} +1 -1
  80. package/dashboard/dist/assets/{react-CTLavVze.js → react-D9vco0ZF.js} +1 -1
  81. package/dashboard/dist/assets/{safePolygon-Yw5w5Nw8.js → safePolygon-Ca2iBTNb.js} +1 -1
  82. package/dashboard/dist/assets/{search-DgV6mpMO.js → search-Z2Hfw99-.js} +1 -1
  83. package/dashboard/dist/assets/{server-BybwAQjW.js → server-Dh_OraRG.js} +1 -1
  84. package/dashboard/dist/assets/{shield-check-BiTYwWdT.js → shield-check-59NUSZvk.js} +1 -1
  85. package/dashboard/dist/assets/{skills-api-Dx_Z8_SO.js → skills-api-Bguk8iPD.js} +1 -1
  86. package/dashboard/dist/assets/{sortable.esm-CmJnBLcr.js → sortable.esm-C9M-1k5o.js} +1 -1
  87. package/dashboard/dist/assets/{store-DzNIKGzf.js → store-nR9Ah4fr.js} +1 -1
  88. package/dashboard/dist/assets/{terminal-DPly-UPW.js → terminal-DKTXh9tj.js} +1 -1
  89. package/dashboard/dist/assets/{trash-DsL2ZAN5.js → trash-CQRRKbCs.js} +1 -1
  90. package/dashboard/dist/assets/{use-community-stats-CSTkXFed.js → use-community-stats-BoOd2Hhq.js} +1 -1
  91. package/dashboard/dist/assets/{use-latest-request-guard-CbAXXNlU.js → use-latest-request-guard-vQtFEBIX.js} +1 -1
  92. package/dashboard/dist/assets/{use-limits-display-prefs-mDl6Yv_-.js → use-limits-display-prefs-BRTj9_xd.js} +1 -1
  93. package/dashboard/dist/assets/{use-native-settings-Bu2C3b20.js → use-native-settings-CC6uEn3j.js} +1 -1
  94. package/dashboard/dist/assets/{use-ordered-list-DkGSfMTv.js → use-ordered-list-BUx6eIN7.js} +1 -1
  95. package/dashboard/dist/assets/use-reduced-motion-BZBrXeyc.js +1 -0
  96. package/dashboard/dist/assets/{use-session-efficiency-pref-B2GDf83h.js → use-session-efficiency-pref-BsUypXPb.js} +1 -1
  97. package/dashboard/dist/assets/{use-transform-BVVduBPJ.js → use-transform-oomGXI86.js} +1 -1
  98. package/dashboard/dist/assets/{use-usage-limits-fuzpbbVh.js → use-usage-limits-CXeCKJZ_.js} +1 -1
  99. package/dashboard/dist/assets/{useCurrency-CdDQzroJ.js → useCurrency-DIZEXq5g.js} +1 -1
  100. package/dashboard/dist/assets/{usePositioner-b6XXJtxE.js → usePositioner-Drh2sy7w.js} +1 -1
  101. package/dashboard/dist/assets/{useTokenFormat-90RoMQgI.js → useTokenFormat-DKURSOqb.js} +1 -1
  102. package/dashboard/dist/assets/{zap-xEHzTW-T.js → zap-BQ8nGK7b.js} +1 -1
  103. package/dashboard/dist/index.html +1 -1
  104. package/dashboard/dist/ip-check.html +1 -1
  105. package/dashboard/dist/leaderboard.html +1 -1
  106. package/dashboard/dist/pricing.html +1 -1
  107. package/dashboard/dist/share.html +1 -1
  108. package/dashboard/dist/terms.html +1 -1
  109. package/package.json +1 -1
  110. package/src/commands/status.js +5 -1
  111. package/src/commands/sync.js +28 -1
  112. package/src/lib/jsonl-lines.js +34 -4
  113. package/src/lib/pricing/curated-overrides.json +47 -0
  114. package/src/lib/pricing/matcher.js +11 -3
  115. package/src/lib/pricing/seed-snapshot.json +1 -1
  116. package/src/lib/rollout.js +148 -52
  117. package/src/lib/session-analytics.js +11 -10
  118. package/src/lib/upload-queue.js +1 -1
  119. package/dashboard/dist/assets/DialogDescription-ChbOGLc_.js +0 -1
  120. package/dashboard/dist/assets/__vite-browser-external-CPskAZuH.js +0 -45
  121. package/dashboard/dist/assets/use-reduced-motion-6nBw3cR5.js +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tokentracker-cli",
3
- "version": "1.3.13",
3
+ "version": "1.3.15",
4
4
  "description": "Local-first AI coding token usage and cost tracker for 45 tools, with a dashboard, desktop pet, widgets, achievements, and native macOS/Windows apps.",
5
5
  "main": "src/cli.js",
6
6
  "bin": {
@@ -106,6 +106,7 @@ const {
106
106
  resolveCopilotAppDbPath,
107
107
  resolveCopilotAppDbPaths,
108
108
  probeWslDistros,
109
+ resolveZcodeInstallPaths,
109
110
  } = require("../lib/rollout");
110
111
  const {
111
112
  TRAE_CN_USAGE_ENV,
@@ -584,7 +585,10 @@ async function cmdStatus(argv = []) {
584
585
  const wslZcodeDir = process.platform === "win32" && wsl.shouldProbeWsl(process.env)
585
586
  ? wsl.discoverWslHome(".zcode")
586
587
  : null;
587
- const zcodePaths = resolveInstallPaths({ nativeValue: zcodeNativeValue, wslValue: wslZcodeDir ? path.join(wslZcodeDir, "cli", "db", "db.sqlite") : null });
588
+ const zcodePaths = resolveZcodeInstallPaths(
589
+ { nativeValue: zcodeNativeValue, wslValue: wslZcodeDir ? path.join(wslZcodeDir, "cli", "db", "db.sqlite") : null },
590
+ process.env, { cursors },
591
+ );
588
592
  const zcodeActive = formatResolvedPaths(zcodePaths);
589
593
  const zcodeInstalled = zcodeActive.length > 0;
590
594
  const zcodeDbPath = zcodeActive.join(" | ");
@@ -145,6 +145,8 @@ const {
145
145
  toUtcHalfHourStart,
146
146
  totalsKey,
147
147
  claudeMessageDedupKey,
148
+ hasZcodeCursorState,
149
+ resolveZcodeInstallPaths,
148
150
  } = require("../lib/rollout");
149
151
  const { computeClaudeGroundTruthBuckets } = require("../lib/claude-categorizer");
150
152
  const { createProgress, renderBar, formatNumber, formatBytes } = require("../lib/progress");
@@ -1733,8 +1735,23 @@ async function cmdSync(argv, context = {}) {
1733
1735
  const wslZcodeDir = process.platform === "win32" && wsl.shouldProbeWsl(process.env)
1734
1736
  ? wsl.discoverWslHome(".zcode")
1735
1737
  : null;
1736
- const zcodePaths = resolveInstallPaths({ nativeValue: zcodeNativeValue, wslValue: wslZcodeDir ? path.join(wslZcodeDir, "cli", "db", "db.sqlite") : null });
1738
+ const zcodeWslValue = wslZcodeDir ? path.join(wslZcodeDir, "cli", "db", "db.sqlite") : null;
1739
+ const zcodePaths = resolveZcodeInstallPaths(
1740
+ { nativeValue: zcodeNativeValue, wslValue: zcodeWslValue }, process.env,
1741
+ { cursors },
1742
+ );
1737
1743
  if (zcodePaths.native || zcodePaths.wsl) {
1744
+ const mode = wsl.getWslMode(process.env);
1745
+ if (process.platform === "win32" && ["native-first", "wsl-first"].includes(mode) &&
1746
+ !cursors.zcodeInstallSelection && hasZcodeCursorState(cursors)) {
1747
+ // Preserve legacy ownership before a repair can clear old buckets,
1748
+ // even when the selected database currently has no rows to parse.
1749
+ cursors.zcodeInstallSelection = {
1750
+ mode, zcodeHome: process.env.ZCODE_HOME?.trim() || null,
1751
+ dbPath: zcodePaths.native || zcodePaths.wsl,
1752
+ };
1753
+ cursorStore.requiresCommit = true;
1754
+ }
1738
1755
  if (progress?.enabled) progress.start(`Parsing ZCode ${renderBar(0)} | buckets 0`);
1739
1756
  try {
1740
1757
  const nativeUsageAvailable = [zcodePaths.native, zcodePaths.wsl]
@@ -1761,6 +1778,16 @@ async function cmdSync(argv, context = {}) {
1761
1778
  cursors, getParams: (p) => ({ dbPath: p, readFn: readZcodeDbMessages, source: "zcode", cursorKey: "zcode" }),
1762
1779
  queuePath, projectQueuePath, onProgress: makeProviderProgress("ZCode"),
1763
1780
  });
1781
+ if (zcodeResult.recordsProcessed > 0) {
1782
+ if (process.platform === "win32" && ["native-first", "wsl-first"].includes(mode)) {
1783
+ cursors.zcodeInstallSelection = {
1784
+ mode, zcodeHome: process.env.ZCODE_HOME?.trim() || null,
1785
+ dbPath: zcodePaths.native || zcodePaths.wsl,
1786
+ };
1787
+ } else {
1788
+ delete cursors.zcodeInstallSelection;
1789
+ }
1790
+ }
1764
1791
  } catch (err) { warnProviderParseFailure("ZCode", err, opts); }
1765
1792
  }
1766
1793
  }
@@ -5,6 +5,9 @@
5
5
  * only LF as a record separator so valid U+2028/U+2029 characters inside JSON
6
6
  * strings remain part of the record. Reading raw bytes keeps byte budgets exact
7
7
  * and lets malformed UTF-8 fail closed.
8
+ * Records longer than maxRecordBytes content bytes (excluding LF) are reported
9
+ * as { line: null, utf8Valid: null, oversized: true } without being buffered
10
+ * beyond the limit or decoded.
8
11
  */
9
12
  class PhysicalJsonlLimitError extends Error {
10
13
  constructor(maxPhysicalBytes) {
@@ -26,6 +29,7 @@ function decodePhysicalLine(buffer, { stripCr = false } = {}) {
26
29
  async function* physicalJsonlRecords(input, {
27
30
  invalidUtf8 = "throw",
28
31
  maxPhysicalBytes = Infinity,
32
+ maxRecordBytes = Infinity,
29
33
  } = {}) {
30
34
  if (invalidUtf8 !== "throw" && invalidUtf8 !== "record") {
31
35
  throw new TypeError(`unsupported invalidUtf8 policy: ${invalidUtf8}`);
@@ -33,8 +37,12 @@ async function* physicalJsonlRecords(input, {
33
37
  const byteLimit = Number.isFinite(maxPhysicalBytes)
34
38
  ? Math.max(0, Number(maxPhysicalBytes))
35
39
  : Infinity;
40
+ const recordLimit = Number.isFinite(maxRecordBytes)
41
+ ? Math.max(0, Number(maxRecordBytes))
42
+ : Infinity;
36
43
  const fragments = [];
37
44
  let fragmentsBytes = 0;
45
+ let oversized = false;
38
46
  let physicalBytesRead = 0;
39
47
 
40
48
  for await (const value of input) {
@@ -53,6 +61,17 @@ async function* physicalJsonlRecords(input, {
53
61
  if (physicalBytesRead + physicalBytes > byteLimit) {
54
62
  throw new PhysicalJsonlLimitError(byteLimit);
55
63
  }
64
+ const contentBytes = fragmentsBytes + fragment.length;
65
+ if (oversized || contentBytes > recordLimit) {
66
+ fragments.length = 0;
67
+ fragmentsBytes = 0;
68
+ oversized = false;
69
+ physicalBytesRead += physicalBytes;
70
+ start = newline + 1;
71
+ newline = chunk.indexOf(0x0a, start);
72
+ yield { line: null, utf8Valid: null, oversized: true, physicalBytes, terminated: true };
73
+ continue;
74
+ }
56
75
  const lineBuffer = fragments.length === 0
57
76
  ? fragment
58
77
  : Buffer.concat([...fragments, fragment], fragmentsBytes + fragment.length);
@@ -66,10 +85,10 @@ async function* physicalJsonlRecords(input, {
66
85
  line = decodePhysicalLine(lineBuffer, { stripCr: true });
67
86
  } catch (error) {
68
87
  if (invalidUtf8 === "throw") throw error;
69
- yield { line: null, utf8Valid: false, physicalBytes, terminated: true };
88
+ yield { line: null, utf8Valid: false, oversized: false, physicalBytes, terminated: true };
70
89
  continue;
71
90
  }
72
- yield { line, utf8Valid: true, physicalBytes, terminated: true };
91
+ yield { line, utf8Valid: true, oversized: false, physicalBytes, terminated: true };
73
92
  }
74
93
 
75
94
  if (start < chunk.length) {
@@ -77,12 +96,23 @@ async function* physicalJsonlRecords(input, {
77
96
  if (physicalBytesRead + fragmentsBytes + fragment.length > byteLimit) {
78
97
  throw new PhysicalJsonlLimitError(byteLimit);
79
98
  }
80
- fragments.push(Buffer.from(fragment));
99
+ if (!oversized) {
100
+ if (fragmentsBytes + fragment.length > recordLimit) {
101
+ fragments.length = 0;
102
+ oversized = true;
103
+ } else {
104
+ fragments.push(Buffer.from(fragment));
105
+ }
106
+ }
81
107
  fragmentsBytes += fragment.length;
82
108
  }
83
109
  }
84
110
 
85
111
  if (fragmentsBytes > 0) {
112
+ if (oversized) {
113
+ yield { line: null, utf8Valid: null, oversized: true, physicalBytes: fragmentsBytes, terminated: false };
114
+ return;
115
+ }
86
116
  const lineBuffer = fragments.length === 1
87
117
  ? fragments[0]
88
118
  : Buffer.concat(fragments, fragmentsBytes);
@@ -94,7 +124,7 @@ async function* physicalJsonlRecords(input, {
94
124
  if (invalidUtf8 === "throw") throw error;
95
125
  utf8Valid = false;
96
126
  }
97
- yield { line, utf8Valid, physicalBytes: fragmentsBytes, terminated: false };
127
+ yield { line, utf8Valid, oversized: false, physicalBytes: fragmentsBytes, terminated: false };
98
128
  }
99
129
  }
100
130
 
@@ -201,6 +201,25 @@
201
201
  "output": 7.5,
202
202
  "cache_read": 0.15
203
203
  },
204
+ "composer-2.5": {
205
+ "input": 0.5,
206
+ "output": 2.5,
207
+ "cache_read": 0.2,
208
+ "note": "Cursor Composer 2.5. Cursor Models & Pricing: $0.50/M input, $0.20/M cached input, $2.50/M output; no cache-write rate is published. https://cursor.com/docs/models-and-pricing"
209
+ },
210
+ "composer-2.5-fast": {
211
+ "input": 3.0,
212
+ "output": 15.0,
213
+ "cache_read": 0.5,
214
+ "note": "Cursor Composer 2.5 Fast. Cursor Models & Pricing: $3/M input, $0.50/M cached input, $15/M output. Kept separate from the cheaper base SKU."
215
+ },
216
+ "gemini-4-argon": {
217
+ "input": 2.0,
218
+ "output": 10.0,
219
+ "cache_read": 0.1,
220
+ "cache_write": 0,
221
+ "note": "Google Gemini 4 Argon introductory list rate (through 2026-11-30) matching Cursor Other Models pool: $2/M input, $0.10/M cached input, $10/M output. Effort suffixes (-high/-medium/-low/-minimal) are stripped by normalizeCursorModel. Sources: https://cursor.com/docs/models-and-pricing and https://ai.google.dev/gemini-api/docs/pricing"
222
+ },
204
223
  "MiniMax-M2.7": {
205
224
  "input": 0.3,
206
225
  "output": 1.2,
@@ -277,6 +296,34 @@
277
296
  "cache_write": 0,
278
297
  "note": "Cursor Grok 4.5 Fast rate. Cursor publishes $4/M input and $18/M output; the Cursor usage breakdown reports $1/M cached input. Kept separate from the cheaper base SKU."
279
298
  },
299
+ "cursor-grok-4.6": {
300
+ "input": 2.0,
301
+ "output": 6.0,
302
+ "cache_read": 0.5,
303
+ "cache_write": 0,
304
+ "note": "Cursor Grok 4.6 base rate. Cursor Models & Pricing: $2/M input, $0.50/M cached input, $6/M output; no cache-write rate is published."
305
+ },
306
+ "cursor-grok-4.6-fast": {
307
+ "input": 4.0,
308
+ "output": 12.0,
309
+ "cache_read": 1.0,
310
+ "cache_write": 0,
311
+ "note": "Cursor Grok 4.6 Fast rate. Cursor publishes $4/M input, $1/M cached input, $12/M output. Kept separate from the cheaper base SKU."
312
+ },
313
+ "cursor-grok-4.7": {
314
+ "input": 2.0,
315
+ "output": 6.0,
316
+ "cache_read": 0.5,
317
+ "cache_write": 0,
318
+ "note": "Cursor Grok 4.7 base rate. Cursor Models & Pricing: $2/M input, $0.50/M cached input, $6/M output. Long-context (>256k) premiums are not applied here yet because Cursor CSV rows do not expose per-request long-context flags."
319
+ },
320
+ "cursor-grok-4.7-fast": {
321
+ "input": 4.0,
322
+ "output": 12.0,
323
+ "cache_read": 1.0,
324
+ "cache_write": 0,
325
+ "note": "Cursor Grok 4.7 Fast rate. Cursor publishes $4/M input, $1/M cached input, $12/M output. Kept separate from the cheaper base SKU."
326
+ },
280
327
  "grok-4-0709": {
281
328
  "input": 3.0,
282
329
  "output": 15.0,
@@ -122,7 +122,9 @@ function normalizeClaudeModel(model) {
122
122
 
123
123
  // Cursor decorates model ids with reasoning effort and sometimes places the
124
124
  // Claude version before the tier. Normalize those lookup-only aliases while
125
- // preserving Grok 4.5's distinct Fast SKU (its rate is not the base rate).
125
+ // preserving Cursor Grok Fast SKUs (4.5/4.6/4.7 Fast rates are not the base
126
+ // rates). Gemini 4 Argon effort suffixes (-high/-medium/-low/-minimal) are
127
+ // stripped with the shared decorations set below.
126
128
  function normalizeCursorModel(model) {
127
129
  if (!model || typeof model !== "string") return model;
128
130
  let m = model
@@ -135,6 +137,12 @@ function normalizeCursorModel(model) {
135
137
  const parts = m.split("-");
136
138
  const isFast = parts.includes("fast");
137
139
 
140
+ if (/^(?:cursor-)?grok-4[.-]7(?:-|$)/.test(m)) {
141
+ return isFast ? "cursor-grok-4.7-fast" : "cursor-grok-4.7";
142
+ }
143
+ if (/^(?:cursor-)?grok-4[.-]6(?:-|$)/.test(m)) {
144
+ return isFast ? "cursor-grok-4.6-fast" : "cursor-grok-4.6";
145
+ }
138
146
  if (/^(?:cursor-)?grok-4[.-]5(?:-|$)/.test(m)) {
139
147
  return isFast ? "cursor-grok-4.5-fast" : "cursor-grok-4.5";
140
148
  }
@@ -142,8 +150,8 @@ function normalizeCursorModel(model) {
142
150
  // `fast` can be a separately priced SKU (for example composer-2-fast and
143
151
  // claude-opus-5-fast). Preserve it for the exact lookups below; when it is
144
152
  // merely a decoration, lookupPricing's later suffix-strip still falls back
145
- // to the base LiteLLM model.
146
- const decorations = new Set(["thinking", "xhigh", "high", "medium", "low"]);
153
+ // to the base LiteLLM model. Gemini Argon uses "minimal" as an effort level.
154
+ const decorations = new Set(["thinking", "xhigh", "high", "medium", "low", "minimal"]);
147
155
  m = parts.filter((part) => !decorations.has(part)).join("-");
148
156
  if (m.startsWith("claude-")) return normalizeClaudeModel(m);
149
157
  return m;