camel-ai 0.2.76a0__py3-none-any.whl → 0.2.76a2__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.

Files changed (34) hide show
  1. camel/__init__.py +1 -1
  2. camel/agents/chat_agent.py +8 -1
  3. camel/environments/tic_tac_toe.py +1 -1
  4. camel/memories/__init__.py +2 -1
  5. camel/memories/agent_memories.py +3 -1
  6. camel/memories/blocks/chat_history_block.py +17 -2
  7. camel/models/base_model.py +30 -0
  8. camel/societies/workforce/single_agent_worker.py +44 -38
  9. camel/societies/workforce/workforce.py +10 -1
  10. camel/storages/object_storages/google_cloud.py +1 -1
  11. camel/toolkits/__init__.py +9 -2
  12. camel/toolkits/aci_toolkit.py +45 -0
  13. camel/toolkits/context_summarizer_toolkit.py +683 -0
  14. camel/toolkits/{file_write_toolkit.py → file_toolkit.py} +194 -34
  15. camel/toolkits/hybrid_browser_toolkit/config_loader.py +4 -0
  16. camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit.py +67 -2
  17. camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit_ts.py +62 -45
  18. camel/toolkits/hybrid_browser_toolkit/ts/src/browser-session.ts +489 -60
  19. camel/toolkits/hybrid_browser_toolkit/ts/src/config-loader.ts +5 -2
  20. camel/toolkits/hybrid_browser_toolkit/ts/src/hybrid-browser-toolkit.ts +72 -12
  21. camel/toolkits/hybrid_browser_toolkit/ts/src/snapshot-parser.ts +2 -14
  22. camel/toolkits/hybrid_browser_toolkit/ts/src/types.ts +1 -0
  23. camel/toolkits/hybrid_browser_toolkit/ws_wrapper.py +228 -62
  24. camel/toolkits/hybrid_browser_toolkit_py/hybrid_browser_toolkit.py +4 -4
  25. camel/toolkits/markitdown_toolkit.py +27 -1
  26. camel/toolkits/note_taking_toolkit.py +18 -8
  27. camel/toolkits/slack_toolkit.py +50 -1
  28. camel/toolkits/vertex_ai_veo_toolkit.py +590 -0
  29. camel/toolkits/wechat_official_toolkit.py +483 -0
  30. camel/utils/context_utils.py +395 -0
  31. {camel_ai-0.2.76a0.dist-info → camel_ai-0.2.76a2.dist-info}/METADATA +84 -6
  32. {camel_ai-0.2.76a0.dist-info → camel_ai-0.2.76a2.dist-info}/RECORD +34 -30
  33. {camel_ai-0.2.76a0.dist-info → camel_ai-0.2.76a2.dist-info}/WHEEL +0 -0
  34. {camel_ai-0.2.76a0.dist-info → camel_ai-0.2.76a2.dist-info}/licenses/LICENSE +0 -0
@@ -15,7 +15,7 @@ import os
15
15
  import re
16
16
  from datetime import datetime
17
17
  from pathlib import Path
18
- from typing import List, Optional, Tuple, Union
18
+ from typing import Dict, List, Optional, Tuple, Union
19
19
 
20
20
  from camel.logger import get_logger
21
21
  from camel.toolkits.base import BaseToolkit
@@ -26,14 +26,17 @@ logger = get_logger(__name__)
26
26
 
27
27
 
28
28
  @MCPServer()
29
- class FileWriteToolkit(BaseToolkit):
30
- r"""A toolkit for creating, writing, and modifying text in files.
31
-
32
- This class provides cross-platform (macOS, Linux, Windows) support for
33
- writing to various file formats (Markdown, DOCX, PDF, and plaintext),
34
- replacing text in existing files, automatic filename uniquification to
35
- prevent overwrites, custom encoding and enhanced formatting options for
36
- specialized formats.
29
+ class FileToolkit(BaseToolkit):
30
+ r"""A comprehensive toolkit for file operations including reading,
31
+ writing, and editing files.
32
+
33
+ This class provides cross-platform (macOS, Linux, Windows) support for:
34
+ - Reading various file formats (text, JSON, YAML, PDF, DOCX)
35
+ - Writing to multiple formats (Markdown, DOCX, PDF, plaintext, JSON,
36
+ YAML, CSV, HTML)
37
+ - Editing and modifying existing files with content replacement
38
+ - Automatic backup creation before modifications
39
+ - Custom encoding and enhanced formatting options
37
40
  """
38
41
 
39
42
  def __init__(
@@ -126,36 +129,32 @@ class FileWriteToolkit(BaseToolkit):
126
129
  with file_path.open("w", encoding=encoding) as f:
127
130
  f.write(content)
128
131
 
129
- def _generate_unique_filename(self, file_path: Path) -> Path:
130
- r"""Generate a unique filename if the target file already exists.
132
+ def _create_backup(self, file_path: Path) -> Optional[Path]:
133
+ r"""Create a backup of the file if it exists and backup is enabled.
131
134
 
132
135
  Args:
133
- file_path (Path): The original file path.
136
+ file_path (Path): The file path to backup.
134
137
 
135
138
  Returns:
136
- Path: A unique file path that doesn't exist yet.
139
+ Optional[Path]: Path to the backup file if created, None otherwise.
137
140
  """
138
- if not file_path.exists():
139
- return file_path
141
+ if not self.backup_enabled or not file_path.exists():
142
+ return None
140
143
 
141
- # Generate unique filename with timestamp and counter
144
+ # Generate backup filename with .bak extension and timestamp
142
145
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
143
- stem = file_path.stem
144
- suffix = file_path.suffix
145
- parent = file_path.parent
146
-
147
- # First try with timestamp
148
- new_path = parent / f"{stem}_{timestamp}{suffix}"
149
- if not new_path.exists():
150
- return new_path
151
-
152
- # If timestamp version exists, add counter
153
- counter = 1
154
- while True:
155
- new_path = parent / f"{stem}_{timestamp}_{counter}{suffix}"
156
- if not new_path.exists():
157
- return new_path
158
- counter += 1
146
+ backup_path = file_path.parent / f"{file_path.name}.{timestamp}.bak"
147
+
148
+ # Copy the file to backup location
149
+ import shutil
150
+
151
+ try:
152
+ shutil.copy2(file_path, backup_path)
153
+ logger.info(f"Created backup: {backup_path}")
154
+ return backup_path
155
+ except Exception as e:
156
+ logger.warning(f"Failed to create backup: {e}")
157
+ return None
159
158
 
160
159
  def _write_docx_file(self, file_path: Path, content: str) -> None:
161
160
  r"""Write text content to a DOCX file with default formatting.
@@ -1006,8 +1005,9 @@ class FileWriteToolkit(BaseToolkit):
1006
1005
  file_path = self._resolve_filepath(filename)
1007
1006
  file_path.parent.mkdir(parents=True, exist_ok=True)
1008
1007
 
1009
- # Generate unique filename if file exists
1010
- file_path = self._generate_unique_filename(file_path)
1008
+ # Create backup of existing file if backup is enabled
1009
+ if file_path.exists() and self.backup_enabled:
1010
+ self._create_backup(file_path)
1011
1011
 
1012
1012
  extension = file_path.suffix.lower()
1013
1013
 
@@ -1062,6 +1062,144 @@ class FileWriteToolkit(BaseToolkit):
1062
1062
  logger.error(error_msg)
1063
1063
  return error_msg
1064
1064
 
1065
+ # ----------------------------------------------
1066
+ # Read File Functions
1067
+ # ----------------------------------------------
1068
+ def read_file(
1069
+ self, file_paths: Union[str, List[str]]
1070
+ ) -> Union[str, Dict[str, str]]:
1071
+ r"""Read and return content of one or more files using MarkItDown
1072
+ for better format support.
1073
+
1074
+ This method uses MarkItDownLoader to convert various file formats
1075
+ to Markdown. It supports a wide range of formats including:
1076
+ - PDF (.pdf)
1077
+ - Microsoft Office: Word (.doc, .docx), Excel (.xls, .xlsx),
1078
+ PowerPoint (.ppt, .pptx)
1079
+ - EPUB (.epub)
1080
+ - HTML (.html, .htm)
1081
+ - Images (.jpg, .jpeg, .png) for OCR
1082
+ - Audio (.mp3, .wav) for transcription
1083
+ - Text-based formats (.csv, .json, .xml, .txt, .md)
1084
+ - ZIP archives (.zip)
1085
+
1086
+ Args:
1087
+ file_paths (Union[str, List[str]]): A single file path or a list
1088
+ of file paths to read. Paths can be relative or absolute.
1089
+ If relative, they will be resolved relative to the working
1090
+ directory.
1091
+
1092
+ Returns:
1093
+ Union[str, Dict[str, str]]:
1094
+ - If a single file path is provided: Returns the content as
1095
+ a string.
1096
+ - If multiple file paths are provided: Returns a dictionary
1097
+ where keys are file paths and values are the corresponding
1098
+ content in Markdown format.
1099
+ If conversion fails, returns an error message.
1100
+ """
1101
+ from camel.loaders.markitdown import MarkItDownLoader
1102
+
1103
+ try:
1104
+ # Handle single file path for backward compatibility
1105
+ if isinstance(file_paths, str):
1106
+ resolved_path = self._resolve_filepath(file_paths)
1107
+
1108
+ # Use MarkItDownLoader to convert the file
1109
+ result = MarkItDownLoader().convert_files(
1110
+ file_paths=[str(resolved_path)], parallel=False
1111
+ )
1112
+
1113
+ # Return the converted content or error message
1114
+ return result.get(
1115
+ str(resolved_path), f"Failed to read file: {resolved_path}"
1116
+ )
1117
+
1118
+ # Handle multiple file paths
1119
+ else:
1120
+ resolved_paths = [
1121
+ str(self._resolve_filepath(fp)) for fp in file_paths
1122
+ ]
1123
+
1124
+ # Use MarkItDownLoader to convert files in parallel
1125
+ result = MarkItDownLoader().convert_files(
1126
+ file_paths=resolved_paths, parallel=True
1127
+ )
1128
+
1129
+ # Map back to original paths if needed
1130
+ return_dict = {}
1131
+ for original, resolved in zip(file_paths, resolved_paths):
1132
+ return_dict[original] = result.get(
1133
+ resolved, f"Failed to read file: {resolved}"
1134
+ )
1135
+
1136
+ return return_dict
1137
+
1138
+ except Exception as e:
1139
+ return f"Error reading file(s): {e}"
1140
+
1141
+ # ----------------------------------------------
1142
+ # Edit File Functions
1143
+ # ----------------------------------------------
1144
+ def edit_file(
1145
+ self, file_path: str, old_content: str, new_content: str
1146
+ ) -> str:
1147
+ r"""Edit a file by replacing specified content.
1148
+
1149
+ This method performs simple text replacement in files. It reads
1150
+ the file, replaces all occurrences of old_content with new_content,
1151
+ and writes the result back.
1152
+
1153
+ Args:
1154
+ file_path (str): The path to the file to edit. Can be
1155
+ relative or absolute. If relative, it will be resolved
1156
+ relative to the working directory.
1157
+ old_content (str): The exact text to find and replace.
1158
+ new_content (str): The text to replace old_content with.
1159
+
1160
+ Returns:
1161
+ str: A success message if the edit was successful, or an
1162
+ error message if the content wasn't found or an error occurred.
1163
+ """
1164
+ try:
1165
+ working_path = self._resolve_filepath(file_path)
1166
+
1167
+ if not working_path.exists():
1168
+ return f"Error: File {working_path} does not exist"
1169
+
1170
+ # Create backup before editing if enabled
1171
+ self._create_backup(working_path)
1172
+
1173
+ # Read the file content
1174
+ try:
1175
+ file_text = working_path.read_text(
1176
+ encoding=self.default_encoding
1177
+ )
1178
+ except Exception as e:
1179
+ return f"Error reading file: {e}"
1180
+
1181
+ # Check if the old_content exists in the file
1182
+ if old_content not in file_text:
1183
+ return (
1184
+ f"No replacement performed: '{old_content}' not found in "
1185
+ f"{working_path}."
1186
+ )
1187
+
1188
+ # Replace the content
1189
+ new_file_text = file_text.replace(old_content, new_content)
1190
+
1191
+ # Write back to file
1192
+ try:
1193
+ working_path.write_text(
1194
+ new_file_text, encoding=self.default_encoding
1195
+ )
1196
+ return f"Successfully edited {working_path}"
1197
+ except Exception as e:
1198
+ return f"Error writing file: {e}"
1199
+
1200
+ except Exception as e:
1201
+ return f"Error editing file: {e}"
1202
+
1065
1203
  def get_tools(self) -> List[FunctionTool]:
1066
1204
  r"""Return a list of FunctionTool objects representing the functions
1067
1205
  in the toolkit.
@@ -1072,4 +1210,26 @@ class FileWriteToolkit(BaseToolkit):
1072
1210
  """
1073
1211
  return [
1074
1212
  FunctionTool(self.write_to_file),
1213
+ FunctionTool(self.read_file),
1214
+ FunctionTool(self.edit_file),
1075
1215
  ]
1216
+
1217
+
1218
+ # Backward compatibility: FileWriteToolkit as deprecated alias
1219
+ class FileWriteToolkit(FileToolkit):
1220
+ r"""Deprecated: Use FileToolkit instead.
1221
+
1222
+ This class is maintained for backward compatibility only.
1223
+ Please use FileToolkit for new code.
1224
+ """
1225
+
1226
+ def __init__(self, *args, **kwargs):
1227
+ import warnings
1228
+
1229
+ warnings.warn(
1230
+ "FileWriteToolkit is deprecated and will be removed in a "
1231
+ "future version. Please use FileToolkit instead.",
1232
+ DeprecationWarning,
1233
+ stacklevel=2,
1234
+ )
1235
+ super().__init__(*args, **kwargs)
@@ -43,6 +43,7 @@ class BrowserConfig:
43
43
  # CDP connection configuration
44
44
  connect_over_cdp: bool = False
45
45
  cdp_url: Optional[str] = None
46
+ cdp_keep_current_page: bool = False
46
47
 
47
48
  # Full visual mode configuration
48
49
  full_visual_mode: bool = False
@@ -110,6 +111,8 @@ class ConfigLoader:
110
111
  browser_kwargs["connect_over_cdp"] = value
111
112
  elif key == "cdpUrl":
112
113
  browser_kwargs["cdp_url"] = value
114
+ elif key == "cdpKeepCurrentPage":
115
+ browser_kwargs["cdp_keep_current_page"] = value
113
116
  elif key == "consoleLogLimit":
114
117
  browser_kwargs["console_log_limit"] = value
115
118
  elif key == "cacheDir":
@@ -153,6 +156,7 @@ class ConfigLoader:
153
156
  "viewport_limit": self.browser_config.viewport_limit,
154
157
  "connectOverCdp": self.browser_config.connect_over_cdp,
155
158
  "cdpUrl": self.browser_config.cdp_url,
159
+ "cdpKeepCurrentPage": self.browser_config.cdp_keep_current_page,
156
160
  "fullVisualMode": self.browser_config.full_visual_mode,
157
161
  }
158
162
 
@@ -25,6 +25,66 @@ class HybridBrowserToolkit(BaseToolkit):
25
25
  This wrapper allows users to choose between:
26
26
  - 'typescript': WebSocket-based implementation using TypeScript/Node.js
27
27
  - 'python': Pure Python implementation using Playwright directly
28
+
29
+ Args:
30
+ mode (Literal["typescript", "python"]): Implementation mode. -
31
+ 'typescript': Uses WebSocket-based TypeScript implementation -
32
+ 'python': Uses pure Python Playwright implementation. Defaults to
33
+ "typescript".
34
+ headless (bool): Whether to run browser in headless mode.
35
+ Defaults to True.
36
+ user_data_dir (Optional[str]): Directory for user data
37
+ persistence. Defaults to None.
38
+ stealth (bool): Whether to enable stealth mode. Defaults to
39
+ False.
40
+ web_agent_model (Optional[BaseModelBackend]): Model for web
41
+ agent operations. Defaults to None.
42
+ cache_dir (str): Directory for caching. Defaults to "tmp/".
43
+ enabled_tools (Optional[List[str]]): List of enabled tools.
44
+ Defaults to None.
45
+ browser_log_to_file (bool): Whether to log browser actions to
46
+ file. Defaults to False.
47
+ log_dir (Optional[str]): Custom directory path for log files.
48
+ If None, defaults to "browser_log". Defaults to None.
49
+ session_id (Optional[str]): Session identifier. Defaults to None.
50
+ default_start_url (str): Default URL to start with. Defaults
51
+ to "https://google.com/".
52
+ default_timeout (Optional[int]): Default timeout in
53
+ milliseconds. Defaults to None.
54
+ short_timeout (Optional[int]): Short timeout in milliseconds.
55
+ Defaults to None.
56
+ navigation_timeout (Optional[int]): Navigation timeout in
57
+ milliseconds. Defaults to None.
58
+ network_idle_timeout (Optional[int]): Network idle timeout in
59
+ milliseconds. Defaults to None.
60
+ screenshot_timeout (Optional[int]): Screenshot timeout in
61
+ milliseconds. Defaults to None.
62
+ page_stability_timeout (Optional[int]): Page stability timeout
63
+ in milliseconds. Defaults to None.
64
+ dom_content_loaded_timeout (Optional[int]): DOM content loaded
65
+ timeout in milliseconds. Defaults to None.
66
+ viewport_limit (bool): Whether to filter page snapshot
67
+ elements to only those visible in the current viewport.
68
+ Defaults to False.
69
+ connect_over_cdp (bool): Whether to connect to an existing
70
+ browser via Chrome DevTools Protocol. Defaults to False.
71
+ (Only supported in TypeScript mode)
72
+ cdp_url (Optional[str]): WebSocket endpoint URL for CDP
73
+ connection. Required when connect_over_cdp is True.
74
+ Defaults to None. (Only supported in TypeScript mode)
75
+ cdp_keep_current_page (bool): When True and using CDP mode,
76
+ won't create new pages but use the existing one. Defaults to False.
77
+ (Only supported in TypeScript mode)
78
+ full_visual_mode (bool): When True, browser actions like click,
79
+ browser_open, visit_page, etc. will return 'full visual mode'
80
+ as snapshot instead of actual page content. The
81
+ browser_get_page_snapshot method will still return the actual
82
+ snapshot. Defaults to False.
83
+ **kwargs: Additional keyword arguments passed to the
84
+ implementation.
85
+
86
+ Returns:
87
+ HybridBrowserToolkit instance of the specified implementation.
28
88
  """
29
89
 
30
90
  def __new__(
@@ -35,12 +95,12 @@ class HybridBrowserToolkit(BaseToolkit):
35
95
  user_data_dir: Optional[str] = None,
36
96
  stealth: bool = False,
37
97
  web_agent_model: Optional[BaseModelBackend] = None,
38
- cache_dir: str = "tmp/",
98
+ cache_dir: Optional[str] = None,
39
99
  enabled_tools: Optional[List[str]] = None,
40
100
  browser_log_to_file: bool = False,
41
101
  log_dir: Optional[str] = None,
42
102
  session_id: Optional[str] = None,
43
- default_start_url: str = "https://google.com/",
103
+ default_start_url: Optional[str] = None,
44
104
  default_timeout: Optional[int] = None,
45
105
  short_timeout: Optional[int] = None,
46
106
  navigation_timeout: Optional[int] = None,
@@ -51,6 +111,7 @@ class HybridBrowserToolkit(BaseToolkit):
51
111
  viewport_limit: bool = False,
52
112
  connect_over_cdp: bool = False,
53
113
  cdp_url: Optional[str] = None,
114
+ cdp_keep_current_page: bool = False,
54
115
  full_visual_mode: bool = False,
55
116
  **kwargs: Any,
56
117
  ) -> Any:
@@ -102,6 +163,9 @@ class HybridBrowserToolkit(BaseToolkit):
102
163
  cdp_url (Optional[str]): WebSocket endpoint URL for CDP
103
164
  connection. Required when connect_over_cdp is True.
104
165
  Defaults to None. (Only supported in TypeScript mode)
166
+ cdp_keep_current_page (bool): When True and using CDP mode,
167
+ won't create new pages but use the existing one. Defaults to False.
168
+ (Only supported in TypeScript mode)
105
169
  full_visual_mode (bool): When True, browser actions like click,
106
170
  browser_open, visit_page, etc. will return 'full visual mode'
107
171
  as snapshot instead of actual page content. The
@@ -139,6 +203,7 @@ class HybridBrowserToolkit(BaseToolkit):
139
203
  viewport_limit=viewport_limit,
140
204
  connect_over_cdp=connect_over_cdp,
141
205
  cdp_url=cdp_url,
206
+ cdp_keep_current_page=cdp_keep_current_page,
142
207
  full_visual_mode=full_visual_mode,
143
208
  **kwargs,
144
209
  )