From 91a54496ada4bc3b83e7e34725d00b4077aa567b Mon Sep 17 00:00:00 2001 From: shrimbly Date: Fri, 9 Jan 2026 16:33:58 +1300 Subject: [PATCH] feat(02-03): add provider module exports and helper functions Export cache utilities from provider index and add listAllModels/ searchAllModels helper functions for multi-provider operations. Co-Authored-By: Claude Opus 4.5 --- src/lib/providers/index.ts | 112 ++++++++++++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 1 deletion(-) diff --git a/src/lib/providers/index.ts b/src/lib/providers/index.ts index e57e99f9..a459168d 100644 --- a/src/lib/providers/index.ts +++ b/src/lib/providers/index.ts @@ -20,11 +20,14 @@ */ import { ProviderType } from "@/types"; -import { ProviderInterface } from "./types"; +import { ProviderInterface, ProviderModel } from "./types"; // Re-export all types for convenient imports export * from "./types"; +// Re-export cache utilities for convenient imports +export * from "./cache"; + /** * Provider registry - populated by provider implementations when they are imported. * Initially empty; providers call registerProvider() to add themselves. @@ -88,3 +91,110 @@ export function getAllProviders(): ProviderInterface[] { (p): p is ProviderInterface => p !== undefined ); } + +// ============ Multi-Provider Helpers ============ + +/** + * API keys object for multi-provider operations. + * Keys are provider IDs, values are API keys. + */ +export interface ApiKeys { + replicate?: string; + fal?: string; + gemini?: string; +} + +/** + * List models from all registered providers. + * + * Note: This function calls provider.listModels() which may use localStorage + * for API keys (client-side only). For server-side usage, use the API routes + * at /api/models or /api/providers/[provider]/models instead. + * + * @param _apiKeys - API keys object (currently unused, reserved for future use) + * @returns Combined array of models from all registered providers + * + * @example + * // Client-side usage (providers get keys from localStorage) + * const models = await listAllModels({}); + */ +export async function listAllModels( + _apiKeys: ApiKeys = {} +): Promise { + const providers = getAllProviders(); + const results = await Promise.allSettled( + providers.map((p) => p.listModels()) + ); + + const allModels: ProviderModel[] = []; + for (const result of results) { + if (result.status === "fulfilled") { + allModels.push(...result.value); + } + } + + // Sort by provider, then by name + allModels.sort((a, b) => { + if (a.provider !== b.provider) { + return a.provider.localeCompare(b.provider); + } + return a.name.localeCompare(b.name); + }); + + return allModels; +} + +/** + * Search for models across all registered providers. + * + * Note: This function calls provider.searchModels() which may use localStorage + * for API keys (client-side only). For server-side usage, use the API routes + * at /api/models?search=query or /api/providers/[provider]/models?search=query. + * + * @param query - Search query string + * @param _apiKeys - API keys object (currently unused, reserved for future use) + * @returns Combined array of matching models from all registered providers + * + * @example + * // Client-side usage (providers get keys from localStorage) + * const models = await searchAllModels("flux", {}); + */ +export async function searchAllModels( + query: string, + _apiKeys: ApiKeys = {} +): Promise { + const providers = getAllProviders(); + const results = await Promise.allSettled( + providers.map((p) => p.searchModels(query)) + ); + + const allModels: ProviderModel[] = []; + for (const result of results) { + if (result.status === "fulfilled") { + allModels.push(...result.value); + } + } + + // Sort by provider, then by name + allModels.sort((a, b) => { + if (a.provider !== b.provider) { + return a.provider.localeCompare(b.provider); + } + return a.name.localeCompare(b.name); + }); + + return allModels; +} + +// ============ Provider Auto-Registration ============ + +/** + * Provider modules self-register when imported: + * + * import "@/lib/providers/replicate"; // Registers Replicate provider + * import "@/lib/providers/fal"; // Registers fal.ai provider + * + * The unified API route at /api/models handles fetching directly without + * needing to import provider modules (to avoid client-side localStorage + * dependencies on the server). + */