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.
- ag2-0.10.2.dist-info/METADATA +819 -0
- ag2-0.10.2.dist-info/RECORD +423 -0
- ag2-0.10.2.dist-info/WHEEL +4 -0
- ag2-0.10.2.dist-info/licenses/LICENSE +201 -0
- ag2-0.10.2.dist-info/licenses/NOTICE.md +19 -0
- autogen/__init__.py +88 -0
- autogen/_website/__init__.py +3 -0
- autogen/_website/generate_api_references.py +426 -0
- autogen/_website/generate_mkdocs.py +1216 -0
- autogen/_website/notebook_processor.py +475 -0
- autogen/_website/process_notebooks.py +656 -0
- autogen/_website/utils.py +413 -0
- autogen/a2a/__init__.py +36 -0
- autogen/a2a/agent_executor.py +86 -0
- autogen/a2a/client.py +357 -0
- autogen/a2a/errors.py +18 -0
- autogen/a2a/httpx_client_factory.py +79 -0
- autogen/a2a/server.py +221 -0
- autogen/a2a/utils.py +207 -0
- autogen/agentchat/__init__.py +47 -0
- autogen/agentchat/agent.py +180 -0
- autogen/agentchat/assistant_agent.py +86 -0
- autogen/agentchat/chat.py +325 -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 +432 -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 +578 -0
- autogen/agentchat/contrib/capabilities/transforms_util.py +122 -0
- autogen/agentchat/contrib/capabilities/vision_capability.py +215 -0
- autogen/agentchat/contrib/captainagent/__init__.py +9 -0
- autogen/agentchat/contrib/captainagent/agent_builder.py +790 -0
- autogen/agentchat/contrib/captainagent/captainagent.py +514 -0
- autogen/agentchat/contrib/captainagent/tool_retriever.py +334 -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 +167 -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 +263 -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 +189 -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 +325 -0
- autogen/agentchat/contrib/rag/__init__.py +10 -0
- autogen/agentchat/contrib/rag/chromadb_query_engine.py +268 -0
- autogen/agentchat/contrib/rag/llamaindex_query_engine.py +195 -0
- autogen/agentchat/contrib/rag/mongodb_query_engine.py +319 -0
- autogen/agentchat/contrib/rag/query_engine.py +76 -0
- autogen/agentchat/contrib/retrieve_assistant_agent.py +59 -0
- autogen/agentchat/contrib/retrieve_user_proxy_agent.py +704 -0
- autogen/agentchat/contrib/society_of_mind_agent.py +200 -0
- autogen/agentchat/contrib/swarm_agent.py +1404 -0
- autogen/agentchat/contrib/text_analyzer_agent.py +79 -0
- autogen/agentchat/contrib/vectordb/__init__.py +5 -0
- autogen/agentchat/contrib/vectordb/base.py +224 -0
- autogen/agentchat/contrib/vectordb/chromadb.py +316 -0
- autogen/agentchat/contrib/vectordb/couchbase.py +405 -0
- autogen/agentchat/contrib/vectordb/mongodb.py +551 -0
- autogen/agentchat/contrib/vectordb/pgvectordb.py +927 -0
- autogen/agentchat/contrib/vectordb/qdrant.py +320 -0
- autogen/agentchat/contrib/vectordb/utils.py +126 -0
- autogen/agentchat/contrib/web_surfer.py +304 -0
- autogen/agentchat/conversable_agent.py +4307 -0
- autogen/agentchat/group/__init__.py +67 -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 +39 -0
- autogen/agentchat/group/context_variables.py +182 -0
- autogen/agentchat/group/events/transition_events.py +111 -0
- autogen/agentchat/group/group_tool_executor.py +324 -0
- autogen/agentchat/group/group_utils.py +659 -0
- autogen/agentchat/group/guardrails.py +179 -0
- autogen/agentchat/group/handoffs.py +303 -0
- autogen/agentchat/group/llm_condition.py +93 -0
- autogen/agentchat/group/multi_agent_chat.py +291 -0
- autogen/agentchat/group/on_condition.py +55 -0
- autogen/agentchat/group/on_context_condition.py +51 -0
- autogen/agentchat/group/patterns/__init__.py +18 -0
- autogen/agentchat/group/patterns/auto.py +160 -0
- autogen/agentchat/group/patterns/manual.py +177 -0
- autogen/agentchat/group/patterns/pattern.py +295 -0
- autogen/agentchat/group/patterns/random.py +106 -0
- autogen/agentchat/group/patterns/round_robin.py +117 -0
- autogen/agentchat/group/reply_result.py +24 -0
- autogen/agentchat/group/safeguards/__init__.py +21 -0
- autogen/agentchat/group/safeguards/api.py +241 -0
- autogen/agentchat/group/safeguards/enforcer.py +1158 -0
- autogen/agentchat/group/safeguards/events.py +140 -0
- autogen/agentchat/group/safeguards/validator.py +435 -0
- autogen/agentchat/group/speaker_selection_result.py +41 -0
- autogen/agentchat/group/targets/__init__.py +4 -0
- autogen/agentchat/group/targets/function_target.py +245 -0
- autogen/agentchat/group/targets/group_chat_target.py +133 -0
- autogen/agentchat/group/targets/group_manager_target.py +151 -0
- autogen/agentchat/group/targets/transition_target.py +424 -0
- autogen/agentchat/group/targets/transition_utils.py +6 -0
- autogen/agentchat/groupchat.py +1832 -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 +191 -0
- autogen/agentchat/realtime/experimental/function_observer.py +84 -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 +533 -0
- autogen/agentchat/realtime/experimental/websockets.py +21 -0
- autogen/agentchat/realtime_agent/__init__.py +21 -0
- autogen/agentchat/user_proxy_agent.py +114 -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 +74 -0
- autogen/agents/contrib/time/time_tool_agent.py +52 -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 +301 -0
- autogen/agents/experimental/document_agent/docling_doc_ingest_agent.py +113 -0
- autogen/agents/experimental/document_agent/document_agent.py +643 -0
- autogen/agents/experimental/document_agent/document_conditions.py +50 -0
- autogen/agents/experimental/document_agent/document_utils.py +376 -0
- autogen/agents/experimental/document_agent/inmemory_query_engine.py +214 -0
- autogen/agents/experimental/document_agent/parser_utils.py +134 -0
- autogen/agents/experimental/document_agent/url_utils.py +417 -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 +76 -0
- autogen/agents/experimental/websurfer/__init__.py +7 -0
- autogen/agents/experimental/websurfer/websurfer.py +70 -0
- autogen/agents/experimental/wikipedia/__init__.py +7 -0
- autogen/agents/experimental/wikipedia/wikipedia.py +88 -0
- autogen/browser_utils.py +309 -0
- autogen/cache/__init__.py +10 -0
- autogen/cache/abstract_cache_base.py +71 -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 +97 -0
- autogen/cache/in_memory_cache.py +54 -0
- autogen/cache/redis_cache.py +119 -0
- autogen/code_utils.py +598 -0
- autogen/coding/__init__.py +30 -0
- autogen/coding/base.py +120 -0
- autogen/coding/docker_commandline_code_executor.py +283 -0
- autogen/coding/factory.py +56 -0
- autogen/coding/func_with_reqs.py +203 -0
- autogen/coding/jupyter/__init__.py +23 -0
- autogen/coding/jupyter/base.py +36 -0
- autogen/coding/jupyter/docker_jupyter_server.py +160 -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 +224 -0
- autogen/coding/jupyter/jupyter_code_executor.py +154 -0
- autogen/coding/jupyter/local_jupyter_server.py +164 -0
- autogen/coding/local_commandline_code_executor.py +341 -0
- autogen/coding/markdown_code_extractor.py +44 -0
- autogen/coding/utils.py +55 -0
- autogen/coding/yepcode_code_executor.py +197 -0
- autogen/doc_utils.py +35 -0
- autogen/environments/__init__.py +10 -0
- autogen/environments/docker_python_environment.py +365 -0
- autogen/environments/python_environment.py +125 -0
- autogen/environments/system_python_environment.py +85 -0
- autogen/environments/venv_python_environment.py +220 -0
- autogen/environments/working_directory.py +74 -0
- autogen/events/__init__.py +7 -0
- autogen/events/agent_events.py +1016 -0
- autogen/events/base_event.py +100 -0
- autogen/events/client_events.py +168 -0
- autogen/events/helpers.py +44 -0
- autogen/events/print_event.py +45 -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 +75 -0
- autogen/fast_depends/core/__init__.py +14 -0
- autogen/fast_depends/core/build.py +206 -0
- autogen/fast_depends/core/model.py +527 -0
- autogen/fast_depends/dependencies/__init__.py +15 -0
- autogen/fast_depends/dependencies/model.py +30 -0
- autogen/fast_depends/dependencies/provider.py +40 -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 +272 -0
- autogen/fast_depends/utils.py +177 -0
- autogen/formatting_utils.py +83 -0
- autogen/function_utils.py +13 -0
- autogen/graph_utils.py +173 -0
- autogen/import_utils.py +539 -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 +156 -0
- autogen/interop/langchain/langchain_tool.py +78 -0
- autogen/interop/litellm/__init__.py +7 -0
- autogen/interop/litellm/litellm_config_factory.py +178 -0
- autogen/interop/pydantic_ai/__init__.py +7 -0
- autogen/interop/pydantic_ai/pydantic_ai.py +172 -0
- autogen/interop/registry.py +70 -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 +61 -0
- autogen/io/run_response.py +294 -0
- autogen/io/thread_io_stream.py +63 -0
- autogen/io/websockets.py +214 -0
- autogen/json_utils.py +42 -0
- autogen/llm_clients/MIGRATION_TO_V2.md +782 -0
- autogen/llm_clients/__init__.py +77 -0
- autogen/llm_clients/client_v2.py +122 -0
- autogen/llm_clients/models/__init__.py +55 -0
- autogen/llm_clients/models/content_blocks.py +389 -0
- autogen/llm_clients/models/unified_message.py +145 -0
- autogen/llm_clients/models/unified_response.py +83 -0
- autogen/llm_clients/openai_completions_client.py +444 -0
- autogen/llm_config/__init__.py +11 -0
- autogen/llm_config/client.py +59 -0
- autogen/llm_config/config.py +461 -0
- autogen/llm_config/entry.py +169 -0
- autogen/llm_config/types.py +37 -0
- autogen/llm_config/utils.py +223 -0
- autogen/logger/__init__.py +11 -0
- autogen/logger/base_logger.py +129 -0
- autogen/logger/file_logger.py +262 -0
- autogen/logger/logger_factory.py +42 -0
- autogen/logger/logger_utils.py +57 -0
- autogen/logger/sqlite_logger.py +524 -0
- autogen/math_utils.py +338 -0
- autogen/mcp/__init__.py +7 -0
- autogen/mcp/__main__.py +78 -0
- autogen/mcp/helpers.py +45 -0
- autogen/mcp/mcp_client.py +349 -0
- autogen/mcp/mcp_proxy/__init__.py +19 -0
- autogen/mcp/mcp_proxy/fastapi_code_generator_helpers.py +62 -0
- autogen/mcp/mcp_proxy/mcp_proxy.py +577 -0
- autogen/mcp/mcp_proxy/operation_grouping.py +166 -0
- autogen/mcp/mcp_proxy/operation_renaming.py +110 -0
- autogen/mcp/mcp_proxy/patch_fastapi_code_generator.py +98 -0
- autogen/mcp/mcp_proxy/security.py +399 -0
- autogen/mcp/mcp_proxy/security_schema_visitor.py +37 -0
- autogen/messages/__init__.py +7 -0
- autogen/messages/agent_messages.py +946 -0
- autogen/messages/base_message.py +108 -0
- autogen/messages/client_messages.py +172 -0
- autogen/messages/print_message.py +48 -0
- autogen/oai/__init__.py +61 -0
- autogen/oai/anthropic.py +1516 -0
- autogen/oai/bedrock.py +800 -0
- autogen/oai/cerebras.py +302 -0
- autogen/oai/client.py +1658 -0
- autogen/oai/client_utils.py +196 -0
- autogen/oai/cohere.py +494 -0
- autogen/oai/gemini.py +1045 -0
- autogen/oai/gemini_types.py +156 -0
- autogen/oai/groq.py +319 -0
- autogen/oai/mistral.py +311 -0
- autogen/oai/oai_models/__init__.py +23 -0
- autogen/oai/oai_models/_models.py +16 -0
- autogen/oai/oai_models/chat_completion.py +86 -0
- autogen/oai/oai_models/chat_completion_audio.py +32 -0
- autogen/oai/oai_models/chat_completion_message.py +97 -0
- autogen/oai/oai_models/chat_completion_message_tool_call.py +60 -0
- autogen/oai/oai_models/chat_completion_token_logprob.py +62 -0
- autogen/oai/oai_models/completion_usage.py +59 -0
- autogen/oai/ollama.py +657 -0
- autogen/oai/openai_responses.py +451 -0
- autogen/oai/openai_utils.py +897 -0
- autogen/oai/together.py +387 -0
- autogen/remote/__init__.py +18 -0
- autogen/remote/agent.py +199 -0
- autogen/remote/agent_service.py +197 -0
- autogen/remote/errors.py +17 -0
- autogen/remote/httpx_client_factory.py +131 -0
- autogen/remote/protocol.py +37 -0
- autogen/remote/retry.py +102 -0
- autogen/remote/runtime.py +96 -0
- autogen/retrieve_utils.py +490 -0
- autogen/runtime_logging.py +161 -0
- autogen/testing/__init__.py +12 -0
- autogen/testing/messages.py +45 -0
- autogen/testing/test_agent.py +111 -0
- autogen/token_count_utils.py +280 -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 +40 -0
- autogen/tools/dependency_injection.py +249 -0
- autogen/tools/experimental/__init__.py +54 -0
- autogen/tools/experimental/browser_use/__init__.py +7 -0
- autogen/tools/experimental/browser_use/browser_use.py +154 -0
- autogen/tools/experimental/code_execution/__init__.py +7 -0
- autogen/tools/experimental/code_execution/python_code_execution.py +86 -0
- autogen/tools/experimental/crawl4ai/__init__.py +7 -0
- autogen/tools/experimental/crawl4ai/crawl4ai.py +150 -0
- autogen/tools/experimental/deep_research/__init__.py +7 -0
- autogen/tools/experimental/deep_research/deep_research.py +329 -0
- autogen/tools/experimental/duckduckgo/__init__.py +7 -0
- autogen/tools/experimental/duckduckgo/duckduckgo_search.py +103 -0
- autogen/tools/experimental/firecrawl/__init__.py +7 -0
- autogen/tools/experimental/firecrawl/firecrawl_tool.py +836 -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 +284 -0
- autogen/tools/experimental/messageplatform/slack/__init__.py +7 -0
- autogen/tools/experimental/messageplatform/slack/slack.py +385 -0
- autogen/tools/experimental/messageplatform/telegram/__init__.py +7 -0
- autogen/tools/experimental/messageplatform/telegram/telegram.py +271 -0
- autogen/tools/experimental/perplexity/__init__.py +7 -0
- autogen/tools/experimental/perplexity/perplexity_search.py +249 -0
- autogen/tools/experimental/reliable/__init__.py +10 -0
- autogen/tools/experimental/reliable/reliable.py +1311 -0
- autogen/tools/experimental/searxng/__init__.py +7 -0
- autogen/tools/experimental/searxng/searxng_search.py +142 -0
- autogen/tools/experimental/tavily/__init__.py +7 -0
- autogen/tools/experimental/tavily/tavily_search.py +176 -0
- autogen/tools/experimental/web_search_preview/__init__.py +7 -0
- autogen/tools/experimental/web_search_preview/web_search_preview.py +120 -0
- autogen/tools/experimental/wikipedia/__init__.py +7 -0
- autogen/tools/experimental/wikipedia/wikipedia.py +284 -0
- autogen/tools/function_utils.py +412 -0
- autogen/tools/tool.py +188 -0
- autogen/tools/toolkit.py +86 -0
- autogen/types.py +29 -0
- autogen/version.py +7 -0
- templates/client_template/main.jinja2 +72 -0
- templates/config_template/config.jinja2 +7 -0
- templates/main.jinja2 +61 -0
|
@@ -0,0 +1,181 @@
|
|
|
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
|
+
|
|
6
|
+
import logging
|
|
7
|
+
from typing import Annotated, Any
|
|
8
|
+
|
|
9
|
+
from ....doc_utils import export_module
|
|
10
|
+
from ....import_utils import optional_import_block, require_optional_import
|
|
11
|
+
from ... import Depends, Tool
|
|
12
|
+
from ...dependency_injection import on
|
|
13
|
+
|
|
14
|
+
with optional_import_block():
|
|
15
|
+
import googleapiclient.errors
|
|
16
|
+
from googleapiclient.discovery import build
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@require_optional_import(
|
|
20
|
+
["googleapiclient"],
|
|
21
|
+
"google-search",
|
|
22
|
+
)
|
|
23
|
+
def _execute_search_query(query: str, youtube_api_key: str, max_results: int) -> Any:
|
|
24
|
+
"""Execute a YouTube search query using the YouTube Data API.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
query: The search query string.
|
|
28
|
+
youtube_api_key: The API key for the YouTube Data API.
|
|
29
|
+
max_results: The maximum number of results to return.
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
The search response from the YouTube Data API.
|
|
33
|
+
"""
|
|
34
|
+
youtube = build("youtube", "v3", developerKey=youtube_api_key)
|
|
35
|
+
|
|
36
|
+
try:
|
|
37
|
+
search_response = (
|
|
38
|
+
youtube.search().list(q=query, part="id,snippet", maxResults=max_results, type="video").execute()
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
return search_response
|
|
42
|
+
except googleapiclient.errors.HttpError as e:
|
|
43
|
+
logging.error(f"An HTTP error occurred: {e}")
|
|
44
|
+
raise
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@require_optional_import(
|
|
48
|
+
["googleapiclient"],
|
|
49
|
+
"google-search",
|
|
50
|
+
)
|
|
51
|
+
def _get_video_details(video_ids: list[str], youtube_api_key: str) -> Any:
|
|
52
|
+
"""Get detailed information about specific YouTube videos.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
video_ids: List of YouTube video IDs.
|
|
56
|
+
youtube_api_key: The API key for the YouTube Data API.
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
The video details response from the YouTube Data API.
|
|
60
|
+
"""
|
|
61
|
+
if not video_ids:
|
|
62
|
+
return {"items": []}
|
|
63
|
+
|
|
64
|
+
youtube = build("youtube", "v3", developerKey=youtube_api_key)
|
|
65
|
+
|
|
66
|
+
try:
|
|
67
|
+
videos_response = (
|
|
68
|
+
youtube.videos().list(id=",".join(video_ids), part="snippet,contentDetails,statistics").execute()
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
return videos_response
|
|
72
|
+
except googleapiclient.errors.HttpError as e:
|
|
73
|
+
logging.error(f"An HTTP error occurred: {e}")
|
|
74
|
+
raise
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _youtube_search(
|
|
78
|
+
query: str,
|
|
79
|
+
youtube_api_key: str,
|
|
80
|
+
max_results: int,
|
|
81
|
+
include_video_details: bool = True,
|
|
82
|
+
) -> list[dict[str, Any]]:
|
|
83
|
+
"""Search YouTube videos based on a query.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
query: The search query string.
|
|
87
|
+
youtube_api_key: The API key for the YouTube Data API.
|
|
88
|
+
max_results: The maximum number of results to return.
|
|
89
|
+
include_video_details: Whether to include detailed video information.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
A list of dictionaries containing information about the videos.
|
|
93
|
+
"""
|
|
94
|
+
search_response = _execute_search_query(query=query, youtube_api_key=youtube_api_key, max_results=max_results)
|
|
95
|
+
|
|
96
|
+
results = []
|
|
97
|
+
video_ids = []
|
|
98
|
+
|
|
99
|
+
# Extract basic info from search results
|
|
100
|
+
for item in search_response.get("items", []):
|
|
101
|
+
if item["id"]["kind"] == "youtube#video":
|
|
102
|
+
video_ids.append(item["id"]["videoId"])
|
|
103
|
+
video_info = {
|
|
104
|
+
"title": item["snippet"]["title"],
|
|
105
|
+
"description": item["snippet"]["description"],
|
|
106
|
+
"publishedAt": item["snippet"]["publishedAt"],
|
|
107
|
+
"channelTitle": item["snippet"]["channelTitle"],
|
|
108
|
+
"videoId": item["id"]["videoId"],
|
|
109
|
+
"url": f"https://www.youtube.com/watch?v={item['id']['videoId']}",
|
|
110
|
+
}
|
|
111
|
+
results.append(video_info)
|
|
112
|
+
|
|
113
|
+
# If detailed info requested, get it
|
|
114
|
+
if include_video_details and video_ids:
|
|
115
|
+
video_details = _get_video_details(video_ids, youtube_api_key)
|
|
116
|
+
|
|
117
|
+
# Create a mapping of videoId to details
|
|
118
|
+
details_map = {item["id"]: item for item in video_details.get("items", [])}
|
|
119
|
+
|
|
120
|
+
# Update results with additional details
|
|
121
|
+
for result in results:
|
|
122
|
+
video_id = result["videoId"]
|
|
123
|
+
if video_id in details_map:
|
|
124
|
+
details = details_map[video_id]
|
|
125
|
+
result.update({
|
|
126
|
+
"viewCount": details["statistics"].get("viewCount"),
|
|
127
|
+
"likeCount": details["statistics"].get("likeCount"),
|
|
128
|
+
"commentCount": details["statistics"].get("commentCount"),
|
|
129
|
+
"duration": details["contentDetails"].get("duration"),
|
|
130
|
+
"definition": details["contentDetails"].get("definition"),
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
return results
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@export_module("autogen.tools.experimental")
|
|
137
|
+
class YoutubeSearchTool(Tool):
|
|
138
|
+
"""YoutubeSearchTool is a tool that uses the YouTube Data API to search for videos."""
|
|
139
|
+
|
|
140
|
+
def __init__(
|
|
141
|
+
self,
|
|
142
|
+
*,
|
|
143
|
+
youtube_api_key: str | None = None,
|
|
144
|
+
):
|
|
145
|
+
"""Initialize a YouTube search tool.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
youtube_api_key: The API key for the YouTube Data API.
|
|
149
|
+
"""
|
|
150
|
+
self.youtube_api_key = youtube_api_key
|
|
151
|
+
|
|
152
|
+
if youtube_api_key is None:
|
|
153
|
+
raise ValueError("youtube_api_key must be provided")
|
|
154
|
+
|
|
155
|
+
def youtube_search(
|
|
156
|
+
query: Annotated[str, "The search query for YouTube videos."],
|
|
157
|
+
youtube_api_key: Annotated[str, Depends(on(youtube_api_key))],
|
|
158
|
+
max_results: Annotated[int, "The maximum number of results to return."] = 5,
|
|
159
|
+
include_video_details: Annotated[bool, "Whether to include detailed video information."] = True,
|
|
160
|
+
) -> list[dict[str, Any]]:
|
|
161
|
+
"""Search for YouTube videos based on a query.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
query: The search query string.
|
|
165
|
+
youtube_api_key: The API key for the YouTube Data API.
|
|
166
|
+
max_results: The maximum number of results to return.
|
|
167
|
+
include_video_details: Whether to include detailed video information.
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
A list of dictionaries containing information about the videos.
|
|
171
|
+
"""
|
|
172
|
+
if youtube_api_key is None:
|
|
173
|
+
raise ValueError("YouTube API key is required")
|
|
174
|
+
|
|
175
|
+
return _youtube_search(query, youtube_api_key, max_results, include_video_details)
|
|
176
|
+
|
|
177
|
+
super().__init__(
|
|
178
|
+
name="youtube_search",
|
|
179
|
+
description="Search for YouTube videos based on a query, optionally including detailed information.",
|
|
180
|
+
func_or_tool=youtube_search,
|
|
181
|
+
)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
from .discord import DiscordRetrieveTool, DiscordSendTool
|
|
6
|
+
from .slack import SlackRetrieveRepliesTool, SlackRetrieveTool, SlackSendTool
|
|
7
|
+
from .telegram import TelegramRetrieveTool, TelegramSendTool
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"DiscordRetrieveTool",
|
|
11
|
+
"DiscordSendTool",
|
|
12
|
+
"SlackRetrieveRepliesTool",
|
|
13
|
+
"SlackRetrieveTool",
|
|
14
|
+
"SlackSendTool",
|
|
15
|
+
"TelegramRetrieveTool",
|
|
16
|
+
"TelegramSendTool",
|
|
17
|
+
]
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
# Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
from datetime import datetime, timezone
|
|
7
|
+
from typing import Annotated, Any
|
|
8
|
+
|
|
9
|
+
from .....doc_utils import export_module
|
|
10
|
+
from .....import_utils import optional_import_block, require_optional_import
|
|
11
|
+
from .... import Tool
|
|
12
|
+
from ....dependency_injection import Depends, on
|
|
13
|
+
|
|
14
|
+
__all__ = ["DiscordRetrieveTool", "DiscordSendTool"]
|
|
15
|
+
|
|
16
|
+
with optional_import_block():
|
|
17
|
+
from discord import Client, Intents, utils
|
|
18
|
+
|
|
19
|
+
MAX_MESSAGE_LENGTH = 2000
|
|
20
|
+
MAX_BATCH_RETRIEVE_MESSAGES = 100 # Discord's max per request
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@require_optional_import(["discord"], "commsagent-discord")
|
|
24
|
+
@export_module("autogen.tools.experimental")
|
|
25
|
+
class DiscordSendTool(Tool):
|
|
26
|
+
"""Sends a message to a Discord channel."""
|
|
27
|
+
|
|
28
|
+
def __init__(self, *, bot_token: str, channel_name: str, guild_name: str) -> None:
|
|
29
|
+
"""Initialize the DiscordSendTool.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
bot_token: The bot token to use for sending messages.
|
|
33
|
+
channel_name: The name of the channel to send messages to.
|
|
34
|
+
guild_name: The name of the guild for the channel.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
# Function that sends the message, uses dependency injection for bot token / channel / guild
|
|
38
|
+
async def discord_send_message(
|
|
39
|
+
message: Annotated[str, "Message to send to the channel."],
|
|
40
|
+
bot_token: Annotated[str, Depends(on(bot_token))],
|
|
41
|
+
guild_name: Annotated[str, Depends(on(guild_name))],
|
|
42
|
+
channel_name: Annotated[str, Depends(on(channel_name))],
|
|
43
|
+
) -> Any:
|
|
44
|
+
"""Sends a message to a Discord channel.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
message: The message to send to the channel.
|
|
48
|
+
bot_token: The bot token to use for Discord. (uses dependency injection)
|
|
49
|
+
guild_name: The name of the server. (uses dependency injection)
|
|
50
|
+
channel_name: The name of the channel. (uses dependency injection)
|
|
51
|
+
"""
|
|
52
|
+
intents = Intents.default()
|
|
53
|
+
intents.message_content = True
|
|
54
|
+
intents.guilds = True
|
|
55
|
+
intents.guild_messages = True
|
|
56
|
+
|
|
57
|
+
client = Client(intents=intents)
|
|
58
|
+
result_future: asyncio.Future[str] = asyncio.Future() # Stores the result of the send
|
|
59
|
+
|
|
60
|
+
# When the client is ready, we'll send the message
|
|
61
|
+
@client.event # type: ignore[misc]
|
|
62
|
+
async def on_ready() -> None:
|
|
63
|
+
try:
|
|
64
|
+
# Server
|
|
65
|
+
guild = utils.get(client.guilds, name=guild_name)
|
|
66
|
+
if guild:
|
|
67
|
+
# Channel
|
|
68
|
+
channel = utils.get(guild.text_channels, name=channel_name)
|
|
69
|
+
if channel:
|
|
70
|
+
# Send the message
|
|
71
|
+
if len(message) > MAX_MESSAGE_LENGTH:
|
|
72
|
+
chunks = [
|
|
73
|
+
message[i : i + (MAX_MESSAGE_LENGTH - 1)]
|
|
74
|
+
for i in range(0, len(message), (MAX_MESSAGE_LENGTH - 1))
|
|
75
|
+
]
|
|
76
|
+
for i, chunk in enumerate(chunks):
|
|
77
|
+
sent = await channel.send(chunk)
|
|
78
|
+
|
|
79
|
+
# Store ID for the first chunk
|
|
80
|
+
if i == 0:
|
|
81
|
+
sent_message_id = str(sent.id)
|
|
82
|
+
|
|
83
|
+
result_future.set_result(
|
|
84
|
+
f"Message sent successfully ({len(chunks)} chunks, first ID: {sent_message_id}):\n{message}"
|
|
85
|
+
)
|
|
86
|
+
else:
|
|
87
|
+
sent = await channel.send(message)
|
|
88
|
+
result_future.set_result(f"Message sent successfully (ID: {sent.id}):\n{message}")
|
|
89
|
+
else:
|
|
90
|
+
result_future.set_result(f"Message send failed, could not find channel: {channel_name}")
|
|
91
|
+
else:
|
|
92
|
+
result_future.set_result(f"Message send failed, could not find guild: {guild_name}")
|
|
93
|
+
|
|
94
|
+
except Exception as e:
|
|
95
|
+
result_future.set_exception(e)
|
|
96
|
+
finally:
|
|
97
|
+
try:
|
|
98
|
+
await client.close()
|
|
99
|
+
except Exception as e:
|
|
100
|
+
raise Exception(f"Unable to close Discord client: {e}")
|
|
101
|
+
|
|
102
|
+
# Start the client and when it's ready it'll send the message in on_ready
|
|
103
|
+
try:
|
|
104
|
+
await client.start(bot_token)
|
|
105
|
+
|
|
106
|
+
# Capture the result of the send
|
|
107
|
+
return await result_future
|
|
108
|
+
except Exception as e:
|
|
109
|
+
raise Exception(f"Failed to start Discord client: {e}")
|
|
110
|
+
|
|
111
|
+
super().__init__(
|
|
112
|
+
name="discord_send",
|
|
113
|
+
description="Sends a message to a Discord channel.",
|
|
114
|
+
func_or_tool=discord_send_message,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@require_optional_import(["discord"], "commsagent-discord")
|
|
119
|
+
@export_module("autogen.tools.experimental")
|
|
120
|
+
class DiscordRetrieveTool(Tool):
|
|
121
|
+
"""Retrieves messages from a Discord channel."""
|
|
122
|
+
|
|
123
|
+
def __init__(self, *, bot_token: str, channel_name: str, guild_name: str) -> None:
|
|
124
|
+
"""Initialize the DiscordRetrieveTool.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
bot_token: The bot token to use for retrieving messages.
|
|
128
|
+
channel_name: The name of the channel to retrieve messages from.
|
|
129
|
+
guild_name: The name of the guild for the channel.
|
|
130
|
+
"""
|
|
131
|
+
|
|
132
|
+
async def discord_retrieve_messages(
|
|
133
|
+
bot_token: Annotated[str, Depends(on(bot_token))],
|
|
134
|
+
guild_name: Annotated[str, Depends(on(guild_name))],
|
|
135
|
+
channel_name: Annotated[str, Depends(on(channel_name))],
|
|
136
|
+
messages_since: Annotated[
|
|
137
|
+
str | None,
|
|
138
|
+
"Date to retrieve messages from (ISO format) OR Discord snowflake ID. If None, retrieves latest messages.",
|
|
139
|
+
] = None,
|
|
140
|
+
maximum_messages: Annotated[
|
|
141
|
+
int | None, "Maximum number of messages to retrieve. If None, retrieves all messages since date."
|
|
142
|
+
] = None,
|
|
143
|
+
) -> Any:
|
|
144
|
+
"""Retrieves messages from a Discord channel.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
bot_token: The bot token to use for Discord. (uses dependency injection)
|
|
148
|
+
guild_name: The name of the server. (uses dependency injection)
|
|
149
|
+
channel_name: The name of the channel. (uses dependency injection)
|
|
150
|
+
messages_since: ISO format date string OR Discord snowflake ID, to retrieve messages from. If None, retrieves latest messages.
|
|
151
|
+
maximum_messages: Maximum number of messages to retrieve. If None, retrieves all messages since date.
|
|
152
|
+
"""
|
|
153
|
+
intents = Intents.default()
|
|
154
|
+
intents.message_content = True
|
|
155
|
+
intents.guilds = True
|
|
156
|
+
intents.guild_messages = True
|
|
157
|
+
|
|
158
|
+
client = Client(intents=intents)
|
|
159
|
+
result_future: asyncio.Future[list[dict[str, Any]]] = asyncio.Future()
|
|
160
|
+
|
|
161
|
+
messages_since_date: str | None = None
|
|
162
|
+
if messages_since is not None:
|
|
163
|
+
if DiscordRetrieveTool._is_snowflake(messages_since):
|
|
164
|
+
messages_since_date = DiscordRetrieveTool._snowflake_to_iso(messages_since)
|
|
165
|
+
else:
|
|
166
|
+
messages_since_date = messages_since
|
|
167
|
+
|
|
168
|
+
@client.event # type: ignore[misc]
|
|
169
|
+
async def on_ready() -> None:
|
|
170
|
+
try:
|
|
171
|
+
messages = []
|
|
172
|
+
|
|
173
|
+
# Get guild and channel
|
|
174
|
+
guild = utils.get(client.guilds, name=guild_name)
|
|
175
|
+
if not guild:
|
|
176
|
+
result_future.set_result([{"error": f"Could not find guild: {guild_name}"}])
|
|
177
|
+
return
|
|
178
|
+
|
|
179
|
+
channel = utils.get(guild.text_channels, name=channel_name)
|
|
180
|
+
if not channel:
|
|
181
|
+
result_future.set_result([{"error": f"Could not find channel: {channel_name}"}])
|
|
182
|
+
return
|
|
183
|
+
|
|
184
|
+
# Setup retrieval parameters
|
|
185
|
+
last_message_id = None
|
|
186
|
+
messages_retrieved = 0
|
|
187
|
+
|
|
188
|
+
# Convert to ISO format
|
|
189
|
+
after_date = None
|
|
190
|
+
if messages_since_date:
|
|
191
|
+
try:
|
|
192
|
+
from datetime import datetime
|
|
193
|
+
|
|
194
|
+
after_date = datetime.fromisoformat(messages_since_date)
|
|
195
|
+
except ValueError:
|
|
196
|
+
result_future.set_result([
|
|
197
|
+
{"error": f"Invalid date format: {messages_since_date}. Use ISO format."}
|
|
198
|
+
])
|
|
199
|
+
return
|
|
200
|
+
|
|
201
|
+
while True:
|
|
202
|
+
# Setup fetch options
|
|
203
|
+
fetch_options = {
|
|
204
|
+
"limit": MAX_BATCH_RETRIEVE_MESSAGES,
|
|
205
|
+
"before": last_message_id if last_message_id else None,
|
|
206
|
+
"after": after_date if after_date else None,
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
# Fetch batch of messages
|
|
210
|
+
message_batch = []
|
|
211
|
+
async for message in channel.history(**fetch_options): # type: ignore[arg-type]
|
|
212
|
+
message_batch.append(message)
|
|
213
|
+
messages_retrieved += 1
|
|
214
|
+
|
|
215
|
+
# Check if we've reached the maximum
|
|
216
|
+
if maximum_messages and messages_retrieved >= maximum_messages:
|
|
217
|
+
break
|
|
218
|
+
|
|
219
|
+
if not message_batch:
|
|
220
|
+
break
|
|
221
|
+
|
|
222
|
+
# Process messages
|
|
223
|
+
for msg in message_batch:
|
|
224
|
+
messages.append({
|
|
225
|
+
"id": str(msg.id),
|
|
226
|
+
"content": msg.content,
|
|
227
|
+
"author": str(msg.author),
|
|
228
|
+
"timestamp": msg.created_at.isoformat(),
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
# Update last message ID for pagination
|
|
232
|
+
last_message_id = message_batch[-1] # Use message object directly as 'before' parameter
|
|
233
|
+
|
|
234
|
+
# Break if we've reached the maximum
|
|
235
|
+
if maximum_messages and messages_retrieved >= maximum_messages:
|
|
236
|
+
break
|
|
237
|
+
|
|
238
|
+
result_future.set_result(messages)
|
|
239
|
+
|
|
240
|
+
except Exception as e:
|
|
241
|
+
result_future.set_exception(e)
|
|
242
|
+
finally:
|
|
243
|
+
try:
|
|
244
|
+
await client.close()
|
|
245
|
+
except Exception as e:
|
|
246
|
+
raise Exception(f"Unable to close Discord client: {e}")
|
|
247
|
+
|
|
248
|
+
try:
|
|
249
|
+
await client.start(bot_token)
|
|
250
|
+
return await result_future
|
|
251
|
+
except Exception as e:
|
|
252
|
+
raise Exception(f"Failed to start Discord client: {e}")
|
|
253
|
+
|
|
254
|
+
super().__init__(
|
|
255
|
+
name="discord_retrieve",
|
|
256
|
+
description="Retrieves messages from a Discord channel based datetime/message ID and/or number of latest messages.",
|
|
257
|
+
func_or_tool=discord_retrieve_messages,
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
@staticmethod
|
|
261
|
+
def _is_snowflake(value: str) -> bool:
|
|
262
|
+
"""Check if a string is a valid Discord snowflake ID."""
|
|
263
|
+
# Must be numeric and 17-20 digits
|
|
264
|
+
if not value.isdigit():
|
|
265
|
+
return False
|
|
266
|
+
|
|
267
|
+
digit_count = len(value)
|
|
268
|
+
return 17 <= digit_count <= 20
|
|
269
|
+
|
|
270
|
+
@staticmethod
|
|
271
|
+
def _snowflake_to_iso(snowflake: str) -> str:
|
|
272
|
+
"""Convert a Discord snowflake ID to ISO timestamp string."""
|
|
273
|
+
if not DiscordRetrieveTool._is_snowflake(snowflake):
|
|
274
|
+
raise ValueError(f"Invalid snowflake ID: {snowflake}")
|
|
275
|
+
|
|
276
|
+
# Discord epoch (2015-01-01)
|
|
277
|
+
discord_epoch = 1420070400000
|
|
278
|
+
|
|
279
|
+
# Convert ID to int and shift right 22 bits to get timestamp
|
|
280
|
+
timestamp_ms = (int(snowflake) >> 22) + discord_epoch
|
|
281
|
+
|
|
282
|
+
# Convert to datetime and format as ISO string
|
|
283
|
+
dt = datetime.fromtimestamp(timestamp_ms / 1000.0, tz=timezone.utc)
|
|
284
|
+
return dt.isoformat()
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
from .slack import SlackRetrieveRepliesTool, SlackRetrieveTool, SlackSendTool
|
|
6
|
+
|
|
7
|
+
__all__ = ["SlackRetrieveRepliesTool", "SlackRetrieveTool", "SlackSendTool"]
|