Files
voicebox/web/src/platform/lifecycle.ts
T
James Pine 2867421550 feat: CUDA backend swap via binary download and restart
Add the ability to download a CUDA-enabled backend binary (~2.4 GB) and
swap it in via a backend-only restart, solving the #1 user pain point
(19 open 'GPU not detected' issues caused by GitHub's 2 GB asset limit).

Backend:
- cuda_download.py: download from R2 (primary) or GitHub split-parts
  (fallback), SHA-256 verification, atomic writes, progress via SSE
- 4 new endpoints: GET/POST/DELETE /backend/cuda-*, GET cuda-progress
- server.py: --version flag, auto-detect variant from binary name
- build_binary.py: --cuda flag for CUDA PyInstaller builds
- split_binary.py: split large binaries into <2GB GitHub Release assets
- CI workflow for building CUDA binary

Tauri:
- restart_server command (stop -> wait -> start)
- start_server prefers CUDA binary from {data_dir}/backends/ if present
- Version mismatch check: runs --version before launching CUDA binary

Frontend:
- GpuAcceleration component: download, progress, restart, switch, delete
- API client + types for CUDA status and management
- Platform lifecycle: restartServer() on Tauri/Web
- Aggressive 1s health polling during restart for fast reconnection
2026-03-13 00:04:12 -07:00

33 lines
968 B
TypeScript

import type { PlatformLifecycle } from '@/platform/types';
class WebLifecycle implements PlatformLifecycle {
onServerReady?: () => void;
async startServer(_remote = false): Promise<string> {
// Web assumes server is running externally
// Return a default URL - this should be configured via env vars
const serverUrl = import.meta.env.VITE_SERVER_URL || 'http://localhost:17493';
this.onServerReady?.();
return serverUrl;
}
async stopServer(): Promise<void> {
// No-op for web - server is managed externally
}
async restartServer(): Promise<string> {
// No-op for web - server is managed externally
return import.meta.env.VITE_SERVER_URL || 'http://localhost:17493';
}
async setKeepServerRunning(_keep: boolean): Promise<void> {
// No-op for web
}
async setupWindowCloseHandler(): Promise<void> {
// No-op for web - no window close handling needed
}
}
export const webLifecycle = new WebLifecycle();