mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-30 06:41:51 +00:00
fix(voice): honor PULSE_SERVER/PIPEWIRE_REMOTE inside Docker (#21203)
detect_audio_environment() unconditionally added a hard warning when running inside a container, blocking /voice on even when the host audio socket was correctly forwarded (PulseAudio or PipeWire) and sounddevice could enumerate devices. Mirror the existing WSL/PulseAudio handling: if PULSE_SERVER or PIPEWIRE_REMOTE is set, downgrade to a notice and let the audio backend decide. When neither is set, keep the block but extend the message with the exact -v / -e flags users need. Closes #21203
This commit is contained in:
parent
f6d45e5df4
commit
bde487c911
2 changed files with 68 additions and 2 deletions
|
|
@ -216,6 +216,60 @@ class TestDetectAudioEnvironment:
|
|||
assert any("Termux:API Android app is not installed" in w for w in result["warnings"])
|
||||
|
||||
|
||||
def test_docker_with_pulse_server_allows_voice(self, monkeypatch):
|
||||
"""Docker with PULSE_SERVER set should NOT block voice mode (#21203)."""
|
||||
monkeypatch.delenv("SSH_CLIENT", raising=False)
|
||||
monkeypatch.delenv("SSH_TTY", raising=False)
|
||||
monkeypatch.delenv("SSH_CONNECTION", raising=False)
|
||||
monkeypatch.setenv("PULSE_SERVER", "unix:/run/user/1000/pulse/native")
|
||||
monkeypatch.delenv("PIPEWIRE_REMOTE", raising=False)
|
||||
monkeypatch.setattr("hermes_constants.is_container", lambda: True)
|
||||
monkeypatch.setattr("tools.voice_mode._import_audio",
|
||||
lambda: (MagicMock(), MagicMock()))
|
||||
|
||||
from tools.voice_mode import detect_audio_environment
|
||||
result = detect_audio_environment()
|
||||
|
||||
assert result["available"] is True
|
||||
assert result["warnings"] == []
|
||||
assert any("Docker" in n for n in result.get("notices", []))
|
||||
|
||||
def test_docker_with_pipewire_remote_allows_voice(self, monkeypatch):
|
||||
"""Docker with PIPEWIRE_REMOTE set should NOT block voice mode (#21203)."""
|
||||
monkeypatch.delenv("SSH_CLIENT", raising=False)
|
||||
monkeypatch.delenv("SSH_TTY", raising=False)
|
||||
monkeypatch.delenv("SSH_CONNECTION", raising=False)
|
||||
monkeypatch.delenv("PULSE_SERVER", raising=False)
|
||||
monkeypatch.setenv("PIPEWIRE_REMOTE", "/run/user/1000/pipewire-0")
|
||||
monkeypatch.setattr("hermes_constants.is_container", lambda: True)
|
||||
monkeypatch.setattr("tools.voice_mode._import_audio",
|
||||
lambda: (MagicMock(), MagicMock()))
|
||||
|
||||
from tools.voice_mode import detect_audio_environment
|
||||
result = detect_audio_environment()
|
||||
|
||||
assert result["available"] is True
|
||||
assert result["warnings"] == []
|
||||
assert any("Docker" in n for n in result.get("notices", []))
|
||||
|
||||
def test_docker_without_audio_forwarding_blocks_voice(self, monkeypatch):
|
||||
"""Docker without PULSE_SERVER/PIPEWIRE_REMOTE keeps blocking voice mode."""
|
||||
monkeypatch.delenv("SSH_CLIENT", raising=False)
|
||||
monkeypatch.delenv("SSH_TTY", raising=False)
|
||||
monkeypatch.delenv("SSH_CONNECTION", raising=False)
|
||||
monkeypatch.delenv("PULSE_SERVER", raising=False)
|
||||
monkeypatch.delenv("PIPEWIRE_REMOTE", raising=False)
|
||||
monkeypatch.setattr("hermes_constants.is_container", lambda: True)
|
||||
monkeypatch.setattr("tools.voice_mode._import_audio",
|
||||
lambda: (MagicMock(), MagicMock()))
|
||||
|
||||
from tools.voice_mode import detect_audio_environment
|
||||
result = detect_audio_environment()
|
||||
|
||||
assert result["available"] is False
|
||||
assert any("Docker" in w for w in result["warnings"])
|
||||
assert any("PULSE_SERVER" in w or "PIPEWIRE_REMOTE" in w for w in result["warnings"])
|
||||
|
||||
def test_termux_api_microphone_allows_voice_without_sounddevice(self, monkeypatch):
|
||||
monkeypatch.setenv("TERMUX_VERSION", "0.118.3")
|
||||
monkeypatch.setenv("PREFIX", "/data/data/com.termux/files/usr")
|
||||
|
|
|
|||
|
|
@ -102,10 +102,22 @@ def detect_audio_environment() -> dict:
|
|||
if any(os.environ.get(v) for v in ('SSH_CLIENT', 'SSH_TTY', 'SSH_CONNECTION')):
|
||||
warnings.append("Running over SSH -- no audio devices available")
|
||||
|
||||
# Docker/Podman container detection
|
||||
# Docker/Podman container detection — honor host audio forwarding.
|
||||
# When the user mounts a PulseAudio/PipeWire socket into the container
|
||||
# and points PULSE_SERVER / PIPEWIRE_REMOTE at it, audio works fine
|
||||
# (issue #21203). Only block when no forwarding is configured.
|
||||
from hermes_constants import is_container
|
||||
if is_container():
|
||||
warnings.append("Running inside Docker container -- no audio devices")
|
||||
if os.environ.get('PULSE_SERVER') or os.environ.get('PIPEWIRE_REMOTE'):
|
||||
notices.append("Running inside Docker container with host audio forwarding")
|
||||
else:
|
||||
warnings.append(
|
||||
"Running inside Docker container -- no audio devices.\n"
|
||||
" Forward host audio with one of:\n"
|
||||
" PulseAudio: -v /run/user/1000/pulse/native:/run/user/1000/pulse/native \\\n"
|
||||
" -e PULSE_SERVER=unix:/run/user/1000/pulse/native\n"
|
||||
" PipeWire: -e PIPEWIRE_REMOTE=/run/user/1000/pipewire-0"
|
||||
)
|
||||
|
||||
# WSL detection — PulseAudio bridge makes audio work in WSL.
|
||||
# Only block if PULSE_SERVER is not configured.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue