import { ipcMain, shell, app } from 'electron'; import * as os from 'os'; import type { MantineColorScheme } from '@mantine/core'; import { launchKoboldCpp, downloadRelease, getInstalledVersions, getCurrentVersion, getConfigFiles, saveConfigFile, setCurrentVersion, selectInstallDirectory, stopKoboldCpp, parseConfigFile, selectModelFile, } from '@/main/modules/koboldcpp'; import { get as getConfig, set as setConfig, getSelectedConfig, setSelectedConfig, getInstallDir, getColorScheme, setColorScheme, } from '@/main/modules/config'; import { logError, getLogsDirectory } from '@/main/modules/logging'; import { getSillyTavernManager } from '@/main/modules/sillytavern'; import { startFrontend as startOpenWebUIFrontend, stopFrontend as stopOpenWebUIFrontend, isUvAvailable, } from '@/main/modules/openwebui'; import { getMainWindow } from '@/main/modules/window'; import { detectGPU, detectCPU, detectGPUCapabilities, detectGPUMemory, detectROCm, } from '@/main/modules/hardware'; import { detectBackendSupport, getAvailableBackends, } from '@/main/modules/binary'; import { setMainWindow, startMonitoring, stopMonitoring, } from '@/main/modules/monitoring'; import type { FrontendPreference } from '@/types'; async function launchKoboldCppWithCustomFrontends(args: string[] = []) { try { const frontendPreference = (await getConfig( 'frontendPreference' )) as FrontendPreference; const result = await launchKoboldCpp(args, frontendPreference); if (frontendPreference === 'sillytavern') { getSillyTavernManager().startFrontend(args); } else if (frontendPreference === 'openwebui') { startOpenWebUIFrontend(args); } return result; } catch (error) { logError('Error in enhanced launch:', error as Error); return { success: false, error: (error as Error).message, }; } } export function setupIPCHandlers() { ipcMain.handle('kobold:downloadRelease', async (_, asset) => ({ success: true, path: await downloadRelease(asset), })); ipcMain.handle('kobold:getInstalledVersions', () => getInstalledVersions()); ipcMain.handle('kobold:getCurrentVersion', () => getCurrentVersion()); ipcMain.handle('kobold:getConfigFiles', () => getConfigFiles()); ipcMain.handle('kobold:saveConfigFile', async (_, configName, configData) => saveConfigFile(configName, configData) ); ipcMain.handle('kobold:getSelectedConfig', () => getSelectedConfig()); ipcMain.handle('kobold:setSelectedConfig', (_, configName) => setSelectedConfig(configName) ); ipcMain.handle('kobold:setCurrentVersion', (_, version) => setCurrentVersion(version) ); ipcMain.handle('kobold:getCurrentInstallDir', () => getInstallDir()); ipcMain.handle('kobold:selectInstallDirectory', () => selectInstallDirectory() ); ipcMain.handle('kobold:detectGPU', () => detectGPU()); ipcMain.handle('kobold:detectCPU', () => detectCPU()); ipcMain.handle('kobold:detectGPUCapabilities', () => detectGPUCapabilities()); ipcMain.handle('kobold:detectGPUMemory', () => detectGPUMemory()); ipcMain.handle('kobold:detectROCm', () => detectROCm()); ipcMain.handle('kobold:detectBackendSupport', () => detectBackendSupport()); ipcMain.handle('kobold:getAvailableBackends', (_, includeDisabled = false) => getAvailableBackends(includeDisabled) ); ipcMain.handle('kobold:getPlatform', () => process.platform); ipcMain.handle('kobold:launchKoboldCpp', (_, args) => launchKoboldCppWithCustomFrontends(args) ); ipcMain.handle('kobold:stopKoboldCpp', () => { stopKoboldCpp(); getSillyTavernManager().stopFrontend(); stopOpenWebUIFrontend(); }); ipcMain.handle('kobold:parseConfigFile', (_, filePath) => parseConfigFile(filePath) ); ipcMain.handle('kobold:selectModelFile', (_, title) => selectModelFile(title) ); ipcMain.handle('config:get', (_, key) => getConfig(key)); ipcMain.handle('config:set', (_, key, value) => setConfig(key, value)); ipcMain.handle('app:getVersion', () => app.getVersion()); ipcMain.handle('app:getVersionInfo', () => ({ appVersion: app.getVersion(), electronVersion: process.versions.electron, nodeVersion: process.versions.node, chromeVersion: process.versions.chrome, v8Version: process.versions.v8, osVersion: os.release(), platform: process.platform, arch: process.arch, })); ipcMain.handle('app:showLogsFolder', async () => { try { const logsDir = getLogsDirectory(); await shell.openPath(logsDir); return { success: true }; } catch (error) { logError('Failed to open logs folder:', error as Error); throw new Error( `Failed to open logs folder: ${(error as Error).message}` ); } }); ipcMain.handle('app:minimizeWindow', () => { const mainWindow = getMainWindow(); mainWindow?.minimize(); }); ipcMain.handle('app:maximizeWindow', () => { const mainWindow = getMainWindow(); if (mainWindow?.isMaximized()) { mainWindow.restore(); } else { mainWindow?.maximize(); } }); ipcMain.handle('app:closeWindow', () => { const mainWindow = getMainWindow(); mainWindow?.close(); }); ipcMain.handle('app:getZoomLevel', async () => { const mainWindow = getMainWindow(); if (mainWindow) { return mainWindow.webContents.getZoomLevel(); } return 0; }); ipcMain.handle('app:setZoomLevel', async (_, level: number) => { const mainWindow = getMainWindow(); if (mainWindow) { mainWindow.webContents.setZoomLevel(level); await setConfig('zoomLevel', level); } }); ipcMain.handle('app:getColorScheme', () => getColorScheme()); ipcMain.handle( 'app:setColorScheme', async (_, colorScheme: MantineColorScheme) => { await setColorScheme(colorScheme); } ); const mainWindow = getMainWindow(); if (mainWindow) { mainWindow.webContents.once('did-finish-load', async () => { const savedZoomLevel = await getConfig('zoomLevel'); if (typeof savedZoomLevel === 'number') { mainWindow.webContents.setZoomLevel(savedZoomLevel); } }); } ipcMain.handle('logs:logError', (_, message: string, error?: Error) => { logError(message, error); }); ipcMain.handle('sillytavern:isNpxAvailable', () => getSillyTavernManager().isNpxAvailable() ); ipcMain.handle('openwebui:isUvAvailable', () => isUvAvailable()); ipcMain.handle('monitoring:start', () => { const mainWindow = getMainWindow(); if (mainWindow) { setMainWindow(mainWindow); startMonitoring(); } }); ipcMain.handle('monitoring:stop', () => { stopMonitoring(); }); }