import { useState, useEffect } from "react"; import { Plus, RefreshCw } from "lucide-react"; import { api } from "../api"; import ModelCard from "./ModelCard"; import ModelForm from "./ModelForm"; export default function ModelManager() { const [models, setModels] = useState([]); const [loading, setLoading] = useState(true); const [showForm, setShowForm] = useState(false); const [editModel, setEditModel] = useState(null); const [filter, setFilter] = useState("all"); const load = async () => { setLoading(true); try { const res = await api.listModels(); setModels(res.data); } catch (e) { console.error(e); } finally { setLoading(false); } }; useEffect(() => { load(); }, []); const handleDelete = async (id) => { if (!confirm("Delete this model? It will be removed from the gateway.")) return; await api.deleteModel(id); setModels(m => m.filter(x => x.id !== id)); }; const handleToggle = async (id) => { const res = await api.toggleModel(id); setModels(m => m.map(x => x.id === id ? res.data : x)); }; const handleSave = async (data) => { if (editModel) { const res = await api.updateModel(editModel.id, data); setModels(m => m.map(x => x.id === editModel.id ? res.data : x)); } else { const res = await api.createModel(data); setModels(m => [res.data, ...m]); } setShowForm(false); setEditModel(null); }; const TYPE_COLORS = { chat: "green", embedding: "cyan", image: "purple", audio: "orange", completion: "gray", }; const filtered = filter === "all" ? models : models.filter(m => m.modelType === filter || (filter === "enabled" ? m.enabled : !m.enabled)); const types = [...new Set(models.map(m => m.modelType))].filter(Boolean); return (
{/* ── Header ── */}

Model Registry

Register any AI model and get an OpenAI-compatible endpoint instantly.

{/* ── Filters ── */} {models.length > 0 && (
{["all", "enabled", ...types].map(f => ( ))}
)} {/* ── Content ── */} {loading ? (
{[...Array(3)].map((_, i) => (
))}
) : filtered.length === 0 ? ( setShowForm(true)} hasModels={models.length > 0} /> ) : (
{filtered.map(model => ( { setEditModel(model); setShowForm(true); }} onDelete={() => handleDelete(model.id)} onToggle={() => handleToggle(model.id)} /> ))}
)} {/* ── Form modal ── */} {showForm && ( { setShowForm(false); setEditModel(null); }} /> )}
); } function EmptyState({ onAdd, hasModels }) { return (

{hasModels ? "No models match this filter" : "No models registered yet"}

{hasModels ? "Try a different filter to see your models." : "Add your first model to start routing AI requests through an OpenAI-compatible endpoint."}

{!hasModels && ( )}
); }