* Resolve an issue with direct socket connections using the wrong event data.
* Resolve the formatting issus in the provider file
* chore: fix import ordering with ruff
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Nir Simionovich <nirs@cloudonix.io>
Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(ari): pre-register ext channel id and defer bridge to its StasisStart
Two race conditions in the inbound ARI flow could leave a call silent:
1. Bridging both channels immediately after creating the ext media leg
raced against the ext channel entering the Stasis application; slow
chan_websocket handshakes produced "Channel not in Stasis application"
422 errors on addChannel.
2. Asterisk could fire StasisStart for the ext channel before the
externalMedia POST response returned, so _is_ext_channel returned
False and the event was dropped as an unknown outbound call.
Fixes:
- Generate the ext channel id as dograh-ext-<uuid> client-side and pass
it to Asterisk via the channelId query param. Mark the ext channel,
set its channel->run mapping, register the pending bridge entry, and
persist gathered_context.ext_channel_id all before the POST.
- Defer the bridge to a new _complete_bridge_after_ext_ready handler
triggered by the ext channel's own StasisStart. Both channels are
guaranteed in Stasis by then, so addChannel cannot 422.
- On POST failure or channelId mismatch, roll back the pending entry
and ERROR loudly.
* fix: replace in-memory dict with redis storage
* feat: configurable ElevenLabs base URL for Data Residency (#269)
Adds a `base_url` field to `ElevenlabsTTSConfiguration` so users on an
ElevenLabs Data Residency plan (EU, etc.) can point Dograh at the
regional endpoint instead of the hardcoded global one. Defaults to
`https://api.elevenlabs.io`, preserving existing behaviour. The
service factory rewrites the HTTP scheme to WSS when constructing the
WebSocket TTS service.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: fix drift
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Conference-based transfer for Telnyx with a two-step flow:
- transfer_call dials the destination with a per-transfer webhook URL.
- On call.answered, the webhook seeds a conference with the destination's
live call_control_id and publishes DESTINATION_ANSWERED.
- TelnyxConferenceStrategy joins the caller into the conference on
pipeline teardown (EndTaskReason.TRANSFER_CALL).
- On post-answer destination hangup, the webhook hangs up the caller —
Telnyx's create_conference doesn't accept end_conference_on_exit on
the seed leg, so we tear down the bridge ourselves.
TransferContext gains optional workflow_run_id (for webhook→provider
resolution in multi-config orgs) and conference_id (set on answer,
rd by the strategy).
Also fixes the transfer tool's provider lookup to go through
get_telephony_provider_for_run instead of the deprecated org-default
shim, which was returning the wrong provider in multi-config orgs.
* filter out local sdp candidates on non local environment
* feat: add FORCE_TURN_RELAY variable
* add FORCE_TURN_RELAY option in docker-compose
* fix: fix github workflow
If there are multiple telephony configurations, the form number should be initialized from the campaigns given telephonic configuration rather than the organization default telephonic configuration.
* feat: add headless widget for deployment
* feat: call callbacks at the right time
* feat: add onCallConnected & onCallDisconnected callback
* feat: add a button with text for floating widget
* feat: add headless widget for deployment
* feat: call callbacks at the right time
* feat: add onCallConnected & onCallDisconnected callback
* feat: add a button with text for floating widget
* docs: web widget
* fix: format issue in pre-pr drift check
* fix: fix CD to rely on pipecat dev dependey
* chore: update message
---------
Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
* chore: bump pipecat version and fix tests
* chore: add github workflow to run tests
* fix: install reqirements.dev.txt in test script
* fix: fix api-test action
* feat: add integration test
* test: add integration tests
* test: add test for function call mute strategy
Telnyx's bidirectional stream uses different codecs per direction:
- Dograh → Telnyx: what we declare via `stream_bidirectional_codec`
- Telnyx → Dograh: whatever the PSTN leg negotiated (PCMA for UK,
Europe, India termination; PCMU for US), announced as
`media_format.encoding` on the WebSocket start message.
We hardcoded both directions on the serializer to PCMU, so any call
whose PSTN leg used PCMA arrived as A-law bytes that we decoded
through a μ-law table → static for the entire call.
`handle_websocket` now extracts `media_format.encoding` from the
start message and threads it through `transport_kwargs`. The
serializer uses it for the Telnyx → Dograh direction; the
Dograh → Telnyx direction stays pinned to PCMU to match the
unchanged `stream_bidirectional_codec` in the dial/answer payloads.
Note: pipecat's `TelnyxFrameSerializer` names its params from the
call's POV, not Dograh's — `inbound_encoding` is what we send into
the call, `outbound_encoding` is what we receive. Easy to mix up.
For outbound calls, the caller phone is stored as "phone_number" in
initial_context. For inbound calls, it is stored as "caller_number".
The usage log extraction only checked "phone_number", so inbound
caller numbers were never surfaced.
Add a fallback to also check "caller_number" when "phone_number" is absent.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>