You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
reuse the recorder's cached InputStream only while its active liveness signal remains true
close and rebuild inactive or unprobeable streams before the next recording, using the existing timeout-bounded shutdown path
still attempt close() when stop() rejects an already-inactive stream
add behavioral regression coverage for active reuse, inactive replacement, and failed liveness probes
This addresses the dead cached recorder mechanism isolated in #75417. It is intentionally complementary to #74152, which covers the separate manual push-to-talk wake-listener handoff and does not touch tools/voice_mode.py.
four unrelated platform-specific failures were excluded from that related-suite run after reproducing each on clean upstream/main (two WSL playback mocks, the macOS beep gate, and the missing local TFLite runtime case)
uv run ruff check tools/voice_mode.py tests/tools/test_voice_mode.py
Thanks for the focused regression fix. The premise is confirmed on current main: tools/voice_mode.py:896-897 reuses every non-null cached stream without checking whether it remains active, and tools/voice_mode.py:1096-1101 skips close() if stop() raises. The PR's liveness gate and independent close attempt directly cover both paths, with behavioral tests in tests/tools/test_voice_mode.py:427-480.
The only production caller of _ensure_stream() remains AudioRecorder.start() at tools/voice_mode.py:1082; no sibling recorder lifecycle path was found. The checked-out main is an ancestor of the PR base, so no surrounding-code rework is indicated.
Reviewed: AudioRecorder._ensure_stream rebuilds an inactive/broken sounddevice stream (reuse active, close+rebuild inactive, tolerate broken liveness probes) — the CLI voice-loop analogue of the desktop's mic re-arm class. Note transcribe_recording in the same file serves the desktop /api/audio/transcribe endpoint, but the recorder-stream change does not affect the desktop transcription path (desktop recordings come from the browser's MediaRecorder, not AudioRecorder).
Tests on PR head: 3 new TestAudioRecorder cases cover reuse/rebuild/probe-failure; consistent with the existing mock harness.
No desktop-class gap; recommend merge. (Lane 01/03 may want to run the full tests/tools/test_voice_mode.py suite for the CLI loop.)
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
area/streamingStreaming responses: gateway delivery, provider wirecomp/cliCLI entry point, hermes_cli/, setup wizardP2Medium — degraded but workaround existssweeper:blast-containedSweeper blast radius: contained — one narrow path / opt-in / few userstool/ttsText-to-speech and transcriptiontype/bugSomething isn't working
4 participants
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.
Summary
InputStreamonly while itsactiveliveness signal remains trueclose()whenstop()rejects an already-inactive streamThis addresses the dead cached recorder mechanism isolated in #75417. It is intentionally complementary to #74152, which covers the separate manual push-to-talk wake-listener handoff and does not touch
tools/voice_mode.py.Refs #75417
Validation
scripts/run_tests.sh tests/tools/test_voice_mode.py -q -k 'ensure_stream'— 3 passedupstream/main(two WSL playback mocks, the macOS beep gate, and the missing local TFLite runtime case)uv run ruff check tools/voice_mode.py tests/tools/test_voice_mode.pypython -m py_compile tools/voice_mode.py tests/tools/test_voice_mode.pygit diff upstream/main...HEAD --check