ag2 0.9.1.post0__py3-none-any.whl → 0.9.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ag2 might be problematic. Click here for more details.

Files changed (37) hide show
  1. {ag2-0.9.1.post0.dist-info → ag2-0.9.3.dist-info}/METADATA +22 -12
  2. {ag2-0.9.1.post0.dist-info → ag2-0.9.3.dist-info}/RECORD +37 -23
  3. autogen/agentchat/contrib/capabilities/transforms.py +22 -9
  4. autogen/agentchat/conversable_agent.py +37 -34
  5. autogen/agentchat/group/group_utils.py +65 -20
  6. autogen/agentchat/group/handoffs.py +81 -5
  7. autogen/agentchat/group/on_context_condition.py +2 -2
  8. autogen/agentchat/group/patterns/pattern.py +7 -1
  9. autogen/agentchat/groupchat.py +2 -2
  10. autogen/agentchat/realtime/experimental/realtime_swarm.py +12 -4
  11. autogen/agents/experimental/document_agent/document_agent.py +232 -40
  12. autogen/events/agent_events.py +7 -4
  13. autogen/interop/litellm/litellm_config_factory.py +68 -2
  14. autogen/llm_config.py +4 -1
  15. autogen/mcp/__main__.py +78 -0
  16. autogen/mcp/mcp_proxy/__init__.py +19 -0
  17. autogen/mcp/mcp_proxy/fastapi_code_generator_helpers.py +63 -0
  18. autogen/mcp/mcp_proxy/mcp_proxy.py +581 -0
  19. autogen/mcp/mcp_proxy/operation_grouping.py +158 -0
  20. autogen/mcp/mcp_proxy/operation_renaming.py +114 -0
  21. autogen/mcp/mcp_proxy/patch_fastapi_code_generator.py +98 -0
  22. autogen/mcp/mcp_proxy/security.py +400 -0
  23. autogen/mcp/mcp_proxy/security_schema_visitor.py +37 -0
  24. autogen/oai/client.py +11 -2
  25. autogen/oai/gemini.py +20 -3
  26. autogen/oai/gemini_types.py +27 -0
  27. autogen/oai/oai_models/chat_completion.py +1 -1
  28. autogen/tools/experimental/__init__.py +5 -0
  29. autogen/tools/experimental/reliable/__init__.py +10 -0
  30. autogen/tools/experimental/reliable/reliable.py +1316 -0
  31. autogen/version.py +1 -1
  32. templates/client_template/main.jinja2 +69 -0
  33. templates/config_template/config.jinja2 +7 -0
  34. templates/main.jinja2 +61 -0
  35. {ag2-0.9.1.post0.dist-info → ag2-0.9.3.dist-info}/WHEEL +0 -0
  36. {ag2-0.9.1.post0.dist-info → ag2-0.9.3.dist-info}/licenses/LICENSE +0 -0
  37. {ag2-0.9.1.post0.dist-info → ag2-0.9.3.dist-info}/licenses/NOTICE.md +0 -0
@@ -4,7 +4,7 @@
4
4
 
5
5
  import os
6
6
  from abc import ABC, abstractmethod
7
- from typing import Any, Callable, TypeVar, Union
7
+ from typing import Any, Callable, Optional, TypeVar, Union
8
8
 
9
9
  from ...doc_utils import export_module
10
10
  from ...llm_config import LLMConfig
@@ -15,19 +15,85 @@ __all__ = ["LiteLLmConfigFactory"]
15
15
  T = TypeVar("T", bound="LiteLLmConfigFactory")
16
16
 
17
17
 
18
+ def get_crawl4ai_version() -> Optional[str]:
19
+ """Get the installed crawl4ai version."""
20
+ try:
21
+ import crawl4ai
22
+
23
+ version = getattr(crawl4ai, "__version__", None)
24
+ return version if isinstance(version, str) else None
25
+ except (ImportError, AttributeError):
26
+ return None
27
+
28
+
29
+ def is_crawl4ai_v05_or_higher() -> bool:
30
+ """Check if crawl4ai version is 0.5 or higher."""
31
+ version = get_crawl4ai_version()
32
+ if version is None:
33
+ return False
34
+
35
+ # Parse version string (e.g., "0.5.0" -> [0, 5, 0])
36
+ try:
37
+ version_parts = [int(x) for x in version.split(".")]
38
+ # Check if version >= 0.5.0
39
+ return version_parts >= [0, 5, 0]
40
+ except (ValueError, IndexError):
41
+ return False
42
+
43
+
18
44
  @export_module("autogen.interop")
19
45
  class LiteLLmConfigFactory(ABC):
20
46
  _factories: set["LiteLLmConfigFactory"] = set()
21
47
 
22
48
  @classmethod
23
49
  def create_lite_llm_config(cls, llm_config: Union[LLMConfig, dict[str, Any]]) -> dict[str, Any]:
50
+ """
51
+ Create a lite LLM config compatible with the installed crawl4ai version.
52
+
53
+ For crawl4ai >=0.5: Returns config with llmConfig parameter
54
+ For crawl4ai <0.5: Returns config with provider parameter (legacy)
55
+ """
24
56
  first_llm_config = get_first_llm_config(llm_config)
25
57
  for factory in LiteLLmConfigFactory._factories:
26
58
  if factory.accepts(first_llm_config):
27
- return factory.create(first_llm_config)
59
+ base_config = factory.create(first_llm_config)
60
+
61
+ # Check crawl4ai version and adapt config accordingly
62
+ if is_crawl4ai_v05_or_higher():
63
+ return cls._adapt_for_crawl4ai_v05(base_config)
64
+ else:
65
+ return base_config # Use legacy format
28
66
 
29
67
  raise ValueError("Could not find a factory for the given config.")
30
68
 
69
+ @classmethod
70
+ def _adapt_for_crawl4ai_v05(cls, base_config: dict[str, Any]) -> dict[str, Any]:
71
+ """
72
+ Adapt the config for crawl4ai >=0.5 by moving deprecated parameters
73
+ into an llmConfig object.
74
+ """
75
+ adapted_config = base_config.copy()
76
+
77
+ # Extract deprecated parameters
78
+ llm_config_params = {}
79
+
80
+ if "provider" in adapted_config:
81
+ llm_config_params["provider"] = adapted_config.pop("provider")
82
+
83
+ if "api_token" in adapted_config:
84
+ llm_config_params["api_token"] = adapted_config.pop("api_token")
85
+
86
+ # Add other parameters that should be in llmConfig
87
+ for param in ["base_url", "api_base", "api_version"]:
88
+ if param in adapted_config:
89
+ llm_config_params[param] = adapted_config.pop(param)
90
+
91
+ # Create the llmConfig object if we have parameters for it
92
+ if llm_config_params:
93
+ adapted_config["llmConfig"] = llm_config_params
94
+
95
+ return adapted_config
96
+
31
97
  @classmethod
32
98
  def register_factory(cls) -> Callable[[type[T]], type[T]]:
33
99
  def decorator(factory: type[T]) -> type[T]:
autogen/llm_config.py CHANGED
@@ -138,7 +138,10 @@ class LLMConfig(metaclass=MetaLLMConfig):
138
138
  if len(filtered_config_list) == 0:
139
139
  raise ValueError(f"No config found that satisfies the filter criteria: {kwargs}")
140
140
 
141
- return LLMConfig(config_list=filtered_config_list)
141
+ kwargs = self.model_dump()
142
+ kwargs["config_list"] = filtered_config_list
143
+
144
+ return LLMConfig(**kwargs)
142
145
 
143
146
  # @functools.wraps(BaseModel.model_dump)
144
147
  def model_dump(self, *args: Any, exclude_none: bool = True, **kwargs: Any) -> dict[str, Any]:
@@ -0,0 +1,78 @@
1
+ # Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ import logging
5
+ from typing import Annotated, Literal, Optional
6
+
7
+ from .. import __version__
8
+ from ..import_utils import optional_import_block, require_optional_import
9
+ from .mcp_proxy import MCPProxy
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+ with optional_import_block():
14
+ import typer
15
+
16
+
17
+ @require_optional_import(["typer"], "mcp-proxy-gen")
18
+ def create_typer_app() -> "typer.Typer":
19
+ """Create a Typer app for the mcp proxy CLI."""
20
+ app = typer.Typer(rich_markup_mode="rich")
21
+
22
+ def version_callback(value: bool) -> None:
23
+ if value:
24
+ typer.echo(f"{__version__}")
25
+ raise typer.Exit()
26
+
27
+ @app.callback()
28
+ def callback(
29
+ version: Annotated[
30
+ Optional[bool],
31
+ typer.Option("--version", help="Show the version and exit.", callback=version_callback),
32
+ ] = None,
33
+ ) -> None:
34
+ """AG2 mcp proxy CLI - The [bold]mcp proxy[/bold] command line app. 😎
35
+
36
+ Generate mcp proxy for your [bold]AG2[/bold] projects.
37
+
38
+ Read more in the docs: ...
39
+ """ # noqa: D415
40
+
41
+ @app.command()
42
+ def create(
43
+ openapi_specification: Annotated[
44
+ Optional[str],
45
+ "Specification of the OpenAPI to use for the proxy generation.",
46
+ ] = None,
47
+ openapi_url: Annotated[
48
+ Optional[str],
49
+ "URL to the OpenAPI specification to use for the proxy generation.",
50
+ ] = None,
51
+ client_source_path: Annotated[
52
+ Optional[str],
53
+ "Path to the generated proxy client source code.",
54
+ ] = None,
55
+ server_url: Annotated[
56
+ Optional[str],
57
+ "Comma-separated list of server URLs to use for the proxy generation.",
58
+ ] = None,
59
+ configuration_type: Annotated[
60
+ Literal["json", "yaml"],
61
+ "Configuration type of the specification. Can be 'json' or 'yaml'.",
62
+ ] = "json",
63
+ ) -> None:
64
+ """Generate mcp proxy for your AG2 projects."""
65
+ MCPProxy.create(
66
+ openapi_specification=openapi_specification,
67
+ openapi_url=openapi_url,
68
+ client_source_path=client_source_path,
69
+ servers=[{"url": server_url}],
70
+ configuration_type=configuration_type,
71
+ )
72
+
73
+ return app
74
+
75
+
76
+ if __name__ == "__main__":
77
+ app = create_typer_app()
78
+ app(prog_name="mcp_proxy")
@@ -0,0 +1,19 @@
1
+ # Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from autogen.import_utils import optional_import_block
6
+
7
+ from .patch_fastapi_code_generator import ( # noqa: E402
8
+ SUCCESFUL_IMPORT,
9
+ patch_function_name_parsing,
10
+ patch_generate_code,
11
+ )
12
+
13
+ if SUCCESFUL_IMPORT:
14
+ patch_function_name_parsing()
15
+ patch_generate_code()
16
+
17
+ from .mcp_proxy import MCPProxy # noqa: E402
18
+
19
+ __all__ = ["MCPProxy", "optional_import_block"]
@@ -0,0 +1,63 @@
1
+ # Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ from collections.abc import Iterator
5
+ from contextlib import contextmanager
6
+ from functools import cached_property
7
+ from typing import Optional, Union
8
+
9
+ from ...import_utils import optional_import_block
10
+
11
+ with optional_import_block() as result:
12
+ from fastapi_code_generator.parser import (
13
+ Argument,
14
+ OpenAPIParser,
15
+ ParameterObject,
16
+ ReferenceObject,
17
+ )
18
+
19
+ SUCCESFUL_IMPORT = result.is_successful
20
+
21
+ __all__ = ["SUCCESFUL_IMPORT", "patch_get_parameter_type"]
22
+
23
+
24
+ @contextmanager
25
+ def patch_get_parameter_type() -> Iterator[None]:
26
+ class ArgumentWithDescription(Argument): # type: ignore[misc]
27
+ description: Optional[str] = None
28
+
29
+ @cached_property
30
+ def argument(self) -> str:
31
+ if self.description:
32
+ description = self.description.replace('"""', '"""')
33
+ type_hint = f'Annotated[{self.type_hint}, """{description}"""]'
34
+ else:
35
+ type_hint = self.type_hint
36
+
37
+ if self.default is None and self.required:
38
+ return f"{self.name}: {type_hint}"
39
+
40
+ return f"{self.name}: {type_hint} = {self.default}"
41
+
42
+ original_get_parameter_type = OpenAPIParser.get_parameter_type
43
+
44
+ def get_parameter_type(
45
+ self: OpenAPIParser,
46
+ parameters: Union[ReferenceObject, ParameterObject],
47
+ snake_case: bool,
48
+ path: list[str],
49
+ ) -> Optional[Argument]:
50
+ # get the original argument
51
+ argument = original_get_parameter_type(self, parameters, snake_case, path)
52
+
53
+ # add description to the argument
54
+ parameters = self.resolve_object(parameters, ParameterObject)
55
+ argument_with_description = ArgumentWithDescription(description=parameters.description, **argument.model_dump())
56
+ return argument_with_description
57
+
58
+ OpenAPIParser.get_parameter_type = get_parameter_type
59
+
60
+ try:
61
+ yield
62
+ finally:
63
+ OpenAPIParser.get_parameter_type = original_get_parameter_type