feat(plugins): add Gnani plugin#2004
Open
rosetta-livekit-bot[bot] wants to merge 11 commits into
Open
Conversation
🦋 Changeset detectedLatest commit: 02a10db The changes in this PR will be included in the next version bump. This PR includes changesets to release 37 packages
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 |
Co-authored-by: Cursor <cursoragent@cursor.com>
Classify websocket frames by protocol metadata, decode only supported PCM containers, emit audio incrementally, and honor configured timeout and drain windows. Co-authored-by: Cursor <cursoragent@cursor.com>
Reject premature provider closes, cancel pending sockets promptly, and decode streamed WAV containers without corrupting final audio framing. Co-authored-by: Cursor <cursoragent@cursor.com>
Preserve per-payload WAV decoding and make WebSocket settlement idempotent across real abort ordering and every receive outcome. Co-authored-by: Cursor <cursoragent@cursor.com>
Settle active receives directly and forcefully tear down established sockets on intentional cancellation while preserving graceful handshake and provider closure paths. Co-authored-by: Cursor <cursoragent@cursor.com>
Reject unsupported option mutations, expose complete public types, and verify payload and metrics parity. Co-authored-by: Cursor <cursoragent@cursor.com>
Limit the public audio contract to decodable PCM formats and preserve request-scoped model metadata for in-flight metrics. Co-authored-by: Cursor <cursoragent@cursor.com>
Keep caller aborts quiet while distinguishing timeout and provider failures across REST and SSE requests. Co-authored-by: Cursor <cursoragent@cursor.com>
Apply caller and timeout provenance while reading REST and SSE provider error bodies without losing status details. Co-authored-by: Cursor <cursoragent@cursor.com>
Preserve caller, timeout, provider, and network provenance while reading non-2xx REST STT responses. Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Ports
livekit/agents#6004to the Node.js SDK by adding@livekit/agents-plugin-gnani, since agents-js has no existing Gnani plugin.Python parity and intentional adaptations
The implementation preserves the Python plugin's option names and defaults after idiomatic camelCase adaptation, REST multipart fields, WebSocket headers, voice/model updates, provider/model metadata, and usage metrics.
The public TTS output contract is intentionally narrower than Python: this JS plugin exposes only decoded linear PCM in raw or WAV containers because it has no encoded-audio decoder. Unsupported encoded formats are rejected rather than advertised or treated as PCM.
Protocol correctness
API, options, and metrics
TTS.updateOptions()accepts only Python-equivalent mutablevoiceandmodelfields.updateOptions()while subsequent requests use the new model.Validation
Exact-head Cue voice evidence
Verified remote head
02a10db247665ca503c645d25dcc3f627779e2a2with Cue sessionsid_e4df0b706ef6using a disclosed deterministic, protocol-compatible Gnani boundary becauseGNANI_API_KEYwas unavailable.Predicate:
user_input_transcribed(.is_final=true) -> agent_state_changed(.new_state="AS_SPEAKING") -> conversation_item_added(.item.message.role="ASSISTANT") -> agent_state_changed(.new_state="AS_LISTENING")[30s]The predicate resolved in 4080 ms. Persisted events show the final transcription, speaking transition, assistant commit (
The exact head Gnani voice path works correctly.), and return to listening. Provider logs captured the TTS request, two binary PCM chunks totaling 32,000 bytes, and terminalcompleteframe.Both flushed WAVs are non-silent:
917762bb22152fcce219506d6c8b1d005cff4826cd98af8d5ca08075437ac8f0.1e61c0802415feeb66859dcfb87a611766aad08330a95caf77bcc679e1365a63.56e081171ec85259c6f17023bc5ba8f264a9c5c5a0d412f1c3ac22e805da7fe9.883b25c783a6a808373ef14ebc68cd1c328152eb820cd288b8a1b7fb38af3e01.017ef335be31e32725559c57ef674cb712e490e5ed22b02aed79ea13c47419b7.Earlier successful sessions
sid_ec92f760dc6a(at9934a770) andsid_0f763aa3c02bare historical evidence only;sid_e4df0b706ef6is the exact-head run.Ported from livekit/agents#6004