Skip to content

Anthropic/ChatCompletions clients → ChatGPT Codex via Responses API - #1

Closed
Jiliac wants to merge 10 commits into
adil/fix-responses-identity-passthroughfrom
adil/anthropic-client-codex-responses
Closed

Anthropic/ChatCompletions clients → ChatGPT Codex via Responses API#1
Jiliac wants to merge 10 commits into
adil/fix-responses-identity-passthroughfrom
adil/anthropic-client-codex-responses

Conversation

@Jiliac

@Jiliac Jiliac commented Jul 13, 2026

Copy link
Copy Markdown
Owner

Stacked on katanemo#988 (adil/fix-responses-identity-passthrough) — merge that first; this PR's diff will shrink to just the commits below once it lands.

Problem

Claude Code speaks the Anthropic Messages API. The ChatGPT Codex backend only serves /backend-api/codex/responses (the Responses API) — any client hitting it with a /chat/completions-shaped or Messages-shaped payload gets a hard 404 before this PR. There were two independent root causes:

  1. The ChatGPT provider was grouped together with the OpenAI-compatible providers in providers/id.rs, so it never got routed to the Responses API in the first place.
  2. Even once routed, the Anthropic client fell through to the /chat/completions default in clients/endpoints.rs instead of /responses.

What was added

  • Dedicated ChatGPT → Responses API routing for all client APIs (Anthropic Messages, ChatCompletions, and Responses passthrough).
  • Direct MessagesRequest ⇄ ResponsesAPIRequest and ChatCompletionsRequest → ResponsesAPIRequest transforms, including mapping reasoning into Anthropic thinking blocks with multi-turn encrypted_content replay.
  • Streaming transforms that turn Responses SSE events into Anthropic and ChatCompletions stream events.
  • Anthropic streaming buffer: multi-block balancing and [DONE] synthesis for the ChatCompletions leg.
  • InputItem untagged-enum fix: replaced with a manual type-dispatching Deserialize impl. This fixes a bug where ItemReference was silently swallowing function_call/reasoning items — it also benefits the pre-existing identity passthrough path, not just this feature.
  • Codex payload normalization: strip parameters Codex rejects (max_output_tokens, truncation, metadata, user, temperature, top_p), migrate the nested reasoning object handling, and add the ReasoningEffort::None/Minimal variants Codex can return.
  • Provider-prefix routing precedence fix in common/llm_providers.rs: an explicit openai/ prefix no longer loses to another provider's wildcard alias. This was a pre-existing bug, exposed by the new gpt-5.6 registry entries added under the chatgpt provider.

Verification

  • 215+ hermesllm lib tests, including full-stream fixture ladders and chunk-boundary replay scenarios.
  • cargo fmt, cargo clippy -D warnings, and the wasm build target all green.
  • Live-verified against real Codex across 3 rounds of testing:
    • Text, tool-call, and thinking ladders on gpt-5.6-luna, gpt-5.6-sol, gpt-5.6-terra, and gpt-5.4.
    • ChatCompletions leg (single [DONE], correct finish_reason).
    • Identity passthrough left intact.
    • Routing precedence confirmed (openai/* explicit prefix beats chatgpt/* wildcard).
    • Culminated in a real headless Claude Code session completing a Write + Read tool loop end-to-end against Codex with zero 400s.

Relationship to katanemo#958

This is orthogonal to katanemo#958. It deliberately does not adopt that PR's JSON post-pass adapter approach — all Codex-specific quirks here live on the typed ResponsesAPIRequest inside normalize_for_upstream, not as a generic JSON patch layer. Conflict surface should be minimal: provider_models.yaml is untouched by this PR.

Known follow-ups (minor, listed for transparency)

  • message_start emits model: "unknown" for Codex streams.
  • The incomplete → Length stop-reason mapping on the ChatCompletions leg is broader than strictly specced.
  • Codex only ever produced empty-summary reasoning items during testing, so thinking blocks currently observed are signature-only (empty thinking text + a signature_delta). Claude Code accepts this shape fine, but a non-empty reasoning summary has not been exercised end-to-end.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5473b344-d081-4561-84b9-5fffc2b8bf19

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch adil/anthropic-client-codex-responses

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.

@Jiliac

Jiliac commented Jul 14, 2026

Copy link
Copy Markdown
Owner Author

Closing as superseded for our local deployment by a chained architecture: Claude Code → Plano routing → CLIProxyAPI → Codex. The direct Anthropic/ChatCompletions → Codex Responses bridge remains incomplete for client-nonstream/upstream-stream and tool/subagent flows, so the PR’s current end-to-end compatibility claim is too broad. Preserving the branch for reference and possible extraction of independently useful fixes.

@Jiliac Jiliac closed this Jul 14, 2026
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