From 2fe4040dc3aa4e5a61b79642934b0443c7be8826 Mon Sep 17 00:00:00 2001 From: Sportinger Date: Tue, 19 May 2026 15:37:19 +0200 Subject: [PATCH 1/5] release native helper v0.3.15 with bundled yt-dlp --- .github/workflows/native-helper-release.yml | 37 +++++++-- AGENTS.md | 2 + CLAUDE.md | 3 +- README.md | 6 +- docs/Features/Download-Panel.md | 2 +- docs/Features/Native-Helper.md | 18 +++-- index.html | 2 +- src/components/common/NativeHelperStatus.tsx | 5 +- .../common/settings/NativeHelperSettings.tsx | 3 +- src/services/nativeHelper/releases.ts | 2 +- src/version.ts | 2 +- tools/native-helper/Cargo.lock | 2 +- tools/native-helper/Cargo.toml | 2 +- tools/native-helper/README.md | 6 +- tools/native-helper/scripts/build-msi.bat | 79 ++++++++++++++++--- tools/native-helper/src/download/ytdlp.rs | 62 ++++++++++++--- tools/native-helper/wix/main.wxs | 5 ++ 17 files changed, 190 insertions(+), 48 deletions(-) diff --git a/.github/workflows/native-helper-release.yml b/.github/workflows/native-helper-release.yml index eb170f0b..820689f7 100644 --- a/.github/workflows/native-helper-release.yml +++ b/.github/workflows/native-helper-release.yml @@ -4,9 +4,9 @@ on: workflow_dispatch: inputs: version: - description: 'Version tag (e.g. v0.3.12)' + description: 'Version tag (e.g. v0.3.15)' required: true - default: 'v0.3.12' + default: 'v0.3.15' jobs: build: @@ -25,6 +25,10 @@ jobs: target: x86_64-apple-darwin artifact: MasterSelects-NativeHelper-macos-x64 ext: '' + - os: windows-latest + target: x86_64-pc-windows-msvc + artifact: MasterSelects-NativeHelper-windows-x64 + ext: '.msi' runs-on: ${{ matrix.os }} steps: @@ -47,10 +51,24 @@ jobs: brew install llvm pkg-config echo "LIBCLANG_PATH=$(brew --prefix llvm)/lib" >> $GITHUB_ENV + - name: Install Windows dependencies + if: runner.os == 'Windows' + shell: pwsh + run: | + dotnet tool install --global wix + wix extension add WixToolset.UI.wixext + - name: Build + if: runner.os != 'Windows' working-directory: tools/native-helper run: cargo build --release --target ${{ matrix.target }} + - name: Build Windows MSI + if: runner.os == 'Windows' + working-directory: tools/native-helper + shell: cmd + run: scripts\build-msi.bat + - name: Package (Linux) if: runner.os == 'Linux' working-directory: tools/native-helper @@ -69,12 +87,20 @@ jobs: chmod +x release/masterselects-helper cd release && tar czf ../${{ matrix.artifact }}.tar.gz * - - name: Upload artifact + - name: Upload Unix artifact + if: runner.os != 'Windows' uses: actions/upload-artifact@v4 with: name: ${{ matrix.artifact }} path: tools/native-helper/${{ matrix.artifact }}.tar.gz + - name: Upload Windows artifact + if: runner.os == 'Windows' + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.artifact }} + path: tools/native-helper/target/wix/*.msi + release: needs: build runs-on: ubuntu-latest @@ -101,17 +127,18 @@ jobs: - Local AI bridge for external agents ### Downloads - - **Windows x64 (MSI)**: Upload manually from `tools/native-helper/target/wix/*.msi` + - **Windows x64 (MSI)**: `MasterSelects-NativeHelper-${{ github.event.inputs.version }}-windows-x64.msi` - **macOS ARM (Apple Silicon)**: `MasterSelects-NativeHelper-macos-arm64.tar.gz` - **macOS x64 (Intel)**: `MasterSelects-NativeHelper-macos-x64.tar.gz` - **Linux x64**: `MasterSelects-NativeHelper-linux-x64.tar.gz` ### Notes - Keep the helper running while using MasterSelects - - Install [yt-dlp](https://github.com/yt-dlp/yt-dlp) if it is not already available on your system + - Windows MSI builds bundle `yt-dlp.exe`; non-Windows archive installs use a bundled `yt-dlp` when present or a system `yt-dlp` on PATH - Windows MSI is the preferred package for in-place upgrades - FFmpeg is not bundled with the helper packages files: | artifacts/**/*.tar.gz + artifacts/**/*.msi draft: false prerelease: false diff --git a/AGENTS.md b/AGENTS.md index c75659dc..4aca705c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -191,6 +191,8 @@ cd tools/native-helper cargo run --release ``` +Windows-MSI-Builds bundlen `yt-dlp.exe`; Source-Builds und nicht-Windows-Archive nutzen `yt-dlp` neben dem Helper-Binary oder aus `PATH`. + Ports: - WebSocket: `9876` diff --git a/CLAUDE.md b/CLAUDE.md index 39502233..05bad8c0 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -161,11 +161,12 @@ npm run preview # Built output lokal serven ### Native Helper (optional, cross-platform) ```bash -# All platforms (FFmpeg decode/encode + yt-dlp downloads): +# All platforms: cd tools/native-helper && cargo run --release # Windows: requires FFMPEG_DIR + LIBCLANG_PATH env vars (see tools/native-helper/README.md) ``` +Windows-MSI-Builds bundlen `yt-dlp.exe`; Source-Builds und nicht-Windows-Archive nutzen `yt-dlp` neben dem Helper-Binary oder aus `PATH`. Ports: WebSocket `9876`, HTTP `9877` --- diff --git a/README.md b/README.md index cb954ceb..084a7d12 100644 --- a/README.md +++ b/README.md @@ -193,7 +193,7 @@ cargo run --release # WebSocket :9876, HTTP :9877 | **AI Control** | Local HTTP bridge for external agents to steer the running editor | | **Download** | yt-dlp integration for YouTube, TikTok, Instagram, Twitter/X, Vimeo, and other supported sites | -**Platforms:** Windows, Linux, macOS. Building the Native Helper requires Rust. Downloads also require `yt-dlp`. See [Native Helper docs](tools/native-helper/README.md) for platform-specific setup. +**Platforms:** Windows, Linux, macOS. Building the Native Helper requires Rust. The Windows MSI bundles `yt-dlp.exe`; source builds and non-Windows archive installs use `yt-dlp` from the helper folder or PATH. See [Native Helper docs](tools/native-helper/README.md) for platform-specific setup. --- @@ -224,7 +224,7 @@ This is alpha software. Features get added fast, things break. - Multicam AI is experimental - Transitions are experimental - Firefox project storage requires the Native Helper backend -- Video downloads require Native Helper with yt-dlp installed +- Video downloads require Native Helper; the Windows MSI bundles yt-dlp, while source/non-Windows installs need yt-dlp beside the helper or on PATH - Audio waveforms may not display for some video formats - Very long videos (>2 hours) may cause performance issues @@ -239,7 +239,7 @@ If something breaks, refresh. If it's still broken, [open an issue](https://gith - **Video:** WebCodecs, MediaBunny, mp4box, HTMLVideo fallback, and experimental FFmpeg WASM export path - **Audio:** Web Audio API with 10-band live EQ, element-synced playback, drift correction, and waveform extraction - **AI:** Built-in OpenAI/Cloud or local Lemonade editor chat with 79 exported tools, Native Helper HTTP bridge for Claude Code / external agents, Claude/Anthropic for experimental multicam EDLs, SAM2 via ONNX Runtime, MatAnyone2 via Native Helper, local Whisper via Hugging Face Transformers, and Kie.ai / hosted cloud / PiAPI-backed generation flows -- **Native:** Rust helper for Firefox storage backend, native decode/encode, and yt-dlp downloads +- **Native:** Rust helper for Firefox storage backend, native decode/encode, and bundled/system yt-dlp downloads - **Storage:** File System Access API on Chrome, Native Helper backend on Firefox, IndexedDB, local project folders with raw media --- diff --git a/docs/Features/Download-Panel.md b/docs/Features/Download-Panel.md index 602c25fc..2c44a226 100644 --- a/docs/Features/Download-Panel.md +++ b/docs/Features/Download-Panel.md @@ -60,7 +60,7 @@ Any site that `yt-dlp` can fetch can still be downloaded even if it is not liste Downloads require the Native Helper for the actual media transfer. 1. The panel asks the helper for available formats -2. The helper runs `yt-dlp` +2. The helper runs the bundled Windows `yt-dlp.exe` or a system `yt-dlp` 3. Progress callbacks feed percent and transfer speed back into the panel 4. The downloaded file is fetched from the helper 5. If a project is open, the file is written into `Downloads//` diff --git a/docs/Features/Native-Helper.md b/docs/Features/Native-Helper.md index 69c81cc8..1eb37261 100644 --- a/docs/Features/Native-Helper.md +++ b/docs/Features/Native-Helper.md @@ -42,7 +42,7 @@ Browser (MasterSelects App) v Native Helper (Rust) | - | yt-dlp (subprocess) + | bundled or system yt-dlp (subprocess) | File system (direct) | AI tool forwarding | @@ -63,8 +63,9 @@ The helper will automatically be detected by the app. ### Windows 1. Download the latest Windows MSI from the toolbar or [GitHub Releases](https://github.com/Sportinger/MasterSelects/releases/latest) -2. Run the MSI installer, then launch `masterselects-helper.exe` if it does not auto-start -3. Use `--console` flag to run in terminal mode instead of tray mode +2. Run the MSI installer. It installs `yt-dlp.exe` next to `masterselects-helper.exe`, so downloads do not need a separate `pip install yt-dlp` +3. Launch `masterselects-helper.exe` if it does not auto-start +4. Use `--console` flag to run in terminal mode instead of tray mode ### macOS @@ -105,7 +106,7 @@ The toolbar shows the helper status: Click the indicator for details: - Helper version -- yt-dlp availability +- yt-dlp availability (bundled next to the helper or installed on PATH) - Download directory - Project root - File system command support @@ -234,10 +235,11 @@ cargo build --release ### Downloads not working -1. Check yt-dlp is installed and available on PATH -2. Run `yt-dlp --version` to verify -3. Check helper log output for errors -4. If YouTube reports bot or sign-in blocking, close Chrome completely and retry so yt-dlp can read cookies +1. On Windows, reinstall or update the helper MSI so the bundled `yt-dlp.exe` is present in the install folder +2. For source builds and non-Windows archive installs, check that `yt-dlp` is installed on PATH or placed next to the helper binary +3. Run `yt-dlp --version` or `\yt-dlp.exe --version` to verify +4. Check helper log output for errors +5. If YouTube reports bot or sign-in blocking, close Chrome completely and retry so yt-dlp can read cookies ### Connection errors diff --git a/index.html b/index.html index 0d95c75c..9d41d794 100644 --- a/index.html +++ b/index.html @@ -113,7 +113,7 @@ - Times are always in seconds (float) - The app requires WebGPU — works in Chrome/Edge 113+ - Native Helper (optional): WebSocket on port 9876, HTTP on port 9877 - Needed for: YouTube downloads, yt-dlp, FFmpeg encode/decode + Needed for: YouTube downloads via bundled/system yt-dlp, FFmpeg encode/decode ============================================================ --> diff --git a/src/components/common/NativeHelperStatus.tsx b/src/components/common/NativeHelperStatus.tsx index 13781eb5..b14b109f 100644 --- a/src/components/common/NativeHelperStatus.tsx +++ b/src/components/common/NativeHelperStatus.tsx @@ -64,10 +64,11 @@ function getInstallGuide(platform: Platform): InstallGuide { title: 'How to install on Windows', steps: [ 'Open the GitHub releases page and download the newest published MSI.', - 'Run the installer and keep the helper running in the system tray.', + 'Run the installer. It includes yt-dlp for downloads.', + 'Keep the helper running in the system tray.', 'Return to MasterSelects and press Check connection.', ], - note: 'The current helper release includes downloads, Firefox project save/open, and the local AI bridge.', + note: 'The Windows MSI installs the helper and yt-dlp together, so no separate pip or winget step is needed for downloads.', }; case 'mac': return { diff --git a/src/components/common/settings/NativeHelperSettings.tsx b/src/components/common/settings/NativeHelperSettings.tsx index eb4b7de0..346cc268 100644 --- a/src/components/common/settings/NativeHelperSettings.tsx +++ b/src/components/common/settings/NativeHelperSettings.tsx @@ -36,7 +36,8 @@ function getInstallSteps(platform: Platform): { steps: string[]; command?: strin return { steps: [ 'Download the newest MSI from GitHub releases.', - 'Run the installer and keep the helper running in the system tray.', + 'Run the installer. It includes yt-dlp for downloads.', + 'Keep the helper running in the system tray.', 'Return here and press Check connection.', ], }; diff --git a/src/services/nativeHelper/releases.ts b/src/services/nativeHelper/releases.ts index 5f1c79b7..9b63ea32 100644 --- a/src/services/nativeHelper/releases.ts +++ b/src/services/nativeHelper/releases.ts @@ -1,4 +1,4 @@ -export const NATIVE_HELPER_TARGET_VERSION = '0.3.14'; +export const NATIVE_HELPER_TARGET_VERSION = '0.3.15'; export const NATIVE_HELPER_RELEASES_URL = 'https://github.com/Sportinger/MasterSelects/releases'; const GITHUB_RELEASES_API_URL = 'https://api.github.com/repos/Sportinger/MasterSelects/releases?per_page=20'; diff --git a/src/version.ts b/src/version.ts index d50ed4be..d25e3f23 100644 --- a/src/version.ts +++ b/src/version.ts @@ -363,7 +363,7 @@ export function getChangelogCalendar( // Known issues and bugs - shown in What's New dialog // Remove items when fixed export const KNOWN_ISSUES: string[] = [ - 'YouTube download requires Native Helper with yt-dlp installed', + 'Non-Windows/source Native Helper builds require yt-dlp beside the helper or on PATH', 'Audio waveforms may not display for some video formats', 'Very long videos (>2 hours) may cause performance issues', ]; diff --git a/tools/native-helper/Cargo.lock b/tools/native-helper/Cargo.lock index ae908198..e27d7742 100644 --- a/tools/native-helper/Cargo.lock +++ b/tools/native-helper/Cargo.lock @@ -1497,7 +1497,7 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "masterselects-helper" -version = "0.3.14" +version = "0.3.15" dependencies = [ "anyhow", "base64 0.22.1", diff --git a/tools/native-helper/Cargo.toml b/tools/native-helper/Cargo.toml index 81e8aae6..75470986 100644 --- a/tools/native-helper/Cargo.toml +++ b/tools/native-helper/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "masterselects-helper" -version = "0.3.14" +version = "0.3.15" edition = "2021" authors = ["MasterSelects Team"] description = "Local control, storage, and download helper for MasterSelects" diff --git a/tools/native-helper/README.md b/tools/native-helper/README.md index f0d64dc2..440f5a16 100644 --- a/tools/native-helper/README.md +++ b/tools/native-helper/README.md @@ -30,11 +30,15 @@ cargo build --release cmd /c scripts\build-msi.bat ``` +`scripts\build-msi.bat` downloads the official `yt-dlp.exe` release binary into `target\release` and bundles it into the MSI next to `masterselects-helper.exe`. Installed Windows helpers therefore do not require a separate `pip install yt-dlp` or system PATH setup for downloads. + ### Linux / macOS ```bash cargo build --release ``` +Source builds and archive packages look for `yt-dlp` next to the helper binary first, then fall back to `yt-dlp` on `PATH`. + ## Running ```bash @@ -49,7 +53,7 @@ WebSocket (JSON commands) on port 9876, HTTP server on port 9877. | Command | Description | |---------|-------------| | `ping` | Connection keepalive | -| `info` | System info (helper features, yt-dlp status, project root, AI bridge status) | +| `info` | System info (helper features, bundled/system yt-dlp status, project root, AI bridge status) | | `register_client` | Register the running MasterSelects editor session with the helper | | `ai_tool_result` | Return the result of a forwarded AI tool request | | `list_formats` | List available download formats for a URL | diff --git a/tools/native-helper/scripts/build-msi.bat b/tools/native-helper/scripts/build-msi.bat index b3735e1f..fe96a003 100644 --- a/tools/native-helper/scripts/build-msi.bat +++ b/tools/native-helper/scripts/build-msi.bat @@ -3,8 +3,11 @@ REM ============================================================ REM Build MSI installer for MasterSelects Native Helper REM REM Prerequisites: -REM - WiX Toolset v3: winget install WiXToolset.WiXToolset -REM - cargo-wix: cargo install cargo-wix +REM - WiX Toolset v6 dotnet tool, or cargo-wix: +REM dotnet tool install --global wix +REM wix extension add WixToolset.UI.wixext +REM Optional legacy path: +REM cargo install cargo-wix REM ============================================================ setlocal enabledelayedexpansion @@ -12,14 +15,23 @@ setlocal enabledelayedexpansion set "PROJECT_DIR=%~dp0.." cd /d "%PROJECT_DIR%" +for /f "tokens=3 delims= " %%v in ('findstr /b /c:"version = " Cargo.toml') do ( + if not defined HELPER_VERSION set "HELPER_VERSION=%%~v" +) +if "%HELPER_VERSION%"=="" ( + echo ERROR: Could not read helper version from Cargo.toml + exit /b 1 +) + echo. echo ======================================== echo MasterSelects Helper - MSI Build +echo Version: %HELPER_VERSION% echo ======================================== echo. REM --- Step 1: Build release binary --- -echo [1/3] Building release binary... +echo [1/4] Building release binary... cargo build --release if errorlevel 1 ( echo ERROR: cargo build failed! @@ -27,22 +39,69 @@ if errorlevel 1 ( ) echo OK -REM --- Step 2: Verify release payload --- -echo [2/2] Verifying release payload... +REM --- Step 2: Download bundled yt-dlp --- set "RELEASE_DIR=target\release" +set "YTDLP_EXE=%RELEASE_DIR%\yt-dlp.exe" +set "YTDLP_URL=https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe" +echo [2/4] Preparing bundled yt-dlp... +if not exist "%YTDLP_EXE%" ( + echo Downloading %YTDLP_URL% + powershell -NoProfile -ExecutionPolicy Bypass -Command "$ErrorActionPreference='Stop'; $ProgressPreference='SilentlyContinue'; [Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -Uri '%YTDLP_URL%' -OutFile '%YTDLP_EXE%'" + if errorlevel 1 ( + echo ERROR: Failed to download yt-dlp.exe + exit /b 1 + ) +) else ( + echo Reusing existing %YTDLP_EXE% +) + +"%YTDLP_EXE%" --version >nul 2>nul +if errorlevel 1 ( + echo ERROR: Bundled yt-dlp.exe is not executable: %YTDLP_EXE% + exit /b 1 +) +echo OK + +REM --- Step 3: Verify release payload --- +echo [3/4] Verifying release payload... if not exist "%RELEASE_DIR%\masterselects-helper.exe" ( echo ERROR: Missing release binary: %RELEASE_DIR%\masterselects-helper.exe exit /b 1 ) +if not exist "%YTDLP_EXE%" ( + echo ERROR: Missing bundled dependency: %YTDLP_EXE% + exit /b 1 +) echo OK REM --- Build MSI --- -echo Building MSI installer... -cargo wix --no-build --nocapture -if errorlevel 1 ( - echo ERROR: cargo wix failed! - exit /b 1 +echo [4/4] Building MSI installer... +if not exist "target\wix" mkdir "target\wix" + +cargo wix --version >nul 2>nul +if not errorlevel 1 ( + echo Building MSI installer with cargo-wix... + cargo wix --no-build --nocapture + if errorlevel 1 ( + echo ERROR: cargo wix failed! + exit /b 1 + ) +) else ( + where wix >nul 2>nul + if errorlevel 1 ( + echo ERROR: Neither cargo-wix nor wix.exe was found. + echo Install WiX with: dotnet tool install --global wix + echo Then install UI extension: wix extension add WixToolset.UI.wixext + exit /b 1 + ) + + echo Building MSI installer with WiX Toolset... + wix build wix\main.wxs -ext WixToolset.UI.wixext -d Version=%HELPER_VERSION% -arch x64 -out target\wix\MasterSelects-NativeHelper-v%HELPER_VERSION%-windows-x64.msi + if errorlevel 1 ( + echo ERROR: wix build failed! + exit /b 1 + ) ) echo. diff --git a/tools/native-helper/src/download/ytdlp.rs b/tools/native-helper/src/download/ytdlp.rs index 999c47f0..38f3792c 100644 --- a/tools/native-helper/src/download/ytdlp.rs +++ b/tools/native-helper/src/download/ytdlp.rs @@ -5,7 +5,7 @@ //! Auto-retries with browser cookies when YouTube bot detection triggers. use std::collections::HashMap; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::sync::Arc; use futures_util::SinkExt; @@ -18,6 +18,9 @@ use tracing::{info, warn}; use crate::protocol::{error_codes, Response}; use crate::utils; +const YTDLP_NOT_FOUND_MESSAGE: &str = + "yt-dlp not found. Install or update the Native Helper MSI, or install yt-dlp on PATH."; + /// Type for sending WebSocket messages (for progress streaming) pub type WsSender = Arc, >>; -/// Find yt-dlp executable, checking common install locations +fn executable_works(path: &Path) -> bool { + if !path.exists() || !path.is_file() { + return false; + } + + crate::utils::no_window_std(std::process::Command::new(path).arg("--version")) + .output() + .map(|output| output.status.success()) + .unwrap_or(false) +} + +fn command_works(command: &str) -> bool { + crate::utils::no_window_std(std::process::Command::new(command).arg("--version")) + .output() + .map(|output| output.status.success()) + .unwrap_or(false) +} + +/// Find yt-dlp executable, checking the helper install folder before PATH. pub fn find_ytdlp() -> Option { - // First check if yt-dlp is in PATH - if let Ok(output) = crate::utils::no_window_std(std::process::Command::new("yt-dlp").arg("--version")).output() { - if output.status.success() { - return Some(PathBuf::from("yt-dlp")); + // Packaged helper builds can ship yt-dlp next to the helper executable. + if let Ok(exe_path) = std::env::current_exe() { + if let Some(exe_dir) = exe_path.parent() { + #[cfg(windows)] + { + let bundled = exe_dir.join("yt-dlp.exe"); + if executable_works(&bundled) { + return Some(bundled); + } + } + + #[cfg(not(windows))] + { + let bundled = exe_dir.join("yt-dlp"); + if executable_works(&bundled) { + return Some(bundled); + } + } } } + // Then check if yt-dlp is in PATH, which keeps local development flexible. + if command_works("yt-dlp") { + return Some(PathBuf::from("yt-dlp")); + } + // On Windows, check common Python user install locations #[cfg(windows)] { @@ -43,7 +83,7 @@ pub fn find_ytdlp() -> Option { if let Ok(entries) = std::fs::read_dir(appdata_path.join("Python")) { for entry in entries.flatten() { let scripts = entry.path().join("Scripts").join("yt-dlp.exe"); - if scripts.exists() { + if executable_works(&scripts) { return Some(scripts); } } @@ -56,7 +96,7 @@ pub fn find_ytdlp() -> Option { if let Ok(entries) = std::fs::read_dir(local_path.join("Programs").join("Python")) { for entry in entries.flatten() { let scripts = entry.path().join("Scripts").join("yt-dlp.exe"); - if scripts.exists() { + if executable_works(&scripts) { return Some(scripts); } } @@ -181,7 +221,7 @@ pub async fn handle_list_formats(id: &str, url: &str) -> Response { return Response::error(id, error_codes::DOWNLOAD_FAILED, error_msg); } Err(e) if e.kind() == std::io::ErrorKind::NotFound => { - return Response::error(id, error_codes::YTDLP_NOT_FOUND, "yt-dlp not found. Install with: pip install yt-dlp"); + return Response::error(id, error_codes::YTDLP_NOT_FOUND, YTDLP_NOT_FOUND_MESSAGE); } Err(e) => return Response::error(id, error_codes::DOWNLOAD_FAILED, e.to_string()), } @@ -360,7 +400,7 @@ async fn run_download( Ok(c) => c, Err(e) if e.kind() == std::io::ErrorKind::NotFound => { return DownloadResult::Failed( - Response::error(id, error_codes::YTDLP_NOT_FOUND, "yt-dlp not found. Install with: pip install yt-dlp") + Response::error(id, error_codes::YTDLP_NOT_FOUND, YTDLP_NOT_FOUND_MESSAGE) ); } Err(e) => { @@ -522,7 +562,7 @@ async fn run_download( } Err(e) if e.kind() == std::io::ErrorKind::NotFound => { DownloadResult::Failed( - Response::error(id, error_codes::YTDLP_NOT_FOUND, "yt-dlp not found. Install with: pip install yt-dlp") + Response::error(id, error_codes::YTDLP_NOT_FOUND, YTDLP_NOT_FOUND_MESSAGE) ) } Err(e) => { diff --git a/tools/native-helper/wix/main.wxs b/tools/native-helper/wix/main.wxs index 9083ab0d..eab9ec09 100644 --- a/tools/native-helper/wix/main.wxs +++ b/tools/native-helper/wix/main.wxs @@ -10,6 +10,7 @@ + @@ -54,6 +55,10 @@ + + + + From 39d970965047ff859815f78fc7f9d2dae32f7bc1 Mon Sep 17 00:00:00 2001 From: Sportinger Date: Tue, 19 May 2026 15:42:19 +0200 Subject: [PATCH 2/5] ci: pin WiX 6 for native helper release --- .github/workflows/native-helper-release.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/native-helper-release.yml b/.github/workflows/native-helper-release.yml index 820689f7..c5b35688 100644 --- a/.github/workflows/native-helper-release.yml +++ b/.github/workflows/native-helper-release.yml @@ -11,6 +11,7 @@ on: jobs: build: strategy: + fail-fast: false matrix: include: - os: ubuntu-latest @@ -55,7 +56,7 @@ jobs: if: runner.os == 'Windows' shell: pwsh run: | - dotnet tool install --global wix + dotnet tool install --global wix --version 6.0.2 wix extension add WixToolset.UI.wixext - name: Build From 18bc507e75b5bb0361a91256dc285b3458f9c58c Mon Sep 17 00:00:00 2001 From: Sportinger Date: Tue, 19 May 2026 16:03:06 +0200 Subject: [PATCH 3/5] ci: allow native helper release asset replacement --- .github/workflows/native-helper-release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/native-helper-release.yml b/.github/workflows/native-helper-release.yml index c5b35688..a64e8304 100644 --- a/.github/workflows/native-helper-release.yml +++ b/.github/workflows/native-helper-release.yml @@ -141,5 +141,6 @@ jobs: files: | artifacts/**/*.tar.gz artifacts/**/*.msi + overwrite_files: true draft: false prerelease: false From a2e98bbdcc5b1f33c36c3b5b59b9c8a27a2a4917 Mon Sep 17 00:00:00 2001 From: Sportinger Date: Tue, 19 May 2026 16:08:01 +0200 Subject: [PATCH 4/5] ci: fix native helper release dependencies --- .github/workflows/native-helper-release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/native-helper-release.yml b/.github/workflows/native-helper-release.yml index a64e8304..918e43f1 100644 --- a/.github/workflows/native-helper-release.yml +++ b/.github/workflows/native-helper-release.yml @@ -44,7 +44,7 @@ jobs: if: runner.os == 'Linux' run: | sudo apt-get update - sudo apt-get install -y clang pkg-config + sudo apt-get install -y clang pkg-config libwayland-dev libxkbcommon-dev - name: Install macOS dependencies if: runner.os == 'macOS' @@ -57,7 +57,7 @@ jobs: shell: pwsh run: | dotnet tool install --global wix --version 6.0.2 - wix extension add WixToolset.UI.wixext + wix extension add WixToolset.UI.wixext/6.0.2 - name: Build if: runner.os != 'Windows' From fc60515197316808339074bad774cb238cafa094 Mon Sep 17 00:00:00 2001 From: Sportinger Date: Tue, 19 May 2026 16:19:15 +0200 Subject: [PATCH 5/5] ci: use current macOS Intel runner for helper release --- .github/workflows/native-helper-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/native-helper-release.yml b/.github/workflows/native-helper-release.yml index 918e43f1..0627550a 100644 --- a/.github/workflows/native-helper-release.yml +++ b/.github/workflows/native-helper-release.yml @@ -22,7 +22,7 @@ jobs: target: aarch64-apple-darwin artifact: MasterSelects-NativeHelper-macos-arm64 ext: '' - - os: macos-13 + - os: macos-15-intel target: x86_64-apple-darwin artifact: MasterSelects-NativeHelper-macos-x64 ext: ''