From 07df59287a853dad4e1d6af5636f36baba916bc7 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 27 Mar 2026 13:59:25 +0000 Subject: [PATCH] refactor: share plugin capability provider resolution --- src/image-generation/provider-registry.ts | 16 ++++++------ src/media-understanding/provider-registry.ts | 15 +++++------ src/plugins/capability-provider-runtime.ts | 27 ++++++++++++++++++++ src/tts/provider-registry.ts | 13 ++++------ 4 files changed, 46 insertions(+), 25 deletions(-) create mode 100644 src/plugins/capability-provider-runtime.ts diff --git a/src/image-generation/provider-registry.ts b/src/image-generation/provider-registry.ts index 83696445933..0d90fc31edc 100644 --- a/src/image-generation/provider-registry.ts +++ b/src/image-generation/provider-registry.ts @@ -1,8 +1,8 @@ import { normalizeProviderId } from "../agents/model-selection.js"; import type { OpenClawConfig } from "../config/config.js"; import { isBlockedObjectKey } from "../infra/prototype-keys.js"; -import { loadOpenClawPlugins } from "../plugins/loader.js"; -import { getActivePluginRegistry, getActivePluginRegistryKey } from "../plugins/runtime.js"; +import { resolvePluginCapabilityProviders } from "../plugins/capability-provider-runtime.js"; +import { getActivePluginRegistryKey } from "../plugins/runtime.js"; import type { ImageGenerationProviderPlugin } from "../plugins/types.js"; const BUILTIN_IMAGE_GENERATION_PROVIDERS: readonly ImageGenerationProviderPlugin[] = []; @@ -23,12 +23,12 @@ function isSafeImageGenerationProviderId(id: string | undefined): id is string { function resolvePluginImageGenerationProviders( cfg?: OpenClawConfig, ): ImageGenerationProviderPlugin[] { - const active = getActivePluginRegistry(); - const registry = - (active?.imageGenerationProviders?.length ?? 0) > 0 || getActivePluginRegistryKey() || !cfg - ? active - : loadOpenClawPlugins({ config: cfg }); - return registry?.imageGenerationProviders?.map((entry) => entry.provider) ?? []; + return resolvePluginCapabilityProviders({ + key: "imageGenerationProviders", + cfg, + useActiveRegistryWhen: (active) => + (active?.imageGenerationProviders?.length ?? 0) > 0 || Boolean(getActivePluginRegistryKey()), + }); } function buildProviderMaps(cfg?: OpenClawConfig): { diff --git a/src/media-understanding/provider-registry.ts b/src/media-understanding/provider-registry.ts index 018d4edc58a..b56faf97bfd 100644 --- a/src/media-understanding/provider-registry.ts +++ b/src/media-understanding/provider-registry.ts @@ -1,6 +1,5 @@ import type { OpenClawConfig } from "../config/config.js"; -import { loadOpenClawPlugins } from "../plugins/loader.js"; -import { getActivePluginRegistry } from "../plugins/runtime.js"; +import { resolvePluginCapabilityProviders } from "../plugins/capability-provider-runtime.js"; import { normalizeMediaProviderId } from "./provider-id.js"; import type { MediaUnderstandingProvider } from "./types.js"; @@ -27,13 +26,11 @@ export function buildMediaUnderstandingRegistry( cfg?: OpenClawConfig, ): Map { const registry = new Map(); - const active = getActivePluginRegistry(); - const pluginRegistry = - (active?.mediaUnderstandingProviders?.length ?? 0) > 0 || !cfg - ? active - : loadOpenClawPlugins({ config: cfg }); - for (const entry of pluginRegistry?.mediaUnderstandingProviders ?? []) { - mergeProviderIntoRegistry(registry, entry.provider); + for (const provider of resolvePluginCapabilityProviders({ + key: "mediaUnderstandingProviders", + cfg, + })) { + mergeProviderIntoRegistry(registry, provider); } if (overrides) { for (const [key, provider] of Object.entries(overrides)) { diff --git a/src/plugins/capability-provider-runtime.ts b/src/plugins/capability-provider-runtime.ts new file mode 100644 index 00000000000..46ec8d7433a --- /dev/null +++ b/src/plugins/capability-provider-runtime.ts @@ -0,0 +1,27 @@ +import type { OpenClawConfig } from "../config/config.js"; +import { loadOpenClawPlugins } from "./loader.js"; +import type { PluginRegistry } from "./registry.js"; +import { getActivePluginRegistry } from "./runtime.js"; + +type CapabilityProviderRegistryKey = + | "speechProviders" + | "mediaUnderstandingProviders" + | "imageGenerationProviders"; + +type CapabilityProviderForKey = + PluginRegistry[K][number] extends { provider: infer T } ? T : never; + +export function resolvePluginCapabilityProviders(params: { + key: K; + cfg?: OpenClawConfig; + useActiveRegistryWhen?: (active: PluginRegistry | undefined) => boolean; +}): CapabilityProviderForKey[] { + const active = getActivePluginRegistry(); + const shouldUseActive = + params.useActiveRegistryWhen?.(active) ?? (active?.[params.key].length ?? 0) > 0; + const registry = + shouldUseActive || !params.cfg ? active : loadOpenClawPlugins({ config: params.cfg }); + return (registry?.[params.key] ?? []).map( + (entry) => entry.provider, + ) as CapabilityProviderForKey[]; +} diff --git a/src/tts/provider-registry.ts b/src/tts/provider-registry.ts index f782e9a9b86..8d71f467d6a 100644 --- a/src/tts/provider-registry.ts +++ b/src/tts/provider-registry.ts @@ -1,6 +1,5 @@ import type { OpenClawConfig } from "../config/config.js"; -import { loadOpenClawPlugins } from "../plugins/loader.js"; -import { getActivePluginRegistry } from "../plugins/runtime.js"; +import { resolvePluginCapabilityProviders } from "../plugins/capability-provider-runtime.js"; import type { SpeechProviderPlugin } from "../plugins/types.js"; import type { SpeechProviderId } from "./provider-types.js"; @@ -16,12 +15,10 @@ export function normalizeSpeechProviderId( } function resolveSpeechProviderPluginEntries(cfg?: OpenClawConfig): SpeechProviderPlugin[] { - const active = getActivePluginRegistry(); - const registry = - (active?.speechProviders?.length ?? 0) > 0 || !cfg - ? active - : loadOpenClawPlugins({ config: cfg }); - return registry?.speechProviders?.map((entry) => entry.provider) ?? []; + return resolvePluginCapabilityProviders({ + key: "speechProviders", + cfg, + }); } function buildProviderMaps(cfg?: OpenClawConfig): {