publish the Codex quota reading clients warn on - #140
Conversation
A spent subscription window arrives as an `error` event carrying `usage_limit_reached` and the moment the window reopens. Nothing read it: the failure classified as a retryable rate limit, and the delay lookup covers `retry_after`, `retry_after_seconds` and `headers.retry-after`, none of which this event carries. With no delay the live stream spent its whole budget -- eleven upstream attempts over 2m54s in a capture of the failure, each answered 429 in under a second -- and then returned 429 with no reset information, so clients retried immediately against a window that reopens hours later. Recognise the event and answer it once, with the headers clients already read for rate limit state: which window ran out and when it reopens. Retry-After is deliberately absent, since clients sleep for its full value and here that is hours; x-should-retry stops the retry loop instead.
Codex reports how much of each subscription window is spent as a `codex.rate_limits` event inside the stream, and nothing forwarded it. The only quota signal reaching a client was the refusal itself, so work stopped with no warning that the allowance was running low. Keep the newest reading and put it on the response, in the headers clients already parse for rate limit state: the spent fraction and reset time of each window, and which one is closest to running out. A window is identified by the length it reports rather than the slot it arrived in, since which rank carries which length has changed between payload versions, and both spellings of the reset field are read for the same reason. The spent fraction only reaches a caller once a threshold is declared surpassed, so a window past its line says which line it crossed. The defaults -- 0.9 for the session window, 0.75 for the weekly -- are the points Anthropic's own windows warn at; CCP_CODEX_QUOTA_WARN_AT lowers both for a consumer that wants the figure earlier. A reading whose window has since reopened is dropped rather than published, so the turn after a reset does not announce an allowance as nearly gone at the moment it came back. A refusal keeps its own headers: it carries the exact state of the window that refused it.
|
Thanks. What do these PRs enable? |
|
The goal is to use the proxy with the Claude Agent SDK and get the native The SDK (and Claude Code itself) only learns about limits from the #139 covers the spent window. Codex ends the stream with an #140 covers the healthy case. Codex sends a Verified end to end with the SDK in all three states (allowed, |
Builds on #139 — the first of the two commits here is that PR, and this diff becomes a single commit once it merges.
What happens now
During a healthy stream Codex reports how much of each subscription window is spent, as a
codex.rate_limitsevent:{"type":"codex.rate_limits", "rate_limits":{"allowed":true,"limit_reached":false, "primary":{"used_percent":4,"window_minutes":300, "reset_after_seconds":16394,"reset_at":1788897775}, "secondary":{"used_percent":16,"window_minutes":10080, "reset_after_seconds":584857,"reset_at":1789466238}}}Nothing forwards it, so the only quota signal a client ever sees is the refusal. Work stops with no warning that the allowance was running low — which is the case where nobody can tell why the assistant stopped answering.
What this changes
The newest reading is kept and put on the response, in the headers clients already parse for rate limit state:
The event arrives ahead of the first content event, so in practice the reading is ready for the response it came from rather than the one after.
Less obvious details:
reset_at, a Codex CLI session log reserialises the same window asresets_at.…-<5h|7d>-surpassed-threshold. The defaults, 0.9 for the session window and 0.75 for the weekly, are the points Anthropic's own windows warn at.CCP_CODEX_QUOTA_WARN_ATlowers both for a consumer that wants the figure earlier.Testing
Verified live against a Codex subscription. The headers above came off a real response, and a client parsed them back into
status='allowed'with the window and its reset time. With the threshold lowered so a warning is reachable at a real 4% spend, the same path producedstatus='allowed_warning',rate_limit_type='five_hour',utilization=0.04and the reset time.Nine unit tests cover the recorded payload shape, window attribution, threshold behaviour, the rollover drop, and the refusal precedence.
cargo fmt --check,cargo clippy --all-targetsandcargo testare clean (1041 tests).