tokentracker-cli 1.5.0 → 1.5.2

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 (132) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/dashboard/dist/.well-known/submitby-ai/6e2fa70e-9eb2-4c97-a9a9-fed567a3d4a9.txt +1 -0
  4. package/dashboard/dist/assets/AchievementBadge-B5kmt0VD.js +1 -0
  5. package/dashboard/dist/assets/{AchievementsPage-9_MxdI7O.js → AchievementsPage-C0FlkOo0.js} +2 -2
  6. package/dashboard/dist/assets/{AchievementsSection-CKDQGcJh.js → AchievementsSection-CRcp80Pp.js} +1 -1
  7. package/dashboard/dist/assets/{BadgeDetailModal-DdrXPVRL.js → BadgeDetailModal-DAFjGbKW.js} +1 -1
  8. package/dashboard/dist/assets/{BotAnimated-DsJDdDid.js → BotAnimated-CO0bbimB.js} +1 -1
  9. package/dashboard/dist/assets/{Card-Bz-sWY1C.js → Card-Xhr5exz8.js} +1 -1
  10. package/dashboard/dist/assets/{CloudCheckoutPage-DRjZcE0W.js → CloudCheckoutPage-DsQ7FmsI.js} +1 -1
  11. package/dashboard/dist/assets/{CloudPage-BNDyyX9r.js → CloudPage-DkSexu5V.js} +2 -2
  12. package/dashboard/dist/assets/{CommandPalette-LbE6Icc0.js → CommandPalette-Bm0huQdj.js} +1 -1
  13. package/dashboard/dist/assets/{CommunityStatsModal-DuEcAOB9.js → CommunityStatsModal-BsL8GN8Q.js} +1 -1
  14. package/dashboard/dist/assets/{ConfirmModal-B5V7ONKv.js → ConfirmModal-_WPp292g.js} +1 -1
  15. package/dashboard/dist/assets/{Controls-ZfN0QwwD.js → Controls-ktzn68KM.js} +1 -1
  16. package/dashboard/dist/assets/{DashboardPage-DqZPFmlv.js → DashboardPage-CdNXi3Im.js} +1 -1
  17. package/dashboard/dist/assets/{DateRangePopover-CbkBeaEI.js → DateRangePopover-DWr4zIzF.js} +1 -1
  18. package/dashboard/dist/assets/{DevicePage-DrHjmpPH.js → DevicePage-CBa8Mk47.js} +1 -1
  19. package/dashboard/dist/assets/{DialogClose-DHaAwV1u.js → DialogClose-CZ5jzgtb.js} +1 -1
  20. package/dashboard/dist/assets/DialogDescription-kCZ4gN09.js +1 -0
  21. package/dashboard/dist/assets/{DialogTitle-CBhd4oLc.js → DialogTitle-Dr0N6q15.js} +1 -1
  22. package/dashboard/dist/assets/{ElectricLogo-CSWd3b2H.js → ElectricLogo-sYqgrO6-.js} +1 -1
  23. package/dashboard/dist/assets/{FadeIn-D5p6nDla.js → FadeIn-Qq-hcrZW.js} +1 -1
  24. package/dashboard/dist/assets/{HeaderGithubStar-BKVSzY27.js → HeaderGithubStar-B77zSv7i.js} +1 -1
  25. package/dashboard/dist/assets/{HoverTooltip-CvkAyCDm.js → HoverTooltip-lRDaUmoW.js} +1 -1
  26. package/dashboard/dist/assets/{IpCheckPage-BEMJGKtl.js → IpCheckPage-B6AvHZjA.js} +1 -1
  27. package/dashboard/dist/assets/{LandingPage-iRp33enQ.js → LandingPage-DgzOjf3x.js} +2 -2
  28. package/dashboard/dist/assets/{LeaderboardPage-DVMPrN4z.js → LeaderboardPage-BtjjtDMC.js} +2 -2
  29. package/dashboard/dist/assets/{LeaderboardProBadge-DwnaJoje.js → LeaderboardProBadge-B2wNTUTU.js} +1 -1
  30. package/dashboard/dist/assets/{LeaderboardProfileModal-DnzVweLM.js → LeaderboardProfileModal-DJJckwHh.js} +3 -3
  31. package/dashboard/dist/assets/{LeaderboardProfilePage-BHNuPuW7.js → LeaderboardProfilePage-DJdxByl2.js} +1 -1
  32. package/dashboard/dist/assets/LimitsPage-gSBHSBi_.js +6 -0
  33. package/dashboard/dist/assets/{LocalOnlyNotice-DStlbPET.js → LocalOnlyNotice-B2lVqf_H.js} +1 -1
  34. package/dashboard/dist/assets/{LoginCard-I47ukXU5.js → LoginCard-i0gg1yby.js} +1 -1
  35. package/dashboard/dist/assets/{LoginModal-C4iotNjY.js → LoginModal-B-loLNZM.js} +1 -1
  36. package/dashboard/dist/assets/{LoginPage-46QSEnG0.js → LoginPage-D_swI75j.js} +1 -1
  37. package/dashboard/dist/assets/{PetPage-SvgDUR8o.js → PetPage-DDpKvpjG.js} +2 -2
  38. package/dashboard/dist/assets/{PopoverPopup-k2ejLK1I.js → PopoverPopup-Gja4MyEK.js} +1 -1
  39. package/dashboard/dist/assets/{ProviderIcon-Bx1XKzin.js → ProviderIcon-DOPj7tAZ.js} +1 -1
  40. package/dashboard/dist/assets/{ResetPasswordPage-CcKIDknp.js → ResetPasswordPage-BVADLk89.js} +1 -1
  41. package/dashboard/dist/assets/{Select-D0hLQyU8.js → Select-D-38tN-E.js} +1 -1
  42. package/dashboard/dist/assets/{SelectItemText-DJGBJhDK.js → SelectItemText-jN61ukxk.js} +1 -1
  43. package/dashboard/dist/assets/{SelfHostPage-CeIFGRep.js → SelfHostPage-k7AkGpl1.js} +1 -1
  44. package/dashboard/dist/assets/ServiceStatusPage-D_Fa_pYz.js +1 -0
  45. package/dashboard/dist/assets/{SessionsPage-D6h5vSZn.js → SessionsPage-BymccEEz.js} +1 -1
  46. package/dashboard/dist/assets/{SettingsPage-BZgpB5SB.js → SettingsPage-DfnMCAuA.js} +3 -3
  47. package/dashboard/dist/assets/{SkillsPage-CtFuZ1ob.js → SkillsPage-YyIHIaHN.js} +1 -1
  48. package/dashboard/dist/assets/{TokenGalaxy-DC-no047.js → TokenGalaxy-BLcvZuQ9.js} +1 -1
  49. package/dashboard/dist/assets/{TooltipPopup-ZM0Ie2_C.js → TooltipPopup-3E8kyVzz.js} +1 -1
  50. package/dashboard/dist/assets/{TrendMonitor-fpLaqJ-o.js → TrendMonitor-ByKAdXSF.js} +1 -1
  51. package/dashboard/dist/assets/{WidgetsPage-DIoHY6ZJ.js → WidgetsPage-BgEVIIzL.js} +1 -1
  52. package/dashboard/dist/assets/{WrappedPage-D1-7o8Z1.js → WrappedPage-HjbX8QaA.js} +1 -1
  53. package/dashboard/dist/assets/__vite-browser-external-D_cMeuqI.js +45 -0
  54. package/dashboard/dist/assets/{agent-logos-YBC1iAbE.js → agent-logos-BVF2siPQ.js} +1 -1
  55. package/dashboard/dist/assets/{arrow-left-BIe3z7iW.js → arrow-left-CYO24PGP.js} +1 -1
  56. package/dashboard/dist/assets/{arrow-right-CJmRcvYZ.js → arrow-right-Xg9PZYhw.js} +1 -1
  57. package/dashboard/dist/assets/{arrow-up-right-IgkBHoCl.js → arrow-up-right-B7ah6Qv-.js} +1 -1
  58. package/dashboard/dist/assets/{calendar-days-DTuIv3ts.js → calendar-days-BV_iG938.js} +1 -1
  59. package/dashboard/dist/assets/{check-DrXhhj46.js → check--EZH8RTp.js} +1 -1
  60. package/dashboard/dist/assets/{chevron-down-DHaFKHMK.js → chevron-down-BzGTlk0-.js} +1 -1
  61. package/dashboard/dist/assets/{cloud-checkout-BffVMyzI.js → cloud-checkout-BgyxPHEh.js} +1 -1
  62. package/dashboard/dist/assets/{composite-M_CP_KSx.js → composite-C0KrmLEK.js} +1 -1
  63. package/dashboard/dist/assets/{copy-D5xoS-Q8.js → copy-BtucSK2U.js} +1 -1
  64. package/dashboard/dist/assets/{download-CqomMv4-.js → download-CWHq03Y2.js} +1 -1
  65. package/dashboard/dist/assets/{external-link--q3pCw6b.js → external-link-DCTXF5VZ.js} +1 -1
  66. package/dashboard/dist/assets/{flame-CUGlDV__.js → flame-BE5TsqVF.js} +1 -1
  67. package/dashboard/dist/assets/{format-tokens-BZ6TX9Km.js → format-tokens-ThNIMWnZ.js} +1 -1
  68. package/dashboard/dist/assets/{gift-BBgOeC20.js → gift-DgaN9s4-.js} +1 -1
  69. package/dashboard/dist/assets/{icons-BELeB4ms.js → icons-B4r5EiDC.js} +1 -1
  70. package/dashboard/dist/assets/{index-B1B6oAbl.js → index-CKhcCLNC.js} +1 -1
  71. package/dashboard/dist/assets/{index-CsdgnKGf.js → index-DFF9xo6f.js} +1 -1
  72. package/dashboard/dist/assets/{index-CoRqgJ71.js → index-DqCtgU0G.js} +1 -1
  73. package/dashboard/dist/assets/{index-DkBvk4Qg.js → index-fNKH4U7j.js} +33 -33
  74. package/dashboard/dist/assets/{info-BG1vQZ1r.js → info-B4YzRR4y.js} +1 -1
  75. package/dashboard/dist/assets/{link-2-oi5TrXqi.js → link-2-DzbUbaBw.js} +1 -1
  76. package/dashboard/dist/assets/{loader-circle-BQQ_Xbby.js → loader-circle-B9c7D-7v.js} +1 -1
  77. package/dashboard/dist/assets/{local-usage-transfer-Dwz-clJ-.js → local-usage-transfer-btuk_b0Y.js} +1 -1
  78. package/dashboard/dist/assets/{modifiers.esm-C7a817l7.js → modifiers.esm-BjrU-Xz7.js} +1 -1
  79. package/dashboard/dist/assets/module-ZyVsxBG_.js +3 -0
  80. package/dashboard/dist/assets/{monitor-smartphone-Bnbo7uRg.js → monitor-smartphone-Bwn4tb4q.js} +1 -1
  81. package/dashboard/dist/assets/{play-C_xI_JM_.js → play-DIFOwGIQ.js} +1 -1
  82. package/dashboard/dist/assets/{plus-xF6PK5As.js → plus-BpBqnwVg.js} +1 -1
  83. package/dashboard/dist/assets/{provider-display-DxquW3js.js → provider-display-DSrs4u7T.js} +1 -1
  84. package/dashboard/dist/assets/{react-CGK0_x3G.js → react-BgG7_MY0.js} +1 -1
  85. package/dashboard/dist/assets/{safePolygon-CCoDMR4f.js → safePolygon-BUGWIDOM.js} +1 -1
  86. package/dashboard/dist/assets/{search-EZAGpmfJ.js → search-aHrmBmtZ.js} +1 -1
  87. package/dashboard/dist/assets/{server-2qbrx2G0.js → server-DOEvwlEU.js} +1 -1
  88. package/dashboard/dist/assets/{shield-check-D8kUejpE.js → shield-check-BPTnLhsT.js} +1 -1
  89. package/dashboard/dist/assets/{skills-api-DYPf1Vxh.js → skills-api-C052Mwez.js} +1 -1
  90. package/dashboard/dist/assets/{sortable.esm-D9gC08dQ.js → sortable.esm-DaZKhjhu.js} +1 -1
  91. package/dashboard/dist/assets/{store-BWUCbK6Y.js → store-Cq30Pofw.js} +1 -1
  92. package/dashboard/dist/assets/{terminal-B16b7r6H.js → terminal-CoSDSkE7.js} +1 -1
  93. package/dashboard/dist/assets/{trash-BIEoE13C.js → trash-BAmt-kPj.js} +1 -1
  94. package/dashboard/dist/assets/use-community-stats-Bxq0kBhm.js +1 -0
  95. package/dashboard/dist/assets/{use-latest-request-guard-CYKu-VOB.js → use-latest-request-guard-DmIQDlvk.js} +1 -1
  96. package/dashboard/dist/assets/use-limits-display-prefs-CyAn1fme.js +1 -0
  97. package/dashboard/dist/assets/{use-native-settings-vTg4j5Ln.js → use-native-settings-s_CIC8Bb.js} +1 -1
  98. package/dashboard/dist/assets/{use-ordered-list-CtXedlqH.js → use-ordered-list-BHhykAbt.js} +1 -1
  99. package/dashboard/dist/assets/use-reduced-motion-BmFyFE3S.js +1 -0
  100. package/dashboard/dist/assets/{use-transform-CdeW5xhz.js → use-transform-CVeMFlS6.js} +1 -1
  101. package/dashboard/dist/assets/use-usage-limits-DRZMI20u.js +1 -0
  102. package/dashboard/dist/assets/{useCurrency-bqycM681.js → useCurrency-DilqL2Iv.js} +1 -1
  103. package/dashboard/dist/assets/{usePositioner-DEXS10fY.js → usePositioner-BcnySw8a.js} +1 -1
  104. package/dashboard/dist/assets/{useTokenFormat-YF6hY8_m.js → useTokenFormat-CvKW46WP.js} +1 -1
  105. package/dashboard/dist/assets/{zap-Dg-ij-lq.js → zap-D7VRNTwk.js} +1 -1
  106. package/dashboard/dist/index.html +24 -1
  107. package/dashboard/dist/indexnow-key.txt +1 -0
  108. package/dashboard/dist/ip-check.html +1 -1
  109. package/dashboard/dist/leaderboard.html +1 -1
  110. package/dashboard/dist/share.html +1 -1
  111. package/dashboard/dist/tt6a1c9e2f4b8d.txt +1 -0
  112. package/package.json +3 -3
  113. package/src/lib/codex-rollout-parser.js +43 -6
  114. package/src/lib/codex-usage-record.js +21 -0
  115. package/src/lib/pricing/curated-overrides.json +94 -0
  116. package/src/lib/pricing/seed-snapshot.json +1 -1
  117. package/src/lib/qoder-limits.js +252 -55
  118. package/src/lib/rollout.js +68 -14
  119. package/src/lib/session-analytics.js +10 -3
  120. package/src/lib/usage-limits.js +6 -4
  121. package/src/lib/workbuddy-limits.js +101 -9
  122. package/src/lib/zcode-limits.js +350 -43
  123. package/dashboard/dist/assets/AchievementBadge-Dn39pyx9.js +0 -1
  124. package/dashboard/dist/assets/DialogDescription-CEY6jbs9.js +0 -1
  125. package/dashboard/dist/assets/LimitsPage-9LitacBf.js +0 -6
  126. package/dashboard/dist/assets/ServiceStatusPage-DMtw0YDh.js +0 -1
  127. package/dashboard/dist/assets/__vite-browser-external-DZF5L1pt.js +0 -45
  128. package/dashboard/dist/assets/module-C2SOSUuR.js +0 -3
  129. package/dashboard/dist/assets/use-community-stats-DWS7YKbM.js +0 -1
  130. package/dashboard/dist/assets/use-limits-display-prefs-CEAjVxFr.js +0 -1
  131. package/dashboard/dist/assets/use-reduced-motion-DVLsAhSA.js +0 -1
  132. package/dashboard/dist/assets/use-usage-limits-DmDa5Py8.js +0 -1
@@ -12,10 +12,11 @@
12
12
  // WorkBuddy adds its own credentials, including encrypted desktop sessions.
13
13
  // Legacy plaintext credentials remain a fallback when no local IPC exists.
14
14
  //
15
- // Only the subscription plan package is returned — the row the app calls
16
- // 套餐基础积分, with that package's cycle end as the reset. Reward grants
17
- // (活动 / 成长计划 / bonus / extra / gift) are dropped. Display names are
18
- // English regardless of the backend's localized package names.
15
+ // Only two windows are returned, mirroring the desktop app's own split:
16
+ // the subscription plan package (the row the app calls 套餐基础积分, with that
17
+ // package's cycle end as the reset) and one pooled resource-package window
18
+ // for every non-plan credit group (套餐赠送积分 / 购买积分 / 平台奖励积分).
19
+ // Display names are English regardless of the backend's localized names.
19
20
 
20
21
  const fs = require("node:fs");
21
22
  const path = require("node:path");
@@ -278,8 +279,8 @@ function planWindow(row) {
278
279
  };
279
280
  }
280
281
 
281
- // One product row, one account's balance. Prefer a usable quota; when both
282
- // editions are connected China wins deterministically. Never add their pools.
282
+ // Legacy merge for the pre-split unified row. The local app now publishes
283
+ // both editions side by side; cloud mirrors of this module still merge.
283
284
  function selectWorkbuddyLimits(china, international) {
284
285
  const editions = [china, international].filter(Boolean);
285
286
  const usable = (value) => value.configured === true && !value.error;
@@ -289,9 +290,10 @@ function selectWorkbuddyLimits(china, international) {
289
290
  || { configured: false };
290
291
  }
291
292
 
292
- // Pick the one subscription-plan package. Reward rows are ignored. When
293
- // several plan packages exist, the highest tier that still has credit wins,
294
- // matching the desktop app's pickActivePlanBase.
293
+ // Pick the one subscription-plan package. Reward rows are ignored here — they
294
+ // feed the resource-pool window instead. When several plan packages exist, the
295
+ // highest tier that still has credit wins, matching the desktop app's
296
+ // pickActivePlanBase.
295
297
  function selectWorkbuddyPlanQuota(rows, identity = {}, variantId = "workbuddy") {
296
298
  const merged = mergePackageRows(rows.filter(Boolean));
297
299
  const subscriptionPackageCode = identity.code || "";
@@ -309,6 +311,93 @@ function selectWorkbuddyPlanQuota(rows, identity = {}, variantId = "workbuddy")
309
311
  };
310
312
  }
311
313
 
314
+ // The desktop app's billing meter splits an account into CreditGroups:
315
+ // plan_base (套餐基础积分) plus the non-plan pools plan_bonus (套餐赠送积分),
316
+ // addon (购买积分) and benefit (平台奖励积分). The app shows those pools as
317
+ // resource packages on top of the plan, so mirror that split: one window for
318
+ // the plan cycle, one pooled window for everything else. Groups the summary
319
+ // does not quantify are ignored; a pool with no credit at all stays null so
320
+ // the UI drops it like a missing window.
321
+ function collectResourceGroups(summary) {
322
+ const data = unwrapBillingBody(summary);
323
+ if (!data) return null;
324
+ const groups = [
325
+ data.CreditGroups,
326
+ data.creditGroups,
327
+ data.credit_groups,
328
+ ].find(Array.isArray);
329
+ if (groups) {
330
+ const pool = { total: 0, used: 0, remain: 0, remainDerived: 0, seen: false, usedSeen: false, remainSeen: false };
331
+ for (const group of groups) {
332
+ if (!group || typeof group !== "object") continue;
333
+ const kind = firstString(group, ["Kind", "kind"]);
334
+ if (kind && kind.toLowerCase() === "plan_base") continue;
335
+ const total = firstCount(group, ["CycleTotalCapacity", "total"]);
336
+ const used = firstCount(group, ["CycleUsedCapacity", "used"]);
337
+ const remain = firstCount(group, ["CycleRemainCapacity", "remain"]);
338
+ if (total === null && used === null && remain === null) continue;
339
+ pool.seen = true;
340
+ // A group that omits its usage is still counted: derive it from the
341
+ // capacity identity, the way planWindow does for the plan row.
342
+ const knownUsed = used ?? (total !== null && remain !== null ? Math.max(0, total - remain) : null);
343
+ pool.usedSeen = pool.usedSeen || knownUsed !== null;
344
+ pool.remainSeen = pool.remainSeen || remain !== null;
345
+ pool.total += total ?? 0;
346
+ pool.used += knownUsed ?? 0;
347
+ if (remain === null) pool.remainDerived += Math.max(0, (total ?? 0) - (used ?? 0));
348
+ else pool.remain += remain;
349
+ }
350
+ return pool.seen ? pool : null;
351
+ }
352
+ // Older summaries predate CreditGroups. Their package rows carry the same
353
+ // pools one row per package — every row that cannot be the subscription
354
+ // plan is resource credit.
355
+ const identity = readSubscriptionIdentity(summary);
356
+ const rows = collectPackageRows(summary)
357
+ .filter((row) => !isSelectablePlan(row, identity.code));
358
+ if (rows.length === 0) return null;
359
+ const derivedUsed = (row) =>
360
+ row.used ?? (row.total !== null && row.remain !== null ? Math.max(0, row.total - row.remain) : null);
361
+ return {
362
+ total: rows.reduce((sum, row) => sum + (row.total ?? 0), 0),
363
+ used: rows.reduce((sum, row) => sum + (derivedUsed(row) ?? 0), 0),
364
+ remain: rows.reduce((sum, row) => sum + (row.remain ?? 0), 0),
365
+ remainDerived: rows.reduce(
366
+ (sum, row) => sum + (row.remain === null ? Math.max(0, (row.total ?? 0) - (row.used ?? 0)) : 0),
367
+ 0,
368
+ ),
369
+ seen: true,
370
+ usedSeen: rows.some((row) => derivedUsed(row) !== null),
371
+ remainSeen: rows.some((row) => row.remain !== null),
372
+ };
373
+ }
374
+
375
+ // Resource credits have no shared cycle: benefit and add-on packages carry
376
+ // their own grants, so the pooled window has no reset. An empty pool (0/0)
377
+ // yields no window instead of a full or zeroed bar.
378
+ function resourceWindow(pool) {
379
+ if (!pool || !(pool.total > 0) || !Number.isFinite(pool.total)) return null;
380
+ // No group reported either side of the meter: usage is unknowable, not
381
+ // zero — hide the pool instead of rendering a full bar.
382
+ if (!pool.usedSeen && !pool.remainSeen) return null;
383
+ const used = pool.usedSeen || pool.used > 0
384
+ ? pool.used
385
+ : Math.max(0, pool.total - (pool.remain + pool.remainDerived));
386
+ const usedPercent = clampPercent((used / pool.total) * 100);
387
+ if (usedPercent === null) return null;
388
+ const remaining = pool.remainSeen
389
+ ? pool.remain + pool.remainDerived
390
+ : Math.max(0, pool.total - used);
391
+ if (!Number.isFinite(remaining)) return null;
392
+ return {
393
+ used_percent: usedPercent,
394
+ reset_at: null,
395
+ used_credits: used,
396
+ limit_credits: pool.total,
397
+ remaining_credits: remaining,
398
+ };
399
+ }
400
+
312
401
  function englishPlanLabel(row, identity, variantId) {
313
402
  // An actual English subscription/package name takes precedence over the
314
403
  // client's edition fallback. Unknown localized tiers stay unnamed.
@@ -479,6 +568,7 @@ async function fetchPlanQuota(post, variantId) {
479
568
  configured: true, error: null,
480
569
  plan_label: quota?.plan_label || englishPlanLabel({ code: identity.code }, identity, variantId),
481
570
  primary_window: quota?.primary_window || null,
571
+ secondary_window: resourceWindow(collectResourceGroups(summary)),
482
572
  };
483
573
  }
484
574
 
@@ -556,6 +646,8 @@ module.exports = {
556
646
  selectWorkbuddyPlanQuota,
557
647
  selectWorkbuddyLimits,
558
648
  collectPackageRows,
649
+ collectResourceGroups,
650
+ resourceWindow,
559
651
  readSubscriptionIdentity,
560
652
  originAllowed,
561
653
  hostAllowed,