Skip to content

feat(retry): rotate credentials on credential-scoped failures - #8

Merged
yelixir-dev merged 2 commits into
yelixir-dev:mainfrom
A8Cl233395:feat/retry-credential-rotation
Oct 3, 2026
Merged

yelixir-dev merged 2 commits into
yelixir-dev:mainfrom
A8Cl233395:feat/retry-credential-rotation

Conversation

@A8Cl233395

Copy link
Copy Markdown
Contributor

Stacked on #7 — merge that first; this diff shrinks to the last commit once it lands.

Problem

Credential-scoped failures (401/402/403, and the 400 insufficient-credits responses classified by #<PR #1 编号>) cool the key down but the request still failed on the first attempt: shouldRetry(400) was false, so the proxy never rotated to a healthy key even when one was available. The two tunnels were also inconsistent — the provider tunnel retried 403, the alpha tunnel did not.

Changes

  • Unify the retry predicate into a single exported shouldRetryStatus(statusCode, errorMessage) shared by both tunnels (removes the duplicated local copy in provider.ts).
  • Credential-scoped failures (401 / 402 / 403 / 400 + insufficient credits) now cool the key down and rotate to the next key, permanently excluding it for the rest of the request.
  • Provider-wide failures (429 / 5xx / network errors) keep the existing behavior: rotate without cooldown.
  • Client errors (bare 400 / 404 / 422) fail fast — no retry, no cooldown.
  • SSE mid-stream errors get the same message-aware classification before any visible event is emitted.
  • When every credential is exhausted, the request fails with the real upstream error instead of NoAvailableCommandCodeCredentialError.

Tests

  • Rotates to the next key when a 400 reports insufficient credits (alpha tunnel; the failed key ends up in insufficient_credits cooldown, the successful key stays clean).
  • Rotates on 403 (alpha tunnel).
  • Fails fast on a plain 400 — exactly one upstream call, no rotation.
  • Rotates on 400 insufficient credits (provider tunnel).

How tested

vitest run — 299/303 passing; the 4 failures are pre-existing platform-dependent tests (POSIX permission bits, launchctl), unrelated to this change.

…lures

Upstream reports an empty balance as HTTP 400 whose body says 'You have insufficient credits to make this request' instead of the 402 that recordFailure and isFatalCredFailure expect. A bare 400 stays provider-scoped and released without marking, but the same status with an insufficient-credits body is now classified as credential-scoped billing failure, so the key cools down like a 402 instead of staying ready and failing every request. Failure plumbing carries the upstream error text from HTTP responses, stream error events, and caught CommandCodeHttpErrors in both the CommandCode and provider clients. Cover with router and client regression cases for the billing cooldown and the untouched plain-400 path.
@A8Cl233395
A8Cl233395 force-pushed the feat/retry-credential-rotation branch from 8589cd5 to 5f5141a Compare October 2, 2026 17:38
Credential-scoped failures (401/402/403, and 400 responses whose body reports insufficient credits) now fall over to the next key instead of failing the request, while bare client errors such as a plain 400 still fail fast. The retry predicate is unified across the alpha and provider tunnels: the provider path gains insufficient-credit 400 rotation and the alpha path gains 403 rotation.
@yelixir-dev

Copy link
Copy Markdown
Owner

Thanks — rotating to another key on insufficient-credits 400s and 403s, and sharing one retry predicate between the Alpha and Provider paths, closes the gap #7 left.

Verified before merging: #7 + #8 merged cleanly onto current main; typecheck, eslint, Prettier and the full vitest suite (16 files, 303 tests) pass on Linux (the 4 failures you saw are Windows-only and pass here), and CI is green on Node 20/22/24.

Merging as-is. We'll follow up on main with doc updates and release it as 1.74.0.b.

@yelixir-dev
yelixir-dev merged commit 0eea7eb into yelixir-dev:main Oct 3, 2026
3 checks passed
yelixir-dev added a commit that referenced this pull request Oct 3, 2026
Release PR #7 and PR #8: a 400 "insufficient credits" response is
now credential-scoped (cooldown that survives billing refreshes,
matching the CLI's own check), and insufficient-credits 400s and
403s rotate the request to another key on both the Alpha and
Provider paths. Plain 400/404/422 still fail fast.

Update the README routing paragraph (en/ko/zh), KNOW_HOW,
ARCHITECTURE and both deployment guides, and record the release in
PROCESS_LOG.
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