feat(codex): classify reset-eligible quota rejection - #866
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughCodex pre-stream responses now receive strict structured rejection classification. Pool-account retry handling uses the asynchronous result and abort signal. Tests cover quota schemas, status categories, malformed bodies, cancellation, and response preservation. ChangesCodex quota retry handling
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
@codex review |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Pre-merge review result: not merge-ready yet. CI is green and the bounded body handling, privacy posture, and Bun compatibility all check out — but the classifier does not hold the fail-closed boundary the PR description promises:
Please: exact-match allowlisted values within explicitly supported response schemas, reject on conflict, and add the negative tests. This is the semantic foundation for the #657 recovery family, so it is worth getting airtight — happy to re-review quickly once updated. |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/server/responses/core.ts`:
- Around line 250-255: Update shouldRetryCodexPoolAccountQuota to be synchronous
and return true only when response.status is 402 or 429, avoiding
classifyCodexPreStreamRejection and any response-body read. Remove the
now-unused classifier import while preserving the existing boolean retry
contract.
In `@tests/codex-quota-rejection.test.ts`:
- Around line 12-13: Extend the test suite in “Codex pre-stream quota rejection
classification” with handleResponses integration coverage for Codex pool
retries. Exercise the reset-eligible 429 and 402 paths in handleResponses,
asserting each retries on an alternate account, and add a non-retryable-status
case asserting the original status and response body are preserved.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 3d172e90-de04-4759-a458-eb24d70ac61a
📒 Files selected for processing (3)
src/codex/quota-rejection.tssrc/server/responses/core.tstests/codex-quota-rejection.test.ts
| async function shouldRetryCodexPoolAccountQuota( | ||
| response: Response, | ||
| signal?: AbortSignal, | ||
| ): Promise<boolean> { | ||
| const rejection = await classifyCodexPreStreamRejection(response, { signal }); | ||
| return rejection.alternateRetryEligible; |
There was a problem hiding this comment.
🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Check the bounded-body timeout magnitude and confirm no other unawaited call site.
rg -n 'BOUNDED_BODY_TIMEOUT_MS\s*=' src/lib/bounded-body.ts
rg -nP '\bshouldRetryCodexPoolAccountQuota\s*\(' src/server/responses/core.tsRepository: lidge-jun/opencodex
Length of output: 361
🏁 Script executed:
#!/bin/bash
set -e
printf '%s\n' '--- quota-rejection symbols ---'
ast-grep outline src/codex/quota-rejection.ts
printf '%s\n' '--- quota-rejection implementation ---'
sed -n '1,190p' src/codex/quota-rejection.ts
printf '%s\n' '--- response helper and call site ---'
sed -n '220,275p' src/server/responses/core.ts
sed -n '1585,1665p' src/server/responses/core.ts
printf '%s\n' '--- bounded body helper ---'
ast-grep outline src/lib/bounded-body.ts
sed -n '1,180p' src/lib/bounded-body.ts
printf '%s\n' '--- related call sites and tests ---'
rg -n 'classifyCodexPreStreamRejection|alternateRetryEligible|resetCreditEligible|semanticCode|shouldRetryCodexPoolAccountQuota' src test tests 2>/dev/null || trueRepository: lidge-jun/opencodex
Length of output: 22739
🏁 Script executed:
#!/bin/bash
set -e
python3 - <<'PY'
from pathlib import Path
import re
quota = Path("src/codex/quota-rejection.ts").read_text()
core = Path("src/server/responses/core.ts").read_text()
bounded = Path("src/lib/bounded-body.ts").read_text()
assert "const semanticCode = await resetEligibleCodeFromResponse(response, options.signal);" in quota
assert re.search(
r'if \(semanticCode\).*?alternateRetryEligible: true',
quota,
re.S,
)
assert re.search(
r'status === 429 \? "generic-rate-limit" : "unverified-billing-or-quota".*?'
r'\{ alternateRetryEligible: true \}',
quota,
re.S,
)
def classifier_retry(status: int) -> bool:
return status in (402, 429)
def proposed_retry(status: int) -> bool:
return status == 429 or status == 402
statuses = [200, 400, 401, 402, 403, 429, 500, 503]
mismatches = [(s, classifier_retry(s), proposed_retry(s))
for s in statuses if classifier_retry(s) != proposed_retry(s)]
assert not mismatches, mismatches
assert "response.clone()" in quota
assert "BOUNDED_BODY_TIMEOUT_MS = 5_000" in bounded
assert len(re.findall(r'\bshouldRetryCodexPoolAccountQuota\s*\(', core)) == 2
print("status-only decision matches classifier for:", statuses)
print("classifier reads response.clone() for 402/429 only")
print("bounded body default timeout: 5000 ms")
print("helper declaration plus one call site found")
PY
printf '%s\n' '--- import usage ---'
rg -n -F 'classifyCodexPreStreamRejection' src/server/responses/core.ts src
printf '%s\n' '--- bounded body cleanup ---'
sed -n '120,230p' src/lib/bounded-body.tsRepository: lidge-jun/opencodex
Length of output: 3216
🏁 Script executed:
#!/bin/bash
set -e
python3 - <<'PY'
from pathlib import Path
import re
quota = Path("src/codex/quota-rejection.ts").read_text()
core = Path("src/server/responses/core.ts").read_text()
bounded = Path("src/lib/bounded-body.ts").read_text()
assert "const semanticCode = await resetEligibleCodeFromResponse(response, options.signal);" in quota
assert re.search(r'if \(semanticCode\).*?alternateRetryEligible: true', quota, re.S)
assert re.search(
r'status === 429 \? "generic-rate-limit" : "unverified-billing-or-quota".*?'
r'\{ alternateRetryEligible: true \}',
quota,
re.S,
)
def classifier_retry(status: int) -> bool:
return status in (402, 429)
def proposed_retry(status: int) -> bool:
return status == 429 or status == 402
statuses = [200, 400, 401, 402, 403, 429, 500, 503]
mismatches = [(s, classifier_retry(s), proposed_retry(s))
for s in statuses if classifier_retry(s) != proposed_retry(s)]
assert not mismatches, mismatches
assert "response.clone()" in quota
assert "BOUNDED_BODY_TIMEOUT_MS = 5_000" in bounded
assert len(re.findall(r'\bshouldRetryCodexPoolAccountQuota\s*\(', core)) == 2
print("status-only decision matches classifier for:", statuses)
print("classifier reads response.clone() for 402/429 only")
print("bounded body default timeout: 5000 ms")
print("helper declaration plus one call site found")
PY
printf '%s\n' '--- import usage ---'
rg -n -F 'classifyCodexPreStreamRejection' src/server/responses/core.ts src
printf '%s\n' '--- bounded body cleanup ---'
sed -n '120,230p' src/lib/bounded-body.tsRepository: lidge-jun/opencodex
Length of output: 3216
Remove the body read from the pool-account retry decision.
classifyCodexPreStreamRejection reads response.clone() for 402 and 429, but both branches always set alternateRetryEligible: true. This can delay failover by up to 5,000 ms. Make shouldRetryCodexPoolAccountQuota synchronous and return response.status === 402 || response.status === 429. Remove the unused classifier import.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/server/responses/core.ts` around lines 250 - 255, Update
shouldRetryCodexPoolAccountQuota to be synchronous and return true only when
response.status is 402 or 429, avoiding classifyCodexPreStreamRejection and any
response-body read. Remove the now-unused classifier import while preserving the
existing boolean retry contract.
| describe("Codex pre-stream quota rejection classification", () => { | ||
| test.each([ |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Check whether an existing test already covers the core.ts pool-retry integration.
rg -ln 'shouldRetryCodexPoolAccountQuota|retryCodexPoolOnAlternateAccount' tests/Repository: lidge-jun/opencodex
Length of output: 157
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- relevant files ---'
git ls-files 'src/server/responses/core.ts' 'tests/*codex*' 'tests/*quota*'
printf '%s\n' '--- changed-file summary ---'
git diff --stat
printf '%s\n' '--- core.ts symbol references ---'
rg -n -C 8 'shouldRetryCodexPoolAccountQuota|retryCodexPoolOnAlternateAccount|classifyCodexPreStreamRejection' src/server/responses/core.ts
printf '%s\n' '--- quota test contents ---'
sed -n '1,240p' tests/codex-quota-rejection.test.ts
printf '%s\n' '--- related test references ---'
rg -n -C 4 'Codex|quota|pool|alternate account|pre-stream' tests/ -g '*.test.ts'Repository: lidge-jun/opencodex
Length of output: 50376
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- changed files ---'
git diff --name-only
printf '%s\n' '--- core.ts diff ---'
git diff -- src/server/responses/core.ts
printf '%s\n' '--- exact integration-symbol references in tests ---'
rg -n 'shouldRetryCodexPoolAccountQuota|retryCodexPoolOnAlternateAccount' tests/ || true
printf '%s\n' '--- quota test ---'
nl -ba tests/codex-quota-rejection.test.ts | sed -n '1,220p'
printf '%s\n' '--- core.ts relevant definitions and call sites ---'
rg -n -C 20 'shouldRetryCodexPoolAccountQuota|retryCodexPoolOnAlternateAccount|classifyCodexPreStreamRejection' src/server/responses/core.tsRepository: lidge-jun/opencodex
Length of output: 8082
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- repository state ---'
git status --short
git log -1 --oneline --stat
printf '%s\n' '--- quota test ---'
sed -n '1,220p' tests/codex-quota-rejection.test.ts
printf '%s\n' '--- core retry implementation ---'
sed -n '230,390p' src/server/responses/core.ts
sed -n '1600,1685p' src/server/responses/core.ts
printf '%s\n' '--- tests that exercise response handling or pool retries indirectly ---'
rg -n -C 5 'handleResponses|handleResponse|poolRetryOutcome|alternate.account|alternateAccount|Codex.*pool|pool.*Codex|retry.*account|account.*retry' tests/ -g '*.test.ts' | head -n 500
printf '%s\n' '--- commit changes for the relevant files ---'
git diff HEAD^ HEAD --stat -- src/server/responses/core.ts tests/codex-quota-rejection.test.ts
git diff HEAD^ HEAD -- src/server/responses/core.ts tests/codex-quota-rejection.test.ts | sed -n '1,260p'Repository: lidge-jun/opencodex
Length of output: 50375
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- commits that introduced the core retry symbols ---'
git log --oneline -8 -- src/server/responses/core.ts
git log --oneline -8 -S'shouldRetryCodexPoolAccountQuota' -- src/server/responses/core.ts
printf '%s\n' '--- candidate integration tests ---'
python3 - <<'PY'
from pathlib import Path
for path in sorted(Path("tests").glob("*.test.ts")):
text = path.read_text()
if "handleResponses" in text and (
"codexAccounts" in text
or "authMode: \"forward\"" in text
or "chatgpt.com/backend-api/codex" in text
):
print(path)
PY
printf '%s\n' '--- focused Codex response tests ---'
rg -l 'handleResponses|chatgpt\.com/backend-api/codex|authMode: "forward"|codexAccounts' tests/ -g '*.test.ts' \
| sort \
| head -n 80
printf '%s\n' '--- relevant test descriptions and setup ---'
rg -n -C 3 'test\(|describe\(|handleResponses|chatgpt\.com/backend-api/codex|authMode: "forward"|codexAccounts' \
tests/server*.test.ts tests/*response*.test.ts tests/*codex*.test.ts 2>/dev/null \
| head -n 800Repository: lidge-jun/opencodex
Length of output: 50375
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- core retry commit ---'
git show --stat --oneline 0b10fe19
git show --format=fuller --no-ext-diff 0b10fe19 -- src/server/responses/core.ts tests/ | sed -n '1,420p'
printf '%s\n' '--- quota-related response tests ---'
rg -n -C 8 'usage_limit_exceeded|insufficient_quota|Retry-After|retry-after|status: 429|status: 402|status: 400|handleResponses|globalThis.fetch' \
tests/chat-completions-endpoint.test.ts \
tests/effort-policy.test.ts \
tests/responses-compaction-routing.test.ts \
tests/server-combo-failover-e2e.test.ts \
tests/subagent-fallback-handle-responses.test.ts \
tests/v2-agent-message-failfast.test.ts \
2>/dev/null || true
printf '%s\n' '--- all test references to the quota semantics ---'
rg -n -C 4 'usage_limit_exceeded|insufficient_quota|reset-eligible|quota rejection|quota.*retry|retry.*quota|alternate.*account' tests/ -g '*.test.ts' || true
printf '%s\n' '--- exact line numbers in core.ts ---'
awk 'NR >= 245 && NR <= 260 || NR >= 1620 && NR <= 1665 { printf "%d:%s\n", NR, $0 }' src/server/responses/core.tsRepository: lidge-jun/opencodex
Length of output: 50376
Add handleResponses integration coverage for Codex pool retries.
tests/codex-quota-rejection.test.ts:12-13 only exercises classifyCodexPreStreamRejection. Add focused tests for src/server/responses/core.ts:250-255 and :1625-1639 that verify a reset-eligible 429 or 402 retries on an alternate account, while a non-retryable status preserves the original status and body.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/codex-quota-rejection.test.ts` around lines 12 - 13, Extend the test
suite in “Codex pre-stream quota rejection classification” with handleResponses
integration coverage for Codex pool retries. Exercise the reset-eligible 429 and
402 paths in handleResponses, asserting each retries on an alternate account,
and add a non-retryable-status case asserting the original status and response
body are preserved.
Source: Path instructions
08949c0 to
aef44bd
Compare
Summary
usage_limit_exceededandinsufficient_quotacodes on HTTP 429/402 as reset-credit eligibleSafety boundary
Explicit non-goals
This PR deliberately does not implement:
Those remain separate follow-up slices under the maintainer direction in #657.
Compatibility
The existing #584 behavior is preserved: pre-stream 429/402 still permits one bounded alternate-account attempt even when the rejection is generic or unverified. This PR only establishes the semantic boundary future irreversible recovery must require.
Verification
1.4.0-canary.1: 69 focused classifier and server-auth tests passed1.3.14: the same 69 tests passedRefs #657
Summary by CodeRabbit