Problem
The mute (and other) voice control words are only checked inside the transcription paths — real-time interim, hands-free finalize, and tap-to-talk final (packages/sdk/src/voice/use-voice.ts handleResult). All three only run when the main STT is actively recording a user turn.
So the mute word does NOT fire when:
- The co-pilot / agent is speaking (TTS playing) — the mic is stopped, nothing is transcribed.
- The agent is working / processing between utterances — the mic is paused (
pausedForThinking).
- The mic is muted — obviously nothing is being recorded.
In practice: exactly the moments a user wants to say "mute" (to shut the agent up while it talks or thinks) are the moments the mute word is unreachable. The command is gated on the recording state machine.
Root cause
Control-word detection is coupled to the main recording pipeline. When that pipeline is stopped/paused (TTS, thinking, muted), there is no listener at all, so control words are never checked.
Fix
A continuous, always-on background control-word listener, separate from the main recording pipeline:
- A lightweight browser-dictation listener dedicated to control words (mute / stop), active whenever voice is engaged — regardless of app state (TTS playing, agent processing, mic paused/muted).
- Separate from the main STT so it never interferes with normal recording (it yields to the main recorder while the main path is actively capturing a turn, which already checks control words).
- Checks spoken words against the mute list at any time.
- On a mute word: immediately mute the mic AND cancel any TTS playing.
- Wired through
useVoice, so it works in both the agent Assistant chat and the Coder Co-pilot (both consume the same hook).
Acceptance Criteria
Related
Problem
The mute (and other) voice control words are only checked inside the transcription paths — real-time interim, hands-free finalize, and tap-to-talk final (
packages/sdk/src/voice/use-voice.tshandleResult). All three only run when the main STT is actively recording a user turn.So the mute word does NOT fire when:
pausedForThinking).In practice: exactly the moments a user wants to say "mute" (to shut the agent up while it talks or thinks) are the moments the mute word is unreachable. The command is gated on the recording state machine.
Root cause
Control-word detection is coupled to the main recording pipeline. When that pipeline is stopped/paused (TTS, thinking, muted), there is no listener at all, so control words are never checked.
Fix
A continuous, always-on background control-word listener, separate from the main recording pipeline:
useVoice, so it works in both the agent Assistant chat and the Coder Co-pilot (both consume the same hook).Acceptance Criteria
useVoice).Related