From 8f6e1108cc4ea0181f972713e20579cc34af03d0 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 22 Mar 2026 05:55:49 -0700 Subject: [PATCH] Enable CUDA for Windows/Linux builds + clean up old sidecars MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Windows and Linux sidecar builds now use --with-cuda for GPU acceleration (macOS stays CPU-only — Apple Silicon uses Metal, not CUDA) - Windows upload switched from --data-binary to -T streaming for 2GB+ files - Add cleanup_old_sidecars() that removes stale sidecar-* directories on startup, keeping only the current version - Add NSIS uninstall hook to remove sidecar data dir on Windows uninstall (user data in ~/.voicetonotes is preserved) Co-Authored-By: Claude Opus 4.6 --- .gitea/workflows/release.yml | 6 ++--- src-tauri/nsis-hooks.nsh | 11 +++++++++ src-tauri/src/sidecar/mod.rs | 47 +++++++++++++++++++++++++++++++++--- src-tauri/tauri.conf.json | 3 +++ 4 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 src-tauri/nsis-hooks.nsh diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 67cfb2b..51a4606 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -114,7 +114,7 @@ jobs: - name: Build sidecar working-directory: python - run: uv run --python ${{ env.PYTHON_VERSION }} python build_sidecar.py --cpu-only + run: uv run --python ${{ env.PYTHON_VERSION }} python build_sidecar.py --with-cuda - name: Package sidecar for Tauri run: | @@ -217,7 +217,7 @@ jobs: - name: Build sidecar shell: powershell working-directory: python - run: uv run --python ${{ env.PYTHON_VERSION }} python build_sidecar.py --cpu-only + run: uv run --python ${{ env.PYTHON_VERSION }} python build_sidecar.py --with-cuda - name: Package sidecar for Tauri shell: powershell @@ -286,7 +286,7 @@ jobs: -X POST ` -H "Authorization: token $env:BUILD_TOKEN" ` -H "Content-Type: application/octet-stream" ` - --data-binary "@$($_.FullName)" ` + -T "$($_.FullName)" ` "$uploadUrl" 2>&1 if ($LASTEXITCODE -eq 0) { Write-Host "Upload successful: ${filename}" diff --git a/src-tauri/nsis-hooks.nsh b/src-tauri/nsis-hooks.nsh new file mode 100644 index 0000000..78b3e95 --- /dev/null +++ b/src-tauri/nsis-hooks.nsh @@ -0,0 +1,11 @@ +; NSIS uninstall hook for Voice to Notes +; Removes the sidecar data directory (extracted sidecar binaries + logs) +; but preserves user data in $PROFILE\.voicetonotes (database, settings, models) + +!macro NSIS_HOOK_POSTUNINSTALL + ; Remove the Tauri app_local_data_dir which contains: + ; - Extracted sidecar directories (voice-to-notes-sidecar/) + ; - sidecar.log + ; Path: %LOCALAPPDATA%\com.voicetonotes.app + RMDir /r "$LOCALAPPDATA\com.voicetonotes.app" +!macroend diff --git a/src-tauri/src/sidecar/mod.rs b/src-tauri/src/sidecar/mod.rs index 8840b1f..b3d4d19 100644 --- a/src-tauri/src/sidecar/mod.rs +++ b/src-tauri/src/sidecar/mod.rs @@ -68,15 +68,15 @@ impl SidecarManager { }; // Versioned extraction directory prevents stale sidecar after app updates - let extract_dir = DATA_DIR - .get() - .ok_or("App data directory not initialized")? - .join(format!("sidecar-{}", env!("CARGO_PKG_VERSION"))); + let data_dir = DATA_DIR.get().ok_or("App data directory not initialized")?; + let current_version = env!("CARGO_PKG_VERSION"); + let extract_dir = data_dir.join(format!("sidecar-{}", current_version)); let binary_path = extract_dir.join(binary_name); // Already extracted — use it directly if binary_path.exists() { + Self::cleanup_old_sidecars(data_dir, current_version); return Ok(binary_path); } @@ -102,6 +102,7 @@ impl SidecarManager { } } + Self::cleanup_old_sidecars(data_dir, current_version); Ok(binary_path) } @@ -182,6 +183,44 @@ impl SidecarManager { Ok(()) } + /// Remove old sidecar-* directories that don't match the current version. + /// Called after the current version's sidecar is confirmed ready. + fn cleanup_old_sidecars(data_dir: &Path, current_version: &str) { + let current_dir_name = format!("sidecar-{}", current_version); + + let entries = match std::fs::read_dir(data_dir) { + Ok(entries) => entries, + Err(e) => { + eprintln!("[sidecar-rs] Cannot read data dir for cleanup: {e}"); + return; + } + }; + + for entry in entries.flatten() { + let name = entry.file_name(); + let name_str = name.to_string_lossy(); + + if !name_str.starts_with("sidecar-") { + continue; + } + if *name_str == current_dir_name { + continue; + } + if entry.path().is_dir() { + eprintln!( + "[sidecar-rs] Removing old sidecar: {}", + entry.path().display() + ); + if let Err(e) = std::fs::remove_dir_all(entry.path()) { + eprintln!( + "[sidecar-rs] Failed to remove {}: {e}", + entry.path().display() + ); + } + } + } + } + /// Find a working Python command for the current platform. fn find_python_command() -> &'static str { if cfg!(target_os = "windows") { diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 3c3ee69..37f2891 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -51,6 +51,9 @@ } }, "windows": { + "nsis": { + "installerHooks": "nsis-hooks.nsh" + }, "wix": { "language": "en-US" }