mirror of
https://github.com/lone-cloud/gerbil
synced 2026-06-04 04:04:44 -07:00
the AI slop code cleanup continues, adding MMAP support, extra polish
This commit is contained in:
parent
7b0362711a
commit
e72c2f491c
21 changed files with 169 additions and 114 deletions
|
|
@ -74,9 +74,11 @@ trycloudflare
|
||||||
unquantized
|
unquantized
|
||||||
useclblast
|
useclblast
|
||||||
usecuda
|
usecuda
|
||||||
|
usemmap
|
||||||
usevulkan
|
usevulkan
|
||||||
vram
|
vram
|
||||||
vulkan
|
vulkan
|
||||||
vulkaninfo
|
vulkaninfo
|
||||||
wayland
|
wayland
|
||||||
websearch
|
websearch
|
||||||
|
MMAP
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "friendly-kobold",
|
"name": "friendly-kobold",
|
||||||
"productName": "Friendly Kobold",
|
"productName": "Friendly Kobold",
|
||||||
"version": "0.4.0",
|
"version": "0.4.1",
|
||||||
"description": "A modern Electron shell for KoboldCpp",
|
"description": "A modern Electron shell for KoboldCpp",
|
||||||
"main": "out/main/index.js",
|
"main": "out/main/index.js",
|
||||||
"homepage": "./",
|
"homepage": "./",
|
||||||
|
|
|
||||||
12
src/App.tsx
12
src/App.tsx
|
|
@ -6,7 +6,7 @@ import { InterfaceScreen } from '@/components/screens/Interface';
|
||||||
import { WelcomeScreen } from '@/components/screens/Welcome';
|
import { WelcomeScreen } from '@/components/screens/Welcome';
|
||||||
import { UpdateAvailableModal } from '@/components/UpdateAvailableModal';
|
import { UpdateAvailableModal } from '@/components/UpdateAvailableModal';
|
||||||
import { SettingsModal } from '@/components/settings/SettingsModal';
|
import { SettingsModal } from '@/components/settings/SettingsModal';
|
||||||
import { EjectConfirmDialog } from '@/components/EjectConfirmDialog';
|
import { EjectConfirmModal } from '@/components/EjectConfirmModal';
|
||||||
import { ScreenTransition } from '@/components/ScreenTransition';
|
import { ScreenTransition } from '@/components/ScreenTransition';
|
||||||
import { AppHeader } from '@/components/AppHeader';
|
import { AppHeader } from '@/components/AppHeader';
|
||||||
import { useUpdateChecker } from '@/hooks/useUpdateChecker';
|
import { useUpdateChecker } from '@/hooks/useUpdateChecker';
|
||||||
|
|
@ -20,7 +20,7 @@ export const App = () => {
|
||||||
const [currentScreen, setCurrentScreen] = useState<Screen | null>(null);
|
const [currentScreen, setCurrentScreen] = useState<Screen | null>(null);
|
||||||
const [settingsOpened, setSettingsOpened] = useState(false);
|
const [settingsOpened, setSettingsOpened] = useState(false);
|
||||||
const [hasInitialized, setHasInitialized] = useState(false);
|
const [hasInitialized, setHasInitialized] = useState(false);
|
||||||
const [showEjectDialog, setShowEjectDialog] = useState(false);
|
const [showEjectModal, setShowEjectModal] = useState(false);
|
||||||
const [activeInterfaceTab, setActiveInterfaceTab] = useState<string | null>(
|
const [activeInterfaceTab, setActiveInterfaceTab] = useState<string | null>(
|
||||||
'terminal'
|
'terminal'
|
||||||
);
|
);
|
||||||
|
|
@ -179,7 +179,7 @@ export const App = () => {
|
||||||
if (skipEjectConfirmation) {
|
if (skipEjectConfirmation) {
|
||||||
performEject();
|
performEject();
|
||||||
} else {
|
} else {
|
||||||
setShowEjectDialog(true);
|
setShowEjectModal(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -309,9 +309,9 @@ export const App = () => {
|
||||||
onClose={() => setSettingsOpened(false)}
|
onClose={() => setSettingsOpened(false)}
|
||||||
currentScreen={currentScreen || undefined}
|
currentScreen={currentScreen || undefined}
|
||||||
/>
|
/>
|
||||||
<EjectConfirmDialog
|
<EjectConfirmModal
|
||||||
opened={showEjectDialog}
|
opened={showEjectModal}
|
||||||
onClose={() => setShowEjectDialog(false)}
|
onClose={() => setShowEjectModal(false)}
|
||||||
onConfirm={handleEjectConfirm}
|
onConfirm={handleEjectConfirm}
|
||||||
/>
|
/>
|
||||||
</AppShell>
|
</AppShell>
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ import { Settings, ArrowLeft } from 'lucide-react';
|
||||||
import { StyledTooltip } from '@/components/StyledTooltip';
|
import { StyledTooltip } from '@/components/StyledTooltip';
|
||||||
import { soundAssets, playSound, initializeAudio } from '@/utils';
|
import { soundAssets, playSound, initializeAudio } from '@/utils';
|
||||||
import iconUrl from '/icon.png';
|
import iconUrl from '/icon.png';
|
||||||
import '@/styles/AppHeader.css';
|
|
||||||
|
|
||||||
type Screen = 'welcome' | 'download' | 'launch' | 'interface';
|
type Screen = 'welcome' | 'download' | 'launch' | 'interface';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Modal, Text, Group, Button, Checkbox, Stack } from '@mantine/core';
|
import { Modal, Text, Group, Button, Checkbox, Stack } from '@mantine/core';
|
||||||
|
|
||||||
interface EjectConfirmDialogProps {
|
interface EjectConfirmModalProps {
|
||||||
opened: boolean;
|
opened: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onConfirm: (skipConfirmation: boolean) => void;
|
onConfirm: (skipConfirmation: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const EjectConfirmDialog = ({
|
export const EjectConfirmModal = ({
|
||||||
opened,
|
opened,
|
||||||
onClose,
|
onClose,
|
||||||
onConfirm,
|
onConfirm,
|
||||||
}: EjectConfirmDialogProps) => {
|
}: EjectConfirmModalProps) => {
|
||||||
const [skipConfirmation, setSkipConfirmation] = useState(false);
|
const [skipConfirmation, setSkipConfirmation] = useState(false);
|
||||||
|
|
||||||
const handleConfirm = () => {
|
const handleConfirm = () => {
|
||||||
|
|
@ -13,6 +13,7 @@ export const AdvancedTab = () => {
|
||||||
failsafe,
|
failsafe,
|
||||||
lowvram,
|
lowvram,
|
||||||
quantmatmul,
|
quantmatmul,
|
||||||
|
usemmap,
|
||||||
backend,
|
backend,
|
||||||
handleAdditionalArgumentsChange,
|
handleAdditionalArgumentsChange,
|
||||||
handleNoshiftChange,
|
handleNoshiftChange,
|
||||||
|
|
@ -21,6 +22,7 @@ export const AdvancedTab = () => {
|
||||||
handleFailsafeChange,
|
handleFailsafeChange,
|
||||||
handleLowvramChange,
|
handleLowvramChange,
|
||||||
handleQuantmatmulChange,
|
handleQuantmatmulChange,
|
||||||
|
handleUsemmapChange,
|
||||||
} = useLaunchConfig();
|
} = useLaunchConfig();
|
||||||
const [backendSupport, setBackendSupport] = useState<{
|
const [backendSupport, setBackendSupport] = useState<{
|
||||||
noavx2: boolean;
|
noavx2: boolean;
|
||||||
|
|
@ -148,6 +150,19 @@ export const AdvancedTab = () => {
|
||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.minWidth200}>
|
||||||
|
<Group gap="xs" align="center">
|
||||||
|
<Checkbox
|
||||||
|
checked={usemmap}
|
||||||
|
onChange={(event) =>
|
||||||
|
handleUsemmapChange(event.currentTarget.checked)
|
||||||
|
}
|
||||||
|
label="MMAP"
|
||||||
|
/>
|
||||||
|
<InfoTooltip label="Use MMAP to load models when enabled." />
|
||||||
|
</Group>
|
||||||
|
</div>
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ export const LaunchScreen = ({
|
||||||
failsafe,
|
failsafe,
|
||||||
lowvram,
|
lowvram,
|
||||||
quantmatmul,
|
quantmatmul,
|
||||||
|
usemmap,
|
||||||
backend,
|
backend,
|
||||||
gpuDevice,
|
gpuDevice,
|
||||||
gpuPlatform,
|
gpuPlatform,
|
||||||
|
|
@ -148,6 +149,7 @@ export const LaunchScreen = ({
|
||||||
flashattention,
|
flashattention,
|
||||||
noavx2,
|
noavx2,
|
||||||
failsafe,
|
failsafe,
|
||||||
|
usemmap,
|
||||||
usecuda: backend === 'cuda' || backend === 'rocm',
|
usecuda: backend === 'cuda' || backend === 'rocm',
|
||||||
usevulkan: backend === 'vulkan',
|
usevulkan: backend === 'vulkan',
|
||||||
useclblast: backend === 'clblast',
|
useclblast: backend === 'clblast',
|
||||||
|
|
@ -248,10 +250,13 @@ export const LaunchScreen = ({
|
||||||
websearch,
|
websearch,
|
||||||
noshift,
|
noshift,
|
||||||
flashattention,
|
flashattention,
|
||||||
|
noavx2,
|
||||||
|
failsafe,
|
||||||
backend,
|
backend,
|
||||||
lowvram,
|
lowvram,
|
||||||
gpuDevice,
|
gpuDevice,
|
||||||
quantmatmul,
|
quantmatmul,
|
||||||
|
usemmap,
|
||||||
additionalArguments,
|
additionalArguments,
|
||||||
sdt5xxl,
|
sdt5xxl,
|
||||||
sdclipl,
|
sdclipl,
|
||||||
|
|
|
||||||
|
|
@ -2,5 +2,3 @@ export const DEFAULT_CONTEXT_SIZE = 4096;
|
||||||
|
|
||||||
export const DEFAULT_MODEL_URL =
|
export const DEFAULT_MODEL_URL =
|
||||||
'https://huggingface.co/MaziyarPanahi/gemma-3-4b-it-GGUF/resolve/main/gemma-3-4b-it.Q8_0.gguf?download=true';
|
'https://huggingface.co/MaziyarPanahi/gemma-3-4b-it-GGUF/resolve/main/gemma-3-4b-it.Q8_0.gguf?download=true';
|
||||||
|
|
||||||
export const DEFAULT_HOST = '';
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ export const useLaunchConfig = () => {
|
||||||
failsafe: state.failsafe,
|
failsafe: state.failsafe,
|
||||||
lowvram: state.lowvram,
|
lowvram: state.lowvram,
|
||||||
quantmatmul: state.quantmatmul,
|
quantmatmul: state.quantmatmul,
|
||||||
|
usemmap: state.usemmap,
|
||||||
backend: state.backend,
|
backend: state.backend,
|
||||||
gpuDevice: state.gpuDevice,
|
gpuDevice: state.gpuDevice,
|
||||||
gpuPlatform: state.gpuPlatform,
|
gpuPlatform: state.gpuPlatform,
|
||||||
|
|
@ -55,6 +56,7 @@ export const useLaunchConfig = () => {
|
||||||
handleFailsafeChange: state.setFailsafe,
|
handleFailsafeChange: state.setFailsafe,
|
||||||
handleLowvramChange: state.setLowvram,
|
handleLowvramChange: state.setLowvram,
|
||||||
handleQuantmatmulChange: state.setQuantmatmul,
|
handleQuantmatmulChange: state.setQuantmatmul,
|
||||||
|
handleUsemmapChange: state.setUsemmap,
|
||||||
handleBackendChange: state.setBackend,
|
handleBackendChange: state.setBackend,
|
||||||
handleGpuDeviceChange: state.setGpuDevice,
|
handleGpuDeviceChange: state.setGpuDevice,
|
||||||
handleGpuPlatformChange: state.setGpuPlatform,
|
handleGpuPlatformChange: state.setGpuPlatform,
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,13 @@ interface LaunchArgs {
|
||||||
websearch: boolean;
|
websearch: boolean;
|
||||||
noshift: boolean;
|
noshift: boolean;
|
||||||
flashattention: boolean;
|
flashattention: boolean;
|
||||||
|
noavx2: boolean;
|
||||||
|
failsafe: boolean;
|
||||||
backend: string;
|
backend: string;
|
||||||
lowvram: boolean;
|
lowvram: boolean;
|
||||||
gpuDevice: number | string;
|
gpuDevice: number | string;
|
||||||
quantmatmul: boolean;
|
quantmatmul: boolean;
|
||||||
|
usemmap: boolean;
|
||||||
additionalArguments: string;
|
additionalArguments: string;
|
||||||
sdt5xxl: string;
|
sdt5xxl: string;
|
||||||
sdclipl: string;
|
sdclipl: string;
|
||||||
|
|
@ -98,6 +101,9 @@ const buildConfigArgs = (launchArgs: LaunchArgs): string[] => {
|
||||||
[launchArgs.websearch, '--websearch'],
|
[launchArgs.websearch, '--websearch'],
|
||||||
[launchArgs.noshift, '--noshift'],
|
[launchArgs.noshift, '--noshift'],
|
||||||
[launchArgs.flashattention, '--flashattention'],
|
[launchArgs.flashattention, '--flashattention'],
|
||||||
|
[launchArgs.noavx2, '--noavx2'],
|
||||||
|
[launchArgs.failsafe, '--failsafe'],
|
||||||
|
[launchArgs.usemmap, '--usemmap'],
|
||||||
];
|
];
|
||||||
|
|
||||||
flagMappings.forEach(([condition, flag, value]) => {
|
flagMappings.forEach(([condition, flag, value]) => {
|
||||||
|
|
|
||||||
|
|
@ -384,6 +384,7 @@ export class KoboldCppManager {
|
||||||
flashattention?: boolean;
|
flashattention?: boolean;
|
||||||
noavx2?: boolean;
|
noavx2?: boolean;
|
||||||
failsafe?: boolean;
|
failsafe?: boolean;
|
||||||
|
usemmap?: boolean;
|
||||||
usecuda?: boolean;
|
usecuda?: boolean;
|
||||||
usevulkan?: boolean;
|
usevulkan?: boolean;
|
||||||
useclblast?: [number, number] | boolean;
|
useclblast?: [number, number] | boolean;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,4 @@
|
||||||
import {
|
import { BrowserWindow, app, Menu, shell, nativeImage } from 'electron';
|
||||||
BrowserWindow,
|
|
||||||
app,
|
|
||||||
Menu,
|
|
||||||
shell,
|
|
||||||
ipcMain,
|
|
||||||
nativeImage,
|
|
||||||
} from 'electron';
|
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { GITHUB_API } from '../../constants';
|
import { GITHUB_API } from '../../constants';
|
||||||
|
|
@ -311,8 +304,9 @@ OS: ${osInfo}`;
|
||||||
maximizable: false,
|
maximizable: false,
|
||||||
show: false,
|
show: false,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: false,
|
||||||
contextIsolation: false,
|
contextIsolation: true,
|
||||||
|
preload: join(__dirname, '../preload/index.js'),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -328,21 +322,6 @@ OS: ${osInfo}`;
|
||||||
aboutWindow.once('ready-to-show', () => {
|
aboutWindow.once('ready-to-show', () => {
|
||||||
aboutWindow.show();
|
aboutWindow.show();
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.once('open-github', () => {
|
|
||||||
shell.openExternal(
|
|
||||||
`https://github.com/${GITHUB_API.FRIENDLY_KOBOLD_REPO}`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.once('close-about-dialog', () => {
|
|
||||||
aboutWindow.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
aboutWindow.on('closed', () => {
|
|
||||||
ipcMain.removeAllListeners('open-github');
|
|
||||||
ipcMain.removeAllListeners('close-about-dialog');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private getTemplatePath(filename: string): string {
|
private getTemplatePath(filename: string): string {
|
||||||
|
|
|
||||||
|
|
@ -131,8 +131,6 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const { ipcRenderer } = require('electron');
|
|
||||||
|
|
||||||
function setVersionInfo(info) {
|
function setVersionInfo(info) {
|
||||||
document.getElementById('version-info').innerHTML = info.replace(
|
document.getElementById('version-info').innerHTML = info.replace(
|
||||||
/\n/g,
|
/\n/g,
|
||||||
|
|
@ -141,11 +139,16 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function openGitHub() {
|
function openGitHub() {
|
||||||
ipcRenderer.send('open-github');
|
// Send IPC message directly since this is a simple modal
|
||||||
|
if (window.electronAPI && window.electronAPI.app) {
|
||||||
|
window.electronAPI.app.openExternal(
|
||||||
|
'https://github.com/lone-cloud/friendly-kobold'
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeDialog() {
|
function closeDialog() {
|
||||||
ipcRenderer.send('close-about-dialog');
|
window.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle keyboard shortcuts
|
// Handle keyboard shortcuts
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,10 @@ import { contextBridge, ipcRenderer, type IpcRendererEvent } from 'electron';
|
||||||
import type { KoboldAPI, AppAPI, ConfigAPI, LogsAPI } from '@/types/electron';
|
import type { KoboldAPI, AppAPI, ConfigAPI, LogsAPI } from '@/types/electron';
|
||||||
|
|
||||||
const koboldAPI: KoboldAPI = {
|
const koboldAPI: KoboldAPI = {
|
||||||
getInstalledVersion: () => ipcRenderer.invoke('kobold:getInstalledVersion'),
|
|
||||||
getInstalledVersions: () => ipcRenderer.invoke('kobold:getInstalledVersions'),
|
getInstalledVersions: () => ipcRenderer.invoke('kobold:getInstalledVersions'),
|
||||||
getCurrentVersion: () => ipcRenderer.invoke('kobold:getCurrentVersion'),
|
|
||||||
getCurrentBinaryInfo: () => ipcRenderer.invoke('kobold:getCurrentBinaryInfo'),
|
getCurrentBinaryInfo: () => ipcRenderer.invoke('kobold:getCurrentBinaryInfo'),
|
||||||
setCurrentVersion: (version: string) =>
|
setCurrentVersion: (version: string) =>
|
||||||
ipcRenderer.invoke('kobold:setCurrentVersion', version),
|
ipcRenderer.invoke('kobold:setCurrentVersion', version),
|
||||||
getVersionFromBinary: (binaryPath: string) =>
|
|
||||||
ipcRenderer.invoke('kobold:getVersionFromBinary', binaryPath),
|
|
||||||
getLatestReleaseWithStatus: () =>
|
getLatestReleaseWithStatus: () =>
|
||||||
ipcRenderer.invoke('kobold:getLatestReleaseWithStatus'),
|
ipcRenderer.invoke('kobold:getLatestReleaseWithStatus'),
|
||||||
getROCmDownload: () => ipcRenderer.invoke('kobold:getROCmDownload'),
|
getROCmDownload: () => ipcRenderer.invoke('kobold:getROCmDownload'),
|
||||||
|
|
@ -18,11 +14,7 @@ const koboldAPI: KoboldAPI = {
|
||||||
getPlatform: () => ipcRenderer.invoke('kobold:getPlatform'),
|
getPlatform: () => ipcRenderer.invoke('kobold:getPlatform'),
|
||||||
detectGPU: () => ipcRenderer.invoke('kobold:detectGPU'),
|
detectGPU: () => ipcRenderer.invoke('kobold:detectGPU'),
|
||||||
detectCPU: () => ipcRenderer.invoke('kobold:detectCPU'),
|
detectCPU: () => ipcRenderer.invoke('kobold:detectCPU'),
|
||||||
detectGPUCapabilities: () =>
|
|
||||||
ipcRenderer.invoke('kobold:detectGPUCapabilities'),
|
|
||||||
detectROCm: () => ipcRenderer.invoke('kobold:detectROCm'),
|
detectROCm: () => ipcRenderer.invoke('kobold:detectROCm'),
|
||||||
detectAllCapabilities: () =>
|
|
||||||
ipcRenderer.invoke('kobold:detectAllCapabilities'),
|
|
||||||
detectBackendSupport: (binaryPath: string) =>
|
detectBackendSupport: (binaryPath: string) =>
|
||||||
ipcRenderer.invoke('kobold:detectBackendSupport', binaryPath),
|
ipcRenderer.invoke('kobold:detectBackendSupport', binaryPath),
|
||||||
getAvailableBackends: () => ipcRenderer.invoke('kobold:getAvailableBackends'),
|
getAvailableBackends: () => ipcRenderer.invoke('kobold:getAvailableBackends'),
|
||||||
|
|
@ -33,7 +25,6 @@ const koboldAPI: KoboldAPI = {
|
||||||
ipcRenderer.invoke('kobold:downloadRelease', asset),
|
ipcRenderer.invoke('kobold:downloadRelease', asset),
|
||||||
launchKoboldCpp: (args?: string[], configFilePath?: string) =>
|
launchKoboldCpp: (args?: string[], configFilePath?: string) =>
|
||||||
ipcRenderer.invoke('kobold:launchKoboldCpp', args, configFilePath),
|
ipcRenderer.invoke('kobold:launchKoboldCpp', args, configFilePath),
|
||||||
checkForUpdates: () => ipcRenderer.invoke('kobold:checkForUpdates'),
|
|
||||||
getConfigFiles: () => ipcRenderer.invoke('kobold:getConfigFiles'),
|
getConfigFiles: () => ipcRenderer.invoke('kobold:getConfigFiles'),
|
||||||
saveConfigFile: (
|
saveConfigFile: (
|
||||||
configName: string,
|
configName: string,
|
||||||
|
|
@ -52,6 +43,7 @@ const koboldAPI: KoboldAPI = {
|
||||||
flashattention?: boolean;
|
flashattention?: boolean;
|
||||||
noavx2?: boolean;
|
noavx2?: boolean;
|
||||||
failsafe?: boolean;
|
failsafe?: boolean;
|
||||||
|
usemmap?: boolean;
|
||||||
usecuda?: boolean;
|
usecuda?: boolean;
|
||||||
usevulkan?: boolean;
|
usevulkan?: boolean;
|
||||||
useclblast?: boolean;
|
useclblast?: boolean;
|
||||||
|
|
@ -107,7 +99,6 @@ const koboldAPI: KoboldAPI = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const appAPI: AppAPI = {
|
const appAPI: AppAPI = {
|
||||||
getVersion: () => ipcRenderer.invoke('app:getVersion'),
|
|
||||||
openExternal: (url) => ipcRenderer.invoke('app:openExternal', url),
|
openExternal: (url) => ipcRenderer.invoke('app:openExternal', url),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import type { ConfigFile } from '@/types';
|
import type { ConfigFile } from '@/types';
|
||||||
import type { ImageModelPreset } from '@/utils/imageModelPresets';
|
import type { ImageModelPreset } from '@/utils/imageModelPresets';
|
||||||
import { DEFAULT_CONTEXT_SIZE, DEFAULT_HOST } from '@/constants';
|
import { DEFAULT_CONTEXT_SIZE } from '@/constants';
|
||||||
|
|
||||||
interface LaunchConfigState {
|
interface LaunchConfigState {
|
||||||
gpuLayers: number;
|
gpuLayers: number;
|
||||||
|
|
@ -22,6 +22,7 @@ interface LaunchConfigState {
|
||||||
failsafe: boolean;
|
failsafe: boolean;
|
||||||
lowvram: boolean;
|
lowvram: boolean;
|
||||||
quantmatmul: boolean;
|
quantmatmul: boolean;
|
||||||
|
usemmap: boolean;
|
||||||
backend: string;
|
backend: string;
|
||||||
gpuDevice: number;
|
gpuDevice: number;
|
||||||
gpuPlatform: number;
|
gpuPlatform: number;
|
||||||
|
|
@ -51,6 +52,7 @@ interface LaunchConfigState {
|
||||||
setFailsafe: (failsafe: boolean) => void;
|
setFailsafe: (failsafe: boolean) => void;
|
||||||
setLowvram: (lowvram: boolean) => void;
|
setLowvram: (lowvram: boolean) => void;
|
||||||
setQuantmatmul: (quantmatmul: boolean) => void;
|
setQuantmatmul: (quantmatmul: boolean) => void;
|
||||||
|
setUsemmap: (usemmap: boolean) => void;
|
||||||
setBackend: (backend: string) => void;
|
setBackend: (backend: string) => void;
|
||||||
setGpuDevice: (device: number) => void;
|
setGpuDevice: (device: number) => void;
|
||||||
setGpuPlatform: (platform: number) => void;
|
setGpuPlatform: (platform: number) => void;
|
||||||
|
|
@ -86,7 +88,7 @@ export const useLaunchConfigStore = create<LaunchConfigState>((set, get) => ({
|
||||||
modelPath: '',
|
modelPath: '',
|
||||||
additionalArguments: '',
|
additionalArguments: '',
|
||||||
port: undefined,
|
port: undefined,
|
||||||
host: DEFAULT_HOST,
|
host: '',
|
||||||
multiuser: false,
|
multiuser: false,
|
||||||
multiplayer: false,
|
multiplayer: false,
|
||||||
remotetunnel: false,
|
remotetunnel: false,
|
||||||
|
|
@ -98,6 +100,7 @@ export const useLaunchConfigStore = create<LaunchConfigState>((set, get) => ({
|
||||||
failsafe: false,
|
failsafe: false,
|
||||||
lowvram: false,
|
lowvram: false,
|
||||||
quantmatmul: true,
|
quantmatmul: true,
|
||||||
|
usemmap: true,
|
||||||
backend: '',
|
backend: '',
|
||||||
gpuDevice: 0,
|
gpuDevice: 0,
|
||||||
gpuPlatform: 0,
|
gpuPlatform: 0,
|
||||||
|
|
@ -127,6 +130,7 @@ export const useLaunchConfigStore = create<LaunchConfigState>((set, get) => ({
|
||||||
setFailsafe: (failsafe) => set({ failsafe }),
|
setFailsafe: (failsafe) => set({ failsafe }),
|
||||||
setLowvram: (lowvram) => set({ lowvram }),
|
setLowvram: (lowvram) => set({ lowvram }),
|
||||||
setQuantmatmul: (quantmatmul) => set({ quantmatmul }),
|
setQuantmatmul: (quantmatmul) => set({ quantmatmul }),
|
||||||
|
setUsemmap: (usemmap) => set({ usemmap }),
|
||||||
setBackend: (backend) => set({ backend }),
|
setBackend: (backend) => set({ backend }),
|
||||||
setGpuDevice: (device) => set({ gpuDevice: device }),
|
setGpuDevice: (device) => set({ gpuDevice: device }),
|
||||||
setGpuPlatform: (platform) => set({ gpuPlatform: platform }),
|
setGpuPlatform: (platform) => set({ gpuPlatform: platform }),
|
||||||
|
|
@ -171,7 +175,7 @@ export const useLaunchConfigStore = create<LaunchConfigState>((set, get) => ({
|
||||||
if (typeof configData.host === 'string') {
|
if (typeof configData.host === 'string') {
|
||||||
updates.host = configData.host;
|
updates.host = configData.host;
|
||||||
} else {
|
} else {
|
||||||
updates.host = DEFAULT_HOST;
|
updates.host = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof configData.multiuser === 'number') {
|
if (typeof configData.multiuser === 'number') {
|
||||||
|
|
@ -236,6 +240,12 @@ export const useLaunchConfigStore = create<LaunchConfigState>((set, get) => ({
|
||||||
updates.quantmatmul = configData.quantmatmul;
|
updates.quantmatmul = configData.quantmatmul;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof configData.usemmap === 'boolean') {
|
||||||
|
updates.usemmap = configData.usemmap;
|
||||||
|
} else {
|
||||||
|
updates.usemmap = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (configData.usecuda === true) {
|
if (configData.usecuda === true) {
|
||||||
const gpuInfo = await window.electronAPI.kobold.detectGPU();
|
const gpuInfo = await window.electronAPI.kobold.detectGPU();
|
||||||
updates.backend = gpuInfo.hasNVIDIA ? 'cuda' : 'rocm';
|
updates.backend = gpuInfo.hasNVIDIA ? 'cuda' : 'rocm';
|
||||||
|
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
@keyframes elephantShake {
|
|
||||||
0%,
|
|
||||||
100% {
|
|
||||||
transform: scale(1.3) rotate(5deg) translateX(0px);
|
|
||||||
}
|
|
||||||
10% {
|
|
||||||
transform: scale(1.4) rotate(-3deg) translateX(-2px);
|
|
||||||
}
|
|
||||||
20% {
|
|
||||||
transform: scale(1.5) rotate(8deg) translateX(2px);
|
|
||||||
}
|
|
||||||
30% {
|
|
||||||
transform: scale(1.4) rotate(-5deg) translateX(-1px);
|
|
||||||
}
|
|
||||||
40% {
|
|
||||||
transform: scale(1.6) rotate(10deg) translateX(3px);
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
transform: scale(1.3) rotate(-8deg) translateX(-2px);
|
|
||||||
}
|
|
||||||
60% {
|
|
||||||
transform: scale(1.5) rotate(6deg) translateX(1px);
|
|
||||||
}
|
|
||||||
70% {
|
|
||||||
transform: scale(1.2) rotate(-4deg) translateX(-1px);
|
|
||||||
}
|
|
||||||
80% {
|
|
||||||
transform: scale(1.4) rotate(3deg) translateX(2px);
|
|
||||||
}
|
|
||||||
90% {
|
|
||||||
transform: scale(1.1) rotate(-2deg) translateX(-1px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes mouseSqueak {
|
|
||||||
0% {
|
|
||||||
transform: scale(1) rotate(0deg);
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
transform: scale(1.15) rotate(2deg);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: scale(1) rotate(0deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1 +1,97 @@
|
||||||
@import '@mantine/core/styles.css';
|
@import '@mantine/core/styles.css';
|
||||||
|
|
||||||
|
/* Global smooth scrolling */
|
||||||
|
* {
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom scrollbars */
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: transparent;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: rgba(134, 142, 150, 0.5);
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: rgba(134, 142, 150, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:active {
|
||||||
|
background: rgba(73, 80, 87, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark mode scrollbar support */
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: rgba(173, 181, 189, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: rgba(173, 181, 189, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:active {
|
||||||
|
background: rgba(206, 212, 218, 0.9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* AppHeader animations */
|
||||||
|
@keyframes elephantShake {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
transform: scale(1.3) rotate(5deg) translateX(0px);
|
||||||
|
}
|
||||||
|
10% {
|
||||||
|
transform: scale(1.4) rotate(-3deg) translateX(-2px);
|
||||||
|
}
|
||||||
|
20% {
|
||||||
|
transform: scale(1.5) rotate(8deg) translateX(2px);
|
||||||
|
}
|
||||||
|
30% {
|
||||||
|
transform: scale(1.4) rotate(-5deg) translateX(-1px);
|
||||||
|
}
|
||||||
|
40% {
|
||||||
|
transform: scale(1.6) rotate(10deg) translateX(3px);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(1.3) rotate(-8deg) translateX(-2px);
|
||||||
|
}
|
||||||
|
60% {
|
||||||
|
transform: scale(1.5) rotate(6deg) translateX(1px);
|
||||||
|
}
|
||||||
|
70% {
|
||||||
|
transform: scale(1.2) rotate(-4deg) translateX(-1px);
|
||||||
|
}
|
||||||
|
80% {
|
||||||
|
transform: scale(1.4) rotate(3deg) translateX(2px);
|
||||||
|
}
|
||||||
|
90% {
|
||||||
|
transform: scale(1.1) rotate(-2deg) translateX(-1px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes mouseSqueak {
|
||||||
|
0% {
|
||||||
|
transform: scale(1) rotate(0deg);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(1.15) rotate(2deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1) rotate(0deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
8
src/types/electron.d.ts
vendored
8
src/types/electron.d.ts
vendored
|
|
@ -57,22 +57,17 @@ export interface DownloadItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface KoboldAPI {
|
export interface KoboldAPI {
|
||||||
getInstalledVersion: () => Promise<string | undefined>;
|
|
||||||
getInstalledVersions: () => Promise<InstalledVersion[]>;
|
getInstalledVersions: () => Promise<InstalledVersion[]>;
|
||||||
getCurrentVersion: () => Promise<InstalledVersion | null>;
|
|
||||||
getCurrentBinaryInfo: () => Promise<{
|
getCurrentBinaryInfo: () => Promise<{
|
||||||
path: string;
|
path: string;
|
||||||
filename: string;
|
filename: string;
|
||||||
} | null>;
|
} | null>;
|
||||||
setCurrentVersion: (version: string) => Promise<boolean>;
|
setCurrentVersion: (version: string) => Promise<boolean>;
|
||||||
getVersionFromBinary: (binaryPath: string) => Promise<string | null>;
|
|
||||||
getLatestRelease: () => Promise<DownloadItem[]>;
|
getLatestRelease: () => Promise<DownloadItem[]>;
|
||||||
getPlatform: () => Promise<PlatformInfo>;
|
getPlatform: () => Promise<PlatformInfo>;
|
||||||
detectGPU: () => Promise<BasicGPUInfo>;
|
detectGPU: () => Promise<BasicGPUInfo>;
|
||||||
detectCPU: () => Promise<CPUCapabilities>;
|
detectCPU: () => Promise<CPUCapabilities>;
|
||||||
detectGPUCapabilities: () => Promise<GPUCapabilities>;
|
|
||||||
detectROCm: () => Promise<{ supported: boolean; devices: string[] }>;
|
detectROCm: () => Promise<{ supported: boolean; devices: string[] }>;
|
||||||
detectAllCapabilities: () => Promise<HardwareInfo>;
|
|
||||||
detectBackendSupport: (binaryPath: string) => Promise<{
|
detectBackendSupport: (binaryPath: string) => Promise<{
|
||||||
rocm: boolean;
|
rocm: boolean;
|
||||||
vulkan: boolean;
|
vulkan: boolean;
|
||||||
|
|
@ -95,7 +90,6 @@ export interface KoboldAPI {
|
||||||
error?: string;
|
error?: string;
|
||||||
}>;
|
}>;
|
||||||
getROCmDownload: () => Promise<DownloadItem | null>;
|
getROCmDownload: () => Promise<DownloadItem | null>;
|
||||||
checkForUpdates: () => Promise<UpdateInfo | null>;
|
|
||||||
getLatestReleaseWithStatus: () => Promise<ReleaseWithStatus | null>;
|
getLatestReleaseWithStatus: () => Promise<ReleaseWithStatus | null>;
|
||||||
launchKoboldCpp: (
|
launchKoboldCpp: (
|
||||||
args?: string[],
|
args?: string[],
|
||||||
|
|
@ -121,6 +115,7 @@ export interface KoboldAPI {
|
||||||
flashattention?: boolean;
|
flashattention?: boolean;
|
||||||
noavx2?: boolean;
|
noavx2?: boolean;
|
||||||
failsafe?: boolean;
|
failsafe?: boolean;
|
||||||
|
usemmap?: boolean;
|
||||||
usecuda?: boolean;
|
usecuda?: boolean;
|
||||||
usevulkan?: boolean;
|
usevulkan?: boolean;
|
||||||
useclblast?: boolean;
|
useclblast?: boolean;
|
||||||
|
|
@ -152,7 +147,6 @@ export interface KoboldAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AppAPI {
|
export interface AppAPI {
|
||||||
getVersion: () => Promise<string>;
|
|
||||||
openExternal: (url: string) => Promise<void>;
|
openExternal: (url: string) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { formatFileSizeInMB } from '@/utils/fileSize';
|
|
||||||
import { KOBOLDAI_URLS } from '@/constants';
|
import { KOBOLDAI_URLS } from '@/constants';
|
||||||
|
|
||||||
export const formatDownloadSize = (size: number, url?: string): string => {
|
export const formatDownloadSize = (size: number, url?: string): string => {
|
||||||
|
|
@ -35,3 +34,9 @@ export const compareVersions = (versionA: string, versionB: string): number => {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const formatFileSizeInMB = (bytes: number) => {
|
||||||
|
if (bytes === 0) return '0 MB';
|
||||||
|
const mb = bytes / (1024 * 1024);
|
||||||
|
return parseFloat(mb.toFixed(1)) + ' MB';
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
export const formatFileSizeInMB = (bytes: number) => {
|
|
||||||
if (bytes === 0) return '0 MB';
|
|
||||||
const mb = bytes / (1024 * 1024);
|
|
||||||
return parseFloat(mb.toFixed(1)) + ' MB';
|
|
||||||
};
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
export * from './assets';
|
export * from './assets';
|
||||||
export * from './clblast';
|
export * from './clblast';
|
||||||
export * from './downloadUtils';
|
export * from './downloadUtils';
|
||||||
export * from './fileSize';
|
|
||||||
export * from './hardware';
|
export * from './hardware';
|
||||||
export * from './imageModelPresets';
|
export * from './imageModelPresets';
|
||||||
export * from './platform';
|
export * from './platform';
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue