From 05cb3b8c0578c260a8a9d4259aff44578b081ef9 Mon Sep 17 00:00:00 2001 From: Egor Date: Sat, 29 Nov 2025 17:52:29 -0800 Subject: [PATCH] allow gerbil to work fully offline by allowing kcpp binary imports on the initial Download screen, more version -> backend renames --- package.json | 8 +- src/components/App/UpdateAvailableModal.tsx | 4 +- src/components/App/index.tsx | 6 +- src/components/DownloadCard.tsx | 48 ++--- src/components/screens/Download.tsx | 176 +++++++++++------- src/components/settings/BackendsTab.tsx | 26 +-- src/hooks/useUpdateChecker.ts | 8 +- src/main/ipc.ts | 7 +- src/main/modules/koboldcpp/backend.ts | 18 +- src/main/modules/koboldcpp/download.ts | 152 +++++++++++---- src/preload/index.ts | 5 +- .../{koboldVersions.ts => koboldBackends.ts} | 23 +-- src/types/electron.d.ts | 5 +- src/types/index.d.ts | 4 +- src/utils/assets.ts | 24 ++- yarn.lock | 30 +-- 16 files changed, 346 insertions(+), 198 deletions(-) rename src/stores/{koboldVersions.ts => koboldBackends.ts} (90%) diff --git a/package.json b/package.json index 60836c8..802bd4d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "gerbil", "productName": "Gerbil", - "version": "1.13.0", + "version": "1.14.0", "description": "Run Large Language Models locally", "main": "out/main/index.js", "homepage": "./", @@ -60,7 +60,7 @@ "eslint-plugin-sonarjs": "^3.0.5", "globals": "^16.5.0", "jiti": "^2.6.1", - "prettier": "^3.7.2", + "prettier": "^3.7.3", "rollup-plugin-visualizer": "^6.0.5", "typescript": "^5.9.3", "vite": "^7.2.4" @@ -75,7 +75,7 @@ "@mantine/hooks": "^8.3.9", "@uiw/react-codemirror": "^4.25.3", "electron-updater": "^6.6.2", - "execa": "^9.6.0", + "execa": "^9.6.1", "lucide-react": "^0.555.0", "mime-types": "^3.0.2", "react": "^19.2.0", @@ -85,7 +85,7 @@ "winston": "^3.18.3", "winston-daily-rotate-file": "^5.0.0", "yauzl": "^3.2.0", - "zustand": "^5.0.8" + "zustand": "^5.0.9" }, "build": { "appId": "com.gerbil.app", diff --git a/src/components/App/UpdateAvailableModal.tsx b/src/components/App/UpdateAvailableModal.tsx index a37bb93..cd5b325 100644 --- a/src/components/App/UpdateAvailableModal.tsx +++ b/src/components/App/UpdateAvailableModal.tsx @@ -12,7 +12,7 @@ import { Download, X, ExternalLink } from 'lucide-react'; import { useState } from 'react'; import type { DownloadItem } from '@/types/electron'; import type { BinaryUpdateInfo } from '@/hooks/useUpdateChecker'; -import { useKoboldVersionsStore } from '@/stores/koboldVersions'; +import { useKoboldBackendsStore } from '@/stores/koboldBackends'; import { pretifyBinName } from '@/utils/assets'; import { formatDownloadSize } from '@/utils/format'; import { GITHUB_API } from '@/constants'; @@ -34,7 +34,7 @@ export const UpdateAvailableModal = ({ updateInfo, onUpdate, }: UpdateAvailableModalProps) => { - const { downloading, downloadProgress } = useKoboldVersionsStore(); + const { downloading, downloadProgress } = useKoboldBackendsStore(); const currentBackend = updateInfo?.currentBackend; const availableUpdate = updateInfo?.availableUpdate; const [isUpdating, setIsUpdating] = useState(false); diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index b149254..dc198ca 100644 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -15,7 +15,7 @@ import { ErrorBoundary } from '@/components/App/ErrorBoundary'; import { AppRouter } from '@/components/App/Router'; import { NotepadContainer } from '@/components/Notepad/Container'; import { useUpdateChecker } from '@/hooks/useUpdateChecker'; -import { useKoboldVersionsStore } from '@/stores/koboldVersions'; +import { useKoboldBackendsStore } from '@/stores/koboldBackends'; import { usePreferencesStore } from '@/stores/preferences'; import { useLaunchConfigStore } from '@/stores/launchConfig'; import { STATUSBAR_HEIGHT, TITLEBAR_HEIGHT } from '@/constants'; @@ -81,7 +81,7 @@ export const App = () => { closeModal, } = useUpdateChecker(); - const { handleDownload, loadingRemote } = useKoboldVersionsStore(); + const { handleDownload, loadingRemote } = useKoboldBackendsStore(); const determineScreen = ( currentVersion: unknown, @@ -142,7 +142,7 @@ export const App = () => { item: download, isUpdate: true, wasCurrentBinary: true, - oldVersionPath: currentBackend?.path, + oldBackendPath: currentBackend?.path, }); closeModal(); diff --git a/src/components/DownloadCard.tsx b/src/components/DownloadCard.tsx index 49c3d6b..75387ce 100644 --- a/src/components/DownloadCard.tsx +++ b/src/components/DownloadCard.tsx @@ -13,11 +13,11 @@ import { Download, Trash2 } from 'lucide-react'; import { MouseEvent } from 'react'; import { pretifyBinName, isWindowsROCmBuild } from '@/utils/assets'; import { usePreferencesStore } from '@/stores/preferences'; -import { useKoboldVersionsStore } from '@/stores/koboldVersions'; -import type { VersionInfo } from '@/types'; +import { useKoboldBackendsStore } from '@/stores/koboldBackends'; +import type { BackendInfo } from '@/types'; interface DownloadCardProps { - version: VersionInfo; + backend: BackendInfo; size: string; description?: string; disabled?: boolean; @@ -29,7 +29,7 @@ interface DownloadCardProps { } export const DownloadCard = ({ - version: versionInfo, + backend, size, description, disabled = false, @@ -40,23 +40,23 @@ export const DownloadCard = ({ onDelete, }: DownloadCardProps) => { const { resolvedColorScheme: colorScheme } = usePreferencesStore(); - const { downloading, downloadProgress } = useKoboldVersionsStore(); + const { downloading, downloadProgress } = useKoboldBackendsStore(); - const isLoading = downloading === versionInfo.name; + const isLoading = downloading === backend.name; const currentProgress = isLoading - ? Math.min(downloadProgress[versionInfo.name], 100) || 0 + ? Math.min(downloadProgress[backend.name], 100) || 0 : 0; const hasVersionMismatch = Boolean( - versionInfo.version && - versionInfo.actualVersion && - versionInfo.version !== versionInfo.actualVersion + backend.version && + backend.actualVersion && + backend.version !== backend.actualVersion ); // eslint-disable-next-line sonarjs/cognitive-complexity const renderActionButtons = () => { const buttons = []; - if (!versionInfo.isInstalled) { + if (!backend.isInstalled) { return ( ); } @@ -138,7 +138,7 @@ export const DownloadCard = ({ ); } - if (onDelete && versionInfo.isInstalled && !versionInfo.isCurrent) { + if (onDelete && backend.isInstalled && !backend.isCurrent) { buttons.push(