fix(wake): auto capture keeps the backend mic when one exists

With capture:auto the desktop always preferred client streaming, so a local
desktop with a working backend mic silently switched from PortAudio to
getUserMedia default-device — dropping wake_word.input_device selection
(#74363). A ready backend input now wins under auto; client capture is the
fallback for a preferring surface on a mic-less backend, and capture:client
still forces streaming.

Also removes the dead auto branch (both arms returned local) and lets the
client-feed test skip cleanly when numpy is absent.
This commit is contained in:
Brooklyn Nicholson
2026-08-05 10:06:49 -06:00
parent d401c27edf
commit 60808dcf72
2 changed files with 15 additions and 9 deletions
+6 -2
View File
@@ -641,7 +641,11 @@ def test_resolve_capture_mode_auto_and_prefer_client(monkeypatch):
assert ww.resolve_capture_mode({"capture": "auto"}, force_local=True) == "local"
monkeypatch.setattr(ww, "_local_input_device_ready", lambda: True)
assert ww.resolve_capture_mode({"capture": "auto"}) == "local"
assert ww.resolve_capture_mode({"capture": "auto"}, prefer_client=True) == "client"
# A working backend mic wins under auto even for a preferring surface, so
# local desktops keep PortAudio + wake_word.input_device selection.
assert ww.resolve_capture_mode({"capture": "auto"}, prefer_client=True) == "local"
# Explicit client still forces streaming (backend mic exists but is wrong).
assert ww.resolve_capture_mode({"capture": "client"}, prefer_client=True) == "client"
def test_requirements_client_capture_without_local_mic(monkeypatch):
@@ -674,7 +678,7 @@ def test_requirements_client_capture_without_local_mic(monkeypatch):
def test_client_capture_feed_fires(monkeypatch, tmp_path):
import numpy as np
np = pytest.importorskip("numpy")
monkeypatch.setattr(ww, "_build_engine", lambda cfg: _FakeEngine(fire=True))
monkeypatch.setattr(ww, "_lock_path", lambda: tmp_path / "wake.lock")
+9 -7
View File
@@ -269,15 +269,17 @@ def resolve_capture_mode(
return "client"
if raw == "local":
return "local"
# auto
if prefer_client:
return "client"
# Prefer local when a PortAudio input exists. Without an explicit client
# preference (desktop remote), stay on local so CLI/TUI/status still
# require a server mic instead of advertising a capture path only the
# desktop can feed.
# auto: a working backend input always wins so local desktops keep
# PortAudio and the configured ``input_device`` selection. Client capture
# is the fallback for a preferring surface (desktop remote) on a backend
# with no usable mic — the headless VPS/Cloud case.
if _local_input_device_ready():
return "local"
if prefer_client:
return "client"
# No local mic and no client preference (CLI/TUI): stay local so status
# reports the real requirement instead of advertising a capture path
# nothing will feed.
return "local"