diff --git a/src/agents/memory-search.ts b/src/agents/memory-search.ts index 2abef2eaf..9eb35f3ee 100644 --- a/src/agents/memory-search.ts +++ b/src/agents/memory-search.ts @@ -119,22 +119,16 @@ function mergeConfig( const provider = overrides?.provider ?? defaults?.provider ?? "auto"; const defaultRemote = defaults?.remote; const overrideRemote = overrides?.remote; - const hasRemoteConfig = Boolean( overrideRemote?.baseUrl || - overrideRemote?.apiKey || - overrideRemote?.headers || - defaultRemote?.baseUrl || - defaultRemote?.apiKey || - defaultRemote?.headers, + overrideRemote?.apiKey || + overrideRemote?.headers || + defaultRemote?.baseUrl || + defaultRemote?.apiKey || + defaultRemote?.headers, ); - const includeRemote = - hasRemoteConfig || - provider === "openai" || - provider === "gemini" || - provider === "auto"; - + hasRemoteConfig || provider === "openai" || provider === "gemini" || provider === "auto"; const batch = { enabled: overrideRemote?.batch?.enabled ?? defaultRemote?.batch?.enabled ?? true, wait: overrideRemote?.batch?.wait ?? defaultRemote?.batch?.wait ?? true, @@ -159,7 +153,7 @@ function mergeConfig( const modelDefault = provider === "gemini" ? DEFAULT_GEMINI_MODEL - : provider === "openai" || provider === "auto" + : provider === "openai" ? DEFAULT_OPENAI_MODEL : undefined; const model = overrides?.model ?? defaults?.model ?? modelDefault ?? ""; diff --git a/src/memory/embeddings.test.ts b/src/memory/embeddings.test.ts index e37bca3cd..1809b24b8 100644 --- a/src/memory/embeddings.test.ts +++ b/src/memory/embeddings.test.ts @@ -1,5 +1,7 @@ import { afterEach, describe, expect, it, vi } from "vitest"; +import { DEFAULT_GEMINI_EMBEDDING_MODEL } from "./embeddings-gemini.js"; + vi.mock("../agents/model-auth.js", () => ({ resolveApiKeyForProvider: vi.fn(), requireApiKey: (auth: { apiKey?: string; mode?: string }, provider: string) => { @@ -193,6 +195,13 @@ describe("embedding provider auto selection", () => { }); it("uses gemini when openai is missing", async () => { + const fetchMock = vi.fn(async () => ({ + ok: true, + status: 200, + json: async () => ({ embedding: { values: [1, 2, 3] } }), + })) as unknown as typeof fetch; + vi.stubGlobal("fetch", fetchMock); + const { createEmbeddingProvider } = await import("./embeddings.js"); const authModule = await import("../agents/model-auth.js"); vi.mocked(authModule.resolveApiKeyForProvider).mockImplementation(async ({ provider }) => { @@ -214,6 +223,44 @@ describe("embedding provider auto selection", () => { expect(result.requestedProvider).toBe("auto"); expect(result.provider.id).toBe("gemini"); + await result.provider.embedQuery("hello"); + const [url] = fetchMock.mock.calls[0] ?? []; + expect(url).toBe( + `https://generativelanguage.googleapis.com/v1beta/models/${DEFAULT_GEMINI_EMBEDDING_MODEL}:embedContent`, + ); + }); + + it("keeps explicit model when openai is selected", async () => { + const fetchMock = vi.fn(async () => ({ + ok: true, + status: 200, + json: async () => ({ data: [{ embedding: [1, 2, 3] }] }), + })) as unknown as typeof fetch; + vi.stubGlobal("fetch", fetchMock); + + const { createEmbeddingProvider } = await import("./embeddings.js"); + const authModule = await import("../agents/model-auth.js"); + vi.mocked(authModule.resolveApiKeyForProvider).mockImplementation(async ({ provider }) => { + if (provider === "openai") { + return { apiKey: "openai-key", source: "env: OPENAI_API_KEY", mode: "api-key" }; + } + throw new Error(`Unexpected provider ${provider}`); + }); + + const result = await createEmbeddingProvider({ + config: {} as never, + provider: "auto", + model: "text-embedding-3-small", + fallback: "none", + }); + + expect(result.requestedProvider).toBe("auto"); + expect(result.provider.id).toBe("openai"); + await result.provider.embedQuery("hello"); + const [url, init] = fetchMock.mock.calls[0] ?? []; + expect(url).toBe("https://api.openai.com/v1/embeddings"); + const payload = JSON.parse(String(init?.body ?? "{}")) as { model?: string }; + expect(payload.model).toBe("text-embedding-3-small"); }); });