ag2 0.9.1__py3-none-any.whl → 0.9.1.post0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ag2 might be problematic. Click here for more details.
- {ag2-0.9.1.dist-info → ag2-0.9.1.post0.dist-info}/METADATA +264 -73
- ag2-0.9.1.post0.dist-info/RECORD +392 -0
- {ag2-0.9.1.dist-info → ag2-0.9.1.post0.dist-info}/WHEEL +1 -2
- autogen/__init__.py +89 -0
- autogen/_website/__init__.py +3 -0
- autogen/_website/generate_api_references.py +427 -0
- autogen/_website/generate_mkdocs.py +1174 -0
- autogen/_website/notebook_processor.py +476 -0
- autogen/_website/process_notebooks.py +656 -0
- autogen/_website/utils.py +412 -0
- autogen/agentchat/__init__.py +44 -0
- autogen/agentchat/agent.py +182 -0
- autogen/agentchat/assistant_agent.py +85 -0
- autogen/agentchat/chat.py +309 -0
- autogen/agentchat/contrib/__init__.py +5 -0
- autogen/agentchat/contrib/agent_eval/README.md +7 -0
- autogen/agentchat/contrib/agent_eval/agent_eval.py +108 -0
- autogen/agentchat/contrib/agent_eval/criterion.py +43 -0
- autogen/agentchat/contrib/agent_eval/critic_agent.py +44 -0
- autogen/agentchat/contrib/agent_eval/quantifier_agent.py +39 -0
- autogen/agentchat/contrib/agent_eval/subcritic_agent.py +45 -0
- autogen/agentchat/contrib/agent_eval/task.py +42 -0
- autogen/agentchat/contrib/agent_optimizer.py +429 -0
- autogen/agentchat/contrib/capabilities/__init__.py +5 -0
- autogen/agentchat/contrib/capabilities/agent_capability.py +20 -0
- autogen/agentchat/contrib/capabilities/generate_images.py +301 -0
- autogen/agentchat/contrib/capabilities/teachability.py +393 -0
- autogen/agentchat/contrib/capabilities/text_compressors.py +66 -0
- autogen/agentchat/contrib/capabilities/tools_capability.py +22 -0
- autogen/agentchat/contrib/capabilities/transform_messages.py +93 -0
- autogen/agentchat/contrib/capabilities/transforms.py +566 -0
- autogen/agentchat/contrib/capabilities/transforms_util.py +122 -0
- autogen/agentchat/contrib/capabilities/vision_capability.py +214 -0
- autogen/agentchat/contrib/captainagent/__init__.py +9 -0
- autogen/agentchat/contrib/captainagent/agent_builder.py +790 -0
- autogen/agentchat/contrib/captainagent/captainagent.py +512 -0
- autogen/agentchat/contrib/captainagent/tool_retriever.py +335 -0
- autogen/agentchat/contrib/captainagent/tools/README.md +44 -0
- autogen/agentchat/contrib/captainagent/tools/__init__.py +5 -0
- autogen/agentchat/contrib/captainagent/tools/data_analysis/calculate_correlation.py +40 -0
- autogen/agentchat/contrib/captainagent/tools/data_analysis/calculate_skewness_and_kurtosis.py +28 -0
- autogen/agentchat/contrib/captainagent/tools/data_analysis/detect_outlier_iqr.py +28 -0
- autogen/agentchat/contrib/captainagent/tools/data_analysis/detect_outlier_zscore.py +28 -0
- autogen/agentchat/contrib/captainagent/tools/data_analysis/explore_csv.py +21 -0
- autogen/agentchat/contrib/captainagent/tools/data_analysis/shapiro_wilk_test.py +30 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/arxiv_download.py +27 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/arxiv_search.py +53 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/extract_pdf_image.py +53 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/extract_pdf_text.py +38 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/get_wikipedia_text.py +21 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/get_youtube_caption.py +34 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/image_qa.py +60 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/optical_character_recognition.py +61 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/perform_web_search.py +47 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/scrape_wikipedia_tables.py +33 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/transcribe_audio_file.py +21 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/youtube_download.py +35 -0
- autogen/agentchat/contrib/captainagent/tools/math/calculate_circle_area_from_diameter.py +21 -0
- autogen/agentchat/contrib/captainagent/tools/math/calculate_day_of_the_week.py +18 -0
- autogen/agentchat/contrib/captainagent/tools/math/calculate_fraction_sum.py +28 -0
- autogen/agentchat/contrib/captainagent/tools/math/calculate_matrix_power.py +31 -0
- autogen/agentchat/contrib/captainagent/tools/math/calculate_reflected_point.py +16 -0
- autogen/agentchat/contrib/captainagent/tools/math/complex_numbers_product.py +25 -0
- autogen/agentchat/contrib/captainagent/tools/math/compute_currency_conversion.py +23 -0
- autogen/agentchat/contrib/captainagent/tools/math/count_distinct_permutations.py +27 -0
- autogen/agentchat/contrib/captainagent/tools/math/evaluate_expression.py +28 -0
- autogen/agentchat/contrib/captainagent/tools/math/find_continuity_point.py +34 -0
- autogen/agentchat/contrib/captainagent/tools/math/fraction_to_mixed_numbers.py +39 -0
- autogen/agentchat/contrib/captainagent/tools/math/modular_inverse_sum.py +23 -0
- autogen/agentchat/contrib/captainagent/tools/math/simplify_mixed_numbers.py +36 -0
- autogen/agentchat/contrib/captainagent/tools/math/sum_of_digit_factorials.py +15 -0
- autogen/agentchat/contrib/captainagent/tools/math/sum_of_primes_below.py +15 -0
- autogen/agentchat/contrib/captainagent/tools/requirements.txt +10 -0
- autogen/agentchat/contrib/captainagent/tools/tool_description.tsv +34 -0
- autogen/agentchat/contrib/gpt_assistant_agent.py +526 -0
- autogen/agentchat/contrib/graph_rag/__init__.py +9 -0
- autogen/agentchat/contrib/graph_rag/document.py +29 -0
- autogen/agentchat/contrib/graph_rag/falkor_graph_query_engine.py +170 -0
- autogen/agentchat/contrib/graph_rag/falkor_graph_rag_capability.py +103 -0
- autogen/agentchat/contrib/graph_rag/graph_query_engine.py +53 -0
- autogen/agentchat/contrib/graph_rag/graph_rag_capability.py +63 -0
- autogen/agentchat/contrib/graph_rag/neo4j_graph_query_engine.py +268 -0
- autogen/agentchat/contrib/graph_rag/neo4j_graph_rag_capability.py +83 -0
- autogen/agentchat/contrib/graph_rag/neo4j_native_graph_query_engine.py +210 -0
- autogen/agentchat/contrib/graph_rag/neo4j_native_graph_rag_capability.py +93 -0
- autogen/agentchat/contrib/img_utils.py +397 -0
- autogen/agentchat/contrib/llamaindex_conversable_agent.py +117 -0
- autogen/agentchat/contrib/llava_agent.py +187 -0
- autogen/agentchat/contrib/math_user_proxy_agent.py +464 -0
- autogen/agentchat/contrib/multimodal_conversable_agent.py +125 -0
- autogen/agentchat/contrib/qdrant_retrieve_user_proxy_agent.py +324 -0
- autogen/agentchat/contrib/rag/__init__.py +10 -0
- autogen/agentchat/contrib/rag/chromadb_query_engine.py +272 -0
- autogen/agentchat/contrib/rag/llamaindex_query_engine.py +198 -0
- autogen/agentchat/contrib/rag/mongodb_query_engine.py +329 -0
- autogen/agentchat/contrib/rag/query_engine.py +74 -0
- autogen/agentchat/contrib/retrieve_assistant_agent.py +56 -0
- autogen/agentchat/contrib/retrieve_user_proxy_agent.py +703 -0
- autogen/agentchat/contrib/society_of_mind_agent.py +199 -0
- autogen/agentchat/contrib/swarm_agent.py +1425 -0
- autogen/agentchat/contrib/text_analyzer_agent.py +79 -0
- autogen/agentchat/contrib/vectordb/__init__.py +5 -0
- autogen/agentchat/contrib/vectordb/base.py +232 -0
- autogen/agentchat/contrib/vectordb/chromadb.py +315 -0
- autogen/agentchat/contrib/vectordb/couchbase.py +407 -0
- autogen/agentchat/contrib/vectordb/mongodb.py +550 -0
- autogen/agentchat/contrib/vectordb/pgvectordb.py +928 -0
- autogen/agentchat/contrib/vectordb/qdrant.py +320 -0
- autogen/agentchat/contrib/vectordb/utils.py +126 -0
- autogen/agentchat/contrib/web_surfer.py +303 -0
- autogen/agentchat/conversable_agent.py +4020 -0
- autogen/agentchat/group/__init__.py +64 -0
- autogen/agentchat/group/available_condition.py +91 -0
- autogen/agentchat/group/context_condition.py +77 -0
- autogen/agentchat/group/context_expression.py +238 -0
- autogen/agentchat/group/context_str.py +41 -0
- autogen/agentchat/group/context_variables.py +192 -0
- autogen/agentchat/group/group_tool_executor.py +202 -0
- autogen/agentchat/group/group_utils.py +591 -0
- autogen/agentchat/group/handoffs.py +244 -0
- autogen/agentchat/group/llm_condition.py +93 -0
- autogen/agentchat/group/multi_agent_chat.py +237 -0
- autogen/agentchat/group/on_condition.py +58 -0
- autogen/agentchat/group/on_context_condition.py +54 -0
- autogen/agentchat/group/patterns/__init__.py +18 -0
- autogen/agentchat/group/patterns/auto.py +159 -0
- autogen/agentchat/group/patterns/manual.py +176 -0
- autogen/agentchat/group/patterns/pattern.py +288 -0
- autogen/agentchat/group/patterns/random.py +106 -0
- autogen/agentchat/group/patterns/round_robin.py +117 -0
- autogen/agentchat/group/reply_result.py +26 -0
- autogen/agentchat/group/speaker_selection_result.py +41 -0
- autogen/agentchat/group/targets/__init__.py +4 -0
- autogen/agentchat/group/targets/group_chat_target.py +132 -0
- autogen/agentchat/group/targets/group_manager_target.py +151 -0
- autogen/agentchat/group/targets/transition_target.py +413 -0
- autogen/agentchat/group/targets/transition_utils.py +6 -0
- autogen/agentchat/groupchat.py +1694 -0
- autogen/agentchat/realtime/__init__.py +3 -0
- autogen/agentchat/realtime/experimental/__init__.py +20 -0
- autogen/agentchat/realtime/experimental/audio_adapters/__init__.py +8 -0
- autogen/agentchat/realtime/experimental/audio_adapters/twilio_audio_adapter.py +148 -0
- autogen/agentchat/realtime/experimental/audio_adapters/websocket_audio_adapter.py +139 -0
- autogen/agentchat/realtime/experimental/audio_observer.py +42 -0
- autogen/agentchat/realtime/experimental/clients/__init__.py +15 -0
- autogen/agentchat/realtime/experimental/clients/gemini/__init__.py +7 -0
- autogen/agentchat/realtime/experimental/clients/gemini/client.py +274 -0
- autogen/agentchat/realtime/experimental/clients/oai/__init__.py +8 -0
- autogen/agentchat/realtime/experimental/clients/oai/base_client.py +220 -0
- autogen/agentchat/realtime/experimental/clients/oai/rtc_client.py +243 -0
- autogen/agentchat/realtime/experimental/clients/oai/utils.py +48 -0
- autogen/agentchat/realtime/experimental/clients/realtime_client.py +190 -0
- autogen/agentchat/realtime/experimental/function_observer.py +85 -0
- autogen/agentchat/realtime/experimental/realtime_agent.py +158 -0
- autogen/agentchat/realtime/experimental/realtime_events.py +42 -0
- autogen/agentchat/realtime/experimental/realtime_observer.py +100 -0
- autogen/agentchat/realtime/experimental/realtime_swarm.py +475 -0
- autogen/agentchat/realtime/experimental/websockets.py +21 -0
- autogen/agentchat/realtime_agent/__init__.py +21 -0
- autogen/agentchat/user_proxy_agent.py +111 -0
- autogen/agentchat/utils.py +206 -0
- autogen/agents/__init__.py +3 -0
- autogen/agents/contrib/__init__.py +10 -0
- autogen/agents/contrib/time/__init__.py +8 -0
- autogen/agents/contrib/time/time_reply_agent.py +73 -0
- autogen/agents/contrib/time/time_tool_agent.py +51 -0
- autogen/agents/experimental/__init__.py +27 -0
- autogen/agents/experimental/deep_research/__init__.py +7 -0
- autogen/agents/experimental/deep_research/deep_research.py +52 -0
- autogen/agents/experimental/discord/__init__.py +7 -0
- autogen/agents/experimental/discord/discord.py +66 -0
- autogen/agents/experimental/document_agent/__init__.py +19 -0
- autogen/agents/experimental/document_agent/chroma_query_engine.py +316 -0
- autogen/agents/experimental/document_agent/docling_doc_ingest_agent.py +118 -0
- autogen/agents/experimental/document_agent/document_agent.py +461 -0
- autogen/agents/experimental/document_agent/document_conditions.py +50 -0
- autogen/agents/experimental/document_agent/document_utils.py +380 -0
- autogen/agents/experimental/document_agent/inmemory_query_engine.py +220 -0
- autogen/agents/experimental/document_agent/parser_utils.py +130 -0
- autogen/agents/experimental/document_agent/url_utils.py +426 -0
- autogen/agents/experimental/reasoning/__init__.py +7 -0
- autogen/agents/experimental/reasoning/reasoning_agent.py +1178 -0
- autogen/agents/experimental/slack/__init__.py +7 -0
- autogen/agents/experimental/slack/slack.py +73 -0
- autogen/agents/experimental/telegram/__init__.py +7 -0
- autogen/agents/experimental/telegram/telegram.py +77 -0
- autogen/agents/experimental/websurfer/__init__.py +7 -0
- autogen/agents/experimental/websurfer/websurfer.py +62 -0
- autogen/agents/experimental/wikipedia/__init__.py +7 -0
- autogen/agents/experimental/wikipedia/wikipedia.py +90 -0
- autogen/browser_utils.py +309 -0
- autogen/cache/__init__.py +10 -0
- autogen/cache/abstract_cache_base.py +75 -0
- autogen/cache/cache.py +203 -0
- autogen/cache/cache_factory.py +88 -0
- autogen/cache/cosmos_db_cache.py +144 -0
- autogen/cache/disk_cache.py +102 -0
- autogen/cache/in_memory_cache.py +58 -0
- autogen/cache/redis_cache.py +123 -0
- autogen/code_utils.py +596 -0
- autogen/coding/__init__.py +22 -0
- autogen/coding/base.py +119 -0
- autogen/coding/docker_commandline_code_executor.py +268 -0
- autogen/coding/factory.py +47 -0
- autogen/coding/func_with_reqs.py +202 -0
- autogen/coding/jupyter/__init__.py +23 -0
- autogen/coding/jupyter/base.py +36 -0
- autogen/coding/jupyter/docker_jupyter_server.py +167 -0
- autogen/coding/jupyter/embedded_ipython_code_executor.py +182 -0
- autogen/coding/jupyter/import_utils.py +82 -0
- autogen/coding/jupyter/jupyter_client.py +231 -0
- autogen/coding/jupyter/jupyter_code_executor.py +160 -0
- autogen/coding/jupyter/local_jupyter_server.py +172 -0
- autogen/coding/local_commandline_code_executor.py +405 -0
- autogen/coding/markdown_code_extractor.py +45 -0
- autogen/coding/utils.py +56 -0
- autogen/doc_utils.py +34 -0
- autogen/events/__init__.py +7 -0
- autogen/events/agent_events.py +1010 -0
- autogen/events/base_event.py +99 -0
- autogen/events/client_events.py +167 -0
- autogen/events/helpers.py +36 -0
- autogen/events/print_event.py +46 -0
- autogen/exception_utils.py +73 -0
- autogen/extensions/__init__.py +5 -0
- autogen/fast_depends/__init__.py +16 -0
- autogen/fast_depends/_compat.py +80 -0
- autogen/fast_depends/core/__init__.py +14 -0
- autogen/fast_depends/core/build.py +225 -0
- autogen/fast_depends/core/model.py +576 -0
- autogen/fast_depends/dependencies/__init__.py +15 -0
- autogen/fast_depends/dependencies/model.py +29 -0
- autogen/fast_depends/dependencies/provider.py +39 -0
- autogen/fast_depends/library/__init__.py +10 -0
- autogen/fast_depends/library/model.py +46 -0
- autogen/fast_depends/py.typed +6 -0
- autogen/fast_depends/schema.py +66 -0
- autogen/fast_depends/use.py +280 -0
- autogen/fast_depends/utils.py +187 -0
- autogen/formatting_utils.py +83 -0
- autogen/function_utils.py +13 -0
- autogen/graph_utils.py +178 -0
- autogen/import_utils.py +526 -0
- autogen/interop/__init__.py +22 -0
- autogen/interop/crewai/__init__.py +7 -0
- autogen/interop/crewai/crewai.py +88 -0
- autogen/interop/interoperability.py +71 -0
- autogen/interop/interoperable.py +46 -0
- autogen/interop/langchain/__init__.py +8 -0
- autogen/interop/langchain/langchain_chat_model_factory.py +155 -0
- autogen/interop/langchain/langchain_tool.py +82 -0
- autogen/interop/litellm/__init__.py +7 -0
- autogen/interop/litellm/litellm_config_factory.py +113 -0
- autogen/interop/pydantic_ai/__init__.py +7 -0
- autogen/interop/pydantic_ai/pydantic_ai.py +168 -0
- autogen/interop/registry.py +69 -0
- autogen/io/__init__.py +15 -0
- autogen/io/base.py +151 -0
- autogen/io/console.py +56 -0
- autogen/io/processors/__init__.py +12 -0
- autogen/io/processors/base.py +21 -0
- autogen/io/processors/console_event_processor.py +56 -0
- autogen/io/run_response.py +293 -0
- autogen/io/thread_io_stream.py +63 -0
- autogen/io/websockets.py +213 -0
- autogen/json_utils.py +43 -0
- autogen/llm_config.py +379 -0
- autogen/logger/__init__.py +11 -0
- autogen/logger/base_logger.py +128 -0
- autogen/logger/file_logger.py +261 -0
- autogen/logger/logger_factory.py +42 -0
- autogen/logger/logger_utils.py +57 -0
- autogen/logger/sqlite_logger.py +523 -0
- autogen/math_utils.py +339 -0
- autogen/mcp/__init__.py +7 -0
- autogen/mcp/mcp_client.py +208 -0
- autogen/messages/__init__.py +7 -0
- autogen/messages/agent_messages.py +948 -0
- autogen/messages/base_message.py +107 -0
- autogen/messages/client_messages.py +171 -0
- autogen/messages/print_message.py +49 -0
- autogen/oai/__init__.py +53 -0
- autogen/oai/anthropic.py +714 -0
- autogen/oai/bedrock.py +628 -0
- autogen/oai/cerebras.py +299 -0
- autogen/oai/client.py +1435 -0
- autogen/oai/client_utils.py +169 -0
- autogen/oai/cohere.py +479 -0
- autogen/oai/gemini.py +990 -0
- autogen/oai/gemini_types.py +129 -0
- autogen/oai/groq.py +305 -0
- autogen/oai/mistral.py +303 -0
- autogen/oai/oai_models/__init__.py +11 -0
- autogen/oai/oai_models/_models.py +16 -0
- autogen/oai/oai_models/chat_completion.py +87 -0
- autogen/oai/oai_models/chat_completion_audio.py +32 -0
- autogen/oai/oai_models/chat_completion_message.py +86 -0
- autogen/oai/oai_models/chat_completion_message_tool_call.py +37 -0
- autogen/oai/oai_models/chat_completion_token_logprob.py +63 -0
- autogen/oai/oai_models/completion_usage.py +60 -0
- autogen/oai/ollama.py +643 -0
- autogen/oai/openai_utils.py +881 -0
- autogen/oai/together.py +370 -0
- autogen/retrieve_utils.py +491 -0
- autogen/runtime_logging.py +160 -0
- autogen/token_count_utils.py +267 -0
- autogen/tools/__init__.py +20 -0
- autogen/tools/contrib/__init__.py +9 -0
- autogen/tools/contrib/time/__init__.py +7 -0
- autogen/tools/contrib/time/time.py +41 -0
- autogen/tools/dependency_injection.py +254 -0
- autogen/tools/experimental/__init__.py +43 -0
- autogen/tools/experimental/browser_use/__init__.py +7 -0
- autogen/tools/experimental/browser_use/browser_use.py +161 -0
- autogen/tools/experimental/crawl4ai/__init__.py +7 -0
- autogen/tools/experimental/crawl4ai/crawl4ai.py +153 -0
- autogen/tools/experimental/deep_research/__init__.py +7 -0
- autogen/tools/experimental/deep_research/deep_research.py +328 -0
- autogen/tools/experimental/duckduckgo/__init__.py +7 -0
- autogen/tools/experimental/duckduckgo/duckduckgo_search.py +109 -0
- autogen/tools/experimental/google/__init__.py +14 -0
- autogen/tools/experimental/google/authentication/__init__.py +11 -0
- autogen/tools/experimental/google/authentication/credentials_hosted_provider.py +43 -0
- autogen/tools/experimental/google/authentication/credentials_local_provider.py +91 -0
- autogen/tools/experimental/google/authentication/credentials_provider.py +35 -0
- autogen/tools/experimental/google/drive/__init__.py +9 -0
- autogen/tools/experimental/google/drive/drive_functions.py +124 -0
- autogen/tools/experimental/google/drive/toolkit.py +88 -0
- autogen/tools/experimental/google/model.py +17 -0
- autogen/tools/experimental/google/toolkit_protocol.py +19 -0
- autogen/tools/experimental/google_search/__init__.py +8 -0
- autogen/tools/experimental/google_search/google_search.py +93 -0
- autogen/tools/experimental/google_search/youtube_search.py +181 -0
- autogen/tools/experimental/messageplatform/__init__.py +17 -0
- autogen/tools/experimental/messageplatform/discord/__init__.py +7 -0
- autogen/tools/experimental/messageplatform/discord/discord.py +288 -0
- autogen/tools/experimental/messageplatform/slack/__init__.py +7 -0
- autogen/tools/experimental/messageplatform/slack/slack.py +391 -0
- autogen/tools/experimental/messageplatform/telegram/__init__.py +7 -0
- autogen/tools/experimental/messageplatform/telegram/telegram.py +275 -0
- autogen/tools/experimental/perplexity/__init__.py +7 -0
- autogen/tools/experimental/perplexity/perplexity_search.py +260 -0
- autogen/tools/experimental/tavily/__init__.py +7 -0
- autogen/tools/experimental/tavily/tavily_search.py +183 -0
- autogen/tools/experimental/web_search_preview/__init__.py +7 -0
- autogen/tools/experimental/web_search_preview/web_search_preview.py +114 -0
- autogen/tools/experimental/wikipedia/__init__.py +7 -0
- autogen/tools/experimental/wikipedia/wikipedia.py +287 -0
- autogen/tools/function_utils.py +411 -0
- autogen/tools/tool.py +187 -0
- autogen/tools/toolkit.py +86 -0
- autogen/types.py +29 -0
- autogen/version.py +7 -0
- ag2-0.9.1.dist-info/RECORD +0 -6
- ag2-0.9.1.dist-info/top_level.txt +0 -1
- {ag2-0.9.1.dist-info → ag2-0.9.1.post0.dist-info/licenses}/LICENSE +0 -0
- {ag2-0.9.1.dist-info → ag2-0.9.1.post0.dist-info/licenses}/NOTICE.md +0 -0
autogen/coding/base.py
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
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
|
+
from collections.abc import Mapping
|
|
10
|
+
from typing import Any, Literal, Optional, Protocol, TypedDict, Union, runtime_checkable
|
|
11
|
+
|
|
12
|
+
from pydantic import BaseModel, Field
|
|
13
|
+
|
|
14
|
+
from ..doc_utils import export_module
|
|
15
|
+
from ..types import UserMessageImageContentPart, UserMessageTextContentPart
|
|
16
|
+
|
|
17
|
+
__all__ = ("CodeBlock", "CodeExecutionConfig", "CodeExecutor", "CodeExtractor", "CodeResult")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@export_module("autogen.coding")
|
|
21
|
+
class CodeBlock(BaseModel):
|
|
22
|
+
"""(Experimental) A class that represents a code block."""
|
|
23
|
+
|
|
24
|
+
code: str = Field(description="The code to execute.")
|
|
25
|
+
|
|
26
|
+
language: str = Field(description="The language of the code.")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@export_module("autogen.coding")
|
|
30
|
+
class CodeResult(BaseModel):
|
|
31
|
+
"""(Experimental) A class that represents the result of a code execution."""
|
|
32
|
+
|
|
33
|
+
exit_code: int = Field(description="The exit code of the code execution.")
|
|
34
|
+
|
|
35
|
+
output: str = Field(description="The output of the code execution.")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@export_module("autogen.coding")
|
|
39
|
+
class CodeExtractor(Protocol):
|
|
40
|
+
"""(Experimental) A code extractor class that extracts code blocks from a message."""
|
|
41
|
+
|
|
42
|
+
def extract_code_blocks(
|
|
43
|
+
self, message: Optional[Union[str, list[Union[UserMessageTextContentPart, UserMessageImageContentPart]]]]
|
|
44
|
+
) -> list[CodeBlock]:
|
|
45
|
+
"""(Experimental) Extract code blocks from a message.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
message (str): The message to extract code blocks from.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
List[CodeBlock]: The extracted code blocks.
|
|
52
|
+
"""
|
|
53
|
+
... # pragma: no cover
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@runtime_checkable
|
|
57
|
+
@export_module("autogen.coding")
|
|
58
|
+
class CodeExecutor(Protocol):
|
|
59
|
+
"""(Experimental) A code executor class that executes code blocks and returns the result."""
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
def code_extractor(self) -> CodeExtractor:
|
|
63
|
+
"""(Experimental) The code extractor used by this code executor."""
|
|
64
|
+
... # pragma: no cover
|
|
65
|
+
|
|
66
|
+
def execute_code_blocks(self, code_blocks: list[CodeBlock]) -> CodeResult:
|
|
67
|
+
"""(Experimental) Execute code blocks and return the result.
|
|
68
|
+
|
|
69
|
+
This method should be implemented by the code executor.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
code_blocks (List[CodeBlock]): The code blocks to execute.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
CodeResult: The result of the code execution.
|
|
76
|
+
"""
|
|
77
|
+
... # pragma: no cover
|
|
78
|
+
|
|
79
|
+
def restart(self) -> None:
|
|
80
|
+
"""(Experimental) Restart the code executor.
|
|
81
|
+
|
|
82
|
+
This method should be implemented by the code executor.
|
|
83
|
+
|
|
84
|
+
This method is called when the agent is reset.
|
|
85
|
+
"""
|
|
86
|
+
... # pragma: no cover
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class IPythonCodeResult(CodeResult):
|
|
90
|
+
"""(Experimental) A code result class for IPython code executor."""
|
|
91
|
+
|
|
92
|
+
output_files: list[str] = Field(
|
|
93
|
+
default_factory=list,
|
|
94
|
+
description="The list of files that the executed code blocks generated.",
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
CodeExecutionConfig = TypedDict(
|
|
99
|
+
"CodeExecutionConfig",
|
|
100
|
+
{
|
|
101
|
+
"executor": Union[Literal["ipython-embedded", "commandline-local"], CodeExecutor],
|
|
102
|
+
"last_n_messages": Union[int, Literal["auto"]],
|
|
103
|
+
"timeout": int,
|
|
104
|
+
"use_docker": Union[bool, str, list[str]],
|
|
105
|
+
"work_dir": str,
|
|
106
|
+
"ipython-embedded": Mapping[str, Any],
|
|
107
|
+
"commandline-local": Mapping[str, Any],
|
|
108
|
+
},
|
|
109
|
+
total=False,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class CommandLineCodeResult(CodeResult):
|
|
114
|
+
"""(Experimental) A code result class for command line code executor."""
|
|
115
|
+
|
|
116
|
+
code_file: Optional[str] = Field(
|
|
117
|
+
default=None,
|
|
118
|
+
description="The file that the executed code block was saved to.",
|
|
119
|
+
)
|
|
@@ -0,0 +1,268 @@
|
|
|
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 logging
|
|
11
|
+
import sys
|
|
12
|
+
import uuid
|
|
13
|
+
from hashlib import md5
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from time import sleep
|
|
16
|
+
from types import TracebackType
|
|
17
|
+
from typing import Any, ClassVar, Optional, Union
|
|
18
|
+
|
|
19
|
+
import docker
|
|
20
|
+
from docker.errors import ImageNotFound
|
|
21
|
+
|
|
22
|
+
from ..code_utils import TIMEOUT_MSG, _cmd
|
|
23
|
+
from ..doc_utils import export_module
|
|
24
|
+
from .base import CodeBlock, CodeExecutor, CodeExtractor, CommandLineCodeResult
|
|
25
|
+
from .markdown_code_extractor import MarkdownCodeExtractor
|
|
26
|
+
from .utils import _get_file_name_from_content, silence_pip
|
|
27
|
+
|
|
28
|
+
if sys.version_info >= (3, 11):
|
|
29
|
+
from typing import Self
|
|
30
|
+
else:
|
|
31
|
+
from typing_extensions import Self
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _wait_for_ready(container: Any, timeout: int = 60, stop_time: float = 0.1) -> None:
|
|
35
|
+
elapsed_time = 0.0
|
|
36
|
+
while container.status != "running" and elapsed_time < timeout:
|
|
37
|
+
sleep(stop_time)
|
|
38
|
+
elapsed_time += stop_time
|
|
39
|
+
container.reload()
|
|
40
|
+
continue
|
|
41
|
+
if container.status != "running":
|
|
42
|
+
raise ValueError("Container failed to start")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
__all__ = ("DockerCommandLineCodeExecutor",)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@export_module("autogen.coding")
|
|
49
|
+
class DockerCommandLineCodeExecutor(CodeExecutor):
|
|
50
|
+
DEFAULT_EXECUTION_POLICY: ClassVar[dict[str, bool]] = {
|
|
51
|
+
"bash": True,
|
|
52
|
+
"shell": True,
|
|
53
|
+
"sh": True,
|
|
54
|
+
"pwsh": True,
|
|
55
|
+
"powershell": True,
|
|
56
|
+
"ps1": True,
|
|
57
|
+
"python": True,
|
|
58
|
+
"javascript": False,
|
|
59
|
+
"html": False,
|
|
60
|
+
"css": False,
|
|
61
|
+
}
|
|
62
|
+
LANGUAGE_ALIASES: ClassVar[dict[str, str]] = {"py": "python", "js": "javascript"}
|
|
63
|
+
|
|
64
|
+
def __init__(
|
|
65
|
+
self,
|
|
66
|
+
image: str = "python:3-slim",
|
|
67
|
+
container_name: Optional[str] = None,
|
|
68
|
+
timeout: int = 60,
|
|
69
|
+
work_dir: Optional[Union[Path, str]] = None,
|
|
70
|
+
bind_dir: Optional[Union[Path, str]] = None,
|
|
71
|
+
auto_remove: bool = True,
|
|
72
|
+
stop_container: bool = True,
|
|
73
|
+
execution_policies: Optional[dict[str, bool]] = None,
|
|
74
|
+
):
|
|
75
|
+
"""(Experimental) A code executor class that executes code through
|
|
76
|
+
a command line environment in a Docker container.
|
|
77
|
+
|
|
78
|
+
The executor first saves each code block in a file in the working
|
|
79
|
+
directory, and then executes the code file in the container.
|
|
80
|
+
The executor executes the code blocks in the order they are received.
|
|
81
|
+
Currently, the executor only supports Python and shell scripts.
|
|
82
|
+
For Python code, use the language "python" for the code block.
|
|
83
|
+
For shell scripts, use the language "bash", "shell", or "sh" for the code
|
|
84
|
+
block.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
image: Docker image to use for code execution. Defaults to "python:3-slim".
|
|
88
|
+
container_name: Name of the Docker container which is created. If None, will autogenerate a name. Defaults to None.
|
|
89
|
+
timeout: The timeout for code execution. Defaults to 60.
|
|
90
|
+
work_dir: The working directory for the code execution. Defaults to Path(".").
|
|
91
|
+
bind_dir: The directory that will be bound to the code executor container. Useful for cases where you want to spawn
|
|
92
|
+
the container from within a container. Defaults to work_dir.
|
|
93
|
+
auto_remove: If true, will automatically remove the Docker container when it is stopped. Defaults to True.
|
|
94
|
+
stop_container: If true, will automatically stop the
|
|
95
|
+
container when stop is called, when the context manager exits or when
|
|
96
|
+
the Python process exits with atext. Defaults to True.
|
|
97
|
+
execution_policies: A dictionary mapping language names to boolean values that determine
|
|
98
|
+
whether code in that language should be executed. True means code in that language
|
|
99
|
+
will be executed, False means it will only be saved to a file. This overrides the
|
|
100
|
+
default execution policies. Defaults to None.
|
|
101
|
+
|
|
102
|
+
Raises:
|
|
103
|
+
ValueError: On argument error, or if the container fails to start.
|
|
104
|
+
"""
|
|
105
|
+
work_dir = work_dir if work_dir is not None else Path()
|
|
106
|
+
|
|
107
|
+
if timeout < 1:
|
|
108
|
+
raise ValueError("Timeout must be greater than or equal to 1.")
|
|
109
|
+
|
|
110
|
+
if isinstance(work_dir, str):
|
|
111
|
+
work_dir = Path(work_dir)
|
|
112
|
+
work_dir.mkdir(exist_ok=True)
|
|
113
|
+
|
|
114
|
+
if bind_dir is None:
|
|
115
|
+
bind_dir = work_dir
|
|
116
|
+
elif isinstance(bind_dir, str):
|
|
117
|
+
bind_dir = Path(bind_dir)
|
|
118
|
+
|
|
119
|
+
client = docker.from_env()
|
|
120
|
+
# Check if the image exists
|
|
121
|
+
try:
|
|
122
|
+
client.images.get(image)
|
|
123
|
+
except ImageNotFound:
|
|
124
|
+
logging.info(f"Pulling image {image}...")
|
|
125
|
+
# Let the docker exception escape if this fails.
|
|
126
|
+
client.images.pull(image)
|
|
127
|
+
|
|
128
|
+
if container_name is None:
|
|
129
|
+
container_name = f"autogen-code-exec-{uuid.uuid4()}"
|
|
130
|
+
|
|
131
|
+
# Start a container from the image, read to exec commands later
|
|
132
|
+
self._container = client.containers.create(
|
|
133
|
+
image,
|
|
134
|
+
name=container_name,
|
|
135
|
+
entrypoint="/bin/sh",
|
|
136
|
+
tty=True,
|
|
137
|
+
auto_remove=auto_remove,
|
|
138
|
+
volumes={str(bind_dir.resolve()): {"bind": "/workspace", "mode": "rw"}},
|
|
139
|
+
working_dir="/workspace",
|
|
140
|
+
)
|
|
141
|
+
self._container.start()
|
|
142
|
+
|
|
143
|
+
_wait_for_ready(self._container)
|
|
144
|
+
|
|
145
|
+
def cleanup() -> None:
|
|
146
|
+
try:
|
|
147
|
+
container = client.containers.get(container_name)
|
|
148
|
+
container.stop()
|
|
149
|
+
except docker.errors.NotFound:
|
|
150
|
+
pass
|
|
151
|
+
atexit.unregister(cleanup)
|
|
152
|
+
|
|
153
|
+
if stop_container:
|
|
154
|
+
atexit.register(cleanup)
|
|
155
|
+
|
|
156
|
+
self._cleanup = cleanup
|
|
157
|
+
|
|
158
|
+
# Check if the container is running
|
|
159
|
+
if self._container.status != "running":
|
|
160
|
+
raise ValueError(f"Failed to start container from image {image}. Logs: {self._container.logs()}")
|
|
161
|
+
|
|
162
|
+
self._timeout = timeout
|
|
163
|
+
self._work_dir: Path = work_dir
|
|
164
|
+
self._bind_dir: Path = bind_dir
|
|
165
|
+
self.execution_policies = self.DEFAULT_EXECUTION_POLICY.copy()
|
|
166
|
+
if execution_policies is not None:
|
|
167
|
+
self.execution_policies.update(execution_policies)
|
|
168
|
+
|
|
169
|
+
@property
|
|
170
|
+
def timeout(self) -> int:
|
|
171
|
+
"""(Experimental) The timeout for code execution."""
|
|
172
|
+
return self._timeout
|
|
173
|
+
|
|
174
|
+
@property
|
|
175
|
+
def work_dir(self) -> Path:
|
|
176
|
+
"""(Experimental) The working directory for the code execution."""
|
|
177
|
+
return self._work_dir
|
|
178
|
+
|
|
179
|
+
@property
|
|
180
|
+
def bind_dir(self) -> Path:
|
|
181
|
+
"""(Experimental) The binding directory for the code execution container."""
|
|
182
|
+
return self._bind_dir
|
|
183
|
+
|
|
184
|
+
@property
|
|
185
|
+
def code_extractor(self) -> CodeExtractor:
|
|
186
|
+
"""(Experimental) Export a code extractor that can be used by an agent."""
|
|
187
|
+
return MarkdownCodeExtractor()
|
|
188
|
+
|
|
189
|
+
def execute_code_blocks(self, code_blocks: list[CodeBlock]) -> CommandLineCodeResult:
|
|
190
|
+
"""(Experimental) Execute the code blocks and return the result.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
code_blocks (List[CodeBlock]): The code blocks to execute.
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
CommandlineCodeResult: The result of the code execution.
|
|
197
|
+
"""
|
|
198
|
+
if len(code_blocks) == 0:
|
|
199
|
+
raise ValueError("No code blocks to execute.")
|
|
200
|
+
|
|
201
|
+
outputs = []
|
|
202
|
+
files = []
|
|
203
|
+
last_exit_code = 0
|
|
204
|
+
for code_block in code_blocks:
|
|
205
|
+
lang = self.LANGUAGE_ALIASES.get(code_block.language.lower(), code_block.language.lower())
|
|
206
|
+
if lang not in self.DEFAULT_EXECUTION_POLICY:
|
|
207
|
+
outputs.append(f"Unsupported language {lang}\n")
|
|
208
|
+
last_exit_code = 1
|
|
209
|
+
break
|
|
210
|
+
|
|
211
|
+
execute_code = self.execution_policies.get(lang, False)
|
|
212
|
+
code = silence_pip(code_block.code, lang)
|
|
213
|
+
|
|
214
|
+
# Check if there is a filename comment
|
|
215
|
+
try:
|
|
216
|
+
filename = _get_file_name_from_content(code, self._work_dir)
|
|
217
|
+
except ValueError:
|
|
218
|
+
outputs.append("Filename is not in the workspace")
|
|
219
|
+
last_exit_code = 1
|
|
220
|
+
break
|
|
221
|
+
|
|
222
|
+
if not filename:
|
|
223
|
+
filename = f"tmp_code_{md5(code.encode()).hexdigest()}.{lang}"
|
|
224
|
+
|
|
225
|
+
code_path = self._work_dir / filename
|
|
226
|
+
with code_path.open("w", encoding="utf-8") as fout:
|
|
227
|
+
fout.write(code)
|
|
228
|
+
files.append(code_path)
|
|
229
|
+
|
|
230
|
+
if not execute_code:
|
|
231
|
+
outputs.append(f"Code saved to {code_path!s}\n")
|
|
232
|
+
continue
|
|
233
|
+
|
|
234
|
+
command = ["timeout", str(self._timeout), _cmd(lang), filename]
|
|
235
|
+
result = self._container.exec_run(command)
|
|
236
|
+
exit_code = result.exit_code
|
|
237
|
+
output = result.output.decode("utf-8")
|
|
238
|
+
if exit_code == 124:
|
|
239
|
+
output += "\n" + TIMEOUT_MSG
|
|
240
|
+
outputs.append(output)
|
|
241
|
+
|
|
242
|
+
last_exit_code = exit_code
|
|
243
|
+
if exit_code != 0:
|
|
244
|
+
break
|
|
245
|
+
|
|
246
|
+
code_file = str(files[0]) if files else None
|
|
247
|
+
return CommandLineCodeResult(exit_code=last_exit_code, output="".join(outputs), code_file=code_file)
|
|
248
|
+
|
|
249
|
+
def restart(self) -> None:
|
|
250
|
+
"""(Experimental) Restart the code executor."""
|
|
251
|
+
self._container.restart()
|
|
252
|
+
if self._container.status != "running":
|
|
253
|
+
raise ValueError(f"Failed to restart container. Logs: {self._container.logs()}")
|
|
254
|
+
|
|
255
|
+
def stop(self) -> None:
|
|
256
|
+
"""(Experimental) Stop the code executor."""
|
|
257
|
+
self._cleanup()
|
|
258
|
+
|
|
259
|
+
def __enter__(self) -> Self:
|
|
260
|
+
return self
|
|
261
|
+
|
|
262
|
+
def __exit__(
|
|
263
|
+
self,
|
|
264
|
+
exc_type: Optional[type[BaseException]],
|
|
265
|
+
exc_val: Optional[BaseException],
|
|
266
|
+
exc_tb: Optional[TracebackType],
|
|
267
|
+
) -> None:
|
|
268
|
+
self.stop()
|
|
@@ -0,0 +1,47 @@
|
|
|
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 ..doc_utils import export_module
|
|
8
|
+
from .base import CodeExecutionConfig, CodeExecutor
|
|
9
|
+
|
|
10
|
+
__all__ = ("CodeExecutorFactory",)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@export_module("autogen.coding")
|
|
14
|
+
class CodeExecutorFactory:
|
|
15
|
+
"""(Experimental) A factory class for creating code executors."""
|
|
16
|
+
|
|
17
|
+
@staticmethod
|
|
18
|
+
def create(code_execution_config: CodeExecutionConfig) -> CodeExecutor:
|
|
19
|
+
"""(Experimental) Get a code executor based on the code execution config.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
code_execution_config (Dict): The code execution config,
|
|
23
|
+
which is a dictionary that must contain the key "executor".
|
|
24
|
+
The value of the key "executor" can be either a string
|
|
25
|
+
or an instance of CodeExecutor, in which case the code
|
|
26
|
+
executor is returned directly.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
CodeExecutor: The code executor.
|
|
30
|
+
|
|
31
|
+
Raises:
|
|
32
|
+
ValueError: If the code executor is unknown or not specified.
|
|
33
|
+
"""
|
|
34
|
+
executor = code_execution_config.get("executor")
|
|
35
|
+
if isinstance(executor, CodeExecutor):
|
|
36
|
+
# If the executor is already an instance of CodeExecutor, return it.
|
|
37
|
+
return executor
|
|
38
|
+
if executor == "ipython-embedded":
|
|
39
|
+
from .jupyter.embedded_ipython_code_executor import EmbeddedIPythonCodeExecutor
|
|
40
|
+
|
|
41
|
+
return EmbeddedIPythonCodeExecutor(**code_execution_config.get("ipython-embedded", {}))
|
|
42
|
+
elif executor == "commandline-local":
|
|
43
|
+
from .local_commandline_code_executor import LocalCommandLineCodeExecutor
|
|
44
|
+
|
|
45
|
+
return LocalCommandLineCodeExecutor(**code_execution_config.get("commandline-local", {}))
|
|
46
|
+
else:
|
|
47
|
+
raise ValueError(f"Unknown code executor {executor}")
|
|
@@ -0,0 +1,202 @@
|
|
|
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
|
+
|
|
8
|
+
import functools
|
|
9
|
+
import importlib
|
|
10
|
+
import inspect
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
|
+
from importlib.abc import SourceLoader
|
|
13
|
+
from textwrap import dedent, indent
|
|
14
|
+
from typing import Any, Callable, Generic, TypeVar, Union
|
|
15
|
+
|
|
16
|
+
from typing_extensions import ParamSpec
|
|
17
|
+
|
|
18
|
+
T = TypeVar("T")
|
|
19
|
+
P = ParamSpec("P")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _to_code(func: Union["FunctionWithRequirements[T, P]", Callable[P, T], "FunctionWithRequirementsStr"]) -> str:
|
|
23
|
+
if isinstance(func, FunctionWithRequirementsStr):
|
|
24
|
+
return func.func
|
|
25
|
+
|
|
26
|
+
code = inspect.getsource(func)
|
|
27
|
+
# Strip the decorator
|
|
28
|
+
if code.startswith("@"):
|
|
29
|
+
code = code[code.index("\n") + 1 :]
|
|
30
|
+
return code
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass
|
|
34
|
+
class Alias:
|
|
35
|
+
name: str
|
|
36
|
+
alias: str
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass
|
|
40
|
+
class ImportFromModule:
|
|
41
|
+
module: str
|
|
42
|
+
imports: list[Union[str, Alias]]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
Import = Union[str, ImportFromModule, Alias]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _import_to_str(im: Import) -> str:
|
|
49
|
+
if isinstance(im, str):
|
|
50
|
+
return f"import {im}"
|
|
51
|
+
elif isinstance(im, Alias):
|
|
52
|
+
return f"import {im.name} as {im.alias}"
|
|
53
|
+
else:
|
|
54
|
+
|
|
55
|
+
def to_str(i: Union[str, Alias]) -> str:
|
|
56
|
+
if isinstance(i, str):
|
|
57
|
+
return i
|
|
58
|
+
else:
|
|
59
|
+
return f"{i.name} as {i.alias}"
|
|
60
|
+
|
|
61
|
+
imports = ", ".join(map(to_str, im.imports))
|
|
62
|
+
return f"from {im.module} import {imports}"
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class _StringLoader(SourceLoader):
|
|
66
|
+
def __init__(self, data: str):
|
|
67
|
+
self.data = data
|
|
68
|
+
|
|
69
|
+
def get_source(self, fullname: str) -> str:
|
|
70
|
+
return self.data
|
|
71
|
+
|
|
72
|
+
def get_data(self, path: str) -> bytes:
|
|
73
|
+
return self.data.encode("utf-8")
|
|
74
|
+
|
|
75
|
+
def get_filename(self, fullname: str) -> str:
|
|
76
|
+
return "<not a real path>/" + fullname + ".py"
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@dataclass
|
|
80
|
+
class FunctionWithRequirementsStr:
|
|
81
|
+
func: str
|
|
82
|
+
_compiled_func: Callable[..., Any]
|
|
83
|
+
_func_name: str
|
|
84
|
+
python_packages: list[str] = field(default_factory=list)
|
|
85
|
+
global_imports: list[Import] = field(default_factory=list)
|
|
86
|
+
|
|
87
|
+
def __init__(self, func: str, python_packages: list[str] = [], global_imports: list[Import] = []):
|
|
88
|
+
self.func = func
|
|
89
|
+
self.python_packages = python_packages
|
|
90
|
+
self.global_imports = global_imports
|
|
91
|
+
|
|
92
|
+
module_name = "func_module"
|
|
93
|
+
loader = _StringLoader(func)
|
|
94
|
+
spec = importlib.util.spec_from_loader(module_name, loader)
|
|
95
|
+
if spec is None:
|
|
96
|
+
raise ValueError("Could not create spec")
|
|
97
|
+
module = importlib.util.module_from_spec(spec)
|
|
98
|
+
if spec.loader is None:
|
|
99
|
+
raise ValueError("Could not create loader")
|
|
100
|
+
|
|
101
|
+
try:
|
|
102
|
+
spec.loader.exec_module(module)
|
|
103
|
+
except Exception as e:
|
|
104
|
+
raise ValueError(f"Could not compile function: {e}") from e
|
|
105
|
+
|
|
106
|
+
functions = inspect.getmembers(module, inspect.isfunction)
|
|
107
|
+
if len(functions) != 1:
|
|
108
|
+
raise ValueError("The string must contain exactly one function")
|
|
109
|
+
|
|
110
|
+
self._func_name, self._compiled_func = functions[0]
|
|
111
|
+
|
|
112
|
+
def __call__(self, *args: Any, **kwargs: Any) -> None:
|
|
113
|
+
raise NotImplementedError("String based function with requirement objects are not directly callable")
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@dataclass
|
|
117
|
+
class FunctionWithRequirements(Generic[T, P]):
|
|
118
|
+
func: Callable[P, T]
|
|
119
|
+
python_packages: list[str] = field(default_factory=list)
|
|
120
|
+
global_imports: list[Import] = field(default_factory=list)
|
|
121
|
+
|
|
122
|
+
@classmethod
|
|
123
|
+
def from_callable(
|
|
124
|
+
cls, func: Callable[P, T], python_packages: list[str] = [], global_imports: list[Import] = []
|
|
125
|
+
) -> "FunctionWithRequirements[T, P]":
|
|
126
|
+
return cls(python_packages=python_packages, global_imports=global_imports, func=func)
|
|
127
|
+
|
|
128
|
+
@staticmethod
|
|
129
|
+
def from_str(
|
|
130
|
+
func: str, python_packages: list[str] = [], global_imports: list[Import] = []
|
|
131
|
+
) -> FunctionWithRequirementsStr:
|
|
132
|
+
return FunctionWithRequirementsStr(func=func, python_packages=python_packages, global_imports=global_imports)
|
|
133
|
+
|
|
134
|
+
# Type this based on F
|
|
135
|
+
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> T:
|
|
136
|
+
return self.func(*args, **kwargs)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def with_requirements(
|
|
140
|
+
python_packages: list[str] = [], global_imports: list[Import] = []
|
|
141
|
+
) -> Callable[[Callable[P, T]], FunctionWithRequirements[T, P]]:
|
|
142
|
+
"""Decorate a function with package and import requirements
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
python_packages (List[str], optional): Packages required to function. Can include version info.. Defaults to [].
|
|
146
|
+
global_imports (List[Import], optional): Required imports. Defaults to [].
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
Callable[[Callable[P, T]], FunctionWithRequirements[T, P]]: The decorated function
|
|
150
|
+
"""
|
|
151
|
+
|
|
152
|
+
def wrapper(func: Callable[P, T]) -> FunctionWithRequirements[T, P]:
|
|
153
|
+
func_with_reqs = FunctionWithRequirements(
|
|
154
|
+
python_packages=python_packages, global_imports=global_imports, func=func
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
functools.update_wrapper(func_with_reqs, func)
|
|
158
|
+
return func_with_reqs
|
|
159
|
+
|
|
160
|
+
return wrapper
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _build_python_functions_file(
|
|
164
|
+
funcs: list[Union[FunctionWithRequirements[Any, P], Callable[..., Any], FunctionWithRequirementsStr]],
|
|
165
|
+
) -> str:
|
|
166
|
+
# First collect all global imports
|
|
167
|
+
global_imports: set[str] = set()
|
|
168
|
+
for func in funcs:
|
|
169
|
+
if isinstance(func, (FunctionWithRequirements, FunctionWithRequirementsStr)):
|
|
170
|
+
global_imports.update(map(_import_to_str, func.global_imports))
|
|
171
|
+
|
|
172
|
+
content = "\n".join(global_imports) + "\n\n"
|
|
173
|
+
|
|
174
|
+
for func in funcs:
|
|
175
|
+
content += _to_code(func) + "\n\n"
|
|
176
|
+
|
|
177
|
+
return content
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def to_stub(func: Union[Callable[..., Any], FunctionWithRequirementsStr]) -> str:
|
|
181
|
+
"""Generate a stub for a function as a string
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
func (Callable[..., Any]): The function to generate a stub for
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
str: The stub for the function
|
|
188
|
+
"""
|
|
189
|
+
if isinstance(func, FunctionWithRequirementsStr):
|
|
190
|
+
return to_stub(func._compiled_func)
|
|
191
|
+
|
|
192
|
+
content = f"def {func.__name__}{inspect.signature(func)}:\n"
|
|
193
|
+
docstring = func.__doc__
|
|
194
|
+
|
|
195
|
+
if docstring:
|
|
196
|
+
docstring = dedent(docstring)
|
|
197
|
+
docstring = '"""' + docstring + '"""'
|
|
198
|
+
docstring = indent(docstring, " ")
|
|
199
|
+
content += docstring + "\n"
|
|
200
|
+
|
|
201
|
+
content += " ..."
|
|
202
|
+
return content
|
|
@@ -0,0 +1,23 @@
|
|
|
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
|
+
# Original portions of this file are derived from https://github.com/microsoft/autogen under the MIT License.
|
|
6
|
+
# SPDX-License-Identifier: MIT
|
|
7
|
+
|
|
8
|
+
from .base import JupyterConnectable, JupyterConnectionInfo
|
|
9
|
+
from .docker_jupyter_server import DockerJupyterServer
|
|
10
|
+
from .embedded_ipython_code_executor import EmbeddedIPythonCodeExecutor
|
|
11
|
+
from .jupyter_client import JupyterClient
|
|
12
|
+
from .jupyter_code_executor import JupyterCodeExecutor
|
|
13
|
+
from .local_jupyter_server import LocalJupyterServer
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"DockerJupyterServer",
|
|
17
|
+
"EmbeddedIPythonCodeExecutor",
|
|
18
|
+
"JupyterClient",
|
|
19
|
+
"JupyterCodeExecutor",
|
|
20
|
+
"JupyterConnectable",
|
|
21
|
+
"JupyterConnectionInfo",
|
|
22
|
+
"LocalJupyterServer",
|
|
23
|
+
]
|
|
@@ -0,0 +1,36 @@
|
|
|
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 dataclasses import dataclass
|
|
8
|
+
from typing import Optional, Protocol, runtime_checkable
|
|
9
|
+
|
|
10
|
+
from ...doc_utils import export_module
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
@export_module("autogen.coding.jupyter")
|
|
15
|
+
class JupyterConnectionInfo:
|
|
16
|
+
"""(Experimental)"""
|
|
17
|
+
|
|
18
|
+
host: str
|
|
19
|
+
"""`str` - Host of the Jupyter gateway server"""
|
|
20
|
+
use_https: bool
|
|
21
|
+
"""`bool` - Whether to use HTTPS"""
|
|
22
|
+
port: Optional[int] = None
|
|
23
|
+
"""`Optional[int]` - Port of the Jupyter gateway server. If None, the default port is used"""
|
|
24
|
+
token: Optional[str] = None
|
|
25
|
+
"""`Optional[str]` - Token for authentication. If None, no token is used"""
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@runtime_checkable
|
|
29
|
+
@export_module("autogen.coding.jupyter")
|
|
30
|
+
class JupyterConnectable(Protocol):
|
|
31
|
+
"""(Experimental)"""
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def connection_info(self) -> JupyterConnectionInfo:
|
|
35
|
+
"""Return the connection information for this connectable."""
|
|
36
|
+
pass
|