Skip to content

Commit 2485fa2

Browse files
committed
begin refactor to cover UUIDs
1 parent 1d8f92e commit 2485fa2

31 files changed

+249
-206
lines changed

scripts/generate_types.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ if [ -z "$1" ]; then
1010
exit 1
1111
fi
1212

13-
REMOTE_URL="https://raw.githubusercontent.com/a2aproject/A2A/refs/heads/main/specification/json/a2a.json"
13+
REMOTE_URL="https://raw.githubusercontent.com/a2aproject/A2A/refs/heads/uuid-fields/specification/json/a2a.json"
1414
GENERATED_FILE="$1"
1515

1616
echo "Running datamodel-codegen..."
@@ -39,6 +39,7 @@ uv run datamodel-codegen \
3939
--no-alias
4040

4141
echo "Formatting generated file with ruff..."
42+
uv run ruff check --fix-only "$GENERATED_FILE"
4243
uv run ruff format "$GENERATED_FILE"
4344

4445
echo "Codegen finished successfully."

src/a2a/types.py

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
# generated by datamodel-codegen:
2-
# filename: https://raw.githubusercontent.com/a2aproject/A2A/refs/heads/main/specification/json/a2a.json
2+
# filename: https://raw.githubusercontent.com/a2aproject/A2A/refs/heads/uuid-fields/specification/json/a2a.json
33

44
from __future__ import annotations
55

66
from enum import Enum
77
from typing import Any, Literal
8+
from uuid import UUID
89

910
from pydantic import Field, RootModel
1011

@@ -293,15 +294,15 @@ class DeleteTaskPushNotificationConfigParams(A2ABaseModel):
293294
Defines parameters for deleting a specific push notification configuration for a task.
294295
"""
295296

296-
id: str
297+
id: UUID
297298
"""
298299
The unique identifier of the task.
299300
"""
300301
metadata: dict[str, Any] | None = None
301302
"""
302303
Optional metadata associated with the request.
303304
"""
304-
push_notification_config_id: str
305+
push_notification_config_id: UUID
305306
"""
306307
The ID of the push notification configuration to delete.
307308
"""
@@ -430,15 +431,15 @@ class GetTaskPushNotificationConfigParams(A2ABaseModel):
430431
Defines parameters for fetching a specific push notification configuration for a task.
431432
"""
432433

433-
id: str
434+
id: UUID
434435
"""
435436
The unique identifier of the task.
436437
"""
437438
metadata: dict[str, Any] | None = None
438439
"""
439440
Optional metadata associated with the request.
440441
"""
441-
push_notification_config_id: str | None = None
442+
push_notification_config_id: UUID | None = None
442443
"""
443444
The ID of the push notification configuration to retrieve.
444445
"""
@@ -675,7 +676,7 @@ class ListTaskPushNotificationConfigParams(A2ABaseModel):
675676
Defines parameters for listing all push notification configurations associated with a task.
676677
"""
677678

678-
id: str
679+
id: UUID
679680
"""
680681
The unique identifier of the task.
681682
"""
@@ -828,7 +829,7 @@ class PushNotificationConfig(A2ABaseModel):
828829
"""
829830
Optional authentication details for the agent to use when calling the notification URL.
830831
"""
831-
id: str | None = None
832+
id: UUID | None = None
832833
"""
833834
A unique ID for the push notification configuration, set by the client
834835
to support multiple notification callbacks.
@@ -879,7 +880,7 @@ class TaskIdParams(A2ABaseModel):
879880
Defines parameters containing a task ID, used for simple task operations.
880881
"""
881882

882-
id: str
883+
id: UUID
883884
"""
884885
The unique identifier of the task.
885886
"""
@@ -938,7 +939,7 @@ class TaskPushNotificationConfig(A2ABaseModel):
938939
"""
939940
The push notification configuration for this task.
940941
"""
941-
task_id: str
942+
task_id: UUID
942943
"""
943944
The ID of the task.
944945
"""
@@ -953,7 +954,7 @@ class TaskQueryParams(A2ABaseModel):
953954
"""
954955
The number of most recent messages from the task's history to retrieve.
955956
"""
956-
id: str
957+
id: UUID
957958
"""
958959
The unique identifier of the task.
959960
"""
@@ -1374,7 +1375,7 @@ class Artifact(A2ABaseModel):
13741375
Represents a file, data structure, or other resource generated by an agent during a task.
13751376
"""
13761377

1377-
artifact_id: str
1378+
artifact_id: UUID
13781379
"""
13791380
A unique identifier for the artifact within the scope of the task.
13801381
"""
@@ -1438,7 +1439,7 @@ class Message(A2ABaseModel):
14381439
Represents a single message in the conversation between a user and an agent.
14391440
"""
14401441

1441-
context_id: str | None = None
1442+
context_id: UUID | None = None
14421443
"""
14431444
The context identifier for this message, used to group related interactions.
14441445
"""
@@ -1450,7 +1451,7 @@ class Message(A2ABaseModel):
14501451
"""
14511452
The type of this object, used as a discriminator. Always 'message' for a Message.
14521453
"""
1453-
message_id: str
1454+
message_id: UUID
14541455
"""
14551456
A unique identifier for the message, typically a UUID, generated by the sender.
14561457
"""
@@ -1463,15 +1464,15 @@ class Message(A2ABaseModel):
14631464
An array of content parts that form the message body. A message can be
14641465
composed of multiple parts of different types (e.g., text and files).
14651466
"""
1466-
reference_task_ids: list[str] | None = None
1467+
reference_task_ids: list[UUID] | None = None
14671468
"""
14681469
A list of other task IDs that this message references for additional context.
14691470
"""
14701471
role: Role
14711472
"""
14721473
Identifies the sender of the message. `user` for the client, `agent` for the service.
14731474
"""
1474-
task_id: str | None = None
1475+
task_id: UUID | None = None
14751476
"""
14761477
The identifier of the task this message is part of. Can be omitted for the first message of a new task.
14771478
"""
@@ -1614,7 +1615,7 @@ class TaskArtifactUpdateEvent(A2ABaseModel):
16141615
"""
16151616
The artifact that was generated or updated.
16161617
"""
1617-
context_id: str
1618+
context_id: UUID
16181619
"""
16191620
The context ID associated with the task.
16201621
"""
@@ -1630,7 +1631,7 @@ class TaskArtifactUpdateEvent(A2ABaseModel):
16301631
"""
16311632
Optional metadata for extensions.
16321633
"""
1633-
task_id: str
1634+
task_id: UUID
16341635
"""
16351636
The ID of the task this artifact belongs to.
16361637
"""
@@ -1663,7 +1664,7 @@ class TaskStatusUpdateEvent(A2ABaseModel):
16631664
This is typically used in streaming or subscription models.
16641665
"""
16651666

1666-
context_id: str
1667+
context_id: UUID
16671668
"""
16681669
The context ID associated with the task.
16691670
"""
@@ -1683,7 +1684,7 @@ class TaskStatusUpdateEvent(A2ABaseModel):
16831684
"""
16841685
The new status of the task.
16851686
"""
1686-
task_id: str
1687+
task_id: UUID
16871688
"""
16881689
The ID of the task that was updated.
16891690
"""
@@ -1861,15 +1862,15 @@ class Task(A2ABaseModel):
18611862
"""
18621863
A collection of artifacts generated by the agent during the execution of the task.
18631864
"""
1864-
context_id: str
1865+
context_id: UUID
18651866
"""
18661867
A server-generated identifier for maintaining context across multiple related tasks or interactions.
18671868
"""
18681869
history: list[Message] | None = None
18691870
"""
18701871
An array of messages exchanged during the task, representing the conversation history.
18711872
"""
1872-
id: str
1873+
id: UUID
18731874
"""
18741875
A unique identifier for the task, generated by the server for a new task.
18751876
"""

src/a2a/utils/task.py

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,10 @@ def new_task(request: Message) -> Task:
2828
if isinstance(part.root, TextPart) and not part.root.text:
2929
raise ValueError('TextPart content cannot be empty')
3030

31-
context_id_str = request.context_id
32-
if context_id_str is not None:
33-
try:
34-
uuid.UUID(context_id_str)
35-
context_id = context_id_str
36-
except (ValueError, AttributeError, TypeError) as e:
37-
raise ValueError(
38-
f"Invalid context_id: '{context_id_str}' is not a valid UUID."
39-
) from e
40-
else:
41-
context_id = str(uuid.uuid4())
42-
4331
return Task(
4432
status=TaskStatus(state=TaskState.submitted),
45-
id=(request.task_id if request.task_id else str(uuid.uuid4())),
46-
context_id=context_id,
33+
id=request.task_id or uuid.uuid4(),
34+
context_id=request.context_id or uuid.uuid4(),
4735
history=[request],
4836
)
4937

tests/client/test_auth_middleware.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def build_success_response(request: httpx.Request) -> httpx.Response:
6464
jsonrpc='2.0',
6565
result=Message(
6666
kind='message',
67-
message_id='message-id',
67+
message_id='c222a603-645e-4c37-8f7b-e49f3ea80e9e',
6868
role=Role.agent,
6969
parts=[],
7070
),
@@ -75,7 +75,7 @@ def build_success_response(request: httpx.Request) -> httpx.Response:
7575
def build_message() -> Message:
7676
"""Builds a minimal Message."""
7777
return Message(
78-
message_id='msg1',
78+
message_id='87c8541d-f773-4825-bbb1-f518727231f2',
7979
role=Role.user,
8080
parts=[],
8181
)

tests/client/test_base_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def sample_agent_card():
4242
def sample_message():
4343
return Message(
4444
role=Role.user,
45-
message_id='msg-1',
45+
message_id='15957e91-63e6-40ac-8205-1d1ffb09a5b2',
4646
parts=[Part(root=TextPart(text='Hello'))],
4747
)
4848

tests/client/test_client_task_manager.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ def task_manager():
2727
@pytest.fixture
2828
def sample_task():
2929
return Task(
30-
id='task123',
31-
context_id='context456',
30+
id='eede470e-ae8f-4910-ba05-085d45dc43c6',
31+
context_id='9a84655d-3956-4410-ba58-2923639254bd',
3232
status=TaskStatus(state=TaskState.working),
3333
history=[],
3434
artifacts=[],
@@ -38,7 +38,7 @@ def sample_task():
3838
@pytest.fixture
3939
def sample_message():
4040
return Message(
41-
message_id='msg1',
41+
message_id='87c8541d-f773-4825-bbb1-f518727231f2',
4242
role=Role.user,
4343
parts=[Part(root=TextPart(text='Hello'))],
4444
)

tests/client/test_grpc_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def sample_message_send_params() -> MessageSendParams:
6767
return MessageSendParams(
6868
message=Message(
6969
role=Role.user,
70-
message_id='msg-1',
70+
message_id='15957e91-63e6-40ac-8205-1d1ffb09a5b2',
7171
parts=[Part(root=TextPart(text='Hello'))],
7272
)
7373
)

tests/client/test_jsonrpc_client.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,15 @@
7979
)
8080

8181
MINIMAL_TASK: dict[str, Any] = {
82-
'id': 'task-abc',
83-
'contextId': 'session-xyz',
82+
'id': 'ea719c56-e398-425e-b02c-49fd77b7c156',
83+
'contextId': '598c0e6f-72c2-48fc-803a-15d693622c6f',
8484
'status': {'state': 'working'},
8585
'kind': 'task',
8686
}
8787

8888
MINIMAL_CANCELLED_TASK: dict[str, Any] = {
89-
'id': 'task-abc',
90-
'contextId': 'session-xyz',
89+
'id': 'ea719c56-e398-425e-b02c-49fd77b7c156',
90+
'contextId': '598c0e6f-72c2-48fc-803a-15d693622c6f',
9191
'status': {'state': 'canceled'},
9292
'kind': 'task',
9393
}
@@ -539,7 +539,7 @@ async def test_get_task_success(
539539
client = JsonRpcTransport(
540540
httpx_client=mock_httpx_client, agent_card=mock_agent_card
541541
)
542-
params = TaskQueryParams(id='task-abc')
542+
params = TaskQueryParams(id='ea719c56-e398-425e-b02c-49fd77b7c156')
543543
rpc_response = {
544544
'id': '123',
545545
'jsonrpc': '2.0',
@@ -567,7 +567,7 @@ async def test_cancel_task_success(
567567
client = JsonRpcTransport(
568568
httpx_client=mock_httpx_client, agent_card=mock_agent_card
569569
)
570-
params = TaskIdParams(id='task-abc')
570+
params = TaskIdParams(id='ea719c56-e398-425e-b02c-49fd77b7c156')
571571
rpc_response = {
572572
'id': '123',
573573
'jsonrpc': '2.0',
@@ -596,7 +596,7 @@ async def test_set_task_callback_success(
596596
httpx_client=mock_httpx_client, agent_card=mock_agent_card
597597
)
598598
params = TaskPushNotificationConfig(
599-
task_id='task-abc',
599+
task_id='ea719c56-e398-425e-b02c-49fd77b7c156',
600600
push_notification_config=PushNotificationConfig(
601601
url='http://callback.com'
602602
),
@@ -625,9 +625,9 @@ async def test_get_task_callback_success(
625625
client = JsonRpcTransport(
626626
httpx_client=mock_httpx_client, agent_card=mock_agent_card
627627
)
628-
params = TaskIdParams(id='task-abc')
628+
params = TaskIdParams(id='ea719c56-e398-425e-b02c-49fd77b7c156')
629629
expected_response = TaskPushNotificationConfig(
630-
task_id='task-abc',
630+
task_id='ea719c56-e398-425e-b02c-49fd77b7c156',
631631
push_notification_config=PushNotificationConfig(
632632
url='http://callback.com'
633633
),

tests/client/test_legacy_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ async def test_a2a_client_send_message(
8282
client._transport.send_message = AsyncMock(return_value=mock_response_task)
8383

8484
message = Message(
85-
message_id='msg-123',
85+
message_id='4a90ce5d-eda0-44be-afae-a709621eb63c',
8686
role=Role.user,
8787
parts=[Part(root=TextPart(text='Hello'))],
8888
)

0 commit comments

Comments
 (0)