diff --git a/src/commands/doctor-memory-search.test.ts b/src/commands/doctor-memory-search.test.ts index 3d939b2b295..dac45c5229f 100644 --- a/src/commands/doctor-memory-search.test.ts +++ b/src/commands/doctor-memory-search.test.ts @@ -33,7 +33,7 @@ vi.mock("../memory/backend-config.js", () => ({ resolveMemoryBackendConfig, })); -vi.mock("../extension-host/runtime-backend-catalog.js", () => ({ +vi.mock("../extension-host/embedding-runtime-policy.js", () => ({ listExtensionHostEmbeddingRemoteRuntimeBackendIds, })); diff --git a/src/commands/doctor-memory-search.ts b/src/commands/doctor-memory-search.ts index 1466855283a..c5a87b8888b 100644 --- a/src/commands/doctor-memory-search.ts +++ b/src/commands/doctor-memory-search.ts @@ -4,8 +4,8 @@ import { resolveMemorySearchConfig } from "../agents/memory-search.js"; import { resolveApiKeyForProvider } from "../agents/model-auth.js"; import { formatCliCommand } from "../cli/command-format.js"; import type { OpenClawConfig } from "../config/config.js"; +import { listExtensionHostEmbeddingRemoteRuntimeBackendIds } from "../extension-host/embedding-runtime-policy.js"; import { DEFAULT_LOCAL_EMBEDDING_MODEL } from "../extension-host/embedding-runtime.js"; -import { listExtensionHostEmbeddingRemoteRuntimeBackendIds } from "../extension-host/runtime-backend-catalog.js"; import { resolveMemoryBackendConfig } from "../memory/backend-config.js"; import { hasConfiguredMemorySecretInput } from "../memory/secret-input.js"; import { note } from "../terminal/note.js"; diff --git a/src/extension-host/embedding-runtime-policy.test.ts b/src/extension-host/embedding-runtime-policy.test.ts index 7d79d8e6102..43d774ac134 100644 --- a/src/extension-host/embedding-runtime-policy.test.ts +++ b/src/extension-host/embedding-runtime-policy.test.ts @@ -1,10 +1,20 @@ import { describe, expect, it } from "vitest"; import { + listExtensionHostEmbeddingRemoteRuntimeBackendIds, resolveExtensionHostEmbeddingFallbackModel, resolveExtensionHostEmbeddingFallbackPolicy, } from "./embedding-runtime-policy.js"; describe("embedding-runtime-policy", () => { + it("uses the shared runtime-backend policy for remote auto-provider order", () => { + expect(listExtensionHostEmbeddingRemoteRuntimeBackendIds()).toEqual([ + "openai", + "gemini", + "voyage", + "mistral", + ]); + }); + it("returns null when fallback is disabled or would repeat the requested provider", () => { expect( resolveExtensionHostEmbeddingFallbackPolicy({ diff --git a/src/extension-host/embedding-runtime-policy.ts b/src/extension-host/embedding-runtime-policy.ts index a6d46d9341b..4f7029b73a6 100644 --- a/src/extension-host/embedding-runtime-policy.ts +++ b/src/extension-host/embedding-runtime-policy.ts @@ -4,6 +4,16 @@ import type { EmbeddingProviderId, EmbeddingProviderRequest, } from "./embedding-runtime-types.js"; +import { listExtensionHostEmbeddingRuntimeBackendCatalogEntries } from "./runtime-backend-catalog.js"; +import { resolveExtensionHostRuntimeBackendIdsByPolicy } from "./runtime-backend-policy.js"; + +export function listExtensionHostEmbeddingRemoteRuntimeBackendIds(): readonly EmbeddingProviderId[] { + return resolveExtensionHostRuntimeBackendIdsByPolicy({ + entries: listExtensionHostEmbeddingRuntimeBackendCatalogEntries(), + subsystemId: "embedding", + include: (entry) => entry.backendId !== "local" && entry.metadata?.autoSelectable === true, + }).map((backendId) => backendId as EmbeddingProviderId); +} export function resolveExtensionHostEmbeddingFallbackPolicy(params: { requestedProvider: EmbeddingProviderRequest | EmbeddingProviderId; diff --git a/src/extension-host/embedding-runtime-registry.test.ts b/src/extension-host/embedding-runtime-registry.test.ts index aae75dace70..a9ec5b4ac8b 100644 --- a/src/extension-host/embedding-runtime-registry.test.ts +++ b/src/extension-host/embedding-runtime-registry.test.ts @@ -6,7 +6,10 @@ const listExtensionHostEmbeddingRemoteRuntimeBackendIds = vi.hoisted(() => const createGeminiEmbeddingProvider = vi.hoisted(() => vi.fn()); const createOpenAiEmbeddingProvider = vi.hoisted(() => vi.fn()); -vi.mock("./runtime-backend-catalog.js", () => ({ +vi.mock("./embedding-runtime-policy.js", async () => ({ + ...(await vi.importActual( + "./embedding-runtime-policy.js", + )), listExtensionHostEmbeddingRemoteRuntimeBackendIds, })); diff --git a/src/extension-host/embedding-runtime-registry.ts b/src/extension-host/embedding-runtime-registry.ts index 096f5989bb9..ce857dbd5cd 100644 --- a/src/extension-host/embedding-runtime-registry.ts +++ b/src/extension-host/embedding-runtime-registry.ts @@ -26,14 +26,16 @@ import { import { importNodeLlamaCpp } from "../memory/node-llama.js"; import { resolveUserPath } from "../utils.js"; import { DEFAULT_EXTENSION_HOST_LOCAL_EMBEDDING_MODEL } from "./embedding-runtime-backends.js"; -import { resolveExtensionHostEmbeddingFallbackPolicy } from "./embedding-runtime-policy.js"; +import { + listExtensionHostEmbeddingRemoteRuntimeBackendIds, + resolveExtensionHostEmbeddingFallbackPolicy, +} from "./embedding-runtime-policy.js"; import type { EmbeddingProvider, EmbeddingProviderId, EmbeddingProviderOptions, EmbeddingProviderResult, } from "./embedding-runtime-types.js"; -import { listExtensionHostEmbeddingRemoteRuntimeBackendIds } from "./runtime-backend-catalog.js"; export type { GeminiEmbeddingClient, diff --git a/src/extension-host/runtime-backend-catalog.test.ts b/src/extension-host/runtime-backend-catalog.test.ts index 82316524a10..bf93e7e5dae 100644 --- a/src/extension-host/runtime-backend-catalog.test.ts +++ b/src/extension-host/runtime-backend-catalog.test.ts @@ -1,4 +1,5 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; +import { listExtensionHostEmbeddingRemoteRuntimeBackendIds } from "./embedding-runtime-policy.js"; vi.mock("./embedding-runtime-backends.js", () => ({ EXTENSION_HOST_EMBEDDING_RUNTIME_BACKEND_IDS: [ @@ -154,7 +155,7 @@ describe("runtime-backend-catalog", () => { subsystemId: "tts", backendId: "edge", }); - expect(catalog.listExtensionHostEmbeddingRemoteRuntimeBackendIds()).toEqual([ + expect(listExtensionHostEmbeddingRemoteRuntimeBackendIds()).toEqual([ "openai", "gemini", "voyage", diff --git a/src/extension-host/runtime-backend-catalog.ts b/src/extension-host/runtime-backend-catalog.ts index 488cd160bf3..3a9f0ded63e 100644 --- a/src/extension-host/runtime-backend-catalog.ts +++ b/src/extension-host/runtime-backend-catalog.ts @@ -5,7 +5,6 @@ import { EXTENSION_HOST_EMBEDDING_RUNTIME_BACKEND_IDS, isExtensionHostEmbeddingRuntimeBackendAutoSelectable, } from "./embedding-runtime-backends.js"; -import type { EmbeddingProviderId } from "./embedding-runtime-types.js"; import { buildExtensionHostMediaRuntimeSelectorKeys, listExtensionHostMediaAutoRuntimeBackendSeedIds, @@ -83,14 +82,6 @@ export function listExtensionHostEmbeddingRuntimeBackendCatalogEntries(): readon })); } -export function listExtensionHostEmbeddingRemoteRuntimeBackendIds(): readonly EmbeddingProviderId[] { - return listExtensionHostRuntimeBackendIdsByArbitration({ - entries: listExtensionHostEmbeddingRuntimeBackendCatalogEntries(), - subsystemId: "embedding", - include: (entry) => entry.backendId !== "local" && entry.metadata?.autoSelectable === true, - }).map((entry) => entry as EmbeddingProviderId); -} - export function listExtensionHostMediaRuntimeBackendCatalogEntries(): readonly ExtensionHostRuntimeBackendCatalogEntry[] { const entries: ExtensionHostRuntimeBackendCatalogEntry[] = []; for (const capability of ["audio", "image", "video"] as const) {