fix(realtime): complete workflow message transitions

This commit is contained in:
Xin Wang
2026-08-05 11:25:50 +08:00
parent 17b5e10ed1
commit 11374238f3
4 changed files with 115 additions and 7 deletions

View File

@@ -35,6 +35,11 @@ from services.workflow_engine import WorkflowEngine
MAX_AUTOMATIC_HOPS = 50
AGENT_ENTRY_TRIGGER = (
"[工作流内部事件,不是用户消息] 当前 Agent 节点已激活。"
"请严格依据当前 instructions 立即生成进入该节点时的回复,"
"不要提及或复述本事件。"
)
ToolHandler = Callable[[dict[str, Any]], Awaitable[RealtimeToolResult]]
@@ -80,10 +85,18 @@ class RealtimeWorkflowOutput(WorkflowOutput):
**({"nodeId": node_id} if node_id else {}),
}
)
return await self._realtime.speak_fixed(
track_speech = getattr(self._runtime.call_end, "track_speech", None)
playback_completion: Awaitable[None] | None = None
if callable(track_speech):
playback_completion = track_speech()
provider_completion = await self._realtime.speak_fixed(
content,
suppress_transcript=True,
)
# Message playback policy and deterministic continuation must use the
# transport boundary. Provider response.done only means generation
# has finished; audio may still be buffered at the output transport.
return playback_completion or provider_completion
class WorkflowRealtimeController:
@@ -138,7 +151,7 @@ class WorkflowRealtimeController:
allow_visible_actions=True,
)
if activation.continue_response:
await self._runtime.realtime.request_response()
await self._request_agent_entry_response()
async def on_client_ready(self) -> None:
await self._output.mark_client_ready()
@@ -160,7 +173,7 @@ class WorkflowRealtimeController:
if activation and activation.after_output:
await activation.after_output()
elif activation and activation.continue_response:
await self._runtime.realtime.request_response()
await self._request_agent_entry_response()
return SessionVariableUpdate(
changed=changed,
dynamic_variables=self._store.public_values(),
@@ -321,7 +334,13 @@ class WorkflowRealtimeController:
if activation.after_output:
await activation.after_output()
elif activation.continue_response:
await self._runtime.realtime.request_response()
await self._request_agent_entry_response()
async def _request_agent_entry_response(self) -> None:
"""Give provider inference a temporary turn for Agent entry speech."""
await self._runtime.realtime.request_response(
trigger_text=AGENT_ENTRY_TRIGGER,
)
async def _follow_edge(
self,