feat: unify debug runtime timelines

This commit is contained in:
Xin Wang
2026-08-13 09:30:43 +08:00
parent 7c18cea16d
commit eb111a3890
21 changed files with 1380 additions and 533 deletions
+56 -6
View File
@@ -17,6 +17,7 @@ from services.conversation_history import ConversationRecorder
from services.pipecat.call_lifecycle import (
CallEndCoordinator,
EndCallAfterSpeechProcessor,
call_end_trace_event,
)
from services.pipecat.service_factory import (
config_with_resource,
@@ -208,6 +209,7 @@ def _call_end_state_frame(
*,
interruptible: bool,
voice_interruptible: bool,
reason: str = "",
) -> OutputTransportMessageUrgentFrame:
"""Build the client event used to render the pending call-end state."""
return OutputTransportMessageUrgentFrame(
@@ -216,10 +218,30 @@ def _call_end_state_frame(
"state": state,
"interruptible": interruptible,
"voice_interruptible": voice_interruptible,
**({"reason": reason} if reason else {}),
}
)
def _call_lifecycle_trace_frame(
state: str,
*,
reason: str = "",
interruptible: bool = False,
voice_interruptible: bool = False,
) -> OutputTransportMessageUrgentFrame:
"""Build one persistent runtime record for the call-ending lifecycle."""
return OutputTransportMessageUrgentFrame(
message=call_end_trace_event(
state,
reason=reason,
interruptible=interruptible,
voice_interruptible=voice_interruptible,
)
)
async def run_pipeline(
transport,
cfg: AssistantConfig,
@@ -307,6 +329,12 @@ async def run_pipeline(
if worker is None:
return
logger.info(f"结束通话: reason={reason}")
await worker.queue_frame(
_call_lifecycle_trace_frame(
"ended",
reason=reason,
)
)
await worker.queue_frame(
OutputTransportMessageUrgentFrame(
message={"type": "call-ended", "reason": reason}
@@ -318,13 +346,21 @@ async def run_pipeline(
worker = worker_holder.get("worker")
if worker is None:
return
voice_interruptible = interruptible and current_enable_interrupt
await worker.queue_frame(
_call_end_state_frame(
state,
interruptible=interruptible,
voice_interruptible=(
interruptible and current_enable_interrupt
),
voice_interruptible=voice_interruptible,
reason=call_end.reason,
)
)
await worker.queue_frame(
_call_lifecycle_trace_frame(
state,
reason=call_end.reason,
interruptible=interruptible,
voice_interruptible=voice_interruptible,
)
)
@@ -1043,6 +1079,12 @@ async def run_realtime_pipeline(
if worker is None:
return
logger.info(f"结束 Realtime 通话: reason={reason}")
await worker.queue_frame(
_call_lifecycle_trace_frame(
"ended",
reason=reason,
)
)
await worker.queue_frame(
OutputTransportMessageUrgentFrame(
message={"type": "call-ended", "reason": reason}
@@ -1054,13 +1096,21 @@ async def run_realtime_pipeline(
worker = worker_holder.get("worker")
if worker is None:
return
voice_interruptible = interruptible and cfg.enableInterrupt
await worker.queue_frame(
_call_end_state_frame(
state,
interruptible=interruptible,
voice_interruptible=(
interruptible and cfg.enableInterrupt
),
voice_interruptible=voice_interruptible,
reason=call_end.reason,
)
)
await worker.queue_frame(
_call_lifecycle_trace_frame(
state,
reason=call_end.reason,
interruptible=interruptible,
voice_interruptible=voice_interruptible,
)
)