'use client'; import { useEffect, useState } from 'react'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Badge } from '@/components/ui/badge'; import { Alert, AlertDescription } from '@/components/ui/alert'; import { RefreshCw, Check, X, Cpu, Search } from 'lucide-react'; interface Model { id: string; name: string; } export function ModelSwitcher() { const [models, setModels] = useState([]); const [activeModel, setActiveModelState] = useState(null); const [loading, setLoading] = useState(true); const [switching, setSwitching] = useState(null); const [filter, setFilter] = useState(''); const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null); const fetchData = async () => { setLoading(true); try { const response = await fetch('/api/models'); const data = await response.json(); setModels(data.models || []); setActiveModelState(data.activeModel); } catch (error) { console.error('Failed to fetch models:', error); setMessage({ type: 'error', text: 'Failed to load models' }); } finally { setLoading(false); } }; useEffect(() => { fetchData(); }, []); const handleSwitchModel = async (modelId: string) => { if (switching) return; setSwitching(modelId); setMessage(null); try { const response = await fetch('/api/models', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ modelId }), }); const result = await response.json(); if (result.success) { setMessage({ type: 'success', text: result.message }); setActiveModelState(modelId); } else { setMessage({ type: 'error', text: result.message || 'Failed to switch model' }); } } catch (error) { setMessage({ type: 'error', text: 'Failed to switch model' }); } finally { setSwitching(null); } }; const groupedModels = models.reduce((acc, model) => { const provider = model.id.split('/')[0]; if (!acc[provider]) { acc[provider] = []; } acc[provider].push(model); return acc; }, {} as Record); const filteredGroups = filter ? Object.fromEntries( Object.entries(groupedModels).filter(([_, models]) => models.some((m) => m.name.toLowerCase().includes(filter.toLowerCase()) || m.id.toLowerCase().includes(filter.toLowerCase()) ) ) ) : groupedModels; return (
{/* Header */}
{activeModel && (
Active: {activeModel}
)}
setFilter(e.target.value)} className="pl-10 bg-zinc-900/50 border-zinc-700 focus:border-orange-500" />
{/* Message */} {message && ( {message.type === 'success' ? ( ) : ( )} {message.text} )} {/* Models List */} {loading ? (
) : Object.keys(filteredGroups).length === 0 ? (

{filter ? 'No models match your search' : 'No models found'}

) : (
{Object.entries(filteredGroups).map(([provider, providerModels]) => ( {provider} {providerModels.length}
{providerModels .filter((model) => !filter || model.name.toLowerCase().includes(filter.toLowerCase()) || model.id.toLowerCase().includes(filter.toLowerCase()) ) .map((model) => (

{model.name}

{model.id}

{activeModel === model.id ? 'Active' : 'Available'}
))}
))}
)}

ℹ️ Switching models restarts the Gateway to apply changes.

); }