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,154 @@
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
+ # Portions derived from https://github.com/microsoft/autogen are under the MIT License.
6
+ # SPDX-License-Identifier: MIT
7
+ import base64
8
+ import json
9
+ import os
10
+ import uuid
11
+ from pathlib import Path
12
+ from types import TracebackType
13
+
14
+ from typing_extensions import Self
15
+
16
+ from ...doc_utils import export_module
17
+ from ..base import CodeBlock, CodeExecutor, CodeExtractor, IPythonCodeResult
18
+ from ..markdown_code_extractor import MarkdownCodeExtractor
19
+ from ..utils import silence_pip
20
+ from .base import JupyterConnectable, JupyterConnectionInfo
21
+ from .jupyter_client import JupyterClient
22
+
23
+
24
+ @export_module("autogen.coding.jupyter")
25
+ class JupyterCodeExecutor(CodeExecutor):
26
+ def __init__(
27
+ self,
28
+ jupyter_server: JupyterConnectable | JupyterConnectionInfo,
29
+ kernel_name: str = "python3",
30
+ timeout: int = 60,
31
+ output_dir: Path | str = Path(),
32
+ ):
33
+ """(Experimental) A code executor class that executes code statefully using
34
+ a Jupyter server supplied to this class.
35
+
36
+ Each execution is stateful and can access variables created from previous
37
+ executions in the same session.
38
+
39
+ Args:
40
+ jupyter_server (Union[JupyterConnectable, JupyterConnectionInfo]): The Jupyter server to use.
41
+ timeout (int): The timeout for code execution, by default 60.
42
+ kernel_name (str): The kernel name to use. Make sure it is installed.
43
+ By default, it is "python3".
44
+ output_dir (str): The directory to save output files, by default ".".
45
+ """
46
+ if timeout < 1:
47
+ raise ValueError("Timeout must be greater than or equal to 1.")
48
+
49
+ if isinstance(output_dir, str):
50
+ output_dir = Path(output_dir)
51
+
52
+ if not output_dir.exists():
53
+ raise ValueError(f"Output directory {output_dir} does not exist.")
54
+
55
+ if isinstance(jupyter_server, JupyterConnectable):
56
+ self._connection_info = jupyter_server.connection_info
57
+ elif isinstance(jupyter_server, JupyterConnectionInfo):
58
+ self._connection_info = jupyter_server
59
+ else:
60
+ raise ValueError("jupyter_server must be a JupyterConnectable or JupyterConnectionInfo.")
61
+
62
+ self._jupyter_client = JupyterClient(self._connection_info)
63
+ available_kernels = self._jupyter_client.list_kernel_specs()
64
+ if kernel_name not in available_kernels["kernelspecs"]:
65
+ raise ValueError(f"Kernel {kernel_name} is not installed.")
66
+
67
+ self._kernel_id = self._jupyter_client.start_kernel(kernel_name)
68
+ self._kernel_name = kernel_name
69
+ self._jupyter_kernel_client = self._jupyter_client.get_kernel_client(self._kernel_id)
70
+ self._timeout = timeout
71
+ self._output_dir = output_dir
72
+
73
+ @property
74
+ def code_extractor(self) -> CodeExtractor:
75
+ """(Experimental) Export a code extractor that can be used by an agent."""
76
+ return MarkdownCodeExtractor()
77
+
78
+ def execute_code_blocks(self, code_blocks: list[CodeBlock]) -> IPythonCodeResult:
79
+ """(Experimental) Execute a list of code blocks and return the result.
80
+
81
+ This method executes a list of code blocks as cells in the Jupyter kernel.
82
+ See: https://jupyter-client.readthedocs.io/en/stable/messaging.html
83
+ for the message protocol.
84
+
85
+ Args:
86
+ code_blocks (List[CodeBlock]): A list of code blocks to execute.
87
+
88
+ Returns:
89
+ IPythonCodeResult: The result of the code execution.
90
+ """
91
+ self._jupyter_kernel_client.wait_for_ready()
92
+ outputs = []
93
+ output_files = []
94
+ for code_block in code_blocks:
95
+ code = silence_pip(code_block.code, code_block.language)
96
+ result = self._jupyter_kernel_client.execute(code, timeout_seconds=self._timeout)
97
+ if result.is_ok:
98
+ outputs.append(result.output)
99
+ for data in result.data_items:
100
+ if data.mime_type == "image/png":
101
+ path = self._save_image(data.data)
102
+ outputs.append(f"Image data saved to {path}")
103
+ output_files.append(path)
104
+ elif data.mime_type == "text/html":
105
+ path = self._save_html(data.data)
106
+ outputs.append(f"HTML data saved to {path}")
107
+ output_files.append(path)
108
+ else:
109
+ outputs.append(json.dumps(data.data))
110
+ else:
111
+ return IPythonCodeResult(
112
+ exit_code=1,
113
+ output=f"ERROR: {result.output}",
114
+ )
115
+
116
+ return IPythonCodeResult(
117
+ exit_code=0, output="\n".join([str(output) for output in outputs]), output_files=output_files
118
+ )
119
+
120
+ def restart(self) -> None:
121
+ """(Experimental) Restart a new session."""
122
+ self._jupyter_client.restart_kernel(self._kernel_id)
123
+ self._jupyter_kernel_client = self._jupyter_client.get_kernel_client(self._kernel_id)
124
+
125
+ def _save_image(self, image_data_base64: str) -> str:
126
+ """Save image data to a file."""
127
+ image_data = base64.b64decode(image_data_base64)
128
+ # Randomly generate a filename.
129
+ filename = f"{uuid.uuid4().hex}.png"
130
+ path = os.path.join(self._output_dir, filename)
131
+ with open(path, "wb") as f:
132
+ f.write(image_data)
133
+ return os.path.abspath(path)
134
+
135
+ def _save_html(self, html_data: str) -> str:
136
+ """Save html data to a file."""
137
+ # Randomly generate a filename.
138
+ filename = f"{uuid.uuid4().hex}.html"
139
+ path = os.path.join(self._output_dir, filename)
140
+ with open(path, "w") as f:
141
+ f.write(html_data)
142
+ return os.path.abspath(path)
143
+
144
+ def stop(self) -> None:
145
+ """Stop the kernel."""
146
+ self._jupyter_client.delete_kernel(self._kernel_id)
147
+
148
+ def __enter__(self) -> Self:
149
+ return self
150
+
151
+ def __exit__(
152
+ self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None
153
+ ) -> None:
154
+ self.stop()
@@ -0,0 +1,164 @@
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
+ # Portions derived from https://github.com/microsoft/autogen are under the MIT License.
6
+ # SPDX-License-Identifier: MIT
7
+ from __future__ import annotations
8
+
9
+ import atexit
10
+ import json
11
+ import secrets
12
+ import signal
13
+ import subprocess
14
+ import sys
15
+ from types import TracebackType
16
+
17
+ from typing_extensions import Self
18
+
19
+ from ...doc_utils import export_module
20
+ from .base import JupyterConnectable, JupyterConnectionInfo
21
+ from .import_utils import require_jupyter_kernel_gateway_installed
22
+ from .jupyter_client import JupyterClient
23
+
24
+
25
+ @require_jupyter_kernel_gateway_installed()
26
+ @export_module("autogen.coding.jupyter")
27
+ class LocalJupyterServer(JupyterConnectable):
28
+ class GenerateToken:
29
+ pass
30
+
31
+ def __init__(
32
+ self,
33
+ ip: str = "127.0.0.1",
34
+ port: int | None = None,
35
+ token: str | GenerateToken = GenerateToken(),
36
+ log_file: str = "jupyter_gateway.log",
37
+ log_level: str = "INFO",
38
+ log_max_bytes: int = 1048576,
39
+ log_backup_count: int = 3,
40
+ ):
41
+ """Runs a Jupyter Kernel Gateway server locally.
42
+
43
+ Args:
44
+ ip (str, optional): IP address to bind to. Defaults to "127.0.0.1".
45
+ port (Optional[int], optional): Port to use, if None it automatically selects a port. Defaults to None.
46
+ token (Union[str, GenerateToken], optional): Token to use for Jupyter server. By default will generate a token. Using None will use no token for authentication. Defaults to GenerateToken().
47
+ log_file (str, optional): File for Jupyter Kernel Gateway logs. Defaults to "jupyter_gateway.log".
48
+ log_level (str, optional): Level for Jupyter Kernel Gateway logs. Defaults to "INFO".
49
+ log_max_bytes (int, optional): Max logfile size. Defaults to 1048576.
50
+ log_backup_count (int, optional): Number of backups for rotating log. Defaults to 3.
51
+ """
52
+
53
+ # Check Jupyter gateway server is installed
54
+ try:
55
+ subprocess.run(
56
+ [sys.executable, "-m", "jupyter", "kernelgateway", "--version"],
57
+ check=True,
58
+ capture_output=True,
59
+ text=True,
60
+ )
61
+ except subprocess.CalledProcessError:
62
+ raise ValueError(
63
+ "Jupyter gateway server is not installed. Please install it with `pip install jupyter_kernel_gateway`."
64
+ )
65
+
66
+ self.ip: str = ip
67
+
68
+ if isinstance(token, LocalJupyterServer.GenerateToken):
69
+ token = secrets.token_hex(32)
70
+
71
+ self.token: str = token
72
+ self._subprocess: subprocess.Popen[str]
73
+ logging_config = {
74
+ "handlers": {
75
+ "file": {
76
+ "class": "logging.handlers.RotatingFileHandler",
77
+ "level": log_level,
78
+ "maxBytes": log_max_bytes,
79
+ "backupCount": log_backup_count,
80
+ "filename": log_file,
81
+ }
82
+ },
83
+ "loggers": {"KernelGatewayApp": {"level": log_level, "handlers": ["file", "console"]}},
84
+ }
85
+
86
+ # Run Jupyter gateway server with detached subprocess
87
+ args = [
88
+ sys.executable,
89
+ "-m",
90
+ "jupyter",
91
+ "kernelgateway",
92
+ "--KernelGatewayApp.ip",
93
+ ip,
94
+ "--KernelGatewayApp.auth_token",
95
+ token,
96
+ "--JupyterApp.answer_yes",
97
+ "true",
98
+ "--JupyterApp.logging_config",
99
+ json.dumps(logging_config),
100
+ "--JupyterWebsocketPersonality.list_kernels",
101
+ "true",
102
+ ]
103
+ if port is not None:
104
+ args.extend(["--KernelGatewayApp.port", str(port)])
105
+ args.extend(["--KernelGatewayApp.port_retries", "0"])
106
+ self._subprocess = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
107
+
108
+ # Satisfy mypy, we know this is not None because we passed PIPE
109
+ assert self._subprocess.stderr is not None
110
+ # Read stderr until we see "is available at" or the process has exited with an error
111
+ stderr = ""
112
+ while True:
113
+ result = self._subprocess.poll()
114
+ if result is not None:
115
+ stderr += self._subprocess.stderr.read()
116
+ raise ValueError(f"Jupyter gateway server failed to start with exit code: {result}. stderr:\n{stderr}")
117
+ line = self._subprocess.stderr.readline()
118
+ stderr += line
119
+
120
+ if "ERROR:" in line:
121
+ error_info = line.split("ERROR:")[1]
122
+ raise ValueError(f"Jupyter gateway server failed to start. {error_info}")
123
+
124
+ if "is available at" in line:
125
+ # We need to extract what port it settled on
126
+ # Example output:
127
+ # Jupyter Kernel Gateway 3.0.0 is available at http://127.0.0.1:8890
128
+ if port is None:
129
+ port = int(line.split(":")[-1])
130
+ self.port: int = port
131
+
132
+ break
133
+
134
+ # Poll the subprocess to check if it is still running
135
+ result = self._subprocess.poll()
136
+ if result is not None:
137
+ raise ValueError(
138
+ f"Jupyter gateway server failed to start. Please check the logs ({log_file}) for more information."
139
+ )
140
+
141
+ atexit.register(self.stop)
142
+
143
+ def stop(self) -> None:
144
+ if self._subprocess.poll() is None:
145
+ if sys.platform == "win32":
146
+ self._subprocess.send_signal(signal.CTRL_C_EVENT)
147
+ else:
148
+ self._subprocess.send_signal(signal.SIGINT)
149
+ self._subprocess.wait()
150
+
151
+ @property
152
+ def connection_info(self) -> JupyterConnectionInfo:
153
+ return JupyterConnectionInfo(host=self.ip, use_https=False, port=self.port, token=self.token)
154
+
155
+ def get_client(self) -> JupyterClient:
156
+ return JupyterClient(self.connection_info)
157
+
158
+ def __enter__(self) -> Self:
159
+ return self
160
+
161
+ def __exit__(
162
+ self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None
163
+ ) -> None:
164
+ self.stop()
@@ -0,0 +1,341 @@
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
+ # Portions derived from https://github.com/microsoft/autogen are under the MIT License.
6
+ # SPDX-License-Identifier: MIT
7
+ import logging
8
+ import os
9
+ import re
10
+ import subprocess
11
+ import sys
12
+ import warnings
13
+ from collections.abc import Callable
14
+ from hashlib import md5
15
+ from pathlib import Path
16
+ from string import Template
17
+ from types import SimpleNamespace
18
+ from typing import Any, ClassVar
19
+
20
+ from typing_extensions import ParamSpec
21
+
22
+ from ..code_utils import PYTHON_VARIANTS, TIMEOUT_MSG, WIN32, _cmd
23
+ from ..doc_utils import export_module
24
+ from .base import CodeBlock, CodeExecutor, CodeExtractor, CommandLineCodeResult
25
+ from .func_with_reqs import (
26
+ FunctionWithRequirements,
27
+ FunctionWithRequirementsStr,
28
+ _build_python_functions_file,
29
+ to_stub,
30
+ )
31
+ from .markdown_code_extractor import MarkdownCodeExtractor
32
+ from .utils import _get_file_name_from_content, silence_pip
33
+
34
+ __all__ = ("LocalCommandLineCodeExecutor",)
35
+
36
+ A = ParamSpec("A")
37
+
38
+
39
+ @export_module("autogen.coding")
40
+ class LocalCommandLineCodeExecutor(CodeExecutor):
41
+ SUPPORTED_LANGUAGES: ClassVar[list[str]] = [
42
+ "bash",
43
+ "shell",
44
+ "sh",
45
+ "pwsh",
46
+ "powershell",
47
+ "ps1",
48
+ "python",
49
+ "javascript",
50
+ "html",
51
+ "css",
52
+ ]
53
+ DEFAULT_EXECUTION_POLICY: ClassVar[dict[str, bool]] = {
54
+ "bash": True,
55
+ "shell": True,
56
+ "sh": True,
57
+ "pwsh": True,
58
+ "powershell": True,
59
+ "ps1": True,
60
+ "python": True,
61
+ "javascript": False,
62
+ "html": False,
63
+ "css": False,
64
+ }
65
+
66
+ FUNCTION_PROMPT_TEMPLATE: ClassVar[
67
+ str
68
+ ] = """You have access to the following user defined functions. They can be accessed from the module called `$module_name` by their function names.
69
+
70
+ For example, if there was a function called `foo` you could import it by writing `from $module_name import foo`
71
+
72
+ $functions"""
73
+
74
+ def __init__(
75
+ self,
76
+ timeout: int = 60,
77
+ virtual_env_context: SimpleNamespace | None = None,
78
+ work_dir: Path | str = Path(),
79
+ functions: list[FunctionWithRequirements[Any, A] | Callable[..., Any] | FunctionWithRequirementsStr] = [],
80
+ functions_module: str = "functions",
81
+ execution_policies: dict[str, bool] | None = None,
82
+ ):
83
+ """(Experimental) A code executor class that executes or saves LLM generated code a local command line
84
+ environment.
85
+
86
+ **This will execute or save LLM generated code on the local machine.**
87
+
88
+ Each code block is saved as a file in the working directory. Depending on the execution policy,
89
+ the code may be executed in a separate process.
90
+ The code blocks are executed or save in the order they are received.
91
+ Command line code is sanitized against a list of dangerous commands to prevent self-destructive commands from being executed,
92
+ which could potentially affect the user's environment. Supported languages include Python, shell scripts (bash, shell, sh),
93
+ PowerShell (pwsh, powershell, ps1), HTML, CSS, and JavaScript.
94
+ Execution policies determine whether each language's code blocks are executed or saved only.
95
+
96
+ ## Execution with a Python virtual environment
97
+ A python virtual env can be used to execute code and install dependencies. This has the added benefit of not polluting the
98
+ base environment with unwanted modules.
99
+ ```python
100
+ from autogen.code_utils import create_virtual_env
101
+ from autogen.coding import LocalCommandLineCodeExecutor
102
+
103
+ venv_dir = ".venv"
104
+ venv_context = create_virtual_env(venv_dir)
105
+
106
+ executor = LocalCommandLineCodeExecutor(virtual_env_context=venv_context)
107
+ ```
108
+
109
+ Args:
110
+ timeout (int): The timeout for code execution, default is 60 seconds.
111
+ virtual_env_context (Optional[SimpleNamespace]): The virtual environment context to use.
112
+ work_dir (Union[Path, str]): The working directory for code execution, defaults to the current directory.
113
+ functions (List[Union[FunctionWithRequirements[Any, A], Callable[..., Any], FunctionWithRequirementsStr]]): A list of callable functions available to the executor.
114
+ functions_module (str): The module name under which functions are accessible.
115
+ execution_policies (Optional[Dict[str, bool]]): A dictionary mapping languages to execution policies (True for execution, False for saving only). Defaults to class-wide DEFAULT_EXECUTION_POLICY.
116
+ """
117
+ if timeout < 1:
118
+ raise ValueError("Timeout must be greater than or equal to 1.")
119
+
120
+ if isinstance(work_dir, str):
121
+ work_dir = Path(work_dir)
122
+
123
+ if not functions_module.isidentifier():
124
+ raise ValueError("Module name must be a valid Python identifier")
125
+
126
+ self._functions_module = functions_module
127
+
128
+ work_dir.mkdir(exist_ok=True)
129
+
130
+ self._timeout = timeout
131
+ self._work_dir: Path = work_dir
132
+ self._virtual_env_context: SimpleNamespace | None = virtual_env_context
133
+
134
+ self._functions = functions
135
+ # Setup could take some time so we intentionally wait for the first code block to do it.
136
+ if len(functions) > 0:
137
+ self._setup_functions_complete = False
138
+ else:
139
+ self._setup_functions_complete = True
140
+
141
+ self.execution_policies = self.DEFAULT_EXECUTION_POLICY.copy()
142
+ if execution_policies is not None:
143
+ self.execution_policies.update(execution_policies)
144
+
145
+ def format_functions_for_prompt(self, prompt_template: str = FUNCTION_PROMPT_TEMPLATE) -> str:
146
+ """(Experimental) Format the functions for a prompt.
147
+
148
+ The template includes two variables:
149
+ - `$module_name`: The module name.
150
+ - `$functions`: The functions formatted as stubs with two newlines between each function.
151
+
152
+ Args:
153
+ prompt_template (str): The prompt template. Default is the class default.
154
+
155
+ Returns:
156
+ str: The formatted prompt.
157
+ """
158
+ template = Template(prompt_template)
159
+ return template.substitute(
160
+ module_name=self._functions_module,
161
+ functions="\n\n".join([to_stub(func) for func in self._functions]),
162
+ )
163
+
164
+ @property
165
+ def functions_module(self) -> str:
166
+ """(Experimental) The module name for the functions."""
167
+ return self._functions_module
168
+
169
+ @property
170
+ def functions(
171
+ self,
172
+ ) -> list[FunctionWithRequirements[Any, A] | Callable[..., Any] | FunctionWithRequirementsStr]:
173
+ """(Experimental) The functions that are available to the code executor."""
174
+ return self._functions
175
+
176
+ @property
177
+ def timeout(self) -> int:
178
+ """(Experimental) The timeout for code execution."""
179
+ return self._timeout
180
+
181
+ @property
182
+ def work_dir(self) -> Path:
183
+ """(Experimental) The working directory for the code execution."""
184
+ return self._work_dir
185
+
186
+ @property
187
+ def code_extractor(self) -> CodeExtractor:
188
+ """(Experimental) Export a code extractor that can be used by an agent."""
189
+ return MarkdownCodeExtractor()
190
+
191
+ @staticmethod
192
+ def sanitize_command(lang: str, code: str) -> None:
193
+ """Sanitize the code block to prevent dangerous commands.
194
+ This approach acknowledges that while Docker or similar
195
+ containerization/sandboxing technologies provide a robust layer of security,
196
+ not all users may have Docker installed or may choose not to use it.
197
+ Therefore, having a baseline level of protection helps mitigate risks for users who,
198
+ either out of choice or necessity, run code outside of a sandboxed environment.
199
+ """
200
+ dangerous_patterns = [
201
+ (r"\brm\s+-rf\b", "Use of 'rm -rf' command is not allowed."),
202
+ (r"\bmv\b.*?\s+/dev/null", "Moving files to /dev/null is not allowed."),
203
+ (r"\bdd\b", "Use of 'dd' command is not allowed."),
204
+ (r">\s*/dev/sd[a-z][1-9]?", "Overwriting disk blocks directly is not allowed."),
205
+ (r":\(\)\{\s*:\|\:&\s*\};:", "Fork bombs are not allowed."),
206
+ ]
207
+ if lang in ["bash", "shell", "sh"]:
208
+ for pattern, message in dangerous_patterns:
209
+ if re.search(pattern, code):
210
+ raise ValueError(f"Potentially dangerous command detected: {message}")
211
+
212
+ def _setup_functions(self) -> None:
213
+ func_file_content = _build_python_functions_file(self._functions)
214
+ func_file = self._work_dir / f"{self._functions_module}.py"
215
+ func_file.write_text(func_file_content)
216
+
217
+ # Collect requirements
218
+ lists_of_packages = [x.python_packages for x in self._functions if isinstance(x, FunctionWithRequirements)]
219
+ flattened_packages = [item for sublist in lists_of_packages for item in sublist]
220
+ required_packages = list(set(flattened_packages))
221
+ if len(required_packages) > 0:
222
+ logging.info("Ensuring packages are installed in executor.")
223
+ py_executable = self._virtual_env_context.env_exe if self._virtual_env_context else sys.executable
224
+ cmd = [py_executable, "-m", "pip", "install"] + required_packages
225
+ try:
226
+ result = subprocess.run(
227
+ cmd,
228
+ cwd=self._work_dir,
229
+ capture_output=True,
230
+ text=True,
231
+ timeout=float(self._timeout),
232
+ encoding="utf-8",
233
+ )
234
+ except subprocess.TimeoutExpired as e:
235
+ raise ValueError("Pip install timed out") from e
236
+ if result.returncode != 0:
237
+ raise ValueError(f"Pip install failed. {result.stdout}, {result.stderr}")
238
+ # Attempt to load the function file to check for syntax errors, imports etc.
239
+ exec_result = self._execute_code_dont_check_setup([CodeBlock(code=func_file_content, language="python")])
240
+ if exec_result.exit_code != 0:
241
+ raise ValueError(f"Functions failed to load: {exec_result.output}")
242
+ self._setup_functions_complete = True
243
+
244
+ def execute_code_blocks(self, code_blocks: list[CodeBlock]) -> CommandLineCodeResult:
245
+ """(Experimental) Execute the code blocks and return the result.
246
+
247
+ Args:
248
+ code_blocks (List[CodeBlock]): The code blocks to execute.
249
+
250
+ Returns:
251
+ CommandLineCodeResult: The result of the code execution.
252
+ """
253
+ if not self._setup_functions_complete:
254
+ self._setup_functions()
255
+ return self._execute_code_dont_check_setup(code_blocks)
256
+
257
+ def _execute_code_dont_check_setup(self, code_blocks: list[CodeBlock]) -> CommandLineCodeResult:
258
+ logs_all = ""
259
+ file_names = []
260
+ for code_block in code_blocks:
261
+ lang, code = code_block.language, code_block.code
262
+ lang = lang.lower()
263
+
264
+ LocalCommandLineCodeExecutor.sanitize_command(lang, code)
265
+ code = silence_pip(code, lang)
266
+
267
+ if lang in PYTHON_VARIANTS:
268
+ lang = "python"
269
+
270
+ if WIN32 and lang in ["sh", "shell"]:
271
+ lang = "ps1"
272
+
273
+ if lang not in self.SUPPORTED_LANGUAGES:
274
+ # In case the language is not supported, we return an error message.
275
+ exitcode = 1
276
+ logs_all += "\n" + f"unknown language {lang}"
277
+ break
278
+
279
+ execute_code = self.execution_policies.get(lang, False)
280
+ try:
281
+ # Check if there is a filename comment
282
+ filename = _get_file_name_from_content(code, self._work_dir)
283
+ except ValueError:
284
+ return CommandLineCodeResult(exit_code=1, output="Filename is not in the workspace")
285
+
286
+ if filename is None:
287
+ # create a file with an automatically generated name
288
+ code_hash = md5(code.encode()).hexdigest()
289
+ filename = f"tmp_code_{code_hash}.{'py' if lang.startswith('python') else lang}"
290
+ written_file = (self._work_dir / filename).resolve()
291
+ with written_file.open("w", encoding="utf-8") as f:
292
+ f.write(code)
293
+ file_names.append(written_file)
294
+
295
+ if not execute_code:
296
+ # Just return a message that the file is saved.
297
+ logs_all += f"Code saved to {written_file!s}\n"
298
+ exitcode = 0
299
+ continue
300
+
301
+ program = _cmd(lang)
302
+ cmd = [program, str(written_file.absolute())]
303
+ env = os.environ.copy()
304
+
305
+ if self._virtual_env_context:
306
+ virtual_env_abs_path = os.path.abspath(self._virtual_env_context.bin_path)
307
+ path_with_virtualenv = rf"{virtual_env_abs_path}{os.pathsep}{env['PATH']}"
308
+ env["PATH"] = path_with_virtualenv
309
+ if WIN32:
310
+ activation_script = os.path.join(virtual_env_abs_path, "activate.bat")
311
+ cmd = [activation_script, "&&", *cmd]
312
+
313
+ try:
314
+ result = subprocess.run(
315
+ cmd,
316
+ cwd=self._work_dir,
317
+ capture_output=True,
318
+ text=True,
319
+ timeout=float(self._timeout),
320
+ env=env,
321
+ encoding="utf-8",
322
+ )
323
+ except subprocess.TimeoutExpired:
324
+ logs_all += "\n" + TIMEOUT_MSG
325
+ # Same exit code as the timeout command on linux.
326
+ exitcode = 124
327
+ break
328
+
329
+ logs_all += result.stderr
330
+ logs_all += result.stdout
331
+ exitcode = result.returncode
332
+
333
+ if exitcode != 0:
334
+ break
335
+
336
+ code_file = str(file_names[0]) if len(file_names) > 0 else None
337
+ return CommandLineCodeResult(exit_code=exitcode, output=logs_all, code_file=code_file)
338
+
339
+ def restart(self) -> None:
340
+ """(Experimental) Restart the code executor."""
341
+ warnings.warn("Restarting local command line code executor is not supported. No action is taken.")