Skip to content

feat(plugin): rewrite codex request body for ChatGPT backend requirements - #39197

Open
patrickpassosb wants to merge 2 commits into
anomalyco:devfrom
patrickpassosb:fm/codex-body-rewrite-upstream
Open

feat(plugin): rewrite codex request body for ChatGPT backend requirements#39197
patrickpassosb wants to merge 2 commits into
anomalyco:devfrom
patrickpassosb:fm/codex-body-rewrite-upstream

Conversation

@patrickpassosb

Copy link
Copy Markdown

Issue for this PR

Follow-up to #38903. #38903 added the codexApiEndpoint option so ChatGPT Plus/Pro (OAuth) inference can route through a gateway instead of the hardcoded https://chatgpt.com/backend-api/codex/responses. That PR routes the URL correctly, but opencode's standard request body violates the ChatGPT codex backend's hard requirements and every request is rejected. This PR rewrites the request body for the codex path so opencode can actually drive a ChatGPT subscription through a gateway end-to-end.

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

The ChatGPT codex backend (chatgpt.com/backend-api/codex/responses) has hard requirements that the OpenAI platform API (api.openai.com) does not:

  • "store": false is required (else {"detail":"Store must be set to false"}).
  • "stream": true is required (else {"detail":"Stream must be set to true"}).
  • "max_output_tokens" is unsupported and must be omitted (else {"detail":"Unsupported parameter: max_output_tokens"}).

Verified live (2026-07-26) with a hand-crafted request through a Tailscale Aperture passthrough provider using a ChatGPT Plus OAuth token: a request succeeds (streams a real response.created SSE event) only when all three hold. Without this PR, opencode run --model openai/gpt-5.6-sol hangs/fails even though the URL routing from #38903 works.

This PR extends the CodexAuthPlugin fetch wrapper (the same one that rewrites the URL via codexApiEndpoint from #38903) so that when the request is headed to the codex endpoint, the JSON request body is rewritten to:

  1. Set store: false.
  2. Set stream: true (the AI SDK already handles streaming responses, so the response is passed through unchanged).
  3. Remove max_output_tokens.

The rewrite is guarded: it only applies when the URL is the codex endpoint (the codexApiEndpoint path), NOT for the standard api.openai.com//v1/responses path. Non-codex OpenAI requests are byte-identical.

How did you verify your code works?

  • bun typecheck (tsgo --noEmit) from packages/opencode — clean.
  • bun test test/plugin/codex.test.ts — 35 pass / 0 fail, including 7 new body-rewrite tests covering: (a) store:false set on codex path, (b) stream:true set on codex path, (c) max_output_tokens stripped on codex path, (d) non-codex requests unchanged, (e) body rewrite only applies when URL is the codex endpoint.
  • End-to-end: opencode run --model openai/gpt-5.6-sol "Reply with exactly: CHATGPT PLUS OK" returned a real streamed answer through a Tailscale Aperture passthrough provider. Non-codex model (ollama-cloud/glm-5.2) still works unchanged.

Screenshots / recordings

N/A — no UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

…xApiEndpoint

Read provider-level codexApiEndpoint (and a baseURL ending in /codex, with
/responses appended) from the auth loader's provider info so a ChatGPT
Plus/Pro/Team subscription can be routed through a gateway instead of the
hardcoded chatgpt.com backend endpoint. The rewrite is byte-identical to
today when neither option is set: the CODEX_API_ENDPOINT constant is used.

Refactors the endpoint resolution into an exported resolveCodexApiEndpoint
helper and threads the second loader argument (provider info) into the
existing URL rewrite site. The experimental websocketFetch path receives
the rewritten URL via the same variable, so both transport modes honor the
config.
…ents

The ChatGPT codex backend (chatgpt.com/backend-api/codex/responses) rejects
requests unless store=false, stream=true, and max_output_tokens is omitted.
Add a request-body rewrite in the CodexAuthPlugin fetch wrapper that is
applied only when the request is routed to the codex endpoint; non-codex
OpenAI requests are left byte-identical.
@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Related PR found:

No duplicate PRs found. PR #39197 is a unique feature that extends functionality from #38903.

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.

1 participant