Skip to content

fix(sse): enable tool calling for GPT OSS and DeepSeek Reasoner models - #1455

Merged
diegosouzapw merged 1 commit into
diegosouzapw:release/v3.7.0from
Tasogarre:fix/gpt-oss-tool-calling
Apr 21, 2026
Merged

diegosouzapw merged 1 commit into
diegosouzapw:release/v3.7.0from
Tasogarre:fix/gpt-oss-tool-calling

Conversation

@Tasogarre

Copy link
Copy Markdown
Contributor

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_PATTERNS in src/lib/modelCapabilities.ts.

The heuristicToolCalling() function is the fallback when no explicit supportsTools value exists in the static model spec, provider registry, or models.dev sync data. It returns true for any model not matched by TOOL_CALLING_UNSUPPORTED_PATTERNS. Both gpt-oss-120b and deepseek-reasoner are in this blocklist, but both models support tool calling -- confirmed by live API testing with tool-bearing requests.

The .includes() substring match also means gpt-oss-120b blocks any model ID containing that string across all providers, and the nvidia provider's GPT OSS entries carry a redundant explicit toolCalling field that no other provider uses for these models.

What changed

  • src/lib/modelCapabilities.ts: Emptied TOOL_CALLING_UNSUPPORTED_PATTERNS (removed gpt-oss-120b and deepseek-reasoner)
  • open-sse/config/providerRegistry.ts: Removed the toolCalling field from 3 nvidia GPT OSS entries for consistency with other providers
  • tests/unit/model-capabilities-registry.test.ts: Added test case verifying tool calling resolves correctly for GPT OSS and DeepSeek Reasoner models
  • tests/unit/services-branch-hardening.test.ts: Updated existing denylist assertions to match the new behaviour

Testing

  • Added unit test covering supportsToolCalling() for GPT OSS (bare and provider-prefixed IDs), DeepSeek Reasoner, and full capability resolution via getResolvedModelCapabilities()
  • Updated existing branch-hardening test assertions
  • Validated end-to-end: nvidia/gpt-oss-120b and openrouter/deepseek-r1 both return tool_calls in responses when given tool definitions

Post-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.

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>
@Tasogarre
Tasogarre requested a review from diegosouzapw as a code owner April 20, 2026 15:22

@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 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.

Comment on lines +82 to +83
assert.equal(modelCapabilities.supportsToolCalling("openai/gpt-oss-120b"), true);
assert.equal(modelCapabilities.supportsToolCalling("deepseek-reasoner"), true);

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.

high

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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[] = [];

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.

medium

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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
diegosouzapw changed the base branch from main to release/v3.7.0 April 21, 2026 07:02
@diegosouzapw
diegosouzapw merged commit 496114a into diegosouzapw:release/v3.7.0 Apr 21, 2026
2 checks passed
@diegosouzapw diegosouzapw mentioned this pull request Apr 22, 2026
Poid-ZA pushed a commit to Poid-ZA/OmniRoute that referenced this pull request Aug 5, 2026
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 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.

2 participants