From c202d1b8288cbf46b3551b9119d620327ae9563a Mon Sep 17 00:00:00 2001 From: dhananjaypai08 Date: Mon, 10 Aug 2026 02:14:45 +0530 Subject: [PATCH 1/3] fix(setup): pin dev venv to Python 3.12 --- CHANGELOG.md | 19 +++ CONTRIBUTING.md | 12 +- README.md | 2 +- backend/pyproject.toml | 7 +- docs/content/docs/developer/architecture.mdx | 2 +- docs/content/docs/developer/setup.mdx | 13 +- .../content/docs/overview/troubleshooting.mdx | 12 +- justfile | 112 +++++++++++++++--- 8 files changed, 147 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b03f5e46..ac7957374 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,25 @@ ## [Unreleased] +### Developer Experience + +- **`just setup` now pins the Python venv to 3.12.** Setup preferred `python3.12` when + it found one but silently fell back to 3.13 or bare `python3`, so a machine on + 3.13/3.14 built a venv that then failed to install dependencies capped below 3.13 + (kokoro, misaki, numpy, numba) with `Could not find a version that satisfies the + requirement`. Setup now requires 3.12, and recreates a venv that is on the wrong + version or whose pip doesn't run, so a stale or half-built one heals on the next + `just setup` rather than needing a manual `rm -rf backend/venv`. Reporting 3.12 + isn't enough for an interpreter to be chosen — it has to actually build a working + venv, so setup falls through to the next candidate when one can't (Debian packages + `ensurepip` separately as `python3.12-venv`; current Homebrew `python@3.12` bottles + carry a `pyexpat` that won't load on macOS 26). If none work it exits with the + install command for your platform instead of failing deep inside pip. Windows + resolves it through the `py -3.12` launcher, since Windows installers don't create + a `python3.12` command. +- **The 3.12 requirement is now machine-readable.** `backend/pyproject.toml` + declares `requires-python = ">=3.12,<3.13"` rather than an open-ended `>=3.12`, + so the constraint the docs describe is the one tooling resolves against. ### Linux - **ROCm setup works on Linux AMD systems.** Docker ROCm builds now keep PyTorch diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9b300704f..513a1a90e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,9 +18,11 @@ Thank you for your interest in contributing to Voicebox! This document provides curl -fsSL https://bun.sh/install | bash ``` -- **[Python 3.11+](https://python.org)** - For backend development +- **[Python 3.12](https://python.org)** - For backend development. Voicebox pins its + virtual environment to 3.12 to match CI, because some dependencies have no 3.13 + release yet. On Debian/Ubuntu also install `python3.12-venv`. ```bash - python --version # Should be 3.11 or higher + python3.12 --version # Should be 3.12.x ``` - **[Rust](https://rustup.rs)** - For Tauri desktop app (installed automatically by Tauri CLI) @@ -44,7 +46,7 @@ just dev # starts backend + desktop app ``` `just setup` handles everything automatically, including: -- Creating a Python virtual environment +- Creating a Python virtual environment pinned to 3.12 (recreating it if an existing venv is on the wrong version) - Installing Python dependencies (with CUDA PyTorch on Windows if an NVIDIA GPU is detected) - Installing MLX dependencies on Apple Silicon - Installing JavaScript dependencies @@ -67,7 +69,7 @@ just --list # see all available commands #### Windows Notes -The justfile works natively on Windows via PowerShell. No WSL or Git Bash required. On Windows with an NVIDIA GPU, `just setup` automatically installs CUDA-enabled PyTorch for GPU acceleration. +The justfile works natively on Windows via PowerShell. No WSL or Git Bash required. On Windows with an NVIDIA GPU, `just setup` automatically installs CUDA-enabled PyTorch for GPU acceleration. Python 3.12 is located via the `py -3.12` launcher; install it with `winget install -e --id Python.Python.3.12` if it's missing. ### Model Downloads @@ -363,7 +365,7 @@ See [docs/content/docs/overview/troubleshooting.mdx](docs/content/docs/overview/ **Quick fixes:** -- **Backend won't start:** Check Python version (3.11+), ensure venv is activated, install dependencies +- **Backend won't start:** Check Python version (must be 3.12), ensure venv is activated, install dependencies - **Tauri build fails:** Ensure Rust is installed, clean build with `cd tauri/src-tauri && cargo clean` - **OpenAPI client generation fails:** Ensure backend is running, check `curl http://localhost:17493/openapi.json` diff --git a/README.md b/README.md index b1ee81fc5..18a1d2a14 100644 --- a/README.md +++ b/README.md @@ -417,7 +417,7 @@ just dev # starts backend + desktop app Install [just](https://github.com/casey/just): `brew install just` or `cargo install just`. Run `just --list` to see all commands. -**Prerequisites:** [Bun](https://bun.sh), [Rust](https://rustup.rs), [Python 3.11+](https://python.org), [Tauri Prerequisites](https://v2.tauri.app/start/prerequisites/), and [Xcode](https://developer.apple.com/xcode/) on macOS. +**Prerequisites:** [Bun](https://bun.sh), [Rust](https://rustup.rs), [Python 3.12](https://python.org), [Tauri Prerequisites](https://v2.tauri.app/start/prerequisites/), and [Xcode](https://developer.apple.com/xcode/) on macOS. The repo ships a pre-wired `.mcp.json` at the root — running Claude Code inside this checkout picks up the Voicebox MCP tools automatically once the dev app is running. diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 7476bf894..ea1c125cc 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -1,7 +1,12 @@ [project] name = "voicebox-backend" version = "0.2.3" -requires-python = ">=3.12" +# This is the one place the Python pin is explained; the justfile and docs point here +# rather than restating it. The upper bound is real, not defensive: requirements.txt +# currently pulls in kokoro and misaki (which declare requires-python <3.13) plus +# numpy<2 and numba<0.61 (no 3.13 wheels), so `pip install -r requirements.txt` fails +# outright on a later interpreter. Recheck those four before raising it. +requires-python = ">=3.12,<3.13" # --------------------------------------------------------------------------- # Ruff – linter + formatter diff --git a/docs/content/docs/developer/architecture.mdx b/docs/content/docs/developer/architecture.mdx index dda492f55..c46fe2250 100644 --- a/docs/content/docs/developer/architecture.mdx +++ b/docs/content/docs/developer/architecture.mdx @@ -48,7 +48,7 @@ These two layers communicate via HTTP on `localhost:17493`, with the frontend ma ### Tech Stack -- **Framework**: FastAPI (Python 3.11+) +- **Framework**: FastAPI (Python 3.12) - **TTS Engines**: Qwen3-TTS, Qwen CustomVoice, LuxTTS, Chatterbox, Chatterbox Turbo, TADA, Kokoro - **Transcription**: Whisper (PyTorch or MLX-Whisper) - **Inference Backends**: MLX (Apple Silicon), PyTorch (CUDA / ROCm / XPU / DirectML / CPU) diff --git a/docs/content/docs/developer/setup.mdx b/docs/content/docs/developer/setup.mdx index 975eb6f14..58c79c42f 100644 --- a/docs/content/docs/developer/setup.mdx +++ b/docs/content/docs/developer/setup.mdx @@ -32,11 +32,12 @@ Ensure you have these installed: curl -fsSL https://bun.sh/install | bash ``` - }> + }> [Download Python](https://python.org) ```bash - python --version + python3.12 --version # Should be 3.12.x ``` + Voicebox pins its venv to 3.12 to match CI, because some dependencies have no 3.13 release yet. On Debian/Ubuntu also install `python3.12-venv`. }> [Install Rust](https://rustup.rs) @@ -65,7 +66,7 @@ Run `just --list` to see all available commands. Highlights: | Command | Description | |---------|-------------| -| `just setup` | Full setup (Python venv + JS deps + dev sidecar). Detects Apple Silicon for MLX and NVIDIA/Intel Arc on Windows for accelerated PyTorch. | +| `just setup` | Full setup (Python venv + JS deps + dev sidecar). Pins the venv to Python 3.12 (recreating a wrong-version one) and detects Apple Silicon for MLX and NVIDIA/Intel Arc on Windows for accelerated PyTorch. | | `just setup-python` | Python venv + dependencies only | | `just setup-js` | `bun install` only | @@ -214,8 +215,8 @@ This installs dependencies for: ```bash cd backend -# Create virtual environment -python -m venv venv +# Create virtual environment (use Python 3.12 — see Prerequisites) +python3.12 -m venv venv # Activate virtual environment source venv/bin/activate # macOS/Linux @@ -277,7 +278,7 @@ bun run tauri dev - - Check Python version (must be 3.11+) + - Check Python version (must be 3.12) - Ensure virtual environment is activated: `source backend/venv/bin/activate` - Verify all dependencies are installed: `pip install -r requirements.txt` - Check if port 17493 is available diff --git a/docs/content/docs/overview/troubleshooting.mdx b/docs/content/docs/overview/troubleshooting.mdx index f615b3c69..5c2f26ee0 100644 --- a/docs/content/docs/overview/troubleshooting.mdx +++ b/docs/content/docs/overview/troubleshooting.mdx @@ -292,13 +292,19 @@ This is expected behavior. The first generation downloads the selected TTS engin - Ensure Python 3.11 or higher: + Ensure Python 3.12: ```bash - python --version + python3.12 --version ``` - If not, install Python 3.11+ and recreate the virtual environment. + Voicebox pins its venv to Python 3.12 because some dependencies have no 3.13 + release yet. `just setup` recreates a venv that was built on the wrong version, + so re-running it is usually the fix. + + If `just setup` can't find a usable 3.12, install one: `uv python install 3.12` + works anywhere, or use `brew install python@3.12` on macOS and `sudo apt install + python3.12 python3.12-venv` on Debian/Ubuntu. diff --git a/justfile b/justfile index 877f15196..99eedda84 100644 --- a/justfile +++ b/justfile @@ -17,8 +17,11 @@ pip := if os() == "windows" { venv_bin / "pip.exe" } else { venv_bin / "pip" } # Shell selection: use powershell on Windows, bash elsewhere set windows-shell := ["powershell", "-NoProfile", "-Command"] -# Detect best python for venv creation (platform-aware) -system_python := if os() == "windows" { "python" } else { `command -v python3.12 2>/dev/null || command -v python3.13 2>/dev/null || echo python3` } +# Pin the venv to one version instead of following whatever `python3` happens to be; +# a newer interpreter fails `pip install` with "no matching distribution". See +# requires-python in backend/pyproject.toml for which dependencies set the ceiling. +# Keep in sync with that and with actions/setup-python in .github/workflows. +python_version := "3.12" # ─── Setup ──────────────────────────────────────────────────────────── @@ -32,14 +35,66 @@ setup: setup-python setup-js setup-python: #!/usr/bin/env bash set -euo pipefail - if [ ! -d "{{ venv }}" ]; then - echo "Creating Python virtual environment..." - PY_MINOR=$({{ system_python }} -c "import sys; print(sys.version_info[1])") - if [ "$PY_MINOR" -gt 13 ]; then - echo "Warning: Python 3.$PY_MINOR detected. ML packages may not be compatible." - echo "Recommended: brew install python@3.12" + + is_pinned() { + "$1" -c 'import sys; sys.exit(sys.version_info[:2] != tuple(map(int, "{{ python_version }}".split("."))))' 2>/dev/null + } + + # Testing for an executable file is not enough: console scripts hard-code the + # venv's absolute path in their shebang, so a venv that was built elsewhere and + # moved into place has a pip that exists, is executable, and still dies with + # "cannot execute: required file not found". Running it is the only real check. + pip_works() { + "{{ pip }}" --version >/dev/null 2>&1 + } + + # Every interpreter on PATH that could be the pinned version, plus uv's, which + # keeps its Pythons off PATH. More than one can match, and the first is not + # necessarily the good one. + candidates() { + type -aP "python{{ python_version }}" python3 python 2>/dev/null || true + if command -v uv >/dev/null 2>&1; then + uv python find "{{ python_version }}" 2>/dev/null || true fi - {{ system_python }} -m venv {{ venv }} + } + + # Reuse the venv only if it is on the pinned version and has a working pip: a + # wrong-version venv resolves dependencies against the wrong Python, and a + # broken pip means an earlier `-m venv` was interrupted or the venv was moved. + if [ -d "{{ venv }}" ] && ! { is_pinned "{{ python }}" && pip_works; }; then + echo "Existing venv is not a working Python {{ python_version }} environment — recreating..." + rm -rf "{{ venv }}" + fi + + if [ ! -d "{{ venv }}" ]; then + # Building the venv is itself the test, so there is no separate probe to keep + # in sync. An interpreter can report the right version and still fail inside + # `-m venv` — Debian packages ensurepip separately, and Homebrew has shipped a + # pyexpat that won't dlopen — so fall through to the next candidate rather + # than giving up on the first. Their output is held back until every candidate + # has failed, so a run that recovers doesn't look like a broken one. + log="$(mktemp)" + while IFS= read -r py; do + is_pinned "$py" || continue + echo "Creating Python virtual environment with $py ..." + "$py" -m venv "{{ venv }}" >>"$log" 2>&1 && pip_works && break + echo " ...it reports {{ python_version }} but cannot build a working venv; trying the next." + rm -rf "{{ venv }}" + done < <(candidates | sed 's|//*|/|g' | awk '!seen[$0]++') + pip_works || cat "$log" + rm -f "$log" + fi + + if ! pip_works; then + echo "" + echo "ERROR: Voicebox needs a Python {{ python_version }} that can create virtual" + echo " environments (see requires-python in backend/pyproject.toml)." + echo " Any: uv python install {{ python_version }}" + echo " macOS: brew install python@{{ python_version }}" + echo " Debian: sudo apt install python{{ python_version }} python{{ python_version }}-venv" + echo "" + echo "Then re-run: just setup" + exit 1 fi echo "Installing Python dependencies..." {{ pip }} install --upgrade pip -q @@ -85,13 +140,40 @@ setup-python: [windows] setup-python: + $target = "{{ python_version }}"; \ + function Test-Py($exe) { \ + if (-not $exe -or -not (Test-Path $exe)) { return $false }; \ + $v = & $exe -c "import sys; print('%s.%s' % sys.version_info[:2])" 2>$null; \ + return ($LASTEXITCODE -eq 0 -and $v -eq $target); \ + }; \ + function Test-Pip { \ + if (-not (Test-Path "{{ pip }}")) { return $false }; \ + & "{{ pip }}" --version *> $null; \ + return ($LASTEXITCODE -eq 0); \ + }; \ + $py = $null; \ + if (Get-Command py -ErrorAction SilentlyContinue) { \ + $p = & py "-$target" -c "import sys; print(sys.executable)" 2>$null; \ + if ($LASTEXITCODE -eq 0) { $py = $p }; \ + }; \ + if (-not $py) { foreach ($n in @("python$target", "python")) { \ + $c = Get-Command $n -ErrorAction SilentlyContinue; \ + if ($c -and (Test-Py $c.Source)) { $py = $c.Source; break }; \ + } }; \ + if (-not $py) { \ + Write-Host "ERROR: Voicebox requires Python $target (see requires-python in backend/pyproject.toml)."; \ + Write-Host "Install it from https://python.org or: winget install -e --id Python.Python.$target"; \ + Write-Host "Then re-run: just setup"; \ + exit 1; \ + }; \ + if ((Test-Path "{{ venv }}") -and (-not (Test-Py "{{ python }}") -or -not (Test-Pip))) { \ + Write-Host "Existing venv is not a working Python $target env - recreating..."; \ + Remove-Item -Recurse -Force "{{ venv }}"; \ + }; \ if (-not (Test-Path "{{ venv }}")) { \ - Write-Host "Creating Python virtual environment..."; \ - $pyMinor = & {{ system_python }} -c "import sys; print(sys.version_info[1])"; \ - if ([int]$pyMinor -gt 13) { \ - Write-Host "Warning: Python 3.$pyMinor detected. ML packages may not be compatible."; \ - }; \ - & {{ system_python }} -m venv {{ venv }}; \ + Write-Host "Creating Python virtual environment with $py ..."; \ + & $py -m venv "{{ venv }}"; \ + if ($LASTEXITCODE -ne 0 -or -not (Test-Pip)) { Write-Host "ERROR: could not create a working venv with $py"; exit 1 }; \ } Write-Host "Installing Python dependencies..." & "{{ python }}" -m pip install --upgrade pip -q From 8c86d90ce706d3d62ef6ea9345a21e6415f111ad Mon Sep 17 00:00:00 2001 From: dhananjaypai08 Date: Mon, 10 Aug 2026 02:28:37 +0530 Subject: [PATCH 2/3] validation and install uses python commands --- docs/content/docs/developer/setup.mdx | 7 ++- .../content/docs/overview/troubleshooting.mdx | 9 ++- justfile | 55 +++++++++---------- 3 files changed, 38 insertions(+), 33 deletions(-) diff --git a/docs/content/docs/developer/setup.mdx b/docs/content/docs/developer/setup.mdx index 58c79c42f..d4a777a52 100644 --- a/docs/content/docs/developer/setup.mdx +++ b/docs/content/docs/developer/setup.mdx @@ -35,7 +35,8 @@ Ensure you have these installed: }> [Download Python](https://python.org) ```bash - python3.12 --version # Should be 3.12.x + python3.12 --version # macOS/Linux — should be 3.12.x + py -3.12 --version # Windows ``` Voicebox pins its venv to 3.12 to match CI, because some dependencies have no 3.13 release yet. On Debian/Ubuntu also install `python3.12-venv`. @@ -216,7 +217,9 @@ This installs dependencies for: cd backend # Create virtual environment (use Python 3.12 — see Prerequisites) -python3.12 -m venv venv +python3.12 -m venv venv # macOS/Linux +# or +py -3.12 -m venv venv # Windows # Activate virtual environment source venv/bin/activate # macOS/Linux diff --git a/docs/content/docs/overview/troubleshooting.mdx b/docs/content/docs/overview/troubleshooting.mdx index 5c2f26ee0..dc1eaef1d 100644 --- a/docs/content/docs/overview/troubleshooting.mdx +++ b/docs/content/docs/overview/troubleshooting.mdx @@ -295,7 +295,8 @@ This is expected behavior. The first generation downloads the selected TTS engin Ensure Python 3.12: ```bash - python3.12 --version + python3.12 --version # macOS/Linux + py -3.12 --version # Windows ``` Voicebox pins its venv to Python 3.12 because some dependencies have no 3.13 @@ -303,8 +304,10 @@ This is expected behavior. The first generation downloads the selected TTS engin so re-running it is usually the fix. If `just setup` can't find a usable 3.12, install one: `uv python install 3.12` - works anywhere, or use `brew install python@3.12` on macOS and `sudo apt install - python3.12 python3.12-venv` on Debian/Ubuntu. + works anywhere; `brew install python@3.12` on macOS; `sudo apt install + python3.12 python3.12-venv` on Debian/Ubuntu; or on Windows install from + [python.org](https://python.org) / `winget install -e --id Python.Python.3.12` + and use the `py -3.12` launcher. diff --git a/justfile b/justfile index 99eedda84..f83e9c991 100644 --- a/justfile +++ b/justfile @@ -12,7 +12,6 @@ venv := backend_dir / "venv" # Platform-aware paths venv_bin := if os() == "windows" { venv / "Scripts" } else { venv / "bin" } python := if os() == "windows" { venv_bin / "python.exe" } else { venv_bin / "python" } -pip := if os() == "windows" { venv_bin / "pip.exe" } else { venv_bin / "pip" } # Shell selection: use powershell on Windows, bash elsewhere set windows-shell := ["powershell", "-NoProfile", "-Command"] @@ -40,12 +39,12 @@ setup-python: "$1" -c 'import sys; sys.exit(sys.version_info[:2] != tuple(map(int, "{{ python_version }}".split("."))))' 2>/dev/null } - # Testing for an executable file is not enough: console scripts hard-code the - # venv's absolute path in their shebang, so a venv that was built elsewhere and - # moved into place has a pip that exists, is executable, and still dies with - # "cannot execute: required file not found". Running it is the only real check. + # Invoke pip via the venv's python so validation and installs share the same + # interpreter. A copied venv can keep a working `pip` console script whose + # shebang still points at the original tree — that would make `pip --version` + # succeed while later installs land in the wrong environment. pip_works() { - "{{ pip }}" --version >/dev/null 2>&1 + "{{ python }}" -m pip --version >/dev/null 2>&1 } # Every interpreter on PATH that could be the pinned version, plus uv's, which @@ -97,7 +96,7 @@ setup-python: exit 1 fi echo "Installing Python dependencies..." - {{ pip }} install --upgrade pip -q + "{{ python }}" -m pip install --upgrade pip -q if [ "$(uname)" = "Linux" ]; then torch_index="" if [ -e /proc/driver/nvidia/version ] || [ -d /sys/module/nvidia ]; then @@ -115,27 +114,27 @@ setup-python: torch_index="https://download.pytorch.org/whl/rocm${rocm_ver}" fi if [ -n "$torch_index" ]; then - {{ pip }} install torch torchaudio --index-url "$torch_index" + "{{ python }}" -m pip install torch torchaudio --index-url "$torch_index" fi fi - {{ pip }} install -r {{ backend_dir }}/requirements.txt + "{{ python }}" -m pip install -r {{ backend_dir }}/requirements.txt # Chatterbox pins numpy<1.26 / torch==2.6 which break on Python 3.12+ - {{ pip }} install --no-deps chatterbox-tts + "{{ python }}" -m pip install --no-deps chatterbox-tts # HumeAI TADA pins torch>=2.7,<2.8 which conflicts with our torch>=2.1 - {{ pip }} install --no-deps hume-tada + "{{ python }}" -m pip install --no-deps hume-tada # Apple Silicon: install MLX backend if [ "$(uname -m)" = "arm64" ] && [ "$(uname)" = "Darwin" ]; then echo "Detected Apple Silicon — installing MLX dependencies..." - {{ pip }} install -r {{ backend_dir }}/requirements-mlx.txt + "{{ python }}" -m pip install -r {{ backend_dir }}/requirements-mlx.txt # mlx-lm and mlx-audio declare transformers>=5.x, which conflicts with # our transformers<=4.57.x cap, so install them --no-deps (their other # runtime deps are covered by requirements.txt / requirements-mlx.txt — # see the note in requirements-mlx.txt and .github/workflows/release.yml) - {{ pip }} install --no-deps mlx-lm==0.31.1 - {{ pip }} install --no-deps mlx-audio==0.4.1 + "{{ python }}" -m pip install --no-deps mlx-lm==0.31.1 + "{{ python }}" -m pip install --no-deps mlx-audio==0.4.1 fi - {{ pip }} install git+https://github.com/QwenLM/Qwen3-TTS.git - {{ pip }} install pyinstaller ruff pytest pytest-asyncio -q + "{{ python }}" -m pip install git+https://github.com/QwenLM/Qwen3-TTS.git + "{{ python }}" -m pip install pyinstaller ruff pytest pytest-asyncio -q echo "Python environment ready." [windows] @@ -147,8 +146,8 @@ setup-python: return ($LASTEXITCODE -eq 0 -and $v -eq $target); \ }; \ function Test-Pip { \ - if (-not (Test-Path "{{ pip }}")) { return $false }; \ - & "{{ pip }}" --version *> $null; \ + if (-not (Test-Path "{{ python }}")) { return $false }; \ + & "{{ python }}" -m pip --version *> $null; \ return ($LASTEXITCODE -eq 0); \ }; \ $py = $null; \ @@ -183,22 +182,22 @@ setup-python: $hasIntelArc = ($gpus | Where-Object { $_ -match 'Arc' }).Count -gt 0; \ if ($hasNvidia) { \ Write-Host "NVIDIA GPU detected — installing PyTorch with CUDA support..."; \ - & "{{ pip }}" install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128; \ + & "{{ python }}" -m pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128; \ } elseif ($hasIntelArc) { \ Write-Host "Intel Arc GPU detected — installing PyTorch with XPU support..."; \ - & "{{ pip }}" install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/xpu; \ - & "{{ pip }}" install intel-extension-for-pytorch --index-url https://download.pytorch.org/whl/xpu; \ + & "{{ python }}" -m pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/xpu; \ + & "{{ python }}" -m pip install intel-extension-for-pytorch --index-url https://download.pytorch.org/whl/xpu; \ } else { \ Write-Host "No NVIDIA or Intel Arc GPU detected — using CPU-only PyTorch."; \ Write-Host "If you have an Intel Arc GPU, install XPU support manually:"; \ - Write-Host " pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/xpu"; \ - Write-Host " pip install intel-extension-for-pytorch --index-url https://download.pytorch.org/whl/xpu"; \ + Write-Host " python -m pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/xpu"; \ + Write-Host " python -m pip install intel-extension-for-pytorch --index-url https://download.pytorch.org/whl/xpu"; \ } - & "{{ pip }}" install -r {{ backend_dir }}/requirements.txt - & "{{ pip }}" install --no-deps chatterbox-tts - & "{{ pip }}" install --no-deps hume-tada - & "{{ pip }}" install git+https://github.com/QwenLM/Qwen3-TTS.git - & "{{ pip }}" install pyinstaller ruff pytest pytest-asyncio -q + & "{{ python }}" -m pip install -r {{ backend_dir }}/requirements.txt + & "{{ python }}" -m pip install --no-deps chatterbox-tts + & "{{ python }}" -m pip install --no-deps hume-tada + & "{{ python }}" -m pip install git+https://github.com/QwenLM/Qwen3-TTS.git + & "{{ python }}" -m pip install pyinstaller ruff pytest pytest-asyncio -q Write-Host "Python environment ready." # Install JavaScript dependencies From b7380e417d281fa7ae0db8aa5dad989da813682e Mon Sep 17 00:00:00 2001 From: dhananjaypai08 Date: Mon, 10 Aug 2026 12:45:24 +0530 Subject: [PATCH 3/3] fix: setup-python now uses invoke-pip --- justfile | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/justfile b/justfile index f83e9c991..62ad108bb 100644 --- a/justfile +++ b/justfile @@ -174,30 +174,36 @@ setup-python: & $py -m venv "{{ venv }}"; \ if ($LASTEXITCODE -ne 0 -or -not (Test-Pip)) { Write-Host "ERROR: could not create a working venv with $py"; exit 1 }; \ } - Write-Host "Installing Python dependencies..." - & "{{ python }}" -m pip install --upgrade pip -q + # PowerShell does not fail the recipe when a native command returns nonzero, so + # wrap every pip invocation and exit on $LASTEXITCODE. + Write-Host "Installing Python dependencies..."; \ + function Invoke-Pip { \ + & "{{ python }}" -m pip @args; \ + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }; \ + }; \ + Invoke-Pip install --upgrade pip -q; \ $gpus = Get-CimInstance Win32_VideoController | Select-Object -ExpandProperty Name; \ Write-Host "Detected GPUs: $($gpus -join ', ')"; \ $hasNvidia = ($gpus | Where-Object { $_ -match 'NVIDIA' }).Count -gt 0; \ $hasIntelArc = ($gpus | Where-Object { $_ -match 'Arc' }).Count -gt 0; \ if ($hasNvidia) { \ Write-Host "NVIDIA GPU detected — installing PyTorch with CUDA support..."; \ - & "{{ python }}" -m pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128; \ + Invoke-Pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128; \ } elseif ($hasIntelArc) { \ Write-Host "Intel Arc GPU detected — installing PyTorch with XPU support..."; \ - & "{{ python }}" -m pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/xpu; \ - & "{{ python }}" -m pip install intel-extension-for-pytorch --index-url https://download.pytorch.org/whl/xpu; \ + Invoke-Pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/xpu; \ + Invoke-Pip install intel-extension-for-pytorch --index-url https://download.pytorch.org/whl/xpu; \ } else { \ Write-Host "No NVIDIA or Intel Arc GPU detected — using CPU-only PyTorch."; \ Write-Host "If you have an Intel Arc GPU, install XPU support manually:"; \ Write-Host " python -m pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/xpu"; \ Write-Host " python -m pip install intel-extension-for-pytorch --index-url https://download.pytorch.org/whl/xpu"; \ - } - & "{{ python }}" -m pip install -r {{ backend_dir }}/requirements.txt - & "{{ python }}" -m pip install --no-deps chatterbox-tts - & "{{ python }}" -m pip install --no-deps hume-tada - & "{{ python }}" -m pip install git+https://github.com/QwenLM/Qwen3-TTS.git - & "{{ python }}" -m pip install pyinstaller ruff pytest pytest-asyncio -q + }; \ + Invoke-Pip install -r {{ backend_dir }}/requirements.txt; \ + Invoke-Pip install --no-deps chatterbox-tts; \ + Invoke-Pip install --no-deps hume-tada; \ + Invoke-Pip install git+https://github.com/QwenLM/Qwen3-TTS.git; \ + Invoke-Pip install pyinstaller ruff pytest pytest-asyncio -q; \ Write-Host "Python environment ready." # Install JavaScript dependencies