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,134 @@
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 json
6
+ import logging
7
+ import os
8
+ import time
9
+ from pathlib import Path
10
+ from typing import Annotated
11
+
12
+ from ....doc_utils import export_module
13
+ from ....import_utils import optional_import_block, require_optional_import
14
+ from .document_utils import handle_input
15
+
16
+ with optional_import_block():
17
+ from docling.datamodel.base_models import InputFormat
18
+ from docling.datamodel.pipeline_options import ( # type: ignore[attr-defined]
19
+ AcceleratorDevice,
20
+ AcceleratorOptions,
21
+ PdfPipelineOptions,
22
+ )
23
+ from docling.document_converter import DocumentConverter, PdfFormatOption
24
+
25
+ __all__ = ["docling_parse_docs"]
26
+
27
+ logger = logging.getLogger(__name__)
28
+ logger.setLevel(logging.DEBUG)
29
+
30
+
31
+ @require_optional_import(["docling"], "rag")
32
+ @export_module("autogen.agents.experimental.document_agent")
33
+ def docling_parse_docs( # type: ignore[no-any-unimported]
34
+ input_file_path: Annotated[Path | str, "Path to the input file or directory"],
35
+ output_dir_path: Annotated[Path | str | None, "Path to the output directory"] = None,
36
+ output_formats: Annotated[list[str] | None, "List of output formats (markdown, json)"] = None,
37
+ table_output_format: str = "html",
38
+ ) -> list[Path]:
39
+ """Convert documents into a Deep Search document format using EasyOCR
40
+ with CPU only, and export the document and its tables to the specified
41
+ output directory.
42
+
43
+ Supported formats:
44
+ PDF,
45
+ IMAGE,
46
+ DOCX,
47
+ HTML,
48
+ PPTX,
49
+ ASCIIDOC,
50
+ MD,
51
+
52
+ Args:
53
+ input_file_path (Union[Path, str]): The path to the input file.
54
+ output_dir_path (Union[Path, str]): The path to the output directory.
55
+ output_formats (list[str], optional): The output formats. Defaults to ["markdown"].
56
+ table_output_format (str, optional): The output format for tables. Defaults to "html".
57
+
58
+ Returns:
59
+ list[ConversionResult]: The result of the conversion.
60
+ """
61
+ output_dir_path = output_dir_path or (Path.cwd() / "output")
62
+ output_dir_path = Path(output_dir_path).resolve()
63
+ output_dir_path.mkdir(parents=True, exist_ok=True)
64
+ # ToDo: For some reason, output_dir_path.mkdir is not creating the directory.
65
+ # This is a workaround to create the directory if it does not exist.
66
+ # Following test is failing without this workaround:
67
+ # test/agents/experimental/document_agent/test_parser_utils.py::TestDoclingParseDocs::test_default_output_dir_path
68
+ if not os.path.exists(output_dir_path):
69
+ os.makedirs(output_dir_path)
70
+ output_formats = output_formats or ["markdown"]
71
+
72
+ input_doc_paths: list[Path] = handle_input(input_file_path, output_dir=output_dir_path)
73
+
74
+ if not input_doc_paths:
75
+ raise ValueError("No documents found.")
76
+
77
+ # Docling Parse PDF with EasyOCR (CPU only)
78
+ # ----------------------
79
+ pdf_pipeline_options = PdfPipelineOptions()
80
+ pdf_pipeline_options.do_ocr = True
81
+ if hasattr(pdf_pipeline_options.ocr_options, "use_gpu"):
82
+ pdf_pipeline_options.ocr_options.use_gpu = False # <-- set this.
83
+ pdf_pipeline_options.do_table_structure = True
84
+ pdf_pipeline_options.table_structure_options.do_cell_matching = True
85
+ pdf_pipeline_options.ocr_options.lang = ["en"]
86
+ pdf_pipeline_options.accelerator_options = AcceleratorOptions(num_threads=4, device=AcceleratorDevice.AUTO)
87
+
88
+ doc_converter = DocumentConverter(
89
+ format_options={
90
+ InputFormat.PDF: PdfFormatOption(pipeline_options=pdf_pipeline_options),
91
+ },
92
+ )
93
+
94
+ start_time = time.time()
95
+ conv_results = list(doc_converter.convert_all(input_doc_paths))
96
+ end_time = time.time() - start_time
97
+
98
+ logger.info(f"Document converted in {end_time:.2f} seconds.")
99
+
100
+ # Export results
101
+ output_dir = Path(output_dir_path).resolve()
102
+ output_dir.mkdir(parents=True, exist_ok=True)
103
+
104
+ conv_files = []
105
+
106
+ for res in conv_results:
107
+ out_path = Path(output_dir_path).resolve()
108
+ doc_filename = res.input.file.stem
109
+ logger.debug(f"Document {res.input.file.name} converted.\nSaved markdown output to: {out_path!s}")
110
+ logger.debug(res.document._export_to_indented_text(max_text_len=16))
111
+
112
+ if "markdown" in output_formats:
113
+ # Export Docling document format to markdown:
114
+ output_file = out_path / f"{doc_filename}.md"
115
+ with output_file.open("w") as fp:
116
+ fp.write(res.document.export_to_markdown())
117
+ conv_files.append(output_file)
118
+
119
+ if "json" in output_formats:
120
+ # Export Docling document format to json
121
+ output_file = out_path / f"{doc_filename}.json"
122
+ with output_file.open("w") as fp:
123
+ fp.write(json.dumps(res.document.export_to_dict()))
124
+ conv_files.append(output_file)
125
+
126
+ # Export tables (used for evaluating conversion)
127
+ if table_output_format == "html":
128
+ for table_ix, table in enumerate(res.document.tables):
129
+ # Save the table as html
130
+ element_html_filename = output_dir / f"{doc_filename}-table-{table_ix + 1}.html"
131
+ logger.debug(f"Saving HTML table to {element_html_filename}")
132
+ with element_html_filename.open("w") as fp:
133
+ fp.write(table.export_to_html())
134
+ return conv_files
@@ -0,0 +1,417 @@
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 enum import Enum
6
+ from typing import Any
7
+ from urllib.parse import urlparse
8
+
9
+ from ....import_utils import optional_import_block, require_optional_import
10
+
11
+ with optional_import_block():
12
+ import requests
13
+
14
+
15
+ class InputFormat(Enum):
16
+ """Enum representing supported input file formats."""
17
+
18
+ DOCX = "docx"
19
+ PPTX = "pptx"
20
+ HTML = "html"
21
+ XML = "xml"
22
+ IMAGE = "image"
23
+ PDF = "pdf"
24
+ ASCIIDOC = "asciidoc"
25
+ MD = "md"
26
+ CSV = "csv"
27
+ XLSX = "xlsx"
28
+ JSON = "json"
29
+ INVALID = "invalid" # Server errors or not a URL
30
+
31
+
32
+ # Map common file extensions to InputFormat
33
+ # INVALID means it's not supported
34
+ # See: https://github.com/DS4SD/docling/blob/e25d557c06afd77f1bb2c1ac4d2ece4dffcd52bd/docling/datamodel/base_models.py#L56
35
+ ExtensionToFormat = {
36
+ # DOCX formats
37
+ "docx": InputFormat.DOCX,
38
+ "dotx": InputFormat.DOCX,
39
+ "docm": InputFormat.DOCX,
40
+ "dotm": InputFormat.DOCX,
41
+ # PPTX formats
42
+ "pptx": InputFormat.PPTX,
43
+ "potx": InputFormat.PPTX,
44
+ "ppsx": InputFormat.PPTX,
45
+ "pptm": InputFormat.PPTX,
46
+ "potm": InputFormat.PPTX,
47
+ "ppsm": InputFormat.PPTX,
48
+ # Excel formats
49
+ "xlsx": InputFormat.XLSX,
50
+ # HTML formats
51
+ "html": InputFormat.HTML,
52
+ "htm": InputFormat.HTML,
53
+ "xhtml": InputFormat.HTML,
54
+ # XML formats
55
+ "xml": InputFormat.XML,
56
+ "nxml": InputFormat.XML,
57
+ "txt": InputFormat.XML, # Note: .txt could be many formats, XML is just one possibility
58
+ # Image formats
59
+ "png": InputFormat.IMAGE,
60
+ "jpg": InputFormat.IMAGE,
61
+ "jpeg": InputFormat.IMAGE,
62
+ "tiff": InputFormat.IMAGE,
63
+ "tif": InputFormat.IMAGE,
64
+ "bmp": InputFormat.IMAGE,
65
+ # PDF format
66
+ "pdf": InputFormat.PDF,
67
+ # AsciiDoc formats
68
+ "adoc": InputFormat.ASCIIDOC,
69
+ "asciidoc": InputFormat.ASCIIDOC,
70
+ "asc": InputFormat.ASCIIDOC,
71
+ # Markdown formats
72
+ "md": InputFormat.MD,
73
+ "markdown": InputFormat.MD,
74
+ # CSV format
75
+ "csv": InputFormat.CSV,
76
+ # JSON format
77
+ "json": InputFormat.JSON,
78
+ # Unsupported formats
79
+ "doc": InputFormat.INVALID,
80
+ "ppt": InputFormat.INVALID,
81
+ "xls": InputFormat.INVALID,
82
+ "gif": InputFormat.INVALID,
83
+ }
84
+
85
+
86
+ class URLAnalyzer:
87
+ """A class that analyzes URLs to determine if they point to web pages or files."""
88
+
89
+ # Mapping of input formats to their corresponding MIME types
90
+ FormatToMimeType: dict[InputFormat, list[str]] = {
91
+ InputFormat.DOCX: [
92
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
93
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.template",
94
+ ],
95
+ InputFormat.PPTX: [
96
+ "application/vnd.openxmlformats-officedocument.presentationml.template",
97
+ "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
98
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
99
+ ],
100
+ InputFormat.HTML: ["text/html", "application/xhtml+xml"],
101
+ InputFormat.XML: ["application/xml", "text/xml", "text/plain"],
102
+ InputFormat.IMAGE: [
103
+ "image/png",
104
+ "image/jpeg",
105
+ "image/tiff",
106
+ "image/gif",
107
+ "image/bmp",
108
+ ],
109
+ InputFormat.PDF: ["application/pdf"],
110
+ InputFormat.ASCIIDOC: ["text/asciidoc"],
111
+ InputFormat.MD: ["text/markdown", "text/x-markdown"],
112
+ InputFormat.CSV: ["text/csv"],
113
+ InputFormat.XLSX: ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"],
114
+ InputFormat.JSON: ["application/json"],
115
+ }
116
+
117
+ # Create a reverse mapping from MIME types to formats
118
+ # Note: For ambiguous MIME types (like "application/xml"), we'll favor the first format found
119
+ MimeTypeToFormat = {}
120
+ for format_type, mime_types in FormatToMimeType.items():
121
+ for mime_type in mime_types:
122
+ if mime_type not in MimeTypeToFormat:
123
+ MimeTypeToFormat[mime_type] = format_type
124
+
125
+ def __init__(self, url: str):
126
+ """Initialize the URLAnalyzer with a URL.
127
+
128
+ Args:
129
+ url (str): The URL to analyze
130
+ """
131
+ self.url = url
132
+ self.analysis_result: dict[str, Any] | None = None
133
+ self.final_url: str | None = None
134
+ self.redirect_chain: list[str] = []
135
+
136
+ def analyze(
137
+ self, test_url: bool = False, follow_redirects: bool = True, prioritize_extension: bool = True
138
+ ) -> dict[str, Any]:
139
+ """Analyze the URL to determine if it points to a web page or a file.
140
+
141
+ Args:
142
+ test_url (bool): Whether to test the URL by making a request
143
+ follow_redirects (bool): Whether to follow redirects when testing the URL
144
+ prioritize_extension (bool): Whether to prioritize file extension over MIME type
145
+
146
+ Returns:
147
+ dict: A dictionary containing the analysis results
148
+ """
149
+ result = {
150
+ "url": self.url,
151
+ "is_file": False,
152
+ "file_type": None,
153
+ "mime_type": None,
154
+ "method": "extension_analysis",
155
+ "redirects": False,
156
+ "redirect_count": 0,
157
+ "final_url": self.url,
158
+ }
159
+
160
+ # First try to analyze based on the URL extension
161
+ extension_analysis = self._analyze_by_extension(self.url)
162
+ if extension_analysis["is_file"]:
163
+ result.update(extension_analysis)
164
+
165
+ # If test_url is True, make a request
166
+ if test_url:
167
+ request_analysis = self._analyze_by_request(follow_redirects)
168
+ if request_analysis:
169
+ # Update the redirect information
170
+ if self.final_url and self.final_url != self.url:
171
+ result["redirects"] = True
172
+ result["redirect_count"] = len(self.redirect_chain)
173
+ result["redirect_chain"] = self.redirect_chain
174
+ result["final_url"] = self.final_url
175
+
176
+ # Re-analyze based on the final URL extension
177
+ if self.final_url != self.url:
178
+ final_extension_analysis = self._analyze_by_extension(self.final_url)
179
+ if final_extension_analysis["is_file"]:
180
+ # If prioritizing extension and we have a file extension match
181
+ if prioritize_extension:
182
+ # Keep the MIME type from the request but use file type from extension
183
+ mime_type = request_analysis.get("mime_type")
184
+ request_analysis.update(final_extension_analysis)
185
+ if mime_type:
186
+ request_analysis["mime_type"] = mime_type
187
+ else:
188
+ # Only use extension analysis if request didn't identify a file type
189
+ if not request_analysis.get("file_type"):
190
+ request_analysis.update(final_extension_analysis)
191
+
192
+ # If prioritize_extension is True and we have both extension and MIME type analyses
193
+ if (
194
+ prioritize_extension
195
+ and result.get("extension")
196
+ and result.get("file_type")
197
+ and request_analysis.get("mime_type")
198
+ ):
199
+ # Keep the extension-based file type but add the MIME type from the request
200
+ request_analysis["file_type"] = result["file_type"]
201
+ request_analysis["is_file"] = True
202
+
203
+ result.update(request_analysis)
204
+ result["method"] = "request_analysis"
205
+
206
+ # Store the result for later access
207
+ self.analysis_result = result
208
+
209
+ return result
210
+
211
+ def _analyze_by_extension(self, url: str) -> dict[str, Any]:
212
+ """Analyze URL based on its file extension.
213
+
214
+ Args:
215
+ url (str): The URL to analyze
216
+
217
+ Returns:
218
+ dict: Analysis results based on the file extension
219
+ """
220
+ parsed_url = urlparse(url)
221
+ path = parsed_url.path.lower()
222
+
223
+ # Check if the URL has a file extension
224
+ if "." in path:
225
+ extension = path.split(".")[-1]
226
+
227
+ # Check if it's a known file extension
228
+ if extension in ExtensionToFormat:
229
+ format_type = ExtensionToFormat[extension]
230
+ return {
231
+ "is_file": True,
232
+ "file_type": format_type,
233
+ "extension": extension,
234
+ }
235
+
236
+ # If no file extension was found or it's not recognized,
237
+ # assume it's a web page (but this could be confirmed with a request)
238
+ return {
239
+ "is_file": False,
240
+ "file_type": None,
241
+ "extension": None,
242
+ }
243
+
244
+ @require_optional_import(["requests"], "rag")
245
+ def _analyze_by_request(self, follow_redirects: bool = True) -> dict[str, Any] | None:
246
+ """Analyze URL by making a HEAD request to check Content-Type.
247
+
248
+ Args:
249
+ follow_redirects (bool): Whether to follow redirects
250
+
251
+ Returns:
252
+ Optional[dict]: Analysis results based on the HTTP response or None if the request failed
253
+ """
254
+ try:
255
+ # Store redirect history
256
+ self.redirect_chain = []
257
+
258
+ # First try a HEAD request (faster but some servers don't handle it well)
259
+ response = requests.head(self.url, allow_redirects=follow_redirects, timeout=5)
260
+
261
+ # If the server returns a 405 (Method Not Allowed) for HEAD, try GET
262
+ if response.status_code == 405:
263
+ response = requests.get(self.url, allow_redirects=follow_redirects, timeout=5, stream=True)
264
+ # Close the connection without downloading the content
265
+ response.close()
266
+
267
+ # Check for non-success status codes
268
+ if response.status_code >= 400:
269
+ return {
270
+ "is_file": False,
271
+ "file_type": InputFormat.INVALID,
272
+ "mime_type": None,
273
+ "error": f"HTTP error: {response.status_code}",
274
+ "status_code": response.status_code,
275
+ }
276
+
277
+ # Store information about redirects
278
+ if hasattr(response, "history") and response.history:
279
+ self.redirect_chain = [r.url for r in response.history]
280
+ self.final_url = response.url
281
+ else:
282
+ self.final_url = self.url
283
+
284
+ # Get the Content-Type header
285
+ content_type = response.headers.get("Content-Type", "").split(";")[0].strip()
286
+
287
+ # Check if it matches any of our known MIME types
288
+ format_type = self.MimeTypeToFormat.get(content_type)
289
+
290
+ # Handle different content types
291
+ if format_type:
292
+ return {
293
+ "is_file": True,
294
+ "file_type": format_type,
295
+ "mime_type": content_type,
296
+ }
297
+ elif content_type in ["text/html", "application/xhtml+xml"]:
298
+ return {
299
+ "is_file": False,
300
+ "file_type": None,
301
+ "mime_type": content_type,
302
+ }
303
+ else:
304
+ # Content type was found but not in our mapping
305
+ return {
306
+ "is_file": True,
307
+ "file_type": "unknown",
308
+ "mime_type": content_type,
309
+ }
310
+
311
+ except requests.exceptions.TooManyRedirects:
312
+ # Handle redirect loops or too many redirects
313
+ return {
314
+ "is_file": False,
315
+ "file_type": InputFormat.INVALID,
316
+ "mime_type": None,
317
+ "error": "Too many redirects",
318
+ "redirects": True,
319
+ }
320
+ except requests.exceptions.ConnectionError:
321
+ # Handle connection errors (e.g., DNS failure, refused connection)
322
+ return {
323
+ "is_file": False,
324
+ "file_type": InputFormat.INVALID,
325
+ "mime_type": None,
326
+ "error": "Connection error - URL may be invalid or server unavailable",
327
+ }
328
+ except requests.exceptions.Timeout:
329
+ # Handle timeout
330
+ return {"is_file": False, "file_type": InputFormat.INVALID, "mime_type": None, "error": "Request timed out"}
331
+ except requests.exceptions.InvalidURL:
332
+ # Handle invalid URL
333
+ return {
334
+ "is_file": False,
335
+ "file_type": InputFormat.INVALID,
336
+ "mime_type": None,
337
+ "error": "Invalid URL format",
338
+ }
339
+ except Exception as e:
340
+ # If the request fails for any other reason
341
+ return {"is_file": False, "file_type": InputFormat.INVALID, "mime_type": None, "error": str(e)}
342
+
343
+ def get_result(self) -> dict[str, Any] | None:
344
+ """Get the last analysis result, or None if the URL hasn't been analyzed yet.
345
+
346
+ Returns:
347
+ Optional[dict]: The analysis result or None
348
+ """
349
+ return self.analysis_result
350
+
351
+ def get_redirect_info(self) -> dict[str, Any]:
352
+ """Get information about redirects that occurred during the last request.
353
+
354
+ Returns:
355
+ dict: Information about redirects
356
+ """
357
+ if not self.final_url:
358
+ return {
359
+ "redirects": False,
360
+ "redirect_count": 0,
361
+ "original_url": self.url,
362
+ "final_url": self.url,
363
+ "redirect_chain": [],
364
+ }
365
+
366
+ return {
367
+ "redirects": self.url != self.final_url,
368
+ "redirect_count": len(self.redirect_chain),
369
+ "original_url": self.url,
370
+ "final_url": self.final_url,
371
+ "redirect_chain": self.redirect_chain,
372
+ }
373
+
374
+ @require_optional_import(["requests"], "rag")
375
+ def follow_redirects(self) -> tuple[str, list[str]]:
376
+ """Follow redirects for the URL without analyzing content types.
377
+
378
+ Returns:
379
+ Tuple[str, list[str]]: The final URL and the redirect chain
380
+ """
381
+ try:
382
+ response = requests.head(self.url, allow_redirects=True, timeout=5)
383
+
384
+ # If the server returns a 405 (Method Not Allowed) for HEAD, try GET
385
+ if response.status_code == 405:
386
+ response = requests.get(self.url, allow_redirects=True, timeout=5, stream=True)
387
+ # Close the connection without downloading the content
388
+ response.close()
389
+
390
+ # Update redirect information
391
+ if hasattr(response, "history") and response.history:
392
+ self.redirect_chain = [r.url for r in response.history]
393
+ self.final_url = response.url
394
+ else:
395
+ self.final_url = self.url
396
+ self.redirect_chain = []
397
+
398
+ return self.final_url, self.redirect_chain
399
+
400
+ except Exception:
401
+ # If the request fails, return the original URL
402
+ return self.url, []
403
+
404
+ @classmethod
405
+ def get_supported_formats(cls) -> list[InputFormat]:
406
+ """Return a list of supported file formats."""
407
+ return list(cls.FormatToMimeType.keys())
408
+
409
+ @classmethod
410
+ def get_supported_mime_types(cls) -> list[str]:
411
+ """Return a list of all supported MIME types."""
412
+ return list(cls.MimeTypeToFormat.keys())
413
+
414
+ @classmethod
415
+ def get_supported_extensions(cls) -> list[str]:
416
+ """Return a list of supported file extensions."""
417
+ return list(ExtensionToFormat.keys())
@@ -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 .reasoning_agent import ReasoningAgent, ThinkNode
6
+
7
+ __all__ = ["ReasoningAgent", "ThinkNode"]