Skip to content

fix(translator): normalize Cursor Anthropic tool blocks on OpenAI endpoint#3804

Closed
HatriGt wants to merge 10 commits into
router-for-me:devfrom
HatriGt:fix/cursor-anthropic-tool-blocks
Closed

fix(translator): normalize Cursor Anthropic tool blocks on OpenAI endpoint#3804
HatriGt wants to merge 10 commits into
router-for-me:devfrom
HatriGt:fix/cursor-anthropic-tool-blocks

Conversation

@HatriGt

@HatriGt HatriGt commented Jun 11, 2026

Copy link
Copy Markdown

Problem

Cursor in agent / tool mode sends Anthropic-native content blocks to the OpenAI /v1/chat/completions endpoint instead of OpenAI-format tool messages. Specifically:

  • user.content arrays containing { "type": "tool_result", "tool_use_id": ..., "content": ... }
  • assistant.content arrays containing { "type": "tool_use", "id": ..., "name": ..., "input": {...} }
  • bare tool definitions { "name", "description", "input_schema" } (no type: "function" wrapper)

ConvertOpenAIRequestToClaude assumes valid OpenAI shapes (tool_calls, role:"tool", tools[].type=="function"), so these payloads were dropped, producing an invalid Claude request and errors like:

messages.N: user messages must have non-empty content

or silently broken tool calling. This matches #1165 and the Cursor community report "Wrong tools handling on OpenAI compatible endpoint".

Fix

Add normalizeAnthropicRequestBlocks, a pre-processing pass at the top of ConvertOpenAIRequestToClaude that rewrites Anthropic-native shapes into standard OpenAI shapes before the existing translation runs:

  1. user content tool_result blocks -> standalone role:"tool" messages (tool_call_id, content); sibling text blocks are preserved as a trailing user message.
  2. assistant content tool_use blocks -> assistant.tool_calls[].function (text blocks merged into content).
  3. bare { name, description, input_schema } tools -> { type:"function", function:{ name, description, parameters } }.

Standard OpenAI payloads are detected via anthropicBlocksPresent and pass through untouched (no behavior change for existing clients).

Why this matters

Without this, Cursor users must run an external request-rewriting proxy/shim in front of CLIProxyAPI to use agent mode with Claude over OAuth. This fix makes the OpenAI endpoint accept Cursor's payloads natively.

Tests

Added claude_openai_normalize_test.go:

  • TestConvertOpenAIRequestToClaude_CursorToolResultBlock - full assistant tool_use + user tool_result round trip
  • TestConvertOpenAIRequestToClaude_CursorToolResultWithText - mixed tool_result + trailing text
  • TestConvertOpenAIRequestToClaude_BareAnthropicTools - bare tool definition wrapping
  • TestConvertOpenAIRequestToClaude_StandardOpenAIUnchanged - regression guard for normal OpenAI payloads
go test ./internal/translator/claude/openai/chat-completions/...
ok
go build ./internal/translator/...
go vet ./internal/translator/claude/openai/chat-completions/...

Refs #1165

@github-actions github-actions Bot changed the base branch from main to dev June 11, 2026 10:08
@github-actions

Copy link
Copy Markdown

This pull request targeted main.

The base branch has been automatically changed to dev.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces normalization of Anthropic-native request blocks (such as tool_use, tool_result, and bare tool definitions) into standard OpenAI shapes within the ConvertOpenAIRequestToClaude translation pipeline, along with corresponding unit tests. The reviewer suggests optimizing performance in the normalization logic by using string types with sjson.Set and sjson.SetRaw instead of []byte with sjson.SetBytes and sjson.SetRawBytes to avoid unnecessary byte slice allocations and conversions.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread internal/translator/claude/openai/chat-completions/claude_openai_request.go Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d5f0f77b0a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread internal/translator/claude/openai/chat-completions/claude_openai_request.go Outdated
@HatriGt HatriGt force-pushed the fix/cursor-anthropic-tool-blocks branch from d5f0f77 to 162200e Compare June 11, 2026 10:28
@HatriGt

HatriGt commented Jun 11, 2026

Copy link
Copy Markdown
Author

Thanks for the reviews. Addressed both in the latest push (rebased onto dev):

@chatgpt-codex-connector (P2 — preserve typed Anthropic tools): Fixed. The wrapper now only treats tools with no type field as bare custom tools. Typed Anthropic server tools (e.g. web_search_20250305) are passed through untouched instead of being rewritten into a schema-less function tool. The detection in anthropicBlocksPresent was updated to match. Added TestNormalizeAnthropicRequestBlocks_TypedToolNotWrapped to lock this in.

@gemini-code-assist (perf — string vs []byte): Done. Switched the message/tool accumulators to string with sjson.Set/sjson.SetRaw, only converting to []byte once at the end when writing back into out.

go test, go vet, and gofmt are all clean on the package.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Thanks for the update, HatriGt. The approach of using sjson for string-based manipulation and performing a single []byte conversion at the end is an efficient way to handle these payloads. The added test coverage for typed Anthropic tools is also a great addition to ensure we don't accidentally break existing server-side tool integrations. Everything looks good to go.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 162200e794

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@HatriGt

HatriGt commented Jun 11, 2026

Copy link
Copy Markdown
Author

Heads up: this PR fails the translator-path-guard check because all changes are under internal/translator/**, which the repo policy reserves for the maintenance team:

Changes under internal/translator are not allowed in pull requests. You need to create an issue for our maintenance team to make the necessary changes.

I've followed that process and filed #3805 with the full context, repro, rationale, and the complete proposed diff inlined.

I'll leave this PR open as ready-to-merge reference code (build + go vet pass; only the path-guard fails by policy). Happy to adjust or close it in favor of #3805 — whichever the maintainers prefer. Thanks!

HatriGt added a commit to HatriGt/CLIProxyAPI that referenced this pull request Jun 11, 2026
…onversion

Addresses the follow-up Codex review on PR router-for-me#3804. The normalizer already
left typed Anthropic server tools (e.g. web_search_20250305) untouched, but
the downstream tool mapper in ConvertOpenAIRequestToClaude only emitted
type=="function" tools, silently dropping typed server tools from the final
Claude request when sent alongside a bare custom tool.

Pass typed server tools (type present, not "function") through verbatim into
the Claude tools array. Add TestConvertOpenAIRequestToClaude_TypedServerToolPreserved
to assert end-to-end survival through the full conversion, not just the
normalizer.
@sususu98 sususu98 force-pushed the dev branch 2 times, most recently from 80d61a3 to ac4017e Compare June 11, 2026 13:49
@HatriGt

HatriGt commented Jun 11, 2026

Copy link
Copy Markdown
Author

@sususu98 @luispater can you review this?

@sususu98

Copy link
Copy Markdown
Collaborator

Please rebase on the dev branch first

HatriGt added a commit to HatriGt/CLIProxyAPI that referenced this pull request Jun 12, 2026
…onversion

Addresses the follow-up Codex review on PR router-for-me#3804. The normalizer already
left typed Anthropic server tools (e.g. web_search_20250305) untouched, but
the downstream tool mapper in ConvertOpenAIRequestToClaude only emitted
type=="function" tools, silently dropping typed server tools from the final
Claude request when sent alongside a bare custom tool.

Pass typed server tools (type present, not "function") through verbatim into
the Claude tools array. Add TestConvertOpenAIRequestToClaude_TypedServerToolPreserved
to assert end-to-end survival through the full conversion, not just the
normalizer.
@HatriGt HatriGt force-pushed the fix/cursor-anthropic-tool-blocks branch from ca61338 to 7226b49 Compare June 12, 2026 07:42
@HatriGt

HatriGt commented Jun 12, 2026

Copy link
Copy Markdown
Author

Rebased onto latest dev (5633c936) and force-pushed. go test ./internal/translator/claude/openai/chat-completions/... passes locally.

Ready for another look — thanks @sususu98.

Copy link
Copy Markdown
Collaborator

Thanks for rebasing. Before we review this further, please drop commit 765728f527a9d5e1b0e4da56a3955bfd0c522849 (feat(antigravity): support native Claude web search) from this branch and recreate the PR with only the Cursor/Anthropic tool-block normalization changes.

The Antigravity Claude Code built-in WebSearch path is broader than this fix, and we plan to support that through the plugin mechanism instead. It should not be merged as part of this PR.

Once the branch is narrowed, please open or refresh the PR and we can review it again. Thanks!

HatriGt added 3 commits June 12, 2026 12:03
…point

Cursor in agent/tool mode sends Anthropic-native content blocks (tool_use /
tool_result) and bare tool definitions to the OpenAI Chat Completions endpoint.
These are not valid OpenAI format, so ConvertOpenAIRequestToClaude produced an
empty/invalid Claude request, causing errors such as
"messages.N: user messages must have non-empty content" and silently broken
tool calling (see router-for-me#1165).

Add normalizeAnthropicRequestBlocks as a pre-processing pass that rewrites:
- user content tool_result blocks -> standalone role:"tool" messages
- assistant content tool_use blocks -> assistant tool_calls[].function
- bare {name, description, input_schema} tools -> {type:"function", function:{...}}

Standard OpenAI payloads are detected and pass through untouched. This removes
the need for an external request-rewriting proxy/shim when using Cursor agent
mode with Claude via OAuth.
…tion

- Preserve typed Anthropic server tools (e.g. web_search_20250305): only wrap
  tools that have NO "type" field as OpenAI function tools, so typed server
  tools are left intact for downstream mapping instead of being rewritten into
  a custom tool with no schema (codex review P2).
- Use string accumulators with sjson.Set/SetRaw instead of []byte +
  SetBytes/SetRawBytes to avoid unnecessary allocations (gemini review).
- Add TestNormalizeAnthropicRequestBlocks_TypedToolNotWrapped regression test.
…onversion

Addresses the follow-up Codex review on PR router-for-me#3804. The normalizer already
left typed Anthropic server tools (e.g. web_search_20250305) untouched, but
the downstream tool mapper in ConvertOpenAIRequestToClaude only emitted
type=="function" tools, silently dropping typed server tools from the final
Claude request when sent alongside a bare custom tool.

Pass typed server tools (type present, not "function") through verbatim into
the Claude tools array. Add TestConvertOpenAIRequestToClaude_TypedServerToolPreserved
to assert end-to-end survival through the full conversion, not just the
normalizer.
@HatriGt HatriGt force-pushed the fix/cursor-anthropic-tool-blocks branch from 7226b49 to 15b29e2 Compare June 12, 2026 08:03
@HatriGt

HatriGt commented Jun 12, 2026

Copy link
Copy Markdown
Author

Done — dropped commit 765728f527a9d5e1b0e4da56a3955bfd0c522849 (feat(antigravity): support native Claude web search) and force-pushed.

The branch is now rebased onto dev (5633c936) and contains only the Cursor/Anthropic tool-block normalization changes — 3 commits touching just:

  • internal/translator/claude/openai/chat-completions/claude_openai_request.go
  • internal/translator/claude/openai/chat-completions/claude_openai_normalize_test.go

No Antigravity / WebSearch code remains. Ready for review again — thanks @sususu98.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 15b29e2a02

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Cursor/Anthropic parallel tool calls arrive as consecutive role:"tool"
messages. The Claude mapper emitted a separate user turn per tool_result,
breaking the tool_use/tool_result pairing Claude requires (all results for
the preceding assistant tool_use turn must share one user message).

Append consecutive tool_result blocks to the prior user/tool_result turn
instead of creating a new message. Add a parallel-tool-results test.
@HatriGt

HatriGt commented Jun 12, 2026

Copy link
Copy Markdown
Author

Addressed the Codex P2 about parallel tool results (commit 1e19366d).

Problem: Cursor runs parallel tool calls — one assistant turn with multiple tool_use blocks, answered by a single user turn with multiple tool_result blocks. The normalizer split those into separate role:"tool" messages, and the downstream Claude mapper emitted a separate user turn per result. Claude requires all tool_result blocks answering the preceding assistant tool_use turn to be grouped in one user message, so the pairing was broken.

Fix: When mapping a role:"tool" message, if the previous emitted message is already a user turn ending in a tool_result block, append to it instead of starting a new turn. Single tool results and the tool_result + trailing text case are unchanged.

Added TestConvertOpenAIRequestToClaude_CursorParallelToolResults. Full package: go test ./internal/translator/claude/openai/chat-completions/... passes, go vet clean.

Branch still contains only the Cursor/Anthropic tool-block normalization changes — no Antigravity code. Thanks @sususu98.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1e19366d1d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Cursor forwards failed tool executions as Anthropic tool_result blocks with
is_error:true. The normalizer dropped that flag when synthesizing the OpenAI
role:"tool" message, so the downstream Claude tool_result lost it and a failed
tool call looked like a success. Carry is_error through the synthesized
message and reconstruct it on the Claude tool_result block. Add a test.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dcd87bd806

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

A Cursor tool_result.content can be an array of Claude-native blocks (image
with source, tool_reference, etc.). Routing it through the OpenAI content-part
converter dropped unknown blocks or stringified them. Flag native arrays in the
normalizer and copy them verbatim into the Claude tool_result instead. Add a test.
@HatriGt

HatriGt commented Jun 12, 2026

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 05be4cb271

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread internal/translator/claude/openai/chat-completions/claude_openai_request.go Outdated
Extended-thinking models emit thinking / redacted_thinking blocks before the
tool_use in an assistant turn. The normalizer rebuilt the assistant message
from only text and tool_use, dropping the signed thinking blocks. Anthropic
requires prior thinking blocks to be returned unchanged on subsequent
tool-result requests, so carry them through and lead the Claude assistant
content with them. Add a test.
@HatriGt

HatriGt commented Jun 12, 2026

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fa4a488675

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread internal/translator/claude/openai/chat-completions/claude_openai_request.go Outdated
@HatriGt

HatriGt commented Jun 12, 2026

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fa4a488675

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread internal/translator/claude/openai/chat-completions/claude_openai_request.go Outdated
The typed-tool passthrough forwarded any non-function OpenAI tool type to
Claude. Unversioned OpenAI built-ins (e.g. {"type":"web_search"}) are not
Claude-native and trigger an upstream 400 instead of being ignored as before.
Restrict passthrough to Anthropic versioned server tools (type ending in
_YYYYMMDD); drop other non-function types. Add a test.
@HatriGt

HatriGt commented Jun 12, 2026

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 279bd73bc8

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread internal/translator/claude/openai/chat-completions/claude_openai_request.go Outdated
After a Claude server tool (e.g. web_search_20250305) runs, the assistant turn
carries server_tool_use and *_tool_result blocks. The normalization predicate
ignored them, so the OpenAI content converter later dropped them, erasing
server-tool context on the next turn. Recognize these block types, carry them
through verbatim, and re-emit them in the Claude assistant content. Add a test.
@HatriGt

HatriGt commented Jun 12, 2026

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 84a08e4a82

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Cursor sends bare Anthropic tools alongside a native forced tool_choice
{"type":"tool","name":...}, plus auto/any/none. The mapper only handled
OpenAI's {"type":"function",...} object form, so the forced selection was
silently dropped and fell back to auto. Handle the Anthropic shapes directly.
Add a test.
@HatriGt

HatriGt commented Jun 12, 2026

Copy link
Copy Markdown
Author

@codex review

1 similar comment
@HatriGt

HatriGt commented Jun 12, 2026

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: 9b8fc48984

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@HatriGt

HatriGt commented Jun 12, 2026

Copy link
Copy Markdown
Author

@sususu98 this is ready for review. All Codex findings are addressed and its latest pass on 9b8fc489 reports "Didn't find any major issues". The branch is rebased on dev and scoped strictly to Cursor/Anthropic tool-block normalization on the OpenAI Chat Completions endpoint — no Antigravity code.

What it does

Cursor agent mode sends Anthropic-native shapes to the OpenAI endpoint. This normalizes them into valid Claude requests:

Core normalization

  • tool_use / tool_result content blocks → OpenAI tool_calls / role:"tool", and bare Anthropic tool defs → OpenAI function tools.
  • Typed Anthropic server tools (e.g. web_search_20250305) survive the full conversion instead of being dropped.

Edge cases hardened from review

  • Parallel tool calls — multiple tool_result blocks are grouped into one Claude user turn (Claude rejects split turns).
  • is_error — failed tool results keep their error flag instead of looking successful.
  • Native tool_result.content arrays — Claude-native blocks (image/source, tool_reference) kept verbatim, not stringified/dropped.
  • Thinking blocksthinking / redacted_thinking preserved and lead the assistant content (required by extended-thinking models).
  • Server-tool historyserver_tool_use / *_tool_result blocks survive into the next turn.
  • Tool-type passthrough — only versioned Claude-native server tools pass through; unversioned OpenAI built-ins are dropped (not forwarded as an upstream 400).
  • tool_choice — Anthropic-native forced choice {"type":"tool","name":...} (and auto/any/none) is mapped instead of silently falling back to auto.

Testing

Dedicated tests for each case in claude_openai_normalize_test.go; full package go test ./internal/translator/claude/openai/chat-completions/... passes and go vet is clean. Changes are confined to claude_openai_request.go + that test file.

Thanks for the thorough review — happy to adjust anything.

@HatriGt

HatriGt commented Jun 14, 2026

Copy link
Copy Markdown
Author

@luispater @sususu98 kindly review this.

@HatriGt

HatriGt commented Jun 17, 2026

Copy link
Copy Markdown
Author

@luispater @sususu98 kindly review this.

@luispater @sususu98 any update

@luispater

Copy link
Copy Markdown
Collaborator

Thanks for the reference implementation.

We are closing this PR because sending Anthropic-native content blocks to the OpenAI Chat Completions endpoint is a client-side protocol error. CLIProxyAPI will not rewrite or correct that invalid client behavior on this endpoint.

Please report this to Cursor so they can send a valid OpenAI Chat Completions payload when using an OpenAI-compatible endpoint.

Community feedback also suggests a possible workaround: alias claude-sonnet-4-5 as 5-4-tennos-edualc. With that alias, Cursor may send the correct OpenAI Chat Completions protocol.

@luispater luispater closed this Jun 20, 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.

3 participants