Skip to content

Commit 69dc344

Browse files
authored
Merge branch 'main' into kthota/extended-card-changes
2 parents 1625692 + 83304bb commit 69dc344

File tree

3 files changed

+86
-7
lines changed

3 files changed

+86
-7
lines changed

src/a2a/types.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,7 @@ class AgentSkill(A2ABaseModel):
174174

175175
class AuthenticatedExtendedCardNotConfiguredError(A2ABaseModel):
176176
"""
177-
An A2A-specific error indicating that the agent does not have an
178-
Authenticated Extended Card configured
177+
An A2A-specific error indicating that the agent does not have an Authenticated Extended Card configured
179178
"""
180179

181180
code: Literal[-32007] = -32007
@@ -187,7 +186,7 @@ class AuthenticatedExtendedCardNotConfiguredError(A2ABaseModel):
187186
A primitive or structured value containing additional information about the error.
188187
This may be omitted.
189188
"""
190-
message: str | None = 'Authenticated Extended Card not configured'
189+
message: str | None = 'Authenticated Extended Card is not configured'
191190
"""
192191
The error message.
193192
"""

tests/server/test_integration.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,8 @@ def test_invalid_request_structure(client: TestClient):
836836
'/',
837837
json={
838838
# Missing required fields
839-
'id': '123'
839+
'id': '123',
840+
'method': 'foo/bar',
840841
},
841842
)
842843
assert response.status_code == 200

tests/test_types.py

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
FileWithUri,
2525
GetTaskPushNotificationConfigParams,
2626
GetTaskPushNotificationConfigRequest,
27+
GetAuthenticatedExtendedCardRequest,
28+
GetAuthenticatedExtendedCardResponse,
29+
GetAuthenticatedExtendedCardSuccessResponse,
2730
GetTaskPushNotificationConfigResponse,
2831
GetTaskPushNotificationConfigSuccessResponse,
2932
GetTaskRequest,
@@ -968,6 +971,21 @@ def test_a2a_request_root_model() -> None:
968971
assert isinstance(a2a_req_task_resubscribe_req.root.params, TaskIdParams)
969972
assert a2a_req_task_resubscribe_req.root.method == 'tasks/resubscribe'
970973

974+
# GetAuthenticatedExtendedCardRequest
975+
get_auth_card_req_data: dict[str, Any] = {
976+
'jsonrpc': '2.0',
977+
'method': 'agent/getAuthenticatedExtendedCard',
978+
'id': 2,
979+
}
980+
a2a_req_get_auth_card = A2ARequest.model_validate(get_auth_card_req_data)
981+
assert isinstance(
982+
a2a_req_get_auth_card.root, GetAuthenticatedExtendedCardRequest
983+
)
984+
assert (
985+
a2a_req_get_auth_card.root.method
986+
== 'agent/getAuthenticatedExtendedCard'
987+
)
988+
971989
# Invalid method case
972990
invalid_req_data: dict[str, Any] = {
973991
'jsonrpc': '2.0',
@@ -1055,6 +1073,14 @@ def test_a2a_request_root_model_id_validation() -> None:
10551073
with pytest.raises(ValidationError):
10561074
A2ARequest.model_validate(task_resubscribe_req_data)
10571075

1076+
# GetAuthenticatedExtendedCardRequest
1077+
get_auth_card_req_data: dict[str, Any] = {
1078+
'jsonrpc': '2.0',
1079+
'method': 'agent/getAuthenticatedExtendedCard',
1080+
}
1081+
with pytest.raises(ValidationError):
1082+
A2ARequest.model_validate(get_auth_card_req_data) # missing id
1083+
10581084

10591085
def test_content_type_not_supported_error():
10601086
# Test ContentTypeNotSupportedError
@@ -1544,11 +1570,11 @@ def test_camelCase() -> None:
15441570
description='Just a hello world agent',
15451571
url='http://localhost:9999/',
15461572
version='1.0.0',
1547-
defaultInputModes=['text'],
1548-
defaultOutputModes=['text'],
1573+
defaultInputModes=['text'], # type: ignore
1574+
defaultOutputModes=['text'], # type: ignore
15491575
capabilities=AgentCapabilities(streaming=True),
15501576
skills=[skill],
1551-
supportsAuthenticatedExtendedCard=True,
1577+
supportsAuthenticatedExtendedCard=True, # type: ignore
15521578
)
15531579

15541580
# Test setting an attribute via camelCase alias
@@ -1568,3 +1594,56 @@ def test_camelCase() -> None:
15681594
assert agent_card.supports_authenticated_extended_card is False
15691595
assert default_input_modes == ['text']
15701596
assert agent_card.default_input_modes == ['text']
1597+
1598+
1599+
def test_get_authenticated_extended_card_request() -> None:
1600+
req_data: dict[str, Any] = {
1601+
'jsonrpc': '2.0',
1602+
'method': 'agent/getAuthenticatedExtendedCard',
1603+
'id': 5,
1604+
}
1605+
req = GetAuthenticatedExtendedCardRequest.model_validate(req_data)
1606+
assert req.method == 'agent/getAuthenticatedExtendedCard'
1607+
assert req.id == 5
1608+
# This request has no params, so we don't check for that.
1609+
1610+
with pytest.raises(ValidationError): # Wrong method literal
1611+
GetAuthenticatedExtendedCardRequest.model_validate(
1612+
{**req_data, 'method': 'wrong/method'}
1613+
)
1614+
1615+
with pytest.raises(ValidationError): # Missing id
1616+
GetAuthenticatedExtendedCardRequest.model_validate(
1617+
{'jsonrpc': '2.0', 'method': 'agent/getAuthenticatedExtendedCard'}
1618+
)
1619+
1620+
1621+
def test_get_authenticated_extended_card_response() -> None:
1622+
resp_data: dict[str, Any] = {
1623+
'jsonrpc': '2.0',
1624+
'result': MINIMAL_AGENT_CARD,
1625+
'id': 'resp-1',
1626+
}
1627+
resp = GetAuthenticatedExtendedCardResponse.model_validate(resp_data)
1628+
assert resp.root.id == 'resp-1'
1629+
assert isinstance(resp.root, GetAuthenticatedExtendedCardSuccessResponse)
1630+
assert isinstance(resp.root.result, AgentCard)
1631+
assert resp.root.result.name == 'TestAgent'
1632+
1633+
with pytest.raises(ValidationError): # Result is not an AgentCard
1634+
GetAuthenticatedExtendedCardResponse.model_validate(
1635+
{'jsonrpc': '2.0', 'result': {'wrong': 'data'}, 'id': 1}
1636+
)
1637+
1638+
resp_data_err: dict[str, Any] = {
1639+
'jsonrpc': '2.0',
1640+
'error': JSONRPCError(**TaskNotFoundError().model_dump()),
1641+
'id': 'resp-1',
1642+
}
1643+
resp_err = GetAuthenticatedExtendedCardResponse.model_validate(
1644+
resp_data_err
1645+
)
1646+
assert resp_err.root.id == 'resp-1'
1647+
assert isinstance(resp_err.root, JSONRPCErrorResponse)
1648+
assert resp_err.root.error is not None
1649+
assert isinstance(resp_err.root.error, JSONRPCError)

0 commit comments

Comments
 (0)