import { useState, useEffect } from 'react' import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { Badge } from '@/components/ui/badge' import { BookOpen, Brain, Zap, Download, Trash2, Loader2, Info, CheckCircle, Cloud, HardDrive } from 'lucide-react' interface ModelInfo { model_name: string name: string supports_thinking: boolean description: string size_gb: string is_loaded: boolean type: 'local' | 'api' } interface ModelsResponse { models: ModelInfo[] current_model: string } export function Models() { const [models, setModels] = useState([]) const [loading, setLoading] = useState(true) const [modelLoading, setModelLoading] = useState(null) useEffect(() => { fetchModels() }, []) const fetchModels = async () => { try { const baseUrl = window.location.hostname === 'localhost' ? `${window.location.protocol}//${window.location.host}` : '' const res = await fetch(`${baseUrl}/models`) if (res.ok) { const data: ModelsResponse = await res.json() setModels(data.models) } } catch (err) { console.error('Failed to fetch models:', err) } finally { setLoading(false) } } const handleLoadModel = async (modelName: string) => { setModelLoading(modelName) try { const baseUrl = window.location.hostname === 'localhost' ? `${window.location.protocol}//${window.location.host}` : '' const res = await fetch(`${baseUrl}/load-model`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ model_name: modelName }), }) if (res.ok) { await fetchModels() } } catch (err) { console.error('Failed to load model:', err) } finally { setModelLoading(null) } } const handleUnloadModel = async (modelName: string) => { try { const baseUrl = window.location.hostname === 'localhost' ? `${window.location.protocol}//${window.location.host}` : '' const res = await fetch(`${baseUrl}/unload-model`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ model_name: modelName }), }) if (res.ok) { await fetchModels() } } catch (err) { console.error('Failed to unload model:', err) } } if (loading) { return (

Model Catalog

) } return (
{/* Header */}

Model Catalog

{/* Info Card */}

Model Management

Load models to use them in the playground. Models are cached locally for faster access. Each model requires significant storage space and initial download time.

{/* API Models Section */}

API Models Cloud-Powered

{models.filter(m => m.type === 'api').map((model) => ( ))}
{/* Local Models Section */}

Local Models Privacy-First

{models.filter(m => m.type === 'local').map((model) => ( ))}
{/* Stats Card */} Model Statistics
{models.length}
Available Models
{models.filter(m => m.is_loaded).length}
Loaded Models
{models.filter(m => m.supports_thinking).length}
Thinking Models
) } // ModelCard component for reusability interface ModelCardProps { model: ModelInfo modelLoading: string | null onLoad: (modelName: string) => void onUnload: (modelName: string) => void } function ModelCard({ model, modelLoading, onLoad, onUnload }: ModelCardProps) { const isApiModel = model.type === 'api' return (
{isApiModel ? ( ) : model.supports_thinking ? ( ) : ( )}
{model.name}
{isApiModel ? ( API Model ) : ( {model.supports_thinking ? "Thinking Model" : "Instruction Model"} )} {model.is_loaded && ( {isApiModel ? "Ready" : "Loaded"} )}

{model.description}

Size: {model.size_gb} {!isApiModel && Format: Safetensors} {isApiModel && Type: Cloud API}

Capabilities

Text Generation Conversation Code {model.supports_thinking && ( Reasoning )} {isApiModel && model.model_name.includes('vl') && ( Vision )}
{model.is_loaded ? (
{!isApiModel && ( )}
) : ( )}
) }