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,73 @@
|
|
|
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 typing import Any
|
|
6
|
+
|
|
7
|
+
from .... import ConversableAgent
|
|
8
|
+
from ....doc_utils import export_module
|
|
9
|
+
from ....tools.experimental import SlackRetrieveRepliesTool, SlackRetrieveTool, SlackSendTool
|
|
10
|
+
|
|
11
|
+
__all__ = ["SlackAgent"]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@export_module("autogen.agents.experimental")
|
|
15
|
+
class SlackAgent(ConversableAgent):
|
|
16
|
+
"""An agent that can send messages and retrieve messages on Slack."""
|
|
17
|
+
|
|
18
|
+
DEFAULT_SYSTEM_MESSAGE = (
|
|
19
|
+
"You are a helpful AI assistant that communicates through Slack. "
|
|
20
|
+
"Remember that Slack uses Markdown-like formatting and has message length limits. "
|
|
21
|
+
"Keep messages clear and concise, and consider using appropriate formatting when helpful."
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
name: str,
|
|
27
|
+
system_message: str | None = None,
|
|
28
|
+
*,
|
|
29
|
+
bot_token: str,
|
|
30
|
+
channel_id: str,
|
|
31
|
+
has_writing_instructions: bool = True,
|
|
32
|
+
**kwargs: Any,
|
|
33
|
+
) -> None:
|
|
34
|
+
"""Initialize the SlackAgent.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
name: name of the agent.
|
|
38
|
+
system_message: system message for the ChatCompletion inference.
|
|
39
|
+
bot_token: Bot User OAuth Token starting with "xoxb-".
|
|
40
|
+
channel_id: Channel ID where messages will be sent.
|
|
41
|
+
has_writing_instructions: Whether to add writing instructions to the system message. Defaults to True.
|
|
42
|
+
**kwargs: Additional keyword arguments passed to the parent ConversableAgent class.
|
|
43
|
+
"""
|
|
44
|
+
slack_system_message = system_message or self.DEFAULT_SYSTEM_MESSAGE
|
|
45
|
+
|
|
46
|
+
self._send_tool = SlackSendTool(bot_token=bot_token, channel_id=channel_id)
|
|
47
|
+
self._retrieve_tool = SlackRetrieveTool(bot_token=bot_token, channel_id=channel_id)
|
|
48
|
+
self._retrieve_replies_tool = SlackRetrieveRepliesTool(bot_token=bot_token, channel_id=channel_id)
|
|
49
|
+
|
|
50
|
+
# Add formatting instructions
|
|
51
|
+
if has_writing_instructions:
|
|
52
|
+
formatting_instructions = (
|
|
53
|
+
"\nFormat guidelines for Slack:\n"
|
|
54
|
+
"Format guidelines for Slack:\n"
|
|
55
|
+
"1. Max message length: 40,000 characters\n"
|
|
56
|
+
"2. Supports Markdown-like formatting:\n"
|
|
57
|
+
" - *text* for italic\n"
|
|
58
|
+
" - **text** for bold\n"
|
|
59
|
+
" - `code` for inline code\n"
|
|
60
|
+
" - ```code block``` for multi-line code\n"
|
|
61
|
+
"3. Supports message threading for organized discussions\n"
|
|
62
|
+
"4. Can use :emoji_name: for emoji reactions\n"
|
|
63
|
+
"5. Supports block quotes with > prefix\n"
|
|
64
|
+
"6. Can use <!here> or <!channel> for notifications"
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
slack_system_message = slack_system_message + formatting_instructions
|
|
68
|
+
|
|
69
|
+
super().__init__(name=name, system_message=slack_system_message, **kwargs)
|
|
70
|
+
|
|
71
|
+
self.register_for_llm()(self._send_tool)
|
|
72
|
+
self.register_for_llm()(self._retrieve_tool)
|
|
73
|
+
self.register_for_llm()(self._retrieve_replies_tool)
|
|
@@ -0,0 +1,76 @@
|
|
|
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 typing import Any
|
|
6
|
+
|
|
7
|
+
from .... import ConversableAgent
|
|
8
|
+
from ....doc_utils import export_module
|
|
9
|
+
from ....tools.experimental import TelegramRetrieveTool, TelegramSendTool
|
|
10
|
+
|
|
11
|
+
__all__ = ["TelegramAgent"]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@export_module("autogen.agents.experimental")
|
|
15
|
+
class TelegramAgent(ConversableAgent):
|
|
16
|
+
"""An agent that can send messages and retrieve messages on Telegram."""
|
|
17
|
+
|
|
18
|
+
DEFAULT_SYSTEM_MESSAGE = (
|
|
19
|
+
"You are a helpful AI assistant that communicates through Telegram. "
|
|
20
|
+
"Remember that Telegram uses Markdown-like formatting and has message length limits. "
|
|
21
|
+
"Keep messages clear and concise, and consider using appropriate formatting when helpful."
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
name: str,
|
|
27
|
+
system_message: str | None = None,
|
|
28
|
+
*,
|
|
29
|
+
api_id: str,
|
|
30
|
+
api_hash: str,
|
|
31
|
+
chat_id: str,
|
|
32
|
+
has_writing_instructions: bool = True,
|
|
33
|
+
**kwargs: Any,
|
|
34
|
+
) -> None:
|
|
35
|
+
"""Initialize the TelegramAgent.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
name: The name of the agent.
|
|
39
|
+
system_message: The system message for the agent.
|
|
40
|
+
api_id: Telegram API ID from https://my.telegram.org/apps.
|
|
41
|
+
api_hash: Telegram API hash from https://my.telegram.org/apps.
|
|
42
|
+
chat_id: The ID of the destination (Channel, Group, or User ID).
|
|
43
|
+
has_writing_instructions (bool): Whether to add writing instructions to the system message. Defaults to True.
|
|
44
|
+
**kwargs: Additional keyword arguments passed to the parent ConversableAgent class.
|
|
45
|
+
"""
|
|
46
|
+
telegram_system_message = system_message or self.DEFAULT_SYSTEM_MESSAGE
|
|
47
|
+
|
|
48
|
+
self._send_tool = TelegramSendTool(api_id=api_id, api_hash=api_hash, chat_id=chat_id)
|
|
49
|
+
self._retrieve_tool = TelegramRetrieveTool(api_id=api_id, api_hash=api_hash, chat_id=chat_id)
|
|
50
|
+
|
|
51
|
+
# Add formatting instructions
|
|
52
|
+
if has_writing_instructions:
|
|
53
|
+
formatting_instructions = (
|
|
54
|
+
"\nFormat guidelines for Telegram:\n"
|
|
55
|
+
"1. Max message length: 4096 characters\n"
|
|
56
|
+
"2. HTML formatting:\n"
|
|
57
|
+
" - <b>bold</b>\n"
|
|
58
|
+
" - <i>italic</i>\n"
|
|
59
|
+
" - <code>code</code>\n"
|
|
60
|
+
" - <pre>code block</pre>\n"
|
|
61
|
+
" - <a href='URL'>link</a>\n"
|
|
62
|
+
" - <u>underline</u>\n"
|
|
63
|
+
" - <s>strikethrough</s>\n"
|
|
64
|
+
"3. HTML rules:\n"
|
|
65
|
+
" - Tags must be properly closed\n"
|
|
66
|
+
" - Can't nest identical tags\n"
|
|
67
|
+
" - Links require full URLs (with http://)\n"
|
|
68
|
+
"4. Supports @mentions and emoji"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
telegram_system_message = telegram_system_message + formatting_instructions
|
|
72
|
+
|
|
73
|
+
super().__init__(name=name, system_message=telegram_system_message, **kwargs)
|
|
74
|
+
|
|
75
|
+
self.register_for_llm()(self._send_tool)
|
|
76
|
+
self.register_for_llm()(self._retrieve_tool)
|
|
@@ -0,0 +1,70 @@
|
|
|
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 typing import Any, Literal
|
|
6
|
+
|
|
7
|
+
from .... import ConversableAgent
|
|
8
|
+
from ....doc_utils import export_module
|
|
9
|
+
from ....llm_config import LLMConfig
|
|
10
|
+
from ....tools import Tool
|
|
11
|
+
from ....tools.experimental import (
|
|
12
|
+
BrowserUseTool,
|
|
13
|
+
Crawl4AITool,
|
|
14
|
+
DuckDuckGoSearchTool,
|
|
15
|
+
FirecrawlTool,
|
|
16
|
+
PerplexitySearchTool,
|
|
17
|
+
SearxngSearchTool,
|
|
18
|
+
TavilySearchTool,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
__all__ = ["WebSurferAgent"]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@export_module("autogen.agents.experimental")
|
|
25
|
+
class WebSurferAgent(ConversableAgent):
|
|
26
|
+
"""An agent that uses web tools to interact with the web."""
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
*,
|
|
31
|
+
llm_config: LLMConfig | dict[str, Any] | None = None,
|
|
32
|
+
web_tool_llm_config: LLMConfig | dict[str, Any] | None = None,
|
|
33
|
+
web_tool: Literal[
|
|
34
|
+
"browser_use", "crawl4ai", "duckduckgo", "firecrawl", "perplexity", "tavily", "searxng"
|
|
35
|
+
] = "browser_use",
|
|
36
|
+
web_tool_kwargs: dict[str, Any] | None = None,
|
|
37
|
+
**kwargs: Any,
|
|
38
|
+
) -> None:
|
|
39
|
+
"""Initialize the WebSurferAgent.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
llm_config: The LLM configuration.
|
|
43
|
+
web_tool_llm_config: The LLM configuration for the web tool. If not provided, the llm_config will be used.
|
|
44
|
+
web_tool: The web tool to use. Defaults to "browser_use".
|
|
45
|
+
web_tool_kwargs: The keyword arguments for the web tool. Defaults to None.
|
|
46
|
+
**kwargs: Additional keyword arguments passed to the parent ConversableAgent class.
|
|
47
|
+
"""
|
|
48
|
+
llm_config = LLMConfig.get_current_llm_config(llm_config) # type: ignore[arg-type]
|
|
49
|
+
web_tool_kwargs = web_tool_kwargs if web_tool_kwargs else {}
|
|
50
|
+
web_tool_llm_config = web_tool_llm_config if web_tool_llm_config else llm_config
|
|
51
|
+
if web_tool == "browser_use":
|
|
52
|
+
self.tool: Tool = BrowserUseTool(llm_config=web_tool_llm_config, **web_tool_kwargs) # type: ignore[arg-type]
|
|
53
|
+
elif web_tool == "crawl4ai":
|
|
54
|
+
self.tool = Crawl4AITool(llm_config=web_tool_llm_config, **web_tool_kwargs)
|
|
55
|
+
elif web_tool == "firecrawl":
|
|
56
|
+
self.tool = FirecrawlTool(llm_config=web_tool_llm_config, **web_tool_kwargs)
|
|
57
|
+
elif web_tool == "perplexity":
|
|
58
|
+
self.tool = PerplexitySearchTool(**web_tool_kwargs)
|
|
59
|
+
elif web_tool == "tavily":
|
|
60
|
+
self.tool = TavilySearchTool(llm_config=web_tool_llm_config, **web_tool_kwargs)
|
|
61
|
+
elif web_tool == "duckduckgo":
|
|
62
|
+
self.tool = DuckDuckGoSearchTool(**web_tool_kwargs)
|
|
63
|
+
elif web_tool == "searxng":
|
|
64
|
+
self.tool = SearxngSearchTool(**web_tool_kwargs)
|
|
65
|
+
else:
|
|
66
|
+
raise ValueError(f"Unsupported {web_tool=}.")
|
|
67
|
+
|
|
68
|
+
super().__init__(llm_config=llm_config, **kwargs)
|
|
69
|
+
|
|
70
|
+
self.register_for_llm()(self.tool)
|
|
@@ -0,0 +1,88 @@
|
|
|
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 typing import Any
|
|
6
|
+
|
|
7
|
+
from .... import ConversableAgent
|
|
8
|
+
from ....doc_utils import export_module
|
|
9
|
+
from ....tools.experimental import WikipediaPageLoadTool, WikipediaQueryRunTool
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@export_module("autogen.agents.experimental")
|
|
13
|
+
class WikipediaAgent(ConversableAgent):
|
|
14
|
+
"""An AI agent that leverages Wikipedia tools to provide accurate, concise answers
|
|
15
|
+
to user queries.
|
|
16
|
+
|
|
17
|
+
Tools:
|
|
18
|
+
- WikipediaQueryRunTool: searches Wikipedia for relevant article titles.
|
|
19
|
+
- WikipediaPageLoadTool: loads full Wikipedia pages (and metadata) for in‑depth content.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
_query_run_tool (WikipediaQueryRunTool): for running title/keyword searches.
|
|
23
|
+
_page_load_tool (WikipediaPageLoadTool): for fetching full page content.
|
|
24
|
+
|
|
25
|
+
Parameters:
|
|
26
|
+
system_message (Optional[Union[str, List[str]]]):
|
|
27
|
+
Custom system prompt(s). If None, DEFAULT_SYSTEM_MESSAGE is used.
|
|
28
|
+
Must be a str or a list of strings, otherwise raises ValueError.
|
|
29
|
+
format_instructions (Optional[str]): Extra formatting instructions to append.
|
|
30
|
+
language (str): ISO code for the Wikipedia language edition (default: "en").
|
|
31
|
+
top_k (int): Number of top search results to return (default: 2).
|
|
32
|
+
**kwargs: Passed through to the base ConversableAgent.
|
|
33
|
+
|
|
34
|
+
Raises:
|
|
35
|
+
ValueError: If `system_message` is not a str or list of str.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
DEFAULT_SYSTEM_MESSAGE = (
|
|
39
|
+
"You are a knowledgeable AI assistant with access to Wikipedia.\n"
|
|
40
|
+
"Use your tools when necessary. Respond to user queries by providing accurate and concise information.\n"
|
|
41
|
+
"If a question requires external data, utilize the appropriate tool to retrieve it."
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
def __init__(
|
|
45
|
+
self,
|
|
46
|
+
system_message: str | list[str] | None = None,
|
|
47
|
+
format_instructions: str | None = None,
|
|
48
|
+
language: str = "en",
|
|
49
|
+
top_k: int = 2,
|
|
50
|
+
**kwargs: Any,
|
|
51
|
+
) -> None:
|
|
52
|
+
"""Initialize the WikipediaAgent with optional custom prompts and tools.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
system_message (Optional[Union[str, List[str]]]):
|
|
56
|
+
Custom system prompt(s). If None, DEFAULT_SYSTEM_MESSAGE is used.
|
|
57
|
+
Must be a str or list of strings.
|
|
58
|
+
format_instructions (Optional[str]): Extra formatting instructions to append.
|
|
59
|
+
language (str): Wikipedia language code (default: "en").
|
|
60
|
+
top_k (int): How many top search results to fetch (default: 2).
|
|
61
|
+
**kwargs: Other parameters for ConversableAgent.
|
|
62
|
+
|
|
63
|
+
Raises:
|
|
64
|
+
ValueError: If `system_message` is not a str or list of str.
|
|
65
|
+
"""
|
|
66
|
+
# Use explicit system_message or fall back to default
|
|
67
|
+
system_message = system_message or self.DEFAULT_SYSTEM_MESSAGE
|
|
68
|
+
|
|
69
|
+
# Append formatting instructions if provided
|
|
70
|
+
if format_instructions is not None:
|
|
71
|
+
instructions = f"\n\nFollow this format:\n\n{format_instructions}"
|
|
72
|
+
if isinstance(system_message, list):
|
|
73
|
+
system_message.append(instructions)
|
|
74
|
+
elif isinstance(system_message, str):
|
|
75
|
+
system_message = system_message + instructions
|
|
76
|
+
else:
|
|
77
|
+
raise ValueError(f"system_message must be str or list[str], got {type(system_message).__name__}")
|
|
78
|
+
|
|
79
|
+
# Initialize Wikipedia tools
|
|
80
|
+
self._query_run_tool = WikipediaQueryRunTool(language=language, top_k=top_k)
|
|
81
|
+
self._page_load_tool = WikipediaPageLoadTool(language=language, top_k=top_k)
|
|
82
|
+
|
|
83
|
+
# Initialize the base ConversableAgent
|
|
84
|
+
super().__init__(system_message=system_message, **kwargs)
|
|
85
|
+
|
|
86
|
+
# Register tools for LLM recommendations
|
|
87
|
+
self.register_for_llm()(self._query_run_tool)
|
|
88
|
+
self.register_for_llm()(self._page_load_tool)
|
autogen/browser_utils.py
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
#
|
|
5
|
+
# Portions derived from https://github.com/microsoft/autogen are under the MIT License.
|
|
6
|
+
# SPDX-License-Identifier: MIT
|
|
7
|
+
import io
|
|
8
|
+
import mimetypes
|
|
9
|
+
import os
|
|
10
|
+
import re
|
|
11
|
+
import uuid
|
|
12
|
+
from contextlib import suppress
|
|
13
|
+
from typing import Any
|
|
14
|
+
from urllib.parse import urljoin, urlparse
|
|
15
|
+
|
|
16
|
+
from .import_utils import optional_import_block, require_optional_import
|
|
17
|
+
|
|
18
|
+
with optional_import_block():
|
|
19
|
+
import markdownify
|
|
20
|
+
import requests
|
|
21
|
+
from bs4 import BeautifulSoup
|
|
22
|
+
|
|
23
|
+
# Optional PDF support
|
|
24
|
+
with optional_import_block() as result:
|
|
25
|
+
import pdfminer
|
|
26
|
+
import pdfminer.high_level
|
|
27
|
+
|
|
28
|
+
IS_PDF_CAPABLE = result.is_successful
|
|
29
|
+
|
|
30
|
+
# Other optional dependencies
|
|
31
|
+
with optional_import_block():
|
|
32
|
+
import pathvalidate
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@require_optional_import(["markdownify", "requests", "bs4", "pdfminer", "pathvalidate"], "websurfer")
|
|
36
|
+
class SimpleTextBrowser:
|
|
37
|
+
"""(In preview) An extremely simple text-based web browser comparable to Lynx. Suitable for Agentic use."""
|
|
38
|
+
|
|
39
|
+
def __init__(
|
|
40
|
+
self,
|
|
41
|
+
start_page: str | None = None,
|
|
42
|
+
viewport_size: int | None = 1024 * 8,
|
|
43
|
+
downloads_folder: str | None | None = None,
|
|
44
|
+
bing_base_url: str = "https://api.bing.microsoft.com/v7.0/search",
|
|
45
|
+
bing_api_key: str | None | None = None,
|
|
46
|
+
request_kwargs: dict[str, Any] | None | None = None,
|
|
47
|
+
):
|
|
48
|
+
"""Initialize the browser with the given parameters.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
start_page (Optional[str], optional): The initial page to load. Defaults to None.
|
|
52
|
+
viewport_size (Optional[int], optional): The number of characters to display per page. Defaults to 1024 * 8.
|
|
53
|
+
downloads_folder (Optional[Union[str, None]], optional): The folder to save downloads to. Defaults to None.
|
|
54
|
+
bing_base_url (str, optional): The base URL for Bing searches. Defaults to "https://api.bing.microsoft.com/v7.0/search".
|
|
55
|
+
bing_api_key (Optional[Union[str, None]], optional): The API key for Bing searches. Defaults to None.
|
|
56
|
+
request_kwargs (Optional[Union[dict[str, Any], None]], optional): Additional keyword arguments to pass to the requests library. Defaults to None.
|
|
57
|
+
"""
|
|
58
|
+
self.start_page: str = start_page if start_page else "about:blank"
|
|
59
|
+
self.viewport_size = viewport_size # Applies only to the standard uri types
|
|
60
|
+
self.downloads_folder = downloads_folder
|
|
61
|
+
self.history: list[str] = []
|
|
62
|
+
self.page_title: str | None = None
|
|
63
|
+
self.viewport_current_page = 0
|
|
64
|
+
self.viewport_pages: list[tuple[int, int]] = []
|
|
65
|
+
self.set_address(self.start_page)
|
|
66
|
+
self.bing_base_url = bing_base_url
|
|
67
|
+
self.bing_api_key = bing_api_key
|
|
68
|
+
self.request_kwargs = request_kwargs
|
|
69
|
+
|
|
70
|
+
self._page_content = ""
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def address(self) -> str:
|
|
74
|
+
"""Return the address of the current page."""
|
|
75
|
+
return self.history[-1]
|
|
76
|
+
|
|
77
|
+
def set_address(self, uri_or_path: str) -> None:
|
|
78
|
+
"""Set the address of the current page.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
uri_or_path (str): The URI or path to set as the current page.
|
|
82
|
+
"""
|
|
83
|
+
self.history.append(uri_or_path)
|
|
84
|
+
|
|
85
|
+
# Handle special URIs
|
|
86
|
+
if uri_or_path == "about:blank":
|
|
87
|
+
self._set_page_content("")
|
|
88
|
+
elif uri_or_path.startswith("bing:"):
|
|
89
|
+
self._bing_search(uri_or_path[len("bing:") :].strip())
|
|
90
|
+
else:
|
|
91
|
+
if not uri_or_path.startswith("http:") and not uri_or_path.startswith("https:"):
|
|
92
|
+
uri_or_path = urljoin(self.address, uri_or_path)
|
|
93
|
+
self.history[-1] = uri_or_path # Update the address with the fully-qualified path
|
|
94
|
+
self._fetch_page(uri_or_path)
|
|
95
|
+
|
|
96
|
+
self.viewport_current_page = 0
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def viewport(self) -> str:
|
|
100
|
+
"""Return the content of the current viewport."""
|
|
101
|
+
bounds = self.viewport_pages[self.viewport_current_page]
|
|
102
|
+
return self.page_content[bounds[0] : bounds[1]]
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def page_content(self) -> str:
|
|
106
|
+
"""Return the full contents of the current page."""
|
|
107
|
+
return self._page_content
|
|
108
|
+
|
|
109
|
+
def _set_page_content(self, content: str) -> None:
|
|
110
|
+
"""Sets the text content of the current page."""
|
|
111
|
+
self._page_content = content
|
|
112
|
+
self._split_pages()
|
|
113
|
+
if self.viewport_current_page >= len(self.viewport_pages):
|
|
114
|
+
self.viewport_current_page = len(self.viewport_pages) - 1
|
|
115
|
+
|
|
116
|
+
def page_down(self) -> None:
|
|
117
|
+
"""Move the viewport down by one page."""
|
|
118
|
+
self.viewport_current_page = min(self.viewport_current_page + 1, len(self.viewport_pages) - 1)
|
|
119
|
+
|
|
120
|
+
def page_up(self) -> None:
|
|
121
|
+
"""Move the viewport up by one page."""
|
|
122
|
+
self.viewport_current_page = max(self.viewport_current_page - 1, 0)
|
|
123
|
+
|
|
124
|
+
def visit_page(self, path_or_uri: str) -> str:
|
|
125
|
+
"""Update the address, visit the page, and return the content of the viewport.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
path_or_uri (str): The URI or path to visit.
|
|
129
|
+
"""
|
|
130
|
+
self.set_address(path_or_uri)
|
|
131
|
+
return self.viewport
|
|
132
|
+
|
|
133
|
+
def _split_pages(self) -> None:
|
|
134
|
+
# Split only regular pages
|
|
135
|
+
if not self.address.startswith("http:") and not self.address.startswith("https:"):
|
|
136
|
+
self.viewport_pages = [(0, len(self._page_content))]
|
|
137
|
+
return
|
|
138
|
+
|
|
139
|
+
# Handle empty pages
|
|
140
|
+
if len(self._page_content) == 0:
|
|
141
|
+
self.viewport_pages = [(0, 0)]
|
|
142
|
+
return
|
|
143
|
+
|
|
144
|
+
# Break the viewport into pages
|
|
145
|
+
self.viewport_pages = []
|
|
146
|
+
start_idx = 0
|
|
147
|
+
while start_idx < len(self._page_content):
|
|
148
|
+
end_idx = min(start_idx + self.viewport_size, len(self._page_content)) # type: ignore[operator]
|
|
149
|
+
# Adjust to end on a space
|
|
150
|
+
while end_idx < len(self._page_content) and self._page_content[end_idx - 1] not in [" ", "\t", "\r", "\n"]:
|
|
151
|
+
end_idx += 1
|
|
152
|
+
self.viewport_pages.append((start_idx, end_idx))
|
|
153
|
+
start_idx = end_idx
|
|
154
|
+
|
|
155
|
+
def _bing_api_call(self, query: str) -> dict[str, dict[str, list[dict[str, str | dict[str, str]]]]]:
|
|
156
|
+
# Make sure the key was set
|
|
157
|
+
if self.bing_api_key is None:
|
|
158
|
+
raise ValueError("Missing Bing API key.")
|
|
159
|
+
|
|
160
|
+
# Prepare the request parameters
|
|
161
|
+
request_kwargs = self.request_kwargs.copy() if self.request_kwargs is not None else {}
|
|
162
|
+
|
|
163
|
+
if "headers" not in request_kwargs:
|
|
164
|
+
request_kwargs["headers"] = {}
|
|
165
|
+
request_kwargs["headers"]["Ocp-Apim-Subscription-Key"] = self.bing_api_key
|
|
166
|
+
|
|
167
|
+
if "params" not in request_kwargs:
|
|
168
|
+
request_kwargs["params"] = {}
|
|
169
|
+
request_kwargs["params"]["q"] = query
|
|
170
|
+
request_kwargs["params"]["textDecorations"] = False
|
|
171
|
+
request_kwargs["params"]["textFormat"] = "raw"
|
|
172
|
+
|
|
173
|
+
request_kwargs["stream"] = False
|
|
174
|
+
|
|
175
|
+
# Make the request
|
|
176
|
+
response = requests.get(self.bing_base_url, **request_kwargs)
|
|
177
|
+
response.raise_for_status()
|
|
178
|
+
results = response.json()
|
|
179
|
+
|
|
180
|
+
return results # type: ignore[no-any-return]
|
|
181
|
+
|
|
182
|
+
def _bing_search(self, query: str) -> None:
|
|
183
|
+
results = self._bing_api_call(query)
|
|
184
|
+
|
|
185
|
+
web_snippets: list[str] = []
|
|
186
|
+
idx = 0
|
|
187
|
+
for page in results["webPages"]["value"]:
|
|
188
|
+
idx += 1
|
|
189
|
+
web_snippets.append(f"{idx}. [{page['name']}]({page['url']})\n{page['snippet']}")
|
|
190
|
+
if "deepLinks" in page:
|
|
191
|
+
for dl in page["deepLinks"]:
|
|
192
|
+
idx += 1
|
|
193
|
+
web_snippets.append(
|
|
194
|
+
f"{idx}. [{dl['name']}]({dl['url']})\n{dl.get('snippet', '')}" # type: ignore[index]
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
news_snippets = []
|
|
198
|
+
if "news" in results:
|
|
199
|
+
for page in results["news"]["value"]:
|
|
200
|
+
idx += 1
|
|
201
|
+
news_snippets.append(f"{idx}. [{page['name']}]({page['url']})\n{page['description']}")
|
|
202
|
+
|
|
203
|
+
self.page_title = f"{query} - Search"
|
|
204
|
+
|
|
205
|
+
content = (
|
|
206
|
+
f"A Bing search for '{query}' found {len(web_snippets) + len(news_snippets)} results:\n\n## Web Results\n"
|
|
207
|
+
+ "\n\n".join(web_snippets)
|
|
208
|
+
)
|
|
209
|
+
if len(news_snippets) > 0:
|
|
210
|
+
content += "\n\n## News Results:\n" + "\n\n".join(news_snippets)
|
|
211
|
+
self._set_page_content(content)
|
|
212
|
+
|
|
213
|
+
def _fetch_page(self, url: str) -> None:
|
|
214
|
+
try:
|
|
215
|
+
# Prepare the request parameters
|
|
216
|
+
request_kwargs = self.request_kwargs.copy() if self.request_kwargs is not None else {}
|
|
217
|
+
request_kwargs["stream"] = True
|
|
218
|
+
|
|
219
|
+
# Send a HTTP request to the URL
|
|
220
|
+
response = requests.get(url, **request_kwargs)
|
|
221
|
+
response.raise_for_status()
|
|
222
|
+
|
|
223
|
+
# If the HTTP request returns a status code 200, proceed
|
|
224
|
+
if response.status_code == 200:
|
|
225
|
+
content_type = response.headers.get("content-type", "")
|
|
226
|
+
for ct in ["text/html", "text/plain", "application/pdf"]:
|
|
227
|
+
if ct in content_type.lower():
|
|
228
|
+
content_type = ct
|
|
229
|
+
break
|
|
230
|
+
|
|
231
|
+
if content_type == "text/html":
|
|
232
|
+
# Get the content of the response
|
|
233
|
+
html = ""
|
|
234
|
+
for chunk in response.iter_content(chunk_size=512, decode_unicode=True):
|
|
235
|
+
html += chunk
|
|
236
|
+
|
|
237
|
+
soup = BeautifulSoup(html, "html.parser")
|
|
238
|
+
|
|
239
|
+
# Remove javascript and style blocks
|
|
240
|
+
for script in soup(["script", "style"]):
|
|
241
|
+
script.extract()
|
|
242
|
+
|
|
243
|
+
# Convert to markdown -- Wikipedia gets special attention to get a clean version of the page
|
|
244
|
+
if url.startswith("https://en.wikipedia.org/"):
|
|
245
|
+
body_elm = soup.find("div", {"id": "mw-content-text"})
|
|
246
|
+
title_elm = soup.find("span", {"class": "mw-page-title-main"})
|
|
247
|
+
|
|
248
|
+
if body_elm:
|
|
249
|
+
# What's the title
|
|
250
|
+
main_title = soup.title.string
|
|
251
|
+
if title_elm and len(title_elm) > 0:
|
|
252
|
+
main_title = title_elm.string
|
|
253
|
+
webpage_text = (
|
|
254
|
+
"# " + main_title + "\n\n" + markdownify.MarkdownConverter().convert_soup(body_elm)
|
|
255
|
+
)
|
|
256
|
+
else:
|
|
257
|
+
webpage_text = markdownify.MarkdownConverter().convert_soup(soup)
|
|
258
|
+
else:
|
|
259
|
+
webpage_text = markdownify.MarkdownConverter().convert_soup(soup)
|
|
260
|
+
|
|
261
|
+
# Convert newlines
|
|
262
|
+
webpage_text = re.sub(r"\r\n", "\n", webpage_text)
|
|
263
|
+
|
|
264
|
+
# Remove excessive blank lines
|
|
265
|
+
self.page_title = soup.title.string
|
|
266
|
+
self._set_page_content(re.sub(r"\n{2,}", "\n\n", webpage_text).strip())
|
|
267
|
+
elif content_type == "text/plain":
|
|
268
|
+
# Get the content of the response
|
|
269
|
+
plain_text = ""
|
|
270
|
+
for chunk in response.iter_content(chunk_size=512, decode_unicode=True):
|
|
271
|
+
plain_text += chunk
|
|
272
|
+
|
|
273
|
+
self.page_title = None
|
|
274
|
+
self._set_page_content(plain_text)
|
|
275
|
+
elif IS_PDF_CAPABLE and content_type == "application/pdf":
|
|
276
|
+
pdf_data = io.BytesIO(response.raw.read())
|
|
277
|
+
self.page_title = None
|
|
278
|
+
self._set_page_content(pdfminer.high_level.extract_text(pdf_data))
|
|
279
|
+
elif self.downloads_folder is not None:
|
|
280
|
+
# Try producing a safe filename
|
|
281
|
+
fname = None
|
|
282
|
+
with suppress(NameError):
|
|
283
|
+
fname = pathvalidate.sanitize_filename(os.path.basename(urlparse(url).path)).strip()
|
|
284
|
+
|
|
285
|
+
# No suitable name, so make one
|
|
286
|
+
if fname is None:
|
|
287
|
+
extension = mimetypes.guess_extension(content_type)
|
|
288
|
+
if extension is None:
|
|
289
|
+
extension = ".download"
|
|
290
|
+
fname = str(uuid.uuid4()) + extension
|
|
291
|
+
|
|
292
|
+
# Open a file for writing
|
|
293
|
+
download_path = os.path.abspath(os.path.join(self.downloads_folder, fname))
|
|
294
|
+
with open(download_path, "wb") as fh:
|
|
295
|
+
for chunk in response.iter_content(chunk_size=512):
|
|
296
|
+
fh.write(chunk)
|
|
297
|
+
|
|
298
|
+
# Return a page describing what just happened
|
|
299
|
+
self.page_title = "Download complete."
|
|
300
|
+
self._set_page_content(f"Downloaded '{url}' to '{download_path}'.")
|
|
301
|
+
else:
|
|
302
|
+
self.page_title = f"Error - Unsupported Content-Type '{content_type}'"
|
|
303
|
+
self._set_page_content(self.page_title)
|
|
304
|
+
else:
|
|
305
|
+
self.page_title = "Error"
|
|
306
|
+
self._set_page_content("Failed to retrieve " + url)
|
|
307
|
+
except requests.exceptions.RequestException as e:
|
|
308
|
+
self.page_title = "Error"
|
|
309
|
+
self._set_page_content(str(e))
|
|
@@ -0,0 +1,10 @@
|
|
|
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 .abstract_cache_base import AbstractCache
|
|
8
|
+
from .cache import Cache
|
|
9
|
+
|
|
10
|
+
__all__ = ["AbstractCache", "Cache"]
|