litellm/tests/integration/compatibility/test_a2a_wire_versions.py
Yuneng Jiang c00f1b4a5c
Some checks failed
Terraform Provider / gofmt, vet, build, test (push) Has been cancelled
Terraform Provider / Provider endpoints vs proxy OpenAPI schema (push) Has been cancelled
LiteLLM Rust / rust-lint (push) Has been cancelled
LiteLLM Rust / rust-test (push) Has been cancelled
test: add extension and browser integration contracts
Adds integration contracts for MCP lifecycle, protocol errors and OAuth
configuration, A2A wire versions, the OpenAI consumer path, persisted
toolsets, callback delivery, guardrail effects, configured prices, the
filtered spend ledger, and a CircleCI-owned browser flow for project
detachment, with the ASGI, browser-state, client and MCP helpers they use.
Consolidates the eleven commits previously stacked on
litellm_integration_providers onto its rebased tip
2026-09-16 13:15:53 -07:00

117 lines
5.5 KiB
Python

import json
import uuid
from typing import Final
import pytest
from integration._support.client import Gateway
from integration._support.database import read_rows
from integration._support.wire import Reply, Request, wire_server
@pytest.mark.covers("other.compatibility.a2a.supported_versions_preserve_literal_envelopes")
def test_a2a_versions_and_legacy_casing_preserve_real_wire_and_response(gateway: Gateway) -> None:
for version, legacy in (("0.3", False), ("1.0", False), ("0.3", True)):
marker: Final = "a2a" + uuid.uuid4().hex
def upstream(request: Request, marker: str = marker, legacy: bool = legacy) -> Reply:
if request.method == "GET":
assert request.target in ("/.well-known/agent-card.json", "/.well-known/agent.json")
card: Final = {
"protocolVersion": "0.3",
"name": marker,
"description": "Synthetic arithmetic peer",
"version": "1.0.0",
"url": wire.url + "/",
"capabilities": {"streaming": False},
"defaultInputModes": ["text"],
"defaultOutputModes": ["text"],
"skills": [],
}
if legacy:
card["supportedInterfaces"] = [
{"url": wire.url + "/", "protocolBinding": "jsonrpc", "protocolVersion": "1.0"}
]
return Reply(body=json.dumps(card).encode())
assert request.method == "POST" and request.target == "/"
body: Final = json.loads(request.body)
assert body["jsonrpc"] == "2.0" and body["method"] == "message/send"
message: Final = body["params"]["message"]
assert message["role"] == "user" and message["messageId"] == marker + "-in"
assert message["parts"] == [{"kind": "text", "text": "synthetic ping"}]
assert "message_id" not in message
return Reply(
body=json.dumps(
{
"jsonrpc": "2.0",
"id": body["id"],
"result": {
"kind": "message",
"role": "agent",
"messageId": marker + "-out",
"parts": [{"kind": "text", "text": "synthetic pong"}],
},
}
).encode()
)
with wire_server(upstream) as wire, gateway.scenario() as scenario:
card: Final = {
"protocolVersion": version,
"name": marker,
"description": "Synthetic arithmetic peer",
"version": "1.0.0",
"url": wire.url + "/",
"capabilities": {"streaming": False},
"defaultInputModes": ["text"],
"defaultOutputModes": ["text"],
"skills": [],
}
created: Final = gateway.request("POST", "/v1/agents", {"agent_name": marker, "agent_card_params": card})
identity: Final = created.json()["agent_id"]
def cleanup(identity: str = identity) -> None:
deleted: Final = gateway.request("DELETE", f"/v1/agents/{identity}")
assert deleted.status_code == 200, deleted.text
assert read_rows('SELECT agent_id FROM "LiteLLM_AgentsTable" WHERE agent_id=%s', (identity,)) == []
scenario.cleanups.callback(cleanup)
assert created.status_code == 200, created.text
assert gateway.get(f"/v1/agents/{identity}")["agent_card_params"]["protocolVersion"] == version
discovered: Final = gateway.request("GET", f"/a2a/{identity}/.well-known/agent-card.json")
assert discovered.status_code == 200, discovered.text
parameters: Final = {
"message": {
"role": "ROLE_USER" if version == "1.0" else "user",
"messageId": marker + "-in",
"parts": [{"text": "synthetic ping"}]
if version == "1.0"
else [{"kind": "text", "text": "synthetic ping"}],
}
}
response: Final = gateway.client.post(
f"/a2a/{identity}",
headers={"Authorization": f"Bearer {gateway.key}", "a2a-version": version},
json={
"jsonrpc": "2.0",
"id": marker,
"method": "SendMessage" if version == "1.0" else "message/send",
"params": parameters,
},
)
assert response.status_code == 200, response.text
body: Final = response.json()
assert body["jsonrpc"] == "2.0" and body["id"] == marker and "error" not in body
result: Final = body["result"]
message: Final = result["message"] if version == "1.0" else result
assert message["messageId"] == marker + "-out"
assert message["role"] == ("ROLE_AGENT" if version == "1.0" else "agent")
assert message["parts"][0]["text"] == "synthetic pong"
assert (
("kind" not in result and "message" in result)
if version == "1.0"
else (result["kind"] == "message" and "message" not in result)
)
actual: Final = wire.drain()
assert len(tuple(item for item in actual if item.method == "POST")) == 1
assert any(item.method == "GET" for item in actual)