fix(voice): release the audio pause a finished speech was still holding - #2142
fix(voice): release the audio pause a finished speech was still holding#2142toubatbrian wants to merge 1 commit into
Conversation
🦋 Changeset detectedLatest commit: 05d50d1 The changes in this PR will be included in the next version bump. This PR includes changesets to release 39 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
0382f6f to
65620fd
Compare
The paused-speech record taken out when user audio activity pauses a reply was never cleared when that reply finished, so it outlived its owner: the sink stayed gated and a later VAD blip arming the resume timer acted on a speech that was already over. Port Python's _scheduling_task block (agent_activity.py:1630-1637), which drops the record, cancels the false-interruption timer and resumes the output once the generation completes. Co-authored-by: Cursor <cursoragent@cursor.com>
65620fd to
05d50d1
Compare
|
Closing: this came out of a misdiagnosis on my side. The reported symptom — the agent's audio and its transcript disagreeing after a barge-in, with the lag compounding over a conversation — is caused by the inference gateway answering a single Measured on its own, #2146's branch contains only The defect it fixes is real and has its own red/green test, and the branch is not deleted. If it ever shows up in practice it is worth reproposing on its own merit rather than as a barge-in fix. |
Top of a four-PR stack: #2131 → #2132 → #2136 → #2142. Base: #2136 — review only the top commit; the diff against
mainincludes #2131 through #2136.Problem
When user audio activity pauses the agent mid-reply, the activity records which speech the pause belongs to, so the false-interruption timer can resume that same speech if the overlap turns out to be a backchannel. That record is never cleared when the speech itself finishes, so it outlives its owner.
Two consequences, both measured directly on
main: the audio sink stays gated indefinitely after a cleanly finished reply, and the next VAD blip to arm the resume timer acts on a speech that is already over — emitting a spuriousagent_false_interruptionfor a completed reply.Fix
Port the block Python already has. The scheduling loop drops the paused-speech record, cancels the false-interruption timer, and resumes the audio output as soon as the paused speech's generation completes.
Testing
paused_speech_completion.test.tsfails onmain(pausedSpeechstill points at the finished handle) and passes here. Voice suite green at 565 tests.Python parity
This is a missing port, not a design difference. Python has three
audio_output.resume()sites and JS had two; the absent one is_scheduling_taskatagent_activity.py:1630-1637, whose own comment reads "clear paused speech after generation done". The JS loop went straight from awaiting the generation to clearing_currentSpeech. The added block is that Python block, in the same position.Scope — read this before merging
Found while investigating a live report of stale audio replaying after a barge-in. That report has since been traced, and not to this: the inference gateway emits multiple
donemessages persession.flushon some TTS paths, the client returns on the first, and the next reply then reads the previous reply's audio off a socket that was handed back to the pool mid-synthesis. Switching only the TTS provider makes the symptom vanish with no code change. Fixes are in flight separately (#2144, #2146).The reported symptom still reproduces with this whole stack applied. This is a real defect in the pause lifecycle on its own terms, with its own red/green test, and it should be read and merged as that and nothing more.