From 8e1637d6c732676e8179a1c624c93e3c6d3c02f7 Mon Sep 17 00:00:00 2001 From: Mark Backman Date: Thu, 18 Sep 2025 10:08:29 -0400 Subject: [PATCH] DailyTransport sip_call_transfer now automatically receives session_id --- CHANGELOG.md | 5 +++++ src/pipecat/transports/daily/transport.py | 22 ++++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e937eaf05..64d22b697 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Fixed `DailyTransport.sip_call_transfer()` to automatically use the session + ID from the `on_dialin_connected` event, when not explicitly provided. Now + supports cold transfers (from incoming dial-in calls) by automatically + tracking session IDs from connection events. + - Fixed a memory leak in `SmallWebRTCTransport`. In `aiortc`, when you receive a `MediaStreamTrack` (audio or video), frames are produced asynchronously. If the code never consumes these frames, they are queued in memory, causing a diff --git a/src/pipecat/transports/daily/transport.py b/src/pipecat/transports/daily/transport.py index 8c9874a47..1568a12bd 100644 --- a/src/pipecat/transports/daily/transport.py +++ b/src/pipecat/transports/daily/transport.py @@ -359,6 +359,7 @@ class DailyTransportClient(EventHandler): self._transcription_ids = [] self._transcription_status = None self._dial_out_session_id: str = "" + self._dial_in_session_id: str = "" self._joining = False self._joined = False @@ -823,6 +824,16 @@ class DailyTransportClient(EventHandler): Args: settings: SIP call transfer settings. """ + session_id = ( + settings.get("sessionId") or self._dial_out_session_id or self._dial_in_session_id + ) + if not session_id: + logger.error("Unable to transfer SIP call: 'sessionId' is not set") + return + + # Update 'sessionId' field. + settings["sessionId"] = session_id + future = self._get_event_loop().create_future() self._client.sip_call_transfer(settings, completion=completion_callback(future)) await future @@ -1141,6 +1152,7 @@ class DailyTransportClient(EventHandler): Args: data: Dial-in connection data. """ + self._dial_in_session_id = data["sessionId"] if "sessionId" in data else "" self._call_event_callback(self._callbacks.on_dialin_connected, data) def on_dialin_ready(self, sip_endpoint: str): @@ -1157,6 +1169,9 @@ class DailyTransportClient(EventHandler): Args: data: Dial-in stop data. """ + # Cleanup only if our session stopped. + if data.get("sessionId") == self._dial_in_session_id: + self._dial_in_session_id = "" self._call_event_callback(self._callbacks.on_dialin_stopped, data) def on_dialin_error(self, data: Any): @@ -1165,6 +1180,9 @@ class DailyTransportClient(EventHandler): Args: data: Dial-in error data. """ + # Cleanup only if our session errored out. + if data.get("sessionId") == self._dial_in_session_id: + self._dial_in_session_id = "" self._call_event_callback(self._callbacks.on_dialin_error, data) def on_dialin_warning(self, data: Any): @@ -1199,7 +1217,7 @@ class DailyTransportClient(EventHandler): data: Dial-out stop data. """ # Cleanup only if our session stopped. - if data["sessionId"] == self._dial_out_session_id: + if data.get("sessionId") == self._dial_out_session_id: self._dial_out_session_id = "" self._call_event_callback(self._callbacks.on_dialout_stopped, data) @@ -1210,7 +1228,7 @@ class DailyTransportClient(EventHandler): data: Dial-out error data. """ # Cleanup only if our session errored out. - if data["sessionId"] == self._dial_out_session_id: + if data.get("sessionId") == self._dial_out_session_id: self._dial_out_session_id = "" self._call_event_callback(self._callbacks.on_dialout_error, data)