mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-13 23:30:44 +00:00
115 lines
3.7 KiB
TypeScript
115 lines
3.7 KiB
TypeScript
import { normalizeProviderId } from "../agents/provider-id.js";
|
|
import type { ModelProviderConfig } from "../config/types.js";
|
|
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
|
import { resolveBundledPluginsDir } from "./bundled-dir.js";
|
|
import { loadPluginManifestRegistry, type PluginManifestRegistry } from "./manifest-registry.js";
|
|
import type {
|
|
ProviderApplyConfigDefaultsContext,
|
|
ProviderNormalizeConfigContext,
|
|
ProviderResolveConfigApiKeyContext,
|
|
} from "./provider-config-context.types.js";
|
|
import type {
|
|
ProviderDefaultThinkingPolicyContext,
|
|
ProviderThinkingProfile,
|
|
} from "./provider-thinking.types.js";
|
|
import { loadBundledPluginPublicArtifactModuleSync } from "./public-surface-loader.js";
|
|
|
|
const PROVIDER_POLICY_ARTIFACT_CANDIDATES = ["provider-policy-api.js"] as const;
|
|
|
|
export type BundledProviderPolicySurface = {
|
|
normalizeConfig?: (ctx: ProviderNormalizeConfigContext) => ModelProviderConfig | null | undefined;
|
|
applyConfigDefaults?: (
|
|
ctx: ProviderApplyConfigDefaultsContext,
|
|
) => OpenClawConfig | null | undefined;
|
|
resolveConfigApiKey?: (ctx: ProviderResolveConfigApiKeyContext) => string | null | undefined;
|
|
resolveThinkingProfile?: (
|
|
ctx: ProviderDefaultThinkingPolicyContext,
|
|
) => ProviderThinkingProfile | null | undefined;
|
|
};
|
|
|
|
function hasProviderPolicyHook(
|
|
mod: Record<string, unknown>,
|
|
): mod is Record<string, unknown> & BundledProviderPolicySurface {
|
|
return (
|
|
typeof mod.normalizeConfig === "function" ||
|
|
typeof mod.applyConfigDefaults === "function" ||
|
|
typeof mod.resolveConfigApiKey === "function" ||
|
|
typeof mod.resolveThinkingProfile === "function"
|
|
);
|
|
}
|
|
|
|
function tryLoadBundledProviderPolicySurface(
|
|
pluginId: string,
|
|
): BundledProviderPolicySurface | null {
|
|
for (const artifactBasename of PROVIDER_POLICY_ARTIFACT_CANDIDATES) {
|
|
try {
|
|
const mod = loadBundledPluginPublicArtifactModuleSync<Record<string, unknown>>({
|
|
dirName: pluginId,
|
|
artifactBasename,
|
|
});
|
|
if (hasProviderPolicyHook(mod)) {
|
|
return mod;
|
|
}
|
|
} catch (error) {
|
|
if (
|
|
error instanceof Error &&
|
|
error.message.startsWith("Unable to resolve bundled plugin public surface ")
|
|
) {
|
|
continue;
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function resolveBundledProviderPolicyPluginId(
|
|
providerId: string,
|
|
options: { manifestRegistry?: Pick<PluginManifestRegistry, "plugins"> } = {},
|
|
): string | null {
|
|
const normalizedProviderId = normalizeProviderId(providerId);
|
|
if (!normalizedProviderId) {
|
|
return null;
|
|
}
|
|
const bundledPluginsDir = resolveBundledPluginsDir();
|
|
if (!bundledPluginsDir) {
|
|
return null;
|
|
}
|
|
|
|
const registry = options.manifestRegistry ?? loadPluginManifestRegistry();
|
|
for (const plugin of registry.plugins.toSorted((left, right) =>
|
|
left.id.localeCompare(right.id),
|
|
)) {
|
|
if (plugin.origin !== "bundled") {
|
|
continue;
|
|
}
|
|
const ownsProvider = plugin.providers.some(
|
|
(provider) => normalizeProviderId(provider) === normalizedProviderId,
|
|
);
|
|
if (ownsProvider) {
|
|
return plugin.id;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
export function resolveBundledProviderPolicySurface(
|
|
providerId: string,
|
|
options: { manifestRegistry?: Pick<PluginManifestRegistry, "plugins"> } = {},
|
|
): BundledProviderPolicySurface | null {
|
|
const normalizedProviderId = normalizeProviderId(providerId);
|
|
if (!normalizedProviderId) {
|
|
return null;
|
|
}
|
|
const directSurface = tryLoadBundledProviderPolicySurface(normalizedProviderId);
|
|
if (directSurface) {
|
|
return directSurface;
|
|
}
|
|
const ownerPluginId = resolveBundledProviderPolicyPluginId(normalizedProviderId, options);
|
|
if (!ownerPluginId || ownerPluginId === normalizedProviderId) {
|
|
return null;
|
|
}
|
|
return tryLoadBundledProviderPolicySurface(ownerPluginId);
|
|
}
|