import type { EffectProviderFactory } from '../base'; /** * Dynamic registry for provider packs. * * Supports both built-in providers (from @fancyrobot/fred-* packages) and * external providers (registered at runtime by custom packages). * * Provider packages auto-register themselves when imported: * * @example * ```typescript * // In your application: * import '@fancyrobot/fred-openai'; // Auto-registers OpenAI provider * import '@fancyrobot/fred-anthropic'; // Auto-registers Anthropic provider * * // Now these providers are available via Fred's provider system * await fred.useProvider('openai'); * await fred.useProvider('anthropic'); * ``` */ const packRegistry = new Map(); /** * Register a provider pack in the registry. * * This function is used by provider packages to register themselves: * - Built-in providers from @fancyrobot/fred-* packages call this on import * - External providers can also call this during their initialization * * @param pack - The provider factory to register */ export function registerBuiltinPack(pack: EffectProviderFactory): void { packRegistry.set(pack.id.toLowerCase(), pack); // Also register aliases pack.aliases?.forEach(alias => packRegistry.set(alias.toLowerCase(), pack)); } /** * Get all registered provider pack IDs. * * @returns Array of unique provider IDs (excludes aliases) */ export function getBuiltinPackIds(): string[] { return [...new Set([...packRegistry.values()].map(p => p.id))]; } /** * Load a registered provider pack by ID. * * @param id - Provider ID (case-insensitive) * @returns The provider factory or null if not found */ export function loadBuiltinPack(id: string): EffectProviderFactory | null { return packRegistry.get(id.toLowerCase()) ?? null; } /** * Check if a provider ID corresponds to a registered pack. * * @param id - Provider ID (case-insensitive) * @returns True if the ID matches a registered pack */ export function isBuiltinPack(id: string): boolean { return packRegistry.has(id.toLowerCase()); } /** * Legacy BUILTIN_PACKS export for backward compatibility. * * This object is dynamically populated from the registry. * Prefer using loadBuiltinPack() or getBuiltinPackIds() instead. * * @deprecated Access registry via loadBuiltinPack/getBuiltinPackIds functions */ export const BUILTIN_PACKS: Record = new Proxy( {} as Record, { get: (_target, prop: string) => packRegistry.get(prop.toLowerCase()), has: (_target, prop: string) => packRegistry.has((prop as string).toLowerCase()), ownKeys: () => [...new Set([...packRegistry.values()].map(p => p.id.toLowerCase()))], getOwnPropertyDescriptor: (_target, prop: string) => { if (packRegistry.has((prop as string).toLowerCase())) { return { enumerable: true, configurable: true }; } return undefined; }, } ); // ============================================================================= // Provider implementations moved to @fancyrobot/fred-* packages // ============================================================================= // // To use providers, install the corresponding package and import it: // // import '@fancyrobot/fred-openai'; // OpenAI via @effect/ai-openai // import '@fancyrobot/fred-anthropic'; // Anthropic via @effect/ai-anthropic // import '@fancyrobot/fred-google'; // Google/Gemini via @effect/ai-google // import '@fancyrobot/fred-groq'; // Groq (Chat Completions API) // import '@fancyrobot/fred-openrouter'; // OpenRouter via @effect/ai-openai // import '@fancyrobot/fred-minimax'; // MiniMax (language + image/video/speech/voice/music) // // Each provider auto-registers itself when imported. // =============================================================================