fix(openai-to-claude): unwrap bare {function:{…}} tools without parent type (#2473)

Translator only unwrapped tool.function when both tool.type==="function"
and tool.function were truthy. Loose/legacy OpenAI clients emit the bare
{ function: { name, parameters } } shape (no parent type), which fell
through and forwarded name: undefined upstream, rejected by strict
Anthropic-compatible gateways (MiniMax M3) as (2013) invalid tool type.

Unwrap tool.function whenever present. Built-in tools stay pass-through.
Adds regression coverage for the 4 tool shapes. See #2435.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Samir Abis
2026-07-10 11:11:37 +07:00
committed by decolua
co-authored by Cursor
parent 288940960a
commit ddd5509e97
2 changed files with 100 additions and 1 deletions
@@ -153,7 +153,15 @@ Respond ONLY with the JSON object, no other text.`);
continue;
}
const toolData = toolType === OPENAI_BLOCK.FUNCTION && tool.function ? tool.function : tool;
// Function-shaped tools arrive in two flavors from real clients:
// (a) openai-spec: { type: "function", function: { name, ... } }
// (b) legacy/loose: { function: { name, ... } } (no parent `type`)
// Both must yield toolData.name = "echo". Treat the bare-function shape
// as a function tool too — Anthropic-compatible gateways (notably
// MiniMax M3 at api.minimaxi.com) reject payloads where this branch
// falls through with `toolData.name === undefined`, returning their
// upstream code (2013) "invalid tool type". See #2435.
const toolData = tool.function ?? tool;
const originalName = toolData.name;
// Claude OAuth requires prefixed tool names to avoid conflicts