From 73d3e9ffd0d2412198b8659c0d80f1d6c58fad25 Mon Sep 17 00:00:00 2001 From: Marcus Bearden Date: Mon, 20 Apr 2026 16:14:34 +0100 Subject: [PATCH] fix(sse): enable tool calling for GPT OSS and DeepSeek Reasoner models 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 --- open-sse/config/providerRegistry.ts | 6 +++--- src/lib/modelCapabilities.ts | 2 +- tests/unit/model-capabilities-registry.test.ts | 17 +++++++++++++++++ tests/unit/services-branch-hardening.test.ts | 4 ++-- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/open-sse/config/providerRegistry.ts b/open-sse/config/providerRegistry.ts index b48b3dc9d96..87a8d638c55 100644 --- a/open-sse/config/providerRegistry.ts +++ b/open-sse/config/providerRegistry.ts @@ -1199,9 +1199,9 @@ export const REGISTRY: Record = { authType: "apikey", authHeader: "bearer", models: [ - { id: "gpt-oss-120b", name: "GPT OSS 120B", toolCalling: false }, - { id: "openai/gpt-oss-120b", name: "GPT OSS 120B (OpenAI Prefix)", toolCalling: false }, - { id: "openai/gpt-oss-20b", name: "GPT OSS 20B", toolCalling: false }, + { id: "gpt-oss-120b", name: "GPT OSS 120B" }, + { id: "openai/gpt-oss-120b", name: "GPT OSS 120B (OpenAI Prefix)" }, + { id: "openai/gpt-oss-20b", name: "GPT OSS 20B" }, { id: "meta/llama-3.3-70b-instruct", name: "Llama 3.3 70B" }, { id: "nvidia/llama-3.3-70b-instruct", name: "Llama 3.3 70B (NVIDIA Prefix)" }, { id: "meta/llama-4-maverick-17b-128e-instruct", name: "Llama 4 Maverick" }, diff --git a/src/lib/modelCapabilities.ts b/src/lib/modelCapabilities.ts index 7ee03545509..45f1aa7c3db 100644 --- a/src/lib/modelCapabilities.ts +++ b/src/lib/modelCapabilities.ts @@ -6,7 +6,7 @@ import { parseModel, resolveCanonicalProviderModel } from "@omniroute/open-sse/s import { MODEL_SPECS, getModelSpec, type ModelSpec } from "@/shared/constants/modelSpecs"; import { getSyncedCapability } from "@/lib/modelsDevSync"; -const TOOL_CALLING_UNSUPPORTED_PATTERNS = ["gpt-oss-120b", "deepseek-reasoner"]; +const TOOL_CALLING_UNSUPPORTED_PATTERNS: string[] = []; const REASONING_UNSUPPORTED_PATTERNS = [ "antigravity/claude-sonnet-4-6", "antigravity/claude-sonnet-4-5", diff --git a/tests/unit/model-capabilities-registry.test.ts b/tests/unit/model-capabilities-registry.test.ts index d862cc54bcb..1dbc1bd240a 100644 --- a/tests/unit/model-capabilities-registry.test.ts +++ b/tests/unit/model-capabilities-registry.test.ts @@ -103,3 +103,20 @@ test("canonical model capability resolver merges models.dev data and keeps stati 32768 ); }); + +test("GPT OSS and DeepSeek Reasoner models support tool calling", () => { + // GPT OSS models should not be blocked by the heuristic + assert.equal(modelCapabilities.supportsToolCalling("nvidia/gpt-oss-120b"), true); + assert.equal(modelCapabilities.supportsToolCalling("gpt-oss-120b"), true); + assert.equal(modelCapabilities.supportsToolCalling("openai/gpt-oss-20b"), true); + + // DeepSeek Reasoner supports tool calling + assert.equal(modelCapabilities.supportsToolCalling("deepseek-reasoner"), true); + assert.equal(modelCapabilities.supportsToolCalling("deepseek/deepseek-r1"), true); + + // Full capability resolution + const gptOss = modelCapabilities.getResolvedModelCapabilities("nvidia/gpt-oss-120b"); + assert.equal(gptOss.toolCalling, true); + const deepseek = modelCapabilities.getResolvedModelCapabilities("deepseek/deepseek-reasoner"); + assert.equal(deepseek.toolCalling, true); +}); diff --git a/tests/unit/services-branch-hardening.test.ts b/tests/unit/services-branch-hardening.test.ts index 16467867d4d..6adef33e1f9 100644 --- a/tests/unit/services-branch-hardening.test.ts +++ b/tests/unit/services-branch-hardening.test.ts @@ -79,8 +79,8 @@ test("model capability helpers cover denylist, empty input and default-safe path assert.equal(modelCapabilities.supportsReasoning("missing-provider/tool"), true); assert.equal(modelCapabilities.supportsToolCalling(""), false); - assert.equal(modelCapabilities.supportsToolCalling("openai/gpt-oss-120b"), false); - assert.equal(modelCapabilities.supportsToolCalling("deepseek-reasoner"), false); + assert.equal(modelCapabilities.supportsToolCalling("openai/gpt-oss-120b"), true); + assert.equal(modelCapabilities.supportsToolCalling("deepseek-reasoner"), true); assert.equal( modelCapabilities.supportsToolCalling("openai/nonexistent-default-safe-model"), true