fix: prevent pipeline freezes when sending endframe (#77)

* fix: dont cancel task if call is already ending

* Update pipecat
This commit is contained in:
Abhishek 2025-12-10 08:22:37 +07:00 committed by GitHub
parent 0a8ce3f644
commit 909c258b6a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 44 additions and 20 deletions

View file

@ -81,6 +81,7 @@ class PipecatEngine:
self._workflow_run_id = workflow_run_id
self._initialized = False
self._client_disconnected = False
self._call_disposed = False
self._current_node: Optional[Node] = None
self._gathered_context: dict = {}
self._user_response_timeout_task: Optional[asyncio.Task] = None
@ -182,7 +183,9 @@ class PipecatEngine:
async def transition_func(function_call_params: FunctionCallParams) -> None:
"""Inner function that handles the node change tool calls"""
logger.info(f"LLM Function Call EXECUTED: {name}")
logger.info(f"Function: {name} -> transitioning to node: {transition_to_node}")
logger.info(
f"Function: {name} -> transitioning to node: {transition_to_node}"
)
logger.info(f"Arguments: {function_call_params.arguments}")
try:
@ -472,6 +475,15 @@ class PipecatEngine:
Centralized method to send EndTaskFrame with metadata including
call_transfer_context and call_context_vars
"""
if self._call_disposed or self._client_disconnected:
# Call is already disposed and client disconnected
logger.debug(
f"Not sending EndFrame since call is already disposed: Call Disposed: {self._call_disposed} Client Disconnected: {self._client_disconnected}"
)
return
self._call_disposed = True
frame_to_push = CancelFrame() if abort_immediately else EndFrame()
# Customer disposition code using their mapping
@ -700,10 +712,14 @@ class PipecatEngine:
"""Accumulate LLM text frames to build reference text."""
self._current_llm_reference_text += text
async def handle_client_disconnected(self):
def handle_client_disconnected(self):
"""Handle client disconnected event."""
self._client_disconnected = True
def is_call_disposed(self):
"""Check whether a call has been disposed by the engine"""
return self._call_disposed
async def get_call_disposition(self) -> Optional[str]:
"""Get the disconnect reason set by the engine."""
if self._call_disposition: