camel-ai 0.2.67__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.
Files changed (224) hide show
  1. camel/__init__.py +1 -1
  2. camel/agents/_types.py +6 -2
  3. camel/agents/_utils.py +38 -0
  4. camel/agents/chat_agent.py +4014 -410
  5. camel/agents/mcp_agent.py +30 -27
  6. camel/agents/repo_agent.py +2 -1
  7. camel/benchmarks/browsecomp.py +6 -6
  8. camel/configs/__init__.py +15 -0
  9. camel/configs/aihubmix_config.py +88 -0
  10. camel/configs/amd_config.py +70 -0
  11. camel/configs/cometapi_config.py +104 -0
  12. camel/configs/minimax_config.py +93 -0
  13. camel/configs/nebius_config.py +103 -0
  14. camel/configs/vllm_config.py +2 -0
  15. camel/data_collectors/alpaca_collector.py +15 -6
  16. camel/datagen/self_improving_cot.py +1 -1
  17. camel/datasets/base_generator.py +39 -10
  18. camel/environments/__init__.py +12 -0
  19. camel/environments/rlcards_env.py +860 -0
  20. camel/environments/single_step.py +28 -3
  21. camel/environments/tic_tac_toe.py +1 -1
  22. camel/interpreters/__init__.py +2 -0
  23. camel/interpreters/docker/Dockerfile +4 -16
  24. camel/interpreters/docker_interpreter.py +3 -2
  25. camel/interpreters/e2b_interpreter.py +34 -1
  26. camel/interpreters/internal_python_interpreter.py +51 -2
  27. camel/interpreters/microsandbox_interpreter.py +395 -0
  28. camel/loaders/__init__.py +11 -2
  29. camel/loaders/base_loader.py +85 -0
  30. camel/loaders/chunkr_reader.py +9 -0
  31. camel/loaders/firecrawl_reader.py +4 -4
  32. camel/logger.py +1 -1
  33. camel/memories/agent_memories.py +84 -1
  34. camel/memories/base.py +34 -0
  35. camel/memories/blocks/chat_history_block.py +122 -4
  36. camel/memories/blocks/vectordb_block.py +8 -1
  37. camel/memories/context_creators/score_based.py +29 -237
  38. camel/memories/records.py +88 -8
  39. camel/messages/base.py +166 -40
  40. camel/messages/func_message.py +32 -5
  41. camel/models/__init__.py +10 -0
  42. camel/models/aihubmix_model.py +83 -0
  43. camel/models/aiml_model.py +1 -16
  44. camel/models/amd_model.py +101 -0
  45. camel/models/anthropic_model.py +117 -18
  46. camel/models/aws_bedrock_model.py +2 -33
  47. camel/models/azure_openai_model.py +205 -91
  48. camel/models/base_audio_model.py +3 -1
  49. camel/models/base_model.py +189 -24
  50. camel/models/cohere_model.py +5 -17
  51. camel/models/cometapi_model.py +83 -0
  52. camel/models/crynux_model.py +1 -16
  53. camel/models/deepseek_model.py +6 -16
  54. camel/models/fish_audio_model.py +6 -0
  55. camel/models/gemini_model.py +71 -20
  56. camel/models/groq_model.py +1 -17
  57. camel/models/internlm_model.py +1 -16
  58. camel/models/litellm_model.py +49 -32
  59. camel/models/lmstudio_model.py +1 -17
  60. camel/models/minimax_model.py +83 -0
  61. camel/models/mistral_model.py +1 -16
  62. camel/models/model_factory.py +27 -1
  63. camel/models/model_manager.py +24 -6
  64. camel/models/modelscope_model.py +1 -16
  65. camel/models/moonshot_model.py +185 -19
  66. camel/models/nebius_model.py +83 -0
  67. camel/models/nemotron_model.py +0 -5
  68. camel/models/netmind_model.py +1 -16
  69. camel/models/novita_model.py +1 -16
  70. camel/models/nvidia_model.py +1 -16
  71. camel/models/ollama_model.py +4 -19
  72. camel/models/openai_compatible_model.py +171 -46
  73. camel/models/openai_model.py +205 -77
  74. camel/models/openrouter_model.py +1 -17
  75. camel/models/ppio_model.py +1 -16
  76. camel/models/qianfan_model.py +1 -16
  77. camel/models/qwen_model.py +1 -16
  78. camel/models/reka_model.py +1 -16
  79. camel/models/samba_model.py +34 -47
  80. camel/models/sglang_model.py +64 -31
  81. camel/models/siliconflow_model.py +1 -16
  82. camel/models/stub_model.py +0 -4
  83. camel/models/togetherai_model.py +1 -16
  84. camel/models/vllm_model.py +1 -16
  85. camel/models/volcano_model.py +0 -17
  86. camel/models/watsonx_model.py +1 -16
  87. camel/models/yi_model.py +1 -16
  88. camel/models/zhipuai_model.py +60 -16
  89. camel/parsers/__init__.py +18 -0
  90. camel/parsers/mcp_tool_call_parser.py +176 -0
  91. camel/retrievers/auto_retriever.py +1 -0
  92. camel/runtimes/configs.py +11 -11
  93. camel/runtimes/daytona_runtime.py +15 -16
  94. camel/runtimes/docker_runtime.py +6 -6
  95. camel/runtimes/remote_http_runtime.py +5 -5
  96. camel/services/agent_openapi_server.py +380 -0
  97. camel/societies/__init__.py +2 -0
  98. camel/societies/role_playing.py +26 -28
  99. camel/societies/workforce/__init__.py +2 -0
  100. camel/societies/workforce/events.py +122 -0
  101. camel/societies/workforce/prompts.py +249 -38
  102. camel/societies/workforce/role_playing_worker.py +82 -20
  103. camel/societies/workforce/single_agent_worker.py +634 -34
  104. camel/societies/workforce/structured_output_handler.py +512 -0
  105. camel/societies/workforce/task_channel.py +169 -23
  106. camel/societies/workforce/utils.py +176 -9
  107. camel/societies/workforce/worker.py +77 -23
  108. camel/societies/workforce/workflow_memory_manager.py +772 -0
  109. camel/societies/workforce/workforce.py +3168 -478
  110. camel/societies/workforce/workforce_callback.py +74 -0
  111. camel/societies/workforce/workforce_logger.py +203 -175
  112. camel/societies/workforce/workforce_metrics.py +33 -0
  113. camel/storages/__init__.py +4 -0
  114. camel/storages/key_value_storages/json.py +15 -2
  115. camel/storages/key_value_storages/mem0_cloud.py +48 -47
  116. camel/storages/object_storages/google_cloud.py +1 -1
  117. camel/storages/vectordb_storages/__init__.py +6 -0
  118. camel/storages/vectordb_storages/chroma.py +731 -0
  119. camel/storages/vectordb_storages/oceanbase.py +13 -13
  120. camel/storages/vectordb_storages/pgvector.py +349 -0
  121. camel/storages/vectordb_storages/qdrant.py +3 -3
  122. camel/storages/vectordb_storages/surreal.py +365 -0
  123. camel/storages/vectordb_storages/tidb.py +8 -6
  124. camel/tasks/task.py +244 -27
  125. camel/toolkits/__init__.py +46 -8
  126. camel/toolkits/aci_toolkit.py +64 -19
  127. camel/toolkits/arxiv_toolkit.py +6 -6
  128. camel/toolkits/base.py +63 -5
  129. camel/toolkits/code_execution.py +28 -1
  130. camel/toolkits/context_summarizer_toolkit.py +684 -0
  131. camel/toolkits/craw4ai_toolkit.py +93 -0
  132. camel/toolkits/dappier_toolkit.py +10 -6
  133. camel/toolkits/dingtalk.py +1135 -0
  134. camel/toolkits/edgeone_pages_mcp_toolkit.py +49 -0
  135. camel/toolkits/excel_toolkit.py +901 -67
  136. camel/toolkits/file_toolkit.py +1402 -0
  137. camel/toolkits/function_tool.py +30 -6
  138. camel/toolkits/github_toolkit.py +107 -20
  139. camel/toolkits/gmail_toolkit.py +1839 -0
  140. camel/toolkits/google_calendar_toolkit.py +38 -4
  141. camel/toolkits/google_drive_mcp_toolkit.py +54 -0
  142. camel/toolkits/human_toolkit.py +34 -10
  143. camel/toolkits/hybrid_browser_toolkit/__init__.py +18 -0
  144. camel/toolkits/hybrid_browser_toolkit/config_loader.py +185 -0
  145. camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit.py +246 -0
  146. camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit_ts.py +1973 -0
  147. camel/toolkits/hybrid_browser_toolkit/installer.py +203 -0
  148. camel/toolkits/hybrid_browser_toolkit/ts/package-lock.json +3749 -0
  149. camel/toolkits/hybrid_browser_toolkit/ts/package.json +32 -0
  150. camel/toolkits/hybrid_browser_toolkit/ts/src/browser-scripts.js +125 -0
  151. camel/toolkits/hybrid_browser_toolkit/ts/src/browser-session.ts +1815 -0
  152. camel/toolkits/hybrid_browser_toolkit/ts/src/config-loader.ts +233 -0
  153. camel/toolkits/hybrid_browser_toolkit/ts/src/hybrid-browser-toolkit.ts +590 -0
  154. camel/toolkits/hybrid_browser_toolkit/ts/src/index.ts +7 -0
  155. camel/toolkits/hybrid_browser_toolkit/ts/src/parent-child-filter.ts +226 -0
  156. camel/toolkits/hybrid_browser_toolkit/ts/src/snapshot-parser.ts +219 -0
  157. camel/toolkits/hybrid_browser_toolkit/ts/src/som-screenshot-injected.ts +543 -0
  158. camel/toolkits/hybrid_browser_toolkit/ts/src/types.ts +130 -0
  159. camel/toolkits/hybrid_browser_toolkit/ts/tsconfig.json +26 -0
  160. camel/toolkits/hybrid_browser_toolkit/ts/websocket-server.js +319 -0
  161. camel/toolkits/hybrid_browser_toolkit/ws_wrapper.py +1032 -0
  162. camel/toolkits/hybrid_browser_toolkit_py/__init__.py +17 -0
  163. camel/toolkits/hybrid_browser_toolkit_py/actions.py +575 -0
  164. camel/toolkits/hybrid_browser_toolkit_py/agent.py +311 -0
  165. camel/toolkits/hybrid_browser_toolkit_py/browser_session.py +787 -0
  166. camel/toolkits/hybrid_browser_toolkit_py/config_loader.py +490 -0
  167. camel/toolkits/hybrid_browser_toolkit_py/hybrid_browser_toolkit.py +2390 -0
  168. camel/toolkits/hybrid_browser_toolkit_py/snapshot.py +233 -0
  169. camel/toolkits/hybrid_browser_toolkit_py/stealth_script.js +0 -0
  170. camel/toolkits/hybrid_browser_toolkit_py/unified_analyzer.js +1043 -0
  171. camel/toolkits/image_generation_toolkit.py +390 -0
  172. camel/toolkits/jina_reranker_toolkit.py +3 -4
  173. camel/toolkits/klavis_toolkit.py +5 -1
  174. camel/toolkits/markitdown_toolkit.py +104 -0
  175. camel/toolkits/math_toolkit.py +64 -10
  176. camel/toolkits/mcp_toolkit.py +370 -45
  177. camel/toolkits/memory_toolkit.py +5 -1
  178. camel/toolkits/message_agent_toolkit.py +608 -0
  179. camel/toolkits/message_integration.py +724 -0
  180. camel/toolkits/minimax_mcp_toolkit.py +195 -0
  181. camel/toolkits/note_taking_toolkit.py +277 -0
  182. camel/toolkits/notion_mcp_toolkit.py +224 -0
  183. camel/toolkits/openbb_toolkit.py +5 -1
  184. camel/toolkits/origene_mcp_toolkit.py +56 -0
  185. camel/toolkits/playwright_mcp_toolkit.py +12 -31
  186. camel/toolkits/pptx_toolkit.py +25 -12
  187. camel/toolkits/resend_toolkit.py +168 -0
  188. camel/toolkits/screenshot_toolkit.py +213 -0
  189. camel/toolkits/search_toolkit.py +437 -142
  190. camel/toolkits/slack_toolkit.py +104 -50
  191. camel/toolkits/sympy_toolkit.py +1 -1
  192. camel/toolkits/task_planning_toolkit.py +3 -3
  193. camel/toolkits/terminal_toolkit/__init__.py +18 -0
  194. camel/toolkits/terminal_toolkit/terminal_toolkit.py +957 -0
  195. camel/toolkits/terminal_toolkit/utils.py +532 -0
  196. camel/toolkits/thinking_toolkit.py +1 -1
  197. camel/toolkits/vertex_ai_veo_toolkit.py +590 -0
  198. camel/toolkits/video_analysis_toolkit.py +106 -26
  199. camel/toolkits/video_download_toolkit.py +17 -14
  200. camel/toolkits/web_deploy_toolkit.py +1219 -0
  201. camel/toolkits/wechat_official_toolkit.py +483 -0
  202. camel/toolkits/zapier_toolkit.py +5 -1
  203. camel/types/__init__.py +2 -2
  204. camel/types/agents/tool_calling_record.py +4 -1
  205. camel/types/enums.py +316 -40
  206. camel/types/openai_types.py +2 -2
  207. camel/types/unified_model_type.py +31 -4
  208. camel/utils/commons.py +36 -5
  209. camel/utils/constants.py +3 -0
  210. camel/utils/context_utils.py +1003 -0
  211. camel/utils/mcp.py +138 -4
  212. camel/utils/mcp_client.py +45 -1
  213. camel/utils/message_summarizer.py +148 -0
  214. camel/utils/token_counting.py +43 -20
  215. camel/utils/tool_result.py +44 -0
  216. {camel_ai-0.2.67.dist-info → camel_ai-0.2.80a2.dist-info}/METADATA +296 -85
  217. {camel_ai-0.2.67.dist-info → camel_ai-0.2.80a2.dist-info}/RECORD +219 -146
  218. camel/loaders/pandas_reader.py +0 -368
  219. camel/toolkits/dalle_toolkit.py +0 -175
  220. camel/toolkits/file_write_toolkit.py +0 -444
  221. camel/toolkits/openai_agent_toolkit.py +0 -135
  222. camel/toolkits/terminal_toolkit.py +0 -1037
  223. {camel_ai-0.2.67.dist-info → camel_ai-0.2.80a2.dist-info}/WHEEL +0 -0
  224. {camel_ai-0.2.67.dist-info → camel_ai-0.2.80a2.dist-info}/licenses/LICENSE +0 -0
@@ -45,8 +45,21 @@ class GoogleCalendarToolkit(BaseToolkit):
45
45
  timeout (Optional[float]): The timeout value for API requests
46
46
  in seconds. If None, no timeout is applied.
47
47
  (default: :obj:`None`)
48
+
49
+ Note:
50
+ Before using this toolkit, make sure to:
51
+ 1. Set the required environment variables: GOOGLE_CLIENT_ID and
52
+ GOOGLE_CLIENT_SECRET
53
+ 2. Configure the redirect URI in Google Cloud Console to
54
+ http://localhost/
48
55
  """
49
56
  super().__init__(timeout=timeout)
57
+ logger.info(
58
+ "Initializing GoogleCalendarToolkit. Make sure to set "
59
+ "GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET environment variables, "
60
+ "and configure the redirect URI in Google Cloud Console to "
61
+ "http://localhost/"
62
+ )
50
63
  self.service = self._get_calendar_service()
51
64
 
52
65
  def create_event(
@@ -197,15 +210,36 @@ class GoogleCalendarToolkit(BaseToolkit):
197
210
 
198
211
  result = []
199
212
  for event in events:
200
- start = event['start'].get(
201
- 'dateTime', event['start'].get('date')
213
+ start_info = event.get('start', {})
214
+ end_info = event.get('end', {})
215
+ start_time = start_info.get(
216
+ 'dateTime', start_info.get('date', 'Unknown')
217
+ )
218
+ end_time = end_info.get(
219
+ 'dateTime', end_info.get('date', 'Unknown')
220
+ )
221
+ timezone = (
222
+ start_info.get('timeZone')
223
+ or end_info.get('timeZone')
224
+ or event.get('timeZone')
202
225
  )
226
+ attendees = [
227
+ attendee.get('email')
228
+ for attendee in event.get('attendees', [])
229
+ if attendee.get('email')
230
+ ]
231
+ organizer = event.get('organizer', {}).get('email')
232
+
203
233
  result.append(
204
234
  {
205
- 'Event ID': event['id'],
235
+ 'Event ID': event.get('id'),
206
236
  'Summary': event.get('summary', 'No Title'),
207
- 'Start Time': start,
237
+ 'Start Time': start_time,
238
+ 'End Time': end_time,
239
+ 'Timezone': timezone,
208
240
  'Link': event.get('htmlLink'),
241
+ 'Attendees': attendees,
242
+ 'Organizer': organizer,
209
243
  }
210
244
  )
211
245
 
@@ -0,0 +1,54 @@
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 Optional
16
+
17
+ from .mcp_toolkit import MCPToolkit
18
+
19
+
20
+ class GoogleDriveMCPToolkit(MCPToolkit):
21
+ r"""GoogleDriveMCPToolkit provides an interface for interacting with
22
+ Google Drive using the Google Drive MCP server.
23
+
24
+ Attributes:
25
+ timeout (Optional[float]): Connection timeout in seconds.
26
+ (default: :obj:`None`)
27
+ """
28
+
29
+ def __init__(
30
+ self,
31
+ timeout: Optional[float] = None,
32
+ credentials_path: Optional[str] = None,
33
+ ) -> None:
34
+ r"""Initializes the GoogleDriveMCPToolkit.
35
+
36
+ Args:
37
+ timeout (Optional[float]): Connection timeout in seconds.
38
+ (default: :obj:`None`)
39
+ credentials_path (Optional[str]): Path to the Google Drive
40
+ credentials file. (default: :obj:`None`)
41
+ """
42
+
43
+ config_dict = {
44
+ "mcpServers": {
45
+ "gdrive": {
46
+ "command": "npx",
47
+ "args": ["-y", "@modelcontextprotocol/server-gdrive"],
48
+ "env": {"GDRIVE_CREDENTIALS_PATH": credentials_path},
49
+ }
50
+ }
51
+ }
52
+
53
+ # Initialize parent MCPToolkit with Playwright configuration
54
+ super().__init__(config_dict=config_dict, timeout=timeout)
@@ -22,16 +22,29 @@ logger = logging.getLogger(__name__)
22
22
 
23
23
 
24
24
  class HumanToolkit(BaseToolkit):
25
- r"""A class representing a toolkit for human interaction."""
25
+ r"""A class representing a toolkit for human interaction.
26
+
27
+ Note:
28
+ This toolkit should be called to send a tidy message to the user to
29
+ keep them informed.
30
+ """
26
31
 
27
32
  def ask_human_via_console(self, question: str) -> str:
28
- r"""Ask a question to the human via the console.
33
+ r"""Use this tool to ask a question to the user when you are stuck,
34
+ need clarification, or require a decision to be made. This is a
35
+ two-way communication channel that will wait for the user's response.
36
+ You should use it to:
37
+ - Clarify ambiguous instructions or requirements.
38
+ - Request missing information that you cannot find (e.g., login
39
+ credentials, file paths).
40
+ - Ask for a decision when there are multiple viable options.
41
+ - Seek help when you encounter an error you cannot resolve on your own.
29
42
 
30
43
  Args:
31
- question (str): The question to ask the human.
44
+ question (str): The question to ask the user.
32
45
 
33
46
  Returns:
34
- str: The answer from the human.
47
+ str: The user's response to the question.
35
48
  """
36
49
  print(f"Question: {question}")
37
50
  logger.info(f"Question: {question}")
@@ -39,18 +52,29 @@ class HumanToolkit(BaseToolkit):
39
52
  logger.info(f"User reply: {reply}")
40
53
  return reply
41
54
 
42
- def send_message_to_user(self, message: str) -> None:
43
- r"""Send a message to the user, without waiting for
44
- a response. This will send to stdout in a noticeable way.
55
+ def send_message_to_user(self, message: str) -> str:
56
+ r"""Use this tool to send a tidy message to the user in one short
57
+ sentence.
45
58
 
46
- This is guaranteed to reach the user regardless of
47
- actual user interface.
59
+ This one-way tool keeps the user informed about your progress,
60
+ decisions, or actions. It does not require a response.
61
+ You should use it to:
62
+ - Announce what you are about to do (e.g., "I will now search for
63
+ papers on GUI Agents.").
64
+ - Report the result of an action (e.g., "I have found 15 relevant
65
+ papers.").
66
+ - State a decision (e.g., "I will now analyze the top 10 papers.").
67
+ - Give a status update during a long-running task.
48
68
 
49
69
  Args:
50
- message (str): The message to send to the user.
70
+ message (str): The tidy and informative message for the user.
71
+
72
+ Returns:
73
+ str: Confirmation that the message was successfully sent.
51
74
  """
52
75
  print(f"\nAgent Message:\n{message}")
53
76
  logger.info(f"\nAgent Message:\n{message}")
77
+ return f"Message successfully sent to user: '{message}'"
54
78
 
55
79
  def get_tools(self) -> List[FunctionTool]:
56
80
  r"""Returns a list of FunctionTool objects representing the
@@ -0,0 +1,18 @@
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
+ from .hybrid_browser_toolkit import HybridBrowserToolkit
15
+
16
+ __all__ = [
17
+ "HybridBrowserToolkit",
18
+ ]
@@ -0,0 +1,185 @@
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
+ from dataclasses import dataclass
15
+ from typing import Any, Dict, Optional
16
+
17
+
18
+ @dataclass
19
+ class BrowserConfig:
20
+ """Browser configuration settings."""
21
+
22
+ # Browser configuration
23
+ headless: bool = True
24
+ user_data_dir: Optional[str] = None
25
+ stealth: bool = False
26
+ console_log_limit: int = 1000
27
+
28
+ # Default settings
29
+ default_start_url: str = "https://google.com/"
30
+
31
+ # Timeout configurations (in milliseconds)
32
+ default_timeout: Optional[int] = None
33
+ short_timeout: Optional[int] = None
34
+ navigation_timeout: int = 30000
35
+ network_idle_timeout: int = 5000
36
+ screenshot_timeout: int = 15000
37
+ page_stability_timeout: int = 1500
38
+ dom_content_loaded_timeout: int = 5000
39
+
40
+ # Viewport configuration
41
+ viewport_limit: bool = False
42
+
43
+ # CDP connection configuration
44
+ connect_over_cdp: bool = False
45
+ cdp_url: Optional[str] = None
46
+ cdp_keep_current_page: bool = False
47
+
48
+ # Full visual mode configuration
49
+ full_visual_mode: bool = False
50
+
51
+
52
+ @dataclass
53
+ class ToolkitConfig:
54
+ """Toolkit-specific configuration."""
55
+
56
+ cache_dir: str = "tmp/"
57
+ browser_log_to_file: bool = False
58
+ log_dir: Optional[str] = None
59
+ session_id: Optional[str] = None
60
+ enabled_tools: Optional[list] = None
61
+
62
+
63
+ class ConfigLoader:
64
+ """Configuration loader for HybridBrowserToolkit."""
65
+
66
+ def __init__(
67
+ self,
68
+ browser_config: Optional[BrowserConfig] = None,
69
+ toolkit_config: Optional[ToolkitConfig] = None,
70
+ ) -> None:
71
+ self.browser_config = browser_config or BrowserConfig()
72
+ self.toolkit_config = toolkit_config or ToolkitConfig()
73
+
74
+ @classmethod
75
+ def from_kwargs(cls, **kwargs) -> 'ConfigLoader':
76
+ """Create ConfigLoader from keyword arguments."""
77
+ browser_kwargs = {}
78
+ toolkit_kwargs = {}
79
+
80
+ # Map arguments to appropriate config classes
81
+ browser_fields = set(BrowserConfig.__dataclass_fields__.keys())
82
+ toolkit_fields = set(ToolkitConfig.__dataclass_fields__.keys())
83
+
84
+ for key, value in kwargs.items():
85
+ # Skip None values to preserve dataclass defaults
86
+ if value is None:
87
+ continue
88
+
89
+ if key in browser_fields:
90
+ browser_kwargs[key] = value
91
+ elif key in toolkit_fields:
92
+ toolkit_kwargs[key] = value
93
+ # Handle some common aliases
94
+ elif key == "userDataDir":
95
+ browser_kwargs["user_data_dir"] = value
96
+ elif key == "defaultStartUrl":
97
+ browser_kwargs["default_start_url"] = value
98
+ elif key == "navigationTimeout":
99
+ browser_kwargs["navigation_timeout"] = value
100
+ elif key == "networkIdleTimeout":
101
+ browser_kwargs["network_idle_timeout"] = value
102
+ elif key == "screenshotTimeout":
103
+ browser_kwargs["screenshot_timeout"] = value
104
+ elif key == "pageStabilityTimeout":
105
+ browser_kwargs["page_stability_timeout"] = value
106
+ elif key == "domContentLoadedTimeout":
107
+ browser_kwargs["dom_content_loaded_timeout"] = value
108
+ elif key == "viewportLimit":
109
+ browser_kwargs["viewport_limit"] = value
110
+ elif key == "connectOverCdp":
111
+ browser_kwargs["connect_over_cdp"] = value
112
+ elif key == "cdpUrl":
113
+ browser_kwargs["cdp_url"] = value
114
+ elif key == "cdpKeepCurrentPage":
115
+ browser_kwargs["cdp_keep_current_page"] = value
116
+ elif key == "consoleLogLimit":
117
+ browser_kwargs["console_log_limit"] = value
118
+ elif key == "cacheDir":
119
+ toolkit_kwargs["cache_dir"] = value
120
+ elif key == "browserLogToFile":
121
+ toolkit_kwargs["browser_log_to_file"] = value
122
+ elif key == "sessionId":
123
+ toolkit_kwargs["session_id"] = value
124
+ elif key == "enabledTools":
125
+ toolkit_kwargs["enabled_tools"] = value
126
+ elif key == "fullVisualMode":
127
+ browser_kwargs["full_visual_mode"] = value
128
+
129
+ browser_config = BrowserConfig(**browser_kwargs)
130
+ toolkit_config = ToolkitConfig(**toolkit_kwargs)
131
+
132
+ return cls(browser_config, toolkit_config)
133
+
134
+ def get_browser_config(self) -> BrowserConfig:
135
+ """Get browser configuration."""
136
+ return self.browser_config
137
+
138
+ def get_toolkit_config(self) -> ToolkitConfig:
139
+ """Get toolkit configuration."""
140
+ return self.toolkit_config
141
+
142
+ def to_ws_config(self) -> Dict[str, Any]:
143
+ """Convert to WebSocket wrapper configuration format."""
144
+ return {
145
+ "headless": self.browser_config.headless,
146
+ "userDataDir": self.browser_config.user_data_dir,
147
+ "stealth": self.browser_config.stealth,
148
+ "defaultStartUrl": self.browser_config.default_start_url,
149
+ "navigationTimeout": self.browser_config.navigation_timeout,
150
+ "networkIdleTimeout": self.browser_config.network_idle_timeout,
151
+ "screenshotTimeout": self.browser_config.screenshot_timeout,
152
+ "pageStabilityTimeout": self.browser_config.page_stability_timeout,
153
+ "browser_log_to_file": self.toolkit_config.browser_log_to_file,
154
+ "log_dir": self.toolkit_config.log_dir,
155
+ "session_id": self.toolkit_config.session_id,
156
+ "viewport_limit": self.browser_config.viewport_limit,
157
+ "connectOverCdp": self.browser_config.connect_over_cdp,
158
+ "cdpUrl": self.browser_config.cdp_url,
159
+ "cdpKeepCurrentPage": self.browser_config.cdp_keep_current_page,
160
+ "fullVisualMode": self.browser_config.full_visual_mode,
161
+ }
162
+
163
+ def get_timeout_config(self) -> Dict[str, Optional[int]]:
164
+ """Get all timeout configurations."""
165
+ return {
166
+ "default_timeout": self.browser_config.default_timeout,
167
+ "short_timeout": self.browser_config.short_timeout,
168
+ "navigation_timeout": self.browser_config.navigation_timeout,
169
+ "network_idle_timeout": self.browser_config.network_idle_timeout,
170
+ "screenshot_timeout": self.browser_config.screenshot_timeout,
171
+ "page_stability_timeout": self.browser_config.page_stability_timeout, # noqa:E501
172
+ "dom_content_loaded_timeout": self.browser_config.dom_content_loaded_timeout, # noqa:E501
173
+ }
174
+
175
+ def update_browser_config(self, **kwargs) -> None:
176
+ """Update browser configuration."""
177
+ for key, value in kwargs.items():
178
+ if hasattr(self.browser_config, key):
179
+ setattr(self.browser_config, key, value)
180
+
181
+ def update_toolkit_config(self, **kwargs) -> None:
182
+ """Update toolkit configuration."""
183
+ for key, value in kwargs.items():
184
+ if hasattr(self.toolkit_config, key):
185
+ setattr(self.toolkit_config, key, value)
@@ -0,0 +1,246 @@
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 Any, List, Literal, Optional
16
+
17
+ from camel.toolkits.base import BaseToolkit
18
+
19
+
20
+ class HybridBrowserToolkit(BaseToolkit):
21
+ r"""A hybrid browser toolkit that can switch between TypeScript and Python
22
+ implementations.
23
+
24
+ This wrapper allows users to choose between:
25
+ - 'typescript': WebSocket-based implementation using TypeScript/Node.js
26
+ - 'python': Pure Python implementation using Playwright directly
27
+
28
+ Args:
29
+ mode (Literal["typescript", "python"]): Implementation mode. -
30
+ 'typescript': Uses WebSocket-based TypeScript implementation -
31
+ 'python': Uses pure Python Playwright implementation. Defaults to
32
+ "typescript".
33
+ headless (bool): Whether to run browser in headless mode.
34
+ Defaults to True.
35
+ user_data_dir (Optional[str]): Directory for user data
36
+ persistence. Defaults to None.
37
+ stealth (bool): Whether to enable stealth mode. Defaults to
38
+ False.
39
+ cache_dir (str): Directory for caching. Defaults to "tmp/".
40
+ enabled_tools (Optional[List[str]]): List of enabled tools.
41
+ Defaults to None.
42
+ browser_log_to_file (bool): Whether to log browser actions to
43
+ file. Defaults to False.
44
+ log_dir (Optional[str]): Custom directory path for log files.
45
+ If None, defaults to "browser_log". Defaults to None.
46
+ session_id (Optional[str]): Session identifier. Defaults to None.
47
+ default_start_url (str): Default URL to start with. Defaults
48
+ to "https://google.com/".
49
+ default_timeout (Optional[int]): Default timeout in
50
+ milliseconds. Defaults to None.
51
+ short_timeout (Optional[int]): Short timeout in milliseconds.
52
+ Defaults to None.
53
+ navigation_timeout (Optional[int]): Navigation timeout in
54
+ milliseconds. Defaults to None.
55
+ network_idle_timeout (Optional[int]): Network idle timeout in
56
+ milliseconds. Defaults to None.
57
+ screenshot_timeout (Optional[int]): Screenshot timeout in
58
+ milliseconds. Defaults to None.
59
+ page_stability_timeout (Optional[int]): Page stability timeout
60
+ in milliseconds. Defaults to None.
61
+ dom_content_loaded_timeout (Optional[int]): DOM content loaded
62
+ timeout in milliseconds. Defaults to None.
63
+ viewport_limit (bool): Whether to filter page snapshot
64
+ elements to only those visible in the current viewport.
65
+ Defaults to False.
66
+ connect_over_cdp (bool): Whether to connect to an existing
67
+ browser via Chrome DevTools Protocol. Defaults to False.
68
+ (Only supported in TypeScript mode)
69
+ cdp_url (Optional[str]): WebSocket endpoint URL for CDP
70
+ connection. Required when connect_over_cdp is True.
71
+ Defaults to None. (Only supported in TypeScript mode)
72
+ cdp_keep_current_page (bool): When True and using CDP mode,
73
+ won't create new pages but use the existing one. Defaults to False.
74
+ (Only supported in TypeScript mode)
75
+ full_visual_mode (bool): When True, browser actions like click,
76
+ browser_open, visit_page, etc. will return 'full visual mode'
77
+ as snapshot instead of actual page content. The
78
+ browser_get_page_snapshot method will still return the actual
79
+ snapshot. Defaults to False.
80
+ **kwargs: Additional keyword arguments passed to the
81
+ implementation.
82
+
83
+ Returns:
84
+ HybridBrowserToolkit instance of the specified implementation.
85
+ """
86
+
87
+ def __new__(
88
+ cls,
89
+ *,
90
+ mode: Literal["typescript", "python"] = "typescript",
91
+ headless: bool = True,
92
+ user_data_dir: Optional[str] = None,
93
+ stealth: bool = False,
94
+ cache_dir: Optional[str] = None,
95
+ enabled_tools: Optional[List[str]] = None,
96
+ browser_log_to_file: bool = False,
97
+ log_dir: Optional[str] = None,
98
+ session_id: Optional[str] = None,
99
+ default_start_url: Optional[str] = None,
100
+ default_timeout: Optional[int] = None,
101
+ short_timeout: Optional[int] = None,
102
+ navigation_timeout: Optional[int] = None,
103
+ network_idle_timeout: Optional[int] = None,
104
+ screenshot_timeout: Optional[int] = None,
105
+ page_stability_timeout: Optional[int] = None,
106
+ dom_content_loaded_timeout: Optional[int] = None,
107
+ viewport_limit: bool = False,
108
+ connect_over_cdp: bool = False,
109
+ cdp_url: Optional[str] = None,
110
+ cdp_keep_current_page: bool = False,
111
+ full_visual_mode: bool = False,
112
+ **kwargs: Any,
113
+ ) -> Any:
114
+ r"""Create a HybridBrowserToolkit instance with the specified mode.
115
+
116
+ Args:
117
+ mode (Literal["typescript", "python"]): Implementation mode.
118
+ - 'typescript': Uses WebSocket-based TypeScript implementation
119
+ - 'python': Uses pure Python Playwright implementation
120
+ Defaults to "typescript".
121
+ headless (bool): Whether to run browser in headless mode.
122
+ Defaults to True.
123
+ user_data_dir (Optional[str]): Directory for user data
124
+ persistence. Defaults to None.
125
+ stealth (bool): Whether to enable stealth mode. Defaults to
126
+ False.
127
+ cache_dir (str): Directory for caching. Defaults to "tmp/".
128
+ enabled_tools (Optional[List[str]]): List of enabled tools.
129
+ Defaults to None.
130
+ browser_log_to_file (bool): Whether to log browser actions to
131
+ file. Defaults to False.
132
+ log_dir (Optional[str]): Custom directory path for log files.
133
+ If None, defaults to "browser_log". Defaults to None.
134
+ session_id (Optional[str]): Session identifier. Defaults to None.
135
+ default_start_url (str): Default URL to start with. Defaults
136
+ to "https://google.com/".
137
+ default_timeout (Optional[int]): Default timeout in
138
+ milliseconds. Defaults to None.
139
+ short_timeout (Optional[int]): Short timeout in milliseconds.
140
+ Defaults to None.
141
+ navigation_timeout (Optional[int]): Navigation timeout in
142
+ milliseconds. Defaults to None.
143
+ network_idle_timeout (Optional[int]): Network idle timeout in
144
+ milliseconds. Defaults to None.
145
+ screenshot_timeout (Optional[int]): Screenshot timeout in
146
+ milliseconds. Defaults to None.
147
+ page_stability_timeout (Optional[int]): Page stability timeout
148
+ in milliseconds. Defaults to None.
149
+ dom_content_loaded_timeout (Optional[int]): DOM content loaded
150
+ timeout in milliseconds. Defaults to None.
151
+ viewport_limit (bool): Whether to filter page snapshot
152
+ elements to only those visible in the current viewport.
153
+ Defaults to False.
154
+ connect_over_cdp (bool): Whether to connect to an existing
155
+ browser via Chrome DevTools Protocol. Defaults to False.
156
+ (Only supported in TypeScript mode)
157
+ cdp_url (Optional[str]): WebSocket endpoint URL for CDP
158
+ connection. Required when connect_over_cdp is True.
159
+ Defaults to None. (Only supported in TypeScript mode)
160
+ cdp_keep_current_page (bool): When True and using CDP mode,
161
+ won't create new pages but use the existing one. Defaults to False.
162
+ (Only supported in TypeScript mode)
163
+ full_visual_mode (bool): When True, browser actions like click,
164
+ browser_open, visit_page, etc. will return 'full visual mode'
165
+ as snapshot instead of actual page content. The
166
+ browser_get_page_snapshot method will still return the actual
167
+ snapshot. Defaults to False.
168
+ **kwargs: Additional keyword arguments passed to the
169
+ implementation.
170
+
171
+ Returns:
172
+ HybridBrowserToolkit instance of the specified implementation.
173
+ """
174
+ if mode == "typescript":
175
+ from .hybrid_browser_toolkit_ts import (
176
+ HybridBrowserToolkit as TSToolkit,
177
+ )
178
+
179
+ return TSToolkit(
180
+ headless=headless,
181
+ user_data_dir=user_data_dir,
182
+ stealth=stealth,
183
+ cache_dir=cache_dir,
184
+ enabled_tools=enabled_tools,
185
+ browser_log_to_file=browser_log_to_file,
186
+ log_dir=log_dir,
187
+ session_id=session_id,
188
+ default_start_url=default_start_url,
189
+ default_timeout=default_timeout,
190
+ short_timeout=short_timeout,
191
+ navigation_timeout=navigation_timeout,
192
+ network_idle_timeout=network_idle_timeout,
193
+ screenshot_timeout=screenshot_timeout,
194
+ page_stability_timeout=page_stability_timeout,
195
+ dom_content_loaded_timeout=dom_content_loaded_timeout,
196
+ viewport_limit=viewport_limit,
197
+ connect_over_cdp=connect_over_cdp,
198
+ cdp_url=cdp_url,
199
+ cdp_keep_current_page=cdp_keep_current_page,
200
+ full_visual_mode=full_visual_mode,
201
+ **kwargs,
202
+ )
203
+ elif mode == "python":
204
+ from ..hybrid_browser_toolkit_py import (
205
+ HybridBrowserToolkit as PyToolkit,
206
+ )
207
+
208
+ # Note: Python implementation doesn't support CDP connection
209
+ if connect_over_cdp:
210
+ raise ValueError(
211
+ "CDP connection is only supported in TypeScript mode"
212
+ )
213
+
214
+ # Note: Python implementation doesn't support viewport_limit
215
+ if viewport_limit:
216
+ import warnings
217
+
218
+ warnings.warn(
219
+ "viewport_limit is not supported "
220
+ "in Python mode and will be ignored",
221
+ UserWarning,
222
+ )
223
+
224
+ return PyToolkit(
225
+ headless=headless,
226
+ user_data_dir=user_data_dir,
227
+ stealth=stealth,
228
+ cache_dir=cache_dir,
229
+ enabled_tools=enabled_tools,
230
+ browser_log_to_file=browser_log_to_file,
231
+ log_dir=log_dir,
232
+ session_id=session_id,
233
+ default_start_url=default_start_url,
234
+ default_timeout=default_timeout,
235
+ short_timeout=short_timeout,
236
+ navigation_timeout=navigation_timeout,
237
+ network_idle_timeout=network_idle_timeout,
238
+ screenshot_timeout=screenshot_timeout,
239
+ page_stability_timeout=page_stability_timeout,
240
+ dom_content_loaded_timeout=dom_content_loaded_timeout,
241
+ **kwargs,
242
+ )
243
+ else:
244
+ raise ValueError(
245
+ f"Invalid mode: {mode}. Must be 'typescript' or 'python'."
246
+ )