Skip to content

fix(openai): recover stale Responses WebSocket connections - #2104

Open
rosetta-livekit-bot[bot] wants to merge 6 commits into
mainfrom
fun-utilize-spring
Open

fix(openai): recover stale Responses WebSocket connections#2104
rosetta-livekit-bot[bot] wants to merge 6 commits into
mainfrom
fun-utilize-spring

Conversation

@rosetta-livekit-bot

@rosetta-livekit-bot rosetta-livekit-bot Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Summary

  • recover a cached stale OpenAI Responses WebSocket by evicting it and reconnecting before one bounded resend
  • restore ConnectionPoolOptions.connectionError source compatibility and add atomic reuse metadata
  • make pool prewarming and Responses connection attempts observable, idempotent, cancellable, and awaited during shutdown
  • preserve request/response IDs, metrics, typed upgrade errors, and post-open WebSocket error handling
  • add deterministic local WebSocket/TCP coverage for stale recovery, fresh failures, 401 classification, cancellation, retry bounds, and socket/listener cleanup
  • retain an OpenAI plugin patch changeset

Python parity

Compared with the Python stale-Responses-WebSocket recovery implementation and current JS behavior. Recovery remains restricted to known stale failures on reused sockets; fresh websocket_closed, ordinary authentication 401s, and fresh send failures are not hidden or retried. The reconnect happens before resend, retries are bounded, and failures preserve normal provider classification.

JS additionally tracks and cancels eager/background connection work through the generic ConnectionPool lifecycle.

Tests

  • strict red-green API compatibility coverage for optional connectionError callbacks and omitted rejection values
  • ConnectionPool/type tests — 22 passed
  • Responses WebSocket tests — all focused local-boundary tests passed, credentialed cases skipped
  • full agents suite — 110 files, 1,467 passed and 5 skipped
  • full OpenAI plugin suite — 81 passed and 7 skipped
  • pnpm typecheck — 33/33 tasks passed
  • exact-head pnpm build — 40/40 tasks passed
  • changed-file lint, Prettier, IDE diagnostics, and git diff --check — clean
  • independent final gates — Spec compliance: APPROVED and Code quality: APPROVED, no findings

API Extractor remains blocked only by documented base-branch namespace-export/missing-config issues; declaration generation passes.

Deterministic transport verification

Credential-free loopback fixtures prove the actual transport predicates:

  • cached stale socket request indices [0, 0, 1], showing reuse then reconnect before resend
  • fresh websocket_closed, ordinary auth 401, and fresh send failures make one attempt and remain visible
  • stale reused-send retries remain bounded
  • hanging upgrade cancellation leaves zero live sockets
  • keep-alive unauthorized upgrade is explicitly terminated and preserves x-request-id
  • malformed post-open frame reaches one typed request failure with no uncaught EventEmitter error or listener leak
  • pending response cancellation closes its socket

Cue voice is inapplicable: a voice turn cannot create or observe the stale provider WebSocket/401 condition. The local transport boundaries are the behavior-level evidence for this port.


Ported from livekit/agents#6583

@rosetta-livekit-bot
rosetta-livekit-bot Bot requested a review from a team as a code owner July 24, 2026 03:34
@changeset-bot

changeset-bot Bot commented Jul 24, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 9459222

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-openai 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-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

@rosetta-livekit-bot
rosetta-livekit-bot Bot requested a review from longcw July 24, 2026 03:34

@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 and others added 4 commits July 24, 2026 15:00
Preserve connection-pool API compatibility while making eager and foreground WebSocket connection work cancellable and leak-free.

Co-authored-by: Cursor <cursoragent@cursor.com>
Only reused Responses sockets qualify for stale recovery, and failed HTTP upgrades now terminate their handshake without leaking listeners or sockets.

Co-authored-by: Cursor <cursoragent@cursor.com>
Transfer error handling to the Responses wrapper before connect cleanup so protocol failures remain typed and cannot escape as uncaught events.

Co-authored-by: Cursor <cursoragent@cursor.com>
@toubatbrian

Copy link
Copy Markdown
Contributor

Completed Rosetta repair and verification at exact head 7a6727c421c7dd5249162d1b6f03bd7b4451ab22.

The branch restores ConnectionPool API compatibility; makes connect/prewarm lifecycle cancellable and shutdown-safe; restricts recovery to stale reused sockets; preserves IDs/metrics/errors; and closes upgrade/post-open socket and listener leaks. Deterministic real local TCP/WebSocket fixtures, focused/full tests, typecheck, 40-task build, independent spec/quality review, and exact-head CI are green. Zero unresolved threads; mergeable. Cue is inapplicable because voice cannot create or observe the stale provider WebSocket condition.

@toubatbrian
toubatbrian enabled auto-merge (squash) July 25, 2026 05:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant