Skip to content

fix(openai): normalize Anthropic content blocks in chat completions r… - #68

Merged
githubgxll merged 8 commits into
DingoRouter-basefrom
DingoRouter-base-1
Sep 30, 2026
Merged

githubgxll merged 8 commits into
DingoRouter-basefrom
DingoRouter-base-1

Conversation

@guojn1

@guojn1 guojn1 commented Sep 20, 2026

Copy link
Copy Markdown
Collaborator

…equests

Gateway may forward Anthropic-format content blocks (thinking, tool_use) inside assistant message content arrays to the OpenAI /v1/chat/completions endpoint. The OpenAI deserializer only accepts text and refusal part types, causing a 400 error. Add middleware to convert Anthropic blocks before deserialization: thinking -> reasoning_content, tool_use -> tool_calls.

Only touches assistant messages whose content array contains type=thinking or type=tool_use. Standard OpenAI requests pass through unchanged.

Overview:

Details:

Where should the reviewer start?

Related Issues

⚠️ This section is required. Choose one path below and delete the other.

🔗 This PR is linked to an issue:

  • Closes #XXXX

🚫 This PR is NOT linked to an issue:

  • Confirmed — no related issue

@guojn1
guojn1 deployed to external_collaborator September 20, 2026 07:35 — with GitHub Actions Active
@guojn1
guojn1 had a problem deploying to external_collaborator September 20, 2026 08:34 — with GitHub Actions Failure
@guojn1
guojn1 had a problem deploying to external_collaborator September 20, 2026 08:50 — with GitHub Actions Failure
@guojn1
guojn1 had a problem deploying to external_collaborator September 20, 2026 09:26 — with GitHub Actions Failure
@guojn1
guojn1 had a problem deploying to external_collaborator September 20, 2026 09:41 — with GitHub Actions Failure
@guojn1
guojn1 had a problem deploying to external_collaborator September 20, 2026 09:43 — with GitHub Actions Failure
@guojn1
guojn1 had a problem deploying to external_collaborator September 20, 2026 10:20 — with GitHub Actions Failure
@guojn1
guojn1 had a problem deploying to external_collaborator September 20, 2026 12:33 — with GitHub Actions Failure
@guojn1
guojn1 had a problem deploying to external_collaborator September 21, 2026 01:58 — with GitHub Actions Failure
@guojn1
guojn1 had a problem deploying to external_collaborator September 21, 2026 01:59 — with GitHub Actions Failure
@guojn1
guojn1 had a problem deploying to external_collaborator September 22, 2026 12:56 — with GitHub Actions Failure
@guojn1
guojn1 had a problem deploying to external_collaborator September 22, 2026 13:12 — with GitHub Actions Failure
@guojn1
guojn1 had a problem deploying to external_collaborator September 23, 2026 01:42 — with GitHub Actions Failure
…equests

Gateway may forward Anthropic-format content blocks (thinking, tool_use)
inside assistant message content arrays to the OpenAI /v1/chat/completions
endpoint. The OpenAI deserializer only accepts text and refusal part types,
causing a 400 error. Add middleware to convert Anthropic blocks before
deserialization: thinking -> reasoning_content, tool_use -> tool_calls.

Only touches assistant messages whose content array contains type=thinking
or type=tool_use. Standard OpenAI requests pass through unchanged.
…blocks

Address PR review findings on the Anthropic content-block compat middleware:

- F1: reject cross combinations of partially-translated messages whose
  ordering cannot be proven: existing tool_calls with residual thinking,
  and existing reasoning_content with residual tool_use (unified into
  check_mixed_format_conflicts, replacing the R1/R2 pair)
- F2: reject unknown/unsupported block types (e.g. server_tool_use)
  instead of silently dropping them when the content array is replaced
- F3: require tool_use input to be present and an object; require
  string payloads for text/thinking/refusal blocks, with the block
  index reported in the error
- F4: merge multiple refusal blocks with a newline instead of keeping
  only the last one
- tests: 14 new unit tests for the converter and the conflict policy,
  plus 9 middleware integration tests against a live echo server
  (end-to-end conversion, pure-OpenAI passthrough, invalid-JSON
  passthrough, F1/F2/F3 rejections, idempotency, 413 body limit)
…ing it

Review v4 R1 (P2): a non-null, non-array tool_calls value (object,
string, number, bool) on an assistant message with residual Anthropic
blocks was treated as 'no existing calls' by the mixed-format check,
so the converted tool_calls insert silently deleted the original
field — normalizing a gateway format error into a valid-looking
request.  Distinguish the structural type up front: missing/null/empty
array means no existing calls, a non-empty array enters the conflict
policy, anything else is rejected with 400 naming messages[i].tool_calls.

Route regression tests: object/string/number/bool all return 400;
null and empty array still convert; non-empty legal arrays keep the
existing mixed-format conflict behavior.
…t converter

- Reject text after tool_use: OpenAI content field cannot preserve
  post-call text ordering
- Reject thinking after text before first tool_use: flat reasoning
  path would lose ordering
- Stop swallowing serde_json::to_string errors on tool_use arguments
- Remove user input (id/type) from error messages, use block index
- rustfmt formatting pass
@guojn1
guojn1 had a problem deploying to external_collaborator September 29, 2026 07:56 — with GitHub Actions Failure
@guojn1
guojn1 had a problem deploying to external_collaborator September 29, 2026 10:00 — with GitHub Actions Failure
@guojn1
guojn1 had a problem deploying to external_collaborator September 30, 2026 03:10 — with GitHub Actions Failure
@guojn1
guojn1 had a problem deploying to external_collaborator September 30, 2026 04:10 — with GitHub Actions Failure
@guojn1
guojn1 had a problem deploying to external_collaborator September 30, 2026 06:31 — with GitHub Actions Failure
@guojn1
guojn1 had a problem deploying to external_collaborator September 30, 2026 07:06 — with GitHub Actions Failure
@githubgxll
githubgxll merged commit d64c67c into DingoRouter-base Sep 30, 2026
4 of 6 checks passed

This branch had an error being deployed

1 failed deployment
external_collaborator — 6d506083 Deployed Sep 30, 2026 by guojn1 via ok-to-test #150
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants