feat: add Novita AI as an LLM provider#1869
feat: add Novita AI as an LLM provider#1869Alex-wuhu wants to merge 1 commit intobrowserbase:mainfrom
Conversation
Registers Novita AI (OpenAI-compatible endpoint) via `@ai-sdk/openai` with a fixed `baseURL` of `https://api.novita.ai/openai`. Supports all three Novita chat models (kimi-k2.5, glm-5, minimax-m2.5) using the `novita/<model-id>` format. API key is read from `NOVITA_API_KEY`. - Add `novita` static provider and `createNovita` factory to `LLMProvider.ts` (both `AISDKProviders` and `AISDKProvidersWithAPIKey`) - Add `novita: "NOVITA_API_KEY"` to `providerEnvVarMap` in `utils.ts` - Add unit tests for the novita provider in `llm-provider.test.ts`
|
|
This PR is from an external contributor and must be approved by a stagehand team member with write access before CI can run. |
There was a problem hiding this comment.
2 issues found across 3 files
Confidence score: 3/5
- There is a concrete user-impact risk in
packages/core/lib/v3/llm/LLMProvider.ts: Novita’s reachable no-options/static provider path does not bind a Novita-specific API key, which could cause authentication failures or use an unintended credential source. - The test gap in
packages/core/tests/unit/llm-provider.test.tslowers confidence in this area—the custombaseURLoverride case currently uses Novita’s default URL and only checks that a value is defined, so override regressions may slip through. - Given the high-severity provider-path issue (7/10) with strong confidence, this is moderate merge risk rather than a merge-blocker, but it should be addressed soon.
- Pay close attention to
packages/core/lib/v3/llm/LLMProvider.ts,packages/core/tests/unit/llm-provider.test.ts- provider credential binding and baseURL override behavior need validation.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/core/tests/unit/llm-provider.test.ts">
<violation number="1" location="packages/core/tests/unit/llm-provider.test.ts:78">
P2: The "custom baseURL override" test is ineffective because it uses Novita’s default URL and only asserts definition, so regressions in override handling would go undetected.</violation>
</file>
<file name="packages/core/lib/v3/llm/LLMProvider.ts">
<violation number="1" location="packages/core/lib/v3/llm/LLMProvider.ts:38">
P1: Novita’s no-options/static provider path is reachable and does not bind a Novita-specific API key, risking wrong/default credential source or auth failure.</violation>
</file>
Architecture diagram
sequenceDiagram
participant Client as User/Application
participant Provider as LLMProvider.ts
participant Env as Environment/Utils
participant AISDK as @ai-sdk/openai
participant Novita as Novita AI API
Note over Client,Novita: Request Flow for "novita" Provider
Client->>Provider: getAISDKLanguageModel("novita", modelId, options)
Provider->>Env: NEW: Lookup "novita" in providerEnvVarMap
Env-->>Provider: Return "NOVITA_API_KEY"
alt NEW: options.apiKey provided OR process.env.NOVITA_API_KEY set
Provider->>Provider: createNovita(options)
Provider->>AISDK: NEW: createOpenAI({ baseURL: "https://api.novita.ai/openai", ...options })
else Use default instance
Provider->>Provider: Use static novita provider
Note right of Provider: Pre-initialized with Novita Base URL
end
Provider-->>Client: Return LanguageModel instance
Client->>AISDK: generateText() / streamText()
AISDK->>Novita: CHANGED: POST to https://api.novita.ai/openai
Note right of AISDK: Standard OpenAI-compatible payload
alt Success
Novita-->>AISDK: 200 OK (Model Response)
AISDK-->>Client: Result object
else Error (e.g. Invalid Key)
Novita-->>AISDK: 401 Unauthorized
AISDK-->>Client: Throw Error
end
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| import { AISDKProvider, AISDKCustomProvider } from "../types/public/model.js"; | ||
|
|
||
| const NOVITA_BASE_URL = "https://api.novita.ai/openai"; | ||
| const novita = createOpenAI({ baseURL: NOVITA_BASE_URL }); |
There was a problem hiding this comment.
P1: Novita’s no-options/static provider path is reachable and does not bind a Novita-specific API key, risking wrong/default credential source or auth failure.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/core/lib/v3/llm/LLMProvider.ts, line 38:
<comment>Novita’s no-options/static provider path is reachable and does not bind a Novita-specific API key, risking wrong/default credential source or auth failure.</comment>
<file context>
@@ -34,6 +34,11 @@ import { ollama, createOllama } from "ollama-ai-provider-v2";
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 });
</file context>
| const novita = createOpenAI({ baseURL: NOVITA_BASE_URL }); | |
| const novita = createOpenAI({ | |
| baseURL: NOVITA_BASE_URL, | |
| apiKey: process.env.NOVITA_API_KEY, | |
| }); |
| it("works with custom baseURL override", () => { | ||
| const model = getAISDKLanguageModel("novita", "minimax/minimax-m2.5", { | ||
| apiKey: "test-novita-key", | ||
| baseURL: "https://api.novita.ai/openai", |
There was a problem hiding this comment.
P2: The "custom baseURL override" test is ineffective because it uses Novita’s default URL and only asserts definition, so regressions in override handling would go undetected.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/core/tests/unit/llm-provider.test.ts, line 78:
<comment>The "custom baseURL override" test is ineffective because it uses Novita’s default URL and only asserts definition, so regressions in override handling would go undetected.</comment>
<file context>
@@ -57,6 +57,30 @@ describe("getAISDKLanguageModel", () => {
+ 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();
</file context>
Summary
Adds Novita AI as a supported LLM provider via the existing Vercel AI SDK / OpenAI-compatible path.
novitahttps://api.novita.ai/openai(OpenAI-compatible)NOVITA_API_KEYenvironment variablenovita/<model-id>format (e.g.novita/moonshotai/kimi-k2.5)Supported models
novita/moonshotai/kimi-k2.5novita/zai-org/glm-5novita/minimax/minimax-m2.5Changes
packages/core/lib/v3/llm/LLMProvider.tsnovitastatic provider andcreateNovitafactory usingcreateOpenAIwithbaseURL: "https://api.novita.ai/openai"AISDKProvidersandAISDKProvidersWithAPIKeypackages/core/lib/utils.tsnovita: "NOVITA_API_KEY"toproviderEnvVarMappackages/core/tests/unit/llm-provider.test.tsNotes
= 1) and prompt-JSON-fallback handling inaisdk.ts(patterns"kimi"and"glm"are already inPROMPT_JSON_FALLBACK_PATTERNS)@ai-sdk/openaialready presentSummary by cubic
Adds Novita as a first-class LLM provider via the OpenAI-compatible endpoint. Use provider key
novitawithNOVITA_API_KEYagainsthttps://api.novita.ai/openai.novita/<model-id>:moonshotai/kimi-k2.5,zai-org/glm-5,minimax/minimax-m2.5.@ai-sdk/openai; supports API key and baseURL override.Written for commit 1860060. Summary will update on new commits. Review in cubic