import { spawn, ChildProcess } from 'child_process'; import { readFile, writeFile, copyFile } from 'fs/promises'; import { join } from 'path'; import { terminateProcess } from '@/utils/node/process'; import { logError, tryExecute, safeExecute } from '@/utils/node/logging'; import { sendKoboldOutput } from '../window'; import { SERVER_READY_SIGNALS } from '@/constants'; import { KLITE_CSS_OVERRIDE } from '@/constants/patches'; import { pathExists } from '@/utils/node/fs'; import { parseKoboldConfig } from '@/utils/node/kobold'; import { getAssetPath } from '@/utils/node/path'; import { getCurrentVersion } from './version'; import { getCurrentKoboldBinary, get as getConfig } from '../config'; import { startFrontend as startSillyTavernFrontend } from '@/main/modules/sillytavern'; import { startFrontend as startOpenWebUIFrontend } from '@/main/modules/openwebui'; import { startFrontend as startComfyUIFrontend } from '@/main/modules/comfyui'; import type { FrontendPreference, ImageGenerationFrontendPreference, } from '@/types'; let koboldProcess: ChildProcess | null = null; const patchKliteEmbd = (unpackedDir: string) => tryExecute(async () => { const possiblePaths = [ join(unpackedDir, '_internal', 'embd_res', 'klite.embd'), join(unpackedDir, 'klite.embd'), ]; let kliteEmbdPath: string | null = null; for (const path of possiblePaths) { if (await pathExists(path)) { kliteEmbdPath = path; break; } } if (!kliteEmbdPath) { return; } const content = await readFile(kliteEmbdPath, 'utf8'); if (content.includes('')) { let patchedContent = content; if (content.includes('gerbil-css-override')) { patchedContent = patchedContent.replace( /