fix(llm): expand compatible provider bridge

This commit is contained in:
Kit Langton
2026-05-03 13:11:45 -04:00
parent 6224ce84fd
commit fea96490e3
5 changed files with 77 additions and 15 deletions
@@ -11,7 +11,12 @@ export const families = {
deepinfra: { provider: "deepinfra", baseURL: "https://api.deepinfra.com/v1/openai" },
deepseek: { provider: "deepseek", baseURL: "https://api.deepseek.com/v1" },
fireworks: { provider: "fireworks", baseURL: "https://api.fireworks.ai/inference/v1" },
groq: { provider: "groq", baseURL: "https://api.groq.com/openai/v1" },
mistral: { provider: "mistral", baseURL: "https://api.mistral.ai/v1" },
openrouter: { provider: "openrouter", baseURL: "https://openrouter.ai/api/v1" },
perplexity: { provider: "perplexity", baseURL: "https://api.perplexity.ai" },
togetherai: { provider: "togetherai", baseURL: "https://api.together.xyz/v1" },
venice: { provider: "venice", baseURL: "https://api.venice.ai/api/v1" },
} as const satisfies Record<string, ProviderFamily>
export const byProvider: Record<string, ProviderFamily> = Object.fromEntries(
+3 -1
View File
@@ -1,5 +1,7 @@
import { ProviderResolver } from "../provider-resolver"
export const resolver = ProviderResolver.fixed("xai", "openai-responses")
export const resolver = ProviderResolver.fixed("xai", "openai-compatible-chat", {
baseURL: "https://api.x.ai/v1",
})
export * as XAI from "./xai"
+24 -1
View File
@@ -1,5 +1,5 @@
import { describe, expect, test } from "bun:test"
import { Azure, GitHubCopilot, OpenAI, OpenAICompatibleFamily, ProviderResolver } from "../src"
import { Azure, GitHubCopilot, OpenAI, OpenAICompatibleFamily, ProviderResolver, XAI } from "../src"
describe("provider resolver", () => {
test("fixed providers resolve protocol and auth defaults", () => {
@@ -30,6 +30,29 @@ describe("provider resolver", () => {
baseURL: "https://api.together.xyz/v1",
auth: "key",
})
expect(OpenAICompatibleFamily.resolver.resolve(ProviderResolver.input("llama", "groq", {}))).toMatchObject({
provider: "groq",
protocol: "openai-compatible-chat",
baseURL: "https://api.groq.com/openai/v1",
})
expect(OpenAICompatibleFamily.resolver.resolve(ProviderResolver.input("sonar", "perplexity", {}))).toMatchObject({
provider: "perplexity",
protocol: "openai-compatible-chat",
baseURL: "https://api.perplexity.ai",
})
expect(OpenAICompatibleFamily.resolver.resolve(ProviderResolver.input("gpt-5", "openrouter", {}))).toMatchObject({
provider: "openrouter",
protocol: "openai-compatible-chat",
baseURL: "https://openrouter.ai/api/v1",
})
})
test("xAI resolves to its OpenAI-compatible chat endpoint", () => {
expect(XAI.resolver.resolve(ProviderResolver.input("grok-4", "xai", {}))).toMatchObject({
provider: "xai",
protocol: "openai-compatible-chat",
baseURL: "https://api.x.ai/v1",
})
})
test("Azure resolves resource URLs and API-version query params", () => {
@@ -31,14 +31,20 @@ const PROVIDERS: Record<string, ProviderResolverShape> = {
"@ai-sdk/azure": Azure.resolver,
"@ai-sdk/baseten": OpenAICompatibleFamily.resolver,
"@ai-sdk/cerebras": OpenAICompatibleFamily.resolver,
"@ai-sdk/deepseek": OpenAICompatibleFamily.resolver,
"@ai-sdk/deepinfra": OpenAICompatibleFamily.resolver,
"@ai-sdk/fireworks": OpenAICompatibleFamily.resolver,
"@ai-sdk/groq": OpenAICompatibleFamily.resolver,
"@ai-sdk/github-copilot": GitHubCopilot.resolver,
"@ai-sdk/google": Google.resolver,
"@ai-sdk/mistral": OpenAICompatibleFamily.resolver,
"@ai-sdk/openai": OpenAI.resolver,
"@ai-sdk/openai-compatible": OpenAICompatibleFamily.resolver,
"@ai-sdk/perplexity": OpenAICompatibleFamily.resolver,
"@ai-sdk/togetherai": OpenAICompatibleFamily.resolver,
"@ai-sdk/xai": XAI.resolver,
"@openrouter/ai-sdk-provider": OpenAICompatibleFamily.resolver,
"venice-ai-sdk-provider": OpenAICompatibleFamily.resolver,
}
const REASONING_EFFORTS = new Set<ReasoningEffort>(ReasoningEfforts)
@@ -87,22 +87,46 @@ describe("ProviderLLMBridge", () => {
})
test("maps known OpenAI-compatible provider families", () => {
const cases = [
["togetherai", "@ai-sdk/togetherai", "https://api.together.xyz/v1"],
["openrouter", "@openrouter/ai-sdk-provider", "https://openrouter.ai/api/v1"],
["groq", "@ai-sdk/groq", "https://api.groq.com/openai/v1"],
["mistral", "@ai-sdk/mistral", "https://api.mistral.ai/v1"],
["perplexity", "@ai-sdk/perplexity", "https://api.perplexity.ai"],
["venice", "venice-ai-sdk-provider", "https://api.venice.ai/api/v1"],
] as const
for (const [providerID, npm, baseURL] of cases) {
const ref = ProviderLLMBridge.toModelRef({
provider: provider({ id: ProviderID.make(providerID), options: { apiKey: `${providerID}-key` } }),
model: model({
id: "llama",
apiID: providerID === "togetherai" ? "meta-llama/Llama-3.3-70B-Instruct-Turbo" : "model-1",
providerID,
npm,
}),
})
expect(ref).toMatchObject({
provider: providerID,
protocol: "openai-compatible-chat",
baseURL,
apiKey: `${providerID}-key`,
})
}
})
test("maps xAI to OpenAI-compatible Chat", () => {
const ref = ProviderLLMBridge.toModelRef({
provider: provider({ id: ProviderID.make("togetherai"), options: { apiKey: "together-key" } }),
model: model({
id: "llama",
apiID: "meta-llama/Llama-3.3-70B-Instruct-Turbo",
providerID: "togetherai",
npm: "@ai-sdk/togetherai",
}),
provider: provider({ id: ProviderID.make("xai"), key: "xai-key" }),
model: model({ id: "grok-4", providerID: "xai", npm: "@ai-sdk/xai" }),
})
expect(ref).toMatchObject({
id: "meta-llama/Llama-3.3-70B-Instruct-Turbo",
provider: "togetherai",
provider: "xai",
protocol: "openai-compatible-chat",
baseURL: "https://api.together.xyz/v1",
apiKey: "together-key",
baseURL: "https://api.x.ai/v1",
apiKey: "xai-key",
})
})
@@ -202,7 +226,9 @@ describe("ProviderLLMBridge", () => {
test("leaves undecided provider packages unmapped", () => {
const unsupported = [
["mistral", "mistral-large", "@ai-sdk/mistral"],
["cohere", "command-a", "@ai-sdk/cohere"],
["google-vertex", "gemini-2.5-flash", "@ai-sdk/google-vertex"],
["gateway", "openai/gpt-5", "@ai-sdk/gateway"],
] as const
expect(
@@ -212,6 +238,6 @@ describe("ProviderLLMBridge", () => {
model: model({ id: modelID, providerID, npm }),
}),
),
).toEqual([undefined, undefined])
).toEqual([undefined, undefined, undefined])
})
})