From e1ef8596e5760ef6c766fff9b91f9aa38e04fb02 Mon Sep 17 00:00:00 2001 From: Egor Date: Wed, 20 Aug 2025 18:24:16 -0700 Subject: [PATCH] fix terminal display on windows, better cspell --- .cspell/project-terms.txt | 82 ++++++++++++ cspell.json | 119 ++++-------------- .../screens/Interface/TerminalTab.tsx | 24 +--- src/main/managers/KoboldCppManager.ts | 62 +++++++-- 4 files changed, 153 insertions(+), 134 deletions(-) create mode 100644 .cspell/project-terms.txt diff --git a/.cspell/project-terms.txt b/.cspell/project-terms.txt new file mode 100644 index 0000000..4a1a15f --- /dev/null +++ b/.cspell/project-terms.txt @@ -0,0 +1,82 @@ +AMDGPU +APPIMAGE +BLAS +CUDA +GGUF +KOBOLDAI +KOBOLDCPP +OLDPC +ROCM +SDXL +SPACEBAR +Consolas +Cooldown +Dolfino +Flashattention +KoboldCpp +Lowvram +Segoe +Tauri +asar +clblast +clinfo +contextsize +cublas +cuda +finetuned +flashattention +friendlykobold +geforce +ggml +gguf +gpulayers +hipblas +kcpps +kcppt +koboldai +koboldcpp +lora +lowvram +maximizable +minimizable +mmproj +mmq +multiuser +noavx +nocertify +nocuda +noheader +nommq +noshift +nsis +nvidia +oldpc +opencl +pkexec +quantmatmul +radeon +remotetunnel +rocm +rocminfo +safetensors +sdclipg +sdclipl +sdlora +sdmodel +sdphotomaker +sdui +sdvae +sonarjs +taskkill +togglefullscreen +treemap +trycloudflare +unquantized +useclblast +usecuda +usevulkan +vram +vulkan +vulkaninfo +wayland +websearch diff --git a/cspell.json b/cspell.json index f3da924..31da32c 100644 --- a/cspell.json +++ b/cspell.json @@ -1,91 +1,25 @@ { "version": "0.2", "language": "en", - // Only project-specific terms that aren't covered by built-in dictionaries - "words": [ - "AMDGPU", - "APPIMAGE", - "asar", - "BLAS", - "clblast", - "clinfo", - "contextsize", - "Cooldown", - "cublas", - "cuda", - "CUDA", - "Dolfino", - "Egor", - "finetuned", - "flashattention", - "Flashattention", - "friendlykobold", - "geforce", - "ggml", - "gguf", - "GGUF", - "gpulayers", - "hipblas", - "kcpps", - "kcppt", - "koboldai", - "KoboldAI", - "KOBOLDAI", - "koboldcpp", - "KoboldCpp", - "lora", - "lowvram", - "Lowvram", - "maximizable", - "minimizable", - "mmproj", - "mmq", - "multiuser", - "noavx", - "nocertify", - "nocuda", - "noheader", - "nommq", - "noshift", - "nsis", - "nvidia", - "oldpc", - "OLDPC", - "opencl", - "Papi", - "Philippov", - "pkexec", - "PYTHONDONTWRITEBYTECODE", - "PYTHONUNBUFFERED", - "quantmatmul", - "radeon", - "remotetunnel", - "rocm", - "ROCM", - "rocminfo", - "safetensors", - "sdclipg", - "sdclipl", - "sdlora", - "sdmodel", - "sdphotomaker", - "sdui", - "sdvae", - "SDXL", - "sonarjs", - "Tauri", - "togglefullscreen", - "treemap", - "trycloudflare", - "unquantized", - "useclblast", - "usecuda", - "usevulkan", - "vram", - "vulkan", - "vulkaninfo", - "wayland", - "websearch" + "dictionaryDefinitions": [ + { + "name": "project-terms", + "path": "./.cspell/project-terms.txt", + "addWords": true + } + ], + "dictionaries": [ + "typescript", + "node", + "npm", + "html", + "css", + "bash", + "en-gb", + "companies", + "softwareTerms", + "misc", + "project-terms" ], "ignorePaths": [ "node_modules/**", @@ -101,19 +35,8 @@ "coverage/**", ".git/**", ".vscode/**", - "*.map" - ], - "dictionaries": [ - "typescript", - "node", - "npm", - "html", - "css", - "bash", - "en-gb", - "companies", - "softwareTerms", - "misc" + "*.map", + ".cspell/**" ], "languageSettings": [ { diff --git a/src/components/screens/Interface/TerminalTab.tsx b/src/components/screens/Interface/TerminalTab.tsx index f421f1f..173b392 100644 --- a/src/components/screens/Interface/TerminalTab.tsx +++ b/src/components/screens/Interface/TerminalTab.tsx @@ -50,7 +50,6 @@ export const TerminalTab = ({ onServerReady }: TerminalTabProps) => { useEffect(() => { const cleanup = window.electronAPI.kobold.onKoboldOutput((data: string) => { setTerminalContent((prev) => { - const lines = prev.split('\n'); const newData = data.toString(); if ( @@ -66,28 +65,7 @@ export const TerminalTab = ({ onServerReady }: TerminalTabProps) => { } } - if (newData.includes('\r')) { - const parts = newData.split('\r'); - - for (let i = 0; i < parts.length; i++) { - if (i === 0) { - if (lines.length > 0) { - lines[lines.length - 1] += parts[i]; - } else { - lines.push(parts[i]); - } - } else { - if (lines.length > 0) { - lines[lines.length - 1] = parts[i]; - } else { - lines.push(parts[i]); - } - } - } - return lines.join('\n'); - } else { - return prev + newData; - } + return prev + newData; }); }); diff --git a/src/main/managers/KoboldCppManager.ts b/src/main/managers/KoboldCppManager.ts index c78e7aa..de8e7fa 100644 --- a/src/main/managers/KoboldCppManager.ts +++ b/src/main/managers/KoboldCppManager.ts @@ -612,10 +612,9 @@ export class KoboldCppManager { if (!existsSync(versionPath)) { throw new Error('Selected version file does not exist'); } - this.koboldProcess = spawn(versionPath, args, { - stdio: ['ignore', 'pipe', 'pipe'], - shell: process.platform === 'win32', + stdio: ['pipe', 'pipe', 'pipe'], + detached: false, }); if (onOutput) { @@ -939,7 +938,6 @@ export class KoboldCppManager { const child = spawn(currentVersion.path, finalArgs, { stdio: ['pipe', 'pipe', 'pipe'], detached: false, - shell: process.platform === 'win32', }); this.koboldProcess = child; @@ -1057,18 +1055,56 @@ export class KoboldCppManager { this.koboldProcess.once('error', cleanup); try { - this.koboldProcess.kill('SIGTERM'); - - setTimeout(() => { - if (this.koboldProcess && !this.koboldProcess.killed) { + if (process.platform === 'win32') { + const pid = this.koboldProcess.pid; + if (pid) { try { - this.koboldProcess.kill('SIGKILL'); - } catch { - void 0; + this.koboldProcess.kill('SIGTERM'); + + setTimeout(() => { + if (this.koboldProcess && !this.koboldProcess.killed) { + const { exec: execCmd } = require('child_process'); + execCmd( + `taskkill /pid ${pid} /t /f`, + (error: Error | null) => { + if (error) { + this.logManager.logError( + 'Error force-killing process:', + error + ); + } + cleanup(); + } + ); + } else { + cleanup(); + } + }, 2000); + } catch (error) { + this.logManager.logError( + 'Error during Windows cleanup:', + error as Error + ); + cleanup(); } + } else { + cleanup(); } - cleanup(); - }, 3000); + } else { + // Unix-like systems + this.koboldProcess.kill('SIGTERM'); + + setTimeout(() => { + if (this.koboldProcess && !this.koboldProcess.killed) { + try { + this.koboldProcess.kill('SIGKILL'); + } catch { + void 0; + } + } + cleanup(); + }, 3000); + } } catch (error) { this.logManager.logError('Error during cleanup:', error as Error); cleanup();