'use client'; import { Cpu, Loader2, Search } from 'lucide-react'; import { cn } from '@/lib/utils'; import { Popover, PopoverButton, PopoverPanel, Transition, } from '@headlessui/react'; import { Fragment, useEffect, useMemo, useState } from 'react'; import { MinimalProvider } from '@/lib/models/types'; import { useChat } from '@/lib/hooks/useChat'; const ModelSelector = () => { const [providers, setProviders] = useState([]); const [isLoading, setIsLoading] = useState(true); const [searchQuery, setSearchQuery] = useState(''); const { setChatModelProvider, chatModelProvider } = useChat(); useEffect(() => { const loadProviders = async () => { try { setIsLoading(true); const res = await fetch('/api/providers'); if (!res.ok) { throw new Error('Failed to fetch providers'); } const data: { providers: MinimalProvider[] } = await res.json(); setProviders(data.providers); } catch (error) { console.error('Error loading providers:', error); } finally { setIsLoading(false); } }; loadProviders(); }, []); const orderedProviders = useMemo(() => { if (!chatModelProvider?.providerId) return providers; const currentProviderIndex = providers.findIndex( (p) => p.id === chatModelProvider.providerId, ); if (currentProviderIndex === -1) { return providers; } const selectedProvider = providers[currentProviderIndex]; const remainingProviders = providers.filter( (_, index) => index !== currentProviderIndex, ); return [selectedProvider, ...remainingProviders]; }, [providers, chatModelProvider]); const handleModelSelect = (providerId: string, modelKey: string) => { setChatModelProvider({ providerId, key: modelKey }); localStorage.setItem('chatModelProviderId', providerId); localStorage.setItem('chatModelKey', modelKey); }; const filteredProviders = orderedProviders .map((provider) => ({ ...provider, chatModels: provider.chatModels.filter( (model) => model.name.toLowerCase().includes(searchQuery.toLowerCase()) || provider.name.toLowerCase().includes(searchQuery.toLowerCase()), ), })) .filter((provider) => provider.chatModels.length > 0); return (
setSearchQuery(e.target.value)} className="w-full pl-9 pr-3 py-2 bg-light-secondary dark:bg-dark-secondary rounded-lg placeholder:text-sm text-sm text-black dark:text-white placeholder:text-black/40 dark:placeholder:text-white/40 focus:outline-none focus:ring-2 focus:ring-sky-500/20 border border-transparent focus:border-sky-500/30 transition duration-200" />
{isLoading ? (
) : filteredProviders.length === 0 ? (
{searchQuery ? 'No models found' : 'No chat models configured'}
) : (
{filteredProviders.map((provider, providerIndex) => (

{provider.name}

{provider.chatModels.map((model) => ( ))}
{providerIndex < filteredProviders.length - 1 && (
)}
))}
)}
); }; export default ModelSelector;