Skip to content

fix(elevenlabs): end server vad turns - #1745

Merged
chenghao-mou merged 2 commits into
1.5.0from
fix-elevenlabs-end-server-vad-turns
Jun 10, 2026
Merged

chenghao-mou merged 2 commits into
1.5.0from
fix-elevenlabs-end-server-vad-turns

Conversation

@rosetta-livekit-bot

@rosetta-livekit-bot rosetta-livekit-bot Bot commented Jun 10, 2026 •

Copy link
Copy Markdown
Contributor

Ports livekit/agents#5872 to agents-js.

Summary

  • map unset ElevenLabs realtime server VAD (undefined) and explicit null to manual commit strategy
  • use VAD commit strategy only when server VAD options are provided
  • emit END_OF_SPEECH after final committed transcripts when server VAD is enabled
  • update existing ElevenLabs realtime tests only

Testing

  • pnpm build
  • pnpm test -- plugins/elevenlabs/src/stt.test.ts

@changeset-bot

changeset-bot Bot commented Jun 10, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 6879c5d

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a 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 found 1 potential issue.

View 2 additional findings in Devin Review.

Open in Devin Review

Comment thread plugins/elevenlabs/src/stt.ts Outdated
Comment on lines +807 to +810
if (this.#opts.serverVad !== null) {
this.queue.put({ type: stt.SpeechEventType.END_OF_SPEECH });
this.#speaking = false;
}

@devin-ai-integration devin-ai-integration Bot Jun 10, 2026 •

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.

🚩 #speaking state is not reset on WebSocket reconnect

When updateOptions({ serverVad: ... }) triggers a reconnect via #reconnectEvent (line 639-641 in the run method), the #speaking boolean is not reset. If a reconnect happens mid-speech (e.g., after a partial_transcript but before a committed_transcript), the new WebSocket connection starts with #speaking = true, which means a subsequent partial_transcript won't emit START_OF_SPEECH. The new code at line 807-810 actually improves this situation for the VAD case, since each committed transcript now resets #speaking to false. However, the general reconnect-without-reset pattern is still a potential pre-existing issue for manual mode.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

expected since the framework already observed the SOS. Otherwise we have to send a fake EOS before reconnecting.

@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 found 1 new potential issue.

View 4 additional findings in Devin Review.

Open in Devin Review

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.

🚩 Shared #opts reference between STT and SpeechStream enables live updates but has a narrow race window

The SpeechStream stores a direct reference to the STT instance's #opts object (plugins/elevenlabs/src/stt.ts:488). This means STT.updateOptions() modifying this.#opts.serverVad at line 437 is immediately visible to SpeechStream.#processStreamEvent() at line 799 — even before the WebSocket reconnects with the new commit_strategy. During the brief window between updateOptions() and the reconnect completing, the stream may process events using new serverVad state while the server is still operating under the old commit strategy. This is a pre-existing pattern (the old code had the same shared reference) and the window is very narrow, but worth noting for robustness.

(Refers to lines 497-503)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Factually correct, benign in both toggle directions

@chenghao-mou
chenghao-mou merged commit 0daf4ef into 1.5.0 Jun 10, 2026
2 checks passed
@chenghao-mou
chenghao-mou deleted the fix-elevenlabs-end-server-vad-turns branch June 10, 2026 15:48
tinalenguyen added a commit that referenced this pull request Jun 23, 2026
Squashed local branch work, reconciled with the latest remote state:

- Refactor ToolContext to parity class taking a list of Tool | Toolset (#1517)
- feat(agents): add Toolset support to ToolContext and AgentActivity (#1525)
- feat(agents): add beta end call tool (#1474)
- fix(agents): thread FlushSentinel through Agent.create llmNode types
- fix(elevenlabs): end server vad turns (#1745)
- Add Inworld delivery mode inference TTS option (#1749)
- Don't retain recorded events when recording is disabled (#1750)
- fix(deepgram): validate updated model with stored language on updateOptions
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