WIP: feat(api): add is_resumption to node_started and workflow_started events

This commit is contained in:
QuantumGhost
2026-01-04 01:10:50 +08:00
parent f4642f85b7
commit 6337a9a125
11 changed files with 215 additions and 1 deletions

View File

@ -391,6 +391,7 @@ class WorkflowResponseConverter:
iteration_id=event.in_iteration_id,
loop_id=event.in_loop_id,
agent_strategy=event.agent_strategy,
is_resumption=event.is_resumption,
),
)

View File

@ -418,6 +418,7 @@ class WorkflowBasedAppRunner:
agent_strategy=event.agent_strategy,
provider_type=event.provider_type,
provider_id=event.provider_id,
is_resumption=event.is_resumption,
)
)
elif isinstance(event, NodeRunSucceededEvent):

View File

@ -318,6 +318,7 @@ class QueueNodeStartedEvent(AppQueueEvent):
# FIXME(-LAN-): only for ToolNode, need to refactor
provider_type: str # should be a core.tools.entities.tool_entities.ToolProviderType
provider_id: str
is_resumption: bool = False
class QueueNodeSucceededEvent(AppQueueEvent):

View File

@ -307,6 +307,7 @@ class NodeStartStreamResponse(StreamResponse):
iteration_id: str | None = None
loop_id: str | None = None
agent_strategy: AgentNodeStrategyInit | None = None
is_resumption: bool = False
event: StreamEvent = StreamEvent.NODE_STARTED
workflow_run_id: str

View File

@ -131,6 +131,9 @@ class EventHandler:
node_execution.mark_started(event.id)
self._graph_runtime_state.increment_node_run_steps()
# Mark whether this start is part of a resume flow
event.is_resumption = self._graph_runtime_state.consume_resuming_node(event.node_id)
# Track in response coordinator for stream ordering
self._response_coordinator.track_node_execution(event.node_id, event.id)

View File

@ -15,6 +15,7 @@ class NodeRunStartedEvent(GraphNodeEventBase):
predecessor_node_id: str | None = None
agent_strategy: AgentNodeStrategyInit | None = None
start_at: datetime = Field(..., description="node start time")
is_resumption: bool = False
# FIXME(-LAN-): only for ToolNode
provider_type: str = ""

View File

@ -177,6 +177,9 @@ class GraphRuntimeState:
self._pending_response_coordinator_dump: str | None = None
self._pending_graph_execution_workflow_id: str | None = None
self._paused_nodes: set[str] = set()
# Tracks nodes that are being resumed in the current execution cycle.
# Populated when paused nodes are consumed during resume.
self._resuming_nodes: set[str] = set()
if graph is not None:
self.attach_graph(graph)
@ -363,8 +366,19 @@ class GraphRuntimeState:
nodes = list(self._paused_nodes)
self._paused_nodes.clear()
# Mark these nodes as resuming so downstream handlers can annotate events.
self._resuming_nodes.update(nodes)
return nodes
def consume_resuming_node(self, node_id: str) -> bool:
"""
Return True iff `node_id` is in the resuming set and remove it.
"""
if node_id in self._resuming_nodes:
self._resuming_nodes.remove(node_id)
return True
return False
# ------------------------------------------------------------------
# Builders
# ------------------------------------------------------------------