refactor: explicit kind=='final' check in async-tool routing

Replaces the implicit "final happens last" pattern in
_process_completed_function_calls with an explicit
`if async_payload.kind == "final":` block in both AWSNovaSonicLLMService
and OpenAIRealtimeLLMService. Adds a trailing defensive `continue` so
async-tool messages with an unrecognized kind don't fall through to the
regular tool-result handling block — clearer at the call site, and safer
against future additions to AsyncToolMessageKind.
This commit is contained in:
Paul Kompfner
2026-05-08 15:43:37 -04:00
parent 72d0fb418a
commit ad0f0a1294
2 changed files with 25 additions and 11 deletions

View File

@@ -645,11 +645,18 @@ class AWSNovaSonicLLMService(LLMService[AWSNovaSonicLLMAdapter]):
error_msg="Nova Sonic does not support streamed async tool results.", error_msg="Nova Sonic does not support streamed async tool results.",
) )
continue continue
# kind == "final": deliver via the formal toolResult channel if async_payload.kind == "final":
# — same path as a synchronous tool result, just delayed. # Deliver via the formal toolResult channel — same path
if send_new_results: # as a synchronous tool result, just delayed.
await self._send_tool_result(async_payload.tool_call_id, async_payload.result) if send_new_results:
self._completed_tool_calls.add(async_payload.tool_call_id) await self._send_tool_result(
async_payload.tool_call_id, async_payload.result
)
self._completed_tool_calls.add(async_payload.tool_call_id)
continue
# Defensive: any async-tool message must not fall through
# to the regular tool-result block below, even if it
# carries a kind we don't recognize.
continue continue
# Look for newly-completed "regular" (as opposed to async-tool) results # Look for newly-completed "regular" (as opposed to async-tool) results

View File

@@ -1068,12 +1068,19 @@ class OpenAIRealtimeLLMService(LLMService[OpenAIRealtimeLLMAdapter]):
error_msg="OpenAI Realtime does not support streamed async tool results.", error_msg="OpenAI Realtime does not support streamed async tool results.",
) )
continue continue
# kind == "final": deliver via the formal tool-result channel if async_payload.kind == "final":
# — same path as a synchronous tool result, just delayed. # Deliver via the formal tool-result channel — same path
if send_new_results: # as a synchronous tool result, just delayed.
sent_new_result = True if send_new_results:
await self._send_tool_result(async_payload.tool_call_id, async_payload.result) sent_new_result = True
self._completed_tool_calls.add(async_payload.tool_call_id) await self._send_tool_result(
async_payload.tool_call_id, async_payload.result
)
self._completed_tool_calls.add(async_payload.tool_call_id)
continue
# Defensive: any async-tool message must not fall through
# to the regular tool-result block below, even if it
# carries a kind we don't recognize.
continue continue
# Look for newly-completed "regular" (as opposed to async-tool) results # Look for newly-completed "regular" (as opposed to async-tool) results