Skip to content

feat: track provider usage and project weekly quota#1605

Open
Aditya190803 wants to merge 3 commits intopingdotgg:mainfrom
Aditya190803:feat/weekly-usage
Open

feat: track provider usage and project weekly quota#1605
Aditya190803 wants to merge 3 commits intopingdotgg:mainfrom
Aditya190803:feat/weekly-usage

Conversation

@Aditya190803
Copy link
Copy Markdown

@Aditya190803 Aditya190803 commented Mar 31, 2026

What Changed

  • Added provider usage normalization and merge utilities for Codex/Claude quota payloads.
  • Extended provider snapshots and websocket config/update flow to carry normalized usage buckets.
  • Fixed usage percent math to avoid double-scaling low percentages derived from usage/limit.
  • Fixed usage cache merge behavior so stale cached usage is dropped when a newer provider snapshot omits usage.
  • Added/updated tests covering usage normalization, merge behavior, and stale cache handling.

Why

Issue #228 asks for accurate quota visibility. This PR adds provider usage projection and makes it robust under incremental updates so UI quota values stay correct. The follow-up fixes address reviewer-reported edge cases that could misreport low usage percentages or retain stale usage after newer snapshots.

UI Changes

  • Settings provider quota bars now render normalized usage/reset data from provider snapshots.
  • No layout redesign.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Closes #228

Note

Track provider usage quotas and display weekly/5-hour usage buckets in settings

  • Adds normalizeProviderUsageFromRateLimits in providerUsage.ts to derive standardized ServerProviderUsageBucket records from heterogeneous Codex and Claude rate-limit payloads.
  • Extends Claude and Codex provider probes to collect rate-limit data and return account, rateLimits, and derived usage fields on the ServerProvider snapshot.
  • The WebSocket server maintains a per-provider usage cache, merges incremental account.rate-limits.updated events, and pushes serverProvidersUpdated only when usage materially changes.
  • Adds ProviderUsageRows to the settings UI to render a progress bar, remaining percentage, and reset timestamp for each usage bucket.
  • Behavioral Change: serverGetConfig and serverRefreshProviders responses now include provider usage fields; stale cached usage is dropped when the provider snapshot has a newer timestamp.

Macroscope summarized 6b8ed4d.


Note

Medium Risk
Touches provider probing and WebSocket provider update logic to ingest and cache rate-limit events; bugs here could cause incorrect quota display or extra/missed serverProvidersUpdated pushes.

Overview
Adds end-to-end provider quota/usage tracking by extending ServerProvider snapshots with optional account, rateLimits, and normalized usage buckets (weekly/5-hour).

Codex and Claude probes now collect rate-limit payloads (Codex via account/rateLimits/read + account/rateLimits/updated, Claude via SDK rate_limit_event capture), normalize them via new normalizeProviderUsageFromRateLimits, and attach derived usage to provider status.

The server now maintains a per-provider usage cache that merges incremental account.rate-limits.updated runtime events, drops stale cached usage when newer provider snapshots omit it, and only pushes server.providersUpdated when usage materially changes; the settings UI renders these buckets as progress bars with remaining percent and reset time.

Written by Cursor Bugbot for commit 6b8ed4d. This will update automatically on new commits. Configure here.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 31, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 7d94fdf2-6028-43be-8f44-f60835306908

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
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added size:XL 500-999 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Mar 31, 2026
@Aditya190803 Aditya190803 marked this pull request as draft March 31, 2026 11:08
@Aditya190803 Aditya190803 marked this pull request as ready for review March 31, 2026 11:13
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 11eab91d87

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

Comment on lines +137 to +140
const mergedUsage = mergeProviderUsage(cachedUsage, provider.usage);
if (mergedUsage !== undefined) {
nextCache[provider.provider] = mergedUsage;
continue;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Drop stale usage cache when provider snapshot has no usage

In mergeUsageCacheFromProviders, stale entries are never evicted because mergeProviderUsage(cachedUsage, provider.usage) returns cachedUsage whenever the new snapshot omits usage, so the mergedUsage !== undefined branch always keeps the cache and bypasses shouldKeepCachedUsage. This means a newer provider snapshot (checkedAt later than cached updatedAt) can still be served with outdated quota buckets via serverGetConfig and server.providersUpdated.

Useful? React with 👍 / 👎.

Comment on lines +76 to +77
if (limit !== null && limit > 0) {
return normalizePercent((usage / limit) * 100);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid double-scaling low usage percentages

derivePercentFromUsage converts absolute usage to percent with (usage / limit) * 100, then passes that result to normalizePercent, which multiplies any value <= 1 by 100 again. For low-but-valid percentages (for example usage=1, limit=1000), this reports 10% instead of 0.1%, causing major quota misreporting near the start of a window.

Useful? React with 👍 / 👎.

@github-actions github-actions bot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Apr 1, 2026
Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

planType: "pro",
});
expect(state.rateLimits).toBeNull();
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grace period exceeds test abort timeout causing rejection

High Severity

The test passes AbortSignal.timeout(1_000) (1s) but RATE_LIMITS_PROBE_GRACE_MS is 1_500 (1.5s). When the stub ignores account/rateLimits/read, the grace timer starts after the account snapshot is set. The abort signal fires at ~1s — before the 1.5s grace timer resolves rateLimitsPayload to null — causing fail() to reject the promise with an abort error instead of the expected successful resolution.

Additional Locations (1)
Fix in Cursor Fix in Web

@Aditya190803
Copy link
Copy Markdown
Author

I cleaned up the branch history to reduce review noise and make the change set easier to reason about.

What changed:

  1. Rebased onto latest main.
  2. Removed merge/sync churn from feature history.
  3. Squashed follow-up fixups into logical commits.
  4. Kept implementation scope unchanged (no new feature surface beyond already discussed fixes).

Current commit structure:

  1. feat(contracts): add normalized provider usage and quota bucket schemas
  2. feat(server): normalize provider rate-limit usage and stabilize usage cache updates
  3. feat(web): render provider quota usage buckets in settings

Behavior/correctness included in this cleaned history:

  1. Fix low-percent double-scaling risk in usage normalization.
  2. Drop stale cached usage when newer provider snapshots omit usage.
  3. Clamp over-limit utilization and suppress no-op provider update pushes.
  4. Preserve tests across contracts/server/web for quota projection and cache behavior.

Validation run locally:

  1. bun fmt
  2. bun lint
  3. bun typecheck

No functional intent change; this is primarily a history hygiene pass for clearer review.

@juliusmarminge
Copy link
Copy Markdown
Member

Please add screenshots

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: add usage / quota visibility for Codex sessions and accounts

2 participants