@@ -92,15 +92,19 @@ async def consume_all(
9292 return await self .task_manager .get_task ()
9393
9494 async def consume_and_break_on_interrupt (
95- self , consumer : EventConsumer
95+ self , consumer : EventConsumer , blocking : bool = True
9696 ) -> tuple [Task | Message | None , bool ]:
9797 """Processes the event stream until completion or an interruptable state is encountered.
9898
99- Interruptable states currently include `TaskState.auth_required`.
99+ If `blocking` is False, it returns after the first event that creates a Task or Message.
100+ If `blocking` is True, it waits for completion unless an `auth_required`
101+ state is encountered, which is always an interruption.
100102 If interrupted, consumption continues in a background task.
101103
102104 Args:
103105 consumer: The `EventConsumer` to read events from.
106+ blocking: If `False`, the method returns as soon as a task/message
107+ is available. If `True`, it waits for a terminal state.
104108
105109 Returns:
106110 A tuple containing:
@@ -117,10 +121,15 @@ async def consume_and_break_on_interrupt(
117121 self ._message = event
118122 return event , False
119123 await self .task_manager .process (event )
120- if (
124+
125+ should_interrupt = False
126+ is_auth_required = (
121127 isinstance (event , Task | TaskStatusUpdateEvent )
122128 and event .status .state == TaskState .auth_required
123- ):
129+ )
130+
131+ # Always interrupt on auth_required, as it needs external action.
132+ if is_auth_required :
124133 # auth-required is a special state: the message should be
125134 # escalated back to the caller, but the agent is expected to
126135 # continue producing events once the authorization is received
@@ -130,6 +139,16 @@ async def consume_and_break_on_interrupt(
130139 logger .debug (
131140 'Encountered an auth-required task: breaking synchronous message/send flow.'
132141 )
142+ should_interrupt = True
143+ # For non-blocking calls, interrupt as soon as a task is available.
144+ elif not blocking :
145+ logger .debug (
146+ 'Non-blocking call: returning task after first event.'
147+ )
148+ should_interrupt = True
149+
150+ if should_interrupt :
151+ # Continue consuming the rest of the events in the background.
133152 # TODO: We should track all outstanding tasks to ensure they eventually complete.
134153 asyncio .create_task (self ._continue_consuming (event_stream )) # noqa: RUF006
135154 interrupted = True
0 commit comments