Two parsing bugs caught by Codex review on the Telnyx Media Streaming
PR:
Lifecycle webhook event names had a stray `call.` prefix that never
matched Telnyx's documented event types. Telnyx surfaces stream
lifecycle as `streaming.started` and `streaming.stopped` (no prefix);
stream errors arrive as `{event:"error"}` JSON frames over the
WebSocket, not as carrier webhooks. Drop the bogus
`call.streaming.failed` case from the webhook parser and add a new
`error` frame kind to the StreamFrameAdapter union so the realtime
handler can log failures instead of silently dropping them.
Telnyx WebSocket frames carry `stream_id` at the top level of the
envelope and `call_control_id` inside the `start` object; the
Telnyx adapter was reading `start.stream_id` (always undefined) and
defaulting `providerCallId` to the constructor-supplied value
regardless of what the carrier sent. Read both fields from the
documented locations and fall back to the constructor providerCallId
only when the carrier frame omits them.
Tests updated to reflect the carrier-documented frame shapes; new
fixture covers `{event:"error"}` round-trip through the adapter.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds tests across the touched surface: StreamFrameAdapter for both
Twilio (with streamSid) and Telnyx (without), the generalized
RealtimeAudioPacer carrying both envelopes, Telnyx provider
dial-time and answer-action streaming params with the
call.streaming.failed -> call.error mapping, manager
streamSessionIssuer wiring for Telnyx outbound, and the widened
realtime + telnyx config gate.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wires bidirectional PCMU WebSocket audio for Telnyx so realtime
providers (OpenAI Realtime, etc.) can drive Telnyx calls the same
way they drive Twilio. Telnyx attaches Media Streaming at dial
time and answer-action time per the documented canonical patterns
(no actions/streaming_start call needed).
New StreamFrameAdapter abstraction owns provider-shaped frame
parsing and outbound serialization, so realtime-handler.ts stays
carrier-agnostic. RealtimeAudioPacer is generalized to accept any
serializer. The provider-twilio realtime gate widens to accept
telnyx.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>