Implements offline mode patch for API stability issues:
- Add hf_offline_patch.py to monkey-patch huggingface_hub
- Force cache-only lookups before mlx_audio imports
- Create symlink from original Qwen repo to MLX community version
when only MLX version is cached
This fixes:
- Issue #150: Internet required even with cached models
- Issue #151: API crashes when HF network fails
The patch ensures that if models are locally cached, no network
requests are made to HuggingFace during speech generation.
Adds a persistent top-of-page banner linking to spacebot.sh,
another project by the creator of Voicebox. Uses existing design
tokens for a consistent look.
Exposes the existing remote server mode through a checkbox in Server
Connection settings. When enabled, the server binds to 0.0.0.0 instead
of 127.0.0.1, making it accessible from other devices on the network.
The plumbing already existed (Rust sidecar passes --host 0.0.0.0 when
remote=true, serverStore has mode state, Python backend accepts --host),
but the UI hardcoded startServer(false). This wires it up.
Closes#104
The web version was missing the Tailwind CSS Vite plugin, causing
CSS to not load at all. This adds the same plugin configuration
that exists in the tauri version.
Fixes#121
The /generate endpoint created the voice prompt before loading the
user's requested model size. Since create_voice_prompt() internally
calls load_model_async(None), it fell back to the hardcoded default
of "1.7B", causing the 1.7B model to be downloaded even when the
user explicitly selected 0.6B.
This reorders the operations so the requested model is loaded first,
ensuring create_voice_prompt() and generate() use the correct model.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
The distributed macOS aarch64 binary shipped without MLX acceleration despite
the model and backend code supporting it. Two root causes:
1. **OSError not caught in platform_detect.py**
PyInstaller bundles isolate the filesystem, so when MLX tries to load its
Metal shader libraries (.metallib) it raises OSError, not ImportError.
platform_detect.get_backend_type() only caught ImportError, causing a
silent fallback to PyTorch even on Apple Silicon hardware.
Fix: broaden the except clause to (ImportError, OSError, RuntimeError)
and import mlx.core instead of mlx (forces native lib loading eagerly).
2. **collect_data_files used instead of collect_all for MLX**
build_binary.py and voicebox-server.spec used --collect-data /
collect_data_files for mlx and mlx_audio. This copies Python source and
pure-Python data, but NOT native shared libraries (.dylib, .metallib).
Fix: switch to --collect-all / collect_all which captures binaries too,
then pass them to Analysis(binaries=...) in the spec.
Result: macOS Apple Silicon users now get MLX inference (~4-5x faster than
PyTorch CPU), matching the performance documented in the README.
20 tests covering:
- All 6 default local origins are allowed
- Arbitrary external origins are blocked
- Preflight (OPTIONS) requests respect the allowlist
- VOICEBOX_CORS_ORIGINS env var extends the allowlist
- Edge cases: empty env, whitespace trimming, trailing commas
Tests use a minimal FastAPI app mirroring the real CORS config,
so they run without ML dependencies (torch, numpy, etc.).
The wildcard `allow_origins=["*"]` allows any website the user visits to
make requests to the local voicebox backend, potentially triggering TTS
generation or reading voice profiles without consent.
Restrict to the known Tauri webview and Vite dev server origins by
default. Users running in remote server mode can set
VOICEBOX_CORS_ORIGINS to allow additional origins.
The export endpoints (export-audio, export generation, export profile,
export story) crash with `'latin-1' codec can't encode characters` when
the generated text or profile/story name contains non-ASCII characters
(e.g. Cyrillic, Chinese, Arabic).
Root cause: Python's `str.isalnum()` passes Unicode letters through to
the filename, but HTTP headers are encoded as latin-1 by the ASGI server,
which cannot represent characters outside the 0-255 range.
Fix: introduce `_safe_content_disposition()` helper that builds a
standards-compliant header with an ASCII-only `filename` fallback and a
RFC 5987 `filename*=UTF-8''...` parameter for Unicode-capable clients.
Fixes#68
Co-authored-by: Cursor <[email protected]>
- Adds tooltips on hover for buttons of the generate box
- Replaces the message square icon with a sliders icon for the instruction mode toggle.
- Adds a tooltip to the instruction mode toggle button.
- Updates the placeholder text for the input field.
- Updated caching methods in MLX, PyTorch, and backend to ensure models are fully downloaded before being marked as cached.
- Improved progress tracking to filter out non-download progress and provide accurate feedback during model downloads.
- Enhanced HFProgressTracker to skip non-byte progress bars and ensure meaningful progress reporting.
- Refactored progress initialization to provide immediate feedback while fetching metadata from HuggingFace.
- Added error handling and logging for better debugging during cache checks and download processes.
- Rearranged imports for consistency in useModelDownloadToast hook.
- Improved logging in useModelDownloadToast for better debugging during download events.
- Updated progress calculation to handle cases where progress exceeds 100%.
- Enhanced toast notifications to reflect download completion and error states.
- Introduced throttling in ProgressManager to optimize SSE updates and prevent overwhelming clients.
- Added new test scripts for monitoring SSE events during model downloads, ensuring accurate progress reporting.