import React, { useEffect, useState } from "react"; import { Download, Trash2, RefreshCw } from "lucide-react"; import { Card, CardHeader, CardTitle, CardContent, Button, Input, Badge, Progress, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, } from "@/components/ui"; import { HardwareReport } from "@/components/HardwareReport"; import { checkOllamaInstalledCmd, detectHardwareCmd, recommendModelsCmd, pullOllamaModelCmd, deleteOllamaModelCmd, listOllamaModelsCmd, getOllamaInstallGuideCmd, type OllamaStatus, type HardwareInfo, type ModelRecommendation, type OllamaModel, type InstallGuide, } from "@/lib/tauriCommands"; import { listen } from "@tauri-apps/api/event"; export default function Ollama() { const [status, setStatus] = useState(null); const [installGuide, setInstallGuide] = useState(null); const [models, setModels] = useState([]); const [hardware, setHardware] = useState(null); const [recommendations, setRecommendations] = useState([]); const [isLoading, setIsLoading] = useState(false); const [pullModel, setPullModel] = useState(""); const [customModel, setCustomModel] = useState(""); const [isPulling, setIsPulling] = useState(false); const [pullProgress, setPullProgress] = useState(0); const [error, setError] = useState(null); const loadData = async () => { setIsLoading(true); try { const platform = navigator.platform.toLowerCase().includes("mac") ? "macos" : navigator.platform.toLowerCase().includes("win") ? "windows" : "linux"; const [ollamaStatus, hw, recs, modelList, guide] = await Promise.all([ checkOllamaInstalledCmd(), detectHardwareCmd(), recommendModelsCmd(), listOllamaModelsCmd().catch(() => [] as OllamaModel[]), getOllamaInstallGuideCmd(platform), ]); setStatus(ollamaStatus); setInstallGuide(guide); setHardware(hw); setRecommendations(recs); setModels(modelList); } catch (err) { setError(String(err)); } finally { setIsLoading(false); } }; useEffect(() => { loadData(); }, []); useEffect(() => { let unlisten: (() => void) | undefined; const setup = async () => { unlisten = await listen<{ progress: number }>("model://progress", (event) => { setPullProgress(event.payload.progress); if (event.payload.progress >= 100) { setIsPulling(false); loadData(); } }); }; setup(); return () => { unlisten?.(); }; }, []); const handlePull = async () => { const modelName = pullModel === "__custom__" ? customModel : pullModel; if (!modelName.trim()) return; setIsPulling(true); setPullProgress(0); setError(null); try { await pullOllamaModelCmd(modelName.trim()); } catch (err) { setError(String(err)); setIsPulling(false); } }; const handleDelete = async (modelName: string) => { try { await deleteOllamaModelCmd(modelName); await loadData(); } catch (err) { setError(String(err)); } }; return (

Ollama (Local AI)

Manage local AI models via Ollama for privacy-first inference.

{/* Hardware Report */} Hardware {/* Ollama Status */} Ollama Status {status ? (
{status.installed ? "Installed" : "Not Installed"} {status.running ? "Running" : "Stopped"} {status.version && ( v{status.version} )}
) : (

{isLoading ? "Checking status..." : "Unable to determine status."}

)}
{/* Install Instructions — shown when Ollama is not detected */} {status && !status.installed && installGuide && ( Ollama Not Detected — Installation Required
    {installGuide.steps.map((step, i) => (
  1. {step}
  2. ))}
)} {/* Model List */} Installed Models {models.length > 0 ? (
{models.map((model: OllamaModel) => (

{model.name}

{model.size} | Modified: {new Date(model.modified).toLocaleDateString()}

))}
) : (

No models installed.

)}
{/* Pull Model */} Pull Model
{pullModel === "__custom__" && ( setCustomModel(e.target.value)} placeholder="e.g., llama3:8b" className="w-48" /> )}
{isPulling && (
Downloading... {pullProgress.toFixed(0)}%
)}
{error && (
{error}
)}
); }