-
#2157
f08ee06Thanks @cjol! - Improve voice lifecycle accuracy, diagnostics, and per-turn timing visibility.- Clear stale interim transcripts when calls start, end, disconnect, close, or fail during startup.
- Emit
speakingonly when the first server audio chunk is sent. - Add structured, content-free browser diagnostics and structured Worker error logging without reading arbitrary provider response bodies.
- Report transcriber startup and runtime failures through
onFatalError, structured client errors, and reliable call cleanup. - Preserve model finish reasons and distinguish no-output, output-limit, content-filtered, and model-error completions.
- Add stable typed per-turn timing summaries for speech, text, terminal outcomes, model streaming, reasoning exposed by the model stream, and overlapping TTS work through
VoiceClientand the React hooks. - Keep the existing four-field metrics wire shape compatible while making no-audio and streamed TTS accounting consistent.
- Update the bundled voice providers to propagate lifecycle failures and log errors consistently.
-
#2083
48eeba7Thanks @cjol! - DefineVoiceTurnContext.messagesas completed history before the current transcript for both text and audio turns, preventing duplicate user messages when following the documented prompt construction.Existing
onTurn()implementations:- If you pass
context.messagesdirectly as the complete LLM input, appendtranscriptexactly once. - If you already append
transcripttocontext.messages, no change is required. - Direct
getConversationHistory()calls insideonTurn()continue to include the current transcript.
- If you pass
-
#2004
0efd545Thanks @cjol! - Pass the fullkeytermsarray to Workers AI Flux and Nova-3 STT instead of only the first term. -
#2049
ce0e608Thanks @cjol! - Preserve spacing between streamed text segments separated by tool calls. Think messenger delivery and Voice now share the same boundary-aware text joining logic fromagents/chat.Existing users must:
- Replace imports of
textDeltaFromStreamChunk()from@cloudflare/think/messengerswithTextStreamCallback, passing it the complete structured stream events. - Upgrade to
agents@0.21.0when installing@cloudflare/think@0.16.0or@cloudflare/voice@0.3.6; both now requireagents >=0.20.2. - Update exact-text expectations if they relied on segments around tool calls being concatenated without a space.
- Replace imports of
- #1912
219d59bThanks @cjol! - Add AssemblyAI and ElevenLabs streaming STT providers for the voice pipeline.
-
#1909
63491bdThanks @cjol! - Honor the configured sample rate for rawpcm16audio payloads.Adds a
sampleRateoption toVoiceAgentOptions(default16000) that is declared in the serveraudio_configmessage.VoiceClientreads it (exposed via a newsampleRategetter) and constructsAudioBufferinstances at that rate for rawpcm16playback, so providers with a native rate other than 16 kHz (e.g. 24 kHz Gemini TTS) play at the correct speed. Falls back to 16 kHz when the server omits the field. -
#1891
d1cc317Thanks @korinne! - Add transcriber readiness so voice agents wait for streaming STT startup before entering listening state or running call-start hooks.
-
#1605
8bfebf0Thanks @cjol! - Support AI SDK fullStream responses in voice turns and warn when textStream is used. -
#1772
d4f27feThanks @mattzcarey! - Include each package's documentation in its published package. -
#1816
f18ff01Thanks @cjol! - Fix assistant speech playing back slow on a new turn after an idle gap.VoiceClientroutes playback through aMediaStreamAudioDestinationNode->HTMLAudioElementbridge, and reusing that element for a fresh burst after it had been idle between turns made the new turn resume at the wrong rate (audible as slow-motion that re-converges to normal over the turn). The bridge is now torn down and rebuilt once it has fully drained and been idle past a short threshold, so each turn plays through a freshly created element. Rebuilds never happen mid-turn, since chunks within a turn keep at least one source scheduled on the playback cursor.
- #1747
28653b3Thanks @cjol! - Fix audible clicks at audio chunk boundaries during agent speech.VoiceClientplayed each response chunk by starting it atcurrentTimeand waiting for itsendedevent before scheduling the next, so every chunk seam carried a few milliseconds of silence (event-loop latency plus the next chunk's setup) — audible as a periodic click, roughly one per chunk. Chunks are now scheduled back-to-back on the audio clock via a playback cursor (start(Math.max(currentTime, cursor))), so consecutive chunks butt together sample-tight. Because chunks can now be scheduled ahead of playback, the client tracks every scheduled source and stops them all on interrupt/end-call (previously only the single active source needed stopping), and playback counts as active until the last scheduled chunk finishes so barge-in detection keeps working through the scheduled tail.
- #1754
151d457Thanks @threepointone! - Stop fire-and-forget voice lifecycle handlers from leaking unhandled rejections on connection teardown. ThewithVoiceInputmixin dispatchesstart_call,end_call,interrupt, and transcript emission from the synchronousonMessagehandler without awaiting them, so a client dropping mid-operation (e.g. whilekeepAlive()'s alarm write is still in flight) could surface a retryable "Network connection lost." rejection. These background tasks now run through a teardown-aware helper that swallows expected connection-teardown errors and logs anything unexpected.
- #1711
a3a8d83Thanks @cjol! - AddoutputDeviceIdandsetOutputDevice()for routing assistant playback to a selected audio output device when the browser supports sink selection.
- #1568
c7649acThanks @cjol! - Avoid emitting empty assistant transcript entries when a voice turn produces no response text.
- #1478
2c7d91bThanks @whoiskatrin! - Add anenabledoption touseVoiceAgentso React apps can delay creating and connecting aVoiceClientuntil async prerequisites such as capability tokens are ready.
-
#1458
84cb429Thanks @whoiskatrin! - Fix Workers AI STT session edge cases for Flux and Nova 3.Flux now preserves the latest non-empty turn transcript from turn lifecycle events so an
EndOfTurnevent with an emptytranscriptcan still emit the completed utterance. FluxStartOfTurnalso drives server-side barge-in so model-detected user speech aborts active LLM/TTS playback promptly. Nova 3 now defensively normalizes finalized segment state before reading it to avoid stale teardown messages throwing during abnormal close paths. -
#1462
5f6214dThanks @whoiskatrin! - FixwithVoicetext streaming for AI SDKtextStreamresponses so TTS audio is produced whenonTurn()returnsstreamText(...).textStreamdirectly.
-
ca510d4Thanks @threepointone! - Tighten theagentspeer dependency floor from>=0.9.0to>=0.11.7to reflect the current monorepo set we actually test against. Upper bound (<1.0.0) is unchanged.No runtime change in
@cloudflare/voiceitself. The visible effect for consumers: pairing the latest@cloudflare/voicewith a staleagents(<0.11.7) now produces a peer warning where it previously did not. That's the intended signal —agentsversions older than 0.11.7 are no longer tested against this@cloudflare/voice.
- #1313
08da191Thanks @threepointone! - Publish with correct peer dependency ranges foragents(wide ranges were being overwritten to tight^0.x.yby the pre-publish script)
- #1310
bd0346eThanks @threepointone! - Fix peer dependency ranges foragents— published packages incorrectly had tight^0.10.xranges instead of the intended>=0.8.7 <1.0.0/>=0.9.0 <1.0.0, causing install warnings withagents@0.11.0. Also changedupdateInternalDependenciesfrom"patch"to"minor"in changesets config to prevent the ranges from being overwritten on future releases.
-
#1293
16769b0Thanks @threepointone! - Switch to per-call continuous STT sessions. Breaking API change.The transcriber session is now created at
start_calland lives for the entire call duration. The model handles turn detection — no client-sidestart_of_speech/end_of_speechrequired for STT. Voice agents usekeepAliveto prevent DO eviction during calls.New API:
transcriberproperty replacesstt,streamingStt, andvadcreateTranscriber(connection)hook for runtime model switchingWorkersAIFluxSTT— per-call Flux sessions (recommended forwithVoice)WorkersAINova3STT— per-call Nova 3 streaming sessions (recommended forwithVoiceInput)queryoption onVoiceClientOptions— pass query params to the WebSocket URL (e.g. for model selection)- Throws at
start_callif no transcriber is configured - Duplicate
start_callis silently ignored when already in a call
Removed:
stt(batch STT),streamingStt(per-utterance streaming),vad(server-side VAD)WorkersAISTT,WorkersAIVAD,pcmToWavprerollMs,vadThreshold,vadPushbackSeconds,vadRetryMs,minAudioBytesoptionsVoiceInputAgentOptionstypebeforeTranscribehook (audio is fed continuously, not in batches)vad_msandstt_msfrom pipeline metrics- Hibernation support (
withVoiceandwithVoiceInputnow requireAgent, not partyserverServer)
c5ca556Thanks @threepointone! - Replace wildcard*peer dependencies with real version ranges:agentsto>=0.9.0 <1.0.0andpartysocketto^1.0.0.
- #1198
dde826eThanks @threepointone! - Fix TypeScript 6 declaration emit forwithVoiceandwithVoiceInputmixin functions. TS6 enforces TS4094 which disallows#privatemembers in exported anonymous class types. Added explicit return type interfaces (VoiceAgentMixinMembers,VoiceInputMixinMembers) so the generated.d.tsonly exposes the public API surface.
8fd45cfThanks @threepointone! - Initial publish (again)
d384339Thanks @threepointone! - Initial publish