feat: add stateful responses API
This commit is contained in:
@@ -187,6 +187,7 @@ class WorkflowBrain(BaseBrain):
|
||||
self._next_message_token = 1
|
||||
self._pending_message: _MessageContinuation | None = None
|
||||
self._realtime_controller: WorkflowRealtimeController | None = None
|
||||
self._restored_text_node_id: str | None = None
|
||||
|
||||
async def greeting(self, _cfg: AssistantConfig) -> str:
|
||||
"""Workflow opening speech belongs to an explicit Message or Agent."""
|
||||
@@ -274,6 +275,18 @@ class WorkflowBrain(BaseBrain):
|
||||
if self._realtime_controller is not None:
|
||||
await self._realtime_controller.start()
|
||||
return
|
||||
if self._restored_text_node_id:
|
||||
node_id = self._restored_text_node_id
|
||||
self._restored_text_node_id = None
|
||||
self._state.enter(node_id, WorkflowStatus.WAITING_USER)
|
||||
await self._emit_node_active(node_id)
|
||||
await self._emit_variables(reason="restored", node_id=node_id)
|
||||
if self._manager is None:
|
||||
raise RuntimeError("Workflow FlowManager 尚未初始化")
|
||||
node_config = await self._resolve_path(node_id)
|
||||
await self._activate_node_config(node_config, initialize=True)
|
||||
logger.info(f"工作流文本状态已恢复: 当前节点={self._manager.current_node}")
|
||||
return
|
||||
self._state.enter(self._engine.start_id, WorkflowStatus.STARTING)
|
||||
await self._emit_node_active(self._engine.start_id)
|
||||
await self._emit_variables(
|
||||
@@ -287,6 +300,33 @@ class WorkflowBrain(BaseBrain):
|
||||
await self._activate_node_config(node_config, initialize=True)
|
||||
logger.info(f"工作流模式启用: 当前节点={self._manager.current_node}")
|
||||
|
||||
def restore_text_state(self, snapshot: dict[str, Any]) -> None:
|
||||
"""Restore one stable Responses API workflow node before connecting."""
|
||||
if not snapshot:
|
||||
return
|
||||
if snapshot.get("type") != "workflow":
|
||||
raise ValueError("Responses runtime state does not belong to a workflow")
|
||||
if snapshot.get("revision") != self._engine.revision:
|
||||
raise ValueError("Workflow definition changed after the previous response")
|
||||
node_id = str(snapshot.get("current_node_id") or "")
|
||||
if not self._engine.node_type(node_id):
|
||||
raise ValueError("Previous workflow node no longer exists")
|
||||
self._restored_text_node_id = node_id
|
||||
|
||||
def text_state_snapshot(self) -> dict[str, Any]:
|
||||
"""Return the minimum durable state needed by the next text request."""
|
||||
node_id = (
|
||||
str(self._manager.current_node)
|
||||
if self._manager is not None and self._manager.current_node
|
||||
else self._state.current_node_id
|
||||
)
|
||||
return {
|
||||
"type": "workflow",
|
||||
"revision": self._engine.revision,
|
||||
"current_node_id": node_id,
|
||||
"status": self._state.status.value,
|
||||
}
|
||||
|
||||
async def _initial_node_config(self) -> NodeConfig:
|
||||
"""Only a default-only Start advances before the first user turn."""
|
||||
outgoing = self._engine.outgoing(self._engine.start_id)
|
||||
|
||||
Reference in New Issue
Block a user