fix: allow voice mode in WSL when PulseAudio bridge is configured

WSL detection was treated as a hard fail, blocking voice mode even when
audio worked via PulseAudio bridge. Now PULSE_SERVER env var presence
makes WSL a soft notice instead of a blocking warning. Device query
failures in WSL with PULSE_SERVER are also treated as non-blocking.
This commit is contained in:
0xbyt4
2026-03-30 11:30:26 +03:00
committed by Teknium
parent 7f670a06cf
commit 08171c1c31
2 changed files with 153 additions and 5 deletions

View File

@@ -51,9 +51,12 @@ def _audio_available() -> bool:
def detect_audio_environment() -> dict:
"""Detect if the current environment supports audio I/O.
Returns dict with 'available' (bool) and 'warnings' (list of strings).
Returns dict with 'available' (bool), 'warnings' (list of hard-fail
reasons that block voice mode), and 'notices' (list of informational
messages that do NOT block voice mode).
"""
warnings = []
warnings = [] # hard-fail: these block voice mode
notices = [] # informational: logged but don't block
# SSH detection
if any(os.environ.get(v) for v in ('SSH_CLIENT', 'SSH_TTY', 'SSH_CONNECTION')):
@@ -63,11 +66,20 @@ def detect_audio_environment() -> dict:
if os.path.exists('/.dockerenv'):
warnings.append("Running inside Docker container -- no audio devices")
# WSL detection
# WSL detection — PulseAudio bridge makes audio work in WSL.
# Only block if PULSE_SERVER is not configured.
try:
with open('/proc/version', 'r') as f:
if 'microsoft' in f.read().lower():
warnings.append("Running in WSL -- audio requires PulseAudio bridge to Windows")
if os.environ.get('PULSE_SERVER'):
notices.append("Running in WSL with PulseAudio bridge")
else:
warnings.append(
"Running in WSL -- audio requires PulseAudio bridge.\n"
" 1. Set PULSE_SERVER=unix:/mnt/wslg/PulseServer\n"
" 2. Create ~/.asoundrc pointing ALSA at PulseAudio\n"
" 3. Verify with: arecord -d 3 /tmp/test.wav && aplay /tmp/test.wav"
)
except (FileNotFoundError, PermissionError, OSError):
pass
@@ -79,7 +91,12 @@ def detect_audio_environment() -> dict:
if not devices:
warnings.append("No audio input/output devices detected")
except Exception:
warnings.append("Audio subsystem error (PortAudio cannot query devices)")
# In WSL with PulseAudio, device queries can fail even though
# recording/playback works fine. Don't block if PULSE_SERVER is set.
if os.environ.get('PULSE_SERVER'):
notices.append("Audio device query failed but PULSE_SERVER is set -- continuing")
else:
warnings.append("Audio subsystem error (PortAudio cannot query devices)")
except ImportError:
warnings.append("Audio libraries not installed (pip install sounddevice numpy)")
except OSError:
@@ -93,6 +110,7 @@ def detect_audio_environment() -> dict:
return {
"available": len(warnings) == 0,
"warnings": warnings,
"notices": notices,
}
# ---------------------------------------------------------------------------
@@ -748,6 +766,8 @@ def check_voice_requirements() -> Dict[str, Any]:
for warning in env_check["warnings"]:
details_parts.append(f"Environment: {warning}")
for notice in env_check.get("notices", []):
details_parts.append(f"Environment: {notice}")
return {
"available": available,