Memory: adopt embedding backend catalog

This commit is contained in:
Gustavo Madeira Santana 2026-03-15 21:26:50 +00:00
parent 2380ee5fca
commit 7ff79aa494
2 changed files with 84 additions and 6 deletions

View File

@ -0,0 +1,80 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
const listExtensionHostEmbeddingRemoteRuntimeBackendIds = vi.hoisted(() =>
vi.fn(() => ["gemini", "openai"] as const),
);
const createGeminiEmbeddingProvider = vi.hoisted(() => vi.fn());
const createOpenAiEmbeddingProvider = vi.hoisted(() => vi.fn());
vi.mock("./runtime-backend-catalog.js", () => ({
listExtensionHostEmbeddingRemoteRuntimeBackendIds,
}));
vi.mock("../memory/embeddings-gemini.js", () => ({
createGeminiEmbeddingProvider,
}));
vi.mock("../memory/embeddings-openai.js", () => ({
createOpenAiEmbeddingProvider,
}));
vi.mock("../memory/embeddings-mistral.js", () => ({
createMistralEmbeddingProvider: vi.fn(),
}));
vi.mock("../memory/embeddings-ollama.js", () => ({
createOllamaEmbeddingProvider: vi.fn(),
}));
vi.mock("../memory/embeddings-voyage.js", () => ({
createVoyageEmbeddingProvider: vi.fn(),
}));
vi.mock("../memory/node-llama.js", () => ({
importNodeLlamaCpp: vi.fn(),
}));
describe("extension host embedding runtime registry", () => {
beforeEach(() => {
vi.clearAllMocks();
});
it("uses the runtime-backend catalog for auto provider order", async () => {
createGeminiEmbeddingProvider.mockResolvedValue({
provider: {
id: "gemini",
model: "text-embedding-004",
embedQuery: vi.fn(),
embedBatch: vi.fn(),
},
client: { kind: "gemini" },
});
const { createExtensionHostEmbeddingProvider } =
await import("./embedding-runtime-registry.js");
const result = await createExtensionHostEmbeddingProvider({
config: {} as never,
provider: "auto",
model: "text-embedding-004",
fallback: "none",
});
expect(listExtensionHostEmbeddingRemoteRuntimeBackendIds).toHaveBeenCalledTimes(1);
expect(createGeminiEmbeddingProvider).toHaveBeenCalledTimes(1);
expect(createOpenAiEmbeddingProvider).not.toHaveBeenCalled();
expect(result.provider?.id).toBe("gemini");
});
it("uses the same catalog order in local setup guidance", async () => {
const { formatExtensionHostLocalEmbeddingSetupError } =
await import("./embedding-runtime-registry.js");
const message = formatExtensionHostLocalEmbeddingSetupError(
new Error("Cannot find package 'node-llama-cpp'"),
);
expect(listExtensionHostEmbeddingRemoteRuntimeBackendIds).toHaveBeenCalledTimes(1);
expect(message).toContain('agents.defaults.memorySearch.provider = "gemini"');
expect(message).toContain('agents.defaults.memorySearch.provider = "openai"');
});
});

View File

@ -25,16 +25,14 @@ import {
} from "../memory/embeddings-voyage.js";
import { importNodeLlamaCpp } from "../memory/node-llama.js";
import { resolveUserPath } from "../utils.js";
import {
DEFAULT_EXTENSION_HOST_LOCAL_EMBEDDING_MODEL,
EXTENSION_HOST_REMOTE_EMBEDDING_PROVIDER_IDS,
} from "./embedding-runtime-backends.js";
import { DEFAULT_EXTENSION_HOST_LOCAL_EMBEDDING_MODEL } from "./embedding-runtime-backends.js";
import type {
EmbeddingProvider,
EmbeddingProviderId,
EmbeddingProviderOptions,
EmbeddingProviderResult,
} from "./embedding-runtime-types.js";
import { listExtensionHostEmbeddingRemoteRuntimeBackendIds } from "./runtime-backend-catalog.js";
export type {
GeminiEmbeddingClient,
@ -192,7 +190,7 @@ export async function createExtensionHostEmbeddingProvider(
}
}
for (const provider of EXTENSION_HOST_REMOTE_EMBEDDING_PROVIDER_IDS) {
for (const provider of listExtensionHostEmbeddingRemoteRuntimeBackendIds()) {
try {
const result = await createExtensionHostEmbeddingProviderById(provider, options);
return { ...result, requestedProvider };
@ -292,7 +290,7 @@ export function formatExtensionHostLocalEmbeddingSetupError(err: unknown): strin
? "2) Reinstall OpenClaw (this should install node-llama-cpp): npm i -g openclaw@latest"
: null,
"3) If you use pnpm: pnpm approve-builds (select node-llama-cpp), then pnpm rebuild node-llama-cpp",
...EXTENSION_HOST_REMOTE_EMBEDDING_PROVIDER_IDS.map(
...listExtensionHostEmbeddingRemoteRuntimeBackendIds().map(
(provider) => `Or set agents.defaults.memorySearch.provider = "${provider}" (remote).`,
),
]