mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-16 04:20:44 +00:00
233 lines
7.1 KiB
TypeScript
233 lines
7.1 KiB
TypeScript
import type { PluginDiagnostic, ProviderAuthMethod, ProviderPlugin } from "./types.js";
|
|
|
|
function pushProviderDiagnostic(params: {
|
|
level: PluginDiagnostic["level"];
|
|
pluginId: string;
|
|
source: string;
|
|
message: string;
|
|
pushDiagnostic: (diag: PluginDiagnostic) => void;
|
|
}) {
|
|
params.pushDiagnostic({
|
|
level: params.level,
|
|
pluginId: params.pluginId,
|
|
source: params.source,
|
|
message: params.message,
|
|
});
|
|
}
|
|
|
|
function normalizeText(value: string | undefined): string | undefined {
|
|
const trimmed = value?.trim();
|
|
return trimmed ? trimmed : undefined;
|
|
}
|
|
|
|
function normalizeTextList(values: string[] | undefined): string[] | undefined {
|
|
const normalized = Array.from(
|
|
new Set((values ?? []).map((value) => value.trim()).filter(Boolean)),
|
|
);
|
|
return normalized.length > 0 ? normalized : undefined;
|
|
}
|
|
|
|
function normalizeProviderAuthMethods(params: {
|
|
providerId: string;
|
|
pluginId: string;
|
|
source: string;
|
|
auth: ProviderAuthMethod[];
|
|
pushDiagnostic: (diag: PluginDiagnostic) => void;
|
|
}): ProviderAuthMethod[] {
|
|
const seenMethodIds = new Set<string>();
|
|
const normalized: ProviderAuthMethod[] = [];
|
|
|
|
for (const method of params.auth) {
|
|
const methodId = normalizeText(method.id);
|
|
if (!methodId) {
|
|
pushProviderDiagnostic({
|
|
level: "error",
|
|
pluginId: params.pluginId,
|
|
source: params.source,
|
|
message: `provider "${params.providerId}" auth method missing id`,
|
|
pushDiagnostic: params.pushDiagnostic,
|
|
});
|
|
continue;
|
|
}
|
|
if (seenMethodIds.has(methodId)) {
|
|
pushProviderDiagnostic({
|
|
level: "error",
|
|
pluginId: params.pluginId,
|
|
source: params.source,
|
|
message: `provider "${params.providerId}" auth method duplicated id "${methodId}"`,
|
|
pushDiagnostic: params.pushDiagnostic,
|
|
});
|
|
continue;
|
|
}
|
|
seenMethodIds.add(methodId);
|
|
normalized.push({
|
|
...method,
|
|
id: methodId,
|
|
label: normalizeText(method.label) ?? methodId,
|
|
...(normalizeText(method.hint) ? { hint: normalizeText(method.hint) } : {}),
|
|
});
|
|
}
|
|
|
|
return normalized;
|
|
}
|
|
|
|
function normalizeProviderWizard(params: {
|
|
providerId: string;
|
|
pluginId: string;
|
|
source: string;
|
|
auth: ProviderAuthMethod[];
|
|
wizard: ProviderPlugin["wizard"];
|
|
pushDiagnostic: (diag: PluginDiagnostic) => void;
|
|
}): ProviderPlugin["wizard"] {
|
|
if (!params.wizard) {
|
|
return undefined;
|
|
}
|
|
|
|
const hasAuthMethods = params.auth.length > 0;
|
|
const hasMethod = (methodId: string | undefined) =>
|
|
Boolean(methodId && params.auth.some((method) => method.id === methodId));
|
|
|
|
const normalizeOnboarding = () => {
|
|
const onboarding = params.wizard?.onboarding;
|
|
if (!onboarding) {
|
|
return undefined;
|
|
}
|
|
if (!hasAuthMethods) {
|
|
pushProviderDiagnostic({
|
|
level: "warn",
|
|
pluginId: params.pluginId,
|
|
source: params.source,
|
|
message: `provider "${params.providerId}" onboarding metadata ignored because it has no auth methods`,
|
|
pushDiagnostic: params.pushDiagnostic,
|
|
});
|
|
return undefined;
|
|
}
|
|
const methodId = normalizeText(onboarding.methodId);
|
|
if (methodId && !hasMethod(methodId)) {
|
|
pushProviderDiagnostic({
|
|
level: "warn",
|
|
pluginId: params.pluginId,
|
|
source: params.source,
|
|
message: `provider "${params.providerId}" onboarding method "${methodId}" not found; falling back to available methods`,
|
|
pushDiagnostic: params.pushDiagnostic,
|
|
});
|
|
}
|
|
return {
|
|
...(normalizeText(onboarding.choiceId)
|
|
? { choiceId: normalizeText(onboarding.choiceId) }
|
|
: {}),
|
|
...(normalizeText(onboarding.choiceLabel)
|
|
? { choiceLabel: normalizeText(onboarding.choiceLabel) }
|
|
: {}),
|
|
...(normalizeText(onboarding.choiceHint)
|
|
? { choiceHint: normalizeText(onboarding.choiceHint) }
|
|
: {}),
|
|
...(normalizeText(onboarding.groupId) ? { groupId: normalizeText(onboarding.groupId) } : {}),
|
|
...(normalizeText(onboarding.groupLabel)
|
|
? { groupLabel: normalizeText(onboarding.groupLabel) }
|
|
: {}),
|
|
...(normalizeText(onboarding.groupHint)
|
|
? { groupHint: normalizeText(onboarding.groupHint) }
|
|
: {}),
|
|
...(methodId && hasMethod(methodId) ? { methodId } : {}),
|
|
};
|
|
};
|
|
|
|
const normalizeModelPicker = () => {
|
|
const modelPicker = params.wizard?.modelPicker;
|
|
if (!modelPicker) {
|
|
return undefined;
|
|
}
|
|
if (!hasAuthMethods) {
|
|
pushProviderDiagnostic({
|
|
level: "warn",
|
|
pluginId: params.pluginId,
|
|
source: params.source,
|
|
message: `provider "${params.providerId}" model-picker metadata ignored because it has no auth methods`,
|
|
pushDiagnostic: params.pushDiagnostic,
|
|
});
|
|
return undefined;
|
|
}
|
|
const methodId = normalizeText(modelPicker.methodId);
|
|
if (methodId && !hasMethod(methodId)) {
|
|
pushProviderDiagnostic({
|
|
level: "warn",
|
|
pluginId: params.pluginId,
|
|
source: params.source,
|
|
message: `provider "${params.providerId}" model-picker method "${methodId}" not found; falling back to available methods`,
|
|
pushDiagnostic: params.pushDiagnostic,
|
|
});
|
|
}
|
|
return {
|
|
...(normalizeText(modelPicker.label) ? { label: normalizeText(modelPicker.label) } : {}),
|
|
...(normalizeText(modelPicker.hint) ? { hint: normalizeText(modelPicker.hint) } : {}),
|
|
...(methodId && hasMethod(methodId) ? { methodId } : {}),
|
|
};
|
|
};
|
|
|
|
const onboarding = normalizeOnboarding();
|
|
const modelPicker = normalizeModelPicker();
|
|
if (!onboarding && !modelPicker) {
|
|
return undefined;
|
|
}
|
|
return {
|
|
...(onboarding ? { onboarding } : {}),
|
|
...(modelPicker ? { modelPicker } : {}),
|
|
};
|
|
}
|
|
|
|
export function normalizeRegisteredProvider(params: {
|
|
pluginId: string;
|
|
source: string;
|
|
provider: ProviderPlugin;
|
|
pushDiagnostic: (diag: PluginDiagnostic) => void;
|
|
}): ProviderPlugin | null {
|
|
const id = normalizeText(params.provider.id);
|
|
if (!id) {
|
|
pushProviderDiagnostic({
|
|
level: "error",
|
|
pluginId: params.pluginId,
|
|
source: params.source,
|
|
message: "provider registration missing id",
|
|
pushDiagnostic: params.pushDiagnostic,
|
|
});
|
|
return null;
|
|
}
|
|
|
|
const auth = normalizeProviderAuthMethods({
|
|
providerId: id,
|
|
pluginId: params.pluginId,
|
|
source: params.source,
|
|
auth: params.provider.auth ?? [],
|
|
pushDiagnostic: params.pushDiagnostic,
|
|
});
|
|
const docsPath = normalizeText(params.provider.docsPath);
|
|
const aliases = normalizeTextList(params.provider.aliases);
|
|
const envVars = normalizeTextList(params.provider.envVars);
|
|
const wizard = normalizeProviderWizard({
|
|
providerId: id,
|
|
pluginId: params.pluginId,
|
|
source: params.source,
|
|
auth,
|
|
wizard: params.provider.wizard,
|
|
pushDiagnostic: params.pushDiagnostic,
|
|
});
|
|
const {
|
|
wizard: _ignoredWizard,
|
|
docsPath: _ignoredDocsPath,
|
|
aliases: _ignoredAliases,
|
|
envVars: _ignoredEnvVars,
|
|
...restProvider
|
|
} = params.provider;
|
|
return {
|
|
...restProvider,
|
|
id,
|
|
label: normalizeText(params.provider.label) ?? id,
|
|
...(docsPath ? { docsPath } : {}),
|
|
...(aliases ? { aliases } : {}),
|
|
...(envVars ? { envVars } : {}),
|
|
auth,
|
|
...(wizard ? { wizard } : {}),
|
|
};
|
|
}
|