fix(sse): enable tool calling for GPT OSS and DeepSeek Reasoner models - #1455
Conversation
Both model families support tool calling but were incorrectly blocked by TOOL_CALLING_UNSUPPORTED_PATTERNS. The nvidia provider's GPT OSS entries also carried a redundant toolCalling field removed here for consistency with other providers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request enables tool calling support for GPT OSS and DeepSeek Reasoner models by removing them from the TOOL_CALLING_UNSUPPORTED_PATTERNS blocklist and updating the provider registry. Corresponding unit tests have been added and updated to reflect these changes. Feedback highlights a potential issue where the tests might be importing a different implementation of modelCapabilities than the one modified, which could lead to test failures. Additionally, it is noted that emptying the unsupported patterns list changes the default behavior for all unknown models to supported, which may require a more granular approach to avoid incorrect reporting for older models.
| assert.equal(modelCapabilities.supportsToolCalling("openai/gpt-oss-120b"), true); | ||
| assert.equal(modelCapabilities.supportsToolCalling("deepseek-reasoner"), true); |
There was a problem hiding this comment.
This test imports modelCapabilities from ../../open-sse/services/modelCapabilities.ts (line 5), but the changes in this PR are applied to src/lib/modelCapabilities.ts.
Unless these two paths point to the same file (e.g., via a symlink), updating these assertions to true will likely cause this test to fail because the underlying file in open-sse/services/ has not been modified to remove the blocklist. Please verify if open-sse/services/modelCapabilities.ts also needs to be updated or if there is a duplicate implementation that should be unified.
There was a problem hiding this comment.
open-sse/services/modelCapabilities.ts is a barrel re-export of src/lib/modelCapabilities.ts:
export {
getResolvedModelCapabilities,
supportsReasoning,
supportsToolCalling,
} from "../../src/lib/modelCapabilities.ts";Both import paths resolve to the same implementation. The test assertions are correct and pass against the modified code.
| import { getSyncedCapability } from "@/lib/modelsDevSync"; | ||
|
|
||
| const TOOL_CALLING_UNSUPPORTED_PATTERNS = ["gpt-oss-120b", "deepseek-reasoner"]; | ||
| const TOOL_CALLING_UNSUPPORTED_PATTERNS: string[] = []; |
There was a problem hiding this comment.
By emptying TOOL_CALLING_UNSUPPORTED_PATTERNS, the heuristicToolCalling function (lines 126-135) will now return true for any non-empty model string that isn't explicitly defined in MODEL_SPECS, the registry, or synced data.
While this unblocks the intended models, it also changes the default behavior for all unknown models to "supported". If there are other older or specialized models that definitely do not support tool calling and are not in the registry, they will now be incorrectly reported as supporting it. Consider if a minimal blocklist should be maintained for such cases.
There was a problem hiding this comment.
The heuristic was already default-true for all unknown models before this PR -- the blocklist only contained these 2 entries. Emptying it removes 2 false positives; it does not change the paradigm.
Models that genuinely do not support tool calling should have toolCalling: false set explicitly in their registry entry or a ModelSpec with supportsTools: false, both of which take priority over the heuristic (resolution layers 1-3). The heuristic at layer 4 is intentionally optimistic as a fallback for models with no capability data.
No other models in the codebase relied on this blocklist for correctness -- all other tool-calling restrictions are handled by explicit registry fields or model specs.
diegosouzapw#1455) Integrated into release/v3.7.0
diegosouzapw#1455) Integrated into release/v3.7.0
Summary
GPT OSS models (gpt-oss-120b, gpt-oss-20b) and DeepSeek Reasoner (deepseek-reasoner / deepseek-r1) all support tool calling, but OmniRoute incorrectly blocks them via
TOOL_CALLING_UNSUPPORTED_PATTERNSinsrc/lib/modelCapabilities.ts.The
heuristicToolCalling()function is the fallback when no explicitsupportsToolsvalue exists in the static model spec, provider registry, or models.dev sync data. It returnstruefor any model not matched byTOOL_CALLING_UNSUPPORTED_PATTERNS. Bothgpt-oss-120banddeepseek-reasonerare in this blocklist, but both models support tool calling -- confirmed by live API testing with tool-bearing requests.The
.includes()substring match also meansgpt-oss-120bblocks any model ID containing that string across all providers, and the nvidia provider's GPT OSS entries carry a redundant explicittoolCallingfield that no other provider uses for these models.What changed
src/lib/modelCapabilities.ts: EmptiedTOOL_CALLING_UNSUPPORTED_PATTERNS(removedgpt-oss-120banddeepseek-reasoner)open-sse/config/providerRegistry.ts: Removed thetoolCallingfield from 3 nvidia GPT OSS entries for consistency with other providerstests/unit/model-capabilities-registry.test.ts: Added test case verifying tool calling resolves correctly for GPT OSS and DeepSeek Reasoner modelstests/unit/services-branch-hardening.test.ts: Updated existing denylist assertions to match the new behaviourTesting
supportsToolCalling()for GPT OSS (bare and provider-prefixed IDs), DeepSeek Reasoner, and full capability resolution viagetResolvedModelCapabilities()nvidia/gpt-oss-120bandopenrouter/deepseek-r1both returntool_callsin responses when given tool definitionsPost-Deploy Monitoring & Validation
No additional operational monitoring required: this is a configuration-level change that unblocks already-supported model capabilities. The heuristic fallback is the same code path used by all other models without explicit tool calling overrides.