import { Text, Group, Select, Badge, Card, useMantineColorScheme, ActionIcon, Tooltip, } from '@mantine/core'; import { useState, useEffect } from 'react'; import { AlertTriangle } from 'lucide-react'; import { InfoTooltip } from '@/components/InfoTooltip'; import { isNoCudaBinary, isRocmBinary } from '@/utils/binaryUtils'; interface BackendSelectorProps { backend: string; onBackendChange: (backend: string) => void; noavx2?: boolean; failsafe?: boolean; } export const BackendSelector = ({ backend, onBackendChange, noavx2 = false, failsafe = false, }: BackendSelectorProps) => { const { colorScheme } = useMantineColorScheme(); const isDark = colorScheme === 'dark'; const [availableBackends, setAvailableBackends] = useState< Array<{ value: string; label: string; devices?: string[] }> >([]); const [isLoadingBackends, setIsLoadingBackends] = useState(true); const [cpuCapabilities, setCpuCapabilities] = useState<{ avx: boolean; avx2: boolean; } | null>(null); useEffect(() => { const detectAvailableBackends = async () => { setIsLoadingBackends(true); try { const [currentBinaryInfo, cpuCapabilitiesResult, gpuCapabilities] = await Promise.all([ window.electronAPI.kobold.getCurrentBinaryInfo(), window.electronAPI.kobold.detectCPU(), window.electronAPI.kobold.detectGPUCapabilities(), ]); setCpuCapabilities({ avx: cpuCapabilitiesResult.avx, avx2: cpuCapabilitiesResult.avx2, }); const backends: Array<{ value: string; label: string; devices?: string[]; }> = []; if (currentBinaryInfo?.filename) { const filename = currentBinaryInfo.filename; if (!isNoCudaBinary(filename) && gpuCapabilities.cuda.supported) { backends.push({ value: 'cuda', label: 'CUDA', devices: gpuCapabilities.cuda.devices, }); } if (isRocmBinary(filename) && gpuCapabilities.rocm.supported) { backends.push({ value: 'rocm', label: 'ROCm', devices: gpuCapabilities.rocm.devices, }); } if (gpuCapabilities.vulkan.supported) { backends.push({ value: 'vulkan', label: 'Vulkan', devices: gpuCapabilities.vulkan.devices, }); } if (gpuCapabilities.clblast.supported) { backends.push({ value: 'clblast', label: 'CLBlast', devices: gpuCapabilities.clblast.devices, }); } backends.push({ value: 'cpu', label: 'CPU', devices: cpuCapabilitiesResult.cpuInfo, }); } setAvailableBackends(backends); if ( backends.length > 0 && (!backend || !backends.some((b) => b.value === backend)) ) { onBackendChange(backends[0].value); } } catch (error) { console.warn('Failed to detect available backends:', error); setAvailableBackends([]); } finally { setIsLoadingBackends(false); } }; void detectAvailableBackends(); }, [backend, onBackendChange]); const getWarnings = () => { if (backend !== 'cpu' || !cpuCapabilities) return []; const warnings = []; if (!cpuCapabilities.avx2 && !noavx2) { warnings.push({ type: 'warning', message: 'Your CPU does not support AVX2. Enable the "Disable AVX2" option to avoid crashes.', }); } if (!cpuCapabilities.avx && !cpuCapabilities.avx2 && !failsafe) { warnings.push({ type: 'warning', message: 'Your CPU does not support AVX or AVX2. Enable the "Failsafe" option to avoid crashes.', }); } return warnings; }; return (
Backend {getWarnings().map((warning, index) => ( ))}