feat: add deterministic message interaction stages

This commit is contained in:
Xin Wang
2026-08-03 07:10:41 +08:00
parent 479a516546
commit 9daa46ed4d
26 changed files with 1356 additions and 414 deletions

View File

@@ -2,6 +2,8 @@
from __future__ import annotations
import asyncio
from collections import deque
from collections.abc import Awaitable, Callable
from loguru import logger
@@ -19,6 +21,7 @@ class CallEndCoordinator:
self._speaking = False
self._response_speech_started = False
self._tracked_speeches = 0
self._tracked_speech_completions: deque[asyncio.Future[None]] = deque()
self._finish_after_tracked_speech = False
self._finished = False
self._reason = "completed"
@@ -39,9 +42,12 @@ class CallEndCoordinator:
"""Wait for the next observed bot speech to finish."""
self._armed = True
def track_speech(self) -> None:
"""Register one fixed utterance before its TTSSpeakFrame is queued."""
def track_speech(self) -> Awaitable[None]:
"""Register fixed speech and return its transport completion signal."""
completion = asyncio.get_running_loop().create_future()
self._tracked_speech_completions.append(completion)
self._tracked_speeches += 1
return completion
async def arm_after_tracked_speech(self) -> None:
"""Finish after every already queued fixed utterance has played."""
@@ -73,6 +79,9 @@ class CallEndCoordinator:
self._speaking = False
if self._tracked_speeches > 0:
self._tracked_speeches -= 1
completion = self._tracked_speech_completions.popleft()
if not completion.done():
completion.set_result(None)
if (
self._finish_after_tracked_speech
and self._tracked_speeches == 0