1515
1616 from a2a .server .agent_execution .agent_executor import AgentExecutor
1717 from a2a .server .context import ServerCallContext
18- from a2a .server .events .event_queue_v2 import Event , EventQueue
1918 from a2a .server .tasks .push_notification_sender import (
2019 PushNotificationSender ,
2120 )
2221 from a2a .server .tasks .task_manager import TaskManager
2322
24-
2523from a2a .server .events .event_queue_v2 import (
2624 AsyncQueue ,
25+ Event ,
26+ EventQueueSource ,
2727 QueueShutDown ,
2828 _create_async_queue ,
2929)
4848 TaskState .TASK_STATE_FAILED ,
4949 TaskState .TASK_STATE_REJECTED ,
5050}
51+ INTERRUPTED_TASK_STATES = {
52+ TaskState .TASK_STATE_AUTH_REQUIRED ,
53+ TaskState .TASK_STATE_INPUT_REQUIRED ,
54+ }
5155
5256
5357class _RequestCompleted :
@@ -76,11 +80,10 @@ class ActiveTask:
7680 permanently ceased execution and closed its queues.
7781 """
7882
79- def __init__ ( # noqa: PLR0913
83+ def __init__ (
8084 self ,
8185 agent_executor : AgentExecutor ,
8286 task_id : str ,
83- event_queue : EventQueue ,
8487 task_manager : TaskManager ,
8588 push_sender : PushNotificationSender | None = None ,
8689 on_cleanup : Callable [[ActiveTask ], None ] | None = None ,
@@ -90,8 +93,6 @@ def __init__( # noqa: PLR0913
9093 Args:
9194 agent_executor: The executor to run the agent logic (producer).
9295 task_id: The unique identifier of the task being managed.
93- event_queue: The queue for events produced by the agent. Acts as the pipe
94- between the producer and consumer tasks.
9596 task_manager: The manager for task state and database persistence.
9697 push_sender: Optional sender for out-of-band push notifications.
9798 on_cleanup: Optional callback triggered when the task is fully finished
@@ -101,7 +102,10 @@ def __init__( # noqa: PLR0913
101102 # --- Core Dependencies ---
102103 self ._agent_executor = agent_executor
103104 self ._task_id = task_id
104- self ._event_queue = event_queue
105+ self ._event_queue_agent = EventQueueSource ()
106+ self ._event_queue_subscribers = EventQueueSource (
107+ create_default_sink = False
108+ )
105109 self ._task_manager = task_manager
106110 self ._push_sender = push_sender
107111 self ._on_cleanup = on_cleanup
@@ -284,7 +288,7 @@ async def _run_producer(self) -> None:
284288
285289 try :
286290 await self ._agent_executor .execute (
287- request_context , self ._event_queue
291+ request_context , self ._event_queue_agent
288292 )
289293 logger .debug (
290294 'Producer[%s]: Execution finished successfully' ,
@@ -301,7 +305,7 @@ async def _run_producer(self) -> None:
301305 self ._task_id ,
302306 )
303307 # TODO: Hide from external consumers
304- await self ._event_queue .enqueue_event (
308+ await self ._event_queue_agent .enqueue_event (
305309 cast ('Event' , _RequestCompleted (request_id ))
306310 )
307311 self ._request_queue .task_done ()
@@ -319,7 +323,8 @@ async def _run_producer(self) -> None:
319323 self ._exception = e
320324 finally :
321325 self ._request_queue .shutdown (immediate = True )
322- await self ._event_queue .close (immediate = False )
326+ await self ._event_queue_agent .close (immediate = False )
327+ await self ._event_queue_subscribers .close (immediate = False )
323328 finally :
324329 logger .debug ('Producer[%s]: Completed' , self ._task_id )
325330
@@ -345,7 +350,7 @@ async def _run_consumer(self) -> None: # noqa: PLR0915, PLR0912
345350 'Consumer[%s]: Waiting for event' ,
346351 self ._task_id ,
347352 )
348- event = await self ._event_queue .dequeue_event ()
353+ event = await self ._event_queue_agent .dequeue_event ()
349354 logger .debug (
350355 'Consumer[%s]: Dequeued event %s' ,
351356 self ._task_id ,
@@ -373,15 +378,14 @@ async def _run_consumer(self) -> None: # noqa: PLR0915, PLR0912
373378
374379 # Check for AUTH_REQUIRED or INPUT_REQUIRED or TERMINAL states
375380 res = await self ._task_manager .get_task ()
376- is_interrupted = res and res .status .state in (
377- TaskState .TASK_STATE_AUTH_REQUIRED ,
378- TaskState .TASK_STATE_INPUT_REQUIRED ,
381+ is_interrupted = (
382+ res
383+ and res .status .state
384+ in INTERRUPTED_TASK_STATES
379385 )
380- is_terminal = res and res .status .state in (
381- TaskState .TASK_STATE_COMPLETED ,
382- TaskState .TASK_STATE_CANCELED ,
383- TaskState .TASK_STATE_FAILED ,
384- TaskState .TASK_STATE_REJECTED ,
386+ is_terminal = (
387+ res
388+ and res .status .state in TERMINAL_TASK_STATES
385389 )
386390
387391 # If we hit a breakpoint or terminal state, lock in the result.
@@ -427,9 +431,11 @@ async def _run_consumer(self) -> None: # noqa: PLR0915, PLR0912
427431 await self ._push_sender .send_notification (
428432 self ._task_id , event
429433 )
430-
431434 finally :
432- self ._event_queue .task_done ()
435+ await self ._event_queue_subscribers .enqueue_event (
436+ event
437+ )
438+ self ._event_queue_agent .task_done ()
433439 except QueueShutDown :
434440 logger .debug (
435441 'Consumer[%s]: Event queue shut down' , self ._task_id
@@ -482,7 +488,7 @@ async def subscribe( # noqa: PLR0912, PLR0915
482488 self ._reference_count ,
483489 )
484490
485- tapped_queue = await self ._event_queue .tap ()
491+ tapped_queue = await self ._event_queue_subscribers .tap ()
486492 request_id = await self .enqueue_request (request ) if request else None
487493
488494 try :
@@ -562,17 +568,14 @@ async def cancel(self, call_context: ServerCallContext) -> Task | Message:
562568 )
563569
564570 async with self ._lock :
565- # if self._producer_task and not self._producer_task.done():
566571 if not self ._is_finished .is_set () and self ._producer_task :
567572 logger .debug (
568573 'Cancel[%s]: Cancelling producer task' , self ._task_id
569574 )
570- # We do NOT await self._agent_executor.cancel here
571- # because it might take a while and we want to block on `_is_finished.wait()`
572575 self ._producer_task .cancel ()
573576 try :
574577 await self ._agent_executor .cancel (
575- request_context , self ._event_queue
578+ request_context , self ._event_queue_agent
576579 )
577580 except Exception as e :
578581 logger .exception (
0 commit comments