From 4b2e9b2ae96247d0117fe42d5fee9b3c50a3c06f Mon Sep 17 00:00:00 2001 From: Egor Date: Fri, 28 Nov 2025 23:33:37 -0800 Subject: [PATCH] rename version -> backend and backend -> acceleration, display "metal" for mac users and don't show other options, allow "metal" users to select GPU layers --- package.json | 2 +- src/components/App/UpdateAvailableModal.tsx | 4 +- src/components/App/index.tsx | 20 +- src/components/screens/Download.tsx | 2 +- src/components/screens/Launch/AdvancedTab.tsx | 7 +- ...ectItem.tsx => AccelerationSelectItem.tsx} | 8 +- ...dSelector.tsx => AccelerationSelector.tsx} | 102 ++--- .../Launch/GeneralTab/GpuDeviceSelector.tsx | 28 +- .../screens/Launch/GeneralTab/index.tsx | 4 +- src/components/screens/Launch/index.tsx | 7 +- .../{VersionsTab.tsx => BackendsTab.tsx} | 146 +++---- src/components/settings/SettingsModal.tsx | 18 +- src/components/settings/SystemTab.tsx | 2 +- src/hooks/useLaunchLogic.ts | 8 +- src/hooks/useUpdateChecker.ts | 20 +- src/hooks/useWarnings.ts | 34 +- src/main/ipc.ts | 31 +- src/main/modules/koboldcpp/acceleration.ts | 184 +++++++++ src/main/modules/koboldcpp/backend.ts | 367 ++++++++++-------- src/main/modules/koboldcpp/download.ts | 2 +- src/main/modules/koboldcpp/launcher/index.ts | 20 +- src/main/modules/koboldcpp/version.ts | 233 ----------- src/preload/index.ts | 15 +- src/stores/koboldVersions.ts | 14 +- src/types/electron.d.ts | 18 +- src/types/index.d.ts | 12 +- src/utils/version.ts | 11 +- yarn.lock | 10 +- 28 files changed, 677 insertions(+), 652 deletions(-) rename src/components/screens/Launch/GeneralTab/{BackendSelectItem.tsx => AccelerationSelectItem.tsx} (88%) rename src/components/screens/Launch/GeneralTab/{BackendSelector.tsx => AccelerationSelector.tsx} (64%) rename src/components/settings/{VersionsTab.tsx => BackendsTab.tsx} (63%) create mode 100644 src/main/modules/koboldcpp/acceleration.ts delete mode 100644 src/main/modules/koboldcpp/version.ts diff --git a/package.json b/package.json index 23ae01c..60836c8 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "eslint-plugin-sonarjs": "^3.0.5", "globals": "^16.5.0", "jiti": "^2.6.1", - "prettier": "^3.7.1", + "prettier": "^3.7.2", "rollup-plugin-visualizer": "^6.0.5", "typescript": "^5.9.3", "vite": "^7.2.4" diff --git a/src/components/App/UpdateAvailableModal.tsx b/src/components/App/UpdateAvailableModal.tsx index 76d4643..a37bb93 100644 --- a/src/components/App/UpdateAvailableModal.tsx +++ b/src/components/App/UpdateAvailableModal.tsx @@ -35,7 +35,7 @@ export const UpdateAvailableModal = ({ onUpdate, }: UpdateAvailableModalProps) => { const { downloading, downloadProgress } = useKoboldVersionsStore(); - const currentVersion = updateInfo?.currentVersion; + const currentBackend = updateInfo?.currentBackend; const availableUpdate = updateInfo?.availableUpdate; const [isUpdating, setIsUpdating] = useState(false); @@ -73,7 +73,7 @@ export const UpdateAvailableModal = ({ Current Version - {currentVersion?.version} + {currentBackend?.version} diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index 6bebced..b149254 100644 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -98,12 +98,12 @@ export const App = () => { useEffect(() => { const checkInstallation = async () => { - const [currentVersion, hasSeenWelcome] = await Promise.all([ - window.electronAPI.kobold.getCurrentVersion(), + const [currentBackend, hasSeenWelcome] = await Promise.all([ + window.electronAPI.kobold.getCurrentBackend(), window.electronAPI.config.get('hasSeenWelcome') as Promise, ]); - determineScreen(currentVersion, hasSeenWelcome); + determineScreen(currentBackend, hasSeenWelcome); setHasInitialized(true); }; @@ -114,9 +114,9 @@ export const App = () => { const runUpdateCheck = async () => { if (loadingRemote || !hasInitialized) return; - const currentVersion = - await window.electronAPI.kobold.getCurrentVersion(); - if (currentVersion) { + const currentBackend = + await window.electronAPI.kobold.getCurrentBackend(); + if (currentBackend) { setTimeout(() => { checkForUpdates(); }, 5000); @@ -136,13 +136,13 @@ export const App = () => { }, [loadingRemote, hasInitialized, checkForUpdates]); const handleBinaryUpdate = async (download: DownloadItem) => { - const currentVersion = await window.electronAPI.kobold.getCurrentVersion(); + const currentBackend = await window.electronAPI.kobold.getCurrentBackend(); await handleDownload({ item: download, isUpdate: true, wasCurrentBinary: true, - oldVersionPath: currentVersion?.path, + oldVersionPath: currentBackend?.path, }); closeModal(); @@ -170,8 +170,8 @@ export const App = () => { const handleWelcomeComplete = async () => { window.electronAPI.config.set('hasSeenWelcome', true); - const currentVersion = await window.electronAPI.kobold.getCurrentVersion(); - determineScreen(currentVersion, true); + const currentBackend = await window.electronAPI.kobold.getCurrentBackend(); + determineScreen(currentBackend, true); }; const handleDownloadComplete = () => setCurrentScreen('launch'); diff --git a/src/components/screens/Download.tsx b/src/components/screens/Download.tsx index a2b5520..ed55e70 100644 --- a/src/components/screens/Download.tsx +++ b/src/components/screens/Download.tsx @@ -59,7 +59,7 @@ export const DownloadScreen = ({ onDownloadComplete }: DownloadScreenProps) => { - Available Binaries for Your Platform + Select a Backend {loading ? ( diff --git a/src/components/screens/Launch/AdvancedTab.tsx b/src/components/screens/Launch/AdvancedTab.tsx index ee4d057..9105d68 100644 --- a/src/components/screens/Launch/AdvancedTab.tsx +++ b/src/components/screens/Launch/AdvancedTab.tsx @@ -61,8 +61,9 @@ export const AdvancedTab = () => { const isGpuBackend = backend === 'cuda' || backend === 'rocm'; useEffect(() => { - const detectBackendSupport = async () => { - const support = await window.electronAPI.kobold.detectBackendSupport(); + const detectAccelerationSupport = async () => { + const support = + await window.electronAPI.kobold.detectAccelerationSupport(); if (support) { setBackendSupport({ @@ -76,7 +77,7 @@ export const AdvancedTab = () => { setIsLoading(false); }; - void detectBackendSupport(); + void detectAccelerationSupport(); }, []); return ( diff --git a/src/components/screens/Launch/GeneralTab/BackendSelectItem.tsx b/src/components/screens/Launch/GeneralTab/AccelerationSelectItem.tsx similarity index 88% rename from src/components/screens/Launch/GeneralTab/BackendSelectItem.tsx rename to src/components/screens/Launch/GeneralTab/AccelerationSelectItem.tsx index 446b4aa..dcfea47 100644 --- a/src/components/screens/Launch/GeneralTab/BackendSelectItem.tsx +++ b/src/components/screens/Launch/GeneralTab/AccelerationSelectItem.tsx @@ -1,14 +1,14 @@ import { Text, Group, Badge, Box } from '@mantine/core'; -import type { BackendOption } from '@/types'; +import type { AccelerationOption } from '@/types'; import { GPUDevice } from '@/types/hardware'; -type BackendSelectItemProps = Omit; +type AccelerationSelectItemProps = Omit; -export const BackendSelectItem = ({ +export const AccelerationSelectItem = ({ label, devices, disabled = false, -}: BackendSelectItemProps) => { +}: AccelerationSelectItemProps) => { const renderDeviceName = (device: string | GPUDevice) => { const deviceName = typeof device === 'string' ? device : device.name; return deviceName.length > 25 diff --git a/src/components/screens/Launch/GeneralTab/BackendSelector.tsx b/src/components/screens/Launch/GeneralTab/AccelerationSelector.tsx similarity index 64% rename from src/components/screens/Launch/GeneralTab/BackendSelector.tsx rename to src/components/screens/Launch/GeneralTab/AccelerationSelector.tsx index eca3aff..f21c6e1 100644 --- a/src/components/screens/Launch/GeneralTab/BackendSelector.tsx +++ b/src/components/screens/Launch/GeneralTab/AccelerationSelector.tsx @@ -1,13 +1,13 @@ import { Text, Group, Checkbox, TextInput } from '@mantine/core'; import { useState, useEffect, useRef } from 'react'; import { InfoTooltip } from '@/components/InfoTooltip'; -import { BackendSelectItem } from '@/components/screens/Launch/GeneralTab/BackendSelectItem'; +import { AccelerationSelectItem } from '@/components/screens/Launch/GeneralTab/AccelerationSelectItem'; import { GpuDeviceSelector } from '@/components/screens/Launch/GeneralTab/GpuDeviceSelector'; import { useLaunchConfig } from '@/hooks/useLaunchConfig'; -import type { BackendOption } from '@/types'; +import type { AccelerationOption } from '@/types'; import { Select } from '@/components/Select'; -export const BackendSelector = () => { +export const AccelerationSelector = () => { const { backend, gpuLayers, @@ -21,60 +21,67 @@ export const BackendSelector = () => { handleAutoGpuLayersChange, } = useLaunchConfig(); - const [availableBackends, setAvailableBackends] = useState( - [] - ); - const [isLoadingBackends, setIsLoadingBackends] = useState(false); + const [availableAccelerations, setAvailableAccelerations] = useState< + AccelerationOption[] + >([]); + const [isLoadingAccelerations, setIsLoadingAccelerations] = useState(false); const [isCalculatingLayers, setIsCalculatingLayers] = useState(false); + const [isMac, setIsMac] = useState(false); const hasInitialized = useRef(false); useEffect(() => { - const loadBackends = async () => { - setIsLoadingBackends(true); + const loadAccelerations = async () => { + setIsLoadingAccelerations(true); - const backends = - await window.electronAPI.kobold.getAvailableBackends(true); + const [accelerations, platform] = await Promise.all([ + window.electronAPI.kobold.getAvailableAccelerations(true), + window.electronAPI.kobold.getPlatform(), + ]); - setAvailableBackends(backends || []); - setIsLoadingBackends(false); + setAvailableAccelerations(accelerations || []); + setIsMac(platform === 'darwin'); + setIsLoadingAccelerations(false); hasInitialized.current = true; }; if (!hasInitialized.current) { - loadBackends(); + loadAccelerations(); } const cleanup = window.electronAPI.kobold.onVersionsUpdated(() => { hasInitialized.current = false; - loadBackends(); + loadAccelerations(); }); return cleanup; }, []); useEffect(() => { - if (availableBackends.length > 0 && backend) { - const isBackendAvailable = availableBackends.some( - (b) => b.value === backend && !b.disabled + if (availableAccelerations.length > 0 && backend) { + const isAccelerationAvailable = availableAccelerations.some( + (a) => a.value === backend && !a.disabled ); - if (!isBackendAvailable) { - const fallbackBackend = availableBackends.find((b) => !b.disabled); - if (fallbackBackend) { - handleBackendChange(fallbackBackend.value); + if (!isAccelerationAvailable) { + const fallbackAcceleration = availableAccelerations.find( + (a) => !a.disabled + ); + if (fallbackAcceleration) { + handleBackendChange(fallbackAcceleration.value); } } } - }, [availableBackends, backend, handleBackendChange]); + }, [availableAccelerations, backend, handleBackendChange]); useEffect(() => { const calculateLayers = async () => { + const isCpuOnly = backend === 'cpu' && !isMac; if ( !autoGpuLayers || !model || !contextSize || - backend === 'cpu' || - isLoadingBackends + isCpuOnly || + isLoadingAccelerations ) { return; } @@ -133,7 +140,8 @@ export const BackendSelector = () => { backend, gpuDeviceSelection, flashattention, - isLoadingBackends, + isLoadingAccelerations, + isMac, handleGpuLayersChange, ]); @@ -143,16 +151,20 @@ export const BackendSelector = () => {
- Backend + Acceleration - +