Skip to content

fix(responses): preserve caller User-Agent - #4702

Merged
lidge-jun merged 1 commit into
devfrom
ingw/fix-responses-caller-user-agent
Sep 15, 2026
Merged

lidge-jun merged 1 commit into
devfrom
ingw/fix-responses-caller-user-agent

Conversation

@Ingwannu

@Ingwannu Ingwannu commented Sep 15, 2026

Copy link
Copy Markdown
Owner

Summary

  • preserve the incoming client User-Agent as a narrow fallback in both key-auth and canonical-forward Responses routes
  • keep any provider-configured User-Agent authoritative, including mixed-case header names
  • leave a missing caller value absent and do not widen forwarding for credentials or any other caller header
  • document the compatibility boundary in the transport structure and public adapter reference

Why

Some Responses-compatible providers, including Ark-backed compatibility paths, use the Codex client fingerprint to select Codex-specific behavior. The adapter currently rebuilds its upstream headers and drops the caller User-Agent, so those providers can choose a generic path even though the request came from Codex.

Validation

  • bun test tests/codex-integration/codex-metadata-integrity.test.ts — 24 passed
  • bun run typecheck — passed
  • bun run structure:check — passed
  • bun run privacy:scan — passed
  • cd docs-site && bun run build — passed, 441 pages
  • git diff --check — passed

All tests used isolated temporary HOME, OPENCODEX_HOME, and CODEX_HOME values. No local runtime configuration was read or written.

No Go counterpart exists for this TypeScript Responses adapter change on the currently published integration branches.

Closes #4699

Summary by CodeRabbit

  • Enhancements
    • The OpenAI Responses adapter now preserves a caller-provided User-Agent when no provider value is configured.
    • Configured provider User-Agent values take precedence, regardless of header capitalization.
    • No User-Agent is added when the caller does not provide one; other caller headers remain unaffected.
  • Documentation
    • Updated adapter and transport documentation to describe the revised User-Agent handling.

@Ingwannu
Ingwannu requested a review from lidge-jun as a code owner September 15, 2026 09:27
@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@coderabbitai

coderabbitai Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 5aaadfac-ec64-4628-b4a6-19524035fb06

📥 Commits

Reviewing files that changed from the base of the PR and between 51d577c and b5953b7.

📒 Files selected for processing (4)
  • docs-site/src/content/docs/reference/adapters.md
  • src/adapters/openai-responses/passthrough.ts
  • structure/transports/responses.md
  • tests/codex-integration/codex-metadata-integrity.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 3 remain after this review.


📝 Walkthrough

Walkthrough

The Responses adapter now preserves the caller’s User-Agent in key and forward modes when no provider value exists. Provider values remain authoritative case-insensitively. Tests verify fallback, override, omission, and upstream delivery.

Changes

Responses User-Agent Preservation

Layer / File(s) Summary
User-Agent fallback implementation
src/adapters/openai-responses/passthrough.ts, structure/transports/responses.md
buildRequest preserves the caller’s User-Agent when provider headers do not define one. Provider values take case-insensitive precedence, and other caller headers are not forwarded.
Fallback validation and documentation
tests/codex-integration/codex-metadata-integrity.test.ts, docs-site/src/content/docs/reference/adapters.md
Tests cover key and forward modes, configured overrides, missing values, duplicate prevention, and delivery to an HTTP upstream. The adapter documentation describes these rules.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~15 minutes

Change: Bug fix · Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to b5953

The adapter change preserves the intended User-Agent fallback behavior without identified merge-blocking risk.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 2 files. (2 skipped: 2… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the main change: preserving the caller's User-Agent in the Responses adapter. This matches the documented behavior, implementation, and tests.
Linked Issues check ✅ Passed Issue #4699 has coding requirements, and the reviewed head satisfies them. In src/adapters/openai-responses/passthrough.ts, applyCallerUserAgentFallback checks provider headers case-insensitively,…
Out of Scope Changes check ✅ Passed The listed changes stay within Issue #4699. The implementation change is limited to the Responses adapter fallback. The added integration tests validate the requested forwarding, precedence, absence, …
Full details: Docstring Coverage

Explanation

Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 2 files. (2 skipped: 2 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ingw/fix-responses-caller-user-agent

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

리뷰 · 우선순위 74 / 80

이 PR은 이슈 #4699를 고친다. Codex CLI가 OpenCodex를 거쳐 Responses 호환 게이트웨이(보고 사례는 Volcengine Ark/화산방주)로 나갈 때, 어댑터가 업스트림 헤더를 새로 만들면서호출자 User-Agent를 버린다. 그러면 Bun fetch가 기본값 Bun/<version>을 넣을 수 있고, UA로 Codex 호환 경로를 고르는 공급자는일반 경로로 떨어져 요청이 실패할 수 있다. 지금 dev HEAD는 51d577c3f(#4700, 패키지 2.57.0)이고, 이슈 본문이 가리킨 cc182a405 이후에도 src/adapters/openai-responses/passthrough.tsbuildRequest는 같은 구조다. key 모드는 Content-Type·Bearer·provider.headers만 넣고, forward 모드는 좁은 FORWARD_HEADERS 허용 목록만 복사한다. 그 목록에도 user-agent는 없다. 닫힌 #1751은 OpenCodex 전용 UA를 새로 만들자는 제안이었고 거절됐다. 이번 PR은 제품 정체성을 새로 찍지 않고, 이미 들어온 호출자 지문을 그대로 남기는 쪽이라 Decision Log와 맞다.

고치는 방법은 좁다. applyCallerUserAgentFallback 한 함수를 추가하고, key/forward 헤더 조립이 끝난 뒤(라인 237) 한 번만 호출한다. 이미 헤더 맵에 대소문자만 다른 user-agent 키가 있으면 아무 것도 하지 않는다(설정된 provider.headers가 이긴다). 없으면 incoming.headers.get("user-agent")를 읽어 값이 있을 때만 User-Agent로 넣는다. 호출자가 안 보냈으면 어댑터 경계에서 비워 둔다. 다른 호출자 헤더·자격 증명은 넓히지 않는다. FORWARD_HEADERS 목록 자체는 그대로라, 이건 allowlist 확장이 아니라 단일 non-credential fallback이다. structure/transports/responses.mddocs-site/.../reference/adapters.md에 그 경계를 한 단락씩 적어 두었다. 베이스는 현재 dev exact tip 51d577c3f이고 MERGEABLE이다. types.ts/config.ts 스플릿이나 고드파일 모놀리스 경로를 건드리지 않으므로 close-don't-rebase 대상이 아니다. 이미 쪼개진 openai-responses/passthrough.ts leaf만 수정한다.

테스트는 tests/codex-integration/codex-metadata-integrity.test.ts에 세 덩어리를 넣었다. (1) key와 forward 둘 다 호출자 UA를 보존한다. (2) 설정 헤더 uSeR-aGeNt가 호출자 값보다 이기고, 키가 하나만 남으며, 호출자 UA가 없으면 어댑터 결과에 UA가 없다. (3) 로컬 Bun.serve 수신기로 실제 HTTP에 실린 UA가 codex_cli_rs/receiver-proof인지 확인한다. PR 본문 기준 exact-head에서 metadata 테스트 24·typecheck·structure·privacy· docs build(441)·diff check가 통과했다고 적혀 있다. 호스티드 CI는 이 웨이크 시점 대부분 pending(hygiene/label/changes/resolve-pr 등은 이미 pass). Ark 실계정 재현은 이슈에도 없고 PR에도 없다 — 로컬 수신기 증명으로 계약을 고정한 형태다. Go 대응 패치는 없다고 명시했다.

라인 68-74 applyCallerUserAgentFallback - 대소문자 무시로 기존 UA 키를 보고, 있을 때만 복사. 의도한 좁은 fallback이다.
라인 74 if (userAgent) - 빈 문자열 UA는 falsy라 어댑터에 안 실린다. 그 경우 Bun 기본 UA가 다시 붙을 수 있다. 실제 Codex 클라이언트는 보통 비어 있지 않으므로 드물지만, “없으면 발명하지 않는다”와 “빈 값도 그대로 보낸다”는 조금 다르다.
라인 237 호출 위치 - key/forward 분기 공통 직후라 provider.headers Object.assign 이후다. 설정 UA가 이기고, forward의 FORWARD_HEADERS 복사와도 겹치지 않는다. 좋다.
FORWARD_HEADERS - UA를 목록에 넣지 않은 선택은 맞다. 사이드카가 같은 allowlist만 재사용할 때 자격 증명 확대를 막는다. 다만 ChatGPT forward 경로의 다른 헤더 조립(예: WS 준비)이 별도로 UA를 다루는지와는 이번 HTTP buildRequest 범위 밖이다.
테스트 수신기 증명 - buildRequest 헤더만이 아니라 fetch 후 업스트림이 본 값을 검증한다. #4699 재현 핵심(Bun 기본값 대체)을 직접 막는다.
호스티드 CI - exact-head b5953b7cc 게이트가 아직 pending. 머지 전 초록 확인이 필요하다.

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

너의 추천
호스티드 CI가 exact-head b5953b7cc에서 초록이면 dev에 머지한다. #4699는 Closes로 같이 닫힌다. FORWARD_HEADERS에 UA를 넣거나 임의 헤더 포워딩을 넓히지 말 것. 빈 문자열 UA 처리는 follow-up으로도 충분하다(우선순위 낮음). WS/프록시 UA는 이번 PR 범위를 넘기면 새 이슈로 분리한다. #4694 promote에는 넣지 않는다(별도 체리픽 요청이 없을 때). close-don't-rebase·중복 닫기 대상 아님. 프리뷰 배포는 계획에 없음.

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

@lidge-jun
lidge-jun merged commit 45cfb04 into dev Sep 15, 2026
31 checks passed
@lidge-jun
lidge-jun deleted the ingw/fix-responses-caller-user-agent branch September 15, 2026 11:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants