Repository navigation
fix(responses): rotate a pooled API key on a native passthrough 429 - #7323
vadymhimself wants to merge 1 commit into
Conversation
The native Responses passthrough returns before the adapter recovery loop that rotates pooled keys, so a key-pool provider's 429 was returned to the client while the same refusal rotates on the adapter and chat-native wires. Rotate to the next key before output, inside the shared send budget. Distributed round-robin selection keeps its cool-without-replay behaviour. Co-Authored-By: Claude Code <noreply@anthropic.com>
|
✅ Deterministic PR hygiene checks passed. |
⏳ DRAFT
What to do
Review readiness checklist
0/4 boxes ticked. This PR stays in draft until every box above is ticked. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Merge Risk: ⚪ Minimal · up to
|
|
Intake/scoped review at The native passthrough 429 branch uses the existing key-pool selector, excludes distributed selection and synthetic non-replayable replies, then rebinds replay ownership before a bounded rebuild. Preserve attempt identity and the exhausted-budget control without cooling a key for a local refusal. Credential/failover review remains required; keep Draft. Current-head functional workflows are awaiting fork approval; that is pending execution, not a passing test result. No local suite was run for this branch in this intake. No workflow approval, new scan, live configuration change or merge was performed. Required review/readiness gates remain in force. |
Summary
apiKeyPoolentries, active-key selection) therefore returned a 429 to the client on this wire, and kept using the same key on the next request, while the identical refusal rotates to the next key on the adapter dispatch, continuation and native Chat paths.rotatePassthroughKeyOn429(src/server/responses/passthrough-key-rotation.ts) adds the missing arm after the same-keyretryOn429loop and before any output: it rotates throughrotateProviderTransportOn429(which records the cooldown), rebinds the reasoning-replay scope, and refetches through the existingrebuildAndRefetch("key-429"), then re-enters thepassthroughRecoveryloop like the other arms.Retry-After; distributed (round-robin) selections keep the existing cool-without-replay behaviour from feat(providers): carry opt-in API key round-robin and per-key pacing (#6937) #7135 unchanged.passthrough-dispatch.tssits 4 lines under the file-size threshold; the dispatch file grows by 3 lines. The module is registered intests/helpers/responses-core-source.ts, and thehasKeyPoolFailoverrecovery-site contract intests/oauth/generic-oauth-failover.test.tsmoves from 7 to 8 with the new site named.Verification
native Responses rotates a non-distributed key pool on 429 before outputintests/responses/responses-native-key-cooldown.test.ts, run before the src change:bun test tests/responses/responses-native-key-cooldown.test.ts-> 17 pass, 1 fail (Expected: 200, Received: 429). After the change: 18 pass, 0 fail. The test also asserts the second send carries the second key and the first key is cooling.native Responses cools genuine distributed 429 without replay, synthetic-refusal and opt-out cases) pass unchanged.bun test tests/oauth/generic-oauth-failover.test.ts tests/responses/responses-core-modules.test.ts tests/ci-workflows/structure-ssot.test.ts-> pass.bun x tsc --noEmit-> exit 0.bun scripts/file-size-ratchet.ts-> passed (passthrough-dispatch.ts1999 lines).bun run test:changed(Bun 1.4.3 viaOCX_TEST_RUNNER_BUN) -> 15927 pass, 34 skip, 2 fail across 637 files. One failure was the rotator-count contract above, fixed in this PR (67 pass after). The other,tests/cli/cli-connect-readiness.test.ts"a rejected preferred runtime falls back without rewriting the saved selection", also fails on an unmodifiedupstream/devcheckout on this machine (local-environment dependent) and is unrelated.bun run testwas not run locally; the remainder is left to CI.Checklist
structure/transports/responses-failover.md.)Source: carried from the vadymhimself fork build (passthrough hunk of commit 8fb1bbb), re-authored against the current
passthroughRecoveryloop and limited to non-distributed pools so #7135's distributed contract is untouched.🤖 Generated with Claude Code
Review readiness checklist
This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:
Required local validation passed; commands, results, and any full-suite exception are documented.
I pushed my PR to a recent dev commit (at most 10 behind; a maintainer may still ask for the exact tip before merge).
I resolved all correct Codex and CodeRabbit findings.
My PR is ready for review.
Summary by CodeRabbit
New Features
Tests