Kaynağa Gözat

fix(litellm): merge default model info with router models for NTC support (#10187)

* feat(types): add defaultToolProtocol: native to providers

- Added supportsNativeTools: true and defaultToolProtocol: native to all chutes models
- Added defaultToolProtocol: native to moonshot models (already had supportsNativeTools)
- Added defaultToolProtocol: native to litellm default model (already had supportsNativeTools)
- Added defaultToolProtocol: native to minimax models (already had supportsNativeTools)

This enables native tool calling by default for these providers, reducing
the number of users falling back to XML tool protocol unnecessarily.

* fix(litellm): merge only native tool defaults with router models

Only merges supportsNativeTools and defaultToolProtocol from litellmDefaultModelInfo,
not prices or other model-specific info that could be incorrect for different models.
Daniel 1 hafta önce
ebeveyn
işleme
d92d729219

+ 80 - 0
packages/types/src/providers/chutes.ts

@@ -51,6 +51,8 @@ export const chutesModels = {
 		contextWindow: 163840,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "DeepSeek R1 0528 model.",
@@ -60,6 +62,8 @@ export const chutesModels = {
 		contextWindow: 163840,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "DeepSeek R1 model.",
@@ -69,6 +73,8 @@ export const chutesModels = {
 		contextWindow: 163840,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "DeepSeek V3 model.",
@@ -78,6 +84,8 @@ export const chutesModels = {
 		contextWindow: 163840,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "DeepSeek V3.1 model.",
@@ -87,6 +95,8 @@ export const chutesModels = {
 		contextWindow: 163840,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0.23,
 		outputPrice: 0.9,
 		description:
@@ -97,6 +107,8 @@ export const chutesModels = {
 		contextWindow: 163840,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 1.0,
 		outputPrice: 3.0,
 		description:
@@ -107,6 +119,8 @@ export const chutesModels = {
 		contextWindow: 163840,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0.25,
 		outputPrice: 0.35,
 		description:
@@ -117,6 +131,8 @@ export const chutesModels = {
 		contextWindow: 131072, // From Groq
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "Unsloth Llama 3.3 70B Instruct model.",
@@ -126,6 +142,8 @@ export const chutesModels = {
 		contextWindow: 512000,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "ChutesAI Llama 4 Scout 17B Instruct model, 512K context.",
@@ -135,6 +153,8 @@ export const chutesModels = {
 		contextWindow: 128000,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "Unsloth Mistral Nemo Instruct model.",
@@ -144,6 +164,8 @@ export const chutesModels = {
 		contextWindow: 131072,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "Unsloth Gemma 3 12B IT model.",
@@ -153,6 +175,8 @@ export const chutesModels = {
 		contextWindow: 131072,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "Nous DeepHermes 3 Llama 3 8B Preview model.",
@@ -162,6 +186,8 @@ export const chutesModels = {
 		contextWindow: 131072,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "Unsloth Gemma 3 4B IT model.",
@@ -171,6 +197,8 @@ export const chutesModels = {
 		contextWindow: 131072,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "Nvidia Llama 3.3 Nemotron Super 49B model.",
@@ -180,6 +208,8 @@ export const chutesModels = {
 		contextWindow: 131072,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "Nvidia Llama 3.1 Nemotron Ultra 253B model.",
@@ -189,6 +219,8 @@ export const chutesModels = {
 		contextWindow: 256000,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "ChutesAI Llama 4 Maverick 17B Instruct FP8 model.",
@@ -198,6 +230,8 @@ export const chutesModels = {
 		contextWindow: 163840,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "DeepSeek V3 Base model.",
@@ -207,6 +241,8 @@ export const chutesModels = {
 		contextWindow: 163840,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "DeepSeek R1 Zero model.",
@@ -216,6 +252,8 @@ export const chutesModels = {
 		contextWindow: 163840,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "DeepSeek V3 (0324) model.",
@@ -225,6 +263,8 @@ export const chutesModels = {
 		contextWindow: 262144,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "Qwen3 235B A22B Instruct 2507 model with 262K context window.",
@@ -234,6 +274,8 @@ export const chutesModels = {
 		contextWindow: 40960,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "Qwen3 235B A22B model.",
@@ -243,6 +285,8 @@ export const chutesModels = {
 		contextWindow: 40960,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "Qwen3 32B model.",
@@ -252,6 +296,8 @@ export const chutesModels = {
 		contextWindow: 40960,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "Qwen3 30B A3B model.",
@@ -261,6 +307,8 @@ export const chutesModels = {
 		contextWindow: 40960,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "Qwen3 14B model.",
@@ -270,6 +318,8 @@ export const chutesModels = {
 		contextWindow: 40960,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "Qwen3 8B model.",
@@ -279,6 +329,8 @@ export const chutesModels = {
 		contextWindow: 163840,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "Microsoft MAI-DS-R1 FP8 model.",
@@ -288,6 +340,8 @@ export const chutesModels = {
 		contextWindow: 163840,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "TNGTech DeepSeek R1T Chimera model.",
@@ -297,6 +351,8 @@ export const chutesModels = {
 		contextWindow: 151329,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description:
@@ -307,6 +363,8 @@ export const chutesModels = {
 		contextWindow: 131072,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description:
@@ -317,6 +375,8 @@ export const chutesModels = {
 		contextWindow: 131072,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 1,
 		outputPrice: 3,
 		description: "GLM-4.5-turbo model with 128K token context window, optimized for fast inference.",
@@ -326,6 +386,8 @@ export const chutesModels = {
 		contextWindow: 202752,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description:
@@ -336,6 +398,8 @@ export const chutesModels = {
 		contextWindow: 202752,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 1.15,
 		outputPrice: 3.25,
 		description: "GLM-4.6-turbo model with 200K-token context window, optimized for fast inference.",
@@ -345,6 +409,8 @@ export const chutesModels = {
 		contextWindow: 128000,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description:
@@ -355,6 +421,8 @@ export const chutesModels = {
 		contextWindow: 262144,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "Qwen3 Coder 480B A35B Instruct FP8 model, optimized for coding tasks.",
@@ -364,6 +432,8 @@ export const chutesModels = {
 		contextWindow: 75000,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0.1481,
 		outputPrice: 0.5926,
 		description: "Moonshot AI Kimi K2 Instruct model with 75k context window.",
@@ -373,6 +443,8 @@ export const chutesModels = {
 		contextWindow: 262144,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0.1999,
 		outputPrice: 0.8001,
 		description: "Moonshot AI Kimi K2 Instruct 0905 model with 256k context window.",
@@ -382,6 +454,8 @@ export const chutesModels = {
 		contextWindow: 262144,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0.077968332,
 		outputPrice: 0.31202496,
 		description: "Qwen3 235B A22B Thinking 2507 model with 262K context window.",
@@ -391,6 +465,8 @@ export const chutesModels = {
 		contextWindow: 131072,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description:
@@ -401,6 +477,8 @@ export const chutesModels = {
 		contextWindow: 131072,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0,
 		outputPrice: 0,
 		description:
@@ -411,6 +489,8 @@ export const chutesModels = {
 		contextWindow: 262144,
 		supportsImages: true,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0.16,
 		outputPrice: 0.65,
 		description:

+ 1 - 0
packages/types/src/providers/lite-llm.ts

@@ -9,6 +9,7 @@ export const litellmDefaultModelInfo: ModelInfo = {
 	supportsImages: true,
 	supportsPromptCache: true,
 	supportsNativeTools: true,
+	defaultToolProtocol: "native",
 	inputPrice: 3.0,
 	outputPrice: 15.0,
 	cacheWritesPrice: 3.75,

+ 2 - 0
packages/types/src/providers/minimax.ts

@@ -14,6 +14,7 @@ export const minimaxModels = {
 		supportsImages: false,
 		supportsPromptCache: true,
 		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		preserveReasoning: true,
 		inputPrice: 0.3,
 		outputPrice: 1.2,
@@ -28,6 +29,7 @@ export const minimaxModels = {
 		supportsImages: false,
 		supportsPromptCache: true,
 		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		preserveReasoning: true,
 		inputPrice: 0.3,
 		outputPrice: 1.2,

+ 4 - 0
packages/types/src/providers/moonshot.ts

@@ -12,6 +12,7 @@ export const moonshotModels = {
 		supportsImages: false,
 		supportsPromptCache: true,
 		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0.6, // $0.60 per million tokens (cache miss)
 		outputPrice: 2.5, // $2.50 per million tokens
 		cacheWritesPrice: 0, // $0 per million tokens (cache miss)
@@ -24,6 +25,7 @@ export const moonshotModels = {
 		supportsImages: false,
 		supportsPromptCache: true,
 		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0.6,
 		outputPrice: 2.5,
 		cacheReadsPrice: 0.15,
@@ -36,6 +38,7 @@ export const moonshotModels = {
 		supportsImages: false,
 		supportsPromptCache: true,
 		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 2.4, // $2.40 per million tokens (cache miss)
 		outputPrice: 10, // $10.00 per million tokens
 		cacheWritesPrice: 0, // $0 per million tokens (cache miss)
@@ -48,6 +51,7 @@ export const moonshotModels = {
 		supportsImages: false, // Text-only (no image/vision support)
 		supportsPromptCache: true,
 		supportsNativeTools: true,
+		defaultToolProtocol: "native",
 		inputPrice: 0.6, // $0.60 per million tokens (cache miss)
 		outputPrice: 2.5, // $2.50 per million tokens
 		cacheWritesPrice: 0, // $0 per million tokens (cache miss)

+ 9 - 3
webview-ui/src/components/ui/hooks/__tests__/useSelectedModel.spec.ts

@@ -616,7 +616,7 @@ describe("useSelectedModel", () => {
 			expect(result.current.info?.supportsNativeTools).toBe(true)
 		})
 
-		it("should use model info from routerModels when model exists", () => {
+		it("should merge only native tool defaults with routerModels when model exists", () => {
 			const customModelInfo: ModelInfo = {
 				maxTokens: 16384,
 				contextWindow: 128000,
@@ -650,9 +650,15 @@ describe("useSelectedModel", () => {
 
 			expect(result.current.provider).toBe("litellm")
 			expect(result.current.id).toBe("custom-model")
-			// Should use the model info from routerModels, not the fallback
-			expect(result.current.info).toEqual(customModelInfo)
+			// Should only merge native tool defaults, not prices or other model-specific info
+			// Router model values override the defaults
+			const nativeToolDefaults = {
+				supportsNativeTools: litellmDefaultModelInfo.supportsNativeTools,
+				defaultToolProtocol: litellmDefaultModelInfo.defaultToolProtocol,
+			}
+			expect(result.current.info).toEqual({ ...nativeToolDefaults, ...customModelInfo })
 			expect(result.current.info?.supportsNativeTools).toBe(true)
+			expect(result.current.info?.defaultToolProtocol).toBe("native")
 		})
 	})
 })

+ 7 - 1
webview-ui/src/components/ui/hooks/useSelectedModel.ts

@@ -166,7 +166,13 @@ function getSelectedModel({
 		}
 		case "litellm": {
 			const id = getValidatedModelId(apiConfiguration.litellmModelId, routerModels.litellm, defaultModelId)
-			const info = routerModels.litellm?.[id] ?? litellmDefaultModelInfo
+			const routerInfo = routerModels.litellm?.[id]
+			// Only merge native tool call defaults, not prices or other model-specific info
+			const nativeToolDefaults = {
+				supportsNativeTools: litellmDefaultModelInfo.supportsNativeTools,
+				defaultToolProtocol: litellmDefaultModelInfo.defaultToolProtocol,
+			}
+			const info = routerInfo ? { ...nativeToolDefaults, ...routerInfo } : litellmDefaultModelInfo
 			return { id, info }
 		}
 		case "xai": {