diff --git a/src/app/api/models/route.ts b/src/app/api/models/route.ts index 9dad3484..1836acf4 100644 --- a/src/app/api/models/route.ts +++ b/src/app/api/models/route.ts @@ -499,6 +499,8 @@ interface ModelsSuccessResponse { models: ProviderModel[]; cached: boolean; providers: Record; + /** All providers that have API keys configured (env or client header) */ + availableProviders: string[]; errors?: string[]; } @@ -952,6 +954,12 @@ export async function GET( const kieKey = request.headers.get("X-Kie-Key") || process.env.KIE_API_KEY || null; const wavespeedKey = request.headers.get("X-WaveSpeed-Key") || process.env.WAVESPEED_API_KEY || null; + // Build list of all available providers (have keys from env or client headers) + const availableProviders: string[] = ["gemini", "fal"]; // Always available + if (replicateKey) availableProviders.push("replicate"); + if (kieKey) availableProviders.push("kie"); + if (wavespeedKey) availableProviders.push("wavespeed"); + // Determine which providers to fetch from (excluding gemini/kie - handled separately as hardcoded) const providersToFetch: ProviderType[] = []; let includeGemini = false; @@ -1160,6 +1168,7 @@ export async function GET( models: filteredModels, cached: anyFromCache && allFromCache, providers: providerResults, + availableProviders, }; if (errors.length > 0) { diff --git a/src/components/modals/ModelSearchDialog.tsx b/src/components/modals/ModelSearchDialog.tsx index 2ddcf994..b2b808db 100644 --- a/src/components/modals/ModelSearchDialog.tsx +++ b/src/components/modals/ModelSearchDialog.tsx @@ -95,6 +95,8 @@ type CapabilityFilter = "all" | "image" | "video" | "3d" | "audio"; interface ModelsResponse { success: boolean; models?: ProviderModel[]; + /** Providers with API keys configured (env or client header) */ + availableProviders?: string[]; error?: string; } @@ -138,6 +140,7 @@ export function ModelSearchDialog({ const [isLoading, setIsLoading] = useState(false); const [isRefreshing, setIsRefreshing] = useState(false); const [error, setError] = useState(null); + const [serverAvailableProviders, setServerAvailableProviders] = useState([]); // Refs const searchInputRef = useRef(null); @@ -241,6 +244,10 @@ export function ModelSearchDialog({ setModels(data.models); // Cache the successful result setCachedModels(cacheKey, data.models); + // Update server-reported available providers + if (data.availableProviders) { + setServerAvailableProviders(data.availableProviders); + } } else { setError(data.error || "Failed to fetch models"); setModels([]); @@ -405,14 +412,19 @@ export function ModelSearchDialog({ } }; - // Compute which providers are available based on API keys + // Compute which providers are available based on client API keys + server env vars const availableProviders = useMemo(() => { const providers = new Set(["gemini", "fal"]); // Always available + // Client-side keys (from localStorage/provider settings) if (replicateApiKey) providers.add("replicate"); if (kieApiKey) providers.add("kie"); if (wavespeedApiKey) providers.add("wavespeed"); + // Server-side keys (from env vars, reported by /api/models) + for (const p of serverAvailableProviders) { + providers.add(p as ProviderType); + } return providers; - }, [replicateApiKey, kieApiKey, wavespeedApiKey]); + }, [replicateApiKey, kieApiKey, wavespeedApiKey, serverAvailableProviders]); // Reset provider filter if current selection becomes unavailable useEffect(() => {