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,577 @@
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 builtins
5
+ import importlib
6
+ import inspect
7
+ import json
8
+ import re
9
+ import sys
10
+ import tempfile
11
+ from collections.abc import Callable, Iterable, Iterator, Mapping
12
+ from contextlib import contextmanager
13
+ from functools import wraps
14
+ from logging import getLogger
15
+ from pathlib import Path
16
+ from types import ModuleType
17
+ from typing import (
18
+ TYPE_CHECKING,
19
+ Any,
20
+ Literal,
21
+ )
22
+
23
+ import requests
24
+ from pydantic import PydanticInvalidForJsonSchema
25
+ from pydantic_core import PydanticUndefined
26
+
27
+ from autogen.import_utils import optional_import_block, require_optional_import
28
+
29
+ from .security import BaseSecurity, BaseSecurityParameters
30
+
31
+ with optional_import_block() as result:
32
+ import fastapi
33
+ import yaml
34
+ from datamodel_code_generator import DataModelType
35
+ from fastapi_code_generator.__main__ import generate_code
36
+ from jinja2 import Environment, FileSystemLoader
37
+ from mcp.server.fastmcp import FastMCP
38
+
39
+
40
+ if TYPE_CHECKING:
41
+ from autogen.agentchat import ConversableAgent
42
+
43
+ __all__ = ["MCPProxy"]
44
+
45
+ logger = getLogger(__name__)
46
+
47
+
48
+ @contextmanager
49
+ def optional_temp_path(path: str | None = None) -> Iterator[Path]:
50
+ if path is None:
51
+ with tempfile.TemporaryDirectory() as temp_dir:
52
+ yield Path(temp_dir)
53
+ else:
54
+ yield Path(path)
55
+
56
+
57
+ @contextmanager
58
+ def add_to_builtins(new_globals: dict[str, Any]) -> Iterator[None]:
59
+ old_globals = {key: getattr(builtins, key, None) for key in new_globals}
60
+
61
+ try:
62
+ for key, value in new_globals.items():
63
+ setattr(builtins, key, value) # Inject new global
64
+ yield
65
+ finally:
66
+ for key, value in old_globals.items():
67
+ if value is None:
68
+ delattr(builtins, key) # Remove added globals
69
+ else:
70
+ setattr(builtins, key, value) # Restore original value
71
+
72
+
73
+ class MCPProxy:
74
+ def __init__(self, servers: list[dict[str, Any]], title: str | None = None, **kwargs: Any) -> None:
75
+ """Proxy class to generate client from OpenAPI schema."""
76
+ self._servers = servers
77
+ self._title = title or "MCP Proxy"
78
+ self._kwargs = kwargs
79
+ self._registered_funcs: list[Callable[..., Any]] = []
80
+ self._globals: dict[str, Any] = {}
81
+
82
+ self._security: dict[str, list[BaseSecurity]] = {}
83
+ self._security_params: dict[str | None, BaseSecurityParameters] = {}
84
+ self._tags: set[str] = set()
85
+
86
+ self._function_group: dict[str, list[str]] = {}
87
+
88
+ @staticmethod
89
+ def _convert_camel_case_within_braces_to_snake(text: str) -> str:
90
+ # Function to convert camel case to snake case
91
+ def camel_to_snake(match: re.Match[str]) -> str:
92
+ return re.sub(r"(?<!^)(?=[A-Z])", "_", match.group(1)).lower()
93
+
94
+ # Find all occurrences inside curly braces and apply camel_to_snake
95
+ result = re.sub(r"\{([a-zA-Z0-9]+)\}", lambda m: "{" + camel_to_snake(m) + "}", text)
96
+
97
+ return result
98
+
99
+ @staticmethod
100
+ def _get_params(path: str, func: Callable[..., Any]) -> tuple[set[str], set[str], str | None, bool]:
101
+ sig = inspect.signature(func)
102
+
103
+ params_names = set(sig.parameters.keys())
104
+
105
+ path_params = set(re.findall(r"\{(.+?)\}", path))
106
+ if not path_params.issubset(params_names):
107
+ raise ValueError(f"Path params {path_params} not in {params_names}")
108
+
109
+ body = "body" if "body" in params_names else None
110
+
111
+ security = "security" in params_names
112
+
113
+ q_params = set(params_names) - path_params - {body} - {"security"}
114
+
115
+ return q_params, path_params, body, security
116
+
117
+ def get_mcp(self, **settings: Any) -> "FastMCP":
118
+ mcp = FastMCP(name=self._title, **settings) # newer mcp
119
+
120
+ for func in self._registered_funcs:
121
+ try:
122
+ mcp.tool()(func)
123
+ except PydanticInvalidForJsonSchema as e:
124
+ logger.warning("Could not register function %s: %s", func.__name__, e)
125
+
126
+ return mcp
127
+
128
+ def _process_params(
129
+ self, process_path: str, func: Callable[[Any], Any], **kwargs: Any
130
+ ) -> tuple[str, dict[str, Any], dict[str, Any]]:
131
+ process_path = MCPProxy._convert_camel_case_within_braces_to_snake(process_path)
132
+ q_params, path_params, body, security = MCPProxy._get_params(process_path, func)
133
+
134
+ expanded_path = process_path.format(**{p: kwargs[p] for p in path_params})
135
+
136
+ url = self._servers[0]["url"] + expanded_path
137
+
138
+ body_dict = {}
139
+ if body and body in kwargs:
140
+ body_value = kwargs[body]
141
+ if isinstance(body_value, dict):
142
+ body_dict = {"json": body_value}
143
+ elif hasattr(body_value, "model_dump"):
144
+ body_dict = {"json": body_value.model_dump()}
145
+ else:
146
+ body_dict = {"json": body_value.dict()}
147
+
148
+ body_dict["headers"] = {"Content-Type": "application/json"}
149
+ if security:
150
+ q_params, body_dict = kwargs["security"].add_security(q_params, body_dict)
151
+ # body_dict["headers"][security] = kwargs["security"]
152
+
153
+ params = {k: v for k, v in kwargs.items() if k in q_params}
154
+
155
+ return url, params, body_dict
156
+
157
+ def set_security_params(self, security_params: BaseSecurityParameters, name: str | None = None) -> None:
158
+ if name is not None:
159
+ security = self._security.get(name)
160
+ if security is None:
161
+ raise ValueError(f"Security is not set for '{name}'")
162
+
163
+ for match_security in security:
164
+ if match_security.accept(security_params):
165
+ break
166
+ else:
167
+ raise ValueError(f"Security parameters {security_params} do not match security {security}")
168
+
169
+ self._security_params[name] = security_params
170
+
171
+ def _get_matching_security(
172
+ self, security: list[BaseSecurity], security_params: BaseSecurityParameters
173
+ ) -> BaseSecurity:
174
+ # check if security matches security parameters
175
+ for match_security in security:
176
+ if match_security.accept(security_params):
177
+ return match_security
178
+ raise ValueError(f"Security parameters {security_params} does not match any given security {security}")
179
+
180
+ def _get_security_params(self, name: str) -> tuple[BaseSecurityParameters | None, BaseSecurity | None]:
181
+ # check if security is set for the method
182
+ security = self._security.get(name)
183
+ if not security:
184
+ return None, None
185
+
186
+ security_params = self._security_params.get(name)
187
+ if security_params is None:
188
+ # check if default security parameters are set
189
+ security_params = self._security_params.get(None)
190
+ if security_params is None:
191
+ raise ValueError(
192
+ f"Security parameters are not set for {name} and there are no default security parameters"
193
+ )
194
+
195
+ match_security = self._get_matching_security(security, security_params)
196
+
197
+ return security_params, match_security
198
+
199
+ def _request(
200
+ self,
201
+ method: Literal["put", "get", "post", "head", "delete", "patch"],
202
+ path: str,
203
+ description: str | None = None,
204
+ security: list[BaseSecurity] | None = None,
205
+ **kwargs: Any,
206
+ ) -> Callable[..., dict[str, Any]]:
207
+ def decorator(func: Callable[..., Any]) -> Callable[..., dict[str, Any]]:
208
+ name = func.__name__
209
+
210
+ for tag in kwargs.get("tags", []):
211
+ if tag not in self._function_group:
212
+ self._function_group[tag] = []
213
+ self._function_group[tag].append(name)
214
+
215
+ if security is not None:
216
+ self._security[name] = security
217
+
218
+ @wraps(func)
219
+ def wrapper(*args: Any, **kwargs: Any) -> dict[str, Any]:
220
+ url, params, body_dict = self._process_params(path, func, **kwargs)
221
+
222
+ security = self._security.get(name)
223
+ if security is not None:
224
+ security_params, matched_security = self._get_security_params(name)
225
+ if security_params is None:
226
+ raise ValueError(f"Security parameters are not set for '{name}'")
227
+ else:
228
+ security_params.apply(params, body_dict, matched_security) # type: ignore [arg-type]
229
+
230
+ response = getattr(requests, method)(url, params=params, **body_dict)
231
+ return response.json() # type: ignore [no-any-return]
232
+
233
+ wrapper._description = ( # type: ignore [attr-defined]
234
+ description or func.__doc__.strip() if func.__doc__ is not None else None
235
+ )
236
+
237
+ self._registered_funcs.append(wrapper)
238
+
239
+ return wrapper
240
+
241
+ return decorator # type: ignore [return-value]
242
+
243
+ def put(self, path: str, **kwargs: Any) -> Callable[..., dict[str, Any]]:
244
+ return self._request("put", path, **kwargs)
245
+
246
+ def get(self, path: str, **kwargs: Any) -> Callable[..., dict[str, Any]]:
247
+ return self._request("get", path, **kwargs)
248
+
249
+ def post(self, path: str, **kwargs: Any) -> Callable[..., dict[str, Any]]:
250
+ return self._request("post", path, **kwargs)
251
+
252
+ def delete(self, path: str, **kwargs: Any) -> Callable[..., dict[str, Any]]:
253
+ return self._request("delete", path, **kwargs)
254
+
255
+ def head(self, path: str, **kwargs: Any) -> Callable[..., dict[str, Any]]:
256
+ return self._request("head", path, **kwargs)
257
+
258
+ def patch(self, path: str, **kwargs: Any) -> Callable[..., dict[str, Any]]:
259
+ return self._request("patch", path, **kwargs)
260
+
261
+ @classmethod
262
+ def _get_template_dir(cls) -> Path:
263
+ path = Path(__file__).parents[3] / "templates"
264
+ if not path.exists():
265
+ raise RuntimeError(f"Template directory {path.resolve()} not found.")
266
+ return path
267
+
268
+ @classmethod
269
+ @require_optional_import(["datamodel_code_generator", "fastapi_code_generator"], "mcp-proxy-gen")
270
+ def generate_code(
271
+ cls,
272
+ input_text: str,
273
+ output_dir: Path,
274
+ disable_timestamp: bool = False,
275
+ custom_visitors: list[Path] | None = None,
276
+ ) -> str:
277
+ if custom_visitors is None:
278
+ custom_visitors = []
279
+ custom_visitors.append(Path(__file__).parent / "security_schema_visitor.py")
280
+
281
+ # with patch_get_parameter_type():
282
+ generate_code(
283
+ input_name="openapi.yaml",
284
+ input_text=input_text,
285
+ encoding="utf-8",
286
+ output_dir=output_dir,
287
+ template_dir=cls._get_template_dir() / "client_template",
288
+ disable_timestamp=disable_timestamp,
289
+ custom_visitors=custom_visitors,
290
+ output_model_type=DataModelType.PydanticV2BaseModel,
291
+ )
292
+
293
+ main_path = output_dir / "main.py"
294
+
295
+ with main_path.open("r") as f:
296
+ main_py_code = f.read()
297
+ # main_py_code = main_py_code.replace("from .models import", "from models import")
298
+ main_py_code = main_py_code.replace("from .models", "from models")
299
+ # Removing "from __future__ import annotations" to avoid ForwardRef issues, should be fixed in fastapi_code_generator
300
+ main_py_code = main_py_code.replace("from __future__ import annotations", "")
301
+
302
+ with main_path.open("w") as f:
303
+ f.write(main_py_code)
304
+
305
+ return main_path.stem
306
+
307
+ def set_globals(self, main: ModuleType, suffix: str) -> None:
308
+ xs = {k: v for k, v in main.__dict__.items() if not k.startswith("__")}
309
+ self._globals = {
310
+ k: v for k, v in xs.items() if hasattr(v, "__module__") and v.__module__ in [f"models_{suffix}", "typing"]
311
+ }
312
+
313
+ @classmethod
314
+ @require_optional_import(["yaml"], "mcp-proxy-gen")
315
+ def create(
316
+ cls,
317
+ *,
318
+ openapi_specification: str | None = None,
319
+ openapi_url: str | None = None,
320
+ client_source_path: str | None = None,
321
+ servers: list[dict[str, Any]] | None = None,
322
+ rename_functions: bool = False,
323
+ group_functions: bool = False,
324
+ configuration_type: Literal["json", "yaml"] = "json",
325
+ ) -> "MCPProxy":
326
+ if (openapi_specification is None) == (openapi_url is None):
327
+ raise ValueError("Either openapi_specification or openapi_url should be provided")
328
+
329
+ if openapi_specification is None and openapi_url is not None:
330
+ with requests.get(openapi_url, timeout=10) as response:
331
+ response.raise_for_status()
332
+ openapi_specification = response.text
333
+
334
+ openapi_parsed = (
335
+ json.loads(openapi_specification) if configuration_type == "json" else yaml.safe_load(openapi_specification)
336
+ ) # type: ignore [arg-type]
337
+
338
+ if servers:
339
+ openapi_parsed["servers"] = servers
340
+
341
+ yaml_friendly = yaml.safe_dump(openapi_parsed)
342
+
343
+ with optional_temp_path(client_source_path) as td:
344
+ suffix = td.name # noqa F841
345
+
346
+ custom_visitors = []
347
+
348
+ if rename_functions:
349
+ custom_visitors.append(Path(__file__).parent / "operation_renaming.py")
350
+
351
+ if group_functions:
352
+ custom_visitors.append(Path(__file__).parent / "operation_grouping.py")
353
+
354
+ main_name = cls.generate_code( # noqa F841
355
+ input_text=yaml_friendly, # type: ignore [arg-type]
356
+ output_dir=td,
357
+ custom_visitors=custom_visitors,
358
+ )
359
+ # add td to sys.path
360
+ try:
361
+ sys.path.append(str(td))
362
+ main = importlib.import_module(main_name, package=td.name) # nosemgrep
363
+ finally:
364
+ sys.path.remove(str(td))
365
+
366
+ client: MCPProxy = main.app # type: ignore [attr-defined]
367
+ client.set_globals(main, suffix=suffix)
368
+
369
+ client.dump_configurations(output_dir=td)
370
+
371
+ return client
372
+
373
+ def _get_authentications(self) -> list[dict[str, Any]]:
374
+ seen = set()
375
+ authentications = []
376
+
377
+ for security_list in self._security.values():
378
+ for security in security_list:
379
+ params = security.Parameters().dump()
380
+
381
+ if params.get("type") == "unsupported":
382
+ continue
383
+
384
+ dumped = json.dumps(params) # hashable
385
+ if dumped not in seen:
386
+ seen.add(dumped)
387
+ authentications.append(security.Parameters().dump())
388
+ return authentications
389
+
390
+ def dump_configurations(self, output_dir: Path) -> None:
391
+ for tag in self._function_group:
392
+ output_file = output_dir / f"mcp_config_{tag}.json"
393
+
394
+ functions = [
395
+ registered_function
396
+ for registered_function in self._registered_funcs
397
+ if registered_function.__name__ in self._function_group[tag]
398
+ ]
399
+
400
+ self.dump_configuration(output_file, functions)
401
+
402
+ self.dump_configuration(output_dir / "mcp_config.json", self._registered_funcs)
403
+
404
+ def dump_configuration(self, output_file: Path, functions: list[Callable[..., Any]] = None) -> None:
405
+ # Define paths
406
+ template_dir = MCPProxy._get_template_dir() / "config_template"
407
+ template_file = "config.jinja2"
408
+
409
+ # Load Jinja environment
410
+ env = Environment(loader=FileSystemLoader(template_dir), trim_blocks=True, lstrip_blocks=True)
411
+
412
+ # Load the template
413
+ template = env.get_template(template_file)
414
+ # Prepare context for rendering
415
+ context = {
416
+ "server_url": self._servers[0]["url"], # single or list depending on your structure
417
+ "authentications": self._get_authentications(), # list of auth blocks, we will also need to check _security_params
418
+ "operations": [
419
+ {
420
+ "name": op.__name__,
421
+ "description": op._description.replace("\n", " ").replace("\r", "").strip()
422
+ if op._description is not None
423
+ else "",
424
+ }
425
+ for op in functions
426
+ ],
427
+ }
428
+
429
+ # Render the template
430
+ rendered_config = template.render(context)
431
+
432
+ # Save the output to a file
433
+ with open(output_file, "w") as f:
434
+ f.write(rendered_config)
435
+
436
+ def load_configuration(self, config_file: str) -> None:
437
+ with Path(config_file).open("r") as f:
438
+ config_data_str = f.read()
439
+
440
+ self.load_configuration_from_string(config_data_str)
441
+
442
+ def load_configuration_from_string(self, config_data_str: str) -> None:
443
+ config_data = json.loads(config_data_str)
444
+ # Load server URL
445
+ self._servers = [{"url": config_data["server"]["url"]}]
446
+
447
+ # Load authentication
448
+ for auth in config_data.get("authentication", []):
449
+ security = BaseSecurity.parse_security_parameters(auth)
450
+ self.set_security_params(security)
451
+
452
+ operation_names = [op["name"] for op in config_data.get("operations", [])]
453
+
454
+ self._registered_funcs = [func for func in self._registered_funcs if func.__name__ in operation_names]
455
+
456
+ def _get_functions_to_register(
457
+ self,
458
+ functions: Iterable[str | Mapping[str, Mapping[str, str]]] | None = None,
459
+ ) -> dict[Callable[..., Any], dict[str, str | None]]:
460
+ if functions is None:
461
+ return {
462
+ f: {
463
+ "name": None,
464
+ "description": f._description if hasattr(f, "_description") else None,
465
+ }
466
+ for f in self._registered_funcs
467
+ }
468
+
469
+ functions_with_name_desc: dict[str, dict[str, str | None]] = {}
470
+
471
+ for f in functions:
472
+ if isinstance(f, str):
473
+ functions_with_name_desc[f] = {"name": None, "description": None}
474
+ elif isinstance(f, dict):
475
+ functions_with_name_desc.update({
476
+ k: {
477
+ "name": v.get("name", None),
478
+ "description": v.get("description", None),
479
+ }
480
+ for k, v in f.items()
481
+ })
482
+ else:
483
+ raise ValueError(f"Invalid type {type(f)} for function {f}")
484
+
485
+ funcs_to_register: dict[Callable[..., Any], dict[str, str | None]] = {
486
+ f: functions_with_name_desc[f.__name__]
487
+ for f in self._registered_funcs
488
+ if f.__name__ in functions_with_name_desc
489
+ }
490
+ missing_functions = set(functions_with_name_desc.keys()) - {f.__name__ for f in funcs_to_register}
491
+ if missing_functions:
492
+ raise ValueError(f"Following functions {missing_functions} are not valid functions")
493
+
494
+ return funcs_to_register
495
+
496
+ @staticmethod
497
+ def _remove_pydantic_undefined_from_tools(
498
+ tools: list[dict[str, Any]],
499
+ ) -> list[dict[str, Any]]:
500
+ for tool in tools:
501
+ if "function" not in tool:
502
+ continue
503
+
504
+ function = tool["function"]
505
+ if "parameters" not in function or "properties" not in function["parameters"]:
506
+ continue
507
+
508
+ required = function["parameters"].get("required", [])
509
+ for param_name, param_value in function["parameters"]["properties"].items():
510
+ if "default" not in param_value:
511
+ continue
512
+
513
+ default = param_value.get("default")
514
+ if (
515
+ isinstance(default, (fastapi.params.Path, fastapi.params.Query))
516
+ and param_value["default"].default is PydanticUndefined
517
+ ):
518
+ param_value.pop("default")
519
+ # We removed the default value, so we need to add the parameter to the required list
520
+ if param_name not in required:
521
+ required.append(param_name)
522
+
523
+ return tools
524
+
525
+ def _register_for_llm(
526
+ self,
527
+ agent: "ConversableAgent",
528
+ functions: Iterable[str | Mapping[str, Mapping[str, str]]] | None = None,
529
+ ) -> None:
530
+ funcs_to_register = self._get_functions_to_register(functions)
531
+
532
+ with add_to_builtins(
533
+ new_globals=self._globals,
534
+ ):
535
+ for f, v in funcs_to_register.items():
536
+ agent.register_for_llm(name=v["name"], description=v["description"])(f)
537
+
538
+ agent.llm_config["tools"] = MCPProxy._remove_pydantic_undefined_from_tools(agent.llm_config["tools"])
539
+
540
+ def _register_for_execution(
541
+ self,
542
+ agent: "ConversableAgent",
543
+ functions: Iterable[str | Mapping[str, Mapping[str, str]]] | None = None,
544
+ ) -> None:
545
+ funcs_to_register = self._get_functions_to_register(functions)
546
+
547
+ for f, v in funcs_to_register.items():
548
+ agent.register_for_execution(name=v["name"])(f)
549
+
550
+ def get_functions(self) -> list[str]:
551
+ raise DeprecationWarning("Use function_names property instead of get_functions method")
552
+
553
+ @property
554
+ def function_names(self) -> list[str]:
555
+ return [f.__name__ for f in self._registered_funcs]
556
+
557
+ def get_function(self, name: str) -> Callable[..., dict[str, Any]]:
558
+ for f in self._registered_funcs:
559
+ if f.__name__ == name:
560
+ return f
561
+ raise ValueError(f"Function {name} not found")
562
+
563
+ def set_function(self, name: str, func: Callable[..., dict[str, Any]]) -> None:
564
+ for i, f in enumerate(self._registered_funcs):
565
+ if f.__name__ == name:
566
+ self._registered_funcs[i] = func
567
+ return
568
+
569
+ raise ValueError(f"Function {name} not found")
570
+
571
+ def inject_parameters(self, name: str, **kwargs: Any) -> None:
572
+ raise NotImplementedError("Injecting parameters is not implemented yet")
573
+ # for f in self._registered_funcs:
574
+ # if f.__name__ == name:
575
+ # return
576
+
577
+ # raise ValueError(f"Function {name} not found")