Skip to content

fix(server): show Cursor's monthly allowance in Limits again - #29

Merged
andrewcai8 merged 2 commits into
mainfrom
fix/cursor-usage-window-ids
Sep 22, 2026
Merged

andrewcai8 merged 2 commits into
mainfrom
fix/cursor-usage-window-ids

Conversation

@andrewcai8

Copy link
Copy Markdown
Owner

Why

The Usage panel showed "No limits reported." for every Cursor account. The fork's display filter keeps only a window with id cursor_auto, a name from the old dashboard reader. The upstream merge made the driver replace that reader's output with readCursorUsageLimits, which names windows after API fields such as autoPercentUsed. Every probe succeeded and every window was filtered out.

Scope

  • CURSOR_MONTHLY_WINDOW_ID in packages/contracts, used by both the producer and the display filter, so the id names the concept instead of an API field.
  • cursorUsageLimits.ts: reports one window, the included Auto allowance, and restores windowDurationMins from the billing cycle start so the pace marker works.
  • Deleted the dashboard's limit path (currentPeriod, its schema and cache, usageLimits in the status check). The driver overwrote it on every check, so it was dead. identify stays for the account email.

Blast Radius

Only Cursor rows in the Limits view. The Total and API windows are no longer sent; the view already dropped both.

Verification

  • A captured API response fed through the real probe and displayUsageLimits now yields the monthly window at 74.43% with its reset time; limitsNotice is null. This test failed before the fix.
  • tsc --noEmit clean in packages/contracts, packages/shared, and apps/server. Two pre-existing Cursor skills-path tests fail the same way on main (macOS /private/var symlinks).

🤖 Generated with Claude Code

andrewcai8 and others added 2 commits September 22, 2026 17:03
Fails on main: the probe's windows are dropped by the display filter, so
every Cursor account reads "No limits reported."

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The Cursor usage probe named its windows after API fields
(totalPercentUsed, autoPercentUsed, apiPercentUsed) while the Limits view
kept only "cursor_auto", so every Cursor account read "No limits
reported."

The probe now reports one window, the included Auto allowance, under the
shared CURSOR_MONTHLY_WINDOW_ID that the display filter also reads. It
also parses billingCycleStart so the window keeps its pace marker. The
dashboard reader's period limits were overwritten by the probe on every
authenticated check, so that path is deleted.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@andrewcai8
andrewcai8 enabled auto-merge (squash) September 22, 2026 21:06
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L labels Sep 22, 2026
@github-actions

github-actions Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 13.5 KiB 13.5 KiB +28 B (+0.2%) 15.1 KiB ✅
Codex Thread snapshot wire 7.1 KiB 7.1 KiB −5 B (−0.1%) 7.3 KiB ✅
Codex Live turn WebSocket wire 6.4 KiB 6.5 KiB +33 B (+0.5%) 7.8 KiB ✅
Codex Live turn WebSocket decoded 56.2 KiB 56.3 KiB +44 B (+0.1%) 66.4 KiB ✅
Codex Live turn messages 9 10 +1 (+11.1%) 21 ✅
Claude Total thread wire 13.5 KiB 13.5 KiB +23 B (+0.2%) 15.1 KiB ✅
Claude Thread snapshot wire 7.1 KiB 7.1 KiB −2 B (−0.0%) 7.3 KiB ✅
Claude Live turn WebSocket wire 6.5 KiB 6.5 KiB +25 B (+0.4%) 7.8 KiB ✅
Claude Live turn WebSocket decoded 57.0 KiB 57.1 KiB +44 B (+0.1%) 66.4 KiB ✅
Claude Live turn messages 9 10 +1 (+11.1%) 21 ✅

Baseline: 0232597 · PR result: 4736e6b · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 113.9 KiB
  • Claude decoded thread snapshot: 114.6 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@andrewcai8

Copy link
Copy Markdown
Owner Author

Verdict: PASS+NOTES at 4736e6b1c6.

Tests. vp test run on the five named files: 5 files, 91 tests, 89 passed, 2 failed. The two failures are Cursor skills > discovers recursive project skills with project precedence and Cursor skills > treats a symlinked skill outside the root as a package boundary. Running those two on main (0232597323) fails identically, with received paths under /private/var/folders/... (macOS symlink). Pre-existing, unrelated to this PR.

Test-first. On the test-only commit cd41f56b18, Cursor usage limits > reports the monthly allowance in the window the Limits view shows fails (plus the same two skills tests). It passes at head.

Dead code removed. rg -n "currentPeriod|usageLimits" apps/server/src/provider has no Cursor dashboard hits. The remaining currentPeriod hits are Grok's own reader. The only Cursor usageLimits producer left is CursorDriver.ts:146 via readCursorUsageLimits.

One id. CURSOR_MONTHLY_WINDOW_ID is defined once in packages/contracts/src/providerUsageLimits.ts. The producer (cursorUsageLimits.ts:47) and the filter (packages/shared/src/usageLimits.ts:35) both import it. No other non-test code uses the literal.

Clients. rg -n "cursor_auto|cursor_api|cursor_ondemand|autoPercentUsed" apps packages --glob '!*.test.*' finds nothing in apps/web or apps/mobile. Web (ComposerUsageLimits, UsageLimitsPooled) and mobile (UsageLimitsPooled, UsageLimitsSection, the widget snapshot) all go through the shared helpers.

tsc. tsc --noEmit in packages/contracts, packages/shared, apps/server all exit 0 with 0 errors. Only pre-existing TS377 suggestions appear, and none are at error severity.

Notes (not blocking):

  1. apps/server/src/orchestration/FleetCapacity.ts:72 still excludes cursor_api, and FleetCapacity.test.ts fixtures still use cursor_auto and cursor_api. Cursor no longer emits either id, so that branch is dead. The runtime effect of this PR is positive. On main, the emitted apiPercentUsed window (100%) would have gated Cursor lanes as exhausted. Now only cursor_monthly gates. The fixtures and the exclusion are worth a follow-up cleanup.
  2. The filter no longer relabels, so the label now comes from the server. A newer client talking to an older server that still emits cursor_auto will show no Cursor window. This is inferred from the diff and was not exercised. It only matters during version skew.

Independent verification by Claude Opus 5.5 (poteto-agent)

@andrewcai8
andrewcai8 merged commit 46cf18e into main Sep 22, 2026
25 of 26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant