fix(cursor): accept percent-only free usage payloads#269
fix(cursor): accept percent-only free usage payloads#269
Conversation
|
@codex review |
🤖 Augment PR SummarySummary: Updates the Cursor provider to tolerate Free/individual “percent-only” usage payloads where Changes:
Technical Notes: The fallback is scoped to non-team accounts; if neither a finite 🤖 Was this summary useful? React with 👍 or 👎 |
|
augment review |
|
Codex Review: Didn't find any major issues. Chef's kiss. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
There was a problem hiding this comment.
Pull request overview
Updates the Cursor provider plugin to tolerate a newly observed “percent-only” free/individual usage payload shape (missing planUsage.limit but including totalPercentUsed), while keeping team accounts strict about needing a dollar limit.
Changes:
- Allow non-team Cursor accounts to render “Total usage” from
planUsage.totalPercentUsedeven whenplanUsage.limitis absent. - Add regression tests covering (a) percent-only free payloads and (b) team payloads still failing without
limit. - Document the updated/observed Cursor API shape for Total usage.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| plugins/cursor/plugin.js | Adds team-vs-individual gating so percent-only payloads are accepted for non-team accounts while team still requires limit. |
| plugins/cursor/plugin.test.js | Adds regression tests for percent-only free payload acceptance and team payload rejection without limit. |
| docs/providers/cursor.md | Updates provider docs to mention observed percent-only payloads and team limit requirements. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| |---|---|---|---|---| | ||
| | Credits | `GetCreditGrantsBalance` + `/api/auth/stripe.customerBalance` | overview | dollars | Combined total: active grant total + Stripe prepaid balance (negative `customerBalance`). Used stays based on grant usage. | | ||
| | Total usage | `planUsage.totalPercentUsed` | overview | percent (individual) / dollars (team) | Falls back to computed `(limit - remaining) / limit * 100` when `totalPercentUsed` is not finite. Team accounts use dollars format. | | ||
| | Total usage | `planUsage.totalPercentUsed` | overview | percent (individual) / dollars (team) | Falls back to computed `(limit - remaining) / limit * 100` when `totalPercentUsed` is not finite. Free/individual payloads observed on 2026-03-06 may omit `limit`; plugin uses `totalPercentUsed` directly in that case. Team accounts use dollars format and still require `limit`. | |
There was a problem hiding this comment.
Docs note about the computed fallback percent is a bit too specific: in the plugin, when totalPercentUsed is not finite the fallback percent is computed from totalSpend / limit * 100 when totalSpend is present, and only uses (limit - remaining) / limit * 100 when totalSpend is absent. Please update the note so it matches the actual fallback logic.
| | Total usage | `planUsage.totalPercentUsed` | overview | percent (individual) / dollars (team) | Falls back to computed `(limit - remaining) / limit * 100` when `totalPercentUsed` is not finite. Free/individual payloads observed on 2026-03-06 may omit `limit`; plugin uses `totalPercentUsed` directly in that case. Team accounts use dollars format and still require `limit`. | | |
| | Total usage | `planUsage.totalPercentUsed` | overview | percent (individual) / dollars (team) | When `totalPercentUsed` is not finite, falls back to `totalSpend / limit * 100` when `totalSpend` is present, otherwise `(limit - remaining) / limit * 100`. Free/individual payloads observed on 2026-03-06 may omit `limit`; plugin uses `totalPercentUsed` directly in that case. Team accounts use dollars format and still require `limit`. | |
| const ctx = makeCtx() | ||
| ctx.host.sqlite.query.mockReturnValue(JSON.stringify([{ value: "token" }])) | ||
| ctx.host.http.request.mockImplementation((opts) => { | ||
| if (String(opts.url).includes("GetCurrentPeriodUsage")) { |
There was a problem hiding this comment.
This test uses a non-JWT access token ("token"), which makes needsRefresh() treat it as expiring and triggers an implicit /oauth/token refresh call that isn’t explicitly mocked here. To keep the test focused and avoid coupling it to refresh behavior, consider using makeJwt({ sub: ..., exp: ... }) (or explicitly mocking the refresh endpoint).
| const ctx = makeCtx() | ||
| ctx.host.sqlite.query.mockReturnValue(JSON.stringify([{ value: "token" }])) | ||
| ctx.host.http.request.mockImplementation((opts) => { | ||
| if (String(opts.url).includes("GetCurrentPeriodUsage")) { |
There was a problem hiding this comment.
Same as above: using a non-JWT token here causes an implicit refresh attempt via /oauth/token that isn’t mocked, so the test relies on refresh failing gracefully. Using makeJwt(...) (or mocking the refresh response) would make the regression test less brittle.
Summary
planUsage.limitis absent buttotalPercentUsedis presentTesting
bun run test:coverageScreenshots
Before
After