diff --git a/src/app/api/llm/__tests__/route.test.ts b/src/app/api/llm/__tests__/route.test.ts index 458f547c..a1c2c9ff 100644 --- a/src/app/api/llm/__tests__/route.test.ts +++ b/src/app/api/llm/__tests__/route.test.ts @@ -313,6 +313,88 @@ describe("/api/llm route", () => { }); }); + describe("NewApiWG provider", () => { + beforeEach(() => { + global.fetch = mockFetch; + }); + + it("should use current Doubao Seed model ids for NewApiWG", async () => { + mockFetch.mockResolvedValueOnce({ + ok: true, + json: () => + Promise.resolve({ + choices: [{ message: { content: "Doubao response text" } }], + }), + }); + + const request = createMockPostRequest( + { + prompt: "Test prompt", + provider: "newapiwg", + model: "doubao-seed-2-0-lite-260428", + temperature: 0.7, + maxTokens: 1024, + }, + { + "X-NewApiWG-Key": "test-newapiwg-key", + "X-NewApiWG-Base-URL": "https://newapi.example/v1", + } + ); + + const response = await POST(request); + const data = await response.json(); + + expect(response.status).toBe(200); + expect(data.success).toBe(true); + expect(data.text).toBe("Doubao response text"); + expect(mockFetch).toHaveBeenCalledWith( + "https://newapi.example/v1/chat/completions", + expect.objectContaining({ + body: JSON.stringify({ + model: "doubao-seed-2-0-lite-260428", + messages: [{ role: "user", content: "Test prompt" }], + temperature: 0.7, + max_tokens: 1024, + }), + }) + ); + }); + + it("should map legacy Doubao selector values to available gateway model ids", async () => { + mockFetch.mockResolvedValueOnce({ + ok: true, + json: () => + Promise.resolve({ + choices: [{ message: { content: "Legacy Doubao response text" } }], + }), + }); + + const request = createMockPostRequest( + { + prompt: "Test prompt", + provider: "newapiwg", + model: "Doubao-Seed-2.0-lite", + }, + { + "X-NewApiWG-Key": "test-newapiwg-key", + "X-NewApiWG-Base-URL": "https://newapi.example/v1", + } + ); + + const response = await POST(request); + const data = await response.json(); + + expect(response.status).toBe(200); + expect(data.success).toBe(true); + expect(mockFetch).toHaveBeenCalledWith( + "https://newapi.example/v1/chat/completions", + expect.objectContaining({ + body: expect.stringContaining('"model":"doubao-seed-2-0-lite-260428"'), + }) + ); + }); + }); + describe("OpenAI provider", () => { beforeEach(() => { global.fetch = mockFetch; diff --git a/src/app/api/llm/route.ts b/src/app/api/llm/route.ts index 0aab7fb8..8289e054 100644 --- a/src/app/api/llm/route.ts +++ b/src/app/api/llm/route.ts @@ -30,6 +30,11 @@ const ANTHROPIC_MODEL_MAP: Record = { "claude-opus-4.6": "claude-opus-4-6", }; +const NEWAPIWG_LLM_MODEL_ALIASES: Record = { + "Doubao-Seed-2.0-lite": "doubao-seed-2-0-lite-260428", + "Doubao-Seed-2.0-pro": "doubao-seed-2-0-pro-260215", +}; + type GoogleContentPart = | { inlineData: { mimeType: string; data: string } } | { fileData: { mimeType: string; fileUri: string } } @@ -246,6 +251,7 @@ async function generateWithNewApiWG( } const content = buildChatContent(prompt, images, videos); + const modelId = NEWAPIWG_LLM_MODEL_ALIASES[model] ?? model; const startTime = Date.now(); const response = await fetch(`${normalizeNewApiWGBaseUrl(userBaseUrl)}/chat/completions`, { @@ -255,7 +261,7 @@ async function generateWithNewApiWG( "Authorization": `Bearer ${apiKey}`, }, body: JSON.stringify({ - model, + model: modelId, messages: [{ role: "user", content }], temperature, max_tokens: maxTokens, diff --git a/src/components/__tests__/LLMGenerateNode.test.tsx b/src/components/__tests__/LLMGenerateNode.test.tsx index 8abb05c9..8b2d6a08 100644 --- a/src/components/__tests__/LLMGenerateNode.test.tsx +++ b/src/components/__tests__/LLMGenerateNode.test.tsx @@ -54,7 +54,7 @@ describe("LLMGenerateNode", () => { inputVideos: [], outputText: null, provider: "newapiwg", - model: "Doubao-Seed-2.0-lite", + model: "doubao-seed-2-0-lite-260428", temperature: 1.0, maxTokens: 2048, status: "idle", diff --git a/src/lib/__tests__/llmModels.test.ts b/src/lib/__tests__/llmModels.test.ts index 53f8dd83..7c578bac 100644 --- a/src/lib/__tests__/llmModels.test.ts +++ b/src/lib/__tests__/llmModels.test.ts @@ -12,12 +12,12 @@ describe("LLM model options", () => { label: "GPT-4.1 Mini", }); expect(LLM_MODELS.newapiwg).toContainEqual({ - value: "Doubao-Seed-2.0-lite", - label: "Doubao-Seed-2.0-lite", + value: "doubao-seed-2-0-lite-260428", + label: "Doubao Seed 2.0 Lite", }); expect(LLM_MODELS.newapiwg).toContainEqual({ - value: "Doubao-Seed-2.0-pro", - label: "Doubao-Seed-2.0-pro", + value: "doubao-seed-2-0-pro-260215", + label: "Doubao Seed 2.0 Pro", }); }); }); diff --git a/src/lib/chat/tools.ts b/src/lib/chat/tools.ts index f3c452e8..c6fa0717 100644 --- a/src/lib/chat/tools.ts +++ b/src/lib/chat/tools.ts @@ -59,7 +59,7 @@ AI video generation. Takes image + text inputs, outputs video. Only available wi ### LLM Text Generation AI text generation for expanding prompts or analyzing images. - **Provider dropdown**: NewApiWG, Google, OpenAI, or Anthropic -- **Model dropdown**: GPT-4.1 Mini (NewApiWG default), Doubao-Seed-2.0-lite/pro (NewApiWG options) / Gemini 3 Flash, Gemini 2.5 Flash, Gemini 3.0 Pro (Google) / GPT-4.1 Mini, GPT-4.1 Nano (OpenAI) +- **Model dropdown**: GPT-4.1 Mini (NewApiWG default), Doubao Seed 2.0 Lite/Pro (NewApiWG options) / Gemini 3 Flash, Gemini 2.5 Flash, Gemini 3.0 Pro (Google) / GPT-4.1 Mini, GPT-4.1 Nano (OpenAI) - **Parameters** (collapsible): Temperature slider (0-2), Max Tokens slider (256-16384) - Takes **text** input (required), optional **image** input diff --git a/src/lib/llmModels.ts b/src/lib/llmModels.ts index 4d0c796c..cae7e29a 100644 --- a/src/lib/llmModels.ts +++ b/src/lib/llmModels.ts @@ -17,8 +17,8 @@ export const LLM_PROVIDERS: { value: LLMProvider; label: string }[] = [ export const LLM_MODELS: Record = { newapiwg: [ { value: "gpt-4.1-mini", label: "GPT-4.1 Mini" }, - { value: "Doubao-Seed-2.0-lite", label: "Doubao-Seed-2.0-lite" }, - { value: "Doubao-Seed-2.0-pro", label: "Doubao-Seed-2.0-pro" }, + { value: "doubao-seed-2-0-lite-260428", label: "Doubao Seed 2.0 Lite" }, + { value: "doubao-seed-2-0-pro-260215", label: "Doubao Seed 2.0 Pro" }, ], google: [ { value: "gemini-3-flash-preview", label: "Gemini 3 Flash" }, diff --git a/src/types/providers.ts b/src/types/providers.ts index ef56213f..d641e4fa 100644 --- a/src/types/providers.ts +++ b/src/types/providers.ts @@ -47,6 +47,8 @@ export type LLMModelType = | "gemini-3-flash-preview" | "gemini-3-pro-preview" | "gemini-3.1-pro-preview" + | "doubao-seed-2-0-lite-260428" + | "doubao-seed-2-0-pro-260215" | "Doubao-Seed-2.0-lite" | "Doubao-Seed-2.0-pro" | "gpt-4.1-mini"