Skip to content

Add dynamic endpointing to the Node.js voice pipeline#1284

Open
u9g wants to merge 1 commit intomainfrom
rosetta/issue-74
Open

Add dynamic endpointing to the Node.js voice pipeline#1284
u9g wants to merge 1 commit intomainfrom
rosetta/issue-74

Conversation

@u9g
Copy link
Copy Markdown
Contributor

@u9g u9g commented Apr 21, 2026

This PR was created by Rosetta.

Tracking issue: https://github.com/livekit/rosetta/issues/74
Source implementation: https://github.com/livekit/agents/blob/main/livekit-agents/livekit/agents/voice/endpointing.py
Source tests: https://github.com/livekit/agents/blob/main/tests/test_endpointing.py
Docs: https://docs.livekit.io/reference/agents/turn-handling-options/#endpointingoptions-usage

Summary

  • add the Python-style dynamic endpointing tracker to the Node voice runtime so endpointing delays adapt to observed pause timing instead of staying fixed
  • wire the new tracker into audio recognition and agent activity so turnHandling.endpointing.mode = 'dynamic' changes live turn completion behavior
  • port the source endpointing parity tests into agents/src/voice/endpointing.test.ts and update the nearby audio-recognition tests for the new constructor shape

Port the Python dynamic endpointing tracker so Node sessions can adapt turn-ending delays from observed pause timing. Add the source-parity endpointing tests and wire the new runtime into audio recognition and agent activity.
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 21, 2026

⚠️ No Changeset found

Latest commit: 36d0ee1

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

@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


Rosetta Bot seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

Devin Review found 5 potential issues.

View 5 additional findings in Devin Review.

Open in Devin Review

private isInterruptionDetectionEnabled: boolean;
private isInterruptionByAudioActivityEnabled: boolean;
private isDefaultInterruptionByAudioActivityEnabled: boolean;
private interruptionDetected = false;
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.

🟡 Missing // Ref: Python reference comment on interruptionDetected state additions

Per CLAUDE.md rules, every JS change that corresponds to a Python change must carry an inline // Ref: python <relative-file-path> - <line-range> lines comment directly above the relevant line(s). The new interruptionDetected field and its assignment in onInterruptionOverlappingSpeech are clearly ported from the Python agent and lack the required reference comment.

Open in Devin Review

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

this.onError(ev);

private readonly onInterruptionOverlappingSpeech = (ev: OverlappingSpeechEvent): void => {
this.interruptionDetected = ev.isInterruption;
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.

🟡 Missing // Ref: Python reference comment on interruptionDetected assignment in onInterruptionOverlappingSpeech

Per CLAUDE.md rules, every JS change that corresponds to a Python change must carry an inline // Ref: comment. The new line this.interruptionDetected = ev.isInterruption; inside the onInterruptionOverlappingSpeech handler is ported from Python and lacks the required reference comment.

Open in Devin Review

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

});
if (this.isInterruptionDetectionEnabled && this.audioRecognition) {
this.audioRecognition.onStartOfAgentSpeech();
this.audioRecognition.onStartOfAgentSpeech(replyStartedSpeakingAt);
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.

🟡 Missing // Ref: Python reference comment on onStartOfAgentSpeech call-site change in ttsTask

Per CLAUDE.md rules, every JS change that corresponds to a Python change must carry an inline // Ref: comment. The call to this.audioRecognition.onStartOfAgentSpeech(replyStartedSpeakingAt) was changed from the no-arg form this.audioRecognition.onStartOfAgentSpeech() to pass a timestamp — a Python-ported behavioral change — but has no // Ref: comment.

Open in Devin Review

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

});
if (this.isInterruptionDetectionEnabled && this.audioRecognition) {
this.audioRecognition.onStartOfAgentSpeech();
this.audioRecognition.onStartOfAgentSpeech(agentStartedSpeakingAt);
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.

🟡 Missing // Ref: Python reference comment on onStartOfAgentSpeech call-site change in _pipelineReplyTaskImpl

Per CLAUDE.md rules, every JS change that corresponds to a Python change must carry an inline // Ref: comment. The call to this.audioRecognition.onStartOfAgentSpeech(agentStartedSpeakingAt) was changed from the no-arg form to pass a timestamp — a Python-ported behavioral change — but has no // Ref: comment.

Open in Devin Review

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

Comment thread agents/src/voice/agent_activity.ts
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.

2 participants