Skip to content

Commit 0c8d0d6

Browse files
authored
Merge branch 'main' into docs/langgraph
2 parents a3d93e6 + 73820b1 commit 0c8d0d6

File tree

12 files changed

+47
-65
lines changed

12 files changed

+47
-65
lines changed

.github/actions/spelling/allow.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
AError
22
ARequest
3+
AServer
34
AStarlette
45
adk
6+
codegen
7+
datamodel
58
genai
69
inmemory
710
langgraph
@@ -10,3 +13,4 @@ oauthoidc
1013
opensource
1114
socio
1215
sse
16+
tagwords

CODE_OF_CONDUCT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
## Our Pledge
44

55
In the interest of fostering an open and welcoming environment, we as
6-
contributors and maintainers pledge to making participation in our project and
6+
contributors and maintainers pledge to make participation in our project and
77
our community a harassment-free experience for everyone, regardless of age, body
88
size, disability, ethnicity, gender identity and expression, level of
99
experience, education, socio-economic status, nationality, personal appearance,

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,4 @@ This project is licensed under the terms of the [Apache 2.0 License](LICENSE).
3535

3636
## Contributing
3737

38-
See [CONTRIBUTING.md](../CONTRIBUTING.md) for contribution guidelines.
38+
See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines.

src/a2a/server/agent_execution/base_agent_executor.py

Lines changed: 0 additions & 48 deletions
This file was deleted.

src/a2a/server/events/event_consumer.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ class EventConsumer:
2222

2323
def __init__(self, queue: EventQueue):
2424
self.queue = queue
25+
self._timeout = 0.5
26+
self._exception: BaseException | None = None
2527
logger.debug('EventConsumer initialized')
2628

2729
async def consume_one(self) -> Event:
@@ -45,8 +47,15 @@ async def consume_all(self) -> AsyncGenerator[Event]:
4547
"""Consume all the generated streaming events from the agent."""
4648
logger.debug('Starting to consume all events from the queue.')
4749
while True:
50+
if self._exception:
51+
raise self._exception
4852
try:
49-
event = await self.queue.dequeue_event()
53+
# We use a timeout when waiting for an event from the queue.
54+
# This is required because it allows the loop to check if
55+
# `self._exception` has been set by the `agent_task_callback`.
56+
# Without the timeout, loop might hang indefinitely if no events are
57+
# enqueued by the agent and the agent simply threw an exception
58+
event = await asyncio.wait_for(self.queue.dequeue_event(), timeout=self._timeout)
5059
logger.debug(
5160
f'Dequeued event of type: {type(event)} in consume_all.'
5261
)
@@ -74,5 +83,16 @@ async def consume_all(self) -> AsyncGenerator[Event]:
7483
logger.debug('Stopping event consumption in consume_all.')
7584
self.queue.close()
7685
break
86+
except asyncio.TimeoutError:
87+
# continue polling until there is a final event
88+
continue
7789
except asyncio.QueueShutDown:
7890
break
91+
92+
93+
94+
95+
96+
def agent_task_callback(self, agent_task: asyncio.Task[None]):
97+
if agent_task.exception() is not None:
98+
self._exception = agent_task.exception()

src/a2a/server/request_handlers/default_request_handler.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ async def on_message_send(
138138
await self._register_producer(task_id, producer_task)
139139

140140
consumer = EventConsumer(queue)
141+
producer_task.add_done_callback(consumer.agent_task_callback)
141142

142143
interrupted = False
143144
try:
@@ -192,6 +193,7 @@ async def on_message_send_stream(
192193

193194
try:
194195
consumer = EventConsumer(queue)
196+
producer_task.add_done_callback(consumer.agent_task_callback)
195197
async for event in result_aggregator.consume_and_emit(consumer):
196198
# Now we know we have a Task, register the queue
197199
if isinstance(event, Task):

src/a2a/server/tasks/inmemory_task_store.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,5 @@ async def delete(self, task_id: str) -> None:
3939
logger.info('Task %s deleted successfully.', task_id)
4040
else:
4141
logger.warning(
42-
'Attempted to delete non-existent task with id: %s', task_id
42+
'Attempted to delete nonexistent task with id: %s', task_id
4343
)

src/a2a/types.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,7 @@ class SetTaskPushNotificationConfigSuccessResponse(BaseModel):
933933

934934
class Artifact(BaseModel):
935935
"""
936-
Represents an artifact generated for a task task.
936+
Represents an artifact generated for a task.
937937
"""
938938

939939
artifactId: str

src/a2a/utils/errors.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616

1717
class A2AServerError(Exception):
18-
"""Base exception for A2A Server errors."""
18+
"""Base exception for A2A Server errors."""
1919

2020

2121
class MethodNotImplementedError(A2AServerError):

src/a2a/utils/helpers.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def append_artifact_to_task(task: Task, event: TaskArtifactUpdateEvent) -> None:
6565
)
6666
task.artifacts.append(new_artifact_data)
6767
elif existing_artifact:
68-
# Append new parts to the existing artifact's parts list
68+
# Append new parts to the existing artifact's part list
6969
logger.debug(
7070
f'Appending parts to artifact id {artifact_id} for task {task.id}'
7171
)
@@ -74,7 +74,7 @@ def append_artifact_to_task(task: Task, event: TaskArtifactUpdateEvent) -> None:
7474
# We received a chunk to append, but we don't have an existing artifact.
7575
# we will ignore this chunk
7676
logger.warning(
77-
f'Received append=True for non-existent artifact index {artifact_id} in task {task.id}. Ignoring chunk.'
77+
f'Received append=True for nonexistent artifact index {artifact_id} in task {task.id}. Ignoring chunk.'
7878
)
7979

8080

@@ -93,7 +93,7 @@ def wrapper(self, *args, **kwargs):
9393
if not expression(self):
9494
if not error_message:
9595
message = str(expression)
96-
logger.error(f'Unsuppported Operation: {error_message}')
96+
logger.error(f'Unsupported Operation: {error_message}')
9797
raise ServerError(
9898
UnsupportedOperationError(message=error_message)
9999
)

0 commit comments

Comments
 (0)