Răsfoiți Sursa

feat: add native tools support for OpenAI-compatible providers (#9676)

Co-authored-by: Matt Rubens <[email protected]>
Daniel 1 lună în urmă
părinte
comite
59ee1c9d04

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

@@ -31,6 +31,7 @@ export const featherlessModels = {
 		contextWindow: 32678,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "Kimi K2 Instruct model.",
@@ -49,6 +50,7 @@ export const featherlessModels = {
 		contextWindow: 32678,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		inputPrice: 0,
 		outputPrice: 0,
 		description: "Qwen3 Coder 480B A35B Instruct model.",

+ 13 - 0
packages/types/src/providers/fireworks.ts

@@ -23,6 +23,7 @@ export const fireworksModels = {
 		contextWindow: 262144,
 		supportsImages: false,
 		supportsPromptCache: true,
+		supportsNativeTools: true,
 		inputPrice: 0.6,
 		outputPrice: 2.5,
 		cacheReadsPrice: 0.15,
@@ -34,6 +35,7 @@ export const fireworksModels = {
 		contextWindow: 128000,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		inputPrice: 0.6,
 		outputPrice: 2.5,
 		description:
@@ -44,6 +46,7 @@ export const fireworksModels = {
 		contextWindow: 204800,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		inputPrice: 0.3,
 		outputPrice: 1.2,
 		description:
@@ -54,6 +57,7 @@ export const fireworksModels = {
 		contextWindow: 256000,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		inputPrice: 0.22,
 		outputPrice: 0.88,
 		description: "Latest Qwen3 thinking model, competitive against the best closed source models in Jul 2025.",
@@ -63,6 +67,7 @@ export const fireworksModels = {
 		contextWindow: 256000,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		inputPrice: 0.45,
 		outputPrice: 1.8,
 		description: "Qwen3's most agentic code model to date.",
@@ -72,6 +77,7 @@ export const fireworksModels = {
 		contextWindow: 160000,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		inputPrice: 3,
 		outputPrice: 8,
 		description:
@@ -82,6 +88,7 @@ export const fireworksModels = {
 		contextWindow: 128000,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		inputPrice: 0.9,
 		outputPrice: 0.9,
 		description:
@@ -92,6 +99,7 @@ export const fireworksModels = {
 		contextWindow: 163840,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		inputPrice: 0.56,
 		outputPrice: 1.68,
 		description:
@@ -102,6 +110,7 @@ export const fireworksModels = {
 		contextWindow: 128000,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		inputPrice: 0.55,
 		outputPrice: 2.19,
 		description:
@@ -112,6 +121,7 @@ export const fireworksModels = {
 		contextWindow: 128000,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		inputPrice: 0.55,
 		outputPrice: 2.19,
 		description:
@@ -122,6 +132,7 @@ export const fireworksModels = {
 		contextWindow: 198000,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		inputPrice: 0.55,
 		outputPrice: 2.19,
 		description:
@@ -132,6 +143,7 @@ export const fireworksModels = {
 		contextWindow: 128000,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		inputPrice: 0.07,
 		outputPrice: 0.3,
 		description:
@@ -142,6 +154,7 @@ export const fireworksModels = {
 		contextWindow: 128000,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		inputPrice: 0.15,
 		outputPrice: 0.6,
 		description:

+ 4 - 0
packages/types/src/providers/io-intelligence.ts

@@ -18,6 +18,7 @@ export const ioIntelligenceModels = {
 		contextWindow: 128000,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		description: "DeepSeek R1 reasoning model",
 	},
 	"meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8": {
@@ -25,6 +26,7 @@ export const ioIntelligenceModels = {
 		contextWindow: 430000,
 		supportsImages: true,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		description: "Llama 4 Maverick 17B model",
 	},
 	"Intel/Qwen3-Coder-480B-A35B-Instruct-int4-mixed-ar": {
@@ -32,6 +34,7 @@ export const ioIntelligenceModels = {
 		contextWindow: 106000,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		description: "Qwen3 Coder 480B specialized for coding",
 	},
 	"openai/gpt-oss-120b": {
@@ -39,6 +42,7 @@ export const ioIntelligenceModels = {
 		contextWindow: 131072,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		description: "OpenAI GPT-OSS 120B model",
 	},
 } as const satisfies Record<string, ModelInfo>

+ 8 - 0
packages/types/src/providers/sambanova.ts

@@ -21,6 +21,7 @@ export const sambaNovaModels = {
 		contextWindow: 16384,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		inputPrice: 0.1,
 		outputPrice: 0.2,
 		description: "Meta Llama 3.1 8B Instruct model with 16K context window.",
@@ -30,6 +31,7 @@ export const sambaNovaModels = {
 		contextWindow: 131072,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		inputPrice: 0.6,
 		outputPrice: 1.2,
 		description: "Meta Llama 3.3 70B Instruct model with 128K context window.",
@@ -40,6 +42,7 @@ export const sambaNovaModels = {
 		supportsImages: false,
 		supportsPromptCache: false,
 		supportsReasoningBudget: true,
+		supportsNativeTools: true,
 		inputPrice: 5.0,
 		outputPrice: 7.0,
 		description: "DeepSeek R1 reasoning model with 32K context window.",
@@ -49,6 +52,7 @@ export const sambaNovaModels = {
 		contextWindow: 32768,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		inputPrice: 3.0,
 		outputPrice: 4.5,
 		description: "DeepSeek V3 model with 32K context window.",
@@ -58,6 +62,7 @@ export const sambaNovaModels = {
 		contextWindow: 32768,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		inputPrice: 3.0,
 		outputPrice: 4.5,
 		description: "DeepSeek V3.1 model with 32K context window.",
@@ -76,6 +81,7 @@ export const sambaNovaModels = {
 		contextWindow: 131072,
 		supportsImages: true,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		inputPrice: 0.63,
 		outputPrice: 1.8,
 		description: "Meta Llama 4 Maverick 17B 128E Instruct model with 128K context window.",
@@ -94,6 +100,7 @@ export const sambaNovaModels = {
 		contextWindow: 8192,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		inputPrice: 0.4,
 		outputPrice: 0.8,
 		description: "Alibaba Qwen 3 32B model with 8K context window.",
@@ -103,6 +110,7 @@ export const sambaNovaModels = {
 		contextWindow: 131072,
 		supportsImages: false,
 		supportsPromptCache: false,
+		supportsNativeTools: true,
 		inputPrice: 0.22,
 		outputPrice: 0.59,
 		description: "OpenAI gpt oss 120b model with 128k context window.",

+ 2 - 0
src/api/providers/__tests__/io-intelligence.spec.ts

@@ -255,6 +255,7 @@ describe("IOIntelligenceHandler", () => {
 			description: "Llama 4 Maverick 17B model",
 			supportsImages: true,
 			supportsPromptCache: false,
+			supportsNativeTools: true,
 		})
 	})
 
@@ -271,6 +272,7 @@ describe("IOIntelligenceHandler", () => {
 			description: "Llama 4 Maverick 17B model",
 			supportsImages: true,
 			supportsPromptCache: false,
+			supportsNativeTools: true,
 		})
 	})
 

+ 7 - 2
src/api/providers/featherless.ts

@@ -13,6 +13,7 @@ import { convertToR1Format } from "../transform/r1-format"
 import { convertToOpenAiMessages } from "../transform/openai-format"
 import { ApiStream } from "../transform/stream"
 
+import type { ApiHandlerCreateMessageMetadata } from "../index"
 import { BaseOpenAiCompatibleProvider } from "./base-openai-compatible-provider"
 
 export class FeatherlessHandler extends BaseOpenAiCompatibleProvider<FeatherlessModelId> {
@@ -49,7 +50,11 @@ export class FeatherlessHandler extends BaseOpenAiCompatibleProvider<Featherless
 		}
 	}
 
-	override async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
+	override async *createMessage(
+		systemPrompt: string,
+		messages: Anthropic.Messages.MessageParam[],
+		metadata?: ApiHandlerCreateMessageMetadata,
+	): ApiStream {
 		const model = this.getModel()
 
 		if (model.id.includes("DeepSeek-R1")) {
@@ -90,7 +95,7 @@ export class FeatherlessHandler extends BaseOpenAiCompatibleProvider<Featherless
 				yield processedChunk
 			}
 		} else {
-			yield* super.createMessage(systemPrompt, messages)
+			yield* super.createMessage(systemPrompt, messages, metadata)
 		}
 	}