mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-04 02:31:27 +00:00
fix(a2a): keep the missing a2a-sdk error reachable
a2a-sdk is optional and litellm[proxy] does not install it. The card resolver fell back to None and then subclassed that placeholder at module scope, so importing the package raised TypeError before anything could read A2A_SDK_AVAILABLE Agent calls therefore reported "NoneType takes no arguments" instead of the message naming the package to install, which has been unreachable since the resolver was introduced Fall back to a subclassable placeholder so the availability check runs Signed-off-by: Aryan Gorde <aryangorde8@gmail.com>
This commit is contained in:
parent
423b791ee0
commit
327e9ffd72
2 changed files with 44 additions and 1 deletions
|
|
@ -13,7 +13,7 @@ if TYPE_CHECKING:
|
|||
from a2a.types import AgentCard
|
||||
|
||||
# Runtime imports with availability check
|
||||
_A2ACardResolver: Any = None
|
||||
_A2ACardResolver: Any = object
|
||||
AGENT_CARD_WELL_KNOWN_PATH: str = "/.well-known/agent-card.json"
|
||||
PREV_AGENT_CARD_WELL_KNOWN_PATH: str = "/.well-known/agent.json"
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@ Mock tests for LiteLLMA2ACardResolver.
|
|||
Tests that the card resolver tries both old and new well-known paths.
|
||||
"""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import textwrap
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
|
|
@ -17,6 +21,45 @@ from litellm.a2a_protocol.card_resolver import (
|
|||
)
|
||||
|
||||
|
||||
def test_a2a_protocol_imports_when_a2a_sdk_is_missing():
|
||||
"""
|
||||
a2a-sdk is an optional dependency, so the proxy degrades by reading A2A_SDK_AVAILABLE and
|
||||
returning a JSON-RPC "'a2a' package not installed" error. Reading that flag imports this
|
||||
module, so importing it with the SDK absent must not raise.
|
||||
|
||||
Runs in a subprocess because the check is about import time, and a2a-sdk is installed in CI.
|
||||
"""
|
||||
script = textwrap.dedent(
|
||||
"""
|
||||
import sys
|
||||
|
||||
class _BlockA2A:
|
||||
def find_spec(self, name, path=None, target=None):
|
||||
if name == "a2a" or name.startswith("a2a."):
|
||||
raise ModuleNotFoundError(f"No module named '{name}'")
|
||||
return None
|
||||
|
||||
sys.meta_path.insert(0, _BlockA2A())
|
||||
|
||||
from litellm.a2a_protocol import asend_message_streaming
|
||||
from litellm.a2a_protocol.main import A2A_SDK_AVAILABLE
|
||||
|
||||
print(f"A2A_SDK_AVAILABLE={A2A_SDK_AVAILABLE}")
|
||||
"""
|
||||
)
|
||||
|
||||
result = subprocess.run(
|
||||
[sys.executable, "-c", script],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=300,
|
||||
env={**os.environ, "LITELLM_LOCAL_MODEL_COST_MAP": "True"},
|
||||
)
|
||||
|
||||
assert result.returncode == 0, f"importing litellm.a2a_protocol without a2a-sdk failed:\n{result.stderr}"
|
||||
assert "A2A_SDK_AVAILABLE=False" in result.stdout
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_card_resolver_fallback_from_new_to_old_path():
|
||||
"""
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue