Skip to content

fix(responses): strip Codex-private item metadata at the noncanonical boundary - #3107

Merged
lidge-jun merged 2 commits into
devfrom
codex/3066-strip-codex-private-metadata
Sep 1, 2026
Merged

fix(responses): strip Codex-private item metadata at the noncanonical boundary#3107
lidge-jun merged 2 commits into
devfrom
codex/3066-strip-codex-private-metadata

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Aug 31, 2026

Copy link
Copy Markdown
Owner

Summary

Carries #3066 (author @yanzhibo-bytedance) rebased onto current dev. Both commits are the author's and needed no changes.

Codex ≥0.151 attaches internal_chat_message_metadata_passthrough to Responses input[] items. OpenCodex occupies the built-in openai slot, so that private field reaches whatever destination the request is routed to, and a strict upstream rejects it as an unknown input[*] parameter. The adapter now removes it at the noncanonical boundary, copy-on-write so _rawBody stays caller-owned.

Supersedes #3038, which found the same defect. See below.

Why this one and not #3038

They differ in layer, and the layer is the whole decision.

#3038 strips inside core.ts and compact.ts after readJsonRequestBody, unconditionally — including on the canonical ChatGPT forward path, where the field is not foreign at all. isCanonicalOpenAiForwardProvider exists precisely to mark that destination (src/providers/openai-tiers.ts:34-37).

Its tests are also vacuous: tests/openai-internal-request-metadata.test.ts imports stripOpenAiInternalRequestMetadata and calls it directly. It never drives handleResponses, compact, or an adapter buildRequest, so deleting both production call sites leaves that file green.

#3066 strips inside createResponsesPassthroughAdapter().buildRequest, inside the existing if (!isCanonicalOpenAiForwardProvider(provider)) block, and its tests call that production buildRequest.

Verification

bun test tests/openai-responses-passthrough.test.ts  -> 117 pass / 0 fail / 372 expect()
bun x tsc --noEmit                                   -> exit 0

Two mutations, each restored:

mutation result
remove the strip call site 116 pass / 1 failnoncanonical Responses destinations strip Codex-private item metadata
move the call outside the noncanonical guard 116 pass / 1 failcanonical ChatGPT forward preserves Codex-private item metadata

Two mutations, two different failures: stripping and ChatGPT preservation are guarded independently, which is exactly the property #3038's test layer cannot assert.

Known residual

Official openai-apikey native compact bypasses this adapter, so a strict-validator failure on that specific destination is not covered here. That destination is OpenAI-operated and outside the reported joy-openai / gpt-5.6-sol failure; it belongs in its own change if it ever reproduces.

Checklist

  • Focused tests for the changed subsystem pass
  • bun x tsc --noEmit clean
  • Regression tests present and mutation-verified
  • No docs-site change needed (wire-level request hygiene)

Triaged in the 2026-08-31 non-priority-70 bug round.

Summary by CodeRabbit

  • Bug Fixes

    • Prevented private internal metadata from being sent to routed Responses API destinations.
    • Preserved required metadata when communicating with the canonical ChatGPT backend.
    • Ensured request data remains unchanged for callers while being safely filtered for forwarding.
  • Tests

    • Added coverage confirming metadata filtering and preservation across supported destinations.

Remove internal ChatGPT item metadata before forwarding Responses requests to noncanonical destinations.

(cherry picked from commit a3f61f8)
Exercise key and forwarded noncanonical routes while preserving canonical ChatGPT passthrough behavior.

(cherry picked from commit 2e15e4b)
@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner August 31, 2026 18:55
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 31, 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-08-31T18:59:11.993846Z 39712e4 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.

@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Review 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: Pro Plus

Run ID: 0786393c-d9ff-44ae-b2c5-4dff2a9a73ef

📥 Commits

Reviewing files that changed from the base of the PR and between 6123be3 and 39712e4.

📒 Files selected for processing (2)
  • src/adapters/openai-responses.ts
  • tests/openai-responses-passthrough.test.ts

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


📝 Walkthrough

Walkthrough

Changes

Responses metadata filtering

Layer / File(s) Summary
Conditional metadata stripping and provider coverage
src/adapters/openai-responses.ts, tests/openai-responses-passthrough.test.ts
The request builder removes internal_chat_message_metadata_passthrough from message and function-call items for non-canonical providers. The copy-on-write helper preserves the original body when no changes are needed. Tests verify input immutability, non-canonical stripping, and canonical preservation.

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

Merge Risk: ⚪ Minimal · up to 39712

The change removes private item metadata only for noncanonical Responses destinations while preserving canonical forwarding and caller-owned requests. No actionable merge-blocking risk remains after normal checks and review.

Suggested reviewers: ingwannu, olddonkey

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% 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. 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 describes the main change: removing Codex-private Responses item metadata at the noncanonical forwarding boundary.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • 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 codex/3066-strip-codex-private-metadata

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

리뷰 · 우선순위 64 / 80

설명

이 PR은 기여자 @yanzhibo-bytedance 의 #3066을 지금 dev HEAD 6123be31f (#3103 forked-rollout restore) 위에 다시 올린 랜딩입니다. Codex 0.151부터 Responses input[] 항목에 internal_chat_message_metadata_passthrough 라는 ChatGPT 전용 필드가 붙습니다. OpenCodex는 히스토리 연속을 위해 루프백에서 공급자 이름을 openai 로 남겨 두기 때문에, 그 필드가 공개 Responses 게이트웨이까지 같이 갑니다. 그쪽은 input[*] 의 알 수 없는 파라미터라며 요청 전체를 거절합니다.

지금 체크아웃의 src/adapters/openai-responses.ts 를 보면, 비정규 목적지에만 쓰는 정리는 이미 isCanonicalOpenAiForwardProvider 가드로 나뉘어 있습니다. 이 함수는 src/providers/openai-tiers.ts 34–37행에서 adapter가 openai-responses이고 authMode가 forward이며 baseUrl이 Codex forward URL일 때만 참입니다. 2141행 근처에서 비정규일 때만 promoteClientLoadedTools 를 돌리고, 그 다음 블록에서 커스텀 툴·툴서치·네임스페이스 툴을 낮춥니다. 이 PR은 그 첫 비정규 블록 맨 앞에 stripInternalChatMessageMetadataPassthrough 를 넣습니다. 본문 객체를 직접 고치지 않고 input 항목만 복사한 뒤 필드를 지워서, 호출자가 넘긴 _rawBody 는 그대로 남습니다.

같은 결함을 먼저 잡은 #3038은 core.ts / compact.ts 에서 readJsonRequestBody 직후 무조건 지웁니다. 그러면 ChatGPT 정규 전달 경로의 필드까지 빠집니다. 그 경로는 이 필드가 외국 필드가 아닙니다. #3038 테스트는 헬퍼를 직접 호출해서 handleResponses 나 어댑터 buildRequest 를 한 번도 안 탑니다. 이 PR 테스트는 tests/openai-responses-passthrough.test.ts 에서 키 인증·forward 비정규 목적지 둘 다 필드가 빠지는지, 그리고 정규 ChatGPT forward에서는 남는지, 원본 rawBody 는 안 바뀌는지를 봅니다. types.ts/config.ts 분할 캠페인과는 무관합니다. #3066은 이 랜딩이 머지된 뒤에 leftover로 닫으면 됩니다.

round-2 prio≥70 남은 축은 #3029 / #3008 / #3019 입니다. 이 PR은 그 열차 밖이지만, 공개 게이트웨이로 라우트하는 사용자에게는 요청이 통째로 거절되는 체감이 큽니다. 변경은 파일 2개·함수 하나·테스트 두 개입니다. 다만 같은 시각에 열린 #3109도 src/adapters/openai-responses.ts 를 만집니다. 둘 다 머지하려면 한쪽에 리베이스가 필요합니다.

라인 src/adapters/openai-responses.ts strip 함수 - 최상위 input 배열의 직접 항목만 지웁니다. 중첩 메시지 content 안의 같은 필드가 있으면 그대로 남습니다. 지금 Codex가 붙이는 위치와 맞는지 한 번만 확인하면 됩니다.
경로 src/adapters/openai-responses.ts 비정규 가드 블록 - 같은 파일의 isCanonicalOpenAiForwardProvider 가드가 여러 개로 쪼개져 있습니다. 이 PR은 첫 블록에만 넣어서 promote보다 먼저 돕니다. 순서는 맞지만, 나중에 누군가 가드를 합치면 빠지기 쉬운 자리입니다.
경로 #3109 - 같은 어댑터 파일의 compact SSE 수집을 고칩니다. 이 PR과 한 커밋에 안 넣어도 되지만, 머지 순서를 정하지 않으면 한쪽이 CONFLICTING이 됩니다.
경로 #3038 / #3066 - 레이어 결정은 이 PR이 맞습니다. #3038을 리베이스하지 말고, 이 랜딩이 들어간 뒤 leftover로 닫는 쪽이 분할 캠페인 원칙과도 맞습니다.

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

  • #3109와 누가 먼저 dev 에 들어갈지 (같은 openai-responses.ts)
  • leftover fix(responses): strip Codex-private item metadata #3066 / 대체된 #3038을 이 랜딩 머지 직후 바로 닫을지
  • 중첩 input 항목까지 재귀로 지울지, 최상위만으로 충분한지

너의 추천
머지 쪽으로 진행하는 것을 추천합니다. 비정규 경계에서만 지우고 정규 ChatGPT 경로는 보존하며, 테스트가 어댑터 buildRequest 를 실제로 탑니다. #3038은 닫고 이 브랜치를 쓰면 됩니다. #3109와 파일이 겹치니 둘 중 하나를 먼저 랜딩한 뒤 나머지를 고치면 됩니다. Protect dev 리뷰 후 넣으면 됩니다.

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

@lidge-jun

Copy link
Copy Markdown
Owner Author

Administrator bypass record\n\nOwner authorization was explicit in Codex session 01a05a34-1e3a-73f2-8607-15e517cbec11 on 2026-09-01 KST. Exact head: 39712e4. Current exact-head check rollup: 0 failing, 0 pending. Independent A-gate review found no unresolved code blocker. Using the maintain/admin pull_request bypass documented in MAINTAINERS.md because the author cannot approve their own PR. This bypass does not waive CI or security review.

@lidge-jun
lidge-jun merged commit e9d198a into dev Sep 1, 2026
27 checks passed
@lidge-jun
lidge-jun deleted the codex/3066-strip-codex-private-metadata branch September 1, 2026 00:10
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