mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-21 14:22:14 +03:00
fix: don't blanket-disable Claude tool-name prefix for non-Anthropic providers (#13856)
* fix: don't blanket-disable Claude tool-name prefix for non-Anthropic providers
The Issue #199/#618 fix that disables the proxy_ tool-name prefix for
requests landing in the general (non-CC-bridge, non-passthrough)
translation branch was scoped to "targetFormat === Claude", but that
condition is true for any provider translating into Claude's wire
format, not just genuine first-party Anthropic traffic. In practice
this let ordinary third-party tool names (e.g. GitHub Copilot's own
client-executed "web_fetch" function tool) pass through unprefixed
and collide with Claude's reserved tool namespace, getting rejected
upstream ("rejected tool(s): web_fetch") for any gh/claude-* model.
#618's actual traffic was real Claude Code (provider "claude") landing
in this fallback branch, so scoping the disable to provider === "claude"
(the same check already used a few lines above in the sibling
isClaudePassthrough branch) keeps that fix intact while restoring
correct prefixing for every other provider that merely targets
Claude's wire format.
Fixes #13835.
* docs: add changelog fragment for #13856
This commit is contained in:
@@ -0,0 +1 @@
|
||||
- **fix(translator):** Third-party tool names (e.g. GitHub Copilot's own `web_fetch` function tool) are no longer sent unprefixed to Claude-wire-format providers outside genuine first-party Anthropic traffic, fixing a `rejected tool(s): web_fetch` 400 for any `gh/claude-*` model ([#13856](https://github.com/diegosouzapw/OmniRoute/pull/13856)) — thanks @dylanhaskins
|
||||
@@ -2494,8 +2494,21 @@ export async function handleChatCore({
|
||||
// conflicts with Claude OAuth tools, but in the passthrough path the tools
|
||||
// are already in Claude format. Applying the prefix turns "Bash" into
|
||||
// "proxy_Bash", which Claude rejects ("No such tool available: proxy_Bash").
|
||||
//
|
||||
// #618's actual traffic was real Claude Code talking to first-party Anthropic
|
||||
// (provider "claude") reaching this fallback branch instead of the dedicated
|
||||
// Claude Code bridge/passthrough branches above. Scoping the disable to
|
||||
// `provider === "claude"` keeps that fix intact while no longer blanket-applying
|
||||
// it to every other provider that merely targets Claude's wire format — a
|
||||
// third-party provider's own ordinary (non-Claude-native) tool names, e.g.
|
||||
// GitHub Copilot's own client-executed "web_fetch" tool, were passing through
|
||||
// unprefixed here and colliding with Claude's reserved tool namespace, since
|
||||
// they were never "already in Claude format" the way this comment assumes.
|
||||
// See #13835.
|
||||
if (targetFormat === FORMATS.CLAUDE) {
|
||||
translatedBody._disableToolPrefix = true;
|
||||
if (provider === "claude") {
|
||||
translatedBody._disableToolPrefix = true;
|
||||
}
|
||||
normalizeClaudeUpstreamMessages(translatedBody);
|
||||
}
|
||||
|
||||
|
||||
@@ -1832,6 +1832,40 @@ test("chatCore sets Claude tool prefix disabling, strips empty Anthropic text bl
|
||||
["hello"]
|
||||
);
|
||||
});
|
||||
// #13835: a third-party provider's own ordinary tool name (GitHub Copilot's client-executed
|
||||
// "web_fetch" function tool) must still get the proxy_ prefix even though this request lands
|
||||
// in the same general (non-claude-passthrough) branch as the "claude" provider test above —
|
||||
// only genuine first-party Anthropic traffic (provider "claude") should skip prefixing.
|
||||
test("chatCore still prefixes ordinary third-party tool names for non-Anthropic providers targeting Claude", async () => {
|
||||
const { call } = await invokeChatCore({
|
||||
provider: "github",
|
||||
model: "claude-haiku-4.5",
|
||||
endpoint: "/v1/chat/completions",
|
||||
credentials: { apiKey: "gh-key", providerSpecificData: {} },
|
||||
body: {
|
||||
model: "github/claude-haiku-4.5",
|
||||
messages: [{ role: "user", content: "fetch a url" }],
|
||||
tools: [
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "web_fetch",
|
||||
description: "Fetches a URL from the internet.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: { url: { type: "string" } },
|
||||
required: ["url"],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
responseFormat: "claude",
|
||||
});
|
||||
|
||||
assert.equal(call.body.tools[0].name, "proxy_web_fetch");
|
||||
assert.equal(call.body._toolNameMap, undefined);
|
||||
});
|
||||
test("chatCore restores prefixed Claude passthrough tool names in upstream responses", async () => {
|
||||
const { result } = await invokeChatCore({
|
||||
provider: "claude",
|
||||
|
||||
Reference in New Issue
Block a user