diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 51d720ebf..7306f0512 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,7 +19,7 @@ repos: language: system pass_filenames: true types: [python] - exclude: ^(lib/crewai/src/crewai/cli/templates/|lib/crewai/tests/|lib/crewai-tools/tests/|lib/crewai-files/tests/) + exclude: ^(lib/crewai/src/crewai/cli/templates/|lib/crewai/tests/|lib/crewai-tools/tests/|lib/crewai-files/tests/|lib/crewai-a2a/tests/) - repo: https://github.com/astral-sh/uv-pre-commit rev: 0.11.3 hooks: diff --git a/lib/crewai-a2a/README.md b/lib/crewai-a2a/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/lib/crewai-a2a/pyproject.toml b/lib/crewai-a2a/pyproject.toml new file mode 100644 index 000000000..30a2f84a3 --- /dev/null +++ b/lib/crewai-a2a/pyproject.toml @@ -0,0 +1,22 @@ +[project] +name = "crewai-a2a" +dynamic = ["version"] +description = "Add your description here" +readme = "README.md" +authors = [ + { name = "Greyson LaLonde", email = "greyson@crewai.com" } +] +requires-python = ">=3.10, <3.14" +dependencies = [ + "a2a-sdk~=0.3.10", + "httpx-auth~=0.23.1", + "httpx-sse~=0.4.0", + "aiocache[redis,memcached]~=0.12.3", +] + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.version] +path = "src/crewai_a2a/__init__.py" diff --git a/lib/crewai-a2a/src/crewai_a2a/__init__.py b/lib/crewai-a2a/src/crewai_a2a/__init__.py new file mode 100644 index 000000000..985996a62 --- /dev/null +++ b/lib/crewai-a2a/src/crewai_a2a/__init__.py @@ -0,0 +1,13 @@ +"""Agent-to-Agent (A2A) protocol communication module for CrewAI.""" + +__version__ = "1.14.2a3" + +from crewai_a2a.config import A2AClientConfig, A2AConfig, A2AServerConfig + + +__all__ = [ + "A2AClientConfig", + "A2AConfig", + "A2AServerConfig", + "__version__", +] diff --git a/lib/crewai/src/crewai/a2a/auth/__init__.py b/lib/crewai-a2a/src/crewai_a2a/auth/__init__.py similarity index 88% rename from lib/crewai/src/crewai/a2a/auth/__init__.py rename to lib/crewai-a2a/src/crewai_a2a/auth/__init__.py index cd7e67d72..95a7e84f5 100644 --- a/lib/crewai/src/crewai/a2a/auth/__init__.py +++ b/lib/crewai-a2a/src/crewai_a2a/auth/__init__.py @@ -1,6 +1,6 @@ """A2A authentication schemas.""" -from crewai.a2a.auth.client_schemes import ( +from crewai_a2a.auth.client_schemes import ( APIKeyAuth, AuthScheme, BearerTokenAuth, @@ -11,7 +11,7 @@ from crewai.a2a.auth.client_schemes import ( OAuth2ClientCredentials, TLSConfig, ) -from crewai.a2a.auth.server_schemes import ( +from crewai_a2a.auth.server_schemes import ( AuthenticatedUser, EnterpriseTokenAuth, OIDCAuth, diff --git a/lib/crewai/src/crewai/a2a/auth/client_schemes.py b/lib/crewai-a2a/src/crewai_a2a/auth/client_schemes.py similarity index 100% rename from lib/crewai/src/crewai/a2a/auth/client_schemes.py rename to lib/crewai-a2a/src/crewai_a2a/auth/client_schemes.py diff --git a/lib/crewai-a2a/src/crewai_a2a/auth/schemas.py b/lib/crewai-a2a/src/crewai_a2a/auth/schemas.py new file mode 100644 index 000000000..4372ed5fe --- /dev/null +++ b/lib/crewai-a2a/src/crewai_a2a/auth/schemas.py @@ -0,0 +1,71 @@ +"""Deprecated: Authentication schemes for A2A protocol agents. + +This module is deprecated. Import from crewai_a2a.auth instead: +- crewai_a2a.auth.ClientAuthScheme (replaces AuthScheme) +- crewai_a2a.auth.BearerTokenAuth +- crewai_a2a.auth.HTTPBasicAuth +- crewai_a2a.auth.HTTPDigestAuth +- crewai_a2a.auth.APIKeyAuth +- crewai_a2a.auth.OAuth2ClientCredentials +- crewai_a2a.auth.OAuth2AuthorizationCode +""" + +from __future__ import annotations + +from typing_extensions import deprecated + +from crewai_a2a.auth.client_schemes import ( + APIKeyAuth as _APIKeyAuth, + BearerTokenAuth as _BearerTokenAuth, + ClientAuthScheme as _ClientAuthScheme, + HTTPBasicAuth as _HTTPBasicAuth, + HTTPDigestAuth as _HTTPDigestAuth, + OAuth2AuthorizationCode as _OAuth2AuthorizationCode, + OAuth2ClientCredentials as _OAuth2ClientCredentials, +) + + +@deprecated("Use ClientAuthScheme from crewai_a2a.auth instead", category=FutureWarning) +class AuthScheme(_ClientAuthScheme): + """Deprecated: Use ClientAuthScheme from crewai_a2a.auth instead.""" + + +@deprecated("Import from crewai_a2a.auth instead", category=FutureWarning) +class BearerTokenAuth(_BearerTokenAuth): + """Deprecated: Import from crewai_a2a.auth instead.""" + + +@deprecated("Import from crewai_a2a.auth instead", category=FutureWarning) +class HTTPBasicAuth(_HTTPBasicAuth): + """Deprecated: Import from crewai_a2a.auth instead.""" + + +@deprecated("Import from crewai_a2a.auth instead", category=FutureWarning) +class HTTPDigestAuth(_HTTPDigestAuth): + """Deprecated: Import from crewai_a2a.auth instead.""" + + +@deprecated("Import from crewai_a2a.auth instead", category=FutureWarning) +class APIKeyAuth(_APIKeyAuth): + """Deprecated: Import from crewai_a2a.auth instead.""" + + +@deprecated("Import from crewai_a2a.auth instead", category=FutureWarning) +class OAuth2ClientCredentials(_OAuth2ClientCredentials): + """Deprecated: Import from crewai_a2a.auth instead.""" + + +@deprecated("Import from crewai_a2a.auth instead", category=FutureWarning) +class OAuth2AuthorizationCode(_OAuth2AuthorizationCode): + """Deprecated: Import from crewai_a2a.auth instead.""" + + +__all__ = [ + "APIKeyAuth", + "AuthScheme", + "BearerTokenAuth", + "HTTPBasicAuth", + "HTTPDigestAuth", + "OAuth2AuthorizationCode", + "OAuth2ClientCredentials", +] diff --git a/lib/crewai/src/crewai/a2a/auth/server_schemes.py b/lib/crewai-a2a/src/crewai_a2a/auth/server_schemes.py similarity index 100% rename from lib/crewai/src/crewai/a2a/auth/server_schemes.py rename to lib/crewai-a2a/src/crewai_a2a/auth/server_schemes.py diff --git a/lib/crewai/src/crewai/a2a/auth/utils.py b/lib/crewai-a2a/src/crewai_a2a/auth/utils.py similarity index 99% rename from lib/crewai/src/crewai/a2a/auth/utils.py rename to lib/crewai-a2a/src/crewai_a2a/auth/utils.py index 3e8de3e0d..d1699143e 100644 --- a/lib/crewai/src/crewai/a2a/auth/utils.py +++ b/lib/crewai-a2a/src/crewai_a2a/auth/utils.py @@ -20,7 +20,7 @@ from a2a.types import ( ) from httpx import AsyncClient, Response -from crewai.a2a.auth.client_schemes import ( +from crewai_a2a.auth.client_schemes import ( APIKeyAuth, BearerTokenAuth, ClientAuthScheme, diff --git a/lib/crewai/src/crewai/a2a/config.py b/lib/crewai-a2a/src/crewai_a2a/config.py similarity index 97% rename from lib/crewai/src/crewai/a2a/config.py rename to lib/crewai-a2a/src/crewai_a2a/config.py index 499248046..05c97164b 100644 --- a/lib/crewai/src/crewai/a2a/config.py +++ b/lib/crewai-a2a/src/crewai_a2a/config.py @@ -20,10 +20,10 @@ from pydantic import ( ) from typing_extensions import Self, deprecated -from crewai.a2a.auth.client_schemes import ClientAuthScheme -from crewai.a2a.auth.server_schemes import ServerAuthScheme -from crewai.a2a.extensions.base import ValidatedA2AExtension -from crewai.a2a.types import ProtocolVersion, TransportType, Url +from crewai_a2a.auth.client_schemes import ClientAuthScheme +from crewai_a2a.auth.server_schemes import ServerAuthScheme +from crewai_a2a.extensions.base import ValidatedA2AExtension +from crewai_a2a.types import ProtocolVersion, TransportType, Url try: @@ -36,8 +36,8 @@ try: SecurityScheme, ) - from crewai.a2a.extensions.server import ServerExtension - from crewai.a2a.updates import UpdateConfig + from crewai_a2a.extensions.server import ServerExtension + from crewai_a2a.updates import UpdateConfig except ImportError: UpdateConfig: Any = Any # type: ignore[no-redef] AgentCapabilities: Any = Any # type: ignore[no-redef] @@ -50,7 +50,7 @@ except ImportError: def _get_default_update_config() -> UpdateConfig: - from crewai.a2a.updates import StreamingConfig + from crewai_a2a.updates import StreamingConfig return StreamingConfig() @@ -360,8 +360,8 @@ class ClientTransportConfig(BaseModel): @deprecated( """ - `crewai.a2a.config.A2AConfig` is deprecated and will be removed in v2.0.0, - use `crewai.a2a.config.A2AClientConfig` or `crewai.a2a.config.A2AServerConfig` instead. + `crewai_a2a.config.A2AConfig` is deprecated and will be removed in v2.0.0, + use `crewai_a2a.config.A2AClientConfig` or `crewai_a2a.config.A2AServerConfig` instead. """, category=FutureWarning, ) diff --git a/lib/crewai/src/crewai/a2a/errors.py b/lib/crewai-a2a/src/crewai_a2a/errors.py similarity index 100% rename from lib/crewai/src/crewai/a2a/errors.py rename to lib/crewai-a2a/src/crewai_a2a/errors.py diff --git a/lib/crewai/src/crewai/a2a/extensions/__init__.py b/lib/crewai-a2a/src/crewai_a2a/extensions/__init__.py similarity index 91% rename from lib/crewai/src/crewai/a2a/extensions/__init__.py rename to lib/crewai-a2a/src/crewai_a2a/extensions/__init__.py index b21ae10ad..ef066ca96 100644 --- a/lib/crewai/src/crewai/a2a/extensions/__init__.py +++ b/lib/crewai-a2a/src/crewai_a2a/extensions/__init__.py @@ -13,13 +13,13 @@ via the X-A2A-Extensions header. See: https://a2a-protocol.org/latest/topics/extensions/ """ -from crewai.a2a.extensions.base import ( +from crewai_a2a.extensions.base import ( A2AExtension, ConversationState, ExtensionRegistry, ValidatedA2AExtension, ) -from crewai.a2a.extensions.server import ( +from crewai_a2a.extensions.server import ( ExtensionContext, ServerExtension, ServerExtensionRegistry, diff --git a/lib/crewai/src/crewai/a2a/extensions/a2ui/__init__.py b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/__init__.py similarity index 89% rename from lib/crewai/src/crewai/a2a/extensions/a2ui/__init__.py rename to lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/__init__.py index 72e6a22d0..6bd6ce502 100644 --- a/lib/crewai/src/crewai/a2a/extensions/a2ui/__init__.py +++ b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/__init__.py @@ -1,6 +1,6 @@ """A2UI (Agent to UI) declarative UI protocol support for CrewAI.""" -from crewai.a2a.extensions.a2ui.catalog import ( +from crewai_a2a.extensions.a2ui.catalog import ( AudioPlayer, Button, Card, @@ -20,8 +20,8 @@ from crewai.a2a.extensions.a2ui.catalog import ( TextField, Video, ) -from crewai.a2a.extensions.a2ui.client_extension import A2UIClientExtension -from crewai.a2a.extensions.a2ui.models import ( +from crewai_a2a.extensions.a2ui.client_extension import A2UIClientExtension +from crewai_a2a.extensions.a2ui.models import ( A2UIEvent, A2UIMessage, A2UIResponse, @@ -31,13 +31,13 @@ from crewai.a2a.extensions.a2ui.models import ( SurfaceUpdate, UserAction, ) -from crewai.a2a.extensions.a2ui.server_extension import ( +from crewai_a2a.extensions.a2ui.server_extension import ( A2UI_STANDARD_CATALOG_ID, A2UI_V09_BASIC_CATALOG_ID, A2UI_V09_EXTENSION_URI, A2UIServerExtension, ) -from crewai.a2a.extensions.a2ui.v0_9 import ( +from crewai_a2a.extensions.a2ui.v0_9 import ( A2UIEventV09, A2UIMessageV09, ActionEvent, @@ -68,7 +68,7 @@ from crewai.a2a.extensions.a2ui.v0_9 import ( UpdateDataModel, VideoV09, ) -from crewai.a2a.extensions.a2ui.validator import ( +from crewai_a2a.extensions.a2ui.validator import ( validate_a2ui_event, validate_a2ui_event_v09, validate_a2ui_message, diff --git a/lib/crewai/src/crewai/a2a/extensions/a2ui/catalog.py b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/catalog.py similarity index 100% rename from lib/crewai/src/crewai/a2a/extensions/a2ui/catalog.py rename to lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/catalog.py diff --git a/lib/crewai/src/crewai/a2a/extensions/a2ui/client_extension.py b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/client_extension.py similarity index 98% rename from lib/crewai/src/crewai/a2a/extensions/a2ui/client_extension.py rename to lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/client_extension.py index de1047796..1ba9f462e 100644 --- a/lib/crewai/src/crewai/a2a/extensions/a2ui/client_extension.py +++ b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/client_extension.py @@ -10,18 +10,18 @@ from pydantic import Field from pydantic.dataclasses import dataclass from typing_extensions import TypeIs, TypedDict -from crewai.a2a.extensions.a2ui.models import extract_a2ui_json_objects -from crewai.a2a.extensions.a2ui.prompt import ( +from crewai_a2a.extensions.a2ui.models import extract_a2ui_json_objects +from crewai_a2a.extensions.a2ui.prompt import ( build_a2ui_system_prompt, build_a2ui_v09_system_prompt, ) -from crewai.a2a.extensions.a2ui.server_extension import ( +from crewai_a2a.extensions.a2ui.server_extension import ( A2UI_MIME_TYPE, A2UI_STANDARD_CATALOG_ID, A2UI_V09_BASIC_CATALOG_ID, ) -from crewai.a2a.extensions.a2ui.v0_9 import extract_a2ui_v09_json_objects -from crewai.a2a.extensions.a2ui.validator import ( +from crewai_a2a.extensions.a2ui.v0_9 import extract_a2ui_v09_json_objects +from crewai_a2a.extensions.a2ui.validator import ( A2UIValidationError, validate_a2ui_message, validate_a2ui_message_v09, @@ -30,7 +30,6 @@ from crewai.a2a.extensions.a2ui.validator import ( if TYPE_CHECKING: from a2a.types import Message - from crewai.agent.core import Agent diff --git a/lib/crewai/src/crewai/a2a/extensions/a2ui/models.py b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/models.py similarity index 100% rename from lib/crewai/src/crewai/a2a/extensions/a2ui/models.py rename to lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/models.py diff --git a/lib/crewai/src/crewai/a2a/extensions/a2ui/prompt.py b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/prompt.py similarity index 96% rename from lib/crewai/src/crewai/a2a/extensions/a2ui/prompt.py rename to lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/prompt.py index 1b6e01cfc..b4af5a5fd 100644 --- a/lib/crewai/src/crewai/a2a/extensions/a2ui/prompt.py +++ b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/prompt.py @@ -4,13 +4,13 @@ from __future__ import annotations import json -from crewai.a2a.extensions.a2ui.catalog import STANDARD_CATALOG_COMPONENTS -from crewai.a2a.extensions.a2ui.schema import load_schema -from crewai.a2a.extensions.a2ui.server_extension import ( +from crewai_a2a.extensions.a2ui.catalog import STANDARD_CATALOG_COMPONENTS +from crewai_a2a.extensions.a2ui.schema import load_schema +from crewai_a2a.extensions.a2ui.server_extension import ( A2UI_EXTENSION_URI, A2UI_V09_BASIC_CATALOG_ID, ) -from crewai.a2a.extensions.a2ui.v0_9 import ( +from crewai_a2a.extensions.a2ui.v0_9 import ( BASIC_CATALOG_COMPONENTS as V09_CATALOG_COMPONENTS, BASIC_CATALOG_FUNCTIONS, ) diff --git a/lib/crewai/src/crewai/a2a/extensions/a2ui/schema/__init__.py b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/__init__.py similarity index 100% rename from lib/crewai/src/crewai/a2a/extensions/a2ui/schema/__init__.py rename to lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/__init__.py diff --git a/lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_8/client_to_server.json b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_8/client_to_server.json similarity index 100% rename from lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_8/client_to_server.json rename to lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_8/client_to_server.json diff --git a/lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_8/server_to_client.json b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_8/server_to_client.json similarity index 100% rename from lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_8/server_to_client.json rename to lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_8/server_to_client.json diff --git a/lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_8/server_to_client_with_standard_catalog.json b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_8/server_to_client_with_standard_catalog.json similarity index 100% rename from lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_8/server_to_client_with_standard_catalog.json rename to lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_8/server_to_client_with_standard_catalog.json diff --git a/lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_8/standard_catalog_definition.json b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_8/standard_catalog_definition.json similarity index 100% rename from lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_8/standard_catalog_definition.json rename to lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_8/standard_catalog_definition.json diff --git a/lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_9/basic_catalog.json b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_9/basic_catalog.json similarity index 100% rename from lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_9/basic_catalog.json rename to lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_9/basic_catalog.json diff --git a/lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_9/client_capabilities.json b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_9/client_capabilities.json similarity index 100% rename from lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_9/client_capabilities.json rename to lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_9/client_capabilities.json diff --git a/lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_9/client_data_model.json b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_9/client_data_model.json similarity index 100% rename from lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_9/client_data_model.json rename to lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_9/client_data_model.json diff --git a/lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_9/client_to_server.json b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_9/client_to_server.json similarity index 100% rename from lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_9/client_to_server.json rename to lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_9/client_to_server.json diff --git a/lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_9/common_types.json b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_9/common_types.json similarity index 100% rename from lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_9/common_types.json rename to lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_9/common_types.json diff --git a/lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_9/server_capabilities.json b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_9/server_capabilities.json similarity index 100% rename from lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_9/server_capabilities.json rename to lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_9/server_capabilities.json diff --git a/lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_9/server_to_client.json b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_9/server_to_client.json similarity index 100% rename from lib/crewai/src/crewai/a2a/extensions/a2ui/schema/v0_9/server_to_client.json rename to lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/schema/v0_9/server_to_client.json diff --git a/lib/crewai/src/crewai/a2a/extensions/a2ui/server_extension.py b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/server_extension.py similarity index 95% rename from lib/crewai/src/crewai/a2a/extensions/a2ui/server_extension.py rename to lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/server_extension.py index f2a0620f8..e942ab1e3 100644 --- a/lib/crewai/src/crewai/a2a/extensions/a2ui/server_extension.py +++ b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/server_extension.py @@ -5,16 +5,16 @@ from __future__ import annotations import logging from typing import Any -from crewai.a2a.extensions.a2ui.models import A2UIResponse, extract_a2ui_json_objects -from crewai.a2a.extensions.a2ui.v0_9 import ( +from crewai_a2a.extensions.a2ui.models import A2UIResponse, extract_a2ui_json_objects +from crewai_a2a.extensions.a2ui.v0_9 import ( extract_a2ui_v09_json_objects, ) -from crewai.a2a.extensions.a2ui.validator import ( +from crewai_a2a.extensions.a2ui.validator import ( A2UIValidationError, validate_a2ui_message, validate_a2ui_message_v09, ) -from crewai.a2a.extensions.server import ExtensionContext, ServerExtension +from crewai_a2a.extensions.server import ExtensionContext, ServerExtension logger = logging.getLogger(__name__) diff --git a/lib/crewai/src/crewai/a2a/extensions/a2ui/v0_9.py b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/v0_9.py similarity index 100% rename from lib/crewai/src/crewai/a2a/extensions/a2ui/v0_9.py rename to lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/v0_9.py diff --git a/lib/crewai/src/crewai/a2a/extensions/a2ui/validator.py b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/validator.py similarity index 97% rename from lib/crewai/src/crewai/a2a/extensions/a2ui/validator.py rename to lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/validator.py index 7bfc80dec..49ecbeba5 100644 --- a/lib/crewai/src/crewai/a2a/extensions/a2ui/validator.py +++ b/lib/crewai-a2a/src/crewai_a2a/extensions/a2ui/validator.py @@ -6,7 +6,7 @@ from typing import Any from pydantic import BaseModel, ValidationError -from crewai.a2a.extensions.a2ui.catalog import ( +from crewai_a2a.extensions.a2ui.catalog import ( AudioPlayer, Button, Card, @@ -26,8 +26,8 @@ from crewai.a2a.extensions.a2ui.catalog import ( TextField, Video, ) -from crewai.a2a.extensions.a2ui.models import A2UIEvent, A2UIMessage -from crewai.a2a.extensions.a2ui.v0_9 import ( +from crewai_a2a.extensions.a2ui.models import A2UIEvent, A2UIMessage +from crewai_a2a.extensions.a2ui.v0_9 import ( A2UIEventV09, A2UIMessageV09, AudioPlayerV09, diff --git a/lib/crewai/src/crewai/a2a/extensions/base.py b/lib/crewai-a2a/src/crewai_a2a/extensions/base.py similarity index 99% rename from lib/crewai/src/crewai/a2a/extensions/base.py rename to lib/crewai-a2a/src/crewai_a2a/extensions/base.py index d9a280506..e8d912d17 100644 --- a/lib/crewai/src/crewai/a2a/extensions/base.py +++ b/lib/crewai-a2a/src/crewai_a2a/extensions/base.py @@ -19,7 +19,6 @@ from pydantic import BeforeValidator if TYPE_CHECKING: from a2a.types import Message - from crewai.agent.core import Agent diff --git a/lib/crewai/src/crewai/a2a/extensions/registry.py b/lib/crewai-a2a/src/crewai_a2a/extensions/registry.py similarity index 97% rename from lib/crewai/src/crewai/a2a/extensions/registry.py rename to lib/crewai-a2a/src/crewai_a2a/extensions/registry.py index 4d195961b..9403de2a0 100644 --- a/lib/crewai/src/crewai/a2a/extensions/registry.py +++ b/lib/crewai-a2a/src/crewai_a2a/extensions/registry.py @@ -18,8 +18,8 @@ from a2a.extensions.common import ( ) from a2a.types import AgentCard, AgentExtension -from crewai.a2a.config import A2AClientConfig, A2AConfig -from crewai.a2a.extensions.base import ExtensionRegistry +from crewai_a2a.config import A2AClientConfig, A2AConfig +from crewai_a2a.extensions.base import ExtensionRegistry def get_extensions_from_config( diff --git a/lib/crewai/src/crewai/a2a/extensions/server.py b/lib/crewai-a2a/src/crewai_a2a/extensions/server.py similarity index 100% rename from lib/crewai/src/crewai/a2a/extensions/server.py rename to lib/crewai-a2a/src/crewai_a2a/extensions/server.py diff --git a/lib/crewai/src/crewai/a2a/task_helpers.py b/lib/crewai-a2a/src/crewai_a2a/task_helpers.py similarity index 99% rename from lib/crewai/src/crewai/a2a/task_helpers.py rename to lib/crewai-a2a/src/crewai_a2a/task_helpers.py index 979652e26..1eb2c0062 100644 --- a/lib/crewai/src/crewai/a2a/task_helpers.py +++ b/lib/crewai-a2a/src/crewai_a2a/task_helpers.py @@ -18,13 +18,12 @@ from a2a.types import ( TaskStatusUpdateEvent, TextPart, ) -from typing_extensions import NotRequired, TypedDict - from crewai.events.event_bus import crewai_event_bus from crewai.events.types.a2a_events import ( A2AConnectionErrorEvent, A2AResponseReceivedEvent, ) +from typing_extensions import NotRequired, TypedDict if TYPE_CHECKING: diff --git a/lib/crewai/src/crewai/a2a/templates.py b/lib/crewai-a2a/src/crewai_a2a/templates.py similarity index 100% rename from lib/crewai/src/crewai/a2a/templates.py rename to lib/crewai-a2a/src/crewai_a2a/templates.py diff --git a/lib/crewai/src/crewai/a2a/types.py b/lib/crewai-a2a/src/crewai_a2a/types.py similarity index 98% rename from lib/crewai/src/crewai/a2a/types.py rename to lib/crewai-a2a/src/crewai_a2a/types.py index 5b06f8b8b..3b9fb7922 100644 --- a/lib/crewai/src/crewai/a2a/types.py +++ b/lib/crewai-a2a/src/crewai_a2a/types.py @@ -15,7 +15,7 @@ from typing_extensions import NotRequired, TypedDict try: - from crewai.a2a.updates import ( + from crewai_a2a.updates import ( PollingConfig, PollingHandler, PushNotificationConfig, diff --git a/lib/crewai/src/crewai/a2a/updates/__init__.py b/lib/crewai-a2a/src/crewai_a2a/updates/__init__.py similarity index 62% rename from lib/crewai/src/crewai/a2a/updates/__init__.py rename to lib/crewai-a2a/src/crewai_a2a/updates/__init__.py index 953eb48c3..5c9f98c05 100644 --- a/lib/crewai/src/crewai/a2a/updates/__init__.py +++ b/lib/crewai-a2a/src/crewai_a2a/updates/__init__.py @@ -1,6 +1,6 @@ """A2A update mechanism configuration types.""" -from crewai.a2a.updates.base import ( +from crewai_a2a.updates.base import ( BaseHandlerKwargs, PollingHandlerKwargs, PushNotificationHandlerKwargs, @@ -8,12 +8,12 @@ from crewai.a2a.updates.base import ( StreamingHandlerKwargs, UpdateHandler, ) -from crewai.a2a.updates.polling.config import PollingConfig -from crewai.a2a.updates.polling.handler import PollingHandler -from crewai.a2a.updates.push_notifications.config import PushNotificationConfig -from crewai.a2a.updates.push_notifications.handler import PushNotificationHandler -from crewai.a2a.updates.streaming.config import StreamingConfig -from crewai.a2a.updates.streaming.handler import StreamingHandler +from crewai_a2a.updates.polling.config import PollingConfig +from crewai_a2a.updates.polling.handler import PollingHandler +from crewai_a2a.updates.push_notifications.config import PushNotificationConfig +from crewai_a2a.updates.push_notifications.handler import PushNotificationHandler +from crewai_a2a.updates.streaming.config import StreamingConfig +from crewai_a2a.updates.streaming.handler import StreamingHandler UpdateConfig = PollingConfig | StreamingConfig | PushNotificationConfig diff --git a/lib/crewai/src/crewai/a2a/updates/base.py b/lib/crewai-a2a/src/crewai_a2a/updates/base.py similarity index 97% rename from lib/crewai/src/crewai/a2a/updates/base.py rename to lib/crewai-a2a/src/crewai_a2a/updates/base.py index bec2e2795..1344cfe38 100644 --- a/lib/crewai/src/crewai/a2a/updates/base.py +++ b/lib/crewai-a2a/src/crewai_a2a/updates/base.py @@ -29,8 +29,8 @@ if TYPE_CHECKING: from a2a.client import Client from a2a.types import AgentCard, Message, Task - from crewai.a2a.task_helpers import TaskStateResult - from crewai.a2a.updates.push_notifications.config import PushNotificationConfig + from crewai_a2a.task_helpers import TaskStateResult + from crewai_a2a.updates.push_notifications.config import PushNotificationConfig class BaseHandlerKwargs(TypedDict, total=False): diff --git a/lib/crewai/src/crewai/a2a/updates/polling/__init__.py b/lib/crewai-a2a/src/crewai_a2a/updates/polling/__init__.py similarity index 100% rename from lib/crewai/src/crewai/a2a/updates/polling/__init__.py rename to lib/crewai-a2a/src/crewai_a2a/updates/polling/__init__.py diff --git a/lib/crewai/src/crewai/a2a/updates/polling/config.py b/lib/crewai-a2a/src/crewai_a2a/updates/polling/config.py similarity index 100% rename from lib/crewai/src/crewai/a2a/updates/polling/config.py rename to lib/crewai-a2a/src/crewai_a2a/updates/polling/config.py diff --git a/lib/crewai/src/crewai/a2a/updates/polling/handler.py b/lib/crewai-a2a/src/crewai_a2a/updates/polling/handler.py similarity index 98% rename from lib/crewai/src/crewai/a2a/updates/polling/handler.py rename to lib/crewai-a2a/src/crewai_a2a/updates/polling/handler.py index dad5bca57..30fbf90e5 100644 --- a/lib/crewai/src/crewai/a2a/updates/polling/handler.py +++ b/lib/crewai-a2a/src/crewai_a2a/updates/polling/handler.py @@ -18,17 +18,6 @@ from a2a.types import ( TaskState, TextPart, ) -from typing_extensions import Unpack - -from crewai.a2a.errors import A2APollingTimeoutError -from crewai.a2a.task_helpers import ( - ACTIONABLE_STATES, - TERMINAL_STATES, - TaskStateResult, - process_task_state, - send_message_and_get_task_id, -) -from crewai.a2a.updates.base import PollingHandlerKwargs from crewai.events.event_bus import crewai_event_bus from crewai.events.types.a2a_events import ( A2AConnectionErrorEvent, @@ -36,6 +25,17 @@ from crewai.events.types.a2a_events import ( A2APollingStatusEvent, A2AResponseReceivedEvent, ) +from typing_extensions import Unpack + +from crewai_a2a.errors import A2APollingTimeoutError +from crewai_a2a.task_helpers import ( + ACTIONABLE_STATES, + TERMINAL_STATES, + TaskStateResult, + process_task_state, + send_message_and_get_task_id, +) +from crewai_a2a.updates.base import PollingHandlerKwargs if TYPE_CHECKING: diff --git a/lib/crewai/src/crewai/a2a/updates/push_notifications/__init__.py b/lib/crewai-a2a/src/crewai_a2a/updates/push_notifications/__init__.py similarity index 100% rename from lib/crewai/src/crewai/a2a/updates/push_notifications/__init__.py rename to lib/crewai-a2a/src/crewai_a2a/updates/push_notifications/__init__.py diff --git a/lib/crewai/src/crewai/a2a/updates/push_notifications/config.py b/lib/crewai-a2a/src/crewai_a2a/updates/push_notifications/config.py similarity index 94% rename from lib/crewai/src/crewai/a2a/updates/push_notifications/config.py rename to lib/crewai-a2a/src/crewai_a2a/updates/push_notifications/config.py index de81dbe80..d0f486cf0 100644 --- a/lib/crewai/src/crewai/a2a/updates/push_notifications/config.py +++ b/lib/crewai-a2a/src/crewai_a2a/updates/push_notifications/config.py @@ -7,8 +7,8 @@ from typing import Annotated from a2a.types import PushNotificationAuthenticationInfo from pydantic import AnyHttpUrl, BaseModel, BeforeValidator, Field -from crewai.a2a.updates.base import PushNotificationResultStore -from crewai.a2a.updates.push_notifications.signature import WebhookSignatureConfig +from crewai_a2a.updates.base import PushNotificationResultStore +from crewai_a2a.updates.push_notifications.signature import WebhookSignatureConfig def _coerce_signature( diff --git a/lib/crewai/src/crewai/a2a/updates/push_notifications/handler.py b/lib/crewai-a2a/src/crewai_a2a/updates/push_notifications/handler.py similarity index 99% rename from lib/crewai/src/crewai/a2a/updates/push_notifications/handler.py rename to lib/crewai-a2a/src/crewai_a2a/updates/push_notifications/handler.py index 783bf6483..19add538b 100644 --- a/lib/crewai/src/crewai/a2a/updates/push_notifications/handler.py +++ b/lib/crewai-a2a/src/crewai_a2a/updates/push_notifications/handler.py @@ -16,19 +16,6 @@ from a2a.types import ( TaskState, TextPart, ) -from typing_extensions import Unpack - -from crewai.a2a.task_helpers import ( - TaskStateResult, - process_task_state, - send_message_and_get_task_id, -) -from crewai.a2a.updates.base import ( - CommonParams, - PushNotificationHandlerKwargs, - PushNotificationResultStore, - extract_common_params, -) from crewai.events.event_bus import crewai_event_bus from crewai.events.types.a2a_events import ( A2AConnectionErrorEvent, @@ -36,6 +23,19 @@ from crewai.events.types.a2a_events import ( A2APushNotificationTimeoutEvent, A2AResponseReceivedEvent, ) +from typing_extensions import Unpack + +from crewai_a2a.task_helpers import ( + TaskStateResult, + process_task_state, + send_message_and_get_task_id, +) +from crewai_a2a.updates.base import ( + CommonParams, + PushNotificationHandlerKwargs, + PushNotificationResultStore, + extract_common_params, +) if TYPE_CHECKING: diff --git a/lib/crewai/src/crewai/a2a/updates/push_notifications/signature.py b/lib/crewai-a2a/src/crewai_a2a/updates/push_notifications/signature.py similarity index 100% rename from lib/crewai/src/crewai/a2a/updates/push_notifications/signature.py rename to lib/crewai-a2a/src/crewai_a2a/updates/push_notifications/signature.py diff --git a/lib/crewai/src/crewai/a2a/updates/streaming/__init__.py b/lib/crewai-a2a/src/crewai_a2a/updates/streaming/__init__.py similarity index 100% rename from lib/crewai/src/crewai/a2a/updates/streaming/__init__.py rename to lib/crewai-a2a/src/crewai_a2a/updates/streaming/__init__.py diff --git a/lib/crewai/src/crewai/a2a/updates/streaming/config.py b/lib/crewai-a2a/src/crewai_a2a/updates/streaming/config.py similarity index 100% rename from lib/crewai/src/crewai/a2a/updates/streaming/config.py rename to lib/crewai-a2a/src/crewai_a2a/updates/streaming/config.py diff --git a/lib/crewai/src/crewai/a2a/updates/streaming/handler.py b/lib/crewai-a2a/src/crewai_a2a/updates/streaming/handler.py similarity index 99% rename from lib/crewai/src/crewai/a2a/updates/streaming/handler.py rename to lib/crewai-a2a/src/crewai_a2a/updates/streaming/handler.py index 9b0c21d12..fc5abcbcd 100644 --- a/lib/crewai/src/crewai/a2a/updates/streaming/handler.py +++ b/lib/crewai-a2a/src/crewai_a2a/updates/streaming/handler.py @@ -22,18 +22,6 @@ from a2a.types import ( TaskStatusUpdateEvent, TextPart, ) -from typing_extensions import Unpack - -from crewai.a2a.task_helpers import ( - ACTIONABLE_STATES, - TERMINAL_STATES, - TaskStateResult, - process_task_state, -) -from crewai.a2a.updates.base import StreamingHandlerKwargs, extract_common_params -from crewai.a2a.updates.streaming.params import ( - process_status_update, -) from crewai.events.event_bus import crewai_event_bus from crewai.events.types.a2a_events import ( A2AArtifactReceivedEvent, @@ -42,6 +30,18 @@ from crewai.events.types.a2a_events import ( A2AStreamingChunkEvent, A2AStreamingStartedEvent, ) +from typing_extensions import Unpack + +from crewai_a2a.task_helpers import ( + ACTIONABLE_STATES, + TERMINAL_STATES, + TaskStateResult, + process_task_state, +) +from crewai_a2a.updates.base import StreamingHandlerKwargs, extract_common_params +from crewai_a2a.updates.streaming.params import ( + process_status_update, +) logger = logging.getLogger(__name__) diff --git a/lib/crewai/src/crewai/a2a/updates/streaming/params.py b/lib/crewai-a2a/src/crewai_a2a/updates/streaming/params.py similarity index 100% rename from lib/crewai/src/crewai/a2a/updates/streaming/params.py rename to lib/crewai-a2a/src/crewai_a2a/updates/streaming/params.py diff --git a/lib/crewai/src/crewai/a2a/utils/__init__.py b/lib/crewai-a2a/src/crewai_a2a/utils/__init__.py similarity index 100% rename from lib/crewai/src/crewai/a2a/utils/__init__.py rename to lib/crewai-a2a/src/crewai_a2a/utils/__init__.py diff --git a/lib/crewai/src/crewai/a2a/utils/agent_card.py b/lib/crewai-a2a/src/crewai_a2a/utils/agent_card.py similarity index 98% rename from lib/crewai/src/crewai/a2a/utils/agent_card.py rename to lib/crewai-a2a/src/crewai_a2a/utils/agent_card.py index df5886988..55a1878ea 100644 --- a/lib/crewai/src/crewai/a2a/utils/agent_card.py +++ b/lib/crewai-a2a/src/crewai_a2a/utils/agent_card.py @@ -16,15 +16,6 @@ from a2a.client.errors import A2AClientHTTPError from a2a.types import AgentCapabilities, AgentCard, AgentSkill from aiocache import cached # type: ignore[import-untyped] from aiocache.serializers import PickleSerializer # type: ignore[import-untyped] -import httpx - -from crewai.a2a.auth.client_schemes import APIKeyAuth, HTTPDigestAuth -from crewai.a2a.auth.utils import ( - _auth_store, - configure_auth_client, - retry_on_401, -) -from crewai.a2a.config import A2AServerConfig from crewai.crew import Crew from crewai.events.event_bus import crewai_event_bus from crewai.events.types.a2a_events import ( @@ -32,13 +23,23 @@ from crewai.events.types.a2a_events import ( A2AAuthenticationFailedEvent, A2AConnectionErrorEvent, ) +import httpx + +from crewai_a2a.auth.client_schemes import APIKeyAuth, HTTPDigestAuth +from crewai_a2a.auth.utils import ( + _auth_store, + configure_auth_client, + retry_on_401, +) +from crewai_a2a.config import A2AServerConfig if TYPE_CHECKING: - from crewai.a2a.auth.client_schemes import ClientAuthScheme from crewai.agent import Agent from crewai.task import Task + from crewai_a2a.auth.client_schemes import ClientAuthScheme + def _get_tls_verify(auth: ClientAuthScheme | None) -> ssl.SSLContext | bool | str: """Get TLS verify parameter from auth scheme. @@ -495,7 +496,7 @@ def _agent_to_agent_card(agent: Agent, url: str) -> AgentCard: Returns: AgentCard describing the agent's capabilities. """ - from crewai.a2a.utils.agent_card_signing import sign_agent_card + from crewai_a2a.utils.agent_card_signing import sign_agent_card server_config = _get_server_config(agent) or A2AServerConfig() @@ -529,7 +530,7 @@ def _agent_to_agent_card(agent: Agent, url: str) -> AgentCard: capabilities = server_config.capabilities if server_config.server_extensions: - from crewai.a2a.extensions.server import ServerExtensionRegistry + from crewai_a2a.extensions.server import ServerExtensionRegistry registry = ServerExtensionRegistry(server_config.server_extensions) ext_list = registry.get_agent_extensions() diff --git a/lib/crewai/src/crewai/a2a/utils/agent_card_signing.py b/lib/crewai-a2a/src/crewai_a2a/utils/agent_card_signing.py similarity index 99% rename from lib/crewai/src/crewai/a2a/utils/agent_card_signing.py rename to lib/crewai-a2a/src/crewai_a2a/utils/agent_card_signing.py index d869020af..9dfe0ab89 100644 --- a/lib/crewai/src/crewai/a2a/utils/agent_card_signing.py +++ b/lib/crewai-a2a/src/crewai_a2a/utils/agent_card_signing.py @@ -5,7 +5,7 @@ JSON Web Signatures (JWS) as per RFC 7515. Signed agent cards allow clients to verify the authenticity and integrity of agent card information. Example: - >>> from crewai.a2a.utils.agent_card_signing import sign_agent_card + >>> from crewai_a2a.utils.agent_card_signing import sign_agent_card >>> signature = sign_agent_card(agent_card, private_key_pem, key_id="key-1") >>> card_with_sig = card.model_copy(update={"signatures": [signature]}) """ diff --git a/lib/crewai/src/crewai/a2a/utils/content_type.py b/lib/crewai-a2a/src/crewai_a2a/utils/content_type.py similarity index 99% rename from lib/crewai/src/crewai/a2a/utils/content_type.py rename to lib/crewai-a2a/src/crewai_a2a/utils/content_type.py index a18a9072e..886585ceb 100644 --- a/lib/crewai/src/crewai/a2a/utils/content_type.py +++ b/lib/crewai-a2a/src/crewai_a2a/utils/content_type.py @@ -10,7 +10,6 @@ from dataclasses import dataclass from typing import TYPE_CHECKING, Annotated, Final, Literal, cast from a2a.types import Part - from crewai.events.event_bus import crewai_event_bus from crewai.events.types.a2a_events import A2AContentTypeNegotiatedEvent diff --git a/lib/crewai/src/crewai/a2a/utils/delegation.py b/lib/crewai-a2a/src/crewai_a2a/utils/delegation.py similarity index 98% rename from lib/crewai/src/crewai/a2a/utils/delegation.py rename to lib/crewai-a2a/src/crewai_a2a/utils/delegation.py index c634aab1d..32b1611a6 100644 --- a/lib/crewai/src/crewai/a2a/utils/delegation.py +++ b/lib/crewai-a2a/src/crewai_a2a/utils/delegation.py @@ -23,48 +23,6 @@ from a2a.types import ( Role, TextPart, ) -import httpx -from pydantic import BaseModel - -from crewai.a2a.auth.client_schemes import APIKeyAuth, HTTPDigestAuth -from crewai.a2a.auth.utils import ( - _auth_store, - configure_auth_client, - validate_auth_against_agent_card, -) -from crewai.a2a.config import ClientTransportConfig, GRPCClientConfig -from crewai.a2a.extensions.registry import ( - ExtensionsMiddleware, - validate_required_extensions, -) -from crewai.a2a.task_helpers import TaskStateResult -from crewai.a2a.types import ( - HANDLER_REGISTRY, - HandlerType, - PartsDict, - PartsMetadataDict, - TransportType, -) -from crewai.a2a.updates import ( - PollingConfig, - PushNotificationConfig, - StreamingHandler, - UpdateConfig, -) -from crewai.a2a.utils.agent_card import ( - _afetch_agent_card_cached, - _get_tls_verify, - _prepare_auth_headers, -) -from crewai.a2a.utils.content_type import ( - DEFAULT_CLIENT_OUTPUT_MODES, - negotiate_content_types, -) -from crewai.a2a.utils.transport import ( - NegotiatedTransport, - TransportNegotiationError, - negotiate_transport, -) from crewai.events.event_bus import crewai_event_bus from crewai.events.types.a2a_events import ( A2AConversationStartedEvent, @@ -72,6 +30,48 @@ from crewai.events.types.a2a_events import ( A2ADelegationStartedEvent, A2AMessageSentEvent, ) +import httpx +from pydantic import BaseModel + +from crewai_a2a.auth.client_schemes import APIKeyAuth, HTTPDigestAuth +from crewai_a2a.auth.utils import ( + _auth_store, + configure_auth_client, + validate_auth_against_agent_card, +) +from crewai_a2a.config import ClientTransportConfig, GRPCClientConfig +from crewai_a2a.extensions.registry import ( + ExtensionsMiddleware, + validate_required_extensions, +) +from crewai_a2a.task_helpers import TaskStateResult +from crewai_a2a.types import ( + HANDLER_REGISTRY, + HandlerType, + PartsDict, + PartsMetadataDict, + TransportType, +) +from crewai_a2a.updates import ( + PollingConfig, + PushNotificationConfig, + StreamingHandler, + UpdateConfig, +) +from crewai_a2a.utils.agent_card import ( + _afetch_agent_card_cached, + _get_tls_verify, + _prepare_auth_headers, +) +from crewai_a2a.utils.content_type import ( + DEFAULT_CLIENT_OUTPUT_MODES, + negotiate_content_types, +) +from crewai_a2a.utils.transport import ( + NegotiatedTransport, + TransportNegotiationError, + negotiate_transport, +) logger = logging.getLogger(__name__) @@ -80,7 +80,7 @@ logger = logging.getLogger(__name__) if TYPE_CHECKING: from a2a.types import Message - from crewai.a2a.auth.client_schemes import ClientAuthScheme + from crewai_a2a.auth.client_schemes import ClientAuthScheme _DEFAULT_TRANSPORT: Final[TransportType] = "JSONRPC" @@ -771,7 +771,7 @@ def _create_grpc_channel_factory( auth_metadata: list[tuple[str, str]] = [] if auth is not None: - from crewai.a2a.auth.client_schemes import ( + from crewai_a2a.auth.client_schemes import ( APIKeyAuth, BearerTokenAuth, HTTPBasicAuth, diff --git a/lib/crewai/src/crewai/a2a/utils/logging.py b/lib/crewai-a2a/src/crewai_a2a/utils/logging.py similarity index 98% rename from lib/crewai/src/crewai/a2a/utils/logging.py rename to lib/crewai-a2a/src/crewai_a2a/utils/logging.py index 585d1d8f3..f7470cafd 100644 --- a/lib/crewai/src/crewai/a2a/utils/logging.py +++ b/lib/crewai-a2a/src/crewai_a2a/utils/logging.py @@ -103,7 +103,7 @@ class LogContext: _log_context.reset(self._token) -def configure_json_logging(logger_name: str = "crewai.a2a") -> None: +def configure_json_logging(logger_name: str = "crewai_a2a") -> None: """Configure JSON logging for the A2A module. Args: diff --git a/lib/crewai/src/crewai/a2a/utils/response_model.py b/lib/crewai-a2a/src/crewai_a2a/utils/response_model.py similarity index 98% rename from lib/crewai/src/crewai/a2a/utils/response_model.py rename to lib/crewai-a2a/src/crewai_a2a/utils/response_model.py index 1359e2f10..1aa3491fe 100644 --- a/lib/crewai/src/crewai/a2a/utils/response_model.py +++ b/lib/crewai-a2a/src/crewai_a2a/utils/response_model.py @@ -4,10 +4,10 @@ from __future__ import annotations from typing import TypeAlias +from crewai.types.utils import create_literals_from_strings from pydantic import BaseModel, Field, create_model -from crewai.a2a.config import A2AClientConfig, A2AConfig, A2AServerConfig -from crewai.types.utils import create_literals_from_strings +from crewai_a2a.config import A2AClientConfig, A2AConfig, A2AServerConfig A2AConfigTypes: TypeAlias = A2AConfig | A2AServerConfig | A2AClientConfig diff --git a/lib/crewai/src/crewai/a2a/utils/task.py b/lib/crewai-a2a/src/crewai_a2a/utils/task.py similarity index 98% rename from lib/crewai/src/crewai/a2a/utils/task.py rename to lib/crewai-a2a/src/crewai_a2a/utils/task.py index 6af935bb3..c38b76411 100644 --- a/lib/crewai/src/crewai/a2a/utils/task.py +++ b/lib/crewai-a2a/src/crewai_a2a/utils/task.py @@ -37,11 +37,6 @@ from a2a.utils import ( ) from a2a.utils.errors import ServerError from aiocache import SimpleMemoryCache, caches # type: ignore[import-untyped] -from pydantic import BaseModel -from typing_extensions import TypedDict - -from crewai.a2a.utils.agent_card import _get_server_config -from crewai.a2a.utils.content_type import validate_message_parts from crewai.events.event_bus import crewai_event_bus from crewai.events.types.a2a_events import ( A2AServerTaskCanceledEvent, @@ -51,12 +46,18 @@ from crewai.events.types.a2a_events import ( ) from crewai.task import Task from crewai.utilities.pydantic_schema_utils import create_model_from_schema +from pydantic import BaseModel +from typing_extensions import TypedDict + +from crewai_a2a.utils.agent_card import _get_server_config +from crewai_a2a.utils.content_type import validate_message_parts if TYPE_CHECKING: - from crewai.a2a.extensions.server import ExtensionContext, ServerExtensionRegistry from crewai.agent import Agent + from crewai_a2a.extensions.server import ExtensionContext, ServerExtensionRegistry + logger = logging.getLogger(__name__) diff --git a/lib/crewai/src/crewai/a2a/utils/transport.py b/lib/crewai-a2a/src/crewai_a2a/utils/transport.py similarity index 99% rename from lib/crewai/src/crewai/a2a/utils/transport.py rename to lib/crewai-a2a/src/crewai_a2a/utils/transport.py index cc57ba20c..d4667e1de 100644 --- a/lib/crewai/src/crewai/a2a/utils/transport.py +++ b/lib/crewai-a2a/src/crewai_a2a/utils/transport.py @@ -11,7 +11,6 @@ from dataclasses import dataclass from typing import Final, Literal from a2a.types import AgentCard, AgentInterface - from crewai.events.event_bus import crewai_event_bus from crewai.events.types.a2a_events import A2ATransportNegotiatedEvent diff --git a/lib/crewai/src/crewai/a2a/wrapper.py b/lib/crewai-a2a/src/crewai_a2a/wrapper.py similarity index 99% rename from lib/crewai/src/crewai/a2a/wrapper.py rename to lib/crewai-a2a/src/crewai_a2a/wrapper.py index 7f54d60db..f2bf6679f 100644 --- a/lib/crewai/src/crewai/a2a/wrapper.py +++ b/lib/crewai-a2a/src/crewai_a2a/wrapper.py @@ -15,33 +15,6 @@ from types import MethodType from typing import TYPE_CHECKING, Any, NamedTuple from a2a.types import Role, TaskState -from pydantic import BaseModel, ValidationError - -from crewai.a2a.config import A2AClientConfig, A2AConfig -from crewai.a2a.extensions.base import ( - A2AExtension, - ConversationState, - ExtensionRegistry, -) -from crewai.a2a.task_helpers import TaskStateResult -from crewai.a2a.templates import ( - AVAILABLE_AGENTS_TEMPLATE, - CONVERSATION_TURN_INFO_TEMPLATE, - PREVIOUS_A2A_CONVERSATION_TEMPLATE, - REMOTE_AGENT_RESPONSE_NOTICE, - UNAVAILABLE_AGENTS_NOTICE_TEMPLATE, -) -from crewai.a2a.types import AgentResponseProtocol -from crewai.a2a.utils.agent_card import ( - afetch_agent_card, - fetch_agent_card, - inject_a2a_server_methods, -) -from crewai.a2a.utils.delegation import ( - aexecute_a2a_delegation, - execute_a2a_delegation, -) -from crewai.a2a.utils.response_model import get_a2a_agents_and_response_model from crewai.events.event_bus import crewai_event_bus from crewai.events.types.a2a_events import ( A2AConversationCompletedEvent, @@ -49,11 +22,37 @@ from crewai.events.types.a2a_events import ( ) from crewai.lite_agent_output import LiteAgentOutput from crewai.task import Task +from pydantic import BaseModel, ValidationError + +from crewai_a2a.config import A2AClientConfig, A2AConfig +from crewai_a2a.extensions.base import ( + A2AExtension, + ConversationState, + ExtensionRegistry, +) +from crewai_a2a.task_helpers import TaskStateResult +from crewai_a2a.templates import ( + AVAILABLE_AGENTS_TEMPLATE, + CONVERSATION_TURN_INFO_TEMPLATE, + PREVIOUS_A2A_CONVERSATION_TEMPLATE, + REMOTE_AGENT_RESPONSE_NOTICE, + UNAVAILABLE_AGENTS_NOTICE_TEMPLATE, +) +from crewai_a2a.types import AgentResponseProtocol +from crewai_a2a.utils.agent_card import ( + afetch_agent_card, + fetch_agent_card, + inject_a2a_server_methods, +) +from crewai_a2a.utils.delegation import ( + aexecute_a2a_delegation, + execute_a2a_delegation, +) +from crewai_a2a.utils.response_model import get_a2a_agents_and_response_model if TYPE_CHECKING: from a2a.types import AgentCard, Message - from crewai.agent.core import Agent from crewai.tools.base_tool import BaseTool diff --git a/lib/crewai/tests/a2a/extensions/test_a2ui_schema_conformance.py b/lib/crewai-a2a/tests/a2a/extensions/test_a2ui_schema_conformance.py similarity index 98% rename from lib/crewai/tests/a2a/extensions/test_a2ui_schema_conformance.py rename to lib/crewai-a2a/tests/a2a/extensions/test_a2ui_schema_conformance.py index d8e903d6d..34314abea 100644 --- a/lib/crewai/tests/a2a/extensions/test_a2ui_schema_conformance.py +++ b/lib/crewai-a2a/tests/a2a/extensions/test_a2ui_schema_conformance.py @@ -9,12 +9,11 @@ from __future__ import annotations from typing import Any -import jsonschema -import pytest - from crewai.a2a.extensions.a2ui import catalog from crewai.a2a.extensions.a2ui.models import A2UIEvent, A2UIMessage from crewai.a2a.extensions.a2ui.schema import load_schema +import jsonschema +import pytest SERVER_SCHEMA = load_schema("server_to_client") @@ -206,7 +205,10 @@ VALID_COMPONENTS: dict[str, dict[str, Any]] = { "Divider": {"axis": "horizontal"}, "Modal": {"entryPointChild": "trigger", "contentChild": "body"}, "Button": {"child": "label", "action": {"name": "go"}}, - "CheckBox": {"label": {"literalString": "Accept"}, "value": {"literalBoolean": False}}, + "CheckBox": { + "label": {"literalString": "Accept"}, + "value": {"literalBoolean": False}, + }, "TextField": {"label": {"literalString": "Name"}}, "DateTimeInput": {"value": {"path": "/date"}}, "MultipleChoice": { diff --git a/lib/crewai/tests/a2a/test_a2a_integration.py b/lib/crewai-a2a/tests/a2a/test_a2a_integration.py similarity index 97% rename from lib/crewai/tests/a2a/test_a2a_integration.py rename to lib/crewai-a2a/tests/a2a/test_a2a_integration.py index 9950ee0a2..ffa76242d 100644 --- a/lib/crewai/tests/a2a/test_a2a_integration.py +++ b/lib/crewai-a2a/tests/a2a/test_a2a_integration.py @@ -3,14 +3,12 @@ from __future__ import annotations import os import uuid -import pytest -import pytest_asyncio - from a2a.client import ClientFactory -from a2a.types import AgentCard, Message, Part, Role, TaskState, TextPart - +from a2a.types import AgentCard, Message, Part, Role, Task, TaskState, TextPart from crewai.a2a.updates.polling.handler import PollingHandler from crewai.a2a.updates.streaming.handler import StreamingHandler +import pytest +import pytest_asyncio A2A_TEST_ENDPOINT = os.getenv("A2A_TEST_ENDPOINT", "http://localhost:9999") @@ -162,7 +160,7 @@ class TestA2APushNotificationHandler: ) @pytest.fixture - def mock_task(self) -> "Task": + def mock_task(self) -> Task: """Create a minimal valid task for testing.""" from a2a.types import Task, TaskStatus @@ -182,10 +180,11 @@ class TestA2APushNotificationHandler: from unittest.mock import AsyncMock, MagicMock from a2a.types import Task, TaskStatus - from pydantic import AnyHttpUrl - from crewai.a2a.updates.push_notifications.config import PushNotificationConfig - from crewai.a2a.updates.push_notifications.handler import PushNotificationHandler + from crewai.a2a.updates.push_notifications.handler import ( + PushNotificationHandler, + ) + from pydantic import AnyHttpUrl completed_task = Task( id="task-123", @@ -246,10 +245,11 @@ class TestA2APushNotificationHandler: from unittest.mock import AsyncMock, MagicMock from a2a.types import Task, TaskStatus - from pydantic import AnyHttpUrl - from crewai.a2a.updates.push_notifications.config import PushNotificationConfig - from crewai.a2a.updates.push_notifications.handler import PushNotificationHandler + from crewai.a2a.updates.push_notifications.handler import ( + PushNotificationHandler, + ) + from pydantic import AnyHttpUrl mock_store = MagicMock() mock_store.wait_for_result = AsyncMock(return_value=None) @@ -303,7 +303,9 @@ class TestA2APushNotificationHandler: """Test that push handler fails gracefully without config.""" from unittest.mock import MagicMock - from crewai.a2a.updates.push_notifications.handler import PushNotificationHandler + from crewai.a2a.updates.push_notifications.handler import ( + PushNotificationHandler, + ) mock_client = MagicMock() diff --git a/lib/crewai/tests/a2a/utils/test_agent_card.py b/lib/crewai-a2a/tests/a2a/utils/test_agent_card.py similarity index 99% rename from lib/crewai/tests/a2a/utils/test_agent_card.py rename to lib/crewai-a2a/tests/a2a/utils/test_agent_card.py index fb96710a7..cf4124cd0 100644 --- a/lib/crewai/tests/a2a/utils/test_agent_card.py +++ b/lib/crewai-a2a/tests/a2a/utils/test_agent_card.py @@ -3,7 +3,6 @@ from __future__ import annotations from a2a.types import AgentCard, AgentSkill - from crewai import Agent from crewai.a2a.config import A2AClientConfig, A2AServerConfig from crewai.a2a.utils.agent_card import inject_a2a_server_methods diff --git a/lib/crewai/tests/a2a/utils/test_task.py b/lib/crewai-a2a/tests/a2a/utils/test_task.py similarity index 98% rename from lib/crewai/tests/a2a/utils/test_task.py rename to lib/crewai-a2a/tests/a2a/utils/test_task.py index 781827ac8..dc31f72a3 100644 --- a/lib/crewai/tests/a2a/utils/test_task.py +++ b/lib/crewai-a2a/tests/a2a/utils/test_task.py @@ -6,13 +6,12 @@ import asyncio from typing import Any from unittest.mock import AsyncMock, MagicMock, patch -import pytest -import pytest_asyncio from a2a.server.agent_execution import RequestContext from a2a.server.events import EventQueue from a2a.types import Message, Task as A2ATask, TaskState, TaskStatus - from crewai.a2a.utils.task import cancel, cancellable, execute +import pytest +import pytest_asyncio @pytest.fixture @@ -85,8 +84,11 @@ class TestCancellableDecorator: assert call_count == 1 @pytest.mark.asyncio - async def test_executes_function_with_context(self, mock_context: MagicMock) -> None: + async def test_executes_function_with_context( + self, mock_context: MagicMock + ) -> None: """Function executes normally with RequestContext when not cancelled.""" + @cancellable async def my_func(context: RequestContext) -> str: await asyncio.sleep(0.01) @@ -134,6 +136,7 @@ class TestCancellableDecorator: @pytest.mark.asyncio async def test_extracts_context_from_kwargs(self, mock_context: MagicMock) -> None: """Context can be passed as keyword argument.""" + @cancellable async def my_func(value: int, context: RequestContext | None = None) -> int: return value + 1 @@ -354,6 +357,7 @@ class TestExecuteAndCancelIntegration: mock_task: MagicMock, ) -> None: """Calling cancel stops a running execute.""" + async def slow_task(**kwargs: Any) -> str: await asyncio.sleep(2.0) return "should not complete" @@ -372,4 +376,4 @@ class TestExecuteAndCancelIntegration: await cancel(mock_context, mock_event_queue) with pytest.raises(asyncio.CancelledError): - await execute_task \ No newline at end of file + await execute_task diff --git a/lib/crewai/tests/agents/test_a2a_trust_completion_status.py b/lib/crewai-a2a/tests/agents/test_a2a_trust_completion_status.py similarity index 97% rename from lib/crewai/tests/agents/test_a2a_trust_completion_status.py rename to lib/crewai-a2a/tests/agents/test_a2a_trust_completion_status.py index 6347f8e1c..cf9f74726 100644 --- a/lib/crewai/tests/agents/test_a2a_trust_completion_status.py +++ b/lib/crewai-a2a/tests/agents/test_a2a_trust_completion_status.py @@ -2,9 +2,9 @@ from unittest.mock import MagicMock, patch +from crewai.a2a.config import A2AConfig import pytest -from crewai.a2a.config import A2AConfig try: from a2a.types import Message, Role @@ -27,9 +27,8 @@ def _create_mock_agent_card(name: str = "Test", url: str = "http://test-endpoint @pytest.mark.skipif(not A2A_SDK_INSTALLED, reason="Requires a2a-sdk to be installed") def test_trust_remote_completion_status_true_returns_directly(): """When trust_remote_completion_status=True and A2A returns completed, return result directly.""" - from crewai.a2a.wrapper import _delegate_to_a2a - from crewai.a2a.types import AgentResponseProtocol from crewai import Agent, Task + from crewai.a2a.wrapper import _delegate_to_a2a a2a_config = A2AConfig( endpoint="http://test-endpoint.com", @@ -83,8 +82,8 @@ def test_trust_remote_completion_status_true_returns_directly(): @pytest.mark.skipif(not A2A_SDK_INSTALLED, reason="Requires a2a-sdk to be installed") def test_trust_remote_completion_status_false_continues_conversation(): """When trust_remote_completion_status=False and A2A returns completed, ask server agent.""" - from crewai.a2a.wrapper import _delegate_to_a2a from crewai import Agent, Task + from crewai.a2a.wrapper import _delegate_to_a2a a2a_config = A2AConfig( endpoint="http://test-endpoint.com", @@ -152,4 +151,4 @@ def test_default_trust_remote_completion_status_is_false(): endpoint="http://test-endpoint.com", ) - assert a2a_config.trust_remote_completion_status is False \ No newline at end of file + assert a2a_config.trust_remote_completion_status is False diff --git a/lib/crewai/tests/agents/test_agent_a2a_kickoff.py b/lib/crewai-a2a/tests/agents/test_agent_a2a_kickoff.py similarity index 97% rename from lib/crewai/tests/agents/test_agent_a2a_kickoff.py rename to lib/crewai-a2a/tests/agents/test_agent_a2a_kickoff.py index 00123c4cf..705df4bbd 100644 --- a/lib/crewai/tests/agents/test_agent_a2a_kickoff.py +++ b/lib/crewai-a2a/tests/agents/test_agent_a2a_kickoff.py @@ -4,10 +4,9 @@ from __future__ import annotations import os -import pytest - from crewai import Agent from crewai.a2a.config import A2AClientConfig +import pytest A2A_TEST_ENDPOINT = os.getenv( @@ -50,9 +49,7 @@ class TestAgentA2AKickoff: @pytest.mark.skip(reason="VCR cassette matching issue with agent card caching") @pytest.mark.vcr() - def test_agent_kickoff_with_calculator_skill( - self, researcher_agent: Agent - ) -> None: + def test_agent_kickoff_with_calculator_skill(self, researcher_agent: Agent) -> None: """Test that agent can delegate calculation to A2A server.""" result = researcher_agent.kickoff( "Ask the remote A2A agent to calculate 25 times 17." @@ -149,9 +146,7 @@ class TestAgentA2AKickoff: @pytest.mark.skip(reason="VCR cassette matching issue with agent card caching") @pytest.mark.vcr() - def test_agent_kickoff_with_list_messages( - self, researcher_agent: Agent - ) -> None: + def test_agent_kickoff_with_list_messages(self, researcher_agent: Agent) -> None: """Test that agent.kickoff() works with list of messages.""" messages = [ { diff --git a/lib/crewai/tests/agents/test_agent_a2a_wrapping.py b/lib/crewai-a2a/tests/agents/test_agent_a2a_wrapping.py similarity index 94% rename from lib/crewai/tests/agents/test_agent_a2a_wrapping.py rename to lib/crewai-a2a/tests/agents/test_agent_a2a_wrapping.py index 6b7d4be9f..7ae2abfcd 100644 --- a/lib/crewai/tests/agents/test_agent_a2a_wrapping.py +++ b/lib/crewai-a2a/tests/agents/test_agent_a2a_wrapping.py @@ -1,14 +1,12 @@ """Test A2A wrapper is only applied when a2a is passed to Agent.""" -from unittest.mock import patch - -import pytest - from crewai import Agent from crewai.a2a.config import A2AConfig +import pytest + try: - import a2a # noqa: F401 + import a2a A2A_SDK_INSTALLED = True except ImportError: @@ -106,6 +104,9 @@ def test_wrapper_is_applied_differently_per_instance(): a2a=a2a_config, ) - assert agent_without_a2a.execute_task.__func__ is not agent_with_a2a.execute_task.__func__ + assert ( + agent_without_a2a.execute_task.__func__ + is not agent_with_a2a.execute_task.__func__ + ) assert not hasattr(agent_without_a2a.execute_task, "__wrapped__") assert hasattr(agent_with_a2a.execute_task, "__wrapped__") diff --git a/lib/crewai/tests/cassettes/a2a/TestA2AAgentCardFetching.test_fetch_agent_card.yaml b/lib/crewai-a2a/tests/cassettes/TestA2AAgentCardFetching.test_fetch_agent_card.yaml similarity index 100% rename from lib/crewai/tests/cassettes/a2a/TestA2AAgentCardFetching.test_fetch_agent_card.yaml rename to lib/crewai-a2a/tests/cassettes/TestA2AAgentCardFetching.test_fetch_agent_card.yaml diff --git a/lib/crewai/tests/cassettes/a2a/TestA2APollingIntegration.test_polling_completes_task.yaml b/lib/crewai-a2a/tests/cassettes/TestA2APollingIntegration.test_polling_completes_task.yaml similarity index 100% rename from lib/crewai/tests/cassettes/a2a/TestA2APollingIntegration.test_polling_completes_task.yaml rename to lib/crewai-a2a/tests/cassettes/TestA2APollingIntegration.test_polling_completes_task.yaml diff --git a/lib/crewai/tests/cassettes/a2a/TestA2AStreamingIntegration.test_streaming_completes_task.yaml b/lib/crewai-a2a/tests/cassettes/TestA2AStreamingIntegration.test_streaming_completes_task.yaml similarity index 100% rename from lib/crewai/tests/cassettes/a2a/TestA2AStreamingIntegration.test_streaming_completes_task.yaml rename to lib/crewai-a2a/tests/cassettes/TestA2AStreamingIntegration.test_streaming_completes_task.yaml diff --git a/lib/crewai/tests/cassettes/a2a/TestA2ATaskOperations.test_send_message_and_get_response.yaml b/lib/crewai-a2a/tests/cassettes/TestA2ATaskOperations.test_send_message_and_get_response.yaml similarity index 100% rename from lib/crewai/tests/cassettes/a2a/TestA2ATaskOperations.test_send_message_and_get_response.yaml rename to lib/crewai-a2a/tests/cassettes/TestA2ATaskOperations.test_send_message_and_get_response.yaml diff --git a/lib/crewai/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_delegates_to_a2a.yaml b/lib/crewai-a2a/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_delegates_to_a2a.yaml similarity index 100% rename from lib/crewai/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_delegates_to_a2a.yaml rename to lib/crewai-a2a/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_delegates_to_a2a.yaml diff --git a/lib/crewai/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_handles_multi_turn_conversation.yaml b/lib/crewai-a2a/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_handles_multi_turn_conversation.yaml similarity index 100% rename from lib/crewai/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_handles_multi_turn_conversation.yaml rename to lib/crewai-a2a/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_handles_multi_turn_conversation.yaml diff --git a/lib/crewai/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_returns_lite_agent_output.yaml b/lib/crewai-a2a/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_returns_lite_agent_output.yaml similarity index 100% rename from lib/crewai/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_returns_lite_agent_output.yaml rename to lib/crewai-a2a/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_returns_lite_agent_output.yaml diff --git a/lib/crewai/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_with_calculator_skill.yaml b/lib/crewai-a2a/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_with_calculator_skill.yaml similarity index 100% rename from lib/crewai/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_with_calculator_skill.yaml rename to lib/crewai-a2a/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_with_calculator_skill.yaml diff --git a/lib/crewai/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_with_conversation_skill.yaml b/lib/crewai-a2a/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_with_conversation_skill.yaml similarity index 100% rename from lib/crewai/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_with_conversation_skill.yaml rename to lib/crewai-a2a/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_with_conversation_skill.yaml diff --git a/lib/crewai/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_with_failed_a2a_endpoint.yaml b/lib/crewai-a2a/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_with_failed_a2a_endpoint.yaml similarity index 100% rename from lib/crewai/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_with_failed_a2a_endpoint.yaml rename to lib/crewai-a2a/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_with_failed_a2a_endpoint.yaml diff --git a/lib/crewai/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_with_list_messages.yaml b/lib/crewai-a2a/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_with_list_messages.yaml similarity index 100% rename from lib/crewai/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_with_list_messages.yaml rename to lib/crewai-a2a/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_kickoff_with_list_messages.yaml diff --git a/lib/crewai/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_without_a2a_works_normally.yaml b/lib/crewai-a2a/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_without_a2a_works_normally.yaml similarity index 100% rename from lib/crewai/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_without_a2a_works_normally.yaml rename to lib/crewai-a2a/tests/cassettes/agents/TestAgentA2AKickoff.test_agent_without_a2a_works_normally.yaml diff --git a/lib/crewai/tests/cassettes/agents/TestAgentA2AKickoffAsync.test_agent_kickoff_async_delegates_to_a2a.yaml b/lib/crewai-a2a/tests/cassettes/agents/TestAgentA2AKickoffAsync.test_agent_kickoff_async_delegates_to_a2a.yaml similarity index 100% rename from lib/crewai/tests/cassettes/agents/TestAgentA2AKickoffAsync.test_agent_kickoff_async_delegates_to_a2a.yaml rename to lib/crewai-a2a/tests/cassettes/agents/TestAgentA2AKickoffAsync.test_agent_kickoff_async_delegates_to_a2a.yaml diff --git a/lib/crewai/tests/cassettes/agents/TestAgentA2AKickoffAsync.test_agent_kickoff_async_with_calculator.yaml b/lib/crewai-a2a/tests/cassettes/agents/TestAgentA2AKickoffAsync.test_agent_kickoff_async_with_calculator.yaml similarity index 100% rename from lib/crewai/tests/cassettes/agents/TestAgentA2AKickoffAsync.test_agent_kickoff_async_with_calculator.yaml rename to lib/crewai-a2a/tests/cassettes/agents/TestAgentA2AKickoffAsync.test_agent_kickoff_async_with_calculator.yaml diff --git a/lib/crewai/pyproject.toml b/lib/crewai/pyproject.toml index 5ccb5a453..bb3f2b1e2 100644 --- a/lib/crewai/pyproject.toml +++ b/lib/crewai/pyproject.toml @@ -99,10 +99,7 @@ anthropic = [ "anthropic~=0.73.0", ] a2a = [ - "a2a-sdk~=0.3.10", - "httpx-auth~=0.23.1", - "httpx-sse~=0.4.0", - "aiocache[redis,memcached]~=0.12.3", + "crewai-a2a", ] file-processing = [ "crewai-files", @@ -140,6 +137,7 @@ torchvision = [ { index = "pytorch", marker = "python_version < '3.13'" }, ] crewai-files = { workspace = true } +crewai-a2a = { workspace = true } [build-system] diff --git a/lib/crewai/src/crewai/a2a/__init__.py b/lib/crewai/src/crewai/a2a/__init__.py index 634f77708..0703f6e2f 100644 --- a/lib/crewai/src/crewai/a2a/__init__.py +++ b/lib/crewai/src/crewai/a2a/__init__.py @@ -1,10 +1,57 @@ -"""Agent-to-Agent (A2A) protocol communication module for CrewAI.""" +"""Compatibility shim: ``crewai.a2a`` re-exports :mod:`crewai_a2a`. -from crewai.a2a.config import A2AClientConfig, A2AConfig, A2AServerConfig +The package lives in the ``crewai-a2a`` distribution (install via the +``crewai[a2a]`` extra). This module aliases the old import path so existing +code using ``crewai.a2a.*`` keeps working. +""" + +from __future__ import annotations + +from collections.abc import Sequence +import importlib +from importlib.abc import Loader, MetaPathFinder +from importlib.machinery import ModuleSpec +import sys +from types import ModuleType -__all__ = [ - "A2AClientConfig", - "A2AConfig", - "A2AServerConfig", -] +try: + import crewai_a2a as _crewai_a2a +except ImportError as exc: + raise ImportError( + "crewai.a2a requires the 'crewai-a2a' package. " + "Install it with: pip install 'crewai[a2a]'" + ) from exc + + +class _A2AAliasFinder(MetaPathFinder, Loader): + _SRC = "crewai.a2a" + _DST = "crewai_a2a" + + def find_spec( + self, + fullname: str, + path: Sequence[str] | None = None, + target: ModuleType | None = None, + ) -> ModuleSpec | None: + if fullname == self._SRC or fullname.startswith(self._SRC + "."): + return ModuleSpec(fullname, self) + return None + + def create_module(self, spec: ModuleSpec) -> ModuleType: + target = self._DST + spec.name[len(self._SRC) :] + module = importlib.import_module(target) + sys.modules[spec.name] = module + return module + + def exec_module(self, module: ModuleType) -> None: + return None + + +if not any(isinstance(f, _A2AAliasFinder) for f in sys.meta_path): + sys.meta_path.insert(0, _A2AAliasFinder()) + +for _attr in getattr(_crewai_a2a, "__all__", []): + globals()[_attr] = getattr(_crewai_a2a, _attr) + +__all__ = list(getattr(_crewai_a2a, "__all__", [])) diff --git a/lib/crewai/src/crewai/a2a/auth/schemas.py b/lib/crewai/src/crewai/a2a/auth/schemas.py deleted file mode 100644 index 4c8f3c0d7..000000000 --- a/lib/crewai/src/crewai/a2a/auth/schemas.py +++ /dev/null @@ -1,71 +0,0 @@ -"""Deprecated: Authentication schemes for A2A protocol agents. - -This module is deprecated. Import from crewai.a2a.auth instead: -- crewai.a2a.auth.ClientAuthScheme (replaces AuthScheme) -- crewai.a2a.auth.BearerTokenAuth -- crewai.a2a.auth.HTTPBasicAuth -- crewai.a2a.auth.HTTPDigestAuth -- crewai.a2a.auth.APIKeyAuth -- crewai.a2a.auth.OAuth2ClientCredentials -- crewai.a2a.auth.OAuth2AuthorizationCode -""" - -from __future__ import annotations - -from typing_extensions import deprecated - -from crewai.a2a.auth.client_schemes import ( - APIKeyAuth as _APIKeyAuth, - BearerTokenAuth as _BearerTokenAuth, - ClientAuthScheme as _ClientAuthScheme, - HTTPBasicAuth as _HTTPBasicAuth, - HTTPDigestAuth as _HTTPDigestAuth, - OAuth2AuthorizationCode as _OAuth2AuthorizationCode, - OAuth2ClientCredentials as _OAuth2ClientCredentials, -) - - -@deprecated("Use ClientAuthScheme from crewai.a2a.auth instead", category=FutureWarning) -class AuthScheme(_ClientAuthScheme): - """Deprecated: Use ClientAuthScheme from crewai.a2a.auth instead.""" - - -@deprecated("Import from crewai.a2a.auth instead", category=FutureWarning) -class BearerTokenAuth(_BearerTokenAuth): - """Deprecated: Import from crewai.a2a.auth instead.""" - - -@deprecated("Import from crewai.a2a.auth instead", category=FutureWarning) -class HTTPBasicAuth(_HTTPBasicAuth): - """Deprecated: Import from crewai.a2a.auth instead.""" - - -@deprecated("Import from crewai.a2a.auth instead", category=FutureWarning) -class HTTPDigestAuth(_HTTPDigestAuth): - """Deprecated: Import from crewai.a2a.auth instead.""" - - -@deprecated("Import from crewai.a2a.auth instead", category=FutureWarning) -class APIKeyAuth(_APIKeyAuth): - """Deprecated: Import from crewai.a2a.auth instead.""" - - -@deprecated("Import from crewai.a2a.auth instead", category=FutureWarning) -class OAuth2ClientCredentials(_OAuth2ClientCredentials): - """Deprecated: Import from crewai.a2a.auth instead.""" - - -@deprecated("Import from crewai.a2a.auth instead", category=FutureWarning) -class OAuth2AuthorizationCode(_OAuth2AuthorizationCode): - """Deprecated: Import from crewai.a2a.auth instead.""" - - -__all__ = [ - "APIKeyAuth", - "AuthScheme", - "BearerTokenAuth", - "HTTPBasicAuth", - "HTTPDigestAuth", - "OAuth2AuthorizationCode", - "OAuth2ClientCredentials", -] diff --git a/pyproject.toml b/pyproject.toml index 881d7a887..66bf18d03 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -108,6 +108,7 @@ ignore-decorators = ["typing.overload"] "lib/crewai/tests/**/*.py" = ["S101", "RET504", "S105", "S106"] # Allow assert statements, unnecessary assignments, and hardcoded passwords in tests "lib/crewai-tools/tests/**/*.py" = ["S101", "RET504", "S105", "S106", "RUF012", "N818", "E402", "RUF043", "S110", "B017"] # Allow various test-specific patterns "lib/crewai-files/tests/**/*.py" = ["S101", "RET504", "S105", "S106", "B017", "F841"] # Allow assert statements and blind exception assertions in tests +"lib/crewai-a2a/tests/**/*.py" = ["S101", "RET504", "S105", "S106", "B017", "F841", "F401", "RUF012"] # Allow assert statements and blind exception assertions in tests "lib/devtools/tests/**/*.py" = ["S101"] @@ -121,7 +122,7 @@ warn_return_any = true show_error_codes = true warn_unused_ignores = true python_version = "3.12" -exclude = "(?x)(^lib/crewai/src/crewai/cli/templates/|^lib/crewai/tests/|^lib/crewai-tools/tests/|^lib/crewai-files/tests/)" +exclude = "(?x)(^lib/crewai/src/crewai/cli/templates/|^lib/crewai/tests/|^lib/crewai-tools/tests/|^lib/crewai-files/tests/|^lib/crewai-a2a/tests/)" plugins = ["pydantic.mypy"] @@ -190,6 +191,7 @@ members = [ "lib/crewai-tools", "lib/devtools", "lib/crewai-files", + "lib/crewai-a2a", ] @@ -198,3 +200,4 @@ crewai = { workspace = true } crewai-tools = { workspace = true } crewai-devtools = { workspace = true } crewai-files = { workspace = true } +crewai-a2a = { workspace = true } diff --git a/uv.lock b/uv.lock index d07aee183..9335fb792 100644 --- a/uv.lock +++ b/uv.lock @@ -13,12 +13,13 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-04-10T18:30:59.748668Z" +exclude-newer = "2026-04-11T13:34:53.333824Z" exclude-newer-span = "P3D" [manifest] members = [ "crewai", + "crewai-a2a", "crewai-devtools", "crewai-files", "crewai-tools", @@ -1267,10 +1268,7 @@ dependencies = [ [package.optional-dependencies] a2a = [ - { name = "a2a-sdk" }, - { name = "aiocache", extra = ["memcached", "redis"] }, - { name = "httpx-auth" }, - { name = "httpx-sse" }, + { name = "crewai-a2a" }, ] anthropic = [ { name = "anthropic" }, @@ -1327,9 +1325,7 @@ watson = [ [package.metadata] requires-dist = [ - { name = "a2a-sdk", marker = "extra == 'a2a'", specifier = "~=0.3.10" }, { name = "aiobotocore", marker = "extra == 'aws'", specifier = "~=3.4.0" }, - { name = "aiocache", extras = ["memcached", "redis"], marker = "extra == 'a2a'", specifier = "~=0.12.3" }, { name = "aiofiles", specifier = "~=24.1.0" }, { name = "aiosqlite", specifier = "~=0.21.0" }, { name = "anthropic", marker = "extra == 'anthropic'", specifier = "~=0.73.0" }, @@ -1339,13 +1335,12 @@ requires-dist = [ { name = "boto3", marker = "extra == 'bedrock'", specifier = "~=1.42.79" }, { name = "chromadb", specifier = "~=1.1.0" }, { name = "click", specifier = "~=8.1.7" }, + { name = "crewai-a2a", marker = "extra == 'a2a'", editable = "lib/crewai-a2a" }, { name = "crewai-files", marker = "extra == 'file-processing'", editable = "lib/crewai-files" }, { name = "crewai-tools", marker = "extra == 'tools'", editable = "lib/crewai-tools" }, { name = "docling", marker = "extra == 'docling'", specifier = "~=2.84.0" }, { name = "google-genai", marker = "extra == 'google-genai'", specifier = "~=1.65.0" }, { name = "httpx", specifier = "~=0.28.1" }, - { name = "httpx-auth", marker = "extra == 'a2a'", specifier = "~=0.23.1" }, - { name = "httpx-sse", marker = "extra == 'a2a'", specifier = "~=0.4.0" }, { name = "ibm-watsonx-ai", marker = "extra == 'watson'", specifier = "~=1.3.39" }, { name = "instructor", specifier = ">=1.3.3" }, { name = "json-repair", specifier = "~=0.25.2" }, @@ -1382,6 +1377,24 @@ requires-dist = [ ] provides-extras = ["a2a", "anthropic", "aws", "azure-ai-inference", "bedrock", "docling", "embeddings", "file-processing", "google-genai", "litellm", "mem0", "openpyxl", "pandas", "qdrant", "qdrant-edge", "tools", "voyageai", "watson"] +[[package]] +name = "crewai-a2a" +source = { editable = "lib/crewai-a2a" } +dependencies = [ + { name = "a2a-sdk" }, + { name = "aiocache", extra = ["memcached", "redis"] }, + { name = "httpx-auth" }, + { name = "httpx-sse" }, +] + +[package.metadata] +requires-dist = [ + { name = "a2a-sdk", specifier = "~=0.3.10" }, + { name = "aiocache", extras = ["memcached", "redis"], specifier = "~=0.12.3" }, + { name = "httpx-auth", specifier = "~=0.23.1" }, + { name = "httpx-sse", specifier = "~=0.4.0" }, +] + [[package]] name = "crewai-devtools" source = { editable = "lib/devtools" }