Skip to content

fix(codex): derive quota expiry from exhausted windows - #570

Merged
Menci merged 3 commits into
Menci:mainfrom
codebyyassine:fix/codex-rate-limit-expiry
Oct 3, 2026
Merged

Menci merged 3 commits into
Menci:mainfrom
codebyyassine:fix/codex-rate-limit-expiry

Conversation

@codebyyassine

Copy link
Copy Markdown
Contributor

Summary

Codex quota snapshots contain separate primary and secondary usage percentages and reset times. Floway previously set ratelimited_until to the later reset from either window on every 429, even when that window still had capacity. That could keep the Codex account card or upstream-list signal marked rate-limited past the reset of the quota that was actually exhausted.

This PR derives the displayed timed restriction only from windows with a finite reported usage of at least 100% and a valid reset time. When both windows are known to be exhausted, the later of those exhausted windows' known resets remains the timed restriction.

Related report from the fork: Issue #5. It is linked for context; it is not an issue in this upstream repository and is not being closed automatically.

Changes

  • Add one Codex-provider-owned rule for deriving the latest known exhausted-window reset. Use it both for new rate-limit observations and for dashboard projections of already-stored snapshots that have a legacy rate-limit marker.
  • Keep legacy correction non-mutating. Preserve original per-window usage, reset metadata, observation times, and quota-family separation. Successful snapshots without a rate-limit marker are unchanged.
  • If an exhausted window lacks a reset, do not invent one. A known reset on another exhausted window remains visible. The displayed time is the latest known timed restriction, not a guarantee that all quota restrictions have ended.
  • Add provider and control-plane coverage for exhausted/non-exhausted windows, missing or invalid values, supported reset formats, partial metadata, legacy projections, and preservation of stored state.
  • Add rendered component timer coverage for the upstream-list signal and account card, plus request-path coverage that proves cached quota metadata does not gate calls, successful observations replace only their own family, and real upstream 429 status, headers, and body are preserved.

Behavior and scope

The Codex quota badge is informational. The data plane does not use ratelimited_until to reject or skip requests. Floway continues to send requests upstream and returns a real upstream 429 unchanged; this change corrects the displayed known timed restriction and leaves upstream response behavior intact.

The UI behavior was exercised locally with synthetic quota snapshots. It was not tested against a live Codex account or deployment. In particular, an expired known timer does not prove that an account with incomplete quota metadata is fully available; a subsequent upstream response remains authoritative.

Verification

  • pnpm run verify passed: type generation, lint, typecheck, 599 test files / 6,488 tests, repository checks, and web build.
  • Installer harness: 66 passed, 44 skipped because PowerShell is unavailable on the verification host.
  • pnpm run test apps/web/__tests__/components/upstream-editor/codex-quota-expiry_test.tsx packages/provider-codex/__tests__/fetch_test.ts passed: 2 files / 82 tests.
  • pnpm run lint passed.
  • pnpm run typecheck passed.
  • Browser check used the actual rendered Floway components with synthetic data: the badge expired as the known timer passed without a new request, while the observed 100% usage remained visible. Secondary/both-window, partial metadata, successful-observation, dark-theme, and narrow-viewport cases were also checked. No browser console errors or horizontal overflow were observed.

No deployment was performed.

@Menci
Menci merged commit c27a761 into Menci:main Oct 3, 2026
8 checks passed
yyyr-p added a commit to yyyr-p/Floway that referenced this pull request Oct 4, 2026
Integrates upstream commits e286553..c7e4d78:
- refactor(responses): lower agent_message in a request middleware (Menci#576)
- fix(claude-code): update subscription request defaults (Menci#571)
- fix(compaction): use the context compaction shim by default (Menci#572)
- fix(codex): derive quota expiry from exhausted windows (Menci#570)
- fix(tls): support IP-literal certificate identities (Menci#569)
- fix(web-search): resolve the OpenAI search passthrough lazily (Menci#568)
- fix(provider-codex): update stable client identity for newer models (Menci#567)
- fix(provider-codex): preserve Responses Lite wire semantics (Menci#543)
- feat(web): adopt the blue Floway logo (Menci#563)
- feat(codex): show and redeem ChatGPT reset cards (Menci#528)
- fix(responses): answer Codex WebSocket prewarms locally (Menci#552)
- fix(responses): handle positional tool declarations in middleware (Menci#558)
- fix(gateway): preserve first-token timing across tool continuations (Menci#561)
- fix(responses): consume hosted-tool streams before billing metadata (Menci#560)
- fix(codex): restore output omitted from terminal snapshots (Menci#551)
- fix(codex): preserve model catalog context windows (Menci#559)
- fix(web): disable inactive upstream disclosure (Menci#534)
- fix(translate): isolate translated request payloads (Menci#557)
- feat(models): support Claude Sonnet 5.5 (Menci#555)
- feat(models): support GPT-6.1 Sol (Menci#553)
- fix(web): allow imported credentials on upstream creation (Menci#556)
- fix(gateway): preserve hosted tool selection across aliases and continuations (Menci#549)
- fix(translate): restore Responses callable identities (Menci#547)
- perf(translate): bound namespace tool name allocation work (Menci#548)
- fix(translate): preserve namespace descriptions on child tools (Menci#545)
- feat(requests): show each request's time to first token (Menci#550)
- fix(translate): reject ambiguous flat callable kinds (Menci#542)
- fix(gateway): preserve client tool identity in hosted dispatch (Menci#538)
- fix(web): mask credential headers in request record exports (Menci#539)

Conflict resolutions:
- upstreams/access-control.tsx: keep the fork's parameterized title,
  description, and error props (title/description ?? defaults, plus
  defaultOpen/revealOn) alongside upstream Menci#534's disclosureDisabled={!override}.
- upstreams/access-control_test.tsx: union the Control helper to accept both
  error and initialOverride, and keep both Menci#534's disabled-disclosure case and
  the fork's validation-error cases.
- control-plane/routes.ts: union the schemas.ts named imports -- the fork's
  OAuth2 admin bodies plus upstream Menci#528's codexRateLimitResetCreditsBody and
  codexRateLimitResetConsumeBody; both sides' route blocks merged cleanly.
- requests/ttft_test.tsx (Menci#550): pass the fork's required exchangeStreams={[]}
  to the RequestDetailPanel cases that construct it with no collected streams.

Verified with pnpm run verify (typegen, lint, typecheck, 611 test files /
6644 tests, test:installers, check:agents-md, check:generated-assets,
check:verify-parity, build:web).
wang563681252 added a commit to wang563681252/Floway that referenced this pull request Oct 7, 2026
Integrate 68 upstream commits while retaining live Copilot catalog pricing, guarded historical repricing, Windows Codex auth, and encrypted replay lanes. Resolve compatibility identities and advance the catalog contract to revision 16. Adapt Azure Compose and Caddy to the bundled Node dashboard while preserving existing loopback ports and data volumes.

Upstream references: Menci#482, Menci#488, Menci#523, Menci#570, Menci#571, Menci#572, Menci#584.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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