"use client"; import { useState } from "react"; import type { ModelMeta } from "@/lib/modelfit"; import { fetchModels, fetchInstalledModels } from "@/lib/modelfit"; const TASKS = ["chat", "rag", "coding", "summarization", "agents", "vision", "multilingual"]; const FAMILIES = ["llama", "qwen", "mistral", "gemma", "phi", "deepseek", "unknown"]; interface Filters { q: string; source: string; family: string; task: string; embedding_only: boolean; open_license: boolean; } export function ModelSearch({ onSelect, }: { onSelect?: (model: ModelMeta) => void; }) { const [filters, setFilters] = useState({ q: "", source: "", family: "", task: "", embedding_only: false, open_license: false, }); const [models, setModels] = useState([]); const [loading, setLoading] = useState(false); const [warnings, setWarnings] = useState([]); const [searched, setSearched] = useState(false); async function search() { setLoading(true); setWarnings([]); try { const result = await fetchModels({ q: filters.q, source: filters.source || undefined, family: filters.family || undefined, task: filters.task || undefined, embedding_only: filters.embedding_only, open_license: filters.open_license, limit: 50, }); setModels(result.models); setSearched(true); } catch (e) { setWarnings([String(e)]); } finally { setLoading(false); } } async function syncInstalled() { setLoading(true); try { const result = await fetchInstalledModels(); setModels(result.models); setWarnings(result.warnings); setSearched(true); } catch (e) { setWarnings([String(e)]); } finally { setLoading(false); } } function set(key: keyof Filters, value: string | boolean) { setFilters((f) => ({ ...f, [key]: value })); } return (
{/* Filter row */}
set("q", e.target.value)} onKeyDown={(e) => e.key === "Enter" && search()} />
{warnings.map((w, i) => (

⚠ {w}

))} {searched && models.length === 0 && (

No models found.

)} {models.length > 0 && (
{models.map((m) => ( onSelect?.(m)} > ))}
Model Family Params Context Tasks License Source
{m.display_name} {m.gated && ( [gated] )} {m.embedding && ( [embed] )} {m.family} {m.parameter_count_b != null ? `${m.parameter_count_b}B` : "?"} {m.context_length != null ? `${(m.context_length / 1000).toFixed(0)}K` : "?"} {m.tasks.slice(0, 3).join(", ")} {m.license} {m.source}
)}
); }