Repository navigation
feat(usage): surface Codex code-review weekly window + additional_rate_limits fallback - #4494
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Code Review
This pull request introduces support for extracting and displaying the secondary (weekly) window of Codex code-review rate limits, and adds a fallback mechanism to detect these limits within additional_rate_limits when the dedicated code_review_rate_limit block is missing. It also updates the UI label mapping and adds comprehensive unit tests. The reviewer suggested simplifying the descriptor matching logic to handle hyphenated variants and eliminate redundant checks, as well as checking the title field of entries for better coverage.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| function isCodexReviewLimitDescriptor(...values: unknown[]): boolean { | ||
| return values.some((value) => { | ||
| if (typeof value !== "string") return false; | ||
| const normalized = value.trim().toLowerCase(); | ||
| if (!normalized) return false; | ||
| return ( | ||
| normalized === "code_review" || | ||
| normalized === "codex_review" || | ||
| normalized === "review" || | ||
| normalized.includes("code_review") || | ||
| normalized.includes("codex_review") || | ||
| normalized.includes("code review") | ||
| ); | ||
| }); | ||
| } |
There was a problem hiding this comment.
The current implementation of isCodexReviewLimitDescriptor contains redundant checks (e.g., normalized === "code_review" is fully covered by normalized.includes("code_review")). Additionally, it does not support hyphenated variants like code-review or codex-review which are common in API payloads.
We can simplify and make this check more robust by replacing underscores and hyphens with spaces, then performing a clean match. This handles all common formats (code_review, code-review, code review, etc.) while safely avoiding false positives like preview.
function isCodexReviewLimitDescriptor(...values: unknown[]): boolean {
return values.some((value) => {
if (typeof value !== "string") return false;
const normalized = value.trim().toLowerCase();
if (!normalized) return false;
const clean = normalized.replace(/[-_]/g, " ");
return (
clean === "review" ||
clean.includes("code review") ||
clean.includes("codex review")
);
});
}| if ( | ||
| isCodexReviewLimitDescriptor( | ||
| getFieldValue(entry, "limit_name", "limitName"), | ||
| getFieldValue(entry, "metered_feature", "meteredFeature"), | ||
| getFieldValue(entry, "limit_id", "limitId"), | ||
| entry["id"], | ||
| entry["name"] | ||
| ) | ||
| ) { |
There was a problem hiding this comment.
To align with findCodexSparkRateLimit and ensure defensive coverage, we should also check entry["title"] when identifying the review rate limit descriptor. Some plans or upstream variants might report the user-friendly name in the title field.
| if ( | |
| isCodexReviewLimitDescriptor( | |
| getFieldValue(entry, "limit_name", "limitName"), | |
| getFieldValue(entry, "metered_feature", "meteredFeature"), | |
| getFieldValue(entry, "limit_id", "limitId"), | |
| entry["id"], | |
| entry["name"] | |
| ) | |
| ) { | |
| if ( | |
| isCodexReviewLimitDescriptor( | |
| getFieldValue(entry, "limit_name", "limitName"), | |
| getFieldValue(entry, "metered_feature", "meteredFeature"), | |
| getFieldValue(entry, "limit_id", "limitId"), | |
| entry["id"], | |
| entry["name"], | |
| entry["title"] | |
| ) | |
| ) { |
…e_limits fallback The Codex usage dashboard only emitted the primary `code_review_rate_limit` window as `quotas.code_review` and dropped review descriptors that arrive via the `additional_rate_limits` array (the shape some ChatGPT Codex plans report). `buildCodexUsageQuotas` now: - Emits the secondary window as `quotas.code_review_weekly` (mirrors the existing `session`/`weekly` pair for the normal rate limit). - Falls back to the matching `additional_rate_limits[]` entry when the dedicated `code_review_rate_limit` block is empty — matched on `limit_name`, `metered_feature`, `limit_id`, `id`, or `name` containing `code_review`, `codex_review`, or `review`. The dedicated block stays preferred when both are present. The existing `quotas.code_review` key is preserved (back-compat for the dashboard rendering and the `usage-service-hardening` regression test). The new `code_review_weekly → "Code Review Weekly"` label is registered in `ProviderLimits/utils.tsx` so the card renders both windows side-by-side. TDD: 4 new assertions in `tests/unit/codex-usage-quotas-review-window.test.ts` (secondary-window surfacing, `additional_rate_limits` fallback, silent-payload back-compat, dedicated-block preference) + 1 label assertion appended to `tests/unit/provider-limits-ui.test.ts`. All 46 codex-usage-related tests pass. What we did NOT port from upstream: - The virtual `<model>-review` chat-model variants — OmniRoute already exposes `codex-auto-review` as a dedicated native review model (`CODEX_NATIVE_UNPREFIXED_MODELS`), so per-model `-review` aliases would duplicate that surface. - The `idToken` removal — OmniRoute actively parses the `id_token` JWT to extract the workspace id used for `chatgpt-account-id` binding on the usage endpoint (`src/lib/oauth/providers/codex.ts::parseIdToken`); removing it would break workspace selection. - The `max_completion_tokens` / `max_output_tokens` stripping — the Codex executor already enforces an allowlist (`RESPONSES_API_ALLOWLIST`) that rejects unknown chat-completions fields before they reach upstream. Inspired-by: decolua/9router#836 (review-quota plumbing pattern) Co-authored-by: Rezky Hamid <hiepau1231@gmail.com>
b7dfaa0 to
61cbd9b
Compare
…e_limits fallback (diegosouzapw#4494) Rebuilt onto release/v3.8.33 (squash-base-stale). Integrated into release/v3.8.33.
…iegosouzapw#4512) Rebuilt onto release/v3.8.33; usage.ts baseline reconciled for the diegosouzapw#4493/diegosouzapw#4494/diegosouzapw#4512 quota trio. Integrated into release/v3.8.33.
Summary
Ports the review-quota plumbing half of an upstream fix (author @hiepau1231) into OmniRoute. The Codex usage dashboard only emitted the primary
code_review_rate_limitwindow asquotas.code_reviewand dropped review descriptors that arrive via theadditional_rate_limitsarray (the shape some ChatGPT Codex plans report).buildCodexUsageQuotasnow:quotas.code_review_weekly(mirrors the existingsession/weeklypair for the normal rate limit).additional_rate_limits[]entry when the dedicatedcode_review_rate_limitblock is empty — matched onlimit_name,metered_feature,limit_id,id, ornamecontainingcode_review,codex_review, orreview.The dedicated block stays preferred when both are present. The existing
quotas.code_reviewkey is preserved (back-compat for the dashboard rendering and theusage-service-hardeningregression). The newcode_review_weekly → "Code Review Weekly"label is registered inProviderLimits/utils.tsx.What we did NOT port
<model>-reviewchat-model variants — OmniRoute already exposescodex-auto-reviewas a dedicated native review model (CODEX_NATIVE_UNPREFIXED_MODELS), so per-model-reviewaliases would duplicate that surface.idTokenremoval — OmniRoute actively parses theid_tokenJWT to extract the workspace id used forchatgpt-account-idbinding on the usage endpoint (src/lib/oauth/providers/codex.ts::parseIdToken); removing it would break workspace selection.max_completion_tokens/max_output_tokensstripping — the Codex executor already enforces an allowlist (RESPONSES_API_ALLOWLIST) that rejects unknown chat-completions fields before they reach upstream.Test plan
node --import tsx/esm --test tests/unit/codex-usage-quotas-review-window.test.ts(4 new assertions: secondary-window surfacing,additional_rate_limitsfallback, silent-payload back-compat, dedicated-block preference)tests/unit/provider-limits-ui.test.tsnode --import tsx/esm --test tests/unit/codex-usage-quotas-review-window.test.ts tests/unit/provider-limits-ui.test.ts tests/unit/usage-service-hardening.test.ts tests/unit/codex-quota-fetcher.test.ts tests/unit/codex-quota-sync-no-proactive-refresh.test.ts— all 55 greennpm run typecheck:core— cleannpx eslinton touched files — cleanInspired-by: upstream contribution by