import { useCallback, useEffect, useRef, useState } from "react"; import { Loader2 } from "lucide-react"; import { fetchLlamaCppStatus, setLlamaCppEnabled, type LlamaCppStatus } from "../api"; import { ProviderIcon } from "./ProviderIcon"; import "./LlamaCppProviderCard.css"; interface LlamaCppProviderCardProps { authenticated: boolean; onToggled?: (nextEnabled: boolean) => void; compact?: boolean; } export function LlamaCppProviderCard({ authenticated, onToggled, compact = false }: LlamaCppProviderCardProps) { const [status, setStatus] = useState(null); const [busy, setBusy] = useState<"enabling" | "disabling" | "testing" | null>(null); const mountedRef = useRef(true); useEffect(() => { mountedRef.current = true; return () => { mountedRef.current = false; }; }, []); const refresh = useCallback(async () => { const next = await fetchLlamaCppStatus(); if (mountedRef.current) setStatus(next); return next; }, []); useEffect(() => { void refresh(); }, [refresh]); const handleToggle = useCallback(async (next: boolean) => { setBusy(next ? "enabling" : "disabling"); try { const result = await setLlamaCppEnabled(next); onToggled?.(result.enabled); await refresh(); } finally { if (mountedRef.current) setBusy(null); } }, [onToggled, refresh]); const handleTest = useCallback(async () => { setBusy("testing"); try { await refresh(); } finally { if (mountedRef.current) setBusy(null); } }, [refresh]); const enabled = status?.enabled ?? authenticated; const serverAvailable = status?.server.available ?? false; const statusText = !status ? "Probing llama.cpp server…" : status.server.available ? `Server reachable at ${status.server.url}` : `Server unavailable: ${status.server.reason ?? "not reachable"}`; const actions = (
{enabled ? ( ) : ( )}
); if (compact) { return (
llama.cpp — via HTTP server
{actions}
{statusText}
); } return (
llama.cpp — via HTTP server
{statusText} {actions}
); }