Skip to content

feat(settings): surface quota preflight cutoff in Settings → Routing - #12014

Closed
adivekar-utexas wants to merge 6 commits into
diegosouzapw:mainfrom
adivekar-utexas:feat/quota-preflight-routing-ui
Closed

feat(settings): surface quota preflight cutoff in Settings → Routing#12014
adivekar-utexas wants to merge 6 commits into
diegosouzapw:mainfrom
adivekar-utexas:feat/quota-preflight-routing-ui

Conversation

@adivekar-utexas

Copy link
Copy Markdown
Contributor

Summary

The quota-preflight cutoff (resilience.quotaPreflight) already exists in the runtime (it arms credential selection to skip accounts whose remaining quota has hit a cutoff without sending the request upstream), but it had no UI surface — and the /api/resilience PATCH schema silently rejected the section (.strict() dropped it), so it could only be enabled via env var.

This PR surfaces it in Settings → Routing as a "Quota Preflight Cutoff" card:

  • Toggle to enable/disable the preflight cutoff globally.
  • "Global cutoff (min remaining %)" number field (default 2% remaining = stop at 98% used).
  • Per-window cutoffs configured on the Provider Quota page (the Cutoff modal per connection, quotaWindowThresholds) and per-provider window defaults keep precedence; the global default only applies to windows without their own cutoff.

What changed

  • src/shared/validation/schemas/settings.ts — added quotaPreflightSettingsSchema and wired it into updateResilienceSchema (previously the section was dropped by .strict()).
  • src/app/api/resilience/route.ts — GET/PATCH now round-trip quotaPreflight (PATCH was already computing it via mergeResilienceSettings; it just wasn't accepted on input or returned).
  • src/app/(dashboard)/dashboard/settings/components/QuotaPreflightCard.tsx — new card (loads from GET /api/resilience, saves via PATCH /api/resilience with { quotaPreflight }).
  • src/app/(dashboard)/dashboard/settings/routing/page.tsx — mounts the card under the existing Routing Strategy card.
  • src/i18n/messages/en.json — keys for the card (other locales fall back to English via the existing tx() pattern used elsewhere in the settings UI).
  • tests/unit/quota-preflight-routing-ui.test.ts — 3 tests: schema accepts the section, schema rejects malformed values, persisted enabled: true resolves through resolveResilienceSettings (the flag auth.ts reads to arm the preflight latency gate).

Behavior notes

  • No default behavior change: the setting remains off by default (existing enabled: false factory default; enabling via env var QUOTA_PREFLIGHT_CUTOFF_ENABLED still works).
  • Once enabled, credential selection (getProviderCredentialsWithQuotaPreflight) checks each candidate account's quota windows (5h / weekly / monthly / credits, whatever the provider's quota fetcher exposes — e.g. Command Code's five_hour / weekly / credits) against the cutoff and skips exhausted accounts, falling back to the next account in the strategy order without making an upstream request to the skipped account. This is exactly the "skip out-of-quota accounts in priority order without wasting time" behavior.
  • If all accounts are at/below the cutoff, the request returns 429 allRateLimited with the earliest reset time instead of dispatching to an exhausted account.

Test plan

  • tests/unit/quota-preflight-routing-ui.test.ts — 3/3 pass.
  • tests/unit/sse-auth.test.ts — 66/66 pass (preflight gating + sibling selection).
  • tests/unit/combo-priority-quota-exhaustion-cutoff-5923.test.ts, tests/unit/quota-exhaustion-cutoff-opencode.test.ts, tests/unit/issue-6686-quota-preflight-coverage.test.ts — 9/9 pass.
  • npx tsc --noEmit -p tsconfig.typecheck-core.json — clean.
  • npx eslint on the new/changed non-barrel files — clean (pre-existing barrel-level unused-import errors in schemas/settings.ts are untouched).

Add a Quota Preflight Cutoff card to the routing settings page that
enables the pre-existing resilience.quotaPreflight cutoff from the UI
(it previously had no surface and the /api/resilience schema dropped the
section via .strict()). When enabled, credential selection skips accounts
whose remaining quota (5h/weekly/monthly/credits windows) is at or below
the cutoff without sending a request upstream, falling back to the next
account in the strategy order. Per-window cutoffs set on the Provider
Quota page keep precedence over the global default.

Wire quotaPreflight through updateResilienceSchema and the
/api/resilience GET/PATCH round-trip, add the card component + en.json
keys, and cover the schema/persistence path with unit tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
adivekar-utexas and others added 5 commits August 29, 2026 19:01
The i18n parity gate (i18n-pt-br.test.ts) fails when en.json gains keys
that pt-BR.json lacks. Mirror the new settings.quotaPreflight* keys into
pt-BR.json (English fallbacks for now, same pattern as other untranslated
keys) so the UI-coverage CI shard goes green.

Co-authored-by: Cursor <cursoragent@cursor.com>
The i18n completeness gates (i18n-vi-completeness, i18n-pt-br, and the
locale-parity family in CI) require every locale to carry the same keys as
en.json. Mirror the new settings.quotaPreflight* keys into all 41 non-English
locale files using the English strings as fallbacks, matching the established
pattern for untranslated keys.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ction

The resilience HTTP e2e pins the exact /api/resilience response key set.
Adding quotaPreflight to the GET projection (Settings → Routing quota
preflight card, diegosouzapw#12014) requires updating this expectation — the response
must expose the configuration for the card to load it.

Co-authored-by: Cursor <cursoragent@cursor.com>
…own)

Co-authored-by: Cursor <cursoragent@cursor.com>
…ing page-data collection; all other jobs green)

Co-authored-by: Cursor <cursoragent@cursor.com>
@diegosouzapw

Copy link
Copy Markdown
Owner

@adivekar-utexas — confirmei que #12090 é esta PR + 3 commits extras (refactor do context_length routing) na mesma branch/autor (git merge-base --is-ancestor confirma que todo commit desta PR está contido em #12090). Fechando esta em favor de #12090, que cobre tudo aqui e mais. Obrigado!

diegosouzapw pushed a commit that referenced this pull request Aug 30, 2026
)

Honra um `context_length` definido pelo operador em tempo de requisição no roteamento do combo (supersede #12014, que estava incluída nos mesmos commits). Boa cobertura de testes, incluindo o refactor de `resolveComboContextLimit` para módulo próprio. Validado no worktree combinado (13/13). Obrigado!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants