import { normalizeProviderId } from "../agents/model-selection.js"; import type { OpenClawConfig } from "../config/config.js"; import type { ModelProviderConfig } from "../config/types.js"; import type { ProviderDiscoveryOrder, ProviderPlugin } from "./types.js"; const DISCOVERY_ORDER: readonly ProviderDiscoveryOrder[] = ["simple", "profile", "paired", "late"]; let providerRuntimePromise: Promise | undefined; function loadProviderRuntime() { providerRuntimePromise ??= import("./provider-discovery.runtime.js"); return providerRuntimePromise; } function resolveProviderCatalogHook(provider: ProviderPlugin) { return provider.catalog ?? provider.discovery; } export async function resolvePluginDiscoveryProviders(params: { config?: OpenClawConfig; workspaceDir?: string; env?: NodeJS.ProcessEnv; onlyPluginIds?: string[]; }): Promise { return (await loadProviderRuntime()) .resolvePluginDiscoveryProvidersRuntime(params) .filter((provider) => resolveProviderCatalogHook(provider)); } export function groupPluginDiscoveryProvidersByOrder( providers: ProviderPlugin[], ): Record { const grouped = { simple: [], profile: [], paired: [], late: [], } as Record; for (const provider of providers) { const order = resolveProviderCatalogHook(provider)?.order ?? "late"; grouped[order].push(provider); } for (const order of DISCOVERY_ORDER) { grouped[order].sort((a, b) => a.label.localeCompare(b.label)); } return grouped; } export function normalizePluginDiscoveryResult(params: { provider: ProviderPlugin; result: | { provider: ModelProviderConfig } | { providers: Record } | null | undefined; }): Record { const result = params.result; if (!result) { return {}; } if ("provider" in result) { return { [normalizeProviderId(params.provider.id)]: result.provider }; } const normalized: Record = {}; for (const [key, value] of Object.entries(result.providers)) { const normalizedKey = normalizeProviderId(key); if (!normalizedKey || !value) { continue; } normalized[normalizedKey] = value; } return normalized; } export function runProviderCatalog(params: { provider: ProviderPlugin; config: OpenClawConfig; agentDir?: string; workspaceDir?: string; env: NodeJS.ProcessEnv; resolveProviderApiKey: (providerId?: string) => { apiKey: string | undefined; discoveryApiKey?: string; }; resolveProviderAuth: ( providerId?: string, options?: { oauthMarker?: string }, ) => { apiKey: string | undefined; discoveryApiKey?: string; mode: "api_key" | "oauth" | "token" | "none"; source: "env" | "profile" | "none"; profileId?: string; }; }) { return resolveProviderCatalogHook(params.provider)?.run({ config: params.config, agentDir: params.agentDir, workspaceDir: params.workspaceDir, env: params.env, resolveProviderApiKey: params.resolveProviderApiKey, resolveProviderAuth: params.resolveProviderAuth, }); }