Skip to content

Conversation

@toubatbrian
Copy link
Contributor

@toubatbrian toubatbrian commented Jan 23, 2026

Summary

  • Fixed a race condition in StreamAdapter that caused stt_error: "Stream is closed" during agent handover
  • Added isStreamClosedError() utility function for consistent error handling
  • Fixed pre-existing build error in @livekit/agents-plugins-test
  • Upgraded sharp 0.34.3 → 0.34.5 to fix libvips version conflict causing flaky agent behavior

Problem

  1. Agent handover with non-streaming STTs crashed with "Stream is closed"
  2. Two versions of @img/sharp-libvips-darwin-arm64 (1.2.0 and 1.2.4) caused ObjC class collisions and flaky agent behavior

Test Plan

  • Tested agent handover with OpenAI STT
  • Build passes
  • Lint passes

Summary by CodeRabbit

  • Bug Fixes

    • Fixed race condition handling stream closure errors during agent handover
    • Resolved build error in test plugin for audio data handling
  • Chores

    • Upgraded sharp dependency to address stability and platform compatibility issues

✏️ Tip: You can customize this high-level summary in your review settings.

@changeset-bot
Copy link

changeset-bot bot commented Jan 23, 2026

🦋 Changeset detected

Latest commit: e273f4b

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

This PR includes changesets to release 18 packages
Name Type
@livekit/agents-plugins-test Patch
@livekit/agents Patch
@livekit/agents-plugin-anam Patch
@livekit/agents-plugin-baseten Patch
@livekit/agents-plugin-cartesia Patch
@livekit/agents-plugin-deepgram Patch
@livekit/agents-plugin-elevenlabs Patch
@livekit/agents-plugin-google Patch
@livekit/agents-plugin-inworld Patch
@livekit/agents-plugin-neuphonic Patch
@livekit/agents-plugin-openai Patch
@livekit/agents-plugin-resemble Patch
@livekit/agents-plugin-rime Patch
@livekit/agents-plugin-bey Patch
@livekit/agents-plugin-hedra Patch
@livekit/agents-plugin-livekit Patch
@livekit/agents-plugin-silero 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

@coderabbitai
Copy link

coderabbitai bot commented Jan 23, 2026

📝 Walkthrough

Walkthrough

Fix race-condition where StreamAdapter could call endInput() on an already-closed VAD stream during agent handover; add isStreamClosedError() utility to detect and ignore stream-closed errors; update test plugin to pass an ArrayBuffer to AudioByteStream.write(); bump sharp from 0.34.3 to 0.34.5.

Changes

Cohort / File(s) Summary
Changeset
\.changeset/wet-carpets-clean.md
Adds changeset entry marking patches for @livekit/agents-plugins-test and @livekit/agents with fix note about handling VAD stream closed error.
Stream error handling
agents/src/utils.ts, agents/src/stt/stream_adapter.ts
Add isStreamClosedError(error) utility; wrap VAD endInput() in try/catch and return early when error indicates stream already closed.
Test plugin audio input
plugins/test/src/stt.ts
Convert merged Int16Array audio segment to ArrayBuffer before calling AudioByteStream.write() to match expected input type.
Dependency bump
agents/package.json
Upgrade sharp from 0.34.3 to 0.34.5 (libvips/macOS ObjC collision fixes).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • lukasIO
  • theomonnom
  • 1egoman

Poem

🐰 In tangled streams I hopped around,
I caught the error, safe and sound,
A little check, a gentle stop,
No more crashes — handover hops! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the two main changes: fixing VAD stream closed error during handover and upgrading sharp dependency.
Description check ✅ Passed The description covers key changes and includes a problem statement and test plan, but the pre-review checklist items are incomplete with unchecked boxes rather than documented completion.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8487aeb and e273f4b.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (2)
  • .changeset/wet-carpets-clean.md
  • agents/package.json
🔇 Additional comments (2)
.changeset/wet-carpets-clean.md (1)

1-11: LGTM!

The changeset is well-structured and comprehensive. It correctly:

  • Lists both affected packages (@livekit/agents-plugins-test and @livekit/agents) as patch releases
  • Documents all key changes: the race condition fix, the new utility function, the sharp upgrade, and the test plugin fix
  • Provides clear context for the libvips version conflict resolution
agents/package.json (1)

76-76: Verify sharp 0.34.5 availability and security status.

The patch version upgrade from 0.34.3 to 0.34.5 to resolve libvips conflicts is valid. Version 0.34.5 is available on npm and not deprecated. The exact version pinning (no ^) is appropriate for packages with native bindings like sharp.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
plugins/test/src/stt.ts (1)

61-67: Pre-existing issue: endInput() called inside the loop.

The stream.endInput() call is inside the for loop, meaning it's called after every frame instead of once after all frames are pushed. This appears to be a pre-existing bug unrelated to this PR's changes.

         const input = async () => {
           for (const frame of frames) {
             stream.pushFrame(frame);
             await new Promise((resolve) => setTimeout(resolve, 5));
-            stream.endInput();
           }
+          stream.endInput();
         };
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ef35009 and 8487aeb.

📒 Files selected for processing (4)
  • .changeset/wet-carpets-clean.md
  • agents/src/stt/stream_adapter.ts
  • agents/src/utils.ts
  • plugins/test/src/stt.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/agent-core.mdc)

Add SPDX-FileCopyrightText and SPDX-License-Identifier headers to all newly added files with '// SPDX-FileCopyrightText: 2025 LiveKit, Inc.' and '// SPDX-License-Identifier: Apache-2.0'

Files:

  • agents/src/utils.ts
  • plugins/test/src/stt.ts
  • agents/src/stt/stream_adapter.ts
**/*.{ts,tsx}?(test|example|spec)

📄 CodeRabbit inference engine (.cursor/rules/agent-core.mdc)

When testing inference LLM, always use full model names from agents/src/inference/models.ts (e.g., 'openai/gpt-4o-mini' instead of 'gpt-4o-mini')

Files:

  • agents/src/utils.ts
  • plugins/test/src/stt.ts
  • agents/src/stt/stream_adapter.ts
**/*.{ts,tsx}?(test|example)

📄 CodeRabbit inference engine (.cursor/rules/agent-core.mdc)

Initialize logger before using any LLM functionality with initializeLogger({ pretty: true }) from '@livekit/agents'

Files:

  • agents/src/utils.ts
  • plugins/test/src/stt.ts
  • agents/src/stt/stream_adapter.ts
🧠 Learnings (2)
📚 Learning: 2026-01-16T14:33:39.551Z
Learnt from: CR
Repo: livekit/agents-js PR: 0
File: .cursor/rules/agent-core.mdc:0-0
Timestamp: 2026-01-16T14:33:39.551Z
Learning: Applies to examples/src/test_*.ts : For plugin component debugging (STT, TTS, LLM), create test example files prefixed with `test_` under the examples directory and run with `pnpm build && node ./examples/src/test_my_plugin.ts`

Applied to files:

  • plugins/test/src/stt.ts
📚 Learning: 2026-01-16T14:33:39.551Z
Learnt from: CR
Repo: livekit/agents-js PR: 0
File: .cursor/rules/agent-core.mdc:0-0
Timestamp: 2026-01-16T14:33:39.551Z
Learning: Applies to **/{examples,test}/**/*.test.ts : Include both basic streaming and tool calling tests to verify full LLM functionality

Applied to files:

  • plugins/test/src/stt.ts
🧬 Code graph analysis (2)
agents/src/utils.ts (1)
agents/src/transcription.ts (1)
  • Error (302-306)
agents/src/stt/stream_adapter.ts (1)
agents/src/utils.ts (1)
  • isStreamClosedError (685-690)
🔇 Additional comments (4)
.changeset/wet-carpets-clean.md (1)

1-6: LGTM!

The changeset correctly marks both affected packages as patches and provides a clear description of the fix.

agents/src/stt/stream_adapter.ts (1)

72-82: LGTM! Clean fix for the race condition.

The try/catch guard around endInput() correctly handles the case where close() is called while forwardInput is still running. The early return for stream-closed errors is appropriate, and re-throwing other errors preserves the original error handling behavior.

plugins/test/src/stt.ts (1)

143-150: LGTM! Correct ArrayBuffer conversion.

The conversion properly handles the Int16Array view by using byteOffset and byteLength to extract the exact portion of the underlying buffer. This is the correct way to convert a typed array view to a standalone ArrayBuffer.

agents/src/utils.ts (1)

678-690: LGTM! Well-documented utility for stream cleanup.

The function correctly handles the type narrowing and checks for both error messages that are actually thrown throughout the codebase (in vad.ts, tokenizer.ts, token_stream.ts, and stt.ts). The JSDoc clearly explains the purpose and usage context.

One consideration: String-based error matching is somewhat fragile if upstream libraries change their error messages. For critical paths, consider verifying these exact strings match what the stream implementations actually throw.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@toubatbrian
Copy link
Contributor Author

@codex

@toubatbrian toubatbrian requested review from a team and rektdeckard January 23, 2026 22:52
@toubatbrian toubatbrian changed the title fix: handle VAD stream closed error during agent handover fix: handle VAD stream closed error during handover and upgrade sharp Jan 23, 2026
@chatgpt-codex-connector
Copy link

Codex Review: Didn't find any major issues. Another round soon, please!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@toubatbrian toubatbrian merged commit 3544bfa into main Jan 24, 2026
8 checks passed
@toubatbrian toubatbrian deleted the brian/fix-js branch January 24, 2026 00:09
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.

3 participants