import { afterEach, describe, expect, it, vi } from "vitest"; import { invokeLLMWithUserSettings, resolveLlmTrace } from "./_core/llm"; describe("resolveLlmTrace", () => { it("trace Manus Forge avec le modèle réellement résolu", () => { expect(resolveLlmTrace({ aiProvider: "manus" })).toEqual({ provider: "manus", model: "gemini-2.5-flash", transport: "manus-forge", }); }); it("trace Mistral et Gemini sans déduire le modèle depuis un champ historique", () => { expect(resolveLlmTrace({ aiProvider: "mistral" })).toEqual({ provider: "mistral", model: "mistral-large-latest", transport: "mistral-api", }); expect(resolveLlmTrace({ aiProvider: "gemini" })).toEqual({ provider: "gemini", model: "gemini-2.0-flash", transport: "gemini-api", }); }); it("reste sur Mistral lorsque le fournisseur est absent", () => { expect(resolveLlmTrace()).toEqual({ provider: "mistral", model: "mistral-large-latest", transport: "mistral-api", }); }); }); describe("invokeLLMWithUserSettings", () => { afterEach(() => vi.unstubAllGlobals()); it("retourne la trace Manus correspondant au payload réellement envoyé", async () => { const fetchMock = vi.fn().mockResolvedValue({ ok: true, json: async () => ({ id: "test", created: 0, model: "gemini-2.5-flash", choices: [] }), }); vi.stubGlobal("fetch", fetchMock); const invocation = await invokeLLMWithUserSettings( { messages: [{ role: "user", content: "test non sensible" }] }, { aiProvider: "manus", manusForgeApiKey: "test-only-not-a-secret", manusForgeApiUrl: "https://forge.example.test", }, ); expect(invocation.trace).toEqual({ provider: "manus", model: "gemini-2.5-flash", transport: "manus-forge", }); expect(fetchMock).toHaveBeenCalledWith( "https://forge.example.test/v1/chat/completions", expect.objectContaining({ method: "POST" }), ); const request = fetchMock.mock.calls[0][1] as RequestInit; expect(JSON.parse(String(request.body))).toMatchObject({ model: "gemini-2.5-flash" }); }); });