Repository navigation
fix(sse): bypass web-search fallback on Claude passthrough - #2960
Conversation
The web-search fallback rewrites a built-in web_search tool into the OmniRoute-fulfilled omniroute_web_search function for providers that cannot run web search natively. Codex (nativeCodexPassthrough) and Gemini (target format) were explicitly bypassed, but the Claude -> Claude passthrough was not. It was only protected incidentally, because Anthropic's versioned tool type (web_search_20250305) happens to be absent from the exact-match matcher set — a bare or future-renamed type would have started getting rewritten. Add an explicit, symmetric bypass for sourceFormat === CLAUDE && targetFormat === CLAUDE so the native Anthropic web search tool is forwarded untouched to the upstream (e.g. a Claude subscription driven by Claude Code), regardless of the tool's exact type string. The condition is narrowed to source AND target Claude: an OpenAI-format client targeting a Claude provider sends a non-native tool that must still be converted. Tests (folded into the existing web-search-fallback-format suite): predicate coverage for all three native bypasses (Codex/Gemini/Claude) plus negative cases (OpenAI->OpenAI, OpenAI->Claude, Claude->OpenAI), and end-to-end body assertions that the native Claude tool (versioned and bare) and the Codex built-in tool are forwarded verbatim.
There was a problem hiding this comment.
Code Review
This pull request introduces a Claude-to-Claude native web search bypass in supportsNativeWebSearchFallbackBypass to forward native Claude tools untouched, and adds comprehensive unit tests covering the new bypass logic. The review feedback suggests improving type safety in the tests by replacing an explicit 'any' type assertion with a more specific type shape to avoid linter warnings.
| assert.equal(fallback.enabled, true); | ||
| assert.equal(fallback.toolName, OMNIROUTE_WEB_SEARCH_FALLBACK_TOOL_NAME); | ||
| assert.equal(fallback.convertedToolCount, 1); | ||
| const tools = (body.tools as Record<string, any>[]) || []; |
There was a problem hiding this comment.
Using any triggers the @typescript-eslint/no-explicit-any linter warning. We can replace Record<string, any>[] with a more specific, type-safe shape that avoids any while still allowing direct property access to function and name.
const tools = (body.tools as Array<{ function?: { name?: string }; name?: string }>) || [];
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Files Reviewed (2 files)
Inline Comments (0)No inline issues flagged. Other Observations
Reviewed by step-3.7-flash-20260528 · 1,016,378 tokens |
|
Thank you for your contribution! This PR has been reviewed and integrated into the upcoming |
187bc50
into
cheaper-inference:release/v3.8.8
…env-doc fixes - bump package.json / open-sse / electron / openapi / llm.txt to 3.8.8 - restructure CHANGELOG: Unreleased -> [3.8.8], dedup broken Notion/MCP block (was 12x) - add every PR since v3.8.7 that was missing: Quota Share Engine (#2859/#3022/#3032), page redesigns (#2827/#2839/#2847/#2849/#2869/#2873), and fixes #2960/#2973/#2984/ #3021/#3029/#3031/#3035/#3036/#3037/#3039/#3043/#3028; folded #2978/#2988/#3041 - insert [3.8.8] section into all 41 i18n CHANGELOGs + sync llm.txt mirrors - document OMNIROUTE_PLUGINS_ALLOW_EXEC in .env.example + ENVIRONMENT.md (env-doc-sync gap)
…heaper-inference#2960) Integrated into release/v3.8.8
…env-doc fixes - bump package.json / open-sse / electron / openapi / llm.txt to 3.8.8 - restructure CHANGELOG: Unreleased -> [3.8.8], dedup broken Notion/MCP block (was 12x) - add every PR since v3.8.7 that was missing: Quota Share Engine (cheaper-inference#2859/cheaper-inference#3022/cheaper-inference#3032), page redesigns (cheaper-inference#2827/cheaper-inference#2839/cheaper-inference#2847/cheaper-inference#2849/cheaper-inference#2869/cheaper-inference#2873), and fixes cheaper-inference#2960/cheaper-inference#2973/cheaper-inference#2984/ cheaper-inference#3021/cheaper-inference#3029/cheaper-inference#3031/cheaper-inference#3035/cheaper-inference#3036/cheaper-inference#3037/cheaper-inference#3039/cheaper-inference#3043/cheaper-inference#3028; folded cheaper-inference#2978/cheaper-inference#2988/cheaper-inference#3041 - insert [3.8.8] section into all 41 i18n CHANGELOGs + sync llm.txt mirrors - document OMNIROUTE_PLUGINS_ALLOW_EXEC in .env.example + ENVIRONMENT.md (env-doc-sync gap)
…heaper-inference#2960) Integrated into release/v3.8.8
…env-doc fixes - bump package.json / open-sse / electron / openapi / llm.txt to 3.8.8 - restructure CHANGELOG: Unreleased -> [3.8.8], dedup broken Notion/MCP block (was 12x) - add every PR since v3.8.7 that was missing: Quota Share Engine (cheaper-inference#2859/cheaper-inference#3022/cheaper-inference#3032), page redesigns (cheaper-inference#2827/cheaper-inference#2839/cheaper-inference#2847/cheaper-inference#2849/cheaper-inference#2869/cheaper-inference#2873), and fixes cheaper-inference#2960/cheaper-inference#2973/cheaper-inference#2984/ cheaper-inference#3021/cheaper-inference#3029/cheaper-inference#3031/cheaper-inference#3035/cheaper-inference#3036/cheaper-inference#3037/cheaper-inference#3039/cheaper-inference#3043/cheaper-inference#3028; folded cheaper-inference#2978/cheaper-inference#2988/cheaper-inference#3041 - insert [3.8.8] section into all 41 i18n CHANGELOGs + sync llm.txt mirrors - document OMNIROUTE_PLUGINS_ALLOW_EXEC in .env.example + ENVIRONMENT.md (env-doc-sync gap)
…heaper-inference#2960) Integrated into release/v3.8.8
…env-doc fixes - bump package.json / open-sse / electron / openapi / llm.txt to 3.8.8 - restructure CHANGELOG: Unreleased -> [3.8.8], dedup broken Notion/MCP block (was 12x) - add every PR since v3.8.7 that was missing: Quota Share Engine (cheaper-inference#2859/cheaper-inference#3022/cheaper-inference#3032), page redesigns (cheaper-inference#2827/cheaper-inference#2839/cheaper-inference#2847/cheaper-inference#2849/cheaper-inference#2869/cheaper-inference#2873), and fixes cheaper-inference#2960/cheaper-inference#2973/cheaper-inference#2984/ cheaper-inference#3021/cheaper-inference#3029/cheaper-inference#3031/cheaper-inference#3035/cheaper-inference#3036/cheaper-inference#3037/cheaper-inference#3039/cheaper-inference#3043/cheaper-inference#3028; folded cheaper-inference#2978/cheaper-inference#2988/cheaper-inference#3041 - insert [3.8.8] section into all 41 i18n CHANGELOGs + sync llm.txt mirrors - document OMNIROUTE_PLUGINS_ALLOW_EXEC in .env.example + ENVIRONMENT.md (env-doc-sync gap)
Summary
This PR makes the web-search fallback bypass explicit for native Claude → Claude passthrough requests.
The web-search fallback rewrites built-in web search tools into OmniRoute's
omniroute_web_searchfunction for providers that cannot execute web search natively. Codex native passthrough and Gemini targets were already bypassed, but Claude → Claude passthrough was only protected indirectly because Anthropic's current versioned tool type,web_search_20250305, was not part of the exact-match fallback matcher.This change adds an explicit bypass when both
sourceFormatandtargetFormatare Claude, so native Anthropic web-search tools are forwarded untouched to the Claude upstream.Changes
supportsNativeWebSearchFallbackBypass().web_search_20250305forwardingweb_searchforwardingweb_search_previewforwardingWhy
Claude Code / Anthropic Messages passthrough requests may include native Anthropic web-search tools. These should be handled by the Claude upstream, not rewritten into OmniRoute's fallback function.
The new bypass is intentionally narrow:
sourceFormat === "claude"targetFormat === "claude"This avoids breaking non-native requests such as OpenAI-format clients targeting Claude, where the tool still needs to be converted.
Validation
Focused regression tests pass:
Focused lint completed with no errors:
Note: lint reports one warning for an existing explicit
anyin the committed test file: