import { APIKEY_PROVIDERS, AUDIO_ONLY_PROVIDERS, CLOUD_AGENT_PROVIDERS, LOCAL_PROVIDERS, NOAUTH_PROVIDERS, OAUTH_PROVIDERS, SEARCH_PROVIDERS, UPSTREAM_PROXY_PROVIDERS, WEB_COOKIE_PROVIDERS, isClaudeCodeCompatibleProvider, supportsApiKeyOnFreeProvider, type RiskNoticeVariant, } from "@/shared/constants/providers"; export type ProviderDisplayAuthType = "oauth" | "apikey" | "compatible" | "no-auth"; export type ProviderToggleAuthType = "oauth" | "free" | "apikey" | "no-auth"; export type StaticProviderCatalogCategory = | "no-auth" | "oauth" | "web-cookie" | "local" | "search" | "audio" | "upstream-proxy" | "apikey" | "cloud-agent"; export interface ProviderCatalogMetadata { id: string; name: string; color: string; alias?: string; icon?: string; textIcon?: string; website?: string; authHint?: string; apiHint?: string; passthroughModels?: boolean; subscriptionRisk?: boolean; riskNoticeVariant?: RiskNoticeVariant; apiType?: string; baseUrl?: string; [key: string]: unknown; } type ProviderRecord = Record; export interface StaticProviderCatalogGroup { category: StaticProviderCatalogCategory; providers: ProviderRecord; displayAuthType: Exclude; toggleAuthType: ProviderToggleAuthType; } export interface CompatibleProviderNodeLike { id: string; name?: string | null; type?: string | null; apiType?: string | null; baseUrl?: string | null; } export interface CompatibleProviderLabels { ccCompatibleName: string; anthropicCompatibleName: string; openAiCompatibleName: string; } export interface ResolvedStaticProviderCatalogEntry extends ProviderCatalogMetadata { category: StaticProviderCatalogCategory; displayAuthType: Exclude; toggleAuthType: ProviderToggleAuthType; isCompatible: false; } export interface ResolvedCompatibleProviderCatalogEntry extends ProviderCatalogMetadata { category: "compatible"; displayAuthType: "compatible"; toggleAuthType: "apikey"; isCompatible: true; type?: string | null; } export type ResolvedProviderCatalogEntry = | ResolvedStaticProviderCatalogEntry | ResolvedCompatibleProviderCatalogEntry; export const STATIC_PROVIDER_CATALOG_GROUPS: Record< StaticProviderCatalogCategory, StaticProviderCatalogGroup > = { "no-auth": { category: "no-auth", providers: NOAUTH_PROVIDERS as ProviderRecord, displayAuthType: "no-auth", toggleAuthType: "no-auth", }, oauth: { category: "oauth", providers: OAUTH_PROVIDERS as ProviderRecord, displayAuthType: "oauth", toggleAuthType: "oauth", }, "web-cookie": { category: "web-cookie", providers: WEB_COOKIE_PROVIDERS as ProviderRecord, displayAuthType: "apikey", toggleAuthType: "apikey", }, local: { category: "local", providers: LOCAL_PROVIDERS as ProviderRecord, displayAuthType: "apikey", toggleAuthType: "apikey", }, search: { category: "search", providers: SEARCH_PROVIDERS as ProviderRecord, displayAuthType: "apikey", toggleAuthType: "apikey", }, audio: { category: "audio", providers: AUDIO_ONLY_PROVIDERS as ProviderRecord, displayAuthType: "apikey", toggleAuthType: "apikey", }, "upstream-proxy": { category: "upstream-proxy", providers: UPSTREAM_PROXY_PROVIDERS as ProviderRecord, displayAuthType: "apikey", toggleAuthType: "apikey", }, apikey: { category: "apikey", providers: APIKEY_PROVIDERS as ProviderRecord, displayAuthType: "apikey", toggleAuthType: "apikey", }, "cloud-agent": { category: "cloud-agent", providers: CLOUD_AGENT_PROVIDERS as ProviderRecord, displayAuthType: "apikey", toggleAuthType: "apikey", }, }; export const STATIC_PROVIDER_CATALOG_RESOLUTION_ORDER: StaticProviderCatalogCategory[] = [ "no-auth", "oauth", "web-cookie", "local", "search", "audio", "upstream-proxy", "cloud-agent", "apikey", ]; const MANAGED_PROVIDER_CONNECTION_CATEGORIES = new Set([ "apikey", "web-cookie", "local", "search", "audio", "cloud-agent", ]); export function getStaticProviderCatalogGroup( category: StaticProviderCatalogCategory ): StaticProviderCatalogGroup { return STATIC_PROVIDER_CATALOG_GROUPS[category]; } export function getStaticProviderCategories(providerId: string): StaticProviderCatalogCategory[] { const categories: StaticProviderCatalogCategory[] = []; for (const category of STATIC_PROVIDER_CATALOG_RESOLUTION_ORDER) { if (STATIC_PROVIDER_CATALOG_GROUPS[category].providers[providerId]) { categories.push(category); } } return categories; } export function resolveStaticProviderCatalogEntry( providerId: string ): ResolvedStaticProviderCatalogEntry | null { for (const category of STATIC_PROVIDER_CATALOG_RESOLUTION_ORDER) { const group = STATIC_PROVIDER_CATALOG_GROUPS[category]; const provider = group.providers[providerId]; if (!provider) continue; return { ...provider, category, displayAuthType: group.displayAuthType, toggleAuthType: group.toggleAuthType, isCompatible: false, }; } return null; } export function isManagedProviderConnectionId(providerId: string): boolean { if (supportsApiKeyOnFreeProvider(providerId)) return true; const entry = resolveStaticProviderCatalogEntry(providerId); return !!(entry && MANAGED_PROVIDER_CONNECTION_CATEGORIES.has(entry.category)); } export function resolveCompatibleProviderCatalogEntry( providerNode: CompatibleProviderNodeLike, labels: CompatibleProviderLabels ): ResolvedCompatibleProviderCatalogEntry { const isCcCompatible = isClaudeCodeCompatibleProvider(providerNode.id); const isAnthropicCompatible = providerNode.type === "anthropic-compatible" && !isCcCompatible; return { id: providerNode.id, name: providerNode.name || (isCcCompatible ? labels.ccCompatibleName : isAnthropicCompatible ? labels.anthropicCompatibleName : labels.openAiCompatibleName), color: isCcCompatible ? "#B45309" : isAnthropicCompatible ? "#D97757" : "#10A37F", textIcon: isCcCompatible ? "CC" : isAnthropicCompatible ? "AC" : "OC", apiType: providerNode.apiType || undefined, baseUrl: providerNode.baseUrl || undefined, type: providerNode.type, category: "compatible", displayAuthType: "compatible", toggleAuthType: "apikey", isCompatible: true, }; } export function resolveProviderCatalogEntry( providerId: string, options?: { providerNode?: CompatibleProviderNodeLike | null; compatibleLabels?: CompatibleProviderLabels | null; } ): ResolvedProviderCatalogEntry | null { if (options?.providerNode && options.compatibleLabels) { return resolveCompatibleProviderCatalogEntry(options.providerNode, options.compatibleLabels); } return resolveStaticProviderCatalogEntry(providerId); }