diff --git a/packages/core/lib/utils.ts b/packages/core/lib/utils.ts index c5dd13b6f..ab79b9f6a 100644 --- a/packages/core/lib/utils.ts +++ b/packages/core/lib/utils.ts @@ -693,6 +693,7 @@ export const providerEnvVarMap: Partial< azure: "AZURE_API_KEY", xai: "XAI_API_KEY", google_legacy: "GOOGLE_API_KEY", + novita: "NOVITA_API_KEY", }; const providersWithoutApiKey = new Set(["bedrock", "ollama"]); diff --git a/packages/core/lib/v3/llm/LLMProvider.ts b/packages/core/lib/v3/llm/LLMProvider.ts index 11986d3cb..ce4fc6ac3 100644 --- a/packages/core/lib/v3/llm/LLMProvider.ts +++ b/packages/core/lib/v3/llm/LLMProvider.ts @@ -34,6 +34,11 @@ import { ollama, createOllama } from "ollama-ai-provider-v2"; import { gateway, createGateway } from "ai"; import { AISDKProvider, AISDKCustomProvider } from "../types/public/model.js"; +const NOVITA_BASE_URL = "https://api.novita.ai/openai"; +const novita = createOpenAI({ baseURL: NOVITA_BASE_URL }); +const createNovita: AISDKCustomProvider = (options) => + createOpenAI({ baseURL: NOVITA_BASE_URL, ...options }); + const AISDKProviders: Record = { openai, bedrock, @@ -50,6 +55,7 @@ const AISDKProviders: Record = { ollama, vertex, gateway, + novita, }; const AISDKProvidersWithAPIKey: Record = { openai: createOpenAI, @@ -67,6 +73,7 @@ const AISDKProvidersWithAPIKey: Record = { perplexity: createPerplexity, ollama: createOllama, gateway: createGateway, + novita: createNovita, }; const modelToProviderMap: { [key in AvailableModel]: ModelProvider } = { diff --git a/packages/core/tests/unit/llm-provider.test.ts b/packages/core/tests/unit/llm-provider.test.ts index 5bbde12f7..eb0112f29 100644 --- a/packages/core/tests/unit/llm-provider.test.ts +++ b/packages/core/tests/unit/llm-provider.test.ts @@ -57,6 +57,30 @@ describe("getAISDKLanguageModel", () => { }); }); + describe("novita provider", () => { + it("works with apiKey", () => { + const model = getAISDKLanguageModel( + "novita", + "moonshotai/kimi-k2.5", + { apiKey: "test-novita-key" }, + ); + expect(model).toBeDefined(); + }); + + it("works without clientOptions (uses static provider)", () => { + const model = getAISDKLanguageModel("novita", "moonshotai/kimi-k2.5"); + expect(model).toBeDefined(); + }); + + it("works with custom baseURL override", () => { + const model = getAISDKLanguageModel("novita", "minimax/minimax-m2.5", { + apiKey: "test-novita-key", + baseURL: "https://api.novita.ai/openai", + }); + expect(model).toBeDefined(); + }); + }); + describe("hasValidOptions logic", () => { it("treats undefined apiKey as no options", () => { // This should use the default provider path (AISDKProviders)