camel-ai 0.2.65__py3-none-any.whl → 0.2.83a6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of camel-ai might be problematic. Click here for more details.
- camel/__init__.py +3 -3
- camel/agents/__init__.py +2 -2
- camel/agents/_types.py +9 -4
- camel/agents/_utils.py +40 -2
- camel/agents/base.py +2 -2
- camel/agents/chat_agent.py +5107 -995
- camel/agents/critic_agent.py +2 -2
- camel/agents/deductive_reasoner_agent.py +56 -56
- camel/agents/embodied_agent.py +2 -2
- camel/agents/knowledge_graph_agent.py +20 -20
- camel/agents/mcp_agent.py +35 -36
- camel/agents/multi_hop_generator_agent.py +3 -3
- camel/agents/programmed_agent_instruction.py +2 -2
- camel/agents/repo_agent.py +4 -3
- camel/agents/role_assignment_agent.py +2 -2
- camel/agents/search_agent.py +2 -2
- camel/agents/task_agent.py +2 -2
- camel/agents/tool_agents/__init__.py +2 -2
- camel/agents/tool_agents/base.py +2 -2
- camel/agents/tool_agents/hugging_face_tool_agent.py +3 -3
- camel/benchmarks/__init__.py +2 -2
- camel/benchmarks/apibank.py +5 -5
- camel/benchmarks/apibench.py +2 -2
- camel/benchmarks/base.py +2 -2
- camel/benchmarks/browsecomp.py +44 -33
- camel/benchmarks/gaia.py +17 -13
- camel/benchmarks/mock_website/README.md +1 -3
- camel/benchmarks/mock_website/mock_web.py +2 -2
- camel/benchmarks/mock_website/requirements.txt +1 -1
- camel/benchmarks/mock_website/shopping_mall/app.py +2 -2
- camel/benchmarks/mock_website/task.json +1 -1
- camel/benchmarks/nexus.py +3 -3
- camel/benchmarks/ragbench.py +2 -2
- camel/bots/__init__.py +2 -2
- camel/bots/discord/__init__.py +2 -2
- camel/bots/discord/discord_app.py +2 -2
- camel/bots/discord/discord_installation.py +2 -2
- camel/bots/discord/discord_store.py +3 -3
- camel/bots/slack/__init__.py +2 -2
- camel/bots/slack/models.py +4 -4
- camel/bots/slack/slack_app.py +2 -2
- camel/bots/telegram_bot.py +2 -2
- camel/configs/__init__.py +29 -2
- camel/configs/aihubmix_config.py +90 -0
- camel/configs/aiml_config.py +2 -2
- camel/configs/amd_config.py +70 -0
- camel/configs/anthropic_config.py +2 -2
- camel/configs/base_config.py +2 -2
- camel/configs/bedrock_config.py +5 -3
- camel/configs/cerebras_config.py +98 -0
- camel/configs/cohere_config.py +2 -2
- camel/configs/cometapi_config.py +106 -0
- camel/configs/crynux_config.py +2 -2
- camel/configs/deepseek_config.py +9 -8
- camel/configs/function_gemma_config.py +59 -0
- camel/configs/gemini_config.py +6 -4
- camel/configs/groq_config.py +6 -4
- camel/configs/internlm_config.py +6 -4
- camel/configs/litellm_config.py +2 -2
- camel/configs/lmstudio_config.py +6 -4
- camel/configs/minimax_config.py +95 -0
- camel/configs/mistral_config.py +2 -2
- camel/configs/modelscope_config.py +5 -3
- camel/configs/moonshot_config.py +2 -2
- camel/configs/nebius_config.py +105 -0
- camel/configs/netmind_config.py +2 -2
- camel/configs/novita_config.py +2 -2
- camel/configs/nvidia_config.py +2 -2
- camel/configs/ollama_config.py +2 -2
- camel/configs/openai_config.py +5 -3
- camel/configs/openrouter_config.py +6 -4
- camel/configs/ppio_config.py +2 -2
- camel/configs/qianfan_config.py +85 -0
- camel/configs/qwen_config.py +2 -2
- camel/configs/reka_config.py +2 -2
- camel/configs/samba_config.py +6 -4
- camel/configs/sglang_config.py +2 -2
- camel/configs/siliconflow_config.py +2 -2
- camel/configs/togetherai_config.py +2 -2
- camel/configs/vllm_config.py +4 -2
- camel/configs/watsonx_config.py +2 -2
- camel/configs/yi_config.py +6 -4
- camel/configs/zhipuai_config.py +6 -4
- camel/data_collectors/__init__.py +2 -2
- camel/data_collectors/alpaca_collector.py +18 -9
- camel/data_collectors/base.py +2 -2
- camel/data_collectors/sharegpt_collector.py +2 -2
- camel/datagen/__init__.py +2 -2
- camel/datagen/cot_datagen.py +3 -3
- camel/datagen/evol_instruct/__init__.py +2 -2
- camel/datagen/evol_instruct/evol_instruct.py +2 -2
- camel/datagen/evol_instruct/scorer.py +12 -12
- camel/datagen/evol_instruct/templates.py +16 -16
- camel/datagen/self_improving_cot.py +5 -5
- camel/datagen/self_instruct/__init__.py +2 -2
- camel/datagen/self_instruct/filter/__init__.py +2 -2
- camel/datagen/self_instruct/filter/filter_function.py +2 -2
- camel/datagen/self_instruct/filter/filter_registry.py +2 -2
- camel/datagen/self_instruct/filter/instruction_filter.py +2 -2
- camel/datagen/self_instruct/self_instruct.py +2 -2
- camel/datagen/self_instruct/templates.py +47 -47
- camel/datagen/source2synth/__init__.py +2 -2
- camel/datagen/source2synth/data_processor.py +2 -2
- camel/datagen/source2synth/models.py +2 -2
- camel/datagen/source2synth/user_data_processor_config.py +2 -2
- camel/datahubs/__init__.py +2 -2
- camel/datahubs/base.py +2 -2
- camel/datahubs/huggingface.py +2 -2
- camel/datahubs/models.py +2 -2
- camel/datasets/__init__.py +2 -2
- camel/datasets/base_generator.py +41 -12
- camel/datasets/few_shot_generator.py +18 -18
- camel/datasets/models.py +2 -2
- camel/datasets/self_instruct_generator.py +2 -2
- camel/datasets/static_dataset.py +2 -2
- camel/embeddings/__init__.py +2 -2
- camel/embeddings/azure_embedding.py +2 -2
- camel/embeddings/base.py +2 -2
- camel/embeddings/gemini_embedding.py +2 -2
- camel/embeddings/jina_embedding.py +2 -2
- camel/embeddings/mistral_embedding.py +2 -2
- camel/embeddings/openai_compatible_embedding.py +2 -2
- camel/embeddings/openai_embedding.py +2 -2
- camel/embeddings/sentence_transformers_embeddings.py +2 -2
- camel/embeddings/together_embedding.py +2 -2
- camel/embeddings/vlm_embedding.py +2 -2
- camel/environments/__init__.py +14 -2
- camel/environments/models.py +2 -2
- camel/environments/multi_step.py +2 -2
- camel/environments/rlcards_env.py +860 -0
- camel/environments/single_step.py +30 -5
- camel/environments/tic_tac_toe.py +3 -3
- camel/extractors/__init__.py +2 -2
- camel/extractors/base.py +2 -2
- camel/extractors/python_strategies.py +2 -2
- camel/generators.py +2 -2
- camel/human.py +2 -2
- camel/interpreters/__init__.py +4 -2
- camel/interpreters/base.py +2 -2
- camel/interpreters/docker/Dockerfile +14 -24
- camel/interpreters/docker_interpreter.py +5 -4
- camel/interpreters/e2b_interpreter.py +36 -3
- camel/interpreters/internal_python_interpreter.py +53 -4
- camel/interpreters/interpreter_error.py +2 -2
- camel/interpreters/ipython_interpreter.py +2 -2
- camel/interpreters/microsandbox_interpreter.py +395 -0
- camel/interpreters/subprocess_interpreter.py +2 -2
- camel/loaders/__init__.py +13 -4
- camel/loaders/apify_reader.py +2 -2
- camel/loaders/base_io.py +2 -2
- camel/loaders/base_loader.py +85 -0
- camel/loaders/chunkr_reader.py +11 -2
- camel/loaders/crawl4ai_reader.py +2 -2
- camel/loaders/firecrawl_reader.py +6 -6
- camel/loaders/jina_url_reader.py +2 -2
- camel/loaders/markitdown.py +2 -2
- camel/loaders/mineru_extractor.py +2 -2
- camel/loaders/mistral_reader.py +2 -2
- camel/loaders/scrapegraph_reader.py +2 -2
- camel/loaders/unstructured_io.py +2 -2
- camel/logger.py +5 -5
- camel/memories/__init__.py +2 -2
- camel/memories/agent_memories.py +86 -3
- camel/memories/base.py +36 -2
- camel/memories/blocks/__init__.py +2 -2
- camel/memories/blocks/chat_history_block.py +125 -7
- camel/memories/blocks/vectordb_block.py +10 -3
- camel/memories/context_creators/__init__.py +2 -2
- camel/memories/context_creators/score_based.py +109 -230
- camel/memories/records.py +90 -10
- camel/messages/__init__.py +2 -2
- camel/messages/base.py +178 -43
- camel/messages/conversion/__init__.py +2 -2
- camel/messages/conversion/alpaca.py +2 -2
- camel/messages/conversion/conversation_models.py +2 -2
- camel/messages/conversion/sharegpt/__init__.py +2 -2
- camel/messages/conversion/sharegpt/function_call_formatter.py +2 -2
- camel/messages/conversion/sharegpt/hermes/__init__.py +2 -2
- camel/messages/conversion/sharegpt/hermes/hermes_function_formatter.py +2 -2
- camel/messages/func_message.py +54 -17
- camel/models/__init__.py +18 -2
- camel/models/_utils.py +3 -3
- camel/models/aihubmix_model.py +83 -0
- camel/models/aiml_model.py +11 -18
- camel/models/amd_model.py +101 -0
- camel/models/anthropic_model.py +127 -20
- camel/models/aws_bedrock_model.py +12 -35
- camel/models/azure_openai_model.py +214 -115
- camel/models/base_audio_model.py +5 -3
- camel/models/base_model.py +378 -31
- camel/models/cerebras_model.py +83 -0
- camel/models/cohere_model.py +18 -49
- camel/models/cometapi_model.py +83 -0
- camel/models/crynux_model.py +11 -18
- camel/models/deepseek_model.py +20 -84
- camel/models/fish_audio_model.py +8 -2
- camel/models/function_gemma_model.py +889 -0
- camel/models/gemini_model.py +391 -52
- camel/models/groq_model.py +11 -19
- camel/models/internlm_model.py +11 -18
- camel/models/litellm_model.py +57 -49
- camel/models/lmstudio_model.py +17 -20
- camel/models/minimax_model.py +83 -0
- camel/models/mistral_model.py +20 -47
- camel/models/model_factory.py +39 -3
- camel/models/model_manager.py +26 -8
- camel/models/modelscope_model.py +13 -193
- camel/models/moonshot_model.py +183 -21
- camel/models/nebius_model.py +83 -0
- camel/models/nemotron_model.py +19 -9
- camel/models/netmind_model.py +11 -18
- camel/models/novita_model.py +11 -18
- camel/models/nvidia_model.py +11 -18
- camel/models/ollama_model.py +14 -21
- camel/models/openai_audio_models.py +2 -2
- camel/models/openai_compatible_model.py +190 -71
- camel/models/openai_model.py +192 -86
- camel/models/openrouter_model.py +11 -19
- camel/models/ppio_model.py +11 -18
- camel/models/qianfan_model.py +89 -0
- camel/models/qwen_model.py +13 -193
- camel/models/reka_model.py +23 -49
- camel/models/reward/__init__.py +2 -2
- camel/models/reward/base_reward_model.py +2 -2
- camel/models/reward/evaluator.py +2 -2
- camel/models/reward/nemotron_model.py +2 -2
- camel/models/reward/skywork_model.py +2 -2
- camel/models/samba_model.py +50 -75
- camel/models/sglang_model.py +90 -68
- camel/models/siliconflow_model.py +12 -35
- camel/models/stub_model.py +10 -7
- camel/models/togetherai_model.py +11 -18
- camel/models/vllm_model.py +10 -18
- camel/models/volcano_model.py +158 -19
- camel/models/watsonx_model.py +9 -47
- camel/models/yi_model.py +11 -18
- camel/models/zhipuai_model.py +70 -18
- camel/parsers/__init__.py +18 -0
- camel/parsers/mcp_tool_call_parser.py +176 -0
- camel/personas/__init__.py +2 -2
- camel/personas/persona.py +2 -2
- camel/personas/persona_hub.py +2 -2
- camel/prompts/__init__.py +2 -2
- camel/prompts/ai_society.py +2 -2
- camel/prompts/base.py +2 -2
- camel/prompts/code.py +2 -2
- camel/prompts/evaluation.py +2 -2
- camel/prompts/generate_text_embedding_data.py +2 -2
- camel/prompts/image_craft.py +2 -2
- camel/prompts/misalignment.py +2 -2
- camel/prompts/multi_condition_image_craft.py +2 -2
- camel/prompts/object_recognition.py +2 -2
- camel/prompts/persona_hub.py +3 -3
- camel/prompts/prompt_templates.py +2 -2
- camel/prompts/role_description_prompt_template.py +2 -2
- camel/prompts/solution_extraction.py +8 -8
- camel/prompts/task_prompt_template.py +2 -2
- camel/prompts/translation.py +2 -2
- camel/prompts/video_description_prompt.py +3 -3
- camel/responses/__init__.py +2 -2
- camel/responses/agent_responses.py +2 -2
- camel/retrievers/__init__.py +2 -2
- camel/retrievers/auto_retriever.py +3 -2
- camel/retrievers/base.py +2 -2
- camel/retrievers/bm25_retriever.py +2 -2
- camel/retrievers/cohere_rerank_retriever.py +2 -2
- camel/retrievers/hybrid_retrival.py +2 -2
- camel/retrievers/vector_retriever.py +2 -2
- camel/runtimes/Dockerfile.multi-toolkit +90 -0
- camel/runtimes/__init__.py +2 -2
- camel/runtimes/api.py +79 -23
- camel/runtimes/base.py +2 -2
- camel/runtimes/configs.py +13 -13
- camel/runtimes/daytona_runtime.py +17 -18
- camel/runtimes/docker_runtime.py +12 -12
- camel/runtimes/llm_guard_runtime.py +26 -26
- camel/runtimes/remote_http_runtime.py +11 -11
- camel/runtimes/ubuntu_docker_runtime.py +2 -2
- camel/runtimes/utils/__init__.py +2 -2
- camel/runtimes/utils/function_risk_toolkit.py +2 -2
- camel/runtimes/utils/ignore_risk_toolkit.py +2 -2
- camel/schemas/__init__.py +2 -2
- camel/schemas/base.py +2 -2
- camel/schemas/openai_converter.py +3 -3
- camel/schemas/outlines_converter.py +2 -2
- camel/services/agent_openapi_server.py +380 -0
- camel/societies/__init__.py +4 -2
- camel/societies/babyagi_playing.py +2 -2
- camel/societies/role_playing.py +201 -80
- camel/societies/workforce/__init__.py +10 -3
- camel/societies/workforce/base.py +2 -2
- camel/societies/workforce/events.py +145 -0
- camel/societies/workforce/prompts.py +259 -33
- camel/societies/workforce/role_playing_worker.py +88 -31
- camel/societies/workforce/single_agent_worker.py +638 -40
- camel/societies/workforce/structured_output_handler.py +512 -0
- camel/societies/workforce/task_channel.py +182 -38
- camel/societies/workforce/utils.py +780 -65
- camel/societies/workforce/worker.py +92 -26
- camel/societies/workforce/workflow_memory_manager.py +1746 -0
- camel/societies/workforce/workforce.py +5354 -372
- camel/societies/workforce/workforce_callback.py +103 -0
- camel/societies/workforce/workforce_logger.py +647 -0
- camel/societies/workforce/workforce_metrics.py +33 -0
- camel/storages/__init__.py +6 -2
- camel/storages/graph_storages/__init__.py +2 -2
- camel/storages/graph_storages/base.py +2 -2
- camel/storages/graph_storages/graph_element.py +2 -2
- camel/storages/graph_storages/nebula_graph.py +4 -4
- camel/storages/graph_storages/neo4j_graph.py +7 -7
- camel/storages/key_value_storages/__init__.py +2 -2
- camel/storages/key_value_storages/base.py +2 -2
- camel/storages/key_value_storages/in_memory.py +2 -2
- camel/storages/key_value_storages/json.py +17 -4
- camel/storages/key_value_storages/mem0_cloud.py +50 -49
- camel/storages/key_value_storages/redis.py +2 -2
- camel/storages/object_storages/__init__.py +2 -2
- camel/storages/object_storages/amazon_s3.py +2 -2
- camel/storages/object_storages/azure_blob.py +2 -2
- camel/storages/object_storages/base.py +2 -2
- camel/storages/object_storages/google_cloud.py +3 -3
- camel/storages/vectordb_storages/__init__.py +8 -2
- camel/storages/vectordb_storages/base.py +2 -2
- camel/storages/vectordb_storages/chroma.py +731 -0
- camel/storages/vectordb_storages/faiss.py +2 -2
- camel/storages/vectordb_storages/milvus.py +2 -2
- camel/storages/vectordb_storages/oceanbase.py +15 -15
- camel/storages/vectordb_storages/pgvector.py +349 -0
- camel/storages/vectordb_storages/qdrant.py +6 -6
- camel/storages/vectordb_storages/surreal.py +372 -0
- camel/storages/vectordb_storages/tidb.py +11 -8
- camel/storages/vectordb_storages/weaviate.py +2 -2
- camel/tasks/__init__.py +2 -2
- camel/tasks/task.py +348 -26
- camel/tasks/task_prompt.py +3 -3
- camel/terminators/__init__.py +2 -2
- camel/terminators/base.py +2 -2
- camel/terminators/response_terminator.py +2 -2
- camel/terminators/token_limit_terminator.py +2 -2
- camel/toolkits/__init__.py +57 -10
- camel/toolkits/aci_toolkit.py +66 -21
- camel/toolkits/arxiv_toolkit.py +8 -8
- camel/toolkits/ask_news_toolkit.py +2 -2
- camel/toolkits/async_browser_toolkit.py +4 -4
- camel/toolkits/audio_analysis_toolkit.py +3 -3
- camel/toolkits/base.py +106 -6
- camel/toolkits/bohrium_toolkit.py +2 -2
- camel/toolkits/browser_toolkit.py +34 -21
- camel/toolkits/browser_toolkit_commons.py +4 -4
- camel/toolkits/code_execution.py +31 -4
- camel/toolkits/context_summarizer_toolkit.py +684 -0
- camel/toolkits/craw4ai_toolkit.py +93 -0
- camel/toolkits/dappier_toolkit.py +12 -8
- camel/toolkits/data_commons_toolkit.py +2 -2
- camel/toolkits/dingtalk.py +1135 -0
- camel/toolkits/earth_science_toolkit.py +5367 -0
- camel/toolkits/edgeone_pages_mcp_toolkit.py +49 -0
- camel/toolkits/excel_toolkit.py +905 -71
- camel/toolkits/file_toolkit.py +1402 -0
- camel/toolkits/function_tool.py +205 -27
- camel/toolkits/github_toolkit.py +109 -22
- camel/toolkits/gmail_toolkit.py +1839 -0
- camel/toolkits/google_calendar_toolkit.py +40 -6
- camel/toolkits/google_drive_mcp_toolkit.py +54 -0
- camel/toolkits/google_maps_toolkit.py +2 -2
- camel/toolkits/google_scholar_toolkit.py +2 -2
- camel/toolkits/human_toolkit.py +36 -12
- camel/toolkits/hybrid_browser_toolkit/__init__.py +18 -0
- camel/toolkits/hybrid_browser_toolkit/config_loader.py +185 -0
- camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit.py +246 -0
- camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit_ts.py +1958 -0
- camel/toolkits/hybrid_browser_toolkit/installer.py +203 -0
- camel/toolkits/hybrid_browser_toolkit/ts/package-lock.json +4589 -0
- camel/toolkits/hybrid_browser_toolkit/ts/package.json +33 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/browser-scripts.js +125 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/browser-session.ts +1940 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/config-loader.ts +233 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/hybrid-browser-toolkit.ts +589 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/index.ts +7 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/parent-child-filter.ts +226 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/snapshot-parser.ts +219 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/som-screenshot-injected.ts +543 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/types.ts +129 -0
- camel/toolkits/hybrid_browser_toolkit/ts/tsconfig.json +27 -0
- camel/toolkits/hybrid_browser_toolkit/ts/websocket-server.js +325 -0
- camel/toolkits/hybrid_browser_toolkit/ws_wrapper.py +1037 -0
- camel/toolkits/hybrid_browser_toolkit_py/__init__.py +17 -0
- camel/toolkits/hybrid_browser_toolkit_py/actions.py +575 -0
- camel/toolkits/hybrid_browser_toolkit_py/agent.py +311 -0
- camel/toolkits/hybrid_browser_toolkit_py/browser_session.py +787 -0
- camel/toolkits/hybrid_browser_toolkit_py/config_loader.py +490 -0
- camel/toolkits/hybrid_browser_toolkit_py/hybrid_browser_toolkit.py +2390 -0
- camel/toolkits/hybrid_browser_toolkit_py/snapshot.py +233 -0
- camel/toolkits/hybrid_browser_toolkit_py/stealth_script.js +0 -0
- camel/toolkits/hybrid_browser_toolkit_py/unified_analyzer.js +1043 -0
- camel/toolkits/image_analysis_toolkit.py +3 -6
- camel/toolkits/image_generation_toolkit.py +390 -0
- camel/toolkits/jina_reranker_toolkit.py +5 -6
- camel/toolkits/klavis_toolkit.py +7 -3
- camel/toolkits/linkedin_toolkit.py +2 -2
- camel/toolkits/markitdown_toolkit.py +104 -0
- camel/toolkits/math_toolkit.py +66 -12
- camel/toolkits/mcp_toolkit.py +412 -36
- camel/toolkits/memory_toolkit.py +7 -3
- camel/toolkits/meshy_toolkit.py +2 -2
- camel/toolkits/message_agent_toolkit.py +608 -0
- camel/toolkits/message_integration.py +728 -0
- camel/toolkits/microsoft_outlook_mail_toolkit.py +1885 -0
- camel/toolkits/mineru_toolkit.py +2 -2
- camel/toolkits/minimax_mcp_toolkit.py +195 -0
- camel/toolkits/networkx_toolkit.py +2 -2
- camel/toolkits/note_taking_toolkit.py +277 -0
- camel/toolkits/notion_mcp_toolkit.py +224 -0
- camel/toolkits/notion_toolkit.py +2 -2
- camel/toolkits/open_api_specs/biztoc/__init__.py +2 -2
- camel/toolkits/open_api_specs/biztoc/ai-plugin.json +1 -1
- camel/toolkits/open_api_specs/coursera/__init__.py +2 -2
- camel/toolkits/open_api_specs/create_qr_code/__init__.py +2 -2
- camel/toolkits/open_api_specs/klarna/__init__.py +2 -2
- camel/toolkits/open_api_specs/nasa_apod/__init__.py +2 -2
- camel/toolkits/open_api_specs/outschool/__init__.py +2 -2
- camel/toolkits/open_api_specs/outschool/ai-plugin.json +1 -1
- camel/toolkits/open_api_specs/outschool/openapi.yaml +1 -1
- camel/toolkits/open_api_specs/outschool/paths/__init__.py +2 -2
- camel/toolkits/open_api_specs/outschool/paths/get_classes.py +2 -2
- camel/toolkits/open_api_specs/outschool/paths/search_teachers.py +2 -2
- camel/toolkits/open_api_specs/security_config.py +2 -2
- camel/toolkits/open_api_specs/speak/__init__.py +2 -2
- camel/toolkits/open_api_specs/web_scraper/__init__.py +2 -2
- camel/toolkits/open_api_specs/web_scraper/ai-plugin.json +1 -1
- camel/toolkits/open_api_specs/web_scraper/paths/__init__.py +2 -2
- camel/toolkits/open_api_specs/web_scraper/paths/scraper.py +2 -2
- camel/toolkits/open_api_toolkit.py +2 -2
- camel/toolkits/openbb_toolkit.py +7 -3
- camel/toolkits/origene_mcp_toolkit.py +56 -0
- camel/toolkits/page_script.js +53 -53
- camel/toolkits/playwright_mcp_toolkit.py +13 -31
- camel/toolkits/pptx_toolkit.py +36 -23
- camel/toolkits/pubmed_toolkit.py +2 -2
- camel/toolkits/pulse_mcp_search_toolkit.py +2 -2
- camel/toolkits/pyautogui_toolkit.py +2 -2
- camel/toolkits/reddit_toolkit.py +2 -2
- camel/toolkits/resend_toolkit.py +168 -0
- camel/toolkits/retrieval_toolkit.py +2 -2
- camel/toolkits/screenshot_toolkit.py +213 -0
- camel/toolkits/search_toolkit.py +606 -156
- camel/toolkits/searxng_toolkit.py +2 -2
- camel/toolkits/semantic_scholar_toolkit.py +2 -2
- camel/toolkits/slack_toolkit.py +108 -58
- camel/toolkits/sql_toolkit.py +712 -0
- camel/toolkits/stripe_toolkit.py +2 -2
- camel/toolkits/sympy_toolkit.py +3 -3
- camel/toolkits/task_planning_toolkit.py +5 -5
- camel/toolkits/terminal_toolkit/__init__.py +18 -0
- camel/toolkits/terminal_toolkit/terminal_toolkit.py +1281 -0
- camel/toolkits/terminal_toolkit/utils.py +659 -0
- camel/toolkits/thinking_toolkit.py +3 -3
- camel/toolkits/twitter_toolkit.py +2 -2
- camel/toolkits/vertex_ai_veo_toolkit.py +590 -0
- camel/toolkits/video_analysis_toolkit.py +109 -29
- camel/toolkits/video_download_toolkit.py +19 -16
- camel/toolkits/weather_toolkit.py +2 -2
- camel/toolkits/web_deploy_toolkit.py +1219 -0
- camel/toolkits/wechat_official_toolkit.py +483 -0
- camel/toolkits/whatsapp_toolkit.py +2 -2
- camel/toolkits/wolfram_alpha_toolkit.py +2 -2
- camel/toolkits/zapier_toolkit.py +7 -3
- camel/types/__init__.py +4 -4
- camel/types/agents/__init__.py +2 -2
- camel/types/agents/tool_calling_record.py +6 -3
- camel/types/enums.py +381 -41
- camel/types/mcp_registries.py +2 -2
- camel/types/openai_types.py +4 -4
- camel/types/unified_model_type.py +46 -10
- camel/utils/__init__.py +5 -2
- camel/utils/agent_context.py +41 -0
- camel/utils/async_func.py +2 -2
- camel/utils/chunker/__init__.py +2 -2
- camel/utils/chunker/base.py +2 -2
- camel/utils/chunker/code_chunker.py +2 -2
- camel/utils/chunker/uio_chunker.py +2 -2
- camel/utils/commons.py +38 -7
- camel/utils/constants.py +5 -2
- camel/utils/context_utils.py +1134 -0
- camel/utils/deduplication.py +2 -2
- camel/utils/filename.py +2 -2
- camel/utils/langfuse.py +18 -10
- camel/utils/mcp.py +140 -6
- camel/utils/mcp_client.py +48 -38
- camel/utils/message_summarizer.py +148 -0
- camel/utils/response_format.py +2 -2
- camel/utils/token_counting.py +45 -22
- camel/utils/tool_result.py +44 -0
- camel/verifiers/__init__.py +2 -2
- camel/verifiers/base.py +2 -2
- camel/verifiers/math_verifier.py +2 -2
- camel/verifiers/models.py +2 -2
- camel/verifiers/physics_verifier.py +2 -2
- camel/verifiers/python_verifier.py +2 -2
- {camel_ai-0.2.65.dist-info → camel_ai-0.2.83a6.dist-info}/METADATA +355 -117
- camel_ai-0.2.83a6.dist-info/RECORD +511 -0
- {camel_ai-0.2.65.dist-info → camel_ai-0.2.83a6.dist-info}/WHEEL +1 -1
- {camel_ai-0.2.65.dist-info → camel_ai-0.2.83a6.dist-info}/licenses/LICENSE +1 -1
- camel/loaders/pandas_reader.py +0 -368
- camel/toolkits/dalle_toolkit.py +0 -175
- camel/toolkits/file_write_toolkit.py +0 -444
- camel/toolkits/openai_agent_toolkit.py +0 -135
- camel/toolkits/terminal_toolkit.py +0 -1037
- camel_ai-0.2.65.dist-info/RECORD +0 -426
|
@@ -0,0 +1,608 @@
|
|
|
1
|
+
# ========= Copyright 2023-2026 @ CAMEL-AI.org. All Rights Reserved. =========
|
|
2
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
# you may not use this file except in compliance with the License.
|
|
4
|
+
# You may obtain a copy of the License at
|
|
5
|
+
#
|
|
6
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
#
|
|
8
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
# See the License for the specific language governing permissions and
|
|
12
|
+
# limitations under the License.
|
|
13
|
+
# ========= Copyright 2023-2026 @ CAMEL-AI.org. All Rights Reserved. =========
|
|
14
|
+
|
|
15
|
+
import json
|
|
16
|
+
import time
|
|
17
|
+
import uuid
|
|
18
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
|
19
|
+
|
|
20
|
+
from camel.logger import get_logger
|
|
21
|
+
from camel.messages import BaseMessage
|
|
22
|
+
from camel.toolkits.base import BaseToolkit
|
|
23
|
+
from camel.toolkits.function_tool import FunctionTool
|
|
24
|
+
from camel.types import RoleType
|
|
25
|
+
|
|
26
|
+
if TYPE_CHECKING:
|
|
27
|
+
from camel.agents import ChatAgent
|
|
28
|
+
|
|
29
|
+
logger = get_logger(__name__)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class AgentMessage(BaseMessage):
|
|
33
|
+
r"""Represents a message between agents, extending BaseMessage.
|
|
34
|
+
|
|
35
|
+
This class extends the standard CAMEL BaseMessage with additional
|
|
36
|
+
attributes needed for inter-agent communication.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(
|
|
40
|
+
self,
|
|
41
|
+
message_id: str,
|
|
42
|
+
sender_id: str,
|
|
43
|
+
receiver_id: str,
|
|
44
|
+
content: str,
|
|
45
|
+
timestamp: float,
|
|
46
|
+
reply_to: Optional[str] = None,
|
|
47
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
48
|
+
):
|
|
49
|
+
# Initialize BaseMessage with standard fields
|
|
50
|
+
super().__init__(
|
|
51
|
+
role_name=sender_id,
|
|
52
|
+
role_type=RoleType.ASSISTANT,
|
|
53
|
+
meta_dict=metadata or {},
|
|
54
|
+
content=content,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# Add agent-specific fields
|
|
58
|
+
self.id = message_id
|
|
59
|
+
self.sender_id = sender_id
|
|
60
|
+
self.receiver_id = receiver_id
|
|
61
|
+
self.timestamp = timestamp
|
|
62
|
+
self.reply_to = reply_to
|
|
63
|
+
self.metadata = metadata or {}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class AgentCommunicationToolkit(BaseToolkit):
|
|
67
|
+
r"""A toolkit for agent-to-agent communication in multi-agent systems.
|
|
68
|
+
|
|
69
|
+
Enables agents to send messages to each other with message history tracking
|
|
70
|
+
and integration with the CAMEL workforce system.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
agents (Optional[Dict[str, ChatAgent]]): Dictionary mapping agent IDs
|
|
74
|
+
to ChatAgent instances. (default: :obj:`None`)
|
|
75
|
+
timeout (Optional[float]): Maximum execution time for operations in
|
|
76
|
+
seconds. (default: :obj:`None`)
|
|
77
|
+
max_message_history (int): Maximum messages to keep per agent.
|
|
78
|
+
(default: :obj:`100`)
|
|
79
|
+
get_response (bool): Whether to get responses from receiving agents
|
|
80
|
+
by default. (default: :obj:`False`)
|
|
81
|
+
|
|
82
|
+
Example:
|
|
83
|
+
>>> msg_toolkit = AgentCommunicationToolkit(get_response=False)
|
|
84
|
+
>>> msg_toolkit.register_agent("agent1", agent1)
|
|
85
|
+
>>> msg_toolkit.register_agent("agent2", agent2)
|
|
86
|
+
>>>
|
|
87
|
+
>>> # Add tools to agents
|
|
88
|
+
>>> for tool in msg_toolkit.get_tools():
|
|
89
|
+
... agent1.add_tool(tool)
|
|
90
|
+
... agent2.add_tool(tool)
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
def __init__(
|
|
94
|
+
self,
|
|
95
|
+
agents: Optional[Dict[str, "ChatAgent"]] = None,
|
|
96
|
+
timeout: Optional[float] = None,
|
|
97
|
+
max_message_history: int = 100,
|
|
98
|
+
get_response: bool = False,
|
|
99
|
+
) -> None:
|
|
100
|
+
super().__init__(timeout=timeout)
|
|
101
|
+
self.agents = agents or {}
|
|
102
|
+
self.max_message_history = max_message_history
|
|
103
|
+
self.get_response = get_response
|
|
104
|
+
|
|
105
|
+
# Message management
|
|
106
|
+
self._message_history: Dict[str, List[AgentMessage]] = {}
|
|
107
|
+
self._conversation_threads: Dict[str, List[str]] = {}
|
|
108
|
+
|
|
109
|
+
logger.info(
|
|
110
|
+
f"AgentCommunicationToolkit initialized with {len(self.agents)} "
|
|
111
|
+
f"agents. "
|
|
112
|
+
f"Max history: {max_message_history}, Get response: {get_response}"
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
def register_agent(self, agent_id: str, agent: "ChatAgent") -> str:
|
|
116
|
+
r"""Register a new agent for communication.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
agent_id (str): Unique identifier for the agent.
|
|
120
|
+
agent (ChatAgent): The ChatAgent instance to register.
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
str: Confirmation message with registration details.
|
|
124
|
+
|
|
125
|
+
Raises:
|
|
126
|
+
ValueError: If agent_id is empty or agent is None.
|
|
127
|
+
"""
|
|
128
|
+
if agent_id in self.agents:
|
|
129
|
+
logger.warning(f"Agent {agent_id} already exists, overwriting")
|
|
130
|
+
|
|
131
|
+
self.agents[agent_id] = agent
|
|
132
|
+
|
|
133
|
+
# Initialize message history for new agent
|
|
134
|
+
if agent_id not in self._message_history:
|
|
135
|
+
self._message_history[agent_id] = []
|
|
136
|
+
|
|
137
|
+
logger.info(f"Registered agent: {agent_id}")
|
|
138
|
+
return (
|
|
139
|
+
f"Agent {agent_id} registered successfully. "
|
|
140
|
+
f"Total agents: {len(self.agents)}"
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
def _find_agent_id(self, agent_id: str) -> Optional[str]:
|
|
144
|
+
r"""Find agent ID with flexible matching (case-insensitive, partial
|
|
145
|
+
matches).
|
|
146
|
+
"""
|
|
147
|
+
# First try exact match
|
|
148
|
+
if agent_id in self.agents:
|
|
149
|
+
return agent_id
|
|
150
|
+
|
|
151
|
+
# Try case-insensitive exact match
|
|
152
|
+
agent_id_lower = agent_id.lower()
|
|
153
|
+
for registered_id in self.agents.keys():
|
|
154
|
+
if registered_id.lower() == agent_id_lower:
|
|
155
|
+
return registered_id
|
|
156
|
+
|
|
157
|
+
# Try partial matching for common patterns like "writer_01" -> "Writer"
|
|
158
|
+
# Remove common suffixes and prefixes
|
|
159
|
+
clean_id = agent_id_lower
|
|
160
|
+
|
|
161
|
+
# Remove common patterns: _01, _123, _agent, etc.
|
|
162
|
+
import re
|
|
163
|
+
|
|
164
|
+
clean_id = re.sub(r'_\d+$', '', clean_id) # Remove trailing _numbers
|
|
165
|
+
clean_id = re.sub(r'_agent$', '', clean_id) # Remove trailing _agent
|
|
166
|
+
clean_id = re.sub(r'^agent_', '', clean_id) # Remove leading agent_
|
|
167
|
+
|
|
168
|
+
# Try to match cleaned ID
|
|
169
|
+
for registered_id in self.agents.keys():
|
|
170
|
+
if registered_id.lower() == clean_id:
|
|
171
|
+
return registered_id
|
|
172
|
+
# Also try if the registered ID starts with our cleaned ID
|
|
173
|
+
if registered_id.lower().startswith(clean_id):
|
|
174
|
+
return registered_id
|
|
175
|
+
|
|
176
|
+
return None
|
|
177
|
+
|
|
178
|
+
def send_message(
|
|
179
|
+
self,
|
|
180
|
+
message: str,
|
|
181
|
+
receiver_id: str,
|
|
182
|
+
sender_id: str = "system",
|
|
183
|
+
reply_to: Optional[str] = None,
|
|
184
|
+
metadata_json: Optional[str] = None,
|
|
185
|
+
) -> str:
|
|
186
|
+
r"""Sends a message to a specific agent.
|
|
187
|
+
|
|
188
|
+
This function allows one agent to communicate directly with another by
|
|
189
|
+
sending a message. The toolkit's get_response setting determines
|
|
190
|
+
whether to get an immediate response or just send a notification. To
|
|
191
|
+
get the `receiver_id` of the agent you want to communicate with, you
|
|
192
|
+
can use the `list_available_agents` tool.
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
message (str): The content of the message to send.
|
|
196
|
+
receiver_id (str): The unique identifier of the agent to receive
|
|
197
|
+
the message. Use `list_available_agents()` to find the ID of
|
|
198
|
+
the agent you want to talk to.
|
|
199
|
+
sender_id (str): The unique identifier of the agent sending the
|
|
200
|
+
message. This is typically your agent's ID.
|
|
201
|
+
(default: :obj:`"system"`)
|
|
202
|
+
reply_to (Optional[str]): The ID of a previous message this new
|
|
203
|
+
message is a reply to. This helps create conversation threads.
|
|
204
|
+
(default: :obj:`None`)
|
|
205
|
+
metadata_json (Optional[str]): A JSON string containing extra
|
|
206
|
+
information about the message.
|
|
207
|
+
(default: :obj:`None`)
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
str: A confirmation that the message was sent. If the toolkit's
|
|
211
|
+
get_response setting is True, includes the response from the
|
|
212
|
+
receiving agent.
|
|
213
|
+
"""
|
|
214
|
+
if not message or not message.strip():
|
|
215
|
+
raise ValueError("Message content cannot be empty")
|
|
216
|
+
|
|
217
|
+
# Find the actual agent ID (case-insensitive)
|
|
218
|
+
actual_receiver_id = self._find_agent_id(receiver_id)
|
|
219
|
+
if not actual_receiver_id:
|
|
220
|
+
available_agents = ", ".join(self.agents.keys())
|
|
221
|
+
error_msg = (
|
|
222
|
+
f"Agent {receiver_id} not found. "
|
|
223
|
+
f"Available agents: {available_agents}"
|
|
224
|
+
)
|
|
225
|
+
logger.error(error_msg)
|
|
226
|
+
return f"Error: {error_msg}"
|
|
227
|
+
|
|
228
|
+
# Parse metadata from JSON string
|
|
229
|
+
metadata = {}
|
|
230
|
+
if metadata_json:
|
|
231
|
+
try:
|
|
232
|
+
metadata = json.loads(metadata_json)
|
|
233
|
+
if not isinstance(metadata, dict):
|
|
234
|
+
logger.warning(
|
|
235
|
+
"Metadata must be a JSON object, using empty dict"
|
|
236
|
+
)
|
|
237
|
+
metadata = {}
|
|
238
|
+
except json.JSONDecodeError:
|
|
239
|
+
logger.warning(
|
|
240
|
+
"Invalid JSON in metadata_json, using empty dict"
|
|
241
|
+
)
|
|
242
|
+
metadata = {}
|
|
243
|
+
|
|
244
|
+
# Create message
|
|
245
|
+
agent_message = AgentMessage(
|
|
246
|
+
message_id=str(uuid.uuid4()),
|
|
247
|
+
sender_id=sender_id,
|
|
248
|
+
receiver_id=actual_receiver_id, # Use the resolved agent ID
|
|
249
|
+
content=message,
|
|
250
|
+
timestamp=time.time(),
|
|
251
|
+
reply_to=reply_to,
|
|
252
|
+
metadata=metadata,
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
# Handle threading
|
|
256
|
+
if reply_to:
|
|
257
|
+
self._update_conversation_thread(reply_to, agent_message.id)
|
|
258
|
+
|
|
259
|
+
# Deliver message (with or without response)
|
|
260
|
+
return self._deliver_message(agent_message, self.get_response)
|
|
261
|
+
|
|
262
|
+
def _deliver_message(
|
|
263
|
+
self, message: AgentMessage, get_response: bool
|
|
264
|
+
) -> str:
|
|
265
|
+
r"""Deliver a message to the target agent, optionally getting a
|
|
266
|
+
response.
|
|
267
|
+
"""
|
|
268
|
+
try:
|
|
269
|
+
target_agent = self.agents[message.receiver_id]
|
|
270
|
+
logger.info(
|
|
271
|
+
f"Delivering message {message.id} to agent "
|
|
272
|
+
f"{message.receiver_id}"
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
self._add_to_history(message)
|
|
276
|
+
|
|
277
|
+
# Create a clear, structured message for the agent
|
|
278
|
+
structured_message = (
|
|
279
|
+
f"A message has been received from agent with "
|
|
280
|
+
f"ID '{message.sender_id}'.\n\n"
|
|
281
|
+
"--- Message Content ---\n"
|
|
282
|
+
f"{message.content}\n"
|
|
283
|
+
"--- End of Message ---"
|
|
284
|
+
)
|
|
285
|
+
response = target_agent.step(structured_message)
|
|
286
|
+
|
|
287
|
+
if get_response:
|
|
288
|
+
# Extract and return response content
|
|
289
|
+
if hasattr(response, 'msgs') and response.msgs:
|
|
290
|
+
response_content = response.msgs[0].content
|
|
291
|
+
else:
|
|
292
|
+
response_content = str(response)
|
|
293
|
+
|
|
294
|
+
logger.info(
|
|
295
|
+
f"Message {message.id} delivered with response. "
|
|
296
|
+
f"Response length: {len(response_content)}"
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
return (
|
|
300
|
+
f"Message {message.id} delivered to "
|
|
301
|
+
f"{message.receiver_id}. "
|
|
302
|
+
f"Response: {response_content[:100]}"
|
|
303
|
+
f"{'...' if len(response_content) > 100 else ''}"
|
|
304
|
+
)
|
|
305
|
+
else:
|
|
306
|
+
# Message delivered but response not requested
|
|
307
|
+
logger.info(
|
|
308
|
+
f"Message {message.id} delivered to agent "
|
|
309
|
+
f"{message.receiver_id} (response not requested)"
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
return (
|
|
313
|
+
f"Message {message.id} delivered to "
|
|
314
|
+
f"{message.receiver_id}. "
|
|
315
|
+
f"Message: '{message.content[:50]}"
|
|
316
|
+
f"{'...' if len(message.content) > 50 else ''}'"
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
except Exception as e:
|
|
320
|
+
error_msg = f"Failed to deliver message {message.id}: {e!s}"
|
|
321
|
+
logger.error(error_msg)
|
|
322
|
+
return f"Error: {error_msg}"
|
|
323
|
+
|
|
324
|
+
def broadcast_message(
|
|
325
|
+
self,
|
|
326
|
+
message: str,
|
|
327
|
+
sender_id: str = "system",
|
|
328
|
+
exclude_agents: Optional[List[str]] = None,
|
|
329
|
+
) -> str:
|
|
330
|
+
r"""Sends a message to all other agents in the system.
|
|
331
|
+
|
|
332
|
+
This function is useful for making announcements or sending information
|
|
333
|
+
that every agent needs. The message will be sent to all registered
|
|
334
|
+
agents except for the sender and any agents specified in the
|
|
335
|
+
`exclude_agents` list.
|
|
336
|
+
|
|
337
|
+
Args:
|
|
338
|
+
message (str): The content of the message to broadcast.
|
|
339
|
+
sender_id (str): The unique identifier of the agent sending the
|
|
340
|
+
message. This is typically your agent's ID.
|
|
341
|
+
(default: :obj:`"system"`)
|
|
342
|
+
exclude_agents (Optional[List[str]]): A list of agent IDs to
|
|
343
|
+
exclude from the broadcast. The sender is automatically
|
|
344
|
+
excluded.
|
|
345
|
+
(default: :obj:`None`)
|
|
346
|
+
|
|
347
|
+
Returns:
|
|
348
|
+
str: A summary of the broadcast, showing which agents received the
|
|
349
|
+
message and their responses.
|
|
350
|
+
"""
|
|
351
|
+
if not message or not message.strip():
|
|
352
|
+
return "Error: Message content cannot be empty"
|
|
353
|
+
|
|
354
|
+
exclude_set = set(exclude_agents or [])
|
|
355
|
+
if sender_id:
|
|
356
|
+
exclude_set.add(sender_id) # Don't send to self
|
|
357
|
+
|
|
358
|
+
target_agents = [
|
|
359
|
+
agent_id
|
|
360
|
+
for agent_id in self.agents.keys()
|
|
361
|
+
if agent_id not in exclude_set
|
|
362
|
+
]
|
|
363
|
+
|
|
364
|
+
if not target_agents:
|
|
365
|
+
return "No target agents available for broadcast"
|
|
366
|
+
|
|
367
|
+
results = []
|
|
368
|
+
for agent_id in target_agents:
|
|
369
|
+
try:
|
|
370
|
+
result = self.send_message(
|
|
371
|
+
message=message,
|
|
372
|
+
receiver_id=agent_id,
|
|
373
|
+
sender_id=sender_id,
|
|
374
|
+
metadata_json='{"broadcast": true}',
|
|
375
|
+
)
|
|
376
|
+
results.append(f"{agent_id}: {result}")
|
|
377
|
+
except Exception as e:
|
|
378
|
+
results.append(f"{agent_id}: Error - {e}")
|
|
379
|
+
|
|
380
|
+
logger.info(f"Broadcast sent to {len(target_agents)} agents")
|
|
381
|
+
return "Broadcast completed. Results:\n" + "\n".join(results)
|
|
382
|
+
|
|
383
|
+
def get_message_history(
|
|
384
|
+
self, agent_id: str, limit: Optional[int] = None
|
|
385
|
+
) -> str:
|
|
386
|
+
r"""Retrieves the message history for a specific agent.
|
|
387
|
+
|
|
388
|
+
This function allows you to see the messages sent and received by a
|
|
389
|
+
particular agent, which can be useful for understanding past
|
|
390
|
+
conversations. To get the `agent_id` for another agent, use the
|
|
391
|
+
`list_available_agents` tool. You can also use this tool to get
|
|
392
|
+
your own message history by providing your agent ID.
|
|
393
|
+
|
|
394
|
+
Args:
|
|
395
|
+
agent_id (str): The unique identifier of the agent whose message
|
|
396
|
+
history you want to retrieve. Use `list_available_agents()`
|
|
397
|
+
to find available agent IDs.
|
|
398
|
+
limit (Optional[int]): The maximum number of recent messages to
|
|
399
|
+
return. If not specified, it will return all messages up to
|
|
400
|
+
the system's limit.
|
|
401
|
+
(default: :obj:`None`)
|
|
402
|
+
|
|
403
|
+
Returns:
|
|
404
|
+
str: A formatted string containing the message history for the
|
|
405
|
+
specified agent, or an error if the agent is not found.
|
|
406
|
+
"""
|
|
407
|
+
actual_agent_id = self._find_agent_id(agent_id)
|
|
408
|
+
if not actual_agent_id:
|
|
409
|
+
return f"No message history found for agent {agent_id}"
|
|
410
|
+
|
|
411
|
+
history = self._message_history.get(actual_agent_id, [])
|
|
412
|
+
if limit:
|
|
413
|
+
history = history[-limit:]
|
|
414
|
+
|
|
415
|
+
if not history:
|
|
416
|
+
return f"No messages in history for agent {agent_id}"
|
|
417
|
+
|
|
418
|
+
formatted_history = []
|
|
419
|
+
for msg in history:
|
|
420
|
+
timestamp_str = time.strftime(
|
|
421
|
+
'%Y-%m-%d %H:%M:%S', time.localtime(msg.timestamp)
|
|
422
|
+
)
|
|
423
|
+
formatted_history.append(
|
|
424
|
+
f"[{timestamp_str}] {msg.sender_id} -> {msg.receiver_id}: "
|
|
425
|
+
f"{msg.content[:100]}{'...' if len(msg.content) > 100 else ''}"
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
return (
|
|
429
|
+
f"Message history for {agent_id} "
|
|
430
|
+
f"({len(formatted_history)} messages):\n"
|
|
431
|
+
+ "\n".join(formatted_history)
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
def get_conversation_thread(self, message_id: str) -> str:
|
|
435
|
+
r"""Retrieves a full conversation thread based on a message ID.
|
|
436
|
+
|
|
437
|
+
When you send a message that is a reply to another, it creates a
|
|
438
|
+
conversation thread. This function lets you retrieve all messages
|
|
439
|
+
that are part of that thread. You can find message IDs in the
|
|
440
|
+
message history or from the output of the `send_message` tool.
|
|
441
|
+
|
|
442
|
+
Args:
|
|
443
|
+
message_id (str): The unique identifier of any message within the
|
|
444
|
+
conversation thread you want to retrieve.
|
|
445
|
+
|
|
446
|
+
Returns:
|
|
447
|
+
str: A formatted string containing all messages in the
|
|
448
|
+
conversation, sorted by time, or an error if the thread is
|
|
449
|
+
not found.
|
|
450
|
+
"""
|
|
451
|
+
if message_id not in self._conversation_threads:
|
|
452
|
+
return f"No conversation thread found for message {message_id}"
|
|
453
|
+
|
|
454
|
+
thread_ids = self._conversation_threads[message_id]
|
|
455
|
+
thread_messages = []
|
|
456
|
+
|
|
457
|
+
# Find messages in history
|
|
458
|
+
for agent_history in self._message_history.values():
|
|
459
|
+
for msg in agent_history:
|
|
460
|
+
if msg.id in thread_ids:
|
|
461
|
+
thread_messages.append(msg)
|
|
462
|
+
|
|
463
|
+
# Sort by timestamp
|
|
464
|
+
thread_messages.sort(key=lambda x: x.timestamp)
|
|
465
|
+
|
|
466
|
+
if not thread_messages:
|
|
467
|
+
return f"No messages found in thread for {message_id}"
|
|
468
|
+
|
|
469
|
+
formatted_thread = []
|
|
470
|
+
for msg in thread_messages:
|
|
471
|
+
timestamp_str = time.strftime(
|
|
472
|
+
'%H:%M:%S', time.localtime(msg.timestamp)
|
|
473
|
+
)
|
|
474
|
+
formatted_thread.append(
|
|
475
|
+
f"[{timestamp_str}] {msg.sender_id}: {msg.content}"
|
|
476
|
+
)
|
|
477
|
+
|
|
478
|
+
return (
|
|
479
|
+
f"Conversation thread ({len(formatted_thread)} messages):\n"
|
|
480
|
+
+ "\n".join(formatted_thread)
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
def list_available_agents(self) -> str:
|
|
484
|
+
r"""Lists all agents currently available for communication.
|
|
485
|
+
|
|
486
|
+
Call this function to discover which other agents are in the system
|
|
487
|
+
that you can communicate with. The returned list will contain the
|
|
488
|
+
unique IDs for each agent, which you can then use with tools like
|
|
489
|
+
`send_message` and `get_message_history`.
|
|
490
|
+
|
|
491
|
+
Returns:
|
|
492
|
+
str: A formatted string listing the IDs and status of all
|
|
493
|
+
available agents.
|
|
494
|
+
"""
|
|
495
|
+
if not self.agents:
|
|
496
|
+
return "No agents registered"
|
|
497
|
+
|
|
498
|
+
agent_info = []
|
|
499
|
+
for agent_id, agent in self.agents.items():
|
|
500
|
+
# Get message count for this agent
|
|
501
|
+
msg_count = len(self._message_history.get(agent_id, []))
|
|
502
|
+
|
|
503
|
+
# Check if agent has pause support
|
|
504
|
+
has_pause = hasattr(agent, 'pause_event')
|
|
505
|
+
|
|
506
|
+
status_info = f"Messages: {msg_count}"
|
|
507
|
+
if has_pause:
|
|
508
|
+
status_info += ", Workforce-compatible"
|
|
509
|
+
|
|
510
|
+
agent_info.append(f" - {agent_id}: {status_info}")
|
|
511
|
+
|
|
512
|
+
return f"Available agents ({len(self.agents)}):\n" + "\n".join(
|
|
513
|
+
agent_info
|
|
514
|
+
)
|
|
515
|
+
|
|
516
|
+
def remove_agent(self, agent_id: str) -> str:
|
|
517
|
+
r"""Remove an agent from the communication registry.
|
|
518
|
+
|
|
519
|
+
Args:
|
|
520
|
+
agent_id (str): Unique identifier of the agent to remove.
|
|
521
|
+
|
|
522
|
+
Returns:
|
|
523
|
+
str: Confirmation message with cleanup details.
|
|
524
|
+
"""
|
|
525
|
+
if agent_id not in self.agents:
|
|
526
|
+
return f"Error: Agent {agent_id} not found"
|
|
527
|
+
|
|
528
|
+
del self.agents[agent_id]
|
|
529
|
+
|
|
530
|
+
# Keep message history for audit purposes but note agent removal
|
|
531
|
+
if agent_id in self._message_history:
|
|
532
|
+
logger.info(
|
|
533
|
+
f"Preserved {len(self._message_history[agent_id])} "
|
|
534
|
+
f"messages for removed agent {agent_id}"
|
|
535
|
+
)
|
|
536
|
+
|
|
537
|
+
logger.info(f"Removed agent: {agent_id}")
|
|
538
|
+
return (
|
|
539
|
+
f"Agent {agent_id} removed successfully. "
|
|
540
|
+
f"Remaining agents: {len(self.agents)}"
|
|
541
|
+
)
|
|
542
|
+
|
|
543
|
+
def get_toolkit_status(self) -> str:
|
|
544
|
+
r"""Get comprehensive status of the message toolkit.
|
|
545
|
+
|
|
546
|
+
Returns:
|
|
547
|
+
str: Detailed status information including metrics and queue state.
|
|
548
|
+
"""
|
|
549
|
+
total_messages = sum(
|
|
550
|
+
len(history) for history in self._message_history.values()
|
|
551
|
+
)
|
|
552
|
+
|
|
553
|
+
status_info = [
|
|
554
|
+
"AgentCommunicationToolkit Status:",
|
|
555
|
+
f" - Registered agents: {len(self.agents)}",
|
|
556
|
+
f" - Total message history: {total_messages}",
|
|
557
|
+
f" - Max history per agent: {self.max_message_history}",
|
|
558
|
+
]
|
|
559
|
+
|
|
560
|
+
return "\n".join(status_info)
|
|
561
|
+
|
|
562
|
+
def _add_to_history(self, message: AgentMessage) -> None:
|
|
563
|
+
r"""Add a message to the history with size management."""
|
|
564
|
+
# Add to sender's history
|
|
565
|
+
sender_history = self._message_history.setdefault(
|
|
566
|
+
message.sender_id, []
|
|
567
|
+
)
|
|
568
|
+
sender_history.append(message)
|
|
569
|
+
|
|
570
|
+
# Add to receiver's history
|
|
571
|
+
receiver_history = self._message_history.setdefault(
|
|
572
|
+
message.receiver_id, []
|
|
573
|
+
)
|
|
574
|
+
receiver_history.append(message)
|
|
575
|
+
|
|
576
|
+
# Trim history if needed
|
|
577
|
+
for agent_id, history in self._message_history.items():
|
|
578
|
+
if len(history) > self.max_message_history:
|
|
579
|
+
self._message_history[agent_id] = history[
|
|
580
|
+
-self.max_message_history :
|
|
581
|
+
]
|
|
582
|
+
|
|
583
|
+
def _update_conversation_thread(self, parent_id: str, new_id: str) -> None:
|
|
584
|
+
r"""Update conversation threading."""
|
|
585
|
+
if parent_id in self._conversation_threads:
|
|
586
|
+
self._conversation_threads[parent_id].append(new_id)
|
|
587
|
+
else:
|
|
588
|
+
self._conversation_threads[new_id] = [parent_id, new_id]
|
|
589
|
+
|
|
590
|
+
def get_tools(self) -> List[FunctionTool]:
|
|
591
|
+
r"""Returns a list of FunctionTool objects representing the
|
|
592
|
+
communication functions in the toolkit.
|
|
593
|
+
|
|
594
|
+
Note: Only includes functions that are safe and useful for LLMs to
|
|
595
|
+
call. Administrative functions like register_agent and remove_agent are
|
|
596
|
+
excluded as they should only be called programmatically.
|
|
597
|
+
|
|
598
|
+
Returns:
|
|
599
|
+
List[FunctionTool]: A list of FunctionTool objects for agent
|
|
600
|
+
communication and management.
|
|
601
|
+
"""
|
|
602
|
+
return [
|
|
603
|
+
FunctionTool(self.send_message),
|
|
604
|
+
FunctionTool(self.broadcast_message),
|
|
605
|
+
FunctionTool(self.list_available_agents),
|
|
606
|
+
FunctionTool(self.get_message_history),
|
|
607
|
+
FunctionTool(self.get_conversation_thread),
|
|
608
|
+
]
|