fix(realtime): unblock fixed speech after tool calls

This commit is contained in:
Xin Wang
2026-08-05 09:28:21 +08:00
parent bee1e97cdb
commit 55381c5162
3 changed files with 97 additions and 20 deletions

View File

@@ -46,13 +46,20 @@ RealtimeToolDispatcher = Callable[
[str, dict[str, Any], str], Awaitable[RealtimeToolResult]
]
SendProviderEvent = Callable[[dict[str, Any]], Awaitable[None]]
WaitForResponseBoundary = Callable[[], Awaitable[Any]]
class RealtimeToolSession:
"""Serialize provider calls and answer every call id at most once."""
def __init__(self, send_event: SendProviderEvent) -> None:
def __init__(
self,
send_event: SendProviderEvent,
*,
wait_for_response_boundary: WaitForResponseBoundary | None = None,
) -> None:
self._send_event = send_event
self._wait_for_response_boundary = wait_for_response_boundary
self._dispatcher: RealtimeToolDispatcher | None = None
self._handled_call_ids: set[str] = set()
self._lock = asyncio.Lock()
@@ -105,6 +112,12 @@ class RealtimeToolSession:
},
}
)
# Function-call argument events arrive before the provider's
# response.done boundary. Starting another response sooner is
# rejected by both supported realtime providers. The provider
# receive loop stays free while this background task waits.
if self._wait_for_response_boundary is not None:
await self._wait_for_response_boundary()
if result.after_output is not None:
await result.after_output()
if result.continue_response: