tokentracker-cli 0.94.0 → 0.94.1

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 (102) hide show
  1. package/dashboard/dist/assets/{AchievementBadge-DPqwk2zI.js → AchievementBadge-DnmgEa4q.js} +1 -1
  2. package/dashboard/dist/assets/{AchievementsPage-CELHoMQt.js → AchievementsPage-B7YTbAuK.js} +2 -2
  3. package/dashboard/dist/assets/{AchievementsSection-DdAC0VCb.js → AchievementsSection-CwgT5sqH.js} +1 -1
  4. package/dashboard/dist/assets/{BadgeDetailModal-Dd4I1SpM.js → BadgeDetailModal-Dets6jzW.js} +1 -1
  5. package/dashboard/dist/assets/{BotAnimated-DL2-4mnm.js → BotAnimated-5KwUvC9F.js} +1 -1
  6. package/dashboard/dist/assets/{Card-B_MpSRse.js → Card-jf9w-4-N.js} +1 -1
  7. package/dashboard/dist/assets/{ClawdAnimated-BLZZ4rG6.js → ClawdAnimated-CGxDVQ0c.js} +2 -2
  8. package/dashboard/dist/assets/{CommandPalette-B-vfdIbH.js → CommandPalette-B1bUUf32.js} +1 -1
  9. package/dashboard/dist/assets/{CommunityStatsModal-aAico565.js → CommunityStatsModal-DRDpZycV.js} +1 -1
  10. package/dashboard/dist/assets/{ConfirmModal-DLnRwUXC.js → ConfirmModal-BR-aIRH9.js} +1 -1
  11. package/dashboard/dist/assets/{Controls-FZ8wEN5w.js → Controls-CbHsJAqV.js} +1 -1
  12. package/dashboard/dist/assets/{DashboardPage-BByRBsbt.js → DashboardPage-B5XMQoxy.js} +1 -1
  13. package/dashboard/dist/assets/{DevicePage-D2IzPc5o.js → DevicePage-DDlicLLn.js} +1 -1
  14. package/dashboard/dist/assets/{DialogClose-BaqQaUUk.js → DialogClose-B89uLXqp.js} +1 -1
  15. package/dashboard/dist/assets/DialogDescription-DiVbwvTR.js +1 -0
  16. package/dashboard/dist/assets/{DialogTitle-DrbKjtuS.js → DialogTitle-jOyycYKF.js} +1 -1
  17. package/dashboard/dist/assets/{FadeIn-GddKDE8i.js → FadeIn-BEND42ze.js} +1 -1
  18. package/dashboard/dist/assets/{HeaderGithubStar-DUu-Z5mE.js → HeaderGithubStar-Dacl1WGS.js} +1 -1
  19. package/dashboard/dist/assets/{HoverTooltip-BmDkY35A.js → HoverTooltip-B2Mh2LTi.js} +1 -1
  20. package/dashboard/dist/assets/{IpCheckPage-CGJyqWk2.js → IpCheckPage-CPEuRhiU.js} +1 -1
  21. package/dashboard/dist/assets/{LandingPage-Bd91ALUj.js → LandingPage-BYWNR_dx.js} +2 -2
  22. package/dashboard/dist/assets/{LeaderboardAvatar-BGGUwXFd.js → LeaderboardAvatar-B9_5LDVj.js} +1 -1
  23. package/dashboard/dist/assets/{LeaderboardPage-BMEqHwif.js → LeaderboardPage-_Hl1NaIa.js} +2 -2
  24. package/dashboard/dist/assets/{LeaderboardProfileModal-BSweJqm2.js → LeaderboardProfileModal-Cydp7CyA.js} +3 -3
  25. package/dashboard/dist/assets/{LeaderboardProfilePage-CRrI3RFz.js → LeaderboardProfilePage-Dz0ecujs.js} +1 -1
  26. package/dashboard/dist/assets/{LimitsPage-XIRDv46K.js → LimitsPage-CmdT2qOZ.js} +1 -1
  27. package/dashboard/dist/assets/{LocalOnlyNotice-CCD-lGWG.js → LocalOnlyNotice-DhuPGUkw.js} +1 -1
  28. package/dashboard/dist/assets/{LoginCard-lDuqSv4f.js → LoginCard-DQtHaX_5.js} +1 -1
  29. package/dashboard/dist/assets/{LoginModal-DStt5VXN.js → LoginModal-DvpPRnYV.js} +1 -1
  30. package/dashboard/dist/assets/{LoginPage-dmVPSL72.js → LoginPage-DOjfmdwb.js} +1 -1
  31. package/dashboard/dist/assets/{PetPage-ybcZRctF.js → PetPage-Dd6U9fh2.js} +1 -1
  32. package/dashboard/dist/assets/{PopoverPopup-Dar_UjxF.js → PopoverPopup-B1V01u10.js} +1 -1
  33. package/dashboard/dist/assets/{ProviderIcon-Ct9tILpz.js → ProviderIcon-BLRe55c7.js} +1 -1
  34. package/dashboard/dist/assets/{ResetPasswordPage-B4yLh5zx.js → ResetPasswordPage-BJ95vy1S.js} +1 -1
  35. package/dashboard/dist/assets/{SegmentedControl-BOE1CEzq.js → SegmentedControl-DacS_m9M.js} +1 -1
  36. package/dashboard/dist/assets/{Select-D-bSh7Zz.js → Select-bQDO5BEA.js} +1 -1
  37. package/dashboard/dist/assets/{SelectItemText-DMYjXXq4.js → SelectItemText-CUGrs9CY.js} +1 -1
  38. package/dashboard/dist/assets/{ServiceStatusPage-CaleS-6_.js → ServiceStatusPage-CsERvmVC.js} +1 -1
  39. package/dashboard/dist/assets/SessionsPage-0VvqEfPx.js +2 -0
  40. package/dashboard/dist/assets/{SettingsPage-iJH0Yyah.js → SettingsPage-9EHh2HfD.js} +2 -2
  41. package/dashboard/dist/assets/{SkillsPage-BkzJOBLk.js → SkillsPage-B1AcLX41.js} +1 -1
  42. package/dashboard/dist/assets/{TokenGalaxy-CuXKoMPg.js → TokenGalaxy-DSKTHQSs.js} +1 -1
  43. package/dashboard/dist/assets/{ToolbarRootContext-Dx5GB7F5.js → ToolbarRootContext-DP4mQLbq.js} +1 -1
  44. package/dashboard/dist/assets/{TrendMonitor-BuKmsznP.js → TrendMonitor-rabtcE5w.js} +1 -1
  45. package/dashboard/dist/assets/{WidgetsPage-DUaIyGtu.js → WidgetsPage-Cr6Wg9QX.js} +1 -1
  46. package/dashboard/dist/assets/{WrappedPage-BzqlcAUC.js → WrappedPage-DqQvRcnA.js} +1 -1
  47. package/dashboard/dist/assets/{__vite-browser-external-CVIGknXl.js → __vite-browser-external-C8KwSyTz.js} +12 -12
  48. package/dashboard/dist/assets/{agent-logos-BdWWxza6.js → agent-logos-BjIh_mqf.js} +1 -1
  49. package/dashboard/dist/assets/{arrow-up-right-CANSzmm-.js → arrow-up-right-BIhbN0NO.js} +1 -1
  50. package/dashboard/dist/assets/{check-BnJpzXRZ.js → check-U-wNzPvd.js} +1 -1
  51. package/dashboard/dist/assets/{chevron-right-DJm0mbG0.js → chevron-right-Du-QVNj4.js} +1 -1
  52. package/dashboard/dist/assets/{composite-Ccj6KQmh.js → composite-BR91CxNl.js} +1 -1
  53. package/dashboard/dist/assets/{copy-C2Yc8Evu.js → copy-Bw3hXBCu.js} +1 -1
  54. package/dashboard/dist/assets/{download-B52JTk6Y.js → download-WOqcQzvK.js} +1 -1
  55. package/dashboard/dist/assets/{external-link-DayTwZx-.js → external-link-BZtf6WfS.js} +1 -1
  56. package/dashboard/dist/assets/{flame-B8GEX2yT.js → flame-B5kp2VI9.js} +1 -1
  57. package/dashboard/dist/assets/{format-tokens-mhkbohkb.js → format-tokens-BOCnuMuJ.js} +1 -1
  58. package/dashboard/dist/assets/{icons-o8bPXqRP.js → icons-CA3FiIa_.js} +1 -1
  59. package/dashboard/dist/assets/{index-MBVWUKpA.js → index-DQaanK52.js} +1 -1
  60. package/dashboard/dist/assets/{index-Bp0ZHDtz.js → index-DjWC63Bs.js} +1 -1
  61. package/dashboard/dist/assets/{index-CK_CduLm.js → index-mEG0HZ-a.js} +1 -1
  62. package/dashboard/dist/assets/{info-D94QM_vX.js → info-Djer9i3-.js} +1 -1
  63. package/dashboard/dist/assets/{limits-providers-BLzMyCiy.js → limits-providers-F-RnNFAb.js} +1 -1
  64. package/dashboard/dist/assets/{link-2-CqBmFaDI.js → link-2-DV4ocD0l.js} +1 -1
  65. package/dashboard/dist/assets/{loader-circle-SaxUpDR6.js → loader-circle-DJK72c-o.js} +1 -1
  66. package/dashboard/dist/assets/{maximize-2-BoXqARks.js → maximize-2-BwBA_lMm.js} +1 -1
  67. package/dashboard/dist/assets/{modifiers.esm-Conh_-BD.js → modifiers.esm-B3sl4qyZ.js} +1 -1
  68. package/dashboard/dist/assets/{monitor-smartphone-D6qLR9qd.js → monitor-smartphone-BUTpM4ng.js} +1 -1
  69. package/dashboard/dist/assets/{plus-D51mjIc2.js → plus-BA9RP5L6.js} +1 -1
  70. package/dashboard/dist/assets/{provider-display-DpHPjd_s.js → provider-display-DqsJzGSr.js} +1 -1
  71. package/dashboard/dist/assets/{react-D_AcI466.js → react-BYw5AVSz.js} +1 -1
  72. package/dashboard/dist/assets/{search-CwLcNdvZ.js → search-BzcnFWVD.js} +1 -1
  73. package/dashboard/dist/assets/{skills-api-Dqi7Mjgo.js → skills-api-vAME1P7G.js} +1 -1
  74. package/dashboard/dist/assets/{sortable.esm-BPDlUxPb.js → sortable.esm-BpEiRqqI.js} +1 -1
  75. package/dashboard/dist/assets/{store-ikeRIRGd.js → store-GeT5fhRX.js} +1 -1
  76. package/dashboard/dist/assets/{terminal-BfeX3L5T.js → terminal-CZCMYQ8K.js} +1 -1
  77. package/dashboard/dist/assets/{trash-2-5_Qlp1k7.js → trash-2-DzlWEwKO.js} +1 -1
  78. package/dashboard/dist/assets/{use-community-stats-D90Fy2_j.js → use-community-stats-DOvJfj-i.js} +1 -1
  79. package/dashboard/dist/assets/{use-limits-display-prefs-D4BYFaa-.js → use-limits-display-prefs-BmLs4HyN.js} +1 -1
  80. package/dashboard/dist/assets/{use-ordered-list-DJxLNdXY.js → use-ordered-list-BgozDSSV.js} +1 -1
  81. package/dashboard/dist/assets/use-reduced-motion-Bc3RFJdg.js +1 -0
  82. package/dashboard/dist/assets/{use-session-efficiency-pref-CAX_GqXc.js → use-session-efficiency-pref-HP1ckVkS.js} +1 -1
  83. package/dashboard/dist/assets/{use-transform-CeW6Z5R0.js → use-transform-B4VSogOx.js} +1 -1
  84. package/dashboard/dist/assets/{use-usage-limits-5HP8k9a3.js → use-usage-limits-DNNhD2H6.js} +1 -1
  85. package/dashboard/dist/assets/{useCurrency-BarGeFyK.js → useCurrency-CSuzCBAL.js} +1 -1
  86. package/dashboard/dist/assets/{useTokenFormat-DUJ9iT9H.js → useTokenFormat-ClnL9OFe.js} +1 -1
  87. package/dashboard/dist/assets/{zap--m0IWoI3.js → zap-C_T9CCiS.js} +1 -1
  88. package/dashboard/dist/index.html +1 -1
  89. package/dashboard/dist/ip-check.html +1 -1
  90. package/dashboard/dist/leaderboard.html +1 -1
  91. package/dashboard/dist/share.html +1 -1
  92. package/package.json +1 -1
  93. package/src/lib/grok-context-breakdown.js +24 -33
  94. package/src/lib/grok-usage.js +95 -0
  95. package/src/lib/local-api.js +2 -0
  96. package/src/lib/pricing/index.js +10 -0
  97. package/src/lib/pricing/seed-snapshot.json +1 -1
  98. package/src/lib/rollout.js +59 -44
  99. package/src/lib/session-analytics.js +100 -40
  100. package/dashboard/dist/assets/DialogDescription-BUrh0Jod.js +0 -1
  101. package/dashboard/dist/assets/SessionsPage-DOaY6_E9.js +0 -2
  102. package/dashboard/dist/assets/use-reduced-motion-yE3T3cat.js +0 -1
@@ -15,6 +15,7 @@ const {
15
15
  createUsageDeltaState,
16
16
  snapshotUsageBaselines,
17
17
  } = require("./codex-token-usage");
18
+ const { USD_TICKS_PER_USD, normalizeGrokUsage } = require("./grok-usage");
18
19
 
19
20
  const DEFAULT_SOURCE = "codex";
20
21
  const DEFAULT_MODEL = "unknown";
@@ -2887,6 +2888,7 @@ async function enqueueTouchedBuckets({ queuePath, hourlyState, touchedBuckets })
2887
2888
  reasoning_output_tokens: zeroTotals.reasoning_output_tokens,
2888
2889
  total_tokens: zeroTotals.total_tokens,
2889
2890
  billable_total_tokens: zeroTotals.billable_total_tokens,
2891
+ total_cost_usd: zeroTotals.total_cost_usd,
2890
2892
  conversation_count: zeroTotals.conversation_count,
2891
2893
  }),
2892
2894
  );
@@ -2905,10 +2907,12 @@ async function enqueueTouchedBuckets({ queuePath, hourlyState, touchedBuckets })
2905
2907
  hour_start: group.hourStart,
2906
2908
  input_tokens: zeroTotals.input_tokens,
2907
2909
  cached_input_tokens: zeroTotals.cached_input_tokens,
2910
+ cache_creation_input_tokens: zeroTotals.cache_creation_input_tokens,
2908
2911
  output_tokens: zeroTotals.output_tokens,
2909
2912
  reasoning_output_tokens: zeroTotals.reasoning_output_tokens,
2910
2913
  total_tokens: zeroTotals.total_tokens,
2911
2914
  billable_total_tokens: zeroTotals.billable_total_tokens,
2915
+ total_cost_usd: zeroTotals.total_cost_usd,
2912
2916
  conversation_count: zeroTotals.conversation_count,
2913
2917
  }),
2914
2918
  );
@@ -2923,7 +2927,8 @@ async function enqueueTouchedBuckets({ queuePath, hourlyState, touchedBuckets })
2923
2927
  totals = cloneTotals(bucket.totals);
2924
2928
  addTotals(totals, unknownBucket.totals);
2925
2929
  }
2926
- const key = totalsKey(totals);
2930
+ const usagePrecision = bucket.usage_precision || null;
2931
+ const key = usagePrecision ? `${totalsKey(totals)}|${usagePrecision}` : totalsKey(totals);
2927
2932
  if (bucket.queuedKey === key) continue;
2928
2933
  toAppend.push(
2929
2934
  JSON.stringify({
@@ -2937,6 +2942,8 @@ async function enqueueTouchedBuckets({ queuePath, hourlyState, touchedBuckets })
2937
2942
  reasoning_output_tokens: totals.reasoning_output_tokens,
2938
2943
  total_tokens: totals.total_tokens,
2939
2944
  billable_total_tokens: totals.billable_total_tokens ?? totals.total_tokens,
2945
+ total_cost_usd: totals.total_cost_usd || 0,
2946
+ usage_precision: usagePrecision || undefined,
2940
2947
  conversation_count: totals.conversation_count,
2941
2948
  }),
2942
2949
  );
@@ -2960,10 +2967,12 @@ async function enqueueTouchedBuckets({ queuePath, hourlyState, touchedBuckets })
2960
2967
  hour_start: group.hourStart,
2961
2968
  input_tokens: zeroTotals.input_tokens,
2962
2969
  cached_input_tokens: zeroTotals.cached_input_tokens,
2970
+ cache_creation_input_tokens: zeroTotals.cache_creation_input_tokens,
2963
2971
  output_tokens: zeroTotals.output_tokens,
2964
2972
  reasoning_output_tokens: zeroTotals.reasoning_output_tokens,
2965
2973
  total_tokens: zeroTotals.total_tokens,
2966
2974
  billable_total_tokens: zeroTotals.billable_total_tokens,
2975
+ total_cost_usd: zeroTotals.total_cost_usd,
2967
2976
  conversation_count: zeroTotals.conversation_count,
2968
2977
  }),
2969
2978
  );
@@ -2987,6 +2996,7 @@ async function enqueueTouchedBuckets({ queuePath, hourlyState, touchedBuckets })
2987
2996
  reasoning_output_tokens: zeroTotals.reasoning_output_tokens,
2988
2997
  total_tokens: zeroTotals.total_tokens,
2989
2998
  billable_total_tokens: zeroTotals.billable_total_tokens,
2999
+ total_cost_usd: zeroTotals.total_cost_usd,
2990
3000
  conversation_count: zeroTotals.conversation_count,
2991
3001
  }),
2992
3002
  );
@@ -2994,7 +3004,10 @@ async function enqueueTouchedBuckets({ queuePath, hourlyState, touchedBuckets })
2994
3004
  }
2995
3005
  }
2996
3006
  if (unknownBucket) unknownBucket.alignedModel = nextAligned;
2997
- const key = totalsKey(unknownBucket.totals);
3007
+ const usagePrecision = unknownBucket.usage_precision || null;
3008
+ const key = usagePrecision
3009
+ ? `${totalsKey(unknownBucket.totals)}|${usagePrecision}`
3010
+ : totalsKey(unknownBucket.totals);
2998
3011
  const outputKey = outputModel === DEFAULT_MODEL ? key : `${key}|${outputModel}`;
2999
3012
  if (unknownBucket.queuedKey === outputKey) continue;
3000
3013
  toAppend.push(
@@ -3009,6 +3022,8 @@ async function enqueueTouchedBuckets({ queuePath, hourlyState, touchedBuckets })
3009
3022
  reasoning_output_tokens: unknownBucket.totals.reasoning_output_tokens,
3010
3023
  total_tokens: unknownBucket.totals.total_tokens,
3011
3024
  billable_total_tokens: unknownBucket.totals.billable_total_tokens ?? unknownBucket.totals.total_tokens,
3025
+ total_cost_usd: unknownBucket.totals.total_cost_usd || 0,
3026
+ usage_precision: usagePrecision || undefined,
3012
3027
  conversation_count: unknownBucket.totals.conversation_count,
3013
3028
  }),
3014
3029
  );
@@ -3056,6 +3071,7 @@ async function enqueueTouchedBuckets({ queuePath, hourlyState, touchedBuckets })
3056
3071
  reasoning_output_tokens: group.totals.reasoning_output_tokens,
3057
3072
  total_tokens: group.totals.total_tokens,
3058
3073
  billable_total_tokens: group.totals.billable_total_tokens ?? group.totals.total_tokens,
3074
+ total_cost_usd: group.totals.total_cost_usd || 0,
3059
3075
  conversation_count: group.totals.conversation_count,
3060
3076
  }),
3061
3077
  );
@@ -3111,6 +3127,7 @@ async function enqueueTouchedProjectBuckets({
3111
3127
  reasoning_output_tokens: totals.reasoning_output_tokens,
3112
3128
  total_tokens: totals.total_tokens,
3113
3129
  billable_total_tokens: totals.billable_total_tokens ?? totals.total_tokens,
3130
+ total_cost_usd: totals.total_cost_usd || 0,
3114
3131
  conversation_count: totals.conversation_count,
3115
3132
  }),
3116
3133
  );
@@ -3635,6 +3652,7 @@ function initTotals() {
3635
3652
  reasoning_output_tokens: 0,
3636
3653
  total_tokens: 0,
3637
3654
  billable_total_tokens: 0,
3655
+ total_cost_usd: 0,
3638
3656
  conversation_count: 0,
3639
3657
  };
3640
3658
  }
@@ -3647,6 +3665,9 @@ function addTotals(target, delta) {
3647
3665
  target.reasoning_output_tokens += delta.reasoning_output_tokens || 0;
3648
3666
  target.total_tokens += delta.total_tokens || 0;
3649
3667
  target.billable_total_tokens += delta.billable_total_tokens ?? delta.total_tokens ?? 0;
3668
+ target.total_cost_usd = Math.round(
3669
+ ((target.total_cost_usd || 0) + (delta.total_cost_usd || 0)) * USD_TICKS_PER_USD,
3670
+ ) / USD_TICKS_PER_USD;
3650
3671
  target.conversation_count += delta.conversation_count || 0;
3651
3672
  }
3652
3673
 
@@ -3671,6 +3692,12 @@ function subtractTotals(target, totals) {
3671
3692
  target.billable_total_tokens -
3672
3693
  (totals.billable_total_tokens ?? totals.total_tokens ?? 0),
3673
3694
  );
3695
+ target.total_cost_usd = Math.max(
3696
+ 0,
3697
+ Math.round(
3698
+ ((target.total_cost_usd || 0) - (totals.total_cost_usd || 0)) * USD_TICKS_PER_USD,
3699
+ ) / USD_TICKS_PER_USD,
3700
+ );
3674
3701
  target.conversation_count = Math.max(
3675
3702
  0,
3676
3703
  target.conversation_count - (totals.conversation_count || 0),
@@ -3686,6 +3713,7 @@ function totalsKey(totals) {
3686
3713
  totals.reasoning_output_tokens || 0,
3687
3714
  totals.total_tokens || 0,
3688
3715
  totals.billable_total_tokens ?? totals.total_tokens ?? 0,
3716
+ totals.total_cost_usd || 0,
3689
3717
  totals.conversation_count || 0,
3690
3718
  ].join("|");
3691
3719
  }
@@ -16096,14 +16124,14 @@ async function parseCopilotAppDbIncremental({
16096
16124
  // ─────────────────────────────────────────────────────────────────────────────
16097
16125
  // Grok Build (xAI) — passive reader for ~/.grok/sessions/**/updates.jsonl + signals.json
16098
16126
  // Triggered either by full scan in sync or by the SessionEnd hook writing a signal.
16099
- // updates.jsonl exposes cumulative totalTokens metadata. Grok still does not
16100
- // expose a stable prompt/output/cache split locally, so these rows keep the
16101
- // estimated input/output split while using better local telemetry for totals.
16127
+ // turn_completed.usage exposes the reported input/output/cache/reasoning split
16128
+ // and, on current Grok builds, exact server cost ticks. Older/partial sessions
16129
+ // without that event retain the explicitly isolated context-watermark fallback.
16102
16130
  // ─────────────────────────────────────────────────────────────────────────────
16103
16131
 
16104
16132
  const GROK_ESTIMATED_INPUT_RATIO = 0.8;
16105
- // v4: bill from turn_completed.usage (true cumulative API usage), not context-window totalTokens.
16106
- const GROK_CURSOR_VERSION = 4;
16133
+ // v5: split cache creation + reasoning correctly and retain reported cost.
16134
+ const GROK_CURSOR_VERSION = 5;
16107
16135
 
16108
16136
  function resolveGrokBuildHome(env = process.env) {
16109
16137
  if (env.TOKENTRACKER_GROK_HOME) return env.TOKENTRACKER_GROK_HOME;
@@ -16346,37 +16374,13 @@ function canonicalizeGrokUsageModel(model) {
16346
16374
  }
16347
16375
 
16348
16376
  function normalizeGrokTurnUsage(usage, model, timestamp, eventId) {
16349
- if (!usage || typeof usage !== "object") return null;
16350
- const inputRaw = normalizeNonNegativeNumber(
16351
- usage.inputTokens ?? usage.input_tokens,
16352
- );
16353
- const output = normalizeNonNegativeNumber(
16354
- usage.outputTokens ?? usage.output_tokens,
16355
- );
16356
- const cached = normalizeNonNegativeNumber(
16357
- usage.cachedReadTokens ??
16358
- usage.cache_read_input_tokens ??
16359
- usage.cached_input_tokens,
16360
- );
16361
- const reasoning = normalizeNonNegativeNumber(
16362
- usage.reasoningTokens ?? usage.reasoning_output_tokens,
16363
- );
16364
- // Grok reports inputTokens as the full prompt (including cache hits). Split
16365
- // so pricing can apply cache_read rates correctly.
16366
- const nonCachedInput = Math.max(0, inputRaw - cached);
16367
- let total = normalizeNonNegativeNumber(usage.totalTokens ?? usage.total_tokens);
16368
- if (total <= 0) {
16369
- total = inputRaw + output + reasoning;
16370
- }
16371
- if (total <= 0 && nonCachedInput <= 0 && cached <= 0 && output <= 0) return null;
16377
+ const normalized = normalizeGrokUsage(usage);
16378
+ if (!normalized) return null;
16372
16379
  return {
16373
- input_tokens: nonCachedInput,
16374
- cached_input_tokens: cached,
16375
- cache_creation_input_tokens: 0,
16376
- output_tokens: output,
16377
- reasoning_output_tokens: reasoning,
16378
- total_tokens: total > 0 ? total : nonCachedInput + cached + output + reasoning,
16379
- billable_total_tokens: total > 0 ? total : nonCachedInput + cached + output + reasoning,
16380
+ ...normalized,
16381
+ // A missing/partial cost must fall back to model pricing, not turn into a
16382
+ // falsely precise $0 row in the hourly queue.
16383
+ total_cost_usd: normalized.total_cost_usd ?? 0,
16380
16384
  conversation_count: 1,
16381
16385
  model: canonicalizeGrokUsageModel(model),
16382
16386
  timestamp,
@@ -16540,6 +16544,12 @@ function estimateGrokTokenDelta(totalTokens, conversationCount, options = {}) {
16540
16544
  };
16541
16545
  }
16542
16546
 
16547
+ function mergeGrokUsagePrecision(current, next) {
16548
+ if (!current) return next;
16549
+ if (!next || current === next) return current;
16550
+ return "mixed";
16551
+ }
16552
+
16543
16553
  function clearGrokHourlyBuckets(hourlyState) {
16544
16554
  if (!hourlyState || typeof hourlyState !== "object") return;
16545
16555
  const buckets = hourlyState.buckets && typeof hourlyState.buckets === "object" ? hourlyState.buckets : null;
@@ -16668,9 +16678,9 @@ async function parseGrokBuildIncremental({
16668
16678
  const prevVersion = Number(grokState.version) || 0;
16669
16679
  const needsTurnUsageMigration = prevVersion < GROK_CURSOR_VERSION;
16670
16680
 
16671
- // v3 and earlier treated context-window totalTokens as cumulative spend, which
16672
- // undercounts heavily (often 10-50x) and mis-splits input/output. Rebuild from
16673
- // turn_completed.usage when migrating to v4.
16681
+ // v3 and earlier treated context-window totalTokens as cumulative spend;
16682
+ // v4 still overlapped output/reasoning, discarded cache creation, and ignored
16683
+ // provider-reported cost. Rebuild from turn_completed.usage for v5.
16674
16684
  //
16675
16685
  // Drop prior watermark totals / updateOffsets so files are re-read from byte 0,
16676
16686
  // but keep legacySeen markers from seenSessions so the one-shot baseline
@@ -16794,9 +16804,10 @@ async function parseGrokBuildIncremental({
16794
16804
  reasoning_output_tokens: event.reasoning_output_tokens,
16795
16805
  total_tokens: event.total_tokens,
16796
16806
  billable_total_tokens: event.billable_total_tokens,
16807
+ total_cost_usd: event.total_cost_usd,
16797
16808
  conversation_count: event.conversation_count || 1,
16798
16809
  };
16799
- pendingBucketDeltas.push({ model: eventModel, hourStartStr, delta });
16810
+ pendingBucketDeltas.push({ model: eventModel, hourStartStr, delta, usagePrecision: "reported" });
16800
16811
  cumulativeTotal += event.total_tokens;
16801
16812
  tokenDeltaForSession += event.total_tokens;
16802
16813
  finalTouchedHourStart = hourStartStr;
@@ -16823,7 +16834,7 @@ async function parseGrokBuildIncremental({
16823
16834
  toUtcHalfHourStart(Date.now());
16824
16835
  if (!hourStartStr) continue;
16825
16836
  const delta = estimateGrokTokenDelta(deltaTokens, 0, { allowZeroConversationCount: true });
16826
- pendingBucketDeltas.push({ model, hourStartStr, delta });
16837
+ pendingBucketDeltas.push({ model, hourStartStr, delta, usagePrecision: "estimated" });
16827
16838
  tokenDeltaForSession += deltaTokens;
16828
16839
  finalTouchedHourStart = hourStartStr;
16829
16840
  source = "updates";
@@ -16836,7 +16847,7 @@ async function parseGrokBuildIncremental({
16836
16847
  const hourStartStr = toUtcHalfHourStart(lastActive) || toUtcHalfHourStart(Date.now());
16837
16848
  if (hourStartStr) {
16838
16849
  const delta = estimateGrokTokenDelta(deltaTokens, 0, { allowZeroConversationCount: true });
16839
- pendingBucketDeltas.push({ model, hourStartStr, delta });
16850
+ pendingBucketDeltas.push({ model, hourStartStr, delta, usagePrecision: "estimated" });
16840
16851
  tokenDeltaForSession += deltaTokens;
16841
16852
  finalTouchedHourStart = hourStartStr;
16842
16853
  source = "signals";
@@ -16854,6 +16865,10 @@ async function parseGrokBuildIncremental({
16854
16865
  for (const pending of pendingBucketDeltas) {
16855
16866
  const bucket = getHourlyBucket(hourlyState, "grok", pending.model, pending.hourStartStr);
16856
16867
  addTotals(bucket.totals, pending.delta);
16868
+ bucket.usage_precision = mergeGrokUsagePrecision(
16869
+ bucket.usage_precision,
16870
+ pending.usagePrecision,
16871
+ );
16857
16872
  touchedBuckets.add(bucketKey("grok", pending.model, pending.hourStartStr));
16858
16873
  eventsAggregated++;
16859
16874
  }
@@ -17092,7 +17107,7 @@ async function parseGrokBuildIncremental({
17092
17107
  ? { ...grokState.migrations }
17093
17108
  : {};
17094
17109
  if (needsTurnUsageMigration) {
17095
- migrations.turnUsageV4 = {
17110
+ migrations.turnUsageV5 = {
17096
17111
  appliedAt: new Date().toISOString(),
17097
17112
  fromVersion: prevVersion,
17098
17113
  toVersion: GROK_CURSOR_VERSION,
@@ -31,6 +31,7 @@ const readline = require("node:readline");
31
31
  const { listClaudeProjectFiles, listRolloutFilesDeep, claudeMessageDedupKey } = require("./rollout");
32
32
  const { parseCodexRolloutFile } = require("./codex-rollout-parser");
33
33
  const { computeRowCost } = require("./pricing");
34
+ const { USD_TICKS_PER_USD, normalizeGrokUsage } = require("./grok-usage");
34
35
  const wsl = require("./wsl-probe");
35
36
 
36
37
  // Bump the sidecar when derived metrics change so cached rows are rebuilt
@@ -54,6 +55,8 @@ const wsl = require("./wsl-probe");
54
55
  // stay valid while Grok entries appear on the next full rebuild.
55
56
  // v11 groups native/WSL copies of one logical Claude/Codex session and scans
56
57
  // their union, deduping shared records while retaining divergent tails.
58
+ // v12 fixes Grok's mutually exclusive token columns, retains exact reported
59
+ // cost, and adds metadata-only usage diagnostics to the local session browser.
57
60
  // v12 retains Codex parent/subagent metadata locally and derives exact child
58
61
  // token totals from observed child rollouts instead of spawn-call estimates.
59
62
  const SIDECAR_VERSION = 12;
@@ -240,7 +243,12 @@ function finalizeRecord(record) {
240
243
  record.active_ms = Math.max(0, finite(record.active_ms));
241
244
  record.duration_ms = record.active_ms;
242
245
  record.total_tokens = finite(record.total_tokens || record.tokens?.total_tokens);
243
- record.cost_usd = computeRowCost({ source: record.source, model: record.model, ...record.tokens });
246
+ const providerCost = Number(record.provider_cost_usd);
247
+ record.cost_usd = record.cost_source === "provider_reported"
248
+ && Number.isFinite(providerCost)
249
+ && providerCost >= 0
250
+ ? providerCost
251
+ : computeRowCost({ source: record.source, model: record.model, ...record.tokens });
244
252
  record.productive = record.edit_turns > 0;
245
253
  // A first-pass delivery has exactly one user turn containing an observed
246
254
  // edit and no repeated user request. The legacy one_shot field stays as an
@@ -583,42 +591,6 @@ function grokTimestampIso(obj) {
583
591
  return new Date(ms).toISOString();
584
592
  }
585
593
 
586
- // Grok reports inputTokens as the full prompt (including cache hits). Split so
587
- // pricing can apply cache_read rates correctly — same authority as the usage
588
- // parser and grok-context-breakdown.readUsageTotals. Prefer the reported
589
- // totalTokens; do not re-sum input+cached (that double-counts cache hits).
590
- function grokUsageTotals(usage) {
591
- if (!usage || typeof usage !== "object") return emptyTotals();
592
- const inputRaw = finite(usage.inputTokens ?? usage.input_tokens);
593
- const cached_input_tokens = finite(
594
- usage.cachedReadTokens ?? usage.cache_read_input_tokens ?? usage.cached_input_tokens,
595
- );
596
- const cache_creation_input_tokens = finite(
597
- usage.cachedWriteTokens ?? usage.cache_creation_input_tokens,
598
- );
599
- const output_tokens = finite(usage.outputTokens ?? usage.output_tokens);
600
- const reasoning_output_tokens = finite(
601
- usage.reasoningTokens ?? usage.reasoning_output_tokens,
602
- );
603
- const input_tokens = Math.max(0, inputRaw - cached_input_tokens);
604
- let total_tokens = finite(usage.totalTokens ?? usage.total_tokens);
605
- if (total_tokens <= 0) {
606
- total_tokens = input_tokens
607
- + cached_input_tokens
608
- + cache_creation_input_tokens
609
- + output_tokens
610
- + reasoning_output_tokens;
611
- }
612
- return {
613
- input_tokens,
614
- cached_input_tokens,
615
- cache_creation_input_tokens,
616
- output_tokens,
617
- reasoning_output_tokens,
618
- total_tokens,
619
- };
620
- }
621
-
622
594
  function pickGrokModel(usage, fallback) {
623
595
  const modelUsage = usage?.modelUsage;
624
596
  if (modelUsage && typeof modelUsage === "object") {
@@ -718,6 +690,13 @@ async function scanGrokSession(filePath) {
718
690
  let currentHadEdit = false;
719
691
  let subagentCalls = 0;
720
692
  const subagentTypes = new Map();
693
+ let usageEvents = 0;
694
+ let providerCostEvents = 0;
695
+ let providerCostUsd = 0;
696
+ let modelCalls = 0;
697
+ let apiDurationMs = 0;
698
+ let usageIsIncomplete = false;
699
+ let costIsPartial = false;
721
700
  let lastPromptFingerprint = null;
722
701
  // Grok streams user_message_chunk pieces for one prompt. Accumulate until
723
702
  // turn_completed, then fingerprint the full prompt for retry detection.
@@ -786,7 +765,21 @@ async function scanGrokSession(filePath) {
786
765
  if (sessionUpdate === "turn_completed") {
787
766
  closeTurn();
788
767
  const usage = update.usage;
789
- addTotals(tokens, grokUsageTotals(usage));
768
+ const normalizedUsage = normalizeGrokUsage(usage);
769
+ if (normalizedUsage) {
770
+ usageEvents += 1;
771
+ addTotals(tokens, normalizedUsage);
772
+ modelCalls += finite(normalizedUsage.model_calls);
773
+ apiDurationMs += finite(normalizedUsage.api_duration_ms);
774
+ usageIsIncomplete ||= normalizedUsage.usage_is_incomplete;
775
+ costIsPartial ||= normalizedUsage.cost_is_partial;
776
+ if (normalizedUsage.total_cost_usd != null) {
777
+ providerCostEvents += 1;
778
+ providerCostUsd = Math.round(
779
+ (providerCostUsd + normalizedUsage.total_cost_usd) * USD_TICKS_PER_USD,
780
+ ) / USD_TICKS_PER_USD;
781
+ }
782
+ }
790
783
  const candidate = pickGrokModel(usage, model);
791
784
  if (candidate && candidate !== "unknown") model = candidate;
792
785
  continue;
@@ -810,6 +803,11 @@ async function scanGrokSession(filePath) {
810
803
  model = normalizeSessionModel(signals.primaryModelId) || model;
811
804
  }
812
805
 
806
+ const hasCompleteProviderCost = usageEvents > 0
807
+ && providerCostEvents === usageEvents
808
+ && !usageIsIncomplete
809
+ && !costIsPartial;
810
+
813
811
  return finalizeRecord({
814
812
  version: SIDECAR_VERSION,
815
813
  session_hash: sessionHash("grok", observedSessionId || filePath),
@@ -827,7 +825,29 @@ async function scanGrokSession(filePath) {
827
825
  subagent_calls: subagentCalls,
828
826
  subagent_types: Object.fromEntries([...subagentTypes.entries()].sort()),
829
827
  tokens,
830
- provenance: { source: "local-session-log", confidence: "observed", retry_confidence: "inferred", content_retained: false },
828
+ usage_events: usageEvents,
829
+ usage_precision: usageIsIncomplete ? "reported_incomplete" : (usageEvents > 0 ? "reported" : "unavailable"),
830
+ usage_is_incomplete: usageIsIncomplete,
831
+ cost_is_partial: costIsPartial,
832
+ cost_source: hasCompleteProviderCost ? "provider_reported" : "model_pricing",
833
+ provider_cost_usd: hasCompleteProviderCost ? providerCostUsd : null,
834
+ model_calls: modelCalls,
835
+ api_duration_ms: apiDurationMs,
836
+ context_tokens_used: finite(signals.contextTokensUsed),
837
+ context_window_tokens: finite(signals.contextWindowTokens),
838
+ context_usage_percent: finite(signals.contextWindowUsage),
839
+ tool_calls: finite(signals.toolCallCount),
840
+ tool_failures: finite(signals.toolFailureCount),
841
+ error_count: finite(signals.errorCount),
842
+ compaction_count: finite(signals.compactionCount),
843
+ provenance: {
844
+ source: "local-session-log",
845
+ confidence: usageIsIncomplete ? "partial" : "observed",
846
+ retry_confidence: "inferred",
847
+ content_retained: false,
848
+ usage: usageEvents > 0 ? "turn_completed.usage" : "unavailable",
849
+ cost: hasCompleteProviderCost ? "provider_reported" : "model_pricing",
850
+ },
831
851
  });
832
852
  }
833
853
 
@@ -1410,6 +1430,7 @@ function resumeCommandFor(source, sessionId) {
1410
1430
  }
1411
1431
 
1412
1432
  function toSessionBrowserRow(row) {
1433
+ const tokens = row.tokens && typeof row.tokens === "object" ? row.tokens : {};
1413
1434
  return {
1414
1435
  session_hash: row.session_hash,
1415
1436
  session_id: row.session_id || null,
@@ -1435,6 +1456,11 @@ function toSessionBrowserRow(row) {
1435
1456
  edit_turns: finite(row.edit_turns),
1436
1457
  retry_turns: finite(row.retry_turns),
1437
1458
  subagent_calls: finite(row.subagent_calls),
1459
+ input_tokens: finite(tokens.input_tokens),
1460
+ cached_input_tokens: finite(tokens.cached_input_tokens),
1461
+ cache_creation_input_tokens: finite(tokens.cache_creation_input_tokens),
1462
+ output_tokens: finite(tokens.output_tokens),
1463
+ reasoning_output_tokens: finite(tokens.reasoning_output_tokens),
1438
1464
  direct_subagent_count: finite(row.direct_subagent_count),
1439
1465
  descendant_subagent_count: finite(row.descendant_subagent_count),
1440
1466
  own_total_tokens: finite(row.total_tokens),
@@ -1445,6 +1471,20 @@ function toSessionBrowserRow(row) {
1445
1471
  subagent_cost_usd: finite(row.subagent_cost_usd),
1446
1472
  combined_cost_usd: finite(row.combined_cost_usd || row.cost_usd),
1447
1473
  cost_usd: finite(row.cost_usd),
1474
+ cost_source: row.cost_source || null,
1475
+ usage_precision: row.usage_precision || null,
1476
+ usage_is_incomplete: Boolean(row.usage_is_incomplete),
1477
+ cost_is_partial: Boolean(row.cost_is_partial),
1478
+ usage_events: finite(row.usage_events),
1479
+ model_calls: finite(row.model_calls),
1480
+ api_duration_ms: finite(row.api_duration_ms),
1481
+ context_tokens_used: finite(row.context_tokens_used),
1482
+ context_window_tokens: finite(row.context_window_tokens),
1483
+ context_usage_percent: finite(row.context_usage_percent),
1484
+ tool_calls: finite(row.tool_calls),
1485
+ tool_failures: finite(row.tool_failures),
1486
+ error_count: finite(row.error_count),
1487
+ compaction_count: finite(row.compaction_count),
1448
1488
  productive: Boolean(row.productive),
1449
1489
  first_pass: Boolean(row.first_pass ?? row.one_shot),
1450
1490
  resume_command: resumeCommandFor(row.source, row.session_id),
@@ -1463,15 +1503,35 @@ function mergeSessionFragments(rows) {
1463
1503
  const key = row.session_hash;
1464
1504
  const cur = byHash.get(key);
1465
1505
  if (!cur) {
1466
- byHash.set(key, { ...row, _repr_tokens: finite(row.total_tokens) });
1506
+ byHash.set(key, {
1507
+ ...row,
1508
+ tokens: row.tokens && typeof row.tokens === "object" ? { ...row.tokens } : emptyTotals(),
1509
+ _repr_tokens: finite(row.total_tokens),
1510
+ });
1467
1511
  continue;
1468
1512
  }
1469
1513
  cur.turns = finite(cur.turns) + finite(row.turns);
1470
1514
  cur.edit_turns = finite(cur.edit_turns) + finite(row.edit_turns);
1471
1515
  cur.retry_turns = finite(cur.retry_turns) + finite(row.retry_turns);
1472
1516
  cur.subagent_calls = finite(cur.subagent_calls) + finite(row.subagent_calls);
1517
+ addTotals(cur.tokens, row.tokens);
1473
1518
  cur.total_tokens = finite(cur.total_tokens) + finite(row.total_tokens);
1474
1519
  cur.cost_usd = finite(cur.cost_usd) + finite(row.cost_usd);
1520
+ cur.provider_cost_usd = finite(cur.provider_cost_usd) + finite(row.provider_cost_usd);
1521
+ cur.usage_events = finite(cur.usage_events) + finite(row.usage_events);
1522
+ cur.model_calls = finite(cur.model_calls) + finite(row.model_calls);
1523
+ cur.api_duration_ms = finite(cur.api_duration_ms) + finite(row.api_duration_ms);
1524
+ cur.tool_calls = finite(cur.tool_calls) + finite(row.tool_calls);
1525
+ cur.tool_failures = finite(cur.tool_failures) + finite(row.tool_failures);
1526
+ cur.error_count = finite(cur.error_count) + finite(row.error_count);
1527
+ cur.compaction_count = finite(cur.compaction_count) + finite(row.compaction_count);
1528
+ cur.context_tokens_used = Math.max(finite(cur.context_tokens_used), finite(row.context_tokens_used));
1529
+ cur.context_window_tokens = Math.max(finite(cur.context_window_tokens), finite(row.context_window_tokens));
1530
+ cur.context_usage_percent = Math.max(finite(cur.context_usage_percent), finite(row.context_usage_percent));
1531
+ cur.usage_is_incomplete = Boolean(cur.usage_is_incomplete) || Boolean(row.usage_is_incomplete);
1532
+ cur.cost_is_partial = Boolean(cur.cost_is_partial) || Boolean(row.cost_is_partial);
1533
+ if (cur.usage_precision !== row.usage_precision) cur.usage_precision = "mixed";
1534
+ if (cur.cost_source !== row.cost_source) cur.cost_source = "mixed";
1475
1535
  cur.productive = Boolean(cur.productive) || Boolean(row.productive);
1476
1536
  cur.active_ms = finite(cur.active_ms) + finite(row.active_ms);
1477
1537
  if (!cur.title && row.title) cur.title = row.title;
@@ -1 +0,0 @@
1
- import{r as n,z as a}from"./__vite-browser-external-CVIGknXl.js";import{u as p}from"./DialogTitle-DrbKjtuS.js";import{u as c}from"./composite-Ccj6KQmh.js";const x=n.forwardRef(function(e,r){const{render:l,className:u,style:m,id:s,...t}=e,i=p(),o=c(s);return i.useSyncedValueWithCleanup("descriptionElementId",o),a("p",e,{ref:r,props:[{id:o},t]})});export{x as D};
@@ -1,2 +0,0 @@
1
- import{m as Y,r as i,j as e,e as D,c as a,M as ce,J as Z,R as de,X as ue,d as ee,l as L,a4 as xe,a5 as U}from"./__vite-browser-external-CVIGknXl.js";import{L as me,I as he}from"./LocalOnlyNotice-CCD-lGWG.js";import{S as J}from"./SegmentedControl-BOE1CEzq.js";import{C as fe}from"./ToolbarRootContext-Dx5GB7F5.js";import{S as te}from"./search-CwLcNdvZ.js";import{C as ge}from"./check-BnJpzXRZ.js";import{P as be,a as pe,b as ye,c as ke,d as ve}from"./PopoverPopup-Dar_UjxF.js";import{P as je}from"./ProviderIcon-Ct9tILpz.js";import{H as we}from"./HoverTooltip-BmDkY35A.js";import{u as _e}from"./useCurrency-BarGeFyK.js";import{i as Ne}from"./host-mode-Bc_iTzHk.js";import{L as Se}from"./loader-circle-SaxUpDR6.js";import{T as Ce}from"./terminal-BfeX3L5T.js";import"./arrow-up-right-CANSzmm-.js";import"./download-B52JTk6Y.js";import"./composite-Ccj6KQmh.js";import"./store-ikeRIRGd.js";const Me=[["path",{d:"M8 2v3",key:"1ioesn"}],["path",{d:"M16 2v3",key:"otl347"}],["rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",key:"h1oib"}],["path",{d:"M3 9h18",key:"1pudct"}]],Le=Y("calendar",Me);const Te=[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z",key:"1kt360"}]],Re=Y("folder",Te),De="flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-sm text-oai-black outline-none hover:bg-oai-gray-100 dark:text-white dark:hover:bg-oai-gray-800";function Ie({options:r,value:t,onChange:o,allValue:x="all",allLabel:h,searchPlaceholder:y,emptyLabel:u,ariaLabel:_,disabled:f=!1,className:k=""}){const[b,g]=i.useState(!1),[p,S]=i.useState(""),[m,v]=i.useState(-1),I=i.useRef(null),C=`${i.useId()}-listbox`,O=t===x?h:r.find(l=>l.value===t)?.label??t,M=p.trim().toLowerCase(),j=i.useMemo(()=>M?r.filter(l=>l.label.toLowerCase().includes(M)):r,[r,M]),E=i.useMemo(()=>[{value:x,label:h},...j],[x,h,j]),P=m>=0&&m<E.length?E[m]:null,F=l=>{o(l),g(!1),S(""),v(-1)};i.useEffect(()=>{b&&I.current?.querySelector('[data-active="true"]')?.scrollIntoView?.({block:"nearest"})},[b,m]);const A=l=>{if(l.key==="ArrowDown"||l.key==="ArrowUp"){l.preventDefault();const w=l.key==="ArrowDown";v(T=>{const N=E.length;return N?w?T>=N-1?0:T+1:T<=0?N-1:T-1:-1});return}if(l.key==="Enter"){const w=P||(M&&j.length?j[0]:null);if(!w)return;l.preventDefault(),F(w.value)}};return e.jsxs(be,{open:b,onOpenChange:l=>{g(l),v(-1),l||S("")},children:[e.jsxs(pe,{disabled:f,"aria-label":_,className:D("inline-flex h-8 max-w-[12rem] shrink-0 items-center gap-1.5 rounded-md border border-oai-gray-200 bg-oai-white px-2.5 text-xs font-medium transition hover:border-oai-gray-300 focus:outline-none focus:ring-2 focus:ring-oai-gray-400/30 disabled:opacity-60 data-[popup-open]:border-oai-gray-300 dark:border-oai-gray-800 dark:bg-oai-gray-900 dark:hover:border-oai-gray-700",t!==x?"text-oai-black dark:text-white":"text-oai-gray-700 dark:text-oai-gray-200",k),children:[e.jsx(Re,{className:"h-3.5 w-3.5 shrink-0 text-oai-gray-400","aria-hidden":!0}),e.jsx("span",{className:"truncate",children:O}),e.jsx(fe,{className:"h-3.5 w-3.5 shrink-0 text-oai-gray-400","aria-hidden":!0})]}),e.jsx(ye,{children:e.jsx(ke,{sideOffset:4,side:"bottom",align:"start",className:"z-[60]",children:e.jsxs(ve,{className:"w-56 overflow-hidden rounded-md border border-oai-gray-200 bg-white p-1 shadow-[0_12px_32px_-12px_rgba(0,0,0,0.18)] outline-none dark:border-oai-gray-800 dark:bg-oai-gray-950 dark:shadow-[0_12px_32px_-12px_rgba(0,0,0,0.6)]",children:[e.jsxs("div",{className:"relative mb-1",children:[e.jsx(te,{className:"pointer-events-none absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-oai-gray-400","aria-hidden":!0}),e.jsx("input",{type:"text",role:"combobox","aria-expanded":!0,"aria-controls":C,"aria-activedescendant":P?`${C}-${m}`:void 0,value:p,onChange:l=>{S(l.target.value),v(-1)},onKeyDown:A,placeholder:y,className:"h-8 w-full rounded border border-oai-gray-200 bg-transparent pl-8 pr-2 text-xs text-oai-black outline-none placeholder:text-oai-gray-400 focus:border-oai-gray-400 dark:border-oai-gray-800 dark:text-white dark:focus:border-oai-gray-500"})]}),e.jsxs("div",{ref:I,id:C,role:"listbox","aria-label":_,className:"max-h-64 overflow-y-auto",children:[E.map((l,w)=>e.jsxs("button",{id:`${C}-${w}`,type:"button",role:"option","aria-selected":t===l.value,"data-active":w===m?"true":void 0,onMouseEnter:()=>v(w),onClick:()=>F(l.value),className:D(De,t===l.value&&"bg-oai-gray-100 dark:bg-oai-gray-800",w===m&&"ring-1 ring-inset ring-oai-gray-300 dark:ring-oai-gray-600"),children:[e.jsx("span",{className:"flex-1 truncate",children:l.label}),t===l.value?e.jsx(ge,{className:"h-3.5 w-3.5 shrink-0","aria-hidden":!0}):null]},l.value)),j.length===0?e.jsx("div",{className:"px-2 py-3 text-center text-xs text-oai-gray-400 dark:text-oai-gray-500",children:u}):null]})]})})})]})}const Ee="tokentracker-sessions";async function Pe(r={}){const t=new URL(`/functions/${Ee}`,window.location.origin);r.from&&t.searchParams.set("from",r.from),r.to&&t.searchParams.set("to",r.to),r.limit&&t.searchParams.set("limit",String(r.limit)),r.refresh&&t.searchParams.set("refresh","1");const o=await fetch(t.toString(),{headers:{Accept:"application/json"},cache:"no-store"}),x=await o.json().catch(()=>null);if(!o.ok){const h=o.status===404?a("sessions.error.outdated_app"):`Request failed with HTTP ${o.status}`,y=new Error(x?.error||h);throw y.status=o.status,y}return x}const V=Ne(),Fe=[],Q=100,$e=[{id:"all",label:()=>a("sessions.filter.source_all")},{id:"claude",label:()=>"Claude Code"},{id:"codex",label:()=>"Codex"},{id:"grok",label:()=>"Grok"}],ae=[{id:"all",days:0,label:()=>a("sessions.filter.range_all")},{id:"7d",days:7,label:()=>a("sessions.filter.range_7d")},{id:"30d",days:30,label:()=>a("sessions.filter.range_30d")},{id:"90d",days:90,label:()=>a("sessions.filter.range_90d")}];function Oe(r){const t=ae.find(x=>x.id===r)?.days||0;if(!t)return 0;const o=new Date;return o.setDate(o.getDate()-(t-1)),o.setHours(0,0,0,0),o.getTime()}function Ae(r,t){if(!t)return!0;const o=Date.parse(r.ended_at||r.started_at||"");return Number.isFinite(o)?o>=t:!0}function qe(r,t){if(!r)return"—";const o=Date.parse(r);if(!Number.isFinite(o))return"—";try{return new Date(o).toLocaleString(t||void 0,{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return new Date(o).toISOString().slice(0,16).replace("T"," ")}}function Ue(r){const t=Number(r);if(!Number.isFinite(t)||t<=0)return null;const o=Math.round(t/6e4);if(o<60)return a("sessions.duration.minutes",{minutes:o});const x=Math.floor(o/60),h=o%60;return a("sessions.duration.hours",{hours:x,minutes:h})}async function W(r){if(navigator?.clipboard?.writeText)return await navigator.clipboard.writeText(r),!0;const t=document.createElement("textarea");t.value=r,t.style.position="fixed",t.style.opacity="0",document.body.appendChild(t),t.select();const o=document.execCommand("copy");return document.body.removeChild(t),o}const X=ee.memo(function({session:t,locale:o,nested:x=!1,childCount:h=0,expanded:y=!1,onToggle:u}){const{currency:_,rate:f}=_e(),k=String(t.source||"").toUpperCase(),b=Ue(t.duration_ms),g=t.resume_command,p=t.project_key||a("sessions.project.unknown"),S=x||t.thread_kind==="subagent",m=S?t.agent_nickname||t.agent_role||t.title||p:t.title||p,v=!!(t.title&&t.project_key),I=t.project_ref?`${t.project_ref}
2
- ${a("sessions.project.copy_hint")}`:void 0,C=async()=>{if(t.project_ref)try{await W(t.project_ref)?U({title:a("sessions.project.copied")}):U({title:a("sessions.project.copy_failed")})}catch{U({title:a("sessions.project.copy_failed")})}},O=j=>e.jsxs("span",{className:"group relative inline-flex min-w-0 max-w-full",children:[e.jsx(we,{text:I,placement:"bottom"}),e.jsx("button",{type:"button",onClick:C,"aria-label":a("sessions.project.copy_aria",{project:p}),className:D("max-w-full truncate rounded text-left underline decoration-dotted decoration-oai-gray-300 underline-offset-4 hover:decoration-oai-gray-500 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-oai-brand-500 dark:decoration-oai-gray-600 dark:hover:decoration-oai-gray-400",j),children:p})]}),M=async()=>{if(g)try{await W(g)?U({title:a("sessions.resume.copied")}):U({title:a("sessions.resume.copy_failed")})}catch{U({title:a("sessions.resume.copy_failed")})}};return e.jsxs("li",{className:D("flex flex-col gap-3 py-4 sm:flex-row sm:items-start",x&&"ml-6 border-l-2 border-oai-gray-200 pl-4 dark:border-oai-gray-800"),children:[e.jsxs("div",{className:"flex min-w-0 flex-1 items-start gap-2.5",children:[e.jsx("span",{className:"mt-0.5 shrink-0 text-oai-gray-400 dark:text-oai-gray-500",children:e.jsx(je,{provider:k,size:20})}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[!S&&!t.title&&t.project_ref?O("font-medium text-oai-black dark:text-white"):e.jsx("span",{className:"truncate font-medium text-oai-black dark:text-white",children:m}),S?e.jsxs("span",{className:"inline-flex items-center rounded-full bg-sky-50 px-2 py-0.5 text-[11px] font-medium text-sky-700 dark:bg-sky-500/10 dark:text-sky-300",children:[a("sessions.badge.subagent"),t.agent_role?` · ${t.agent_role}`:""]}):null,t.first_pass?e.jsx("span",{className:"inline-flex items-center rounded-full bg-emerald-50 px-2 py-0.5 text-[11px] font-medium text-emerald-700 dark:bg-emerald-500/10 dark:text-emerald-300",children:a("sessions.badge.first_pass")}):null,h?e.jsx("button",{type:"button",onClick:u,"aria-expanded":y,className:"inline-flex items-center rounded-full border border-oai-gray-200 px-2 py-0.5 text-[11px] font-medium text-oai-gray-600 transition-colors hover:bg-oai-gray-100 hover:text-oai-black focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-oai-brand-500 dark:border-oai-gray-700 dark:text-oai-gray-300 dark:hover:bg-oai-gray-800 dark:hover:text-white",children:y?a("sessions.thread.collapse",{count:h}):a("sessions.thread.expand",{count:h})}):null]}),e.jsxs("div",{className:"mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-oai-gray-500 dark:text-oai-gray-400",children:[v?e.jsxs(e.Fragment,{children:[t.project_ref?O("hover:text-oai-black dark:hover:text-white"):e.jsx("span",{className:"truncate",children:p}),e.jsx("span",{"aria-hidden":!0,children:"·"})]}):null,e.jsx("span",{className:"truncate",children:t.model||a("sessions.model.unknown")}),e.jsx("span",{"aria-hidden":!0,children:"·"}),e.jsx("span",{className:"tabular-nums",children:qe(t.started_at,o)}),b?e.jsxs(e.Fragment,{children:[e.jsx("span",{"aria-hidden":!0,children:"·"}),e.jsx("span",{className:"tabular-nums",children:b})]}):null]})]})]}),e.jsxs("div",{className:"flex items-start gap-5 pl-[30px] sm:pl-0",children:[e.jsxs("dl",{className:"flex items-start gap-6 text-right",children:[e.jsxs("div",{className:"flex w-16 flex-col-reverse",children:[e.jsx("dt",{className:"text-[11px] text-oai-gray-400 dark:text-oai-gray-500",children:a("sessions.col.tokens")}),e.jsxs("dd",{title:Number(t.subagent_total_tokens)?a("sessions.thread.tokens_summary",{own:L(t.own_total_tokens),subagents:L(t.subagent_total_tokens),combined:L(t.combined_total_tokens)}):void 0,className:"tabular-nums text-sm font-medium text-oai-black dark:text-white",children:[L(t.total_tokens),Number(t.subagent_total_tokens)?e.jsxs("span",{className:"block text-[9px] font-normal text-oai-gray-400 dark:text-oai-gray-500",children:["Σ ",L(t.combined_total_tokens)]}):null]})]}),e.jsxs("div",{className:"flex w-16 flex-col-reverse",children:[e.jsx("dt",{className:"text-[11px] text-oai-gray-400 dark:text-oai-gray-500",children:a("sessions.col.cost")}),e.jsx("dd",{className:"tabular-nums text-sm font-medium text-oai-black dark:text-white",children:xe(t.cost_usd,{currency:_,rate:f})})]}),e.jsxs("div",{className:"hidden w-10 flex-col-reverse sm:flex",children:[e.jsx("dt",{className:"text-[11px] text-oai-gray-400 dark:text-oai-gray-500",children:a("sessions.col.turns")}),e.jsx("dd",{className:"tabular-nums text-sm font-medium text-oai-black dark:text-white",children:L(t.turns)})]}),e.jsxs("div",{className:"hidden w-10 flex-col-reverse sm:flex",children:[e.jsx("dt",{className:"text-[11px] text-oai-gray-400 dark:text-oai-gray-500",children:a("sessions.col.edits")}),e.jsx("dd",{className:"tabular-nums text-sm font-medium text-oai-black dark:text-white",children:L(t.edit_turns)})]})]}),e.jsxs("button",{type:"button",onClick:M,disabled:!g,title:g||a("sessions.resume.unavailable"),"aria-label":g?a("sessions.resume.copy_aria",{command:g}):a("sessions.resume.unavailable"),className:D("-mt-0.5 inline-flex h-8 shrink-0 items-center gap-1.5 rounded-md px-2.5 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-oai-brand-500",g?"text-oai-gray-500 hover:bg-oai-gray-100 hover:text-oai-black dark:text-oai-gray-400 dark:hover:bg-oai-gray-800 dark:hover:text-white":"cursor-not-allowed text-oai-gray-300 dark:text-oai-gray-600"),children:[e.jsx(Ce,{className:"h-3.5 w-3.5","aria-hidden":!0}),e.jsx("span",{className:"hidden sm:inline",children:a("sessions.resume.copy")})]})]})]})});function He({sessions:r,selectedModel:t,onSelect:o}){const{groups:x,totalTokens:h}=i.useMemo(()=>{const u=new Map;let _=0;for(const f of r){const k=f.model||a("sessions.model.unknown"),b=Number(f.own_total_tokens||f.total_tokens||0),g=u.get(k)||{model:k,count:0,tokens:0};g.count+=1,g.tokens+=b,_+=b,u.set(k,g)}return{groups:[...u.values()].sort((f,k)=>k.tokens-f.tokens),totalTokens:_}},[r]);function y(u){return D("rounded-full border px-2.5 py-1 text-xs tabular-nums transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-oai-brand-500",u?"border-oai-brand-500 bg-oai-brand-50 text-oai-brand-700 dark:bg-oai-brand-500/10 dark:text-oai-brand-300":"border-oai-gray-200 text-oai-gray-600 hover:bg-oai-gray-100 dark:border-oai-gray-700 dark:text-oai-gray-300 dark:hover:bg-oai-gray-800")}return e.jsx("li",{className:"ml-6 border-l-2 border-oai-gray-200 py-3 pl-4 dark:border-oai-gray-800",children:e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("span",{className:"mr-1 text-xs font-medium text-oai-gray-500 dark:text-oai-gray-400",children:a("sessions.thread.model_usage")}),e.jsx("button",{type:"button","aria-pressed":t==="all",onClick:()=>o("all"),className:y(t==="all"),children:a("sessions.thread.model_all",{count:r.length,tokens:L(h)})}),x.map(u=>e.jsx("button",{type:"button","aria-pressed":t===u.model,onClick:()=>o(u.model),className:y(t===u.model),children:a("sessions.thread.model_item",{model:u.model,count:u.count,tokens:L(u.tokens)})},u.model))]})})}function nt(){const[r,t]=i.useState(null),[o,x]=i.useState(null),[h,y]=i.useState(!0),[u,_]=i.useState(!1),[f,k]=i.useState("all"),[b,g]=i.useState("all"),[p,S]=i.useState("all"),[m,v]=i.useState(""),[I,C]=i.useState(Q),[O,M]=i.useState(()=>new Set),[j,E]=i.useState(()=>new Map),P=i.useRef(0),{resolvedLocale:F}=ce(),A=i.useCallback(async(s=!1)=>{const c=++P.current;s?_(!0):y(!0),x(null);try{const n=await Pe({refresh:s});c===P.current&&t(n)}catch(n){c===P.current&&x(n?.message||String(n))}finally{c===P.current&&(y(!1),_(!1))}},[]);i.useEffect(()=>{V||Z()?A(!1):y(!1)},[A]);const l=r?.sessions||Fe,w=i.useMemo(()=>{const s=new Set,c=[];for(const n of l){const d=n.project_key;!d||s.has(d)||(s.add(d),c.push({value:d,label:d}))}return c.sort((n,d)=>n.label.localeCompare(d.label))},[l]),T=i.useDeferredValue(m),N=i.useMemo(()=>{const s=T.trim().toLowerCase(),c=Oe(b);return l.filter(n=>f!=="all"&&n.source!==f||p!=="all"&&n.project_key!==p||!Ae(n,c)?!1:s?`${n.title||""} ${n.project_key||""} ${n.model||""} ${n.agent_nickname||""} ${n.agent_role||""} ${n.project_ref||""} ${n.session_id||""}`.toLowerCase().includes(s):!0)},[l,f,p,b,T]),$=i.useMemo(()=>{const s=new Set(N.map(d=>d.session_hash)),c=new Map,n=[];for(const d of N){const q=d.root_session_hash||d.parent_session_hash;if(d.parent_session_hash&&q&&s.has(q)){const R=c.get(q)||[];R.push(d),c.set(q,R)}else n.push(d)}return{roots:n,childrenByRoot:c,foldedCount:N.length-n.length}},[N]),B=f!=="all"||b!=="all"||p!=="all"||m.trim()!=="";i.useEffect(()=>{C(Q),M(new Set),E(new Map)},[f,p,b,T,l]);const K=i.useMemo(()=>$.roots.slice(0,I),[$.roots,I]),H=$.roots.length>K.length,G=i.useCallback(()=>C(s=>s+Q),[]),se=i.useCallback(s=>{M(c=>{const n=new Set(c);return n.has(s)?n.delete(s):n.add(s),n})},[]),re=i.useCallback((s,c)=>{E(n=>{const d=new Map(n);return c==="all"?d.delete(s):d.set(s,c),d})},[]),z=i.useRef(null);i.useEffect(()=>{if(!H||typeof IntersectionObserver>"u")return;const s=z.current;if(!s)return;const c=new IntersectionObserver(n=>{n.some(d=>d.isIntersecting)&&G()},{rootMargin:"400px"});return c.observe(s),()=>c.disconnect()},[H,G]);const oe=i.useMemo(()=>$e.map(s=>({id:s.id,label:s.label()})),[F]),ne=i.useMemo(()=>ae.map(s=>({id:s.id,label:s.label()})),[F]),ie=Number(r?.session_count)>Number(r?.returned_count);return!V&&!Z()?e.jsx("div",{className:"flex flex-col flex-1 text-oai-black dark:text-oai-white font-oai antialiased",children:e.jsx(me,{})}):e.jsx("div",{className:"flex flex-col flex-1 text-oai-black dark:text-oai-white font-oai antialiased",children:e.jsx("main",{className:"flex-1 pt-8 sm:pt-10 pb-12 sm:pb-16",children:e.jsxs("div",{className:"mx-auto max-w-6xl px-4 sm:px-6",children:[e.jsxs("div",{className:"mb-8 flex flex-row items-start justify-between gap-4",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("h1",{className:"mb-3 text-3xl font-semibold tracking-tight text-oai-black dark:text-white sm:text-4xl",children:a("nav.sessions")}),e.jsx("p",{className:"text-sm text-oai-gray-500 dark:text-oai-gray-400 sm:text-base",children:a("sessions.page.subtitle")})]}),e.jsx("button",{type:"button",onClick:()=>{A(!0)},disabled:u||h,"aria-label":a("sessions.page.refresh"),title:a("sessions.page.refresh"),className:"inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border border-oai-gray-200 text-oai-gray-600 transition-colors hover:bg-oai-gray-100 hover:text-oai-black focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-oai-brand-500 disabled:opacity-50 dark:border-oai-gray-800 dark:text-oai-gray-400 dark:hover:bg-oai-gray-800 dark:hover:text-white",children:e.jsx(de,{className:D("h-4 w-4",u&&"animate-spin"),"aria-hidden":!0})})]}),e.jsxs("div",{className:"mb-2 flex flex-wrap items-center gap-2 pt-1 text-xs text-oai-gray-600 dark:text-oai-gray-300",children:[e.jsx(J,{ariaLabel:a("sessions.filter.source_aria"),options:oe,value:f,onChange:k}),e.jsx(J,{className:"pl-2",ariaLabel:a("sessions.filter.range_aria"),leading:e.jsx(Le,{className:"h-3.5 w-3.5 shrink-0 text-oai-gray-400","aria-hidden":!0}),options:ne,value:b,onChange:g}),e.jsx(Ie,{options:w,value:p,onChange:S,allLabel:a("sessions.filter.project_all"),searchPlaceholder:a("sessions.filter.project_search"),emptyLabel:a("sessions.filter.project_empty"),ariaLabel:a("sessions.filter.project_aria")}),e.jsxs("div",{className:"relative w-72 max-w-full",children:[e.jsx(te,{className:"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-oai-gray-400","aria-hidden":!0}),e.jsx(he,{type:"search",value:m,onChange:s=>v(s.target.value),onKeyDown:s=>{s.key==="Escape"&&m&&(s.preventDefault(),v(""))},"aria-label":a("sessions.action.search_aria"),placeholder:a("sessions.search.placeholder"),className:"h-8 pl-9 pr-8 !border-oai-gray-200 dark:!border-oai-gray-800 focus:!border-oai-gray-400 focus:!ring-oai-gray-400/20 dark:focus:!border-oai-gray-500 dark:focus:!ring-oai-gray-500/20 [&::-webkit-search-cancel-button]:appearance-none"}),e.jsx("button",{type:"button",onMouseDown:s=>s.preventDefault(),onClick:()=>v(""),"aria-label":a("sessions.action.search_clear"),"aria-hidden":!m,tabIndex:m?0:-1,className:D("absolute right-2 top-1/2 flex h-6 w-6 -translate-y-1/2 items-center justify-center rounded-full text-oai-gray-400 transition duration-150 ease-out hover:bg-oai-gray-100 hover:text-oai-gray-600 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-oai-gray-400/40 dark:hover:bg-oai-gray-800 dark:hover:text-oai-gray-200",m?"scale-100 opacity-100":"pointer-events-none scale-90 opacity-0"),children:e.jsx(ue,{className:"h-3.5 w-3.5","aria-hidden":!0})})]}),e.jsx("span",{className:"ml-auto shrink-0 tabular-nums text-oai-gray-500 dark:text-oai-gray-400",children:$.foldedCount>0?a("sessions.thread.result_count",{roots:$.roots.length,subagents:$.foldedCount}):a("sessions.filter.result_count",{filtered:N.length,total:l.length})})]}),ie?e.jsx("p",{className:"mb-4 text-xs text-oai-gray-500 dark:text-oai-gray-400",children:a("sessions.truncated",{shown:r.returned_count,total:r.session_count})}):null,o&&!r?e.jsxs("div",{className:"rounded-xl border border-dashed border-red-300 py-16 text-center dark:border-red-500/40",children:[e.jsx("p",{className:"text-sm font-medium text-oai-black dark:text-white",children:a("sessions.error.title")}),e.jsx("p",{className:"mt-1 text-sm text-oai-gray-500 dark:text-oai-gray-400",children:o}),e.jsx("button",{type:"button",onClick:()=>{A(!1)},className:"mt-4 inline-flex h-8 items-center rounded-md border border-oai-gray-200 px-3 text-xs font-medium text-oai-gray-700 transition-colors hover:bg-oai-gray-100 hover:text-oai-black focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-oai-brand-500 dark:border-oai-gray-800 dark:text-oai-gray-200 dark:hover:bg-oai-gray-800 dark:hover:text-white",children:a("sessions.error.retry")})]}):h?e.jsxs("div",{className:"flex items-center gap-2 py-16 text-sm text-oai-gray-500 dark:text-oai-gray-400",children:[e.jsx(Se,{className:"h-4 w-4 animate-spin","aria-hidden":!0}),a("sessions.loading")]}):N.length===0?e.jsxs("div",{className:"rounded-xl border border-dashed border-oai-gray-200 py-16 text-center dark:border-oai-gray-800",children:[e.jsx("p",{className:"text-sm font-medium text-oai-black dark:text-white",children:B?a("sessions.empty.filtered_title"):a("sessions.empty.title")}),e.jsx("p",{className:"mt-1 text-sm text-oai-gray-500 dark:text-oai-gray-400",children:B?a("sessions.empty.filtered_body"):a("sessions.empty.body")})]}):e.jsxs(e.Fragment,{children:[o?e.jsx("p",{className:"mb-4 text-sm text-red-500 dark:text-red-400",children:a("shared.error.prefix",{error:o})}):null,e.jsx("ul",{className:"divide-y divide-oai-gray-200/70 dark:divide-oai-gray-800/70",children:K.map(s=>{const c=$.childrenByRoot.get(s.session_hash)||[],n=O.has(s.session_hash),d=j.get(s.session_hash)||"all",q=d==="all"?c:c.filter(function(le){return(le.model||a("sessions.model.unknown"))===d});return e.jsxs(ee.Fragment,{children:[e.jsx(X,{session:s,locale:F,childCount:c.length,expanded:n,onToggle:()=>se(s.session_hash)}),n&&c.length?e.jsx(He,{sessions:c,selectedModel:d,onSelect:R=>re(s.session_hash,R)}):null,n?q.map(R=>e.jsx(X,{session:R,locale:F,nested:!0},R.session_hash)):null]},s.session_hash)})}),H?e.jsx("div",{ref:z,className:"flex justify-center pt-6",children:e.jsx("button",{type:"button",onClick:G,className:"inline-flex h-8 items-center rounded-md border border-oai-gray-200 px-3 text-xs font-medium text-oai-gray-600 transition-colors hover:bg-oai-gray-100 hover:text-oai-black focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-oai-brand-500 dark:border-oai-gray-800 dark:text-oai-gray-300 dark:hover:bg-oai-gray-800 dark:hover:text-white",children:a("sessions.action.load_more")})}):null]}),e.jsx("p",{className:"mt-6 text-xs text-oai-gray-400 dark:text-oai-gray-500",children:a("sessions.privacy")})]})})})}export{nt as SessionsPage};
@@ -1 +0,0 @@
1
- import{r as o}from"./__vite-browser-external-CVIGknXl.js";import{h as r,i as t,p as s}from"./react-D_AcI466.js";function i(){!r.current&&t();const[e]=o.useState(s.current);return e}export{i as u};