camel-ai 0.2.73a4__py3-none-any.whl → 0.2.80a2__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.
- camel/__init__.py +1 -1
- camel/agents/_utils.py +38 -0
- camel/agents/chat_agent.py +2217 -519
- camel/agents/mcp_agent.py +30 -27
- camel/configs/__init__.py +15 -0
- camel/configs/aihubmix_config.py +88 -0
- camel/configs/amd_config.py +70 -0
- camel/configs/cometapi_config.py +104 -0
- camel/configs/minimax_config.py +93 -0
- camel/configs/nebius_config.py +103 -0
- camel/data_collectors/alpaca_collector.py +15 -6
- camel/datasets/base_generator.py +39 -10
- camel/environments/single_step.py +28 -3
- camel/environments/tic_tac_toe.py +1 -1
- camel/interpreters/__init__.py +2 -0
- camel/interpreters/docker/Dockerfile +3 -12
- camel/interpreters/e2b_interpreter.py +34 -1
- camel/interpreters/microsandbox_interpreter.py +395 -0
- camel/loaders/__init__.py +11 -2
- camel/loaders/chunkr_reader.py +9 -0
- camel/memories/agent_memories.py +48 -4
- camel/memories/base.py +26 -0
- camel/memories/blocks/chat_history_block.py +122 -4
- camel/memories/context_creators/score_based.py +25 -384
- camel/memories/records.py +88 -8
- camel/messages/base.py +153 -34
- camel/models/__init__.py +10 -0
- camel/models/aihubmix_model.py +83 -0
- camel/models/aiml_model.py +1 -16
- camel/models/amd_model.py +101 -0
- camel/models/anthropic_model.py +6 -19
- camel/models/aws_bedrock_model.py +2 -33
- camel/models/azure_openai_model.py +114 -89
- camel/models/base_audio_model.py +3 -1
- camel/models/base_model.py +32 -14
- camel/models/cohere_model.py +1 -16
- camel/models/cometapi_model.py +83 -0
- camel/models/crynux_model.py +1 -16
- camel/models/deepseek_model.py +1 -16
- camel/models/fish_audio_model.py +6 -0
- camel/models/gemini_model.py +36 -18
- camel/models/groq_model.py +1 -17
- camel/models/internlm_model.py +1 -16
- camel/models/litellm_model.py +1 -16
- camel/models/lmstudio_model.py +1 -17
- camel/models/minimax_model.py +83 -0
- camel/models/mistral_model.py +1 -16
- camel/models/model_factory.py +27 -1
- camel/models/modelscope_model.py +1 -16
- camel/models/moonshot_model.py +105 -24
- camel/models/nebius_model.py +83 -0
- camel/models/nemotron_model.py +0 -5
- camel/models/netmind_model.py +1 -16
- camel/models/novita_model.py +1 -16
- camel/models/nvidia_model.py +1 -16
- camel/models/ollama_model.py +4 -19
- camel/models/openai_compatible_model.py +62 -41
- camel/models/openai_model.py +62 -57
- camel/models/openrouter_model.py +1 -17
- camel/models/ppio_model.py +1 -16
- camel/models/qianfan_model.py +1 -16
- camel/models/qwen_model.py +1 -16
- camel/models/reka_model.py +1 -16
- camel/models/samba_model.py +34 -47
- camel/models/sglang_model.py +64 -31
- camel/models/siliconflow_model.py +1 -16
- camel/models/stub_model.py +0 -4
- camel/models/togetherai_model.py +1 -16
- camel/models/vllm_model.py +1 -16
- camel/models/volcano_model.py +0 -17
- camel/models/watsonx_model.py +1 -16
- camel/models/yi_model.py +1 -16
- camel/models/zhipuai_model.py +60 -16
- camel/parsers/__init__.py +18 -0
- camel/parsers/mcp_tool_call_parser.py +176 -0
- camel/retrievers/auto_retriever.py +1 -0
- camel/runtimes/daytona_runtime.py +11 -12
- camel/societies/__init__.py +2 -0
- camel/societies/workforce/__init__.py +2 -0
- camel/societies/workforce/events.py +122 -0
- camel/societies/workforce/prompts.py +146 -66
- camel/societies/workforce/role_playing_worker.py +15 -11
- camel/societies/workforce/single_agent_worker.py +302 -65
- camel/societies/workforce/structured_output_handler.py +30 -18
- camel/societies/workforce/task_channel.py +163 -27
- camel/societies/workforce/utils.py +107 -13
- camel/societies/workforce/workflow_memory_manager.py +772 -0
- camel/societies/workforce/workforce.py +1949 -579
- camel/societies/workforce/workforce_callback.py +74 -0
- camel/societies/workforce/workforce_logger.py +168 -145
- camel/societies/workforce/workforce_metrics.py +33 -0
- camel/storages/key_value_storages/json.py +15 -2
- camel/storages/key_value_storages/mem0_cloud.py +48 -47
- camel/storages/object_storages/google_cloud.py +1 -1
- camel/storages/vectordb_storages/oceanbase.py +13 -13
- camel/storages/vectordb_storages/qdrant.py +3 -3
- camel/storages/vectordb_storages/tidb.py +8 -6
- camel/tasks/task.py +4 -3
- camel/toolkits/__init__.py +20 -7
- camel/toolkits/aci_toolkit.py +45 -0
- camel/toolkits/base.py +6 -4
- camel/toolkits/code_execution.py +28 -1
- camel/toolkits/context_summarizer_toolkit.py +684 -0
- camel/toolkits/dappier_toolkit.py +5 -1
- camel/toolkits/dingtalk.py +1135 -0
- camel/toolkits/edgeone_pages_mcp_toolkit.py +11 -31
- camel/toolkits/excel_toolkit.py +1 -1
- camel/toolkits/{file_write_toolkit.py → file_toolkit.py} +430 -36
- camel/toolkits/function_tool.py +13 -3
- camel/toolkits/github_toolkit.py +104 -17
- camel/toolkits/gmail_toolkit.py +1839 -0
- camel/toolkits/google_calendar_toolkit.py +38 -4
- camel/toolkits/google_drive_mcp_toolkit.py +12 -31
- camel/toolkits/hybrid_browser_toolkit/config_loader.py +15 -0
- camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit.py +77 -8
- camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit_ts.py +884 -88
- camel/toolkits/hybrid_browser_toolkit/installer.py +203 -0
- camel/toolkits/hybrid_browser_toolkit/ts/package-lock.json +5 -612
- camel/toolkits/hybrid_browser_toolkit/ts/package.json +0 -1
- camel/toolkits/hybrid_browser_toolkit/ts/src/browser-session.ts +959 -89
- camel/toolkits/hybrid_browser_toolkit/ts/src/config-loader.ts +9 -2
- camel/toolkits/hybrid_browser_toolkit/ts/src/hybrid-browser-toolkit.ts +281 -213
- 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 +23 -3
- camel/toolkits/hybrid_browser_toolkit/ts/websocket-server.js +72 -7
- camel/toolkits/hybrid_browser_toolkit/ws_wrapper.py +582 -132
- camel/toolkits/hybrid_browser_toolkit_py/actions.py +158 -0
- camel/toolkits/hybrid_browser_toolkit_py/browser_session.py +55 -8
- camel/toolkits/hybrid_browser_toolkit_py/config_loader.py +43 -0
- camel/toolkits/hybrid_browser_toolkit_py/hybrid_browser_toolkit.py +321 -8
- camel/toolkits/hybrid_browser_toolkit_py/snapshot.py +10 -4
- camel/toolkits/hybrid_browser_toolkit_py/unified_analyzer.js +45 -4
- camel/toolkits/{openai_image_toolkit.py → image_generation_toolkit.py} +151 -53
- camel/toolkits/klavis_toolkit.py +5 -1
- camel/toolkits/markitdown_toolkit.py +27 -1
- camel/toolkits/math_toolkit.py +64 -10
- camel/toolkits/mcp_toolkit.py +366 -71
- camel/toolkits/memory_toolkit.py +5 -1
- camel/toolkits/message_integration.py +18 -13
- camel/toolkits/minimax_mcp_toolkit.py +195 -0
- camel/toolkits/note_taking_toolkit.py +19 -10
- camel/toolkits/notion_mcp_toolkit.py +16 -26
- camel/toolkits/openbb_toolkit.py +5 -1
- camel/toolkits/origene_mcp_toolkit.py +8 -49
- camel/toolkits/playwright_mcp_toolkit.py +12 -31
- camel/toolkits/resend_toolkit.py +168 -0
- camel/toolkits/search_toolkit.py +264 -91
- camel/toolkits/slack_toolkit.py +64 -10
- camel/toolkits/terminal_toolkit/__init__.py +18 -0
- camel/toolkits/terminal_toolkit/terminal_toolkit.py +957 -0
- camel/toolkits/terminal_toolkit/utils.py +532 -0
- camel/toolkits/vertex_ai_veo_toolkit.py +590 -0
- camel/toolkits/video_analysis_toolkit.py +17 -11
- camel/toolkits/wechat_official_toolkit.py +483 -0
- camel/toolkits/zapier_toolkit.py +5 -1
- camel/types/__init__.py +2 -2
- camel/types/enums.py +274 -7
- camel/types/openai_types.py +2 -2
- camel/types/unified_model_type.py +15 -0
- camel/utils/commons.py +36 -5
- camel/utils/constants.py +3 -0
- camel/utils/context_utils.py +1003 -0
- camel/utils/mcp.py +138 -4
- camel/utils/token_counting.py +43 -20
- {camel_ai-0.2.73a4.dist-info → camel_ai-0.2.80a2.dist-info}/METADATA +223 -83
- {camel_ai-0.2.73a4.dist-info → camel_ai-0.2.80a2.dist-info}/RECORD +170 -141
- camel/loaders/pandas_reader.py +0 -368
- camel/toolkits/openai_agent_toolkit.py +0 -135
- camel/toolkits/terminal_toolkit.py +0 -1550
- {camel_ai-0.2.73a4.dist-info → camel_ai-0.2.80a2.dist-info}/WHEEL +0 -0
- {camel_ai-0.2.73a4.dist-info → camel_ai-0.2.80a2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# ========= Copyright 2023-2024 @ 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-2024 @ CAMEL-AI.org. All Rights Reserved. =========
|
|
14
|
+
|
|
15
|
+
import os
|
|
16
|
+
from typing import Any, Dict, List, Optional
|
|
17
|
+
|
|
18
|
+
from camel.toolkits import BaseToolkit, FunctionTool
|
|
19
|
+
|
|
20
|
+
from .mcp_toolkit import MCPToolkit
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class MinimaxMCPToolkit(BaseToolkit):
|
|
24
|
+
r"""MinimaxMCPToolkit provides an interface for interacting with
|
|
25
|
+
MiniMax AI services using the MiniMax MCP server.
|
|
26
|
+
|
|
27
|
+
This toolkit enables access to MiniMax's multimedia generation
|
|
28
|
+
capabilities including text-to-audio, voice cloning, video generation,
|
|
29
|
+
image generation, music generation, and voice design.
|
|
30
|
+
|
|
31
|
+
This toolkit can be used as an async context manager for automatic
|
|
32
|
+
connection management:
|
|
33
|
+
|
|
34
|
+
# Using explicit API key
|
|
35
|
+
async with MinimaxMCPToolkit(api_key="your-key") as toolkit:
|
|
36
|
+
tools = toolkit.get_tools()
|
|
37
|
+
# Toolkit is automatically disconnected when exiting
|
|
38
|
+
|
|
39
|
+
# Using environment variables (recommended for security)
|
|
40
|
+
# Set MINIMAX_API_KEY=your-key in environment
|
|
41
|
+
async with MinimaxMCPToolkit() as toolkit:
|
|
42
|
+
tools = toolkit.get_tools()
|
|
43
|
+
|
|
44
|
+
Environment Variables:
|
|
45
|
+
MINIMAX_API_KEY: MiniMax API key for authentication
|
|
46
|
+
MINIMAX_API_HOST: API host URL (default: https://api.minimax.io)
|
|
47
|
+
MINIMAX_MCP_BASE_PATH: Base path for output files
|
|
48
|
+
|
|
49
|
+
Attributes:
|
|
50
|
+
timeout (Optional[float]): Connection timeout in seconds.
|
|
51
|
+
(default: :obj:`None`)
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
def __init__(
|
|
55
|
+
self,
|
|
56
|
+
api_key: Optional[str] = None,
|
|
57
|
+
api_host: str = "https://api.minimax.io",
|
|
58
|
+
base_path: Optional[str] = None,
|
|
59
|
+
timeout: Optional[float] = None,
|
|
60
|
+
) -> None:
|
|
61
|
+
r"""Initializes the MinimaxMCPToolkit.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
api_key (Optional[str]): MiniMax API key for authentication.
|
|
65
|
+
If None, will attempt to read from MINIMAX_API_KEY
|
|
66
|
+
environment variable. (default: :obj:`None`)
|
|
67
|
+
api_host (str): MiniMax API host URL. Can be either
|
|
68
|
+
"https://api.minimax.io" (global) or
|
|
69
|
+
"https://api.minimaxi.com" (mainland China).
|
|
70
|
+
Can also be read from MINIMAX_API_HOST environment variable.
|
|
71
|
+
(default: :obj:`"https://api.minimax.io"`)
|
|
72
|
+
base_path (Optional[str]): Base path for output files.
|
|
73
|
+
If None, uses current working directory. Can also be read
|
|
74
|
+
from MINIMAX_MCP_BASE_PATH environment variable.
|
|
75
|
+
(default: :obj:`None`)
|
|
76
|
+
timeout (Optional[float]): Connection timeout in seconds.
|
|
77
|
+
(default: :obj:`None`)
|
|
78
|
+
"""
|
|
79
|
+
super().__init__(timeout=timeout)
|
|
80
|
+
|
|
81
|
+
# Read API key from parameter or environment variable
|
|
82
|
+
if api_key is None:
|
|
83
|
+
api_key = os.getenv("MINIMAX_API_KEY")
|
|
84
|
+
|
|
85
|
+
if not api_key:
|
|
86
|
+
raise ValueError(
|
|
87
|
+
"api_key must be provided either as a parameter or through "
|
|
88
|
+
"the MINIMAX_API_KEY environment variable"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
# Read API host from environment variable if not overridden
|
|
92
|
+
env_api_host = os.getenv("MINIMAX_API_HOST")
|
|
93
|
+
if env_api_host:
|
|
94
|
+
api_host = env_api_host
|
|
95
|
+
|
|
96
|
+
# Read base path from environment variable if not provided
|
|
97
|
+
if base_path is None:
|
|
98
|
+
base_path = os.getenv("MINIMAX_MCP_BASE_PATH")
|
|
99
|
+
|
|
100
|
+
# Set up environment variables for the MCP server
|
|
101
|
+
env = {
|
|
102
|
+
"MINIMAX_API_KEY": api_key,
|
|
103
|
+
"MINIMAX_API_HOST": api_host,
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if base_path:
|
|
107
|
+
env["MINIMAX_MCP_BASE_PATH"] = base_path
|
|
108
|
+
|
|
109
|
+
self._mcp_toolkit = MCPToolkit(
|
|
110
|
+
config_dict={
|
|
111
|
+
"mcpServers": {
|
|
112
|
+
"minimax": {
|
|
113
|
+
"command": "uvx",
|
|
114
|
+
"args": ["minimax-mcp", "-y"],
|
|
115
|
+
"env": env,
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
timeout=timeout,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
async def connect(self):
|
|
123
|
+
r"""Explicitly connect to the MiniMax MCP server."""
|
|
124
|
+
await self._mcp_toolkit.connect()
|
|
125
|
+
|
|
126
|
+
async def disconnect(self):
|
|
127
|
+
r"""Explicitly disconnect from the MiniMax MCP server."""
|
|
128
|
+
await self._mcp_toolkit.disconnect()
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def is_connected(self) -> bool:
|
|
132
|
+
r"""Check if the toolkit is connected to the MCP server.
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
bool: True if connected, False otherwise.
|
|
136
|
+
"""
|
|
137
|
+
return self._mcp_toolkit.is_connected
|
|
138
|
+
|
|
139
|
+
async def __aenter__(self) -> "MinimaxMCPToolkit":
|
|
140
|
+
r"""Async context manager entry point.
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
MinimaxMCPToolkit: The connected toolkit instance.
|
|
144
|
+
|
|
145
|
+
Example:
|
|
146
|
+
async with MinimaxMCPToolkit(api_key="your-key") as toolkit:
|
|
147
|
+
tools = toolkit.get_tools()
|
|
148
|
+
"""
|
|
149
|
+
await self.connect()
|
|
150
|
+
return self
|
|
151
|
+
|
|
152
|
+
async def __aexit__(self, _exc_type, _exc_val, _exc_tb) -> None:
|
|
153
|
+
r"""Async context manager exit point.
|
|
154
|
+
|
|
155
|
+
Automatically disconnects from the MiniMax MCP server.
|
|
156
|
+
"""
|
|
157
|
+
await self.disconnect()
|
|
158
|
+
|
|
159
|
+
def get_tools(self) -> List[FunctionTool]:
|
|
160
|
+
r"""Returns a list of tools provided by the MiniMax MCP server.
|
|
161
|
+
|
|
162
|
+
This includes tools for:
|
|
163
|
+
- Text-to-audio conversion
|
|
164
|
+
- Voice cloning
|
|
165
|
+
- Video generation
|
|
166
|
+
- Image generation
|
|
167
|
+
- Music generation
|
|
168
|
+
- Voice design
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
List[FunctionTool]: List of available MiniMax AI tools.
|
|
172
|
+
"""
|
|
173
|
+
return self._mcp_toolkit.get_tools()
|
|
174
|
+
|
|
175
|
+
def get_text_tools(self) -> str:
|
|
176
|
+
r"""Returns a string containing the descriptions of the tools.
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
str: A string containing the descriptions of all MiniMax tools.
|
|
180
|
+
"""
|
|
181
|
+
return self._mcp_toolkit.get_text_tools()
|
|
182
|
+
|
|
183
|
+
async def call_tool(
|
|
184
|
+
self, tool_name: str, tool_args: Dict[str, Any]
|
|
185
|
+
) -> Any:
|
|
186
|
+
r"""Call a MiniMax tool by name.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
tool_name (str): Name of the tool to call.
|
|
190
|
+
tool_args (Dict[str, Any]): Arguments to pass to the tool.
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
Any: The result of the tool call.
|
|
194
|
+
"""
|
|
195
|
+
return await self._mcp_toolkit.call_tool(tool_name, tool_args)
|
|
@@ -138,34 +138,43 @@ class NoteTakingToolkit(BaseToolkit):
|
|
|
138
138
|
self.registry.append(note_name)
|
|
139
139
|
self._save_registry()
|
|
140
140
|
|
|
141
|
-
def create_note(
|
|
141
|
+
def create_note(
|
|
142
|
+
self, note_name: str, content: str, overwrite: bool = False
|
|
143
|
+
) -> str:
|
|
142
144
|
r"""Creates a new note with a unique name.
|
|
143
145
|
|
|
144
146
|
This function will create a new file for your note.
|
|
145
|
-
|
|
146
|
-
to add content to an existing note, use the `append_note`
|
|
147
|
-
instead.
|
|
147
|
+
By default, you must provide a `note_name` that does not already exist.
|
|
148
|
+
If you want to add content to an existing note, use the `append_note`
|
|
149
|
+
function instead. If you want to overwrite an existing note, set
|
|
150
|
+
`overwrite=True`.
|
|
148
151
|
|
|
149
152
|
Args:
|
|
150
153
|
note_name (str): The name for your new note (without the .md
|
|
151
|
-
extension). This name must be unique.
|
|
152
|
-
content (str
|
|
153
|
-
|
|
154
|
+
extension). This name must be unique unless overwrite is True.
|
|
155
|
+
content (str): The initial content to write in the note.
|
|
156
|
+
overwrite (bool): Whether to overwrite an existing note.
|
|
157
|
+
Defaults to False.
|
|
154
158
|
|
|
155
159
|
Returns:
|
|
156
160
|
str: A message confirming the creation of the note or an error if
|
|
157
|
-
|
|
161
|
+
the note name is not valid or already exists
|
|
162
|
+
(when overwrite=False).
|
|
158
163
|
"""
|
|
159
164
|
try:
|
|
160
165
|
note_path = self.working_directory / f"{note_name}.md"
|
|
166
|
+
existed_before = note_path.exists()
|
|
161
167
|
|
|
162
|
-
if
|
|
168
|
+
if existed_before and not overwrite:
|
|
163
169
|
return f"Error: Note '{note_name}.md' already exists."
|
|
164
170
|
|
|
165
171
|
note_path.write_text(content, encoding="utf-8")
|
|
166
172
|
self._register_note(note_name)
|
|
167
173
|
|
|
168
|
-
|
|
174
|
+
if existed_before and overwrite:
|
|
175
|
+
return f"Note '{note_name}.md' successfully overwritten."
|
|
176
|
+
else:
|
|
177
|
+
return f"Note '{note_name}.md' successfully created."
|
|
169
178
|
except Exception as e:
|
|
170
179
|
return f"Error creating note: {e}"
|
|
171
180
|
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
|
|
15
15
|
from typing import Any, ClassVar, Dict, List, Optional, Set
|
|
16
16
|
|
|
17
|
-
from camel.toolkits import
|
|
17
|
+
from camel.toolkits import FunctionTool
|
|
18
18
|
|
|
19
19
|
from .mcp_toolkit import MCPToolkit
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
class NotionMCPToolkit(
|
|
22
|
+
class NotionMCPToolkit(MCPToolkit):
|
|
23
23
|
r"""NotionMCPToolkit provides an interface for interacting with Notion
|
|
24
24
|
through the Model Context Protocol (MCP).
|
|
25
25
|
|
|
@@ -75,31 +75,21 @@ class NotionMCPToolkit(BaseToolkit):
|
|
|
75
75
|
timeout (Optional[float]): Connection timeout in seconds.
|
|
76
76
|
(default: :obj:`None`)
|
|
77
77
|
"""
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
|
|
87
|
-
"mcp-remote",
|
|
88
|
-
"https://mcp.notion.com/mcp",
|
|
89
|
-
],
|
|
90
|
-
}
|
|
78
|
+
config_dict = {
|
|
79
|
+
"mcpServers": {
|
|
80
|
+
"notionMCP": {
|
|
81
|
+
"command": "npx",
|
|
82
|
+
"args": [
|
|
83
|
+
"-y",
|
|
84
|
+
"mcp-remote",
|
|
85
|
+
"https://mcp.notion.com/mcp",
|
|
86
|
+
],
|
|
91
87
|
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
async def connect(self):
|
|
97
|
-
r"""Explicitly connect to the Notion MCP server."""
|
|
98
|
-
await self._mcp_toolkit.connect()
|
|
88
|
+
}
|
|
89
|
+
}
|
|
99
90
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
await self._mcp_toolkit.disconnect()
|
|
91
|
+
# Initialize parent MCPToolkit with Notion configuration
|
|
92
|
+
super().__init__(config_dict=config_dict, timeout=timeout)
|
|
103
93
|
|
|
104
94
|
def get_tools(self) -> List[FunctionTool]:
|
|
105
95
|
r"""Returns a list of tools provided by the NotionMCPToolkit.
|
|
@@ -108,7 +98,7 @@ class NotionMCPToolkit(BaseToolkit):
|
|
|
108
98
|
List[FunctionTool]: List of available tools.
|
|
109
99
|
"""
|
|
110
100
|
all_tools = []
|
|
111
|
-
for client in self.
|
|
101
|
+
for client in self.clients:
|
|
112
102
|
try:
|
|
113
103
|
original_build_schema = client._build_tool_schema
|
|
114
104
|
|
camel/toolkits/openbb_toolkit.py
CHANGED
|
@@ -17,7 +17,11 @@ from typing import List, Literal, Optional
|
|
|
17
17
|
|
|
18
18
|
from camel.toolkits.base import BaseToolkit
|
|
19
19
|
from camel.toolkits.function_tool import FunctionTool
|
|
20
|
-
from camel.utils import
|
|
20
|
+
from camel.utils import (
|
|
21
|
+
MCPServer,
|
|
22
|
+
api_keys_required,
|
|
23
|
+
dependencies_required,
|
|
24
|
+
)
|
|
21
25
|
|
|
22
26
|
|
|
23
27
|
@MCPServer()
|
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
# limitations under the License.
|
|
13
13
|
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
|
|
14
14
|
|
|
15
|
-
from typing import Dict,
|
|
15
|
+
from typing import Dict, Optional
|
|
16
16
|
|
|
17
|
-
from
|
|
17
|
+
from .mcp_toolkit import MCPToolkit
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
class OrigeneToolkit(
|
|
20
|
+
class OrigeneToolkit(MCPToolkit):
|
|
21
21
|
r"""OrigeneToolkit provides an interface for interacting with
|
|
22
22
|
Origene MCP server.
|
|
23
23
|
|
|
@@ -43,55 +43,14 @@ class OrigeneToolkit(BaseToolkit):
|
|
|
43
43
|
|
|
44
44
|
Args:
|
|
45
45
|
config_dict (Optional[Dict]): Configuration dictionary for MCP
|
|
46
|
-
servers. If None,
|
|
47
|
-
(default: :obj:`None`)
|
|
46
|
+
servers. If None, raises ValueError as configuration is
|
|
47
|
+
required. (default: :obj:`None`)
|
|
48
48
|
timeout (Optional[float]): Connection timeout in seconds.
|
|
49
49
|
(default: :obj:`None`)
|
|
50
50
|
"""
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
# Use default configuration if none provided
|
|
51
|
+
# Validate that config_dict is provided
|
|
54
52
|
if config_dict is None:
|
|
55
53
|
raise ValueError("config_dict must be provided")
|
|
56
54
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
timeout=timeout,
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
async def connect(self):
|
|
63
|
-
r"""Explicitly connect to the Origene MCP server."""
|
|
64
|
-
await self._mcp_toolkit.connect()
|
|
65
|
-
|
|
66
|
-
async def disconnect(self):
|
|
67
|
-
r"""Explicitly disconnect from the Origene MCP server."""
|
|
68
|
-
await self._mcp_toolkit.disconnect()
|
|
69
|
-
|
|
70
|
-
async def __aenter__(self) -> "OrigeneToolkit":
|
|
71
|
-
r"""Async context manager entry point.
|
|
72
|
-
|
|
73
|
-
Returns:
|
|
74
|
-
OrigeneToolkit: The connected toolkit instance.
|
|
75
|
-
|
|
76
|
-
Example:
|
|
77
|
-
async with OrigeneToolkit(config_dict=config) as toolkit:
|
|
78
|
-
tools = toolkit.get_tools()
|
|
79
|
-
"""
|
|
80
|
-
await self.connect()
|
|
81
|
-
return self
|
|
82
|
-
|
|
83
|
-
async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
|
|
84
|
-
r"""Async context manager exit point.
|
|
85
|
-
|
|
86
|
-
Automatically disconnects from the Origene MCP server.
|
|
87
|
-
"""
|
|
88
|
-
await self.disconnect()
|
|
89
|
-
return None
|
|
90
|
-
|
|
91
|
-
def get_tools(self) -> List[FunctionTool]:
|
|
92
|
-
r"""Returns a list of tools provided by the Origene MCP server.
|
|
93
|
-
|
|
94
|
-
Returns:
|
|
95
|
-
List[FunctionTool]: List of available tools.
|
|
96
|
-
"""
|
|
97
|
-
return self._mcp_toolkit.get_tools()
|
|
55
|
+
# Initialize parent MCPToolkit with provided configuration
|
|
56
|
+
super().__init__(config_dict=config_dict, timeout=timeout)
|
|
@@ -14,12 +14,10 @@
|
|
|
14
14
|
|
|
15
15
|
from typing import List, Optional
|
|
16
16
|
|
|
17
|
-
from camel.toolkits import BaseToolkit, FunctionTool
|
|
18
|
-
|
|
19
17
|
from .mcp_toolkit import MCPToolkit
|
|
20
18
|
|
|
21
19
|
|
|
22
|
-
class PlaywrightMCPToolkit(
|
|
20
|
+
class PlaywrightMCPToolkit(MCPToolkit):
|
|
23
21
|
r"""PlaywrightMCPToolkit provides an interface for interacting with web
|
|
24
22
|
browsers using the Playwright automation library through the Model Context
|
|
25
23
|
Protocol (MCP).
|
|
@@ -51,33 +49,16 @@ class PlaywrightMCPToolkit(BaseToolkit):
|
|
|
51
49
|
`["--cdp-endpoint=http://localhost:9222"]`.
|
|
52
50
|
(default: :obj:`None`)
|
|
53
51
|
"""
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
"
|
|
60
|
-
|
|
61
|
-
"args": ["@playwright/mcp@latest"]
|
|
62
|
-
+ (additional_args or []),
|
|
63
|
-
}
|
|
52
|
+
# Create config for Playwright MCP server
|
|
53
|
+
config_dict = {
|
|
54
|
+
"mcpServers": {
|
|
55
|
+
"playwright": {
|
|
56
|
+
"command": "npx",
|
|
57
|
+
"args": ["@playwright/mcp@latest"]
|
|
58
|
+
+ (additional_args or []),
|
|
64
59
|
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
async def connect(self):
|
|
70
|
-
r"""Explicitly connect to the Playwright MCP server."""
|
|
71
|
-
await self._mcp_toolkit.connect()
|
|
60
|
+
}
|
|
61
|
+
}
|
|
72
62
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
await self._mcp_toolkit.disconnect()
|
|
76
|
-
|
|
77
|
-
def get_tools(self) -> List[FunctionTool]:
|
|
78
|
-
r"""Returns a list of tools provided by the PlaywrightMCPToolkit.
|
|
79
|
-
|
|
80
|
-
Returns:
|
|
81
|
-
List[FunctionTool]: List of available tools.
|
|
82
|
-
"""
|
|
83
|
-
return self._mcp_toolkit.get_tools()
|
|
63
|
+
# Initialize parent MCPToolkit with Playwright configuration
|
|
64
|
+
super().__init__(config_dict=config_dict, timeout=timeout)
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# ========= Copyright 2023-2024 @ 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-2024 @ CAMEL-AI.org. All Rights Reserved. =========
|
|
14
|
+
|
|
15
|
+
from typing import Dict, List, Optional, cast
|
|
16
|
+
|
|
17
|
+
from camel.toolkits.base import BaseToolkit
|
|
18
|
+
from camel.toolkits.function_tool import FunctionTool
|
|
19
|
+
from camel.utils import MCPServer, api_keys_required
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@MCPServer()
|
|
23
|
+
class ResendToolkit(BaseToolkit):
|
|
24
|
+
r"""A toolkit for sending emails using the Resend API.
|
|
25
|
+
|
|
26
|
+
This toolkit provides functionality to send emails using Resend's
|
|
27
|
+
Python SDK.It supports sending both HTML and plain text emails,
|
|
28
|
+
with options for multiple recipients, CC, BCC, reply-to
|
|
29
|
+
addresses, and custom headers.
|
|
30
|
+
|
|
31
|
+
Notes:
|
|
32
|
+
To use this toolkit, you need to set the following environment
|
|
33
|
+
variable:
|
|
34
|
+
- RESEND_API_KEY: Your Resend API key. You can get one from
|
|
35
|
+
https://resend.com/api-keys
|
|
36
|
+
|
|
37
|
+
Example:
|
|
38
|
+
.. code-block:: python
|
|
39
|
+
|
|
40
|
+
from camel.toolkits import ResendToolkit
|
|
41
|
+
|
|
42
|
+
# Initialize the toolkit
|
|
43
|
+
toolkit = ResendToolkit()
|
|
44
|
+
|
|
45
|
+
# Get tools
|
|
46
|
+
tools = toolkit.get_tools()
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
@api_keys_required([(None, "RESEND_API_KEY")])
|
|
50
|
+
def send_email(
|
|
51
|
+
self,
|
|
52
|
+
to: List[str],
|
|
53
|
+
subject: str,
|
|
54
|
+
from_email: str,
|
|
55
|
+
html: Optional[str] = None,
|
|
56
|
+
text: Optional[str] = None,
|
|
57
|
+
cc: Optional[List[str]] = None,
|
|
58
|
+
bcc: Optional[List[str]] = None,
|
|
59
|
+
reply_to: Optional[str] = None,
|
|
60
|
+
tags: Optional[List[Dict[str, str]]] = None,
|
|
61
|
+
headers: Optional[Dict[str, str]] = None,
|
|
62
|
+
) -> str:
|
|
63
|
+
r"""Send an email using the Resend API.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
to (List[str]): List of recipient email addresses.
|
|
67
|
+
subject (str): The email subject line.
|
|
68
|
+
from_email (str): The sender email address. Must be from a verified
|
|
69
|
+
domain.
|
|
70
|
+
html (Optional[str]): The HTML content of the email. Either html or
|
|
71
|
+
text must be provided. (default: :obj:`None`)
|
|
72
|
+
text (Optional[str]): The plain text content of the email. Either
|
|
73
|
+
html or text must be provided. (default: :obj:`None`)
|
|
74
|
+
cc (Optional[List[str]]): List of CC recipient email addresses.
|
|
75
|
+
(default: :obj:`None`)
|
|
76
|
+
bcc (Optional[List[str]]): List of BCC recipient email addresses.
|
|
77
|
+
(default: :obj:`None`)
|
|
78
|
+
reply_to (Optional[str]): The reply-to email address.
|
|
79
|
+
(default: :obj:`None`)
|
|
80
|
+
tags (Optional[List[Dict[str, str]]]): List of tags to attach to
|
|
81
|
+
the email. Each tag should be a dict with 'name' and
|
|
82
|
+
'value' keys. (default: :obj:`None`)
|
|
83
|
+
headers (Optional[Dict[str, str]]): Custom headers to include in
|
|
84
|
+
the email.(default: :obj:`None`)
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
str: A success message with the email ID if sent successfully,
|
|
88
|
+
or an error message if the send failed.
|
|
89
|
+
|
|
90
|
+
Raises:
|
|
91
|
+
ValueError: If neither html nor text content is provided.
|
|
92
|
+
|
|
93
|
+
Example:
|
|
94
|
+
.. code-block:: python
|
|
95
|
+
|
|
96
|
+
toolkit = ResendToolkit()
|
|
97
|
+
result = toolkit.send_email(
|
|
98
|
+
to=["recipient@example.com"],
|
|
99
|
+
subject="Hello World",
|
|
100
|
+
from_email="sender@yourdomain.com",
|
|
101
|
+
html="<h1>Hello, World!</h1>",
|
|
102
|
+
text="Hello, World!"
|
|
103
|
+
)
|
|
104
|
+
"""
|
|
105
|
+
import os
|
|
106
|
+
|
|
107
|
+
if not html and not text:
|
|
108
|
+
raise ValueError(
|
|
109
|
+
"Either 'html' or 'text' content must be provided"
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
try:
|
|
113
|
+
import resend
|
|
114
|
+
except ImportError:
|
|
115
|
+
raise ImportError(
|
|
116
|
+
"Please install the resend package first. "
|
|
117
|
+
"You can install it by running `pip install resend`."
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
# Set the API key
|
|
121
|
+
resend.api_key = os.getenv("RESEND_API_KEY")
|
|
122
|
+
|
|
123
|
+
# Prepare email parameters
|
|
124
|
+
params: resend.Emails.SendParams = {
|
|
125
|
+
"from": from_email,
|
|
126
|
+
"to": to,
|
|
127
|
+
"subject": subject,
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
# Add content
|
|
131
|
+
if html:
|
|
132
|
+
params["html"] = html
|
|
133
|
+
if text:
|
|
134
|
+
params["text"] = text
|
|
135
|
+
|
|
136
|
+
# Add optional parameters
|
|
137
|
+
if cc:
|
|
138
|
+
params["cc"] = cc
|
|
139
|
+
if bcc:
|
|
140
|
+
params["bcc"] = bcc
|
|
141
|
+
if reply_to:
|
|
142
|
+
params["reply_to"] = reply_to
|
|
143
|
+
if tags:
|
|
144
|
+
params["tags"] = cast('list[resend.emails._tag.Tag]', tags)
|
|
145
|
+
if headers:
|
|
146
|
+
params["headers"] = headers
|
|
147
|
+
|
|
148
|
+
try:
|
|
149
|
+
# Send the email
|
|
150
|
+
email = resend.Emails.send(params)
|
|
151
|
+
return (
|
|
152
|
+
f"Email sent successfully. "
|
|
153
|
+
f"Email ID: {email.get('id', 'Unknown')}"
|
|
154
|
+
)
|
|
155
|
+
except Exception as e:
|
|
156
|
+
return f"Failed to send email: {e!s}"
|
|
157
|
+
|
|
158
|
+
def get_tools(self) -> List[FunctionTool]:
|
|
159
|
+
r"""Returns a list of FunctionTool objects representing the
|
|
160
|
+
functions in the toolkit.
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
List[FunctionTool]: A list of FunctionTool objects
|
|
164
|
+
representing the functions in the toolkit.
|
|
165
|
+
"""
|
|
166
|
+
return [
|
|
167
|
+
FunctionTool(self.send_email),
|
|
168
|
+
]
|