Skip to content

Add Anthropic Messages bridge for OpenAI-compatible chat providers - #26

Merged
OnlyTerp merged 4 commits into
sybil-solutions:mainfrom
eafire15:codex/anthropic-openai-bridge
Jun 8, 2026
Merged

Add Anthropic Messages bridge for OpenAI-compatible chat providers#26
OnlyTerp merged 4 commits into
sybil-solutions:mainfrom
eafire15:codex/anthropic-openai-bridge

Conversation

@eafire15

@eafire15 eafire15 commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Summary

This adds an Anthropic Messages bridge for OpenAI-compatible providers:

POST /v1/messages
  -> provider: anthropic
       pass through to upstream /messages with model rewrite
  -> provider: openai | generic-chat-completion-api
       translate Anthropic Messages requests to /chat/completions
       translate chat-completions responses/streams back to Anthropic shape

Why

Some providers, including OpenCode Go, expose useful models across OpenAI-compatible and Anthropic-compatible surfaces. codex-shim already translates Codex Responses requests to both OpenAI-shaped chat completions and Anthropic Messages upstreams. This adds the reverse client-facing side: Anthropic-speaking clients can point at codex-shim and use configured OpenAI-compatible providers.

That makes OpenCode Go integration easier without adding a provider-specific dependency.

Changes

  • Adds POST /v1/messages.
  • Adds Anthropic Messages -> OpenAI chat-completions request translation.
  • Adds OpenAI chat-completions -> Anthropic message response translation.
  • Adds Anthropic SSE streaming for OpenAI chat-completions streams.
  • Preserves pass-through behavior for provider: "anthropic" models.
  • Adds Anthropic-shaped upstream error responses for bridged OpenAI-compatible calls.
  • Documents the bridge briefly in the README.

Supported bridge surface:

  • text messages
  • image inputs
  • basic function tools and tool results
  • usage mapping
  • streaming text/reasoning/tool-call deltas

Deferred provider-specific surfaces:

  • prompt caching / cache_control
  • extended thinking signatures
  • files/PDF/audio
  • token counting endpoints
  • server tools beyond basic function-call shape

Model-assisted revision notes

  • GPT-5.5 / Codex: drafted the bridge, including /v1/messages, Anthropic-to-chat request conversion, chat-to-Anthropic response/stream conversion, pass-through behavior, docs, tests, and live smoke validation.
  • Qwen 3.7 Max: caught provider compatibility around tool-only assistant messages, changed content: null to content: "", deduplicated helper logic, and expanded stream/error tests.
  • GLM 5.1: caught stream identity/tooling edge cases, switched generated Anthropic message IDs to UUIDs, rewrote pass-through stream model names to the public shim slug, and preserved original Anthropic tool names.
  • MiniMax M3: reviewed the paired OpenCode Go on-ramp work; no direct code changes were needed in this bridge PR.

Testing

python -m pytest

Result:

97 passed

Local smoke:

  • Started this branch on 127.0.0.1:8786 with an OpenAI-compatible upstream route.
  • Sent a live Anthropic Messages request through the bridge to an OpenCode Go model; response came back as Anthropic-shaped message content.
  • Verified streaming /v1/messages emits Anthropic SSE ending with message_stop and no OpenAI [DONE] sentinel.
  • Verified forced tool use returns Anthropic tool_use with stop_reason: "tool_use".

eafire15 and others added 3 commits June 2, 2026 20:31
…s, add bridge tests

- Fix content: None → empty string in _anthropic_assistant_message_to_chat
  for tool-only assistant messages (some providers reject null content)
- Deduplicate _chat_stream_finish_to_anthropic_stop and
  _anthropic_usage_from_normalized from server.py; import canonical
  versions from translate.py instead
- Add 4 new tests: tool call streaming, reasoning streaming,
  Anthropic-shaped error responses, and Anthropic pass-through streaming
- Add 2 new translate tests: tool-only content and reasoning blocks
…ames

- Use uuid4() for Anthropic message_id instead of timestamp (collision risk)
- Rewrite model field in pass-through SSE message_start events
- Preserve original tool names in _anthropic_tools_to_chat_tools and
  _anthropic_tool_choice_to_chat (remove _sanitize_tool_name mangling)
@eafire15
eafire15 marked this pull request as ready for review June 2, 2026 14:35
# Conflicts:
#	codex_shim/server.py
@OnlyTerp
OnlyTerp merged commit b0da566 into sybil-solutions:main Jun 8, 2026
2 checks passed
Samuel86-star added a commit to Samuel86-star/codex-shim that referenced this pull request Jun 10, 2026
Upstream's Anthropic Messages bridge PR (sybil-solutions#26) replaced server.py and
dropped the [route] diagnostic prints that were added during the
smart-vision-routing branch's merge conflict resolution. Re-add them
to _post_openai_chat and _post_anthropic.

Also fixes a merge regression where the old vision_router _route
signature (returning tuple[ShimModel, dict]) leaked back into the
merged file, causing two test failures.
jomangbp pushed a commit to jomangbp/codex-shim that referenced this pull request Jul 6, 2026
…ybil-solutions#26)

* feat: add Anthropic Messages bridge

* fix: empty string for tool-only assistant content, deduplicate helpers, add bridge tests

- Fix content: None → empty string in _anthropic_assistant_message_to_chat
  for tool-only assistant messages (some providers reject null content)
- Deduplicate _chat_stream_finish_to_anthropic_stop and
  _anthropic_usage_from_normalized from server.py; import canonical
  versions from translate.py instead
- Add 4 new tests: tool call streaming, reasoning streaming,
  Anthropic-shaped error responses, and Anthropic pass-through streaming
- Add 2 new translate tests: tool-only content and reasoning blocks

* fix: uuid message ids, model slug in passthrough SSE, preserve tool names

- Use uuid4() for Anthropic message_id instead of timestamp (collision risk)
- Rewrite model field in pass-through SSE message_start events
- Preserve original tool names in _anthropic_tools_to_chat_tools and
  _anthropic_tool_choice_to_chat (remove _sanitize_tool_name mangling)

---------

Co-authored-by: codex <codex@openai.com>
Co-authored-by: test <test@local>
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.

3 participants