You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(usage): Grok and Cursor usage limits show pace and the even-spend line - #21897
Fixes https://git.cafe/pingdotgg/t3code/issues/21896. The Grok and Cursor rows on Usage → Limits never show the pace icon or the even-spend marker. Their windows have no windowDurationMins, so the client cannot tell how much of the period has elapsed.
Grok: the billing response already reports currentPeriod.start, but grokUsageResponseToLimits does not decode it.
Cursor: the usage response already reports billingCycleStart, but cursorUsageResponseToLimits only reads billingCycleEnd.
Change
packages/provider-grok/src/server/usageLimits.ts now decodes currentPeriod.start and sets windowDurationMins to the rounded minutes between start and end. Because it uses the reported bounds, monthly periods get their real length instead of a fixed constant. If start is missing, not a string, unparsable, or not before end, the window stays as it is today, without a duration.
start is decoded as Schema.optional(Schema.Unknown) so an unexpected value cannot fail the whole billing read. This matches the shape https://git.cafe/pingdotgg/t3code/pulls/17061 adds to the same struct, so whichever PR lands second has a trivial rebase. https://git.cafe/pingdotgg/t3code/pulls/21802 also touches this file, and I will rebase if either lands first.
packages/provider-cursor/src/server/usageLimits.ts does the same for Cursor. It decodes billingCycleStart (a millisecond timestamp, string or number, like billingCycleEnd) and sets windowDurationMins on each monthly window to the rounded minutes between the two. If the start is missing, not positive, or not before the end, the window is reported without a duration, as before.
Scope and approval
This is a small, focused fix for an obvious bug, filed as https://git.cafe/pingdotgg/t3code/issues/21896. Claude, Codex, and OpenCode Go windows already send windowDurationMins, and the Usage page uses it the same way for every provider. Grok and Cursor already return the period start, but their adapters discard it. The fix changes one function per adapter. It does not change contracts, clients, or settings. Cursor was added after a report on https://git.cafe/pingdotgg/t3code/issues/21896.
Verification
Confirmed against the live billing endpoint that the Grok response includes the period start. Weekly account, period fields only: {"type":"USAGE_PERIOD_TYPE_WEEKLY","start":"2026-10-14T20:51:37.352+00:00","end":"2026-10-21T20:51:37.352+00:00"}.
Confirmed against the live Cursor endpoint (GetCurrentPeriodUsage) that the response includes billingCycleStart next to billingCycleEnd. For the current cycle the two differ by exactly 30 days, which is 43200 minutes.
Grok, before merging current main: vp test run apps/server/src/provider/GrokProvider.test.ts passed 36 tests. New cases cover a real-shaped weekly period (10080 minutes), a February monthly period (40320 minutes), unusable starts (missing, null, number, invalid string, equal to end, after end), and an HTTP decoding test that would fail if start were dropped from the schema. With the source change reverted, the two duration tests fail and the rest pass.
Cursor: vp test run src/server/usageLimits.test.ts in packages/provider-cursor passes 8 tests. New cases cover a 30-day and a 31-day cycle (43200 and 44640 minutes) and unusable starts (missing, empty, 0, non-numeric, equal to the end). With the source change reverted, the duration test fails and the rest pass.
vp fmt --check and vp lint on packages/provider-cursor/src/server: clean.
Manual check for Grok: ran vp run dev with an isolated --home-dir, added the Grok provider, and opened Usage → Limits with the same account.
Before (change reverted): the row shows only 96% left. The tooltip reads Grok: 96% left, resets in 2d 0h.
After: the row shows the "Under pace" icon and the even-spend marker. The tooltip reads Grok: 96% left, resets in 2d 1h, 29% of the window left.
Before:
After:
Not checked:
The Cursor row on the Usage page. The Cursor change is covered by the unit tests and the live response check above only.
A monthly Grok period on a real account (I only have a weekly one; the unit test covers it) and the mobile client.
After merging current main I could not install dependencies locally (pnpm install --frozen-lockfile stops on minimumReleaseAge for 29 lockfile entries), so the Grok tests, the typecheck, and the knip pre-commit step did not run locally for the final commit. CI needs to cover those.
Claude Opus 5.5 and Claude Sonnet 5.5 in T3 Code (Claude Code harness).
Grok's billing response reports the current period's start, but the
adapter dropped it, so the Grok window had no windowDurationMins and the
Usage page could not compute pace or place the even-spend marker.
Read currentPeriod.start and derive the window length from the reported
bounds, which also covers monthly periods of different lengths.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reviewing files that changed from the base of the PR and between 4160402 and 4d0eb0e.
You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.
Use the checkbox below for a quick retry:
Trigger review
No actionable comments were generated in the recent review.
Walkthrough
Grok and Cursor usage limit converters now derive windowDurationMins from reported period boundaries. Tests cover valid durations and cases where the duration is omitted because the start bound is invalid or unavailable.
Changes: Usage window duration
Layer / File(s)
Summary
Derive and validate the Grok window duration packages/provider-grok/src/server/usageLimits.ts, apps/server/src/provider/GrokProvider.test.ts
The converter calculates duration from the reported period bounds and retains its zero-usage inference conditions. Tests cover weekly and monthly periods, invalid starts, and duration calculation through readGrokAccount.
Derive and validate the Cursor window duration packages/provider-cursor/src/server/usageLimits.ts, packages/provider-cursor/src/server/usageLimits.test.ts
The response type accepts a billing-cycle start as a string or number. The converter includes a positive duration when the bounds allow calculation. Tests cover 30- and 31-day cycles and invalid starts.
No actionable issue is established for the Grok or Cursor duration changes; they are mergeable after normal checks.
Pre-merge checks: 4
Check name
Status
Explanation
Title check
The title clearly identifies the Grok and Cursor usage-limit fix and its visible effects. It is concise, specific, and related to the main changes.
Description check
The description includes all required sections: problem, change, scope and approval, and verification. It explains the implementation, linked issue, tests, manual checks, limitations, and remaining ve…
Linked Issues check
Issue #21896 requires Grok usage windows to provide the period duration so the Usage page can show the pace icon, even-spend marker, and window-percentage tooltip. grokUsageResponseToLimits now pars…
Out of Scope Changes check
The Grok source and tests directly implement #21896. The Cursor source and tests address the same reported symptom by using the already available billingCycleStart and are explicitly included in the…
Full details: Description check
Explanation
The description includes all required sections: problem, change, scope and approval, and verification. It explains the implementation, linked issue, tests, manual checks, limitations, and remaining verification gaps.
Full details: Linked Issues check
Explanation
Issue #21896 requires Grok usage windows to provide the period duration so the Usage page can show the pace icon, even-spend marker, and window-percentage tooltip. grokUsageResponseToLimits now parses currentPeriod.start and currentPeriod.end, computes rounded minutes, and adds windowDurationMins only for a valid positive duration. The Grok tests cover weekly periods, variable monthly periods, unusable starts, and HTTP decoding. Existing client behavior can use this field for the requested indicators.
Full details: Out of Scope Changes check
Explanation
The Grok source and tests directly implement #21896. The Cursor source and tests address the same reported symptom by using the already available billingCycleStart and are explicitly included in the current PR intent. The Cursor changes preserve the existing fallback when the start is missing, invalid, or not before the end. No unrelated contract, client, settings, or repository changes appear in the reviewed diff.
Finishing Touches
Generate unit tests (beta)
Create a new PR
Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.
thanks @wookiist. the reported period bounds are the right source for pace and the even-spend marker, including variable-length months. i kept your commits and merged current main into this branch.
i simplified the duration calculation to reuse main's strict period-boundary parser. the same parsed bounds now serve zero-usage inference and duration, so impossible dates cannot produce a misleading pace. no client, contract, or settings changes. i kept your weekly/monthly, invalid-start, and billing-decoding tests, added an impossible start, and updated the existing zero-usage expectations.
verification passed through blacksmith-testbox: the two duration tests fail against main for the missing field; all 26 grok tests pass with the fix; vp run check:changed passes format, lint, knip, graphql generation, affected typechecks (5 packages), and focused tests. the worker needed its shallow snapshot attached to the pinned main commit for the changed-file comparison.
browser evidence uses the real usage page in system chrome with the same fixed weekly billing fixture and clock. each snapshot uses the actual converter from main or this branch. the after capture shows both the pace icon and even-spend marker. this proves rendering, not live account integration. live grok billing credentials and native mobile/desktop clients are unverified on this vm. the existing mocked HTTP decoding test covers the provider read path. both independent reviews approve cdc2312da3a21573b4b7f6a776dba1810b4a3cf3, with no findings. github CI and four preview workflows are action_required with no jobs: a maintainer must approve these fork workflows. the green status contexts do not include those blocked workflows. coderabbit skipped a fresh review due to its review quota. this pr is waiting on human workflow approval, not merge-ready yet.
Thanks @maria-rcks for picking this up! Reusing the shared period-boundary parser makes sense, and the extra impossible-start test is a nice addition. Happy to help with anything else if needed.
The Cursor usage response carries billingCycleStart, but the adapter only
read billingCycleEnd, so the monthly windows had no windowDurationMins.
Without it the Usage page cannot show the pace badge or the even-spend
marker. Derive the length from end - start, as the Grok adapter does, and
omit it when the start is missing or invalid.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
wookiist
changed the title
fix(provider-grok): Grok usage limits show pace and the even-spend line
fix(usage): Grok and Cursor usage limits show pace and the even-spend line
Nov 8, 2026
@maria-rcks@juliusmarminge I pushed a follow-up that adds the same fix for Cursor, as discussed in #21896, and merged current main into the branch (no conflicts). Could you take another look?
Both providers are covered by unit tests that need no account: the Grok cases in GrokProvider.test.ts and the Cursor cases in usageLimits.test.ts. The live Cursor response does include billingCycleStart, a 30-day cycle for my account. For the manual check, the Grok screenshots are in the PR description. I did not check the Cursor row on the Usage page itself.
Locally I could only run the Cursor tests after the merge, because pnpm install --frozen-lockfile stops on minimumReleaseAge. So the Grok tests and the typecheck need CI.
Also, the PR has had pr:gate-failed since Oct 27. If a specific gate failed, or CI is waiting for a run approval, please let me know what I should change.
Written by Claude Sonnet 5.5 on behalf of @wookiist.
Real web app; fresh databases; same browser, 1280×800 viewport and light theme. Synthetic upstream responses exercise each commit's unchanged adapters: Grok seven-day period and Cursor thirty-day billing cycle, both halfway elapsed.
Steps on both commits: enable the fixture accounts before startup → pair → Usage → Limits → hover Grok Weekly → hover Cursor Models.
Base omits pace icons, even-spend lines and window percentages. Head shows the icons and halfway lines on all three rows, with 'Even pace — 50% left by now' in both inspected hover panels.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bugfixFix PR opened by an issue lead; enters the PR looppr:gate-failedA land gate failedsize:S10-29 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.
3 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Fixes https://git.cafe/pingdotgg/t3code/issues/21896. The Grok and Cursor rows on Usage → Limits never show the pace icon or the even-spend marker. Their windows have no
windowDurationMins, so the client cannot tell how much of the period has elapsed.currentPeriod.start, butgrokUsageResponseToLimitsdoes not decode it.billingCycleStart, butcursorUsageResponseToLimitsonly readsbillingCycleEnd.Change
packages/provider-grok/src/server/usageLimits.tsnow decodescurrentPeriod.startand setswindowDurationMinsto the rounded minutes betweenstartandend. Because it uses the reported bounds, monthly periods get their real length instead of a fixed constant. Ifstartis missing, not a string, unparsable, or not beforeend, the window stays as it is today, without a duration.startis decoded asSchema.optional(Schema.Unknown)so an unexpected value cannot fail the whole billing read. This matches the shape https://git.cafe/pingdotgg/t3code/pulls/17061 adds to the same struct, so whichever PR lands second has a trivial rebase. https://git.cafe/pingdotgg/t3code/pulls/21802 also touches this file, and I will rebase if either lands first.packages/provider-cursor/src/server/usageLimits.tsdoes the same for Cursor. It decodesbillingCycleStart(a millisecond timestamp, string or number, likebillingCycleEnd) and setswindowDurationMinson each monthly window to the rounded minutes between the two. If the start is missing, not positive, or not before the end, the window is reported without a duration, as before.Scope and approval
This is a small, focused fix for an obvious bug, filed as https://git.cafe/pingdotgg/t3code/issues/21896. Claude, Codex, and OpenCode Go windows already send
windowDurationMins, and the Usage page uses it the same way for every provider. Grok and Cursor already return the period start, but their adapters discard it. The fix changes one function per adapter. It does not change contracts, clients, or settings. Cursor was added after a report on https://git.cafe/pingdotgg/t3code/issues/21896.Verification
{"type":"USAGE_PERIOD_TYPE_WEEKLY","start":"2026-10-14T20:51:37.352+00:00","end":"2026-10-21T20:51:37.352+00:00"}.GetCurrentPeriodUsage) that the response includesbillingCycleStartnext tobillingCycleEnd. For the current cycle the two differ by exactly 30 days, which is 43200 minutes.main:vp test run apps/server/src/provider/GrokProvider.test.tspassed 36 tests. New cases cover a real-shaped weekly period (10080 minutes), a February monthly period (40320 minutes), unusable starts (missing,null, number, invalid string, equal toend, afterend), and an HTTP decoding test that would fail ifstartwere dropped from the schema. With the source change reverted, the two duration tests fail and the rest pass.vp test run src/server/usageLimits.test.tsinpackages/provider-cursorpasses 8 tests. New cases cover a 30-day and a 31-day cycle (43200 and 44640 minutes) and unusable starts (missing, empty,0, non-numeric, equal to the end). With the source change reverted, the duration test fails and the rest pass.vp fmt --checkandvp lintonpackages/provider-cursor/src/server: clean.vp run devwith an isolated--home-dir, added the Grok provider, and opened Usage → Limits with the same account.96% left. The tooltip readsGrok: 96% left, resets in 2d 0h.Grok: 96% left, resets in 2d 1h, 29% of the window left.Before:
After:
Not checked:
mainI could not install dependencies locally (pnpm install --frozen-lockfilestops onminimumReleaseAgefor 29 lockfile entries), so the Grok tests, the typecheck, and theknippre-commit step did not run locally for the final commit. CI needs to cover those.Claude Opus 5.5 and Claude Sonnet 5.5 in T3 Code (Claude Code harness).
🤖 Generated with Claude Code
Fixes #21896