mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-22 00:31:44 +00:00
Some checks failed
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
117 lines
5.5 KiB
Python
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)
|