Skip to content

fix(voice): release the audio pause a finished speech was still holding - #2142

Closed
toubatbrian wants to merge 1 commit into
brian/clear-sink-before-resume-v2from
brian/release-pause-on-speech-done
Closed

fix(voice): release the audio pause a finished speech was still holding#2142
toubatbrian wants to merge 1 commit into
brian/clear-sink-before-resume-v2from
brian/release-pause-on-speech-done

Conversation

@toubatbrian

@toubatbrian toubatbrian commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Top of a four-PR stack: #2131#2132#2136#2142. Base: #2136 — review only the top commit; the diff against main includes #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 spurious agent_false_interruption for 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.ts fails on main (pausedSpeech still 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_task at agent_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 done messages per session.flush on 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.

@toubatbrian
toubatbrian requested a review from a team as a code owner July 28, 2026 01:53
@changeset-bot

changeset-bot Bot commented Jul 28, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 05d50d1

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 39 packages
Name Type
@livekit/agents Patch
@livekit/agents-plugin-anam Patch
@livekit/agents-plugin-anthropic Patch
@livekit/agents-plugin-assemblyai Patch
@livekit/agents-plugin-azure Patch
@livekit/agents-plugin-baseten Patch
@livekit/agents-plugin-bey Patch
@livekit/agents-plugin-cartesia Patch
@livekit/agents-plugin-cerebras Patch
@livekit/agents-plugin-deepgram Patch
@livekit/agents-plugin-did Patch
@livekit/agents-plugin-elevenlabs Patch
@livekit/agents-plugin-fishaudio Patch
@livekit/agents-plugin-google Patch
@livekit/agents-plugin-hedra Patch
@livekit/agents-plugin-hume Patch
@livekit/agents-plugin-inworld Patch
@livekit/agents-plugin-krisp Patch
@livekit/agents-plugin-lemonslice Patch
@livekit/agents-plugin-liveavatar Patch
@livekit/agents-plugin-livekit Patch
@livekit/agents-plugin-minimax Patch
@livekit/agents-plugin-mistral Patch
@livekit/agents-plugin-mistralai Patch
@livekit/agents-plugin-neuphonic Patch
@livekit/agents-plugin-openai Patch
@livekit/agents-plugin-perplexity Patch
@livekit/agents-plugin-phonic Patch
@livekit/agents-plugin-protoface Patch
@livekit/agents-plugin-resemble Patch
@livekit/agents-plugin-rime Patch
@livekit/agents-plugin-runway Patch
@livekit/agents-plugin-sarvam Patch
@livekit/agents-plugin-silero Patch
@livekit/agents-plugin-soniox Patch
@livekit/agents-plugin-tavus Patch
@livekit/agents-plugins-test Patch
@livekit/agents-plugin-trugen Patch
@livekit/agents-plugin-xai Patch

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

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

@toubatbrian
toubatbrian force-pushed the brian/release-pause-on-speech-done branch from 0382f6f to 65620fd Compare July 28, 2026 02:08
@toubatbrian
toubatbrian changed the base branch from main to brian/clear-sink-before-resume-v2 July 28, 2026 02:08
@toubatbrian toubatbrian changed the title fix(voice): release the audio pause a finished speech was still holding [barge-in 5/5] fix(voice): release the audio pause a finished speech was still holding Jul 28, 2026
@toubatbrian toubatbrian changed the title [barge-in 5/5] fix(voice): release the audio pause a finished speech was still holding [barge-in] fix(voice): release the audio pause a finished speech was still holding Jul 28, 2026
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>
@toubatbrian

Copy link
Copy Markdown
Contributor Author

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 session.flush with several done events. That is fixed client-side in #2146 and server-side in agent-gateway#1105.

Measured on its own, #2146's branch contains only main + #2144 and none of this chain, and it already takes transcript-ahead windows from 3 to 0 and worst lag from 26.8s to 0 across 3 runs. So this PR is not needed for that bug.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant