'use client'; import * as React from 'react'; import { Check, ChevronsUpDown, Search, DownloadCloud, Cpu, Loader2 } from 'lucide-react'; import { cn } from '@/lib/utils'; import { Button } from '@/components/ui/button'; import { Popover, PopoverContent, PopoverTrigger, } from '@/components/ui/popover'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { useModelSelection } from '@/hooks/use-model-selection'; import { useDownloadContext } from '@/contexts/download-context'; import { Badge } from '@/components/ui/badge'; import { useToast } from '@/hooks/use-toast'; export function ModelSelector() { const [open, setOpen] = React.useState(false); const [searchQuery, setSearchQuery] = React.useState(''); const { myModels, availableModels, selectedModel, setSelectedModel, installedVariantsByFamily, refreshModels } = useModelSelection(); const { startDownload, state: downloadState } = useDownloadContext(); const { toast } = useToast(); // Track selected variant for each model in the catalog const [selectedVariants, setSelectedVariants] = React.useState>({}); const handleDownload = async (e: React.MouseEvent, modelName: string) => { e.stopPropagation(); try { await startDownload(modelName); toast({ title: "Download Iniciado", description: `Baixando ${modelName}...`, }); } catch (error) { toast({ title: "Erro", description: "Falha ao iniciar download.", variant: "destructive", }); } }; const handleSmartDownload = async () => { const term = searchQuery.trim(); if (!term) return; try { await startDownload(term); setOpen(false); setSearchQuery(""); toast({ title: "Download Iniciado", description: `Baixando ${term} da biblioteca Ollama...`, }); } catch (error) { toast({ title: "Erro", description: "Falha ao iniciar download.", variant: "destructive", }); } }; React.useEffect(() => { if (downloadState?.isSuccess) { refreshModels(); } }, [downloadState?.isSuccess, refreshModels]); const filteredMyModels = React.useMemo(() => { if (!searchQuery) return myModels; return myModels.filter(m => m.model.toLowerCase().includes(searchQuery.toLowerCase()) ); }, [myModels, searchQuery]); const filteredAvailableModels = React.useMemo(() => { if (!searchQuery) return availableModels; return availableModels.filter(m => m.model.toLowerCase().includes(searchQuery.toLowerCase()) ); }, [availableModels, searchQuery]); // Helper to check if a model is currently selected (partial match for variants) const isSelected = (modelName: string) => { if (!selectedModel) return false; return selectedModel.startsWith(modelName) || selectedModel === modelName; }; // Helper to extract tag/parameters from model name const getVariantDisplay = (name: string) => { if (name.includes(':')) { return name.split(':')[1]; } return 'latest'; }; return (
{/* Search Input */}
setSearchQuery(e.target.value)} onKeyDown={(e) => { if (e.key === 'Enter' && searchQuery && filteredAvailableModels.length === 0) { handleSmartDownload(); } }} />
Instalados Catálogo {filteredMyModels.length === 0 ? (
{searchQuery ? ( Nenhum modelo instalado encontrado. ) : ( Nenhum modelo instalado. )}
) : (
{filteredMyModels.map((modelDef) => { const family = modelDef.model; const installedTags = installedVariantsByFamily[family] || []; const isFamilySelected = selectedModel ? (selectedModel === family || selectedModel.startsWith(family + ":")) : false; return (
{modelDef.model} {isFamilySelected && ( )} {modelDef.description}
{installedTags.map((fullTag) => { const tag = getVariantDisplay(fullTag); const isExactSelected = selectedModel === fullTag; // Find variant def for size info if available const variantDef = modelDef.variants.find(v => v.name === fullTag); return ( { e.stopPropagation(); setSelectedModel(fullTag); setOpen(false); }} > {tag} ); })}
); })}
)}
{filteredAvailableModels.length === 0 ? (
{searchQuery ? (

Modelo não encontrado no catálogo.

) : ( Nenhum modelo encontrado. )}
) : (
{filteredAvailableModels.map((modelDef) => { // Determine active variant for this item const activeVariantName = selectedVariants[modelDef.model] || modelDef.variants[0]?.name; const activeVariant = modelDef.variants.find(v => v.name === activeVariantName) || modelDef.variants[0]; return (
{modelDef.model} {modelDef.description}
{/* Variants Pills */}
{modelDef.variants.map((variant) => { const isVariantSelected = activeVariant.name === variant.name; return ( { e.stopPropagation(); setSelectedVariants(prev => ({ ...prev, [modelDef.model]: variant.name })); }} > {getVariantDisplay(variant.name)} ); })}
)})}
)}
); }