Skip to content

docs(providers): say where transientRetryOn5xx does not apply - #4894

Merged
lidge-jun merged 1 commit into
devfrom
codex/docs-transient-retry-passthrough-scope-20260917
Sep 17, 2026
Merged

lidge-jun merged 1 commit into
devfrom
codex/docs-transient-retry-passthrough-scope-20260917

Conversation

@lidge-jun

Copy link
Copy Markdown
Owner

Summary

The transientRetryOn5xx reference entry opens with "Key-auth openai-chat providers only", and an operator reasonably reads that as "every other adapter gets no transient retry". That is not what happens, and the gap sent at least one contributor after the wrong fix.

A provider whose adapter is openai-responses never reaches transientRetryPolicyFor. createResponsesPassthroughAdapter declares passthrough: true as const (src/adapters/openai-responses/passthrough.ts:190-193), and src/server/responses/core.ts:116 returns into executePassthroughResponse on exactly that flag, before the adapter dispatch path is constructed. That lane then applies its own transient ladder from a fixed constant (src/server/responses/passthrough-dispatch.ts:760, TRANSIENT_RETRY_MAX_ATTEMPTS at src/lib/upstream-retry.ts:106).

So both halves of the current sentence mislead. The option looks broader than it is, and the lane it does not cover looks quieter than it is. This adds one sentence naming that boundary, in the English source and each of the seven translations, so no locale contradicts another.

The underlying defect — that a provider policy cannot reach the passthrough lane at all — is tracked separately in issue #4893 and is not addressed here.

Verification

  • The claim was read out of the source rather than inferred: transientRetryPolicyFor has exactly four call sites in src/, and three of them (adapter-dispatch.ts:305, adapter-continuation.ts:207 and :411) sit past the early return in core.ts:116. The fourth, chat-native.ts:301, serves /v1/chat/completions and is unaffected by this wording.
  • src/adapters/openai-chat.ts declares no passthrough flag, so the existing sentence stays correct for that adapter.
  • Documentation only: the change set is eight docs-site markdown files, one line each. No runtime, test, script, workflow or structure/ path is touched, so the ownership gate has nothing to bind and the file-size ratchet has no source file to measure.
  • Cross-platform CI at the exact head is the evidence of record; its changes job scopes the expensive legs out for a docs-only diff and still publishes the aggregate check.

Checklist

  • Scope stays focused and avoids unrelated cleanup. Only the sentence that was wrong changed; the rest of each cell, including wording that already drifted between locales, is left alone.
  • Docs or release notes were updated when needed. This PR is the documentation change.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults. No credential, token, workflow or release path is touched.

The reference entry opens with "Key-auth openai-chat providers only",
which an operator reasonably reads as "every other adapter gets no
transient retry". That is not what happens.

A provider whose adapter is openai-responses never reaches
transientRetryPolicyFor at all. createResponsesPassthroughAdapter
declares passthrough: true, and core.ts returns into
executePassthroughResponse on that flag before the adapter dispatch
path is built. The passthrough lane then applies its own transient
ladder from a fixed constant, so such a provider gets replay the
setting can neither enable nor tune.

Both halves of that mismatch mislead: the option looks broader than it
is, and the untouched lane looks quieter than it is. One sentence in
each locale states the boundary.

Documentation only. No runtime behaviour changes.
@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner September 17, 2026 09:08
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 17, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-17T09:10:57.704341Z dc41176 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Next included review available in 38 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 48f876bf-8a69-4103-a7e4-5d2f0332e01c

📥 Commits

Reviewing files that changed from the base of the PR and between a1fe84b and dc41176.

📒 Files selected for processing (8)
  • docs-site/src/content/docs/fr/reference/configuration/providers.md
  • docs-site/src/content/docs/ja/reference/configuration/providers.md
  • docs-site/src/content/docs/ko/reference/configuration/providers.md
  • docs-site/src/content/docs/reference/configuration/providers.md
  • docs-site/src/content/docs/ru/reference/configuration/providers.md
  • docs-site/src/content/docs/tr/reference/configuration/providers.md
  • docs-site/src/content/docs/zh-cn/reference/configuration/providers.md
  • docs-site/src/content/docs/zh-tw/reference/configuration/providers.md

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@lidge-jun

Copy link
Copy Markdown
Owner Author

리뷰 · 우선순위 76 / 80

이 PR은 문서만 고친다. 고치는 곳은 docs-site의 providers 설정 표 한 칸, transientRetryOn5xx 설명이다. 영어 원문과 fr/ja/ko/ru/tr/zh-cn/zh-tw 일곱 번역까지, 파일 여덟 개에 같은 뜻의 문장 한 줄을 넣는다. 런타임·테스트·워크플로·structure/는 건드리지 않는다. 현재 dev HEAD는 a1fe84b31(패키지 2.58.0, tip #4880 — L4 Responses private-field/history-repair 플랜; 바로 아래는 #4879 L6 계약·품질 플랜과 #4882 L7 native-control 감사)이다. 이번 wake에서 dev SHA는 그대로다.

왜 고치느냐면, 지금 문장이 두 쪽으로 사람을 속이기 때문이다. 표는 "키 인증 openai-chat 전용"이라고만 열어 둔다. 운영자는 "그럼 다른 어댑터는 5xx 재시도가 없다"고 읽기 쉽다. 실제로는 adapteropenai-responses인 프로바이더는 Responses 패스스루 레인으로 빠지고, 그 레인은 프로바이더 정책이 아니라 고정 상수로 일시 재시도를 돌린다. 옵션이 안 먹는 레인에도 재시도는 있다. 반대로 옵션 이름을 보고 "여기다 attempts: 5를 넣으면 패스스루도 바뀌겠지"라고 생각하면, 그것도 틀리다. 이슈 #4893이 그 기대 불일치를 추적한다. 이 PR은 코드 결함을 고치지 않고, 문서가 그 경계를 먼저 말하게 한다.

근거는 현재 dev 트리에서 그대로 읽힌다. createResponsesPassthroughAdapter(src/adapters/openai-responses/passthrough.ts L190–193)는 passthrough: true as const를 붙인다. src/server/responses/core.ts는 어댑터 디스패치를 만들기 전에 passthrough 플래그를 보고 executePassthroughResponse로 일찍 돌아간다(현재 tip 기준 L122–131 근처; PR 본문이 적은 L116은 줄 번호만 살짝 밀린 것이다). 패스스루 레인은 src/server/responses/passthrough-dispatch.ts에서 TRANSIENT_RETRY_MAX_ATTEMPTS(src/lib/upstream-retry.ts L106, 값 3)로 사다리를 쓴다. transientRetryPolicyFor 호출 네 곳은 adapter-dispatch.ts(L305·L460·L781), adapter-continuation.ts(L207·L411), chat-native.ts(L301)인데, Responses 경로에서 앞 둘은 그 early return 뒤에만 있다. 게다가 transientRetryPolicyFor 자체도 provider.adapter !== "openai-chat"이면 null을 돌려(src/providers/key-failover.ts L169–175 근처) 정책이 패스스루에 닿을 길이 없다. openai-chat 어댑터에는 passthrough가 없으므로, 기존 "키 인증 openai-chat 전용" 문장은 그 레인에선 그대로 맞다.

추가된 문장은 그 경계를 한 줄로 못 박는다. 영어: 어댑터가 openai-responses이면 Responses 패스스루로 가고, 그 경로는 고정 일시 재시도 사다리를 쓰며 이 옵션을 읽지 않는다. 일곱 로케일도 같은 사실을 말한다. 로케일마다 표 칸이 이미 조금씩 달랐던 부분(영문이 429/계정 복구 재조회를 덜 적는 등)은 일부러 건드리지 않았다. 잘못된 한 문장만 고치고, 번역 드리프트를 이 PR에서 정리하지 않은 선택은 범위 통제로 맞다. types.ts/config.ts 분할 캠페인과도 무관하고, preview deploy도 이 레인의 일이 아니다.

호스트 CI는 지금 exact-head(dc41176)에서 changes/hygiene/label 등이 queued다. 문서 전용 diff라 비싼 다리는 보통 스코프 아웃되고 aggregate만 남는다. 초록을 보고 랜딩하면 된다. 코드 수정은 #4893에 남겨 두는 분리가 맞다. 문서가 먼저 진실을 말하면, 기여자가 잘못된 설정 고침으로 새 PR을 여는 일을 줄일 수 있다.

docs-site/.../providers.md transientRetryOn5xx 칸 - 여덟 로케일 모두 "openai-responses는 패스스루 고정 사다리, 이 옵션 미사용" 한 줄을 앞에 붙인다. 영어 원문과 번역이 같은 경계를 가리킨다.
경로 src/adapters/openai-responses/passthrough.ts L190–193 - passthrough: true 선언이 dev에 있다. 문서 주장의 출발점이다.
경로 src/server/responses/core.ts L122–131 - 패스스루 early return이 dev에 있다. PR 본문 L116은 줄 번호 드리프트일 뿐 동작 설명은 맞다.
경로 src/providers/key-failover.ts transientRetryPolicyFor - adapter !== "openai-chat"이면 null. 문서가 말하는 "옵션이 안 먹음"과 정책 함수 게이트가 이중으로 맞물린다.
경로 src/lib/upstream-retry.ts L106 / passthrough-dispatch.ts - 패스스루는 TRANSIENT_RETRY_MAX_ATTEMPTS(3) 고정. "옵션 밖 레인이 조용하다"는 오해를 문서가 바로잡는다.

메인테이너의 판단이 필요한 지점

  • 이 문서 랜딩을 Provider transientRetryOn5xx never reaches the Responses passthrough lane #4893 코드 픽스보다 먼저 할지. 문서 먼저면 운영자 오해가 즉시 줄고, 코드 픽스는 별도 유닛으로 남긴다(PR 본문 의도).
  • 영문 칸이 다른 로케일보다 짧게 남은 기존 드리프트(429/계정 복구 재조회 등)를 후속 문서 PR로 맞출지, 당분간 방치할지.
  • #4893에서 패스스루가 프로바이더 transientRetryOn5xx를 읽게 할지, 아니면 패스스루 전용 설정/상수를 문서화만 하고 정책 키는 openai-chat 전용으로 둘지.

너의 추천
KEEP — 문서 전용·소스 근거가 dev에서 확인됨·#4893과 범위가 잘 갈라져 있다. exact-head CI 초록이면 머지. types/config 분할에 무효화되지 않으므로 닫지 말고 랜딩한다. 코드 동작 변경은 #4893에서만 다룬다.

이 댓글은 grok-bot이 작성했습니다

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dc41176fee

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

| `webSearchBridge?` | `{ enabled?: boolean; backend?: "ollama" \| "openai" \| "anthropic" \| "xai" \| "gemini" \| "exa"; maxSearches?: number; timeoutMs?: number; endpoint?: string }` | Key-auth `openai-responses` passthrough providers only. Off by default. Codex always declares the hosted `web_search` tool, and the passthrough relays it on the assumption the destination executes it. A gateway that does not run hosted search answers with a `function_call` named `web_search` that nothing runs, and the undeclared-tool guard ends the turn. With `enabled: true` and an explicit `backend` OpenCodex intercepts that call, runs the search itself, feeds the result back to the same upstream, and shows Codex a hosted `web_search_call` cell. Never armed for `authMode: "forward"` (ChatGPT already searches) or for a provider that executes hosted search upstream. `backend` is required; there is no implicit default and a missing credential for the named backend leaves the bridge disarmed rather than falling through to another paid search. `ollama` reuses this provider's own API key on `POST <origin>/api/web_search`, so the origin must be `https://ollama.com` unless the operator names `endpoint` explicitly. `openai` / `anthropic` / `xai` / `gemini` / `exa` reuse the matching sidecar executor and that executor's own credential (`webSearchSidecar.exaApiKey` for Exa). The search model comes from `webSearchSidecar.model` only when `webSearchSidecar.backend` resolves to the same backend this bridge names; otherwise the bridge runs that backend's own default, because a model chosen for one vendor is rejected by another. An unset `webSearchSidecar.backend` resolves to `openai`, so an unset-backend model reaches an `openai` bridge and no other. There is no per-provider bridge model override. Streaming turns only. A turn that mixes `web_search` with another client tool call still fails closed rather than dropping the client's call. Assistant text such as XML-like `<web_search>` prose is not executed. Defaults: `maxSearches: 3` (1..10), `timeoutMs: 60000` (1000..600000). |
| `retryOn429?` | `{ enabled?: boolean; attempts?: number; intervalMs?: number; maxIntervalMs?: number; respectRetryAfter?: boolean }` | API-key providers only (`authMode: "key"`). Opt-in same-target 429 retry: when `retryOn429` is absent the feature is off; object presence enables it unless `enabled: false`. On 429 the proxy waits (upstream `Retry-After` or the fixed interval) and replays the identical request on the same key before any key failover — across the main text-turn recovery loop, the Responses passthrough wire, the image/video bridge, the web-search sidecar, and terminal continuations. Only pre-stream HTTP 429 responses are eligible for replay; custom `runTurn` transports are outside the HTTP retry loop. `attempts` counts same-key replays after the first 429 (total sends = `attempts` + 1) and is one request-wide budget shared by the main recovery loop, the terminal-guard continuation, and bridge retries. Exhausting `attempts` only stops further same-key replays: normal key failover or final-error handling then applies per the available targets — on the key-auth passthrough wire there is no failover, so the exhausted 429 surfaces as-is. Codex itself never retries 429, so this is the only defense for single-key providers. Defaults: `enabled: true`, `attempts: 3`, `intervalMs: 5000`, `maxIntervalMs: 60000` (any single wait is capped at `maxIntervalMs`, itself capped at 600000), `respectRetryAfter: true`. |
| `transientRetryOn5xx?` | `{ enabled?: boolean; attempts?: number }` | Key-auth `openai-chat` providers only. Opt-in retry for pre-stream transient upstream statuses (500, 502, 503, 504, 520, 521, 522): absent means off, object presence enables it unless `enabled: false`. Covers the initial Responses request, the terminal-guard continuation, and native `/v1/chat/completions`. `attempts` is the TOTAL number of upstream sends allowed for one request including the first (1..10, default 3) — it is one budget shared with connection-reset recovery, so `3` means at most three real requests reach the provider. Waits use a fixed 400 ms exponential backoff capped at 5 s and honor `Retry-After`. Separate from `retryOn429`, which handles rate limiting; mid-stream failures are never replayed. |
| `transientRetryOn5xx?` | `{ enabled?: boolean; attempts?: number }` | Key-auth `openai-chat` providers only — a provider whose `adapter` is `openai-responses` goes through the Responses passthrough path instead, which applies its own fixed transient ladder and never reads this option. Opt-in retry for pre-stream transient upstream statuses (500, 502, 503, 504, 520, 521, 522): absent means off, object presence enables it unless `enabled: false`. Covers the initial Responses request, the terminal-guard continuation, and native `/v1/chat/completions`. `attempts` is the TOTAL number of upstream sends allowed for one request including the first (1..10, default 3) — it is one budget shared with connection-reset recovery, so `3` means at most three real requests reach the provider. Waits use a fixed 400 ms exponential backoff capped at 5 s and honor `Retry-After`. Separate from `retryOn429`, which handles rate limiting; mid-stream failures are never replayed. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Describe retries by the effective per-model adapter

For mixed-wire providers, modelAdapters and registry defaults are resolved before dispatch, so a provider configured with adapter: "openai-chat" can still use the Responses passthrough path for a specific model, while an openai-responses provider can resolve a model to Chat. The new wording keys the retry boundary only to the provider-level adapter, which can therefore mislead operators about whether transientRetryOn5xx.attempts controls a selected model; describe this in terms of the effective adapter after per-model resolution and update the translations consistently.

AGENTS.md reference: docs-site/AGENTS.md:L8-L10

Useful? React with 👍 / 👎.

@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Sep 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@lidge-jun
lidge-jun merged commit 09f0421 into dev Sep 17, 2026
19 checks passed
@lidge-jun
lidge-jun deleted the codex/docs-transient-retry-passthrough-scope-20260917 branch September 17, 2026 09:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant