| 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 } : {}), |
| }; |
| } |
|
|