Skip to content

Improve voice diagnostics and turn lifecycle visibility - #2157

Merged
cjol merged 1 commit into
mainfrom
voice-dx-feedback
Aug 25, 2026
Merged

Improve voice diagnostics and turn lifecycle visibility#2157
cjol merged 1 commit into
mainfrom
voice-dx-feedback

Conversation

@cjol

@cjol cjol commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

This PR makes voice failures and turn latency diagnosable across @cloudflare/voice and its continuous-STT providers. It adds structured errors, opt-in content-free lifecycle diagnostics, and stable per-turn timing summaries, while correcting stale interim text, completion outcomes, and speaking-status fidelity.

Why

  • Voice callers currently receive generic connection or no-response strings for materially different failures, while useful provider details can collapse to values such as [object Object].
  • The client can retain stale interim text after a call ends, STT startup can appear to succeed before its provider is ready, and empty, truncated, filtered, and failed model turns are difficult to distinguish.
  • The four coarse voice statuses are application UI state, not a suitable diagnostic model. Expanding that enum would break consumers and still would not describe overlapping STT, model, reasoning, TTS, audio, and playback work.
  • Diagnostics therefore remain an opt-in, content-free, open event stream. Stable timing data uses a separate typed per-turn summary derived from the same scoped lifecycle trackers.
  • The implementation uses explicit input, turn, and model trackers rather than logger injection or async-local context, keeping ownership local and compatible with Workers and provider callbacks.

Public API Surface

Symbol Kind Notes
VoiceDiagnosticsOptions Interface Enables server diagnostics and browser-console forwarding with diagnostics.browserConsole.
VoiceDiagnosticEvent Interface Bounded, content-free diagnostic record. Event names and metadata are intentionally open.
VoiceTurnMetrics Interface Stable terminal summary containing correlated speech, model, reasoning, TTS, first-audio, and total durations.
VoiceTurnSource, VoiceTurnOutcome Types Dimensions used to interpret each terminal timing summary.
VoiceError, VoiceErrorCode, VoiceErrorStage Types Structured STT lifecycle errors while retaining the existing string error event.
VoiceCompletionOutcome and related types Types Distinguish no output, output limits, content filtering, and model errors.
VoiceConnectionDiagnostic Type Carries transport causes and WebSocket close information to the client.
TranscriberSessionOptions.onFatalError Optional callback Lets continuous-STT providers report startup and runtime failure.
VoiceClient.turnMetrics and turnmetrics Property and event Expose the latest stable per-turn timing summary.
useVoiceAgent().turnMetrics, useVoiceInput().turnMetrics Hook properties Expose the same latest terminal summary in React.
normalizeVoiceError, voiceErrorMessage, logVoiceError Functions in @cloudflare/voice/errors Normalize, bound, redact, and log unknown provider failures.

All additions are additive. withVoice and withVoiceInput accept the optional diagnostics configuration without requiring a corresponding client option.

Architectural Changes

STT callbacks -> input scope -> turn scope -> model/TTS/audio scopes
                                      |-> open diagnostic events
                                      `-> stable terminal timing summary

server diagnostic event -> reserved voice wire message -> browser console
client microphone/playback event -----------------------> browser console
  • Stable timing summaries and non-stable diagnostics consume the same lifecycle state rather than parsing console output or diagnostic event names.
  • Server and browser clocks stay separate. Client receive and playback events remain diagnostic-only and are never subtracted from Worker timestamps.
  • Reasoning text remains discarded, but standard reasoning lifecycle chunks contribute content-free timing landmarks.

Code Changes

@cloudflare/voice

  • Adds bounded error normalization and a dedicated @cloudflare/voice/errors export, with redaction for credentials, headers, request bodies, transcripts, prompts, tool data, audio, and raw provider payloads.
  • Waits for continuous-STT readiness and returns failed startup or runtime sessions to idle with structured, retryable errors.
  • Clears interim transcript state at real call and connection boundaries while preserving it during playback interruption.
  • Tracks input, turn, model, reasoning, TTS, and audio lifecycles with generated turn IDs, including abort, replacement, skipped, empty, and error paths.
  • Emits speaking immediately before the first server audio send instead of when response generation begins.
  • Preserves model finish reasons internally so callers can distinguish empty, truncated, filtered, and failed completions.
  • Keeps legacy four-field pipeline metrics intact and adds timing-only terminal summaries for speech and text turns.

Voice providers

  • AssemblyAI, Deepgram, ElevenLabs, Plivo, Telnyx, and Twilio use the shared bounded logger instead of logging arbitrary provider objects or bodies.
  • Continuous-STT providers report fatal connection lifecycle failures through onFatalError; providers with asynchronous startup expose readiness to the voice mixins.
  • Workers AI Flux and Nova-3 propagate startup and runtime connection failures through the same lifecycle.

Documentation

  • Documents structured outcomes, diagnostics opt-in, diagnostic safety boundaries, timing origins and exclusions, and the stable per-turn client and React surfaces.

Compatibility

  • Existing wire messages, the four-value VoiceStatus union, the string error event, and legacy VoicePipelineMetrics remain supported.
  • speaking now means that the server is sending the first audio chunk, rather than that response generation has started. Applications using it as a pre-audio generation indicator should use diagnostics instead.
  • Provider callback additions are optional. Existing custom transcribers continue to compile without changes.

@changeset-bot

changeset-bot Bot commented Aug 24, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5acad68

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

This PR includes changesets to release 7 packages
Name Type
@cloudflare/voice Minor
@cloudflare/voice-assemblyai Minor
@cloudflare/voice-elevenlabs Minor
@cloudflare/voice-deepgram Minor
@cloudflare/voice-telnyx Minor
@cloudflare/voice-plivo Patch
@cloudflare/voice-twilio 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

@pkg-pr-new

pkg-pr-new Bot commented Aug 24, 2026

Copy link
Copy Markdown

Open in StackBlitz

agents

npm i https://pkg.pr.new/cloudflare/agents@2157

@cloudflare/ai-chat

npm i https://pkg.pr.new/cloudflare/agents/@cloudflare/ai-chat@2157

@cloudflare/channels

npm i https://pkg.pr.new/cloudflare/agents/@cloudflare/channels@2157

@cloudflare/codemode

npm i https://pkg.pr.new/cloudflare/agents/@cloudflare/codemode@2157

hono-agents

npm i https://pkg.pr.new/cloudflare/agents/hono-agents@2157

@cloudflare/shell

npm i https://pkg.pr.new/cloudflare/agents/@cloudflare/shell@2157

@cloudflare/think

npm i https://pkg.pr.new/cloudflare/agents/@cloudflare/think@2157

@cloudflare/voice

npm i https://pkg.pr.new/cloudflare/agents/@cloudflare/voice@2157

@cloudflare/worker-bundler

npm i https://pkg.pr.new/cloudflare/agents/@cloudflare/worker-bundler@2157

commit: 5acad68

@cjol
cjol force-pushed the voice-dx-feedback branch from c9a85e5 to 5acad68 Compare August 25, 2026 17:06
@cjol
cjol marked this pull request as ready for review August 25, 2026 17:07
@cjol
cjol merged commit f08ee06 into main Aug 25, 2026
5 checks passed
@cjol
cjol deleted the voice-dx-feedback branch August 25, 2026 17:11
@github-actions github-actions Bot mentioned this pull request Aug 25, 2026
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.

1 participant