Fedora Atomic (Silverblue/Bazzite/Bluefin) support, plus installer and whisper fixes - #517
Open
Sallvainian wants to merge 10 commits into
Open
Fedora Atomic (Silverblue/Bazzite/Bluefin) support, plus installer and whisper fixes#517Sallvainian wants to merge 10 commits into
Sallvainian wants to merge 10 commits into
Conversation
The installer ran `sudo dnf install` for anything reporting ID=fedora in /etc/os-release. Atomic variants report exactly that but have a read-only /usr, and Bazzite ships a dnf shim that refuses `install` outright, so the dependency step always failed and aborted the run. Detect ostree systems via /run/ostree-booted and route package installation through Homebrew, which needs neither root nor a reboot and is the normal way to get development headers on an immutable OS. Packages with no homebrew-core equivalent now print the `rpm-ostree install` command, the reboot it requires, and the distrobox alternative, rather than a bare dnf error. python3-devel is skipped entirely: voice-mode installs with `uv tool install`, which builds against uv's managed CPython and ships its own headers. Also fix the dependency checks themselves, which asked `rpm -q` whether a package was present and so reported missing whenever it came from anywhere other than an RPM. They now test for the capability instead of the packaging: pkg-config for alsa and portaudio-2.0, a Python.h probe for python3-devel, a loadable-library probe for portaudio (sounddevice dlopens it via cffi and never needs the headers), and pactl for the PulseAudio utilities, which PipeWire provides on modern Fedora. Homebrew's pkgconfig directories are added to PKG_CONFIG_PATH for check commands, since Homebrew is not on pkg-config's default search path on Linux. Verified on Bazzite (Fedora Atomic 44, ostree image bazzite-gnome-nvidia-open). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The previous commit fixed installer/voicemode_install/, but `voicemode deps` does not use it. The repo carries two independent dependency systems with separate copies of dependencies.yaml, so the CLI still reported every core dependency missing on Fedora Atomic. Port the same capability-based checks to voice_mode/utils/dependencies/ and voice_mode/dependencies.yaml, and add ostree/Homebrew awareness there. Two additional fixes specific to this checker: - Check commands now run with shell=True. They were passed through str.split(), so a command containing quoted arguments or a `||` fallback was silently mangled into the wrong argv. The standalone installer's checker already used shell=True; this aligns them. Commands come from the bundled YAML, not user input. - python3-devel is probed against the interpreter that would actually build the extensions, exported as VOICEMODE_PYTHON, instead of PATH's python3. Under `uv tool install` these differ -- uv's managed CPython ships headers while the system python3 often has none -- which made a working install report python3-devel missing. On Bazzite this takes `voicemode deps` from 7 missing core dependencies to 0. The three still reported (portaudio-devel, cargo, rust) are genuinely absent and are build dependencies of the local Whisper/Kokoro engines, not of the cloud path. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`voicemode service install whisper` failed on Fedora Atomic with "No available formula with the name portaudio-devel". dependencies.yaml lists Fedora RPM names and they were passed to Homebrew verbatim. `cargo` is worse than a rename: it has no formula at all, since cargo ships inside `rust`, so `brew install cargo rust` dies on the first name. Add OstreeBrewManager, which maps RPM names to homebrew-core formulae and de-duplicates the result (cargo + rust collapse to one `rust`). Names with no formula no longer produce a bare brew error -- they report the rpm-ostree install command with its reboot, and the distrobox alternative. Add RpmOstreeManager for Atomic systems with no Homebrew, which explains both options and never shells out to dnf. Also fix package manager selection, which is a bug beyond Atomic: get_package_manager() tried BrewManager first on every platform, so any Fedora or Debian user with Homebrew installed got brew selected and fed distro package names it cannot resolve. Prefer the native manager on Linux and fall back to Homebrew; Atomic systems now route to Homebrew deliberately instead of by accident. The previous commit fixed dependency *checking* in this package but left *installation* using the old path -- the same two-systems split that motivated that commit. Verified by running the failing flow on Bazzite. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`voicemode service install whisper` printed "❌ Whisper installation failed" and then exited 0. The installer invokes it with subprocess.run(check=True), so nothing raised and it printed "✅ Whisper STT service installed" on the very next line. Users were told a service installed when it had not. Add sys.exit(1) to the whisper, kokoro, voicemode and mlx-audio failure branches, and to the unknown-service branch. The Whisper dependency check also suggested `sudo dnf install cuda-toolkit` and `sudo apt-get install build-essential` based only on which binary exists. Fedora Atomic ships dnf but cannot install with it, so that suggestion sends the user down a path that always fails. On ostree systems, CUDA now suggests --no-gpu or a distrobox container (there is no Homebrew formula for the CUDA toolkit and layering it is heavy), and build tools suggest Homebrew or rpm-ostree with its reboot. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… install Two failures hit while installing Kokoro's dependencies on Bazzite. Homebrew had the shortest install timeout of the three package managers -- 300s against 600s for apt and dnf -- despite doing the heaviest work, since it downloads large bottles and can fall back to building from source. The `rust` bottle Kokoro needs is ~400MB, which took roughly 20 minutes on an ordinary connection and was killed at 5 with only a timeout to show for it. Raised to 1800s. Both halves matter: without the name dedup the install dies instantly on `cargo`, and without the timeout it dies five minutes in. Separately, `voicemode service install` accepted only --force, while whisper_install() has always taken `model` and `use_gpu`. So the CUDA error message instructing users to "use --no-gpu for CPU-only" referred to a flag that did not exist, leaving no way to build whisper without the CUDA toolkit -- which on Fedora Atomic cannot be installed at all. The standalone installer also shells out to `service install whisper --model <name>`, which would have failed as an unknown option for any non-default model. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…toolkit whisper_install() auto-detects the GPU when use_gpu is not specified, then required nvcc and aborted the install without it. So any machine with an NVIDIA card but no CUDA toolkit could not install Whisper at all -- despite nothing having asked for GPU support, and despite whisper.cpp building and running perfectly well on CPU. On Fedora Atomic it is a dead end, since the CUDA toolkit cannot be installed there and the error suggested `sudo dnf install cuda-toolkit`, which cannot work. Track whether GPU support was auto-detected or explicitly requested. When auto-detected, a missing nvcc now warns and builds CPU-only. An explicit --use-gpu still reports the missing toolkit as an error, so a deliberate request is never silently downgraded to something slower than asked for. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
nvcc refuses any host compiler newer than the version its headers were built against, and -DGGML_CUDA=ON was passed with an unmodified environment. On distributions that move faster than CUDA the build aborted at configure time with "#error -- unsupported GNU version!" -- Fedora 44 defaults to GCC 16 while CUDA 13.3 stops at 15. Read the ceiling from CUDA's crt/host_config.h instead of hardcoding a table that goes stale every release, then pick the newest installed g++ at or below it and pass it as CMAKE_CUDA_HOST_COMPILER, with CUDAHOSTCXX and NVCC_CCBIN set to match so CMake and ggml's own nvcc calls cannot disagree. Name the package to install when nothing compatible is present. Also correct the Atomic CUDA guidance: it suggested building in a distrobox container, but voice-mode runs whisper as a host service and a binary built there links the container's CUDA libraries. Point at NVIDIA's runfile instead -- /usr/local is a symlink to /var/usrlocal, so a host-native toolkit installs without layering or a reboot. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019fWTAFm6Cjf8jpprtDd1YN
whisper_install's CalledProcessError handler called e.stderr.decode(), but the
configure and build steps run with text=True, so e.stderr is already str. The
handler raised AttributeError itself, and a sibling `except Exception` cannot
catch an exception raised by a preceding handler, so it escaped the function and
destroyed the cmake output at the one moment it mattered -- a failed GPU build
printed a wall of linker noise ending in an unrelated
"'str' object has no attribute 'decode'".
The identical line in the Kokoro installer avoids crashing today only because
none of its checked calls capture output, so it silently reports None for every
failure. Both now decode only when handed bytes.
Two more handlers could raise over their own error:
- disable_sounddevice_stderr_redirect() imported sys inside its try, making it
function-local; when the sounddevice import failed -- the case the handler
exists for -- sys was unbound and it raised UnboundLocalError.
- Exchange tailing called process.terminate() from its KeyboardInterrupt
handler; a Ctrl-C during Popen() itself left process unbound.
Separately, the installer reported success after a component failed: a run where
Whisper failed and Kokoro succeeded logged the failure and then
"Installation completed" {"success": true}, exiting 0. log_complete took a
literal True, so no component result could reach it. Failures are now collected,
the status reflects them, the summary names the retry command, and it exits 1.
The log gains the error text it was discarding, and the unreachable post-check
`else` branches are removed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019fWTAFm6Cjf8jpprtDd1YN
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…endent TestPackageManagerSelection mocked each manager's check_available but not the OS detection, so it asserted against whatever machine ran it. get_package_manager returns on the Darwin branch on macOS and on the ostree branch on Fedora Atomic, in both cases before the dnf/apt/brew list is consulted -- so test_get_package_manager_dnf failed for any Silverblue/Bazzite contributor while passing in CI. Pin platform.system and is_ostree_system, and add coverage for the Atomic branches: Homebrew when present, the explaining fallback when not, and that DnfManager is never selected there even with dnf on PATH. Also cover the RPM to Homebrew name translation -- stripping -devel and collapsing cargo/rust onto the single rust formula. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
Author
|
The red check on this PR is three pre-existing failures on Python 3.10, not
These only surface on PRs — The CI job also runs fail-fast, so ubuntu 3.10 failing cancelled the other five Happy to send the 3.10 fixes as a separate PR if that's useful, since they're |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds Fedora Atomic (Silverblue, Kinoite, Bazzite, Bluefin) support to the
installer, plus several fixes that are not Atomic-specific.
Why
The installer ran
sudo dnf installfor anything reportingID=fedora. OnAtomic variants that can never succeed —
/usris read-only and Bazzite ships adnfshim that refusesinstalloutright — so the dependency step failed andtook the rest of the run with it. The dependency checks used
rpm -q, so afully working install reported 7 of 7 core deps missing.
Fixes that apply to everyone, not just Atomic
get_package_manager()tried Homebrew first on every platform. AnyFedora/Debian user with Homebrew installed got brew handed distro package
names it cannot resolve. Native manager now wins.
voicemode service installexited 0 on failure, so the installer'ssubprocess.run(..., check=True)never raised — it printedWhisper installation failedandWhisper STT service installedback to back.e.stderr.decode()on atext=Truesubprocess raisesAttributeErrorinside the handler; a siblingexcept Exceptioncannot catch that, so it escaped and destroyed the cmakeoutput at the one moment it mattered. Two more handlers could raise over their
own error (
sysimported inside thetrythat needed it;processunbound onCtrl-C during
Popen).ships GCC 16, CUDA 13.3 accepts ≤15, so
-DGGML_CUDA=ONaborted at configurewith
unsupported GNU version. The ceiling is now read from CUDA's owncrt/host_config.hand a compatibleg++is selected.heaviest work; the
rustbottle exceeded it and was killed mid-download.--modeland--no-gpudid not exist onservice install, though theinstaller shells out with
--modeland the CUDA error told users to pass--no-gpu.stranding anyone with an NVIDIA card and no toolkit. Now falls back to CPU.
not the OS probes, so
test_get_package_manager_dnffailed for anySilverblue/Bazzite contributor while passing in CI.
Atomic support
Detects
/run/ostree-booted, routes installs through Homebrew (no root, noreboot) with an RPM→formula map, and replaces
rpm -qwith capability probes(
pkg-config, loadable-library,Python.h).python3-develis skipped becauseuv tool installbuilds against uv's managed CPython, which ships its ownheaders. Anything with no Homebrew equivalent prints the
rpm-ostree installcommand and reboot rather than failing with a bare
dnferror.Testing
pytest: 1925 passed, 56 skipped, 0 failed.Verified end to end on Bazzite 44 (Fedora Atomic, GNOME/Wayland, RTX 4070 Ti):
voice-mode-installgoes from 7 missing core deps to 0, installscmake,portaudio-devel,cargoandrustitself, builds whisper.cpp with CUDA(
ARCHS = 890), and a full Kokoro→whisper round trip transcribes correctly.