|
@@ -100,6 +100,7 @@ const endpointMocks = [
|
|
|
...(id === "google" ? { checkModel: "gemini-2.5-flash" } : {}),
|
|
...(id === "google" ? { checkModel: "gemini-2.5-flash" } : {}),
|
|
|
...(id === "minimax" ? { checkModel: "MiniMax-M2.7" } : {}),
|
|
...(id === "minimax" ? { checkModel: "MiniMax-M2.7" } : {}),
|
|
|
...(id === "ollama" ? { checkModel: "llama3.2:3b" } : {}),
|
|
...(id === "ollama" ? { checkModel: "llama3.2:3b" } : {}),
|
|
|
|
|
+ ...(id === "volcengine" ? { checkModel: "doubao-lite-32k" } : {}),
|
|
|
models: [
|
|
models: [
|
|
|
{ id: `${id}-model`, maxOutput: 4096, contextWindowTokens: 32768, enabled: true },
|
|
{ id: `${id}-model`, maxOutput: 4096, contextWindowTokens: 32768, enabled: true },
|
|
|
{ id: `${id}-disabled`, maxOutput: 4096, contextWindowTokens: 32768, enabled: false },
|
|
{ id: `${id}-disabled`, maxOutput: 4096, contextWindowTokens: 32768, enabled: false },
|
|
@@ -1305,6 +1306,48 @@ describe("createStudioServer daemon lifecycle", () => {
|
|
|
expect(chatCompletionMock.mock.calls.map((call) => call[1])).not.toContain("MiniMax-M2.7");
|
|
expect(chatCompletionMock.mock.calls.map((call) => call[1])).not.toContain("MiniMax-M2.7");
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+ it("uses discovered Volcengine models before the stale built-in check model", async () => {
|
|
|
|
|
+ const fetchMock = vi.fn().mockResolvedValue({
|
|
|
|
|
+ ok: true,
|
|
|
|
|
+ json: async () => ({ data: [{ id: "doubao-seed-2.0-lite" }] }),
|
|
|
|
|
+ });
|
|
|
|
|
+ vi.stubGlobal("fetch", fetchMock as typeof fetch);
|
|
|
|
|
+ createLLMClientMock.mockImplementation(((cfg: unknown) => cfg) as any);
|
|
|
|
|
+ chatCompletionMock.mockImplementation(async (_client: any, model: string) => {
|
|
|
|
|
+ if (model === "doubao-seed-2.0-lite") {
|
|
|
|
|
+ return {
|
|
|
|
|
+ content: "pong",
|
|
|
|
|
+ usage: { promptTokens: 1, completionTokens: 1, totalTokens: 2 },
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+ throw new Error(`unexpected model: ${model}`);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const { createStudioServer } = await import("./server.js");
|
|
|
|
|
+ const app = createStudioServer(cloneProjectConfig() as never, root);
|
|
|
|
|
+
|
|
|
|
|
+ const response = await app.request("http://localhost/api/v1/services/volcengine/test", {
|
|
|
|
|
+ method: "POST",
|
|
|
|
|
+ headers: { "Content-Type": "application/json" },
|
|
|
|
|
+ body: JSON.stringify({
|
|
|
|
|
+ apiKey: "volc-key",
|
|
|
|
|
+ baseUrl: "https://ark.cn-beijing.volces.com/api/v3",
|
|
|
|
|
+ apiFormat: "responses",
|
|
|
|
|
+ stream: true,
|
|
|
|
|
+ }),
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ expect(response.status).toBe(200);
|
|
|
|
|
+ await expect(response.json()).resolves.toMatchObject({
|
|
|
|
|
+ ok: true,
|
|
|
|
|
+ selectedModel: "doubao-seed-2.0-lite",
|
|
|
|
|
+ detected: {
|
|
|
|
|
+ modelsSource: "api",
|
|
|
|
|
+ },
|
|
|
|
|
+ });
|
|
|
|
|
+ expect(chatCompletionMock.mock.calls.map((call) => call[1])).not.toContain("doubao-lite-32k");
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
it("uses discovered Ollama models without requiring an API key or the built-in check model", async () => {
|
|
it("uses discovered Ollama models without requiring an API key or the built-in check model", async () => {
|
|
|
await writeFile(join(root, "inkos.json"), JSON.stringify({
|
|
await writeFile(join(root, "inkos.json"), JSON.stringify({
|
|
|
...projectConfig,
|
|
...projectConfig,
|