refactor: share embedding provider runtime lookup

This commit is contained in:
Vincent Koc
2026-05-29 06:25:37 +02:00
parent 8a60f39221
commit 4b147f2c2e
3 changed files with 165 additions and 116 deletions

View File

@@ -0,0 +1,108 @@
import { normalizeProviderId } from "../agents/provider-id.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import {
resolvePluginCapabilityProvider,
resolvePluginCapabilityProviders,
} from "./capability-provider-runtime.js";
type EmbeddingProviderCapabilityKey = "embeddingProviders" | "memoryEmbeddingProviders";
type RegisteredAdapterEntry<TAdapter> = {
adapter: TAdapter;
};
type ConfiguredModelProvider = NonNullable<
NonNullable<OpenClawConfig["models"]>["providers"]
>[string];
function resolveConfiguredProviderConfig(
providerId: string,
cfg?: OpenClawConfig,
): ConfiguredModelProvider | undefined {
const providers = cfg?.models?.providers;
if (!providers) {
return undefined;
}
const normalized = normalizeProviderId(providerId);
return (
providers[providerId] ??
Object.entries(providers).find(
([candidateId]) => normalizeProviderId(candidateId) === normalized,
)?.[1]
);
}
export function readConfiguredProviderApiId(params: {
providerId: string;
cfg?: OpenClawConfig;
resolveApiProviderId?: (normalizedApiId: string) => string | undefined;
resolveMissingApiProviderId?: (providerConfig: ConfiguredModelProvider) => string | undefined;
}): string | undefined {
const providerConfig = resolveConfiguredProviderConfig(params.providerId, params.cfg);
if (!providerConfig) {
return undefined;
}
const normalized = normalizeProviderId(params.providerId);
const api = providerConfig.api?.trim();
const resolvedProviderId = api
? (params.resolveApiProviderId?.(normalizeProviderId(api)) ?? normalizeProviderId(api))
: params.resolveMissingApiProviderId?.(providerConfig);
return resolvedProviderId && resolvedProviderId !== normalized ? resolvedProviderId : undefined;
}
export function resolveRuntimeEmbeddingProviderLookupIds(params: {
id: string;
cfg?: OpenClawConfig;
resolveConfiguredProviderId: (id: string, cfg?: OpenClawConfig) => string | undefined;
}): string[] {
const ids = [params.id];
const configuredProviderId = params.resolveConfiguredProviderId(params.id, params.cfg);
if (
configuredProviderId &&
!ids.some((candidate) => normalizeProviderId(candidate) === configuredProviderId)
) {
ids.push(configuredProviderId);
}
return ids;
}
export function listRuntimeEmbeddingProviderAdapters<TAdapter extends { id: string }>(params: {
key: EmbeddingProviderCapabilityKey;
cfg?: OpenClawConfig;
registered: TAdapter[];
}): TAdapter[] {
const merged = new Map(params.registered.map((adapter) => [adapter.id, adapter]));
const capabilityAdapters = resolvePluginCapabilityProviders({
key: params.key,
cfg: params.cfg,
}) as unknown as TAdapter[];
for (const adapter of capabilityAdapters) {
if (!merged.has(adapter.id)) {
merged.set(adapter.id, adapter);
}
}
return [...merged.values()];
}
export function getRuntimeEmbeddingProviderAdapter<TAdapter extends { id: string }>(params: {
key: EmbeddingProviderCapabilityKey;
cfg?: OpenClawConfig;
lookupIds: string[];
getRegisteredProvider: (id: string) => RegisteredAdapterEntry<TAdapter> | undefined;
}): TAdapter | undefined {
for (const candidateId of params.lookupIds) {
const registered = params.getRegisteredProvider(candidateId);
if (registered) {
return registered.adapter;
}
}
for (const candidateId of params.lookupIds) {
const provider = resolvePluginCapabilityProvider({
key: params.key,
providerId: candidateId,
cfg: params.cfg,
}) as TAdapter | undefined;
if (provider) {
return provider;
}
}
return undefined;
}

View File

@@ -1,9 +1,10 @@
import { normalizeProviderId } from "../agents/provider-id.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import {
resolvePluginCapabilityProvider,
resolvePluginCapabilityProviders,
} from "./capability-provider-runtime.js";
getRuntimeEmbeddingProviderAdapter,
listRuntimeEmbeddingProviderAdapters,
readConfiguredProviderApiId,
resolveRuntimeEmbeddingProviderLookupIds,
} from "./embedding-provider-runtime-shared.js";
import {
getRegisteredEmbeddingProvider,
listRegisteredEmbeddingProviders,
@@ -20,77 +21,47 @@ export function listRegisteredEmbeddingProviderAdapters(): EmbeddingProviderAdap
}
export function listEmbeddingProviders(cfg?: OpenClawConfig): EmbeddingProviderAdapter[] {
const registered = listRegisteredEmbeddingProviderAdapters();
const merged = new Map(registered.map((adapter) => [adapter.id, adapter]));
for (const adapter of resolvePluginCapabilityProviders({
return listRuntimeEmbeddingProviderAdapters({
key: "embeddingProviders",
cfg,
})) {
if (!merged.has(adapter.id)) {
merged.set(adapter.id, adapter);
}
}
return [...merged.values()];
registered: listRegisteredEmbeddingProviderAdapters(),
});
}
function readConfiguredProviderApiId(providerId: string, cfg?: OpenClawConfig): string | undefined {
const providers = cfg?.models?.providers;
if (!providers) {
return undefined;
}
const normalized = normalizeProviderId(providerId);
const providerConfig =
providers[providerId] ??
Object.entries(providers).find(
([candidateId]) => normalizeProviderId(candidateId) === normalized,
)?.[1];
const api = providerConfig?.api?.trim();
if (!api && providerConfig?.baseUrl?.trim()) {
return OPENAI_COMPATIBLE_EMBEDDING_PROVIDER_ID;
}
if (!api) {
return undefined;
}
const normalizedApi = normalizeProviderId(api);
const embeddingProviderId = OPENAI_COMPATIBLE_MODEL_APIS.has(normalizedApi)
? OPENAI_COMPATIBLE_EMBEDDING_PROVIDER_ID
: normalizedApi;
return embeddingProviderId && embeddingProviderId !== normalized
? embeddingProviderId
: undefined;
function resolveConfiguredEmbeddingProviderId(
providerId: string,
cfg?: OpenClawConfig,
): string | undefined {
return readConfiguredProviderApiId({
providerId,
cfg,
resolveApiProviderId: (normalizedApiId) =>
OPENAI_COMPATIBLE_MODEL_APIS.has(normalizedApiId)
? OPENAI_COMPATIBLE_EMBEDDING_PROVIDER_ID
: normalizedApiId,
resolveMissingApiProviderId: (providerConfig) =>
providerConfig.baseUrl?.trim() ? OPENAI_COMPATIBLE_EMBEDDING_PROVIDER_ID : undefined,
});
}
function resolveEmbeddingProviderLookupIds(id: string, cfg?: OpenClawConfig): string[] {
const ids = [id];
const apiId = readConfiguredProviderApiId(id, cfg);
if (apiId && !ids.some((candidate) => normalizeProviderId(candidate) === apiId)) {
ids.push(apiId);
}
return ids;
return resolveRuntimeEmbeddingProviderLookupIds({
id,
cfg,
resolveConfiguredProviderId: resolveConfiguredEmbeddingProviderId,
});
}
export function getEmbeddingProvider(
id: string,
cfg?: OpenClawConfig,
): EmbeddingProviderAdapter | undefined {
const ids = resolveEmbeddingProviderLookupIds(id, cfg);
for (const candidateId of ids) {
const registered = getRegisteredEmbeddingProvider(candidateId);
if (registered) {
return registered.adapter;
}
}
for (const candidateId of ids) {
const provider = resolvePluginCapabilityProvider({
key: "embeddingProviders",
providerId: candidateId,
cfg,
});
if (provider) {
return provider;
}
}
return undefined;
return getRuntimeEmbeddingProviderAdapter({
key: "embeddingProviders",
cfg,
lookupIds: resolveEmbeddingProviderLookupIds(id, cfg),
getRegisteredProvider: getRegisteredEmbeddingProvider,
});
}
export type {

View File

@@ -1,9 +1,10 @@
import { normalizeProviderId } from "../agents/provider-id.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import {
resolvePluginCapabilityProvider,
resolvePluginCapabilityProviders,
} from "./capability-provider-runtime.js";
getRuntimeEmbeddingProviderAdapter,
listRuntimeEmbeddingProviderAdapters,
readConfiguredProviderApiId,
resolveRuntimeEmbeddingProviderLookupIds,
} from "./embedding-provider-runtime-shared.js";
import {
getRegisteredMemoryEmbeddingProvider,
listRegisteredMemoryEmbeddingProviders,
@@ -18,67 +19,36 @@ export function listRegisteredMemoryEmbeddingProviderAdapters(): MemoryEmbedding
export function listMemoryEmbeddingProviders(
cfg?: OpenClawConfig,
): MemoryEmbeddingProviderAdapter[] {
const registered = listRegisteredMemoryEmbeddingProviderAdapters();
const merged = new Map(registered.map((adapter) => [adapter.id, adapter]));
for (const adapter of resolvePluginCapabilityProviders({
return listRuntimeEmbeddingProviderAdapters({
key: "memoryEmbeddingProviders",
cfg,
})) {
if (!merged.has(adapter.id)) {
merged.set(adapter.id, adapter);
}
}
return [...merged.values()];
registered: listRegisteredMemoryEmbeddingProviderAdapters(),
});
}
function readConfiguredProviderApiId(providerId: string, cfg?: OpenClawConfig): string | undefined {
const providers = cfg?.models?.providers;
if (!providers) {
return undefined;
}
const normalized = normalizeProviderId(providerId);
const providerConfig =
providers[providerId] ??
Object.entries(providers).find(
([candidateId]) => normalizeProviderId(candidateId) === normalized,
)?.[1];
const api = providerConfig?.api?.trim();
if (!api) {
return undefined;
}
const normalizedApi = normalizeProviderId(api);
return normalizedApi && normalizedApi !== normalized ? normalizedApi : undefined;
function resolveConfiguredMemoryEmbeddingProviderId(
providerId: string,
cfg?: OpenClawConfig,
): string | undefined {
return readConfiguredProviderApiId({ providerId, cfg });
}
function resolveMemoryEmbeddingProviderLookupIds(id: string, cfg?: OpenClawConfig): string[] {
const ids = [id];
const apiId = readConfiguredProviderApiId(id, cfg);
if (apiId && !ids.some((candidate) => normalizeProviderId(candidate) === apiId)) {
ids.push(apiId);
}
return ids;
return resolveRuntimeEmbeddingProviderLookupIds({
id,
cfg,
resolveConfiguredProviderId: resolveConfiguredMemoryEmbeddingProviderId,
});
}
export function getMemoryEmbeddingProvider(
id: string,
cfg?: OpenClawConfig,
): MemoryEmbeddingProviderAdapter | undefined {
const ids = resolveMemoryEmbeddingProviderLookupIds(id, cfg);
for (const candidateId of ids) {
const registered = getRegisteredMemoryEmbeddingProvider(candidateId);
if (registered) {
return registered.adapter;
}
}
for (const candidateId of ids) {
const provider = resolvePluginCapabilityProvider({
key: "memoryEmbeddingProviders",
providerId: candidateId,
cfg,
});
if (provider) {
return provider;
}
}
return undefined;
return getRuntimeEmbeddingProviderAdapter({
key: "memoryEmbeddingProviders",
cfg,
lookupIds: resolveMemoryEmbeddingProviderLookupIds(id, cfg),
getRegisteredProvider: getRegisteredMemoryEmbeddingProvider,
});
}