tokentracker-cli 0.79.8 → 0.80.0
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.
- package/dashboard/dist/assets/{AchievementBadge-Ctu3c_8t.js → AchievementBadge-D9jOMhlD.js} +1 -1
- package/dashboard/dist/assets/{AchievementsPage-B3kBTHDB.js → AchievementsPage-DuswZa4g.js} +2 -2
- package/dashboard/dist/assets/{AchievementsSection-CAnTXGpC.js → AchievementsSection-BJPeE1Uq.js} +1 -1
- package/dashboard/dist/assets/{BadgeDetailModal-oTUXEQk9.js → BadgeDetailModal-nNPIsy6i.js} +1 -1
- package/dashboard/dist/assets/{Card-BHt5f5cD.js → Card-VENq8eEp.js} +1 -1
- package/dashboard/dist/assets/{ClawdAnimated-ChxXY3l0.js → ClawdAnimated-Cq7TW0vv.js} +1 -1
- package/dashboard/dist/assets/{CommunityStatsModal-CVLlItP1.js → CommunityStatsModal-y2VftQuq.js} +1 -1
- package/dashboard/dist/assets/{ConfirmModal-ClrILpb3.js → ConfirmModal-CWgnJ4hm.js} +1 -1
- package/dashboard/dist/assets/{Controls-D_XBBpIh.js → Controls-BUQ_iZZq.js} +1 -1
- package/dashboard/dist/assets/DashboardPage-WkiygMmq.js +19 -0
- package/dashboard/dist/assets/{DevicePage-J7DW7yeX.js → DevicePage-Dh3XDtNx.js} +1 -1
- package/dashboard/dist/assets/{DialogClose-B1r9gzUF.js → DialogClose-KTFU_B3F.js} +1 -1
- package/dashboard/dist/assets/DialogDescription-DIra288n.js +1 -0
- package/dashboard/dist/assets/{DialogTitle-BL2puDA7.js → DialogTitle-bza2pIek.js} +1 -1
- package/dashboard/dist/assets/{FadeIn-Cd-YT4oT.js → FadeIn-Dm3FVNfr.js} +1 -1
- package/dashboard/dist/assets/{HeaderGithubStar-BAtl4a-K.js → HeaderGithubStar-CbSElzLt.js} +1 -1
- package/dashboard/dist/assets/{IpCheckPage-BXK_cYN2.js → IpCheckPage-BDON7VCU.js} +1 -1
- package/dashboard/dist/assets/{LandingPage-C_16AbpF.js → LandingPage-Ck3CwZrt.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardAvatar-B0vUuCYU.js → LeaderboardAvatar-GVUy0Ynq.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardPage-Duhdaq09.js → LeaderboardPage-C19Rkt44.js} +2 -2
- package/dashboard/dist/assets/{LeaderboardProfileModal-CFFyHRTB.js → LeaderboardProfileModal-QcEq_o6E.js} +3 -3
- package/dashboard/dist/assets/{LeaderboardProfilePage-CjTelV-4.js → LeaderboardProfilePage-pFhI6292.js} +1 -1
- package/dashboard/dist/assets/{LimitsPage-DIcXRgSv.js → LimitsPage-ChV3Qezd.js} +1 -1
- package/dashboard/dist/assets/{LocalOnlyNotice-DC7wXWds.js → LocalOnlyNotice-ALvpjznF.js} +1 -1
- package/dashboard/dist/assets/{LoginPage--8hYT3aq.js → LoginPage-CL-QrJxU.js} +1 -1
- package/dashboard/dist/assets/{PetPage-ByWUW7-V.js → PetPage-DSuvdGgd.js} +1 -1
- package/dashboard/dist/assets/{PopoverPopup-g_v1fmhH.js → PopoverPopup-jSDQ87Bi.js} +1 -1
- package/dashboard/dist/assets/{ResetPasswordPage-BfunstIi.js → ResetPasswordPage-Dk2IDAJq.js} +1 -1
- package/dashboard/dist/assets/{Select-C4ShPt1t.js → Select-Cz6WTj7D.js} +1 -1
- package/dashboard/dist/assets/{SelectItemText-gw_TdvY6.js → SelectItemText-BZyRjWCM.js} +1 -1
- package/dashboard/dist/assets/{SettingsPage-BFCFrDuA.js → SettingsPage-CANz8HMM.js} +1 -1
- package/dashboard/dist/assets/{SkillsPage-BNQDySeK.js → SkillsPage-WZkQG_83.js} +1 -1
- package/dashboard/dist/assets/{WidgetsPage-B3bHP3Vk.js → WidgetsPage-BEyJ62NV.js} +1 -1
- package/dashboard/dist/assets/{WrappedPage-6amxWnWT.js → WrappedPage-Ck_dOx_w.js} +1 -1
- package/dashboard/dist/assets/{agent-logos-DPIQzYms.js → agent-logos-DpjHiAbZ.js} +1 -1
- package/dashboard/dist/assets/{arrow-up-right-CKcE2mif.js → arrow-up-right-C4iYPBtK.js} +1 -1
- package/dashboard/dist/assets/check-BkPUxPZV.js +1 -0
- package/dashboard/dist/assets/{copy-vi-V2M_I.js → copy-CHJ-38K6.js} +1 -1
- package/dashboard/dist/assets/{download-BH0Spg15.js → download-BSeG8u17.js} +1 -1
- package/dashboard/dist/assets/{flame-C3jUAnqA.js → flame-DeHwKcE-.js} +1 -1
- package/dashboard/dist/assets/{format-tokens-tnfJT09G.js → format-tokens-B-MJYJyp.js} +1 -1
- package/dashboard/dist/assets/{info-CGCZ5JvP.js → info-DA_0xr_o.js} +1 -1
- package/dashboard/dist/assets/{link-2-CXULWwZY.js → link-2-noUH83Lc.js} +1 -1
- package/dashboard/dist/assets/{loader-circle-B324hSa3.js → loader-circle-wL7KZtm0.js} +1 -1
- package/dashboard/dist/assets/{main-vGUuyRq-.js → main-BHfJDFcu.js} +20 -20
- package/dashboard/dist/assets/{provider-display-CeoAhoCb.js → provider-display-DxIClOGM.js} +1 -1
- package/dashboard/dist/assets/{trash-2-L9vxbDeP.js → trash-2-B8TPUmxZ.js} +1 -1
- package/dashboard/dist/assets/{use-community-stats-DLE30Lh0.js → use-community-stats-CXD3MRRE.js} +1 -1
- package/dashboard/dist/assets/{use-limits-display-prefs-BxN--PEW.js → use-limits-display-prefs-C2pJVYTn.js} +1 -1
- package/dashboard/dist/assets/{use-native-settings-Dn5gWQkJ.js → use-native-settings-BeOBLEZa.js} +1 -1
- package/dashboard/dist/assets/{use-ordered-list-DYoz2NJ9.js → use-ordered-list-kAtW8pJm.js} +1 -1
- package/dashboard/dist/assets/{use-quality-per-dollar-pref-JXorBQsT.js → use-quality-per-dollar-pref-CFZUZM3S.js} +1 -1
- package/dashboard/dist/assets/{use-transform-BTTF5vPC.js → use-transform-B9YwpyKi.js} +1 -1
- package/dashboard/dist/assets/{use-usage-limits-BUemSWQ9.js → use-usage-limits-DSX5iKPE.js} +1 -1
- package/dashboard/dist/assets/{useCurrency-Cxv4RR3U.js → useCurrency-CKg5K4Nj.js} +1 -1
- package/dashboard/dist/assets/{useScrollLock-DTPnHKfF.js → useScrollLock-DyyY_Vyt.js} +1 -1
- package/dashboard/dist/assets/useTokenFormat-FfTjEH_m.js +1 -0
- package/dashboard/dist/assets/{zap-CG8zuY9S.js → zap-B69x9NCT.js} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/dashboard/dist/share.html +1 -1
- package/package.json +1 -1
- package/src/commands/init.js +89 -12
- package/src/commands/serve.js +65 -4
- package/src/commands/status.js +2 -1
- package/src/commands/sync.js +170 -7
- package/src/commands/uninstall.js +10 -2
- package/src/lib/claude-config.js +69 -28
- package/src/lib/diagnostics.js +2 -2
- package/src/lib/local-api.js +19 -6
- package/src/lib/openclaw-session-plugin.js +13 -0
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/src/lib/rollout.js +63 -2
- package/src/lib/usage-limits.js +9 -5
- package/dashboard/dist/assets/DashboardPage-CizTJox2.js +0 -19
- package/dashboard/dist/assets/DialogDescription-Bd9-kaCS.js +0 -1
- package/dashboard/dist/assets/check-B5V4_ezt.js +0 -1
- package/dashboard/dist/assets/useTokenFormat-DMAb2ec3.js +0 -1
package/src/lib/rollout.js
CHANGED
|
@@ -1514,6 +1514,16 @@ async function parseRolloutFile({
|
|
|
1514
1514
|
let currentCwd = null;
|
|
1515
1515
|
let currentDate = null;
|
|
1516
1516
|
let isForkedRollout = false;
|
|
1517
|
+
// The replay prefix only ever exists at the head of a freshly-forked file. A
|
|
1518
|
+
// resumed scan (startOffset > 0) can never see it — and never re-reads the
|
|
1519
|
+
// session_meta line, so isForkedRollout stays false there anyway — but gate
|
|
1520
|
+
// on the offset explicitly so correctness does not hinge on that distant
|
|
1521
|
+
// invariant. Known accepted limitation: if a sync's read races the fork's
|
|
1522
|
+
// single-flush write and persists a cursor INSIDE the burst, the resumed
|
|
1523
|
+
// scan counts the remaining burst tail (bounded over-count, ms-wide window;
|
|
1524
|
+
// self-heals on any inode-changing rescan and never drops genuine usage).
|
|
1525
|
+
let replayPrefixActive = startOffset === 0;
|
|
1526
|
+
let prevForkedTokenMs = null;
|
|
1517
1527
|
const rolloutDate = rolloutDateFromPath(filePath);
|
|
1518
1528
|
let currentProjectRef = projectRef || null;
|
|
1519
1529
|
let currentProjectKey = projectKey || null;
|
|
@@ -1591,8 +1601,50 @@ async function parseRolloutFile({
|
|
|
1591
1601
|
totals = totalUsage;
|
|
1592
1602
|
}
|
|
1593
1603
|
|
|
1594
|
-
//
|
|
1595
|
-
|
|
1604
|
+
// Forked Codex rollouts replay the parent session's entire token history
|
|
1605
|
+
// into the child file the moment the fork is created. The date guard below
|
|
1606
|
+
// (current_date < rolloutDate) catches cross-day forks, but same-day forks
|
|
1607
|
+
// share the parent's current_date and slip through it. The replay is written
|
|
1608
|
+
// in a single flush, so its rows carry near-identical timestamps (sub-ms to a
|
|
1609
|
+
// few ms apart across observed 0.129–0.137 samples), while the first genuine
|
|
1610
|
+
// live turn lands seconds later (≥11s in every sampled fork). We therefore
|
|
1611
|
+
// skip the *leading* run of densely-spaced token_count rows and latch off
|
|
1612
|
+
// permanently at the first multi-second gap: a lone fast turn (always
|
|
1613
|
+
// preceded by a large gap) is never dropped, and an arbitrarily large replay
|
|
1614
|
+
// is fully skipped regardless of length. The threshold sits far above the
|
|
1615
|
+
// flush spacing and well below genuine turn cadence (≥~4.6s observed). The
|
|
1616
|
+
// first replayed row cannot be identified without lookahead, so it is still
|
|
1617
|
+
// counted (a bounded, <1% residual over-count); dropping real usage is the
|
|
1618
|
+
// worse failure, so we bias against it. `totals` is already advanced above,
|
|
1619
|
+
// keeping the cumulative-delta baseline correct for the live turns we keep.
|
|
1620
|
+
// Scoped to forked codex rollouts. (issue #169 follow-up.)
|
|
1621
|
+
let forkedReplaySkip = false;
|
|
1622
|
+
if (isForkedRollout && source === DEFAULT_SOURCE && replayPrefixActive) {
|
|
1623
|
+
const tokenMs = Date.parse(tokenTimestamp);
|
|
1624
|
+
// Fail open on anything the burst heuristic was not measured against:
|
|
1625
|
+
// an unparseable timestamp or a backwards clock step permanently ends
|
|
1626
|
+
// the prefix, so no later row can be skipped off a stale baseline.
|
|
1627
|
+
// Replay flushes are monotonic in every sampled rollout (2,116 gaps,
|
|
1628
|
+
// min 0ms), so this never fires on genuine replays.
|
|
1629
|
+
if (!Number.isFinite(tokenMs) || (prevForkedTokenMs !== null && tokenMs < prevForkedTokenMs)) {
|
|
1630
|
+
replayPrefixActive = false;
|
|
1631
|
+
} else {
|
|
1632
|
+
if (prevForkedTokenMs !== null && tokenMs - prevForkedTokenMs >= CODEX_FORK_REPLAY_GAP_MS) {
|
|
1633
|
+
replayPrefixActive = false;
|
|
1634
|
+
}
|
|
1635
|
+
forkedReplaySkip =
|
|
1636
|
+
replayPrefixActive &&
|
|
1637
|
+
prevForkedTokenMs !== null &&
|
|
1638
|
+
tokenMs - prevForkedTokenMs < CODEX_FORK_REPLAY_GAP_MS;
|
|
1639
|
+
prevForkedTokenMs = tokenMs;
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
// date matching is conservative; same-day fork replays are caught by the
|
|
1644
|
+
// burst detector above rather than this cross-day date guard.
|
|
1645
|
+
if (forkedReplaySkip || isForkedReplayToken({ isForkedRollout, rolloutDate, currentDate })) {
|
|
1646
|
+
continue;
|
|
1647
|
+
}
|
|
1596
1648
|
|
|
1597
1649
|
const bucketStart = toUtcHalfHourStart(tokenTimestamp);
|
|
1598
1650
|
if (!bucketStart) continue;
|
|
@@ -2694,6 +2746,15 @@ function normalizeIsoDate(value) {
|
|
|
2694
2746
|
return match ? match[1] : null;
|
|
2695
2747
|
}
|
|
2696
2748
|
|
|
2749
|
+
// Max inter-row gap (ms) still treated as part of a forked rollout's replay
|
|
2750
|
+
// burst. Empirically the replay flush spaces rows sub-ms to a few ms apart while
|
|
2751
|
+
// genuine live turns arrive ≥~4.6s apart and the replay→live break is ≥11s, so
|
|
2752
|
+
// any value in the ~0.25–2s band separates them with a wide margin; 500ms biases
|
|
2753
|
+
// toward the low end because merging a real fast turn (under-count) is worse than
|
|
2754
|
+
// leaving a slow replay counted (bounded over-count). See the skip site in
|
|
2755
|
+
// parseRolloutFile. (issue #169 follow-up.)
|
|
2756
|
+
const CODEX_FORK_REPLAY_GAP_MS = 500;
|
|
2757
|
+
|
|
2697
2758
|
function isForkedReplayToken({ isForkedRollout, rolloutDate, currentDate }) {
|
|
2698
2759
|
return Boolean(isForkedRollout && rolloutDate && currentDate && currentDate < rolloutDate);
|
|
2699
2760
|
}
|
package/src/lib/usage-limits.js
CHANGED
|
@@ -2823,6 +2823,7 @@ async function fetchUsageLimitsUncached({
|
|
|
2823
2823
|
requestFn,
|
|
2824
2824
|
now = new Date(),
|
|
2825
2825
|
providerTimeoutMs = DEFAULT_PROVIDER_TIMEOUT_MS,
|
|
2826
|
+
forceRefresh = false,
|
|
2826
2827
|
} = {}) {
|
|
2827
2828
|
const nowMs = Date.now();
|
|
2828
2829
|
|
|
@@ -2870,11 +2871,14 @@ async function fetchUsageLimitsUncached({
|
|
|
2870
2871
|
// Skip the upstream Claude call entirely while a 429 cooldown is active — calling again
|
|
2871
2872
|
// just renews the penalty. The result handling below serves cache or a cooldown message.
|
|
2872
2873
|
const claudeRetryAtMs = claudeToken ? readClaudeRateLimitRetryAtMs({ home, nowMs }) : null;
|
|
2873
|
-
// Also avoid cross-process hammering after a recent successful read
|
|
2874
|
-
//
|
|
2875
|
-
//
|
|
2876
|
-
//
|
|
2877
|
-
|
|
2874
|
+
// Also avoid cross-process hammering after a recent successful read: embedded-server
|
|
2875
|
+
// restarts and background polls read the disk cache instead of spending another Claude
|
|
2876
|
+
// OAuth usage request. An explicit user refresh (refresh=1 → forceRefresh) punches
|
|
2877
|
+
// through this cache — but never through the 429 cooldown above, which is exactly the
|
|
2878
|
+
// hammering the cooldown exists to prevent.
|
|
2879
|
+
const freshClaudeCache = claudeToken && !forceRefresh
|
|
2880
|
+
? readFreshClaudeLimitsCache({ home, nowMs })
|
|
2881
|
+
: null;
|
|
2878
2882
|
|
|
2879
2883
|
const providerFetch = withFetchTimeout(fetchImpl, providerTimeoutMs);
|
|
2880
2884
|
const [claudeResult, codexResult, cursor, kimi, gemini, kiro, antigravity, copilot, grok, zcode, opencodeGo] = await Promise.all([
|