ag2 0.10.2__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.
Files changed (423) hide show
  1. ag2-0.10.2.dist-info/METADATA +819 -0
  2. ag2-0.10.2.dist-info/RECORD +423 -0
  3. ag2-0.10.2.dist-info/WHEEL +4 -0
  4. ag2-0.10.2.dist-info/licenses/LICENSE +201 -0
  5. ag2-0.10.2.dist-info/licenses/NOTICE.md +19 -0
  6. autogen/__init__.py +88 -0
  7. autogen/_website/__init__.py +3 -0
  8. autogen/_website/generate_api_references.py +426 -0
  9. autogen/_website/generate_mkdocs.py +1216 -0
  10. autogen/_website/notebook_processor.py +475 -0
  11. autogen/_website/process_notebooks.py +656 -0
  12. autogen/_website/utils.py +413 -0
  13. autogen/a2a/__init__.py +36 -0
  14. autogen/a2a/agent_executor.py +86 -0
  15. autogen/a2a/client.py +357 -0
  16. autogen/a2a/errors.py +18 -0
  17. autogen/a2a/httpx_client_factory.py +79 -0
  18. autogen/a2a/server.py +221 -0
  19. autogen/a2a/utils.py +207 -0
  20. autogen/agentchat/__init__.py +47 -0
  21. autogen/agentchat/agent.py +180 -0
  22. autogen/agentchat/assistant_agent.py +86 -0
  23. autogen/agentchat/chat.py +325 -0
  24. autogen/agentchat/contrib/__init__.py +5 -0
  25. autogen/agentchat/contrib/agent_eval/README.md +7 -0
  26. autogen/agentchat/contrib/agent_eval/agent_eval.py +108 -0
  27. autogen/agentchat/contrib/agent_eval/criterion.py +43 -0
  28. autogen/agentchat/contrib/agent_eval/critic_agent.py +44 -0
  29. autogen/agentchat/contrib/agent_eval/quantifier_agent.py +39 -0
  30. autogen/agentchat/contrib/agent_eval/subcritic_agent.py +45 -0
  31. autogen/agentchat/contrib/agent_eval/task.py +42 -0
  32. autogen/agentchat/contrib/agent_optimizer.py +432 -0
  33. autogen/agentchat/contrib/capabilities/__init__.py +5 -0
  34. autogen/agentchat/contrib/capabilities/agent_capability.py +20 -0
  35. autogen/agentchat/contrib/capabilities/generate_images.py +301 -0
  36. autogen/agentchat/contrib/capabilities/teachability.py +393 -0
  37. autogen/agentchat/contrib/capabilities/text_compressors.py +66 -0
  38. autogen/agentchat/contrib/capabilities/tools_capability.py +22 -0
  39. autogen/agentchat/contrib/capabilities/transform_messages.py +93 -0
  40. autogen/agentchat/contrib/capabilities/transforms.py +578 -0
  41. autogen/agentchat/contrib/capabilities/transforms_util.py +122 -0
  42. autogen/agentchat/contrib/capabilities/vision_capability.py +215 -0
  43. autogen/agentchat/contrib/captainagent/__init__.py +9 -0
  44. autogen/agentchat/contrib/captainagent/agent_builder.py +790 -0
  45. autogen/agentchat/contrib/captainagent/captainagent.py +514 -0
  46. autogen/agentchat/contrib/captainagent/tool_retriever.py +334 -0
  47. autogen/agentchat/contrib/captainagent/tools/README.md +44 -0
  48. autogen/agentchat/contrib/captainagent/tools/__init__.py +5 -0
  49. autogen/agentchat/contrib/captainagent/tools/data_analysis/calculate_correlation.py +40 -0
  50. autogen/agentchat/contrib/captainagent/tools/data_analysis/calculate_skewness_and_kurtosis.py +28 -0
  51. autogen/agentchat/contrib/captainagent/tools/data_analysis/detect_outlier_iqr.py +28 -0
  52. autogen/agentchat/contrib/captainagent/tools/data_analysis/detect_outlier_zscore.py +28 -0
  53. autogen/agentchat/contrib/captainagent/tools/data_analysis/explore_csv.py +21 -0
  54. autogen/agentchat/contrib/captainagent/tools/data_analysis/shapiro_wilk_test.py +30 -0
  55. autogen/agentchat/contrib/captainagent/tools/information_retrieval/arxiv_download.py +27 -0
  56. autogen/agentchat/contrib/captainagent/tools/information_retrieval/arxiv_search.py +53 -0
  57. autogen/agentchat/contrib/captainagent/tools/information_retrieval/extract_pdf_image.py +53 -0
  58. autogen/agentchat/contrib/captainagent/tools/information_retrieval/extract_pdf_text.py +38 -0
  59. autogen/agentchat/contrib/captainagent/tools/information_retrieval/get_wikipedia_text.py +21 -0
  60. autogen/agentchat/contrib/captainagent/tools/information_retrieval/get_youtube_caption.py +34 -0
  61. autogen/agentchat/contrib/captainagent/tools/information_retrieval/image_qa.py +60 -0
  62. autogen/agentchat/contrib/captainagent/tools/information_retrieval/optical_character_recognition.py +61 -0
  63. autogen/agentchat/contrib/captainagent/tools/information_retrieval/perform_web_search.py +47 -0
  64. autogen/agentchat/contrib/captainagent/tools/information_retrieval/scrape_wikipedia_tables.py +33 -0
  65. autogen/agentchat/contrib/captainagent/tools/information_retrieval/transcribe_audio_file.py +21 -0
  66. autogen/agentchat/contrib/captainagent/tools/information_retrieval/youtube_download.py +35 -0
  67. autogen/agentchat/contrib/captainagent/tools/math/calculate_circle_area_from_diameter.py +21 -0
  68. autogen/agentchat/contrib/captainagent/tools/math/calculate_day_of_the_week.py +18 -0
  69. autogen/agentchat/contrib/captainagent/tools/math/calculate_fraction_sum.py +28 -0
  70. autogen/agentchat/contrib/captainagent/tools/math/calculate_matrix_power.py +31 -0
  71. autogen/agentchat/contrib/captainagent/tools/math/calculate_reflected_point.py +16 -0
  72. autogen/agentchat/contrib/captainagent/tools/math/complex_numbers_product.py +25 -0
  73. autogen/agentchat/contrib/captainagent/tools/math/compute_currency_conversion.py +23 -0
  74. autogen/agentchat/contrib/captainagent/tools/math/count_distinct_permutations.py +27 -0
  75. autogen/agentchat/contrib/captainagent/tools/math/evaluate_expression.py +28 -0
  76. autogen/agentchat/contrib/captainagent/tools/math/find_continuity_point.py +34 -0
  77. autogen/agentchat/contrib/captainagent/tools/math/fraction_to_mixed_numbers.py +39 -0
  78. autogen/agentchat/contrib/captainagent/tools/math/modular_inverse_sum.py +23 -0
  79. autogen/agentchat/contrib/captainagent/tools/math/simplify_mixed_numbers.py +36 -0
  80. autogen/agentchat/contrib/captainagent/tools/math/sum_of_digit_factorials.py +15 -0
  81. autogen/agentchat/contrib/captainagent/tools/math/sum_of_primes_below.py +15 -0
  82. autogen/agentchat/contrib/captainagent/tools/requirements.txt +10 -0
  83. autogen/agentchat/contrib/captainagent/tools/tool_description.tsv +34 -0
  84. autogen/agentchat/contrib/gpt_assistant_agent.py +526 -0
  85. autogen/agentchat/contrib/graph_rag/__init__.py +9 -0
  86. autogen/agentchat/contrib/graph_rag/document.py +29 -0
  87. autogen/agentchat/contrib/graph_rag/falkor_graph_query_engine.py +167 -0
  88. autogen/agentchat/contrib/graph_rag/falkor_graph_rag_capability.py +103 -0
  89. autogen/agentchat/contrib/graph_rag/graph_query_engine.py +53 -0
  90. autogen/agentchat/contrib/graph_rag/graph_rag_capability.py +63 -0
  91. autogen/agentchat/contrib/graph_rag/neo4j_graph_query_engine.py +263 -0
  92. autogen/agentchat/contrib/graph_rag/neo4j_graph_rag_capability.py +83 -0
  93. autogen/agentchat/contrib/graph_rag/neo4j_native_graph_query_engine.py +210 -0
  94. autogen/agentchat/contrib/graph_rag/neo4j_native_graph_rag_capability.py +93 -0
  95. autogen/agentchat/contrib/img_utils.py +397 -0
  96. autogen/agentchat/contrib/llamaindex_conversable_agent.py +117 -0
  97. autogen/agentchat/contrib/llava_agent.py +189 -0
  98. autogen/agentchat/contrib/math_user_proxy_agent.py +464 -0
  99. autogen/agentchat/contrib/multimodal_conversable_agent.py +125 -0
  100. autogen/agentchat/contrib/qdrant_retrieve_user_proxy_agent.py +325 -0
  101. autogen/agentchat/contrib/rag/__init__.py +10 -0
  102. autogen/agentchat/contrib/rag/chromadb_query_engine.py +268 -0
  103. autogen/agentchat/contrib/rag/llamaindex_query_engine.py +195 -0
  104. autogen/agentchat/contrib/rag/mongodb_query_engine.py +319 -0
  105. autogen/agentchat/contrib/rag/query_engine.py +76 -0
  106. autogen/agentchat/contrib/retrieve_assistant_agent.py +59 -0
  107. autogen/agentchat/contrib/retrieve_user_proxy_agent.py +704 -0
  108. autogen/agentchat/contrib/society_of_mind_agent.py +200 -0
  109. autogen/agentchat/contrib/swarm_agent.py +1404 -0
  110. autogen/agentchat/contrib/text_analyzer_agent.py +79 -0
  111. autogen/agentchat/contrib/vectordb/__init__.py +5 -0
  112. autogen/agentchat/contrib/vectordb/base.py +224 -0
  113. autogen/agentchat/contrib/vectordb/chromadb.py +316 -0
  114. autogen/agentchat/contrib/vectordb/couchbase.py +405 -0
  115. autogen/agentchat/contrib/vectordb/mongodb.py +551 -0
  116. autogen/agentchat/contrib/vectordb/pgvectordb.py +927 -0
  117. autogen/agentchat/contrib/vectordb/qdrant.py +320 -0
  118. autogen/agentchat/contrib/vectordb/utils.py +126 -0
  119. autogen/agentchat/contrib/web_surfer.py +304 -0
  120. autogen/agentchat/conversable_agent.py +4307 -0
  121. autogen/agentchat/group/__init__.py +67 -0
  122. autogen/agentchat/group/available_condition.py +91 -0
  123. autogen/agentchat/group/context_condition.py +77 -0
  124. autogen/agentchat/group/context_expression.py +238 -0
  125. autogen/agentchat/group/context_str.py +39 -0
  126. autogen/agentchat/group/context_variables.py +182 -0
  127. autogen/agentchat/group/events/transition_events.py +111 -0
  128. autogen/agentchat/group/group_tool_executor.py +324 -0
  129. autogen/agentchat/group/group_utils.py +659 -0
  130. autogen/agentchat/group/guardrails.py +179 -0
  131. autogen/agentchat/group/handoffs.py +303 -0
  132. autogen/agentchat/group/llm_condition.py +93 -0
  133. autogen/agentchat/group/multi_agent_chat.py +291 -0
  134. autogen/agentchat/group/on_condition.py +55 -0
  135. autogen/agentchat/group/on_context_condition.py +51 -0
  136. autogen/agentchat/group/patterns/__init__.py +18 -0
  137. autogen/agentchat/group/patterns/auto.py +160 -0
  138. autogen/agentchat/group/patterns/manual.py +177 -0
  139. autogen/agentchat/group/patterns/pattern.py +295 -0
  140. autogen/agentchat/group/patterns/random.py +106 -0
  141. autogen/agentchat/group/patterns/round_robin.py +117 -0
  142. autogen/agentchat/group/reply_result.py +24 -0
  143. autogen/agentchat/group/safeguards/__init__.py +21 -0
  144. autogen/agentchat/group/safeguards/api.py +241 -0
  145. autogen/agentchat/group/safeguards/enforcer.py +1158 -0
  146. autogen/agentchat/group/safeguards/events.py +140 -0
  147. autogen/agentchat/group/safeguards/validator.py +435 -0
  148. autogen/agentchat/group/speaker_selection_result.py +41 -0
  149. autogen/agentchat/group/targets/__init__.py +4 -0
  150. autogen/agentchat/group/targets/function_target.py +245 -0
  151. autogen/agentchat/group/targets/group_chat_target.py +133 -0
  152. autogen/agentchat/group/targets/group_manager_target.py +151 -0
  153. autogen/agentchat/group/targets/transition_target.py +424 -0
  154. autogen/agentchat/group/targets/transition_utils.py +6 -0
  155. autogen/agentchat/groupchat.py +1832 -0
  156. autogen/agentchat/realtime/__init__.py +3 -0
  157. autogen/agentchat/realtime/experimental/__init__.py +20 -0
  158. autogen/agentchat/realtime/experimental/audio_adapters/__init__.py +8 -0
  159. autogen/agentchat/realtime/experimental/audio_adapters/twilio_audio_adapter.py +148 -0
  160. autogen/agentchat/realtime/experimental/audio_adapters/websocket_audio_adapter.py +139 -0
  161. autogen/agentchat/realtime/experimental/audio_observer.py +42 -0
  162. autogen/agentchat/realtime/experimental/clients/__init__.py +15 -0
  163. autogen/agentchat/realtime/experimental/clients/gemini/__init__.py +7 -0
  164. autogen/agentchat/realtime/experimental/clients/gemini/client.py +274 -0
  165. autogen/agentchat/realtime/experimental/clients/oai/__init__.py +8 -0
  166. autogen/agentchat/realtime/experimental/clients/oai/base_client.py +220 -0
  167. autogen/agentchat/realtime/experimental/clients/oai/rtc_client.py +243 -0
  168. autogen/agentchat/realtime/experimental/clients/oai/utils.py +48 -0
  169. autogen/agentchat/realtime/experimental/clients/realtime_client.py +191 -0
  170. autogen/agentchat/realtime/experimental/function_observer.py +84 -0
  171. autogen/agentchat/realtime/experimental/realtime_agent.py +158 -0
  172. autogen/agentchat/realtime/experimental/realtime_events.py +42 -0
  173. autogen/agentchat/realtime/experimental/realtime_observer.py +100 -0
  174. autogen/agentchat/realtime/experimental/realtime_swarm.py +533 -0
  175. autogen/agentchat/realtime/experimental/websockets.py +21 -0
  176. autogen/agentchat/realtime_agent/__init__.py +21 -0
  177. autogen/agentchat/user_proxy_agent.py +114 -0
  178. autogen/agentchat/utils.py +206 -0
  179. autogen/agents/__init__.py +3 -0
  180. autogen/agents/contrib/__init__.py +10 -0
  181. autogen/agents/contrib/time/__init__.py +8 -0
  182. autogen/agents/contrib/time/time_reply_agent.py +74 -0
  183. autogen/agents/contrib/time/time_tool_agent.py +52 -0
  184. autogen/agents/experimental/__init__.py +27 -0
  185. autogen/agents/experimental/deep_research/__init__.py +7 -0
  186. autogen/agents/experimental/deep_research/deep_research.py +52 -0
  187. autogen/agents/experimental/discord/__init__.py +7 -0
  188. autogen/agents/experimental/discord/discord.py +66 -0
  189. autogen/agents/experimental/document_agent/__init__.py +19 -0
  190. autogen/agents/experimental/document_agent/chroma_query_engine.py +301 -0
  191. autogen/agents/experimental/document_agent/docling_doc_ingest_agent.py +113 -0
  192. autogen/agents/experimental/document_agent/document_agent.py +643 -0
  193. autogen/agents/experimental/document_agent/document_conditions.py +50 -0
  194. autogen/agents/experimental/document_agent/document_utils.py +376 -0
  195. autogen/agents/experimental/document_agent/inmemory_query_engine.py +214 -0
  196. autogen/agents/experimental/document_agent/parser_utils.py +134 -0
  197. autogen/agents/experimental/document_agent/url_utils.py +417 -0
  198. autogen/agents/experimental/reasoning/__init__.py +7 -0
  199. autogen/agents/experimental/reasoning/reasoning_agent.py +1178 -0
  200. autogen/agents/experimental/slack/__init__.py +7 -0
  201. autogen/agents/experimental/slack/slack.py +73 -0
  202. autogen/agents/experimental/telegram/__init__.py +7 -0
  203. autogen/agents/experimental/telegram/telegram.py +76 -0
  204. autogen/agents/experimental/websurfer/__init__.py +7 -0
  205. autogen/agents/experimental/websurfer/websurfer.py +70 -0
  206. autogen/agents/experimental/wikipedia/__init__.py +7 -0
  207. autogen/agents/experimental/wikipedia/wikipedia.py +88 -0
  208. autogen/browser_utils.py +309 -0
  209. autogen/cache/__init__.py +10 -0
  210. autogen/cache/abstract_cache_base.py +71 -0
  211. autogen/cache/cache.py +203 -0
  212. autogen/cache/cache_factory.py +88 -0
  213. autogen/cache/cosmos_db_cache.py +144 -0
  214. autogen/cache/disk_cache.py +97 -0
  215. autogen/cache/in_memory_cache.py +54 -0
  216. autogen/cache/redis_cache.py +119 -0
  217. autogen/code_utils.py +598 -0
  218. autogen/coding/__init__.py +30 -0
  219. autogen/coding/base.py +120 -0
  220. autogen/coding/docker_commandline_code_executor.py +283 -0
  221. autogen/coding/factory.py +56 -0
  222. autogen/coding/func_with_reqs.py +203 -0
  223. autogen/coding/jupyter/__init__.py +23 -0
  224. autogen/coding/jupyter/base.py +36 -0
  225. autogen/coding/jupyter/docker_jupyter_server.py +160 -0
  226. autogen/coding/jupyter/embedded_ipython_code_executor.py +182 -0
  227. autogen/coding/jupyter/import_utils.py +82 -0
  228. autogen/coding/jupyter/jupyter_client.py +224 -0
  229. autogen/coding/jupyter/jupyter_code_executor.py +154 -0
  230. autogen/coding/jupyter/local_jupyter_server.py +164 -0
  231. autogen/coding/local_commandline_code_executor.py +341 -0
  232. autogen/coding/markdown_code_extractor.py +44 -0
  233. autogen/coding/utils.py +55 -0
  234. autogen/coding/yepcode_code_executor.py +197 -0
  235. autogen/doc_utils.py +35 -0
  236. autogen/environments/__init__.py +10 -0
  237. autogen/environments/docker_python_environment.py +365 -0
  238. autogen/environments/python_environment.py +125 -0
  239. autogen/environments/system_python_environment.py +85 -0
  240. autogen/environments/venv_python_environment.py +220 -0
  241. autogen/environments/working_directory.py +74 -0
  242. autogen/events/__init__.py +7 -0
  243. autogen/events/agent_events.py +1016 -0
  244. autogen/events/base_event.py +100 -0
  245. autogen/events/client_events.py +168 -0
  246. autogen/events/helpers.py +44 -0
  247. autogen/events/print_event.py +45 -0
  248. autogen/exception_utils.py +73 -0
  249. autogen/extensions/__init__.py +5 -0
  250. autogen/fast_depends/__init__.py +16 -0
  251. autogen/fast_depends/_compat.py +75 -0
  252. autogen/fast_depends/core/__init__.py +14 -0
  253. autogen/fast_depends/core/build.py +206 -0
  254. autogen/fast_depends/core/model.py +527 -0
  255. autogen/fast_depends/dependencies/__init__.py +15 -0
  256. autogen/fast_depends/dependencies/model.py +30 -0
  257. autogen/fast_depends/dependencies/provider.py +40 -0
  258. autogen/fast_depends/library/__init__.py +10 -0
  259. autogen/fast_depends/library/model.py +46 -0
  260. autogen/fast_depends/py.typed +6 -0
  261. autogen/fast_depends/schema.py +66 -0
  262. autogen/fast_depends/use.py +272 -0
  263. autogen/fast_depends/utils.py +177 -0
  264. autogen/formatting_utils.py +83 -0
  265. autogen/function_utils.py +13 -0
  266. autogen/graph_utils.py +173 -0
  267. autogen/import_utils.py +539 -0
  268. autogen/interop/__init__.py +22 -0
  269. autogen/interop/crewai/__init__.py +7 -0
  270. autogen/interop/crewai/crewai.py +88 -0
  271. autogen/interop/interoperability.py +71 -0
  272. autogen/interop/interoperable.py +46 -0
  273. autogen/interop/langchain/__init__.py +8 -0
  274. autogen/interop/langchain/langchain_chat_model_factory.py +156 -0
  275. autogen/interop/langchain/langchain_tool.py +78 -0
  276. autogen/interop/litellm/__init__.py +7 -0
  277. autogen/interop/litellm/litellm_config_factory.py +178 -0
  278. autogen/interop/pydantic_ai/__init__.py +7 -0
  279. autogen/interop/pydantic_ai/pydantic_ai.py +172 -0
  280. autogen/interop/registry.py +70 -0
  281. autogen/io/__init__.py +15 -0
  282. autogen/io/base.py +151 -0
  283. autogen/io/console.py +56 -0
  284. autogen/io/processors/__init__.py +12 -0
  285. autogen/io/processors/base.py +21 -0
  286. autogen/io/processors/console_event_processor.py +61 -0
  287. autogen/io/run_response.py +294 -0
  288. autogen/io/thread_io_stream.py +63 -0
  289. autogen/io/websockets.py +214 -0
  290. autogen/json_utils.py +42 -0
  291. autogen/llm_clients/MIGRATION_TO_V2.md +782 -0
  292. autogen/llm_clients/__init__.py +77 -0
  293. autogen/llm_clients/client_v2.py +122 -0
  294. autogen/llm_clients/models/__init__.py +55 -0
  295. autogen/llm_clients/models/content_blocks.py +389 -0
  296. autogen/llm_clients/models/unified_message.py +145 -0
  297. autogen/llm_clients/models/unified_response.py +83 -0
  298. autogen/llm_clients/openai_completions_client.py +444 -0
  299. autogen/llm_config/__init__.py +11 -0
  300. autogen/llm_config/client.py +59 -0
  301. autogen/llm_config/config.py +461 -0
  302. autogen/llm_config/entry.py +169 -0
  303. autogen/llm_config/types.py +37 -0
  304. autogen/llm_config/utils.py +223 -0
  305. autogen/logger/__init__.py +11 -0
  306. autogen/logger/base_logger.py +129 -0
  307. autogen/logger/file_logger.py +262 -0
  308. autogen/logger/logger_factory.py +42 -0
  309. autogen/logger/logger_utils.py +57 -0
  310. autogen/logger/sqlite_logger.py +524 -0
  311. autogen/math_utils.py +338 -0
  312. autogen/mcp/__init__.py +7 -0
  313. autogen/mcp/__main__.py +78 -0
  314. autogen/mcp/helpers.py +45 -0
  315. autogen/mcp/mcp_client.py +349 -0
  316. autogen/mcp/mcp_proxy/__init__.py +19 -0
  317. autogen/mcp/mcp_proxy/fastapi_code_generator_helpers.py +62 -0
  318. autogen/mcp/mcp_proxy/mcp_proxy.py +577 -0
  319. autogen/mcp/mcp_proxy/operation_grouping.py +166 -0
  320. autogen/mcp/mcp_proxy/operation_renaming.py +110 -0
  321. autogen/mcp/mcp_proxy/patch_fastapi_code_generator.py +98 -0
  322. autogen/mcp/mcp_proxy/security.py +399 -0
  323. autogen/mcp/mcp_proxy/security_schema_visitor.py +37 -0
  324. autogen/messages/__init__.py +7 -0
  325. autogen/messages/agent_messages.py +946 -0
  326. autogen/messages/base_message.py +108 -0
  327. autogen/messages/client_messages.py +172 -0
  328. autogen/messages/print_message.py +48 -0
  329. autogen/oai/__init__.py +61 -0
  330. autogen/oai/anthropic.py +1516 -0
  331. autogen/oai/bedrock.py +800 -0
  332. autogen/oai/cerebras.py +302 -0
  333. autogen/oai/client.py +1658 -0
  334. autogen/oai/client_utils.py +196 -0
  335. autogen/oai/cohere.py +494 -0
  336. autogen/oai/gemini.py +1045 -0
  337. autogen/oai/gemini_types.py +156 -0
  338. autogen/oai/groq.py +319 -0
  339. autogen/oai/mistral.py +311 -0
  340. autogen/oai/oai_models/__init__.py +23 -0
  341. autogen/oai/oai_models/_models.py +16 -0
  342. autogen/oai/oai_models/chat_completion.py +86 -0
  343. autogen/oai/oai_models/chat_completion_audio.py +32 -0
  344. autogen/oai/oai_models/chat_completion_message.py +97 -0
  345. autogen/oai/oai_models/chat_completion_message_tool_call.py +60 -0
  346. autogen/oai/oai_models/chat_completion_token_logprob.py +62 -0
  347. autogen/oai/oai_models/completion_usage.py +59 -0
  348. autogen/oai/ollama.py +657 -0
  349. autogen/oai/openai_responses.py +451 -0
  350. autogen/oai/openai_utils.py +897 -0
  351. autogen/oai/together.py +387 -0
  352. autogen/remote/__init__.py +18 -0
  353. autogen/remote/agent.py +199 -0
  354. autogen/remote/agent_service.py +197 -0
  355. autogen/remote/errors.py +17 -0
  356. autogen/remote/httpx_client_factory.py +131 -0
  357. autogen/remote/protocol.py +37 -0
  358. autogen/remote/retry.py +102 -0
  359. autogen/remote/runtime.py +96 -0
  360. autogen/retrieve_utils.py +490 -0
  361. autogen/runtime_logging.py +161 -0
  362. autogen/testing/__init__.py +12 -0
  363. autogen/testing/messages.py +45 -0
  364. autogen/testing/test_agent.py +111 -0
  365. autogen/token_count_utils.py +280 -0
  366. autogen/tools/__init__.py +20 -0
  367. autogen/tools/contrib/__init__.py +9 -0
  368. autogen/tools/contrib/time/__init__.py +7 -0
  369. autogen/tools/contrib/time/time.py +40 -0
  370. autogen/tools/dependency_injection.py +249 -0
  371. autogen/tools/experimental/__init__.py +54 -0
  372. autogen/tools/experimental/browser_use/__init__.py +7 -0
  373. autogen/tools/experimental/browser_use/browser_use.py +154 -0
  374. autogen/tools/experimental/code_execution/__init__.py +7 -0
  375. autogen/tools/experimental/code_execution/python_code_execution.py +86 -0
  376. autogen/tools/experimental/crawl4ai/__init__.py +7 -0
  377. autogen/tools/experimental/crawl4ai/crawl4ai.py +150 -0
  378. autogen/tools/experimental/deep_research/__init__.py +7 -0
  379. autogen/tools/experimental/deep_research/deep_research.py +329 -0
  380. autogen/tools/experimental/duckduckgo/__init__.py +7 -0
  381. autogen/tools/experimental/duckduckgo/duckduckgo_search.py +103 -0
  382. autogen/tools/experimental/firecrawl/__init__.py +7 -0
  383. autogen/tools/experimental/firecrawl/firecrawl_tool.py +836 -0
  384. autogen/tools/experimental/google/__init__.py +14 -0
  385. autogen/tools/experimental/google/authentication/__init__.py +11 -0
  386. autogen/tools/experimental/google/authentication/credentials_hosted_provider.py +43 -0
  387. autogen/tools/experimental/google/authentication/credentials_local_provider.py +91 -0
  388. autogen/tools/experimental/google/authentication/credentials_provider.py +35 -0
  389. autogen/tools/experimental/google/drive/__init__.py +9 -0
  390. autogen/tools/experimental/google/drive/drive_functions.py +124 -0
  391. autogen/tools/experimental/google/drive/toolkit.py +88 -0
  392. autogen/tools/experimental/google/model.py +17 -0
  393. autogen/tools/experimental/google/toolkit_protocol.py +19 -0
  394. autogen/tools/experimental/google_search/__init__.py +8 -0
  395. autogen/tools/experimental/google_search/google_search.py +93 -0
  396. autogen/tools/experimental/google_search/youtube_search.py +181 -0
  397. autogen/tools/experimental/messageplatform/__init__.py +17 -0
  398. autogen/tools/experimental/messageplatform/discord/__init__.py +7 -0
  399. autogen/tools/experimental/messageplatform/discord/discord.py +284 -0
  400. autogen/tools/experimental/messageplatform/slack/__init__.py +7 -0
  401. autogen/tools/experimental/messageplatform/slack/slack.py +385 -0
  402. autogen/tools/experimental/messageplatform/telegram/__init__.py +7 -0
  403. autogen/tools/experimental/messageplatform/telegram/telegram.py +271 -0
  404. autogen/tools/experimental/perplexity/__init__.py +7 -0
  405. autogen/tools/experimental/perplexity/perplexity_search.py +249 -0
  406. autogen/tools/experimental/reliable/__init__.py +10 -0
  407. autogen/tools/experimental/reliable/reliable.py +1311 -0
  408. autogen/tools/experimental/searxng/__init__.py +7 -0
  409. autogen/tools/experimental/searxng/searxng_search.py +142 -0
  410. autogen/tools/experimental/tavily/__init__.py +7 -0
  411. autogen/tools/experimental/tavily/tavily_search.py +176 -0
  412. autogen/tools/experimental/web_search_preview/__init__.py +7 -0
  413. autogen/tools/experimental/web_search_preview/web_search_preview.py +120 -0
  414. autogen/tools/experimental/wikipedia/__init__.py +7 -0
  415. autogen/tools/experimental/wikipedia/wikipedia.py +284 -0
  416. autogen/tools/function_utils.py +412 -0
  417. autogen/tools/tool.py +188 -0
  418. autogen/tools/toolkit.py +86 -0
  419. autogen/types.py +29 -0
  420. autogen/version.py +7 -0
  421. templates/client_template/main.jinja2 +72 -0
  422. templates/config_template/config.jinja2 +7 -0
  423. templates/main.jinja2 +61 -0
@@ -0,0 +1,539 @@
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
+ import inspect
6
+ import re
7
+ import sys
8
+ from abc import ABC, abstractmethod
9
+ from collections.abc import Callable, Generator, Iterable
10
+ from contextlib import contextmanager, suppress
11
+ from dataclasses import dataclass
12
+ from functools import wraps
13
+ from logging import getLogger
14
+ from pathlib import Path
15
+ from typing import Any, Generic, Optional, TypeVar
16
+
17
+ from packaging import version
18
+
19
+ from .fast_depends.utils import is_coroutine_callable
20
+
21
+ __all__ = [
22
+ "optional_import_block",
23
+ "patch_object",
24
+ "require_optional_import",
25
+ "run_for_optional_imports",
26
+ "skip_on_missing_imports",
27
+ ]
28
+
29
+ logger = getLogger(__name__)
30
+
31
+
32
+ @dataclass
33
+ class ModuleInfo:
34
+ name: str
35
+ min_version: str | None = None
36
+ max_version: str | None = None
37
+ min_inclusive: bool = False
38
+ max_inclusive: bool = False
39
+
40
+ def is_in_sys_modules(self) -> str | None:
41
+ """Check if the module is installed and satisfies the version constraints
42
+
43
+ Returns:
44
+ None if the module is installed and satisfies the version constraints, otherwise a message indicating the issue.
45
+
46
+ """
47
+ if self.name not in sys.modules:
48
+ return f"'{self.name}' is not installed."
49
+ else:
50
+ if hasattr(sys.modules[self.name], "__file__") and sys.modules[self.name].__file__ is not None:
51
+ autogen_path = (Path(__file__).parent).resolve()
52
+ test_path = (Path(__file__).parent.parent / "test").resolve()
53
+ module_path = Path(sys.modules[self.name].__file__).resolve() # type: ignore[arg-type]
54
+
55
+ if str(autogen_path) in str(module_path) or str(test_path) in str(module_path):
56
+ # The module is in the autogen or test directory
57
+ # Aka similarly named module in the autogen or test directory
58
+ return f"'{self.name}' is not installed."
59
+
60
+ # Ensure that the retrieved version is a string. Some packages might unexpectedly
61
+ # have a __version__ attribute that is not a string (e.g., a module).
62
+ raw_version_attr = (
63
+ sys.modules[self.name].__version__ if hasattr(sys.modules[self.name], "__version__") else None
64
+ )
65
+ installed_version = raw_version_attr if isinstance(raw_version_attr, str) else None
66
+ if installed_version is None and (self.min_version or self.max_version):
67
+ return f"'{self.name}' is installed, but the version is not available."
68
+
69
+ if installed_version:
70
+ # Convert to version object for comparison
71
+ installed_ver = version.parse(installed_version)
72
+
73
+ if self.min_version:
74
+ min_ver = version.parse(self.min_version)
75
+ msg = f"'{self.name}' is installed, but the installed version {installed_version} is too low (required '{self}')."
76
+ if not self.min_inclusive and installed_ver == min_ver:
77
+ return msg
78
+ if self.min_inclusive and installed_ver < min_ver:
79
+ return msg
80
+
81
+ if self.max_version:
82
+ max_ver = version.parse(self.max_version)
83
+ msg = f"'{self.name}' is installed, but the installed version {installed_version} is too high (required '{self}')."
84
+ if not self.max_inclusive and installed_ver == max_ver:
85
+ return msg
86
+ if self.max_inclusive and installed_ver > max_ver:
87
+ return msg
88
+
89
+ return None
90
+
91
+ def __repr__(self) -> str:
92
+ s = self.name
93
+ if self.min_version:
94
+ s += f">={self.min_version}" if self.min_inclusive else f">{self.min_version}"
95
+ if self.max_version:
96
+ s += f"<={self.max_version}" if self.max_inclusive else f"<{self.max_version}"
97
+ return s
98
+
99
+ @classmethod
100
+ def from_str(cls, module_info: str) -> "ModuleInfo":
101
+ """Parse a string to create a ModuleInfo object
102
+
103
+ Args:
104
+ module_info (str): A string containing the module name and optional version constraints
105
+
106
+ Returns:
107
+ ModuleInfo: A ModuleInfo object with the parsed information
108
+
109
+ Raises:
110
+ ValueError: If the module information is invalid
111
+ """
112
+ pattern = re.compile(r"^(?P<name>[a-zA-Z0-9-_]+)(?P<constraint>.*)$")
113
+ match = pattern.match(module_info.strip())
114
+
115
+ if not match:
116
+ raise ValueError(f"Invalid package information: {module_info}")
117
+
118
+ name = match.group("name")
119
+ constraints = match.group("constraint").strip()
120
+ min_version = max_version = None
121
+ min_inclusive = max_inclusive = False
122
+
123
+ if constraints:
124
+ constraint_pattern = re.findall(r"(>=|<=|>|<)([0-9\.]+)?", constraints)
125
+
126
+ if not all(version for _, version in constraint_pattern):
127
+ raise ValueError(f"Invalid module information: {module_info}")
128
+
129
+ for operator, version in constraint_pattern:
130
+ if operator == ">=":
131
+ min_version = version
132
+ min_inclusive = True
133
+ elif operator == "<=":
134
+ max_version = version
135
+ max_inclusive = True
136
+ elif operator == ">":
137
+ min_version = version
138
+ min_inclusive = False
139
+ elif operator == "<":
140
+ max_version = version
141
+ max_inclusive = False
142
+ else:
143
+ raise ValueError(f"Invalid package information: {module_info}")
144
+
145
+ return ModuleInfo(
146
+ name=name,
147
+ min_version=min_version,
148
+ max_version=max_version,
149
+ min_inclusive=min_inclusive,
150
+ max_inclusive=max_inclusive,
151
+ )
152
+
153
+
154
+ class Result:
155
+ def __init__(self) -> None:
156
+ self._failed: bool | None = None
157
+
158
+ @property
159
+ def is_successful(self) -> bool:
160
+ if self._failed is None:
161
+ raise ValueError("Result not set")
162
+ return not self._failed
163
+
164
+
165
+ @contextmanager
166
+ def optional_import_block() -> Generator[Result, None, None]:
167
+ """Guard a block of code to suppress ImportErrors
168
+
169
+ A context manager to temporarily suppress ImportErrors.
170
+ Use this to attempt imports without failing immediately on missing modules.
171
+
172
+ Example:
173
+ ```python
174
+ with optional_import_block():
175
+ import some_module
176
+ import some_other_module
177
+ ```
178
+ """
179
+ result = Result()
180
+ try:
181
+ yield result
182
+ result._failed = False
183
+ except ImportError as e:
184
+ # Ignore ImportErrors during this context
185
+ logger.debug(f"Ignoring ImportError: {e}")
186
+ result._failed = True
187
+
188
+
189
+ def get_missing_imports(modules: str | Iterable[str]) -> dict[str, str]:
190
+ """Get missing modules from a list of module names
191
+
192
+ Args:
193
+ modules (Union[str, Iterable[str]]): Module name or list of module names
194
+
195
+ Returns:
196
+ List of missing module names
197
+ """
198
+ if isinstance(modules, str):
199
+ modules = [modules]
200
+
201
+ module_infos = [ModuleInfo.from_str(module) for module in modules]
202
+ x = {m.name: m.is_in_sys_modules() for m in module_infos}
203
+ return {k: v for k, v in x.items() if v}
204
+
205
+
206
+ T = TypeVar("T")
207
+ G = TypeVar("G", bound=Callable[..., Any] | type)
208
+ F = TypeVar("F", bound=Callable[..., Any])
209
+
210
+
211
+ class PatchObject(ABC, Generic[T]):
212
+ def __init__(self, o: T, missing_modules: dict[str, str], dep_target: str):
213
+ if not self.accept(o):
214
+ raise ValueError(f"Cannot patch object of type {type(o)}")
215
+
216
+ self.o = o
217
+ self.missing_modules = missing_modules
218
+ self.dep_target = dep_target
219
+
220
+ @classmethod
221
+ @abstractmethod
222
+ def accept(cls, o: Any) -> bool: ...
223
+
224
+ @abstractmethod
225
+ def patch(self, except_for: Iterable[str]) -> T: ...
226
+
227
+ def get_object_with_metadata(self) -> Any:
228
+ return self.o
229
+
230
+ @property
231
+ def msg(self) -> str:
232
+ o = self.get_object_with_metadata()
233
+ plural = len(self.missing_modules) > 1
234
+ fqn = f"{o.__module__}.{o.__name__}" if hasattr(o, "__module__") else o.__name__
235
+ # modules_str = ", ".join([f"'{m}'" for m in self.missing_modules])
236
+ msg = f"{'Modules' if plural else 'A module'} needed for {fqn} {'are' if plural else 'is'} missing:\n"
237
+ for _, status in self.missing_modules.items():
238
+ msg += f" - {status}\n"
239
+ msg += f"Please install {'them' if plural else 'it'} using:\n'pip install ag2[{self.dep_target}]'"
240
+ return msg
241
+
242
+ def copy_metadata(self, retval: T) -> None:
243
+ """Copy metadata from original object to patched object
244
+
245
+ Args:
246
+ retval: Patched object
247
+
248
+ """
249
+ o = self.o
250
+ if hasattr(o, "__doc__"):
251
+ retval.__doc__ = o.__doc__
252
+ if hasattr(o, "__name__"):
253
+ retval.__name__ = o.__name__ # type: ignore[attr-defined]
254
+ if hasattr(o, "__module__"):
255
+ retval.__module__ = o.__module__
256
+
257
+ _registry: list[type["PatchObject[Any]"]] = []
258
+
259
+ @classmethod
260
+ def register(cls) -> Callable[[type["PatchObject[Any]"]], type["PatchObject[Any]"]]:
261
+ def decorator(subclass: type["PatchObject[Any]"]) -> type["PatchObject[Any]"]:
262
+ cls._registry.append(subclass)
263
+ return subclass
264
+
265
+ return decorator
266
+
267
+ @classmethod
268
+ def create(
269
+ cls,
270
+ o: T,
271
+ *,
272
+ missing_modules: dict[str, str],
273
+ dep_target: str,
274
+ ) -> Optional["PatchObject[T]"]:
275
+ for subclass in cls._registry:
276
+ if subclass.accept(o):
277
+ return subclass(o, missing_modules, dep_target)
278
+ return None
279
+
280
+
281
+ @PatchObject.register()
282
+ class PatchCallable(PatchObject[F]):
283
+ @classmethod
284
+ def accept(cls, o: Any) -> bool:
285
+ return inspect.isfunction(o) or inspect.ismethod(o)
286
+
287
+ def patch(self, except_for: Iterable[str]) -> F:
288
+ if self.o.__name__ in except_for:
289
+ return self.o
290
+
291
+ f: Callable[..., Any] = self.o
292
+
293
+ # @wraps(f.__call__) # type: ignore[operator]
294
+ @wraps(f)
295
+ def _call(*args: Any, **kwargs: Any) -> Any:
296
+ raise ImportError(self.msg)
297
+
298
+ self.copy_metadata(_call) # type: ignore[arg-type]
299
+
300
+ return _call # type: ignore[return-value]
301
+
302
+
303
+ @PatchObject.register()
304
+ class PatchStatic(PatchObject[F]):
305
+ @classmethod
306
+ def accept(cls, o: Any) -> bool:
307
+ # return inspect.ismethoddescriptor(o)
308
+ return isinstance(o, staticmethod)
309
+
310
+ def patch(self, except_for: Iterable[str]) -> F:
311
+ if hasattr(self.o, "__name__"):
312
+ name = self.o.__name__
313
+ elif hasattr(self.o, "__func__"):
314
+ name = self.o.__func__.__name__
315
+ else:
316
+ raise ValueError(f"Cannot determine name for object {self.o}")
317
+ if name in except_for:
318
+ return self.o
319
+
320
+ f: Callable[..., Any] = self.o.__func__ # type: ignore[attr-defined]
321
+
322
+ @wraps(f)
323
+ def _call(*args: Any, **kwargs: Any) -> Any:
324
+ raise ImportError(self.msg)
325
+
326
+ self.copy_metadata(_call) # type: ignore[arg-type]
327
+
328
+ return staticmethod(_call) # type: ignore[return-value]
329
+
330
+ def get_object_with_metadata(self) -> Any:
331
+ return self.o.__func__ # type: ignore[attr-defined]
332
+
333
+
334
+ @PatchObject.register()
335
+ class PatchInit(PatchObject[F]):
336
+ @classmethod
337
+ def accept(cls, o: Any) -> bool:
338
+ return inspect.ismethoddescriptor(o) and o.__name__ == "__init__"
339
+
340
+ def patch(self, except_for: Iterable[str]) -> F:
341
+ if self.o.__name__ in except_for:
342
+ return self.o
343
+
344
+ f: Callable[..., Any] = self.o
345
+
346
+ @wraps(f)
347
+ def _call(*args: Any, **kwargs: Any) -> Any:
348
+ raise ImportError(self.msg)
349
+
350
+ self.copy_metadata(_call) # type: ignore[arg-type]
351
+
352
+ return staticmethod(_call) # type: ignore[return-value]
353
+
354
+ def get_object_with_metadata(self) -> Any:
355
+ return self.o
356
+
357
+
358
+ @PatchObject.register()
359
+ class PatchProperty(PatchObject[Any]):
360
+ @classmethod
361
+ def accept(cls, o: Any) -> bool:
362
+ return inspect.isdatadescriptor(o) and hasattr(o, "fget")
363
+
364
+ def patch(self, except_for: Iterable[str]) -> property:
365
+ if not hasattr(self.o, "fget"):
366
+ raise ValueError(f"Cannot patch property without getter: {self.o}")
367
+ f: Callable[..., Any] = self.o.fget
368
+
369
+ if f.__name__ in except_for:
370
+ return self.o # type: ignore[no-any-return]
371
+
372
+ @wraps(f)
373
+ def _call(*args: Any, **kwargs: Any) -> Any:
374
+ raise ImportError(self.msg)
375
+
376
+ self.copy_metadata(_call)
377
+
378
+ return property(_call)
379
+
380
+ def get_object_with_metadata(self) -> Any:
381
+ return self.o.fget
382
+
383
+
384
+ @PatchObject.register()
385
+ class PatchClass(PatchObject[type[Any]]):
386
+ @classmethod
387
+ def accept(cls, o: Any) -> bool:
388
+ return inspect.isclass(o)
389
+
390
+ def patch(self, except_for: Iterable[str]) -> type[Any]:
391
+ if self.o.__name__ in except_for:
392
+ return self.o
393
+
394
+ for name, member in inspect.getmembers(self.o):
395
+ # Patch __init__ method if possible, but not other internal methods
396
+ if name.startswith("__") and name != "__init__":
397
+ continue
398
+ patched = patch_object(
399
+ member,
400
+ missing_modules=self.missing_modules,
401
+ dep_target=self.dep_target,
402
+ fail_if_not_patchable=False,
403
+ except_for=except_for,
404
+ )
405
+ with suppress(AttributeError):
406
+ setattr(self.o, name, patched)
407
+
408
+ return self.o
409
+
410
+
411
+ def patch_object(
412
+ o: T,
413
+ *,
414
+ missing_modules: dict[str, str],
415
+ dep_target: str,
416
+ fail_if_not_patchable: bool = True,
417
+ except_for: str | Iterable[str] | None = None,
418
+ ) -> T:
419
+ patcher = PatchObject.create(o, missing_modules=missing_modules, dep_target=dep_target)
420
+ if fail_if_not_patchable and patcher is None:
421
+ raise ValueError(f"Cannot patch object of type {type(o)}")
422
+
423
+ except_for = except_for if except_for is not None else []
424
+ except_for = [except_for] if isinstance(except_for, str) else except_for
425
+
426
+ return patcher.patch(except_for=except_for) if patcher else o
427
+
428
+
429
+ def require_optional_import(
430
+ modules: str | Iterable[str],
431
+ dep_target: str,
432
+ *,
433
+ except_for: str | Iterable[str] | None = None,
434
+ ) -> Callable[[T], T]:
435
+ """Decorator to handle optional module dependencies
436
+
437
+ Args:
438
+ modules: Module name or list of module names required
439
+ dep_target: Target name for pip installation (e.g. 'test' in pip install ag2[test])
440
+ except_for: Name or list of names of objects to exclude from patching
441
+ """
442
+ missing_modules = get_missing_imports(modules)
443
+
444
+ if not missing_modules:
445
+
446
+ def decorator(o: T) -> T:
447
+ return o
448
+
449
+ else:
450
+
451
+ def decorator(o: T) -> T:
452
+ return patch_object(o, missing_modules=missing_modules, dep_target=dep_target, except_for=except_for)
453
+
454
+ return decorator
455
+
456
+
457
+ def _mark_object(o: T, dep_target: str) -> T:
458
+ import pytest
459
+
460
+ markname = dep_target.replace("-", "_")
461
+ pytest_mark_markname = getattr(pytest.mark, markname)
462
+ pytest_mark_o = pytest_mark_markname(o)
463
+
464
+ pytest_mark_o = pytest.mark.aux_neg_flag(pytest_mark_o)
465
+
466
+ return pytest_mark_o # type: ignore[no-any-return]
467
+
468
+
469
+ def run_for_optional_imports(modules: str | Iterable[str], dep_target: str) -> Callable[[G], G]:
470
+ """Decorator to run a test if and only if optional modules are installed
471
+
472
+ Args:
473
+ modules: Module name or list of module names
474
+ dep_target: Target name for pip installation (e.g. 'test' in pip install ag2[test])
475
+ """
476
+ # missing_modules = get_missing_imports(modules)
477
+ # if missing_modules:
478
+ # raise ImportError(f"Missing module{'s' if len(missing_modules) > 1 else ''}: {', '.join(missing_modules)}. Install using 'pip install ag2[{dep_target}]'")
479
+
480
+ def decorator(o: G) -> G:
481
+ missing_modules = get_missing_imports(modules)
482
+
483
+ if isinstance(o, type):
484
+ wrapped = require_optional_import(modules, dep_target)(o)
485
+ else:
486
+ if is_coroutine_callable(o):
487
+
488
+ @wraps(o)
489
+ async def wrapped(*args: Any, **kwargs: Any) -> Any:
490
+ if missing_modules:
491
+ raise ImportError(
492
+ f"Missing module{'s' if len(missing_modules) > 1 else ''}: {', '.join(missing_modules)}. Install using 'pip install ag2[{dep_target}]'"
493
+ )
494
+ return await o(*args, **kwargs)
495
+
496
+ else:
497
+
498
+ @wraps(o)
499
+ def wrapped(*args: Any, **kwargs: Any) -> Any:
500
+ if missing_modules:
501
+ raise ImportError(
502
+ f"Missing module{'s' if len(missing_modules) > 1 else ''}: {', '.join(missing_modules)}. Install using 'pip install ag2[{dep_target}]'"
503
+ )
504
+ return o(*args, **kwargs)
505
+
506
+ pytest_mark_o: G = _mark_object(wrapped, dep_target) # type: ignore[assignment]
507
+
508
+ return pytest_mark_o
509
+
510
+ return decorator
511
+
512
+
513
+ def skip_on_missing_imports(modules: str | Iterable[str], dep_target: str) -> Callable[[T], T]:
514
+ """Decorator to skip a test if an optional module is missing
515
+
516
+ Args:
517
+ modules: Module name or list of module names
518
+ dep_target: Target name for pip installation (e.g. 'test' in pip install ag2[test])
519
+ """
520
+ import pytest
521
+
522
+ missing_modules = get_missing_imports(modules)
523
+
524
+ if not missing_modules:
525
+
526
+ def decorator(o: T) -> T:
527
+ pytest_mark_o = _mark_object(o, dep_target)
528
+ return pytest_mark_o # type: ignore[no-any-return]
529
+
530
+ else:
531
+
532
+ def decorator(o: T) -> T:
533
+ pytest_mark_o = _mark_object(o, dep_target)
534
+
535
+ return pytest.mark.skip( # type: ignore[return-value,no-any-return]
536
+ f"Missing module{'s' if len(missing_modules) > 1 else ''}: {', '.join(missing_modules)}. Install using 'pip install ag2[{dep_target}]'"
537
+ )(pytest_mark_o)
538
+
539
+ return decorator
@@ -0,0 +1,22 @@
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 .crewai import CrewAIInteroperability
6
+ from .interoperability import Interoperability
7
+ from .interoperable import Interoperable
8
+ from .langchain import LangChainChatModelFactory, LangChainInteroperability
9
+ from .litellm import LiteLLmConfigFactory
10
+ from .pydantic_ai import PydanticAIInteroperability
11
+ from .registry import register_interoperable_class
12
+
13
+ __all__ = [
14
+ "CrewAIInteroperability",
15
+ "Interoperability",
16
+ "Interoperable",
17
+ "LangChainChatModelFactory",
18
+ "LangChainInteroperability",
19
+ "LiteLLmConfigFactory",
20
+ "PydanticAIInteroperability",
21
+ "register_interoperable_class",
22
+ ]
@@ -0,0 +1,7 @@
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 .crewai import CrewAIInteroperability
6
+
7
+ __all__ = ["CrewAIInteroperability"]
@@ -0,0 +1,88 @@
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
+ import re
6
+ import sys
7
+ from typing import Any
8
+
9
+ from ...doc_utils import export_module
10
+ from ...import_utils import optional_import_block, require_optional_import
11
+ from ...tools import Tool
12
+ from ..registry import register_interoperable_class
13
+
14
+ __all__ = ["CrewAIInteroperability"]
15
+
16
+
17
+ def _sanitize_name(s: str) -> str:
18
+ return re.sub(r"\W|^(?=\d)", "_", s)
19
+
20
+
21
+ with optional_import_block():
22
+ from crewai.tools import BaseTool as CrewAITool
23
+
24
+
25
+ @register_interoperable_class("crewai")
26
+ @export_module("autogen.interop")
27
+ class CrewAIInteroperability:
28
+ """A class implementing the `Interoperable` protocol for converting CrewAI tools
29
+ to a general `Tool` format.
30
+
31
+ This class takes a `CrewAITool` and converts it into a standard `Tool` object.
32
+ """
33
+
34
+ @classmethod
35
+ @require_optional_import("crewai", "interop-crewai")
36
+ def convert_tool(cls, tool: Any, **kwargs: Any) -> Tool:
37
+ """Converts a given CrewAI tool into a general `Tool` format.
38
+
39
+ This method ensures that the provided tool is a valid `CrewAITool`, sanitizes
40
+ the tool's name, processes its description, and prepares a function to interact
41
+ with the tool's arguments. It then returns a standardized `Tool` object.
42
+
43
+ Args:
44
+ tool (Any): The tool to convert, expected to be an instance of `CrewAITool`.
45
+ **kwargs (Any): Additional arguments, which are not supported by this method.
46
+
47
+ Returns:
48
+ Tool: A standardized `Tool` object converted from the CrewAI tool.
49
+
50
+ Raises:
51
+ ValueError: If the provided tool is not an instance of `CrewAITool`, or if
52
+ any additional arguments are passed.
53
+ """
54
+ if not isinstance(tool, CrewAITool):
55
+ raise ValueError(f"Expected an instance of `crewai.tools.BaseTool`, got {type(tool)}")
56
+ if kwargs:
57
+ raise ValueError(f"The CrewAIInteroperability does not support any additional arguments, got {kwargs}")
58
+
59
+ # needed for type checking
60
+ crewai_tool: CrewAITool = tool # type: ignore[no-any-unimported]
61
+
62
+ name = _sanitize_name(crewai_tool.name)
63
+ description = (
64
+ crewai_tool.description.split("Tool Description: ")[-1]
65
+ + " (IMPORTANT: When using arguments, put them all in an `args` dictionary)"
66
+ )
67
+
68
+ def func(args: crewai_tool.args_schema) -> Any: # type: ignore[no-any-unimported]
69
+ return crewai_tool.run(**args.model_dump())
70
+
71
+ return Tool(
72
+ name=name,
73
+ description=description,
74
+ func_or_tool=func,
75
+ )
76
+
77
+ @classmethod
78
+ def get_unsupported_reason(cls) -> str | None:
79
+ if sys.version_info < (3, 10) or sys.version_info >= (3, 13):
80
+ return "This submodule is only supported for Python versions 3.10, 3.11, and 3.12"
81
+
82
+ with optional_import_block() as result:
83
+ import crewai.tools # noqa: F401
84
+
85
+ if not result.is_successful:
86
+ return "Please install `interop-crewai` extra to use this module:\n\n\tpip install ag2[interop-crewai]"
87
+
88
+ return None