mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 11:10:45 +00:00
fix(media): decouple capability registry from runtime loaders
This commit is contained in:
@@ -1,13 +1,9 @@
|
||||
import type { MediaUnderstandingModelConfig } from "../config/types.tools.js";
|
||||
import { normalizeMediaProviderId } from "./provider-id.js";
|
||||
import type { MediaUnderstandingCapability } from "./types.js";
|
||||
|
||||
export type MediaUnderstandingCapabilityRegistry = Map<
|
||||
string,
|
||||
{
|
||||
capabilities?: MediaUnderstandingCapability[];
|
||||
}
|
||||
>;
|
||||
import type {
|
||||
MediaUnderstandingCapability,
|
||||
MediaUnderstandingCapabilityRegistry,
|
||||
} from "./types.js";
|
||||
|
||||
const MEDIA_CAPABILITIES = ["audio", "image", "video"] as const;
|
||||
|
||||
|
||||
61
src/media-understanding/provider-capability-registry.ts
Normal file
61
src/media-understanding/provider-capability-registry.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import type { OpenClawConfig } from "../config/types.js";
|
||||
import { resolvePluginCapabilityProviders } from "../plugins/capability-provider-runtime.js";
|
||||
import { normalizeMediaProviderId } from "./provider-id.js";
|
||||
import type { MediaUnderstandingCapabilityRegistry, MediaUnderstandingProvider } from "./types.js";
|
||||
|
||||
type ConfigProvider = NonNullable<
|
||||
NonNullable<NonNullable<OpenClawConfig["models"]>["providers"]>[string]
|
||||
>;
|
||||
|
||||
type ConfigProviderModel = NonNullable<ConfigProvider["models"]>[number];
|
||||
|
||||
function mergeProviderCapabilities(
|
||||
registry: MediaUnderstandingCapabilityRegistry,
|
||||
provider: Pick<MediaUnderstandingProvider, "id" | "capabilities">,
|
||||
) {
|
||||
const normalizedKey = normalizeMediaProviderId(provider.id);
|
||||
const existing = registry.get(normalizedKey);
|
||||
registry.set(normalizedKey, {
|
||||
capabilities: provider.capabilities ?? existing?.capabilities,
|
||||
});
|
||||
}
|
||||
|
||||
export function buildMediaUnderstandingCapabilityRegistry(
|
||||
cfg?: OpenClawConfig,
|
||||
): MediaUnderstandingCapabilityRegistry {
|
||||
const registry: MediaUnderstandingCapabilityRegistry = new Map();
|
||||
|
||||
for (const provider of resolvePluginCapabilityProviders({
|
||||
key: "mediaUnderstandingProviders",
|
||||
cfg,
|
||||
})) {
|
||||
mergeProviderCapabilities(registry, provider);
|
||||
}
|
||||
|
||||
const configProviders = cfg?.models?.providers;
|
||||
if (configProviders && typeof configProviders === "object") {
|
||||
for (const [providerKey, providerCfg] of Object.entries(configProviders)) {
|
||||
if (!providerKey?.trim()) {
|
||||
continue;
|
||||
}
|
||||
const normalizedKey = normalizeMediaProviderId(providerKey);
|
||||
if (registry.has(normalizedKey)) {
|
||||
continue;
|
||||
}
|
||||
const models = providerCfg.models ?? [];
|
||||
const hasImageModel = models.some(
|
||||
(model: ConfigProviderModel) =>
|
||||
Array.isArray(model?.input) && model.input.includes("image"),
|
||||
);
|
||||
if (!hasImageModel) {
|
||||
continue;
|
||||
}
|
||||
mergeProviderCapabilities(registry, {
|
||||
id: normalizedKey,
|
||||
capabilities: ["image"],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return registry;
|
||||
}
|
||||
@@ -7,6 +7,13 @@ export type MediaUnderstandingKind =
|
||||
|
||||
export type MediaUnderstandingCapability = "image" | "audio" | "video";
|
||||
|
||||
export type MediaUnderstandingCapabilityRegistry = Map<
|
||||
string,
|
||||
{
|
||||
capabilities?: MediaUnderstandingCapability[];
|
||||
}
|
||||
>;
|
||||
|
||||
export type MediaAttachment = {
|
||||
path?: string;
|
||||
url?: string;
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
resolveConfiguredMediaEntryCapabilities,
|
||||
resolveEffectiveMediaEntryCapabilities,
|
||||
} from "../media-understanding/entry-capabilities.js";
|
||||
import { buildMediaUnderstandingRegistry } from "../media-understanding/provider-registry.js";
|
||||
import { buildMediaUnderstandingCapabilityRegistry } from "../media-understanding/provider-capability-registry.js";
|
||||
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
|
||||
import { collectTtsApiKeyAssignments } from "./runtime-config-collectors-tts.js";
|
||||
import { evaluateGatewayAuthSurfaceStates } from "./runtime-gateway-auth-surfaces.js";
|
||||
@@ -401,9 +401,9 @@ function collectMediaRequestAssignments(params: {
|
||||
return;
|
||||
}
|
||||
|
||||
let providerRegistry: ReturnType<typeof buildMediaUnderstandingRegistry> | undefined;
|
||||
let providerRegistry: ReturnType<typeof buildMediaUnderstandingCapabilityRegistry> | undefined;
|
||||
const getProviderRegistry = () => {
|
||||
providerRegistry ??= buildMediaUnderstandingRegistry(undefined, params.config);
|
||||
providerRegistry ??= buildMediaUnderstandingCapabilityRegistry(params.config);
|
||||
return providerRegistry;
|
||||
};
|
||||
const capabilityKeys = ["audio", "image", "video"] as const;
|
||||
|
||||
Reference in New Issue
Block a user