camel-ai 0.2.72a8__py3-none-any.whl → 0.2.73__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 +1 -1
- camel/agents/chat_agent.py +140 -345
- camel/memories/agent_memories.py +18 -17
- camel/societies/__init__.py +2 -0
- camel/societies/workforce/prompts.py +36 -10
- camel/societies/workforce/single_agent_worker.py +7 -5
- camel/societies/workforce/workforce.py +6 -4
- camel/storages/key_value_storages/mem0_cloud.py +48 -47
- camel/storages/vectordb_storages/__init__.py +1 -0
- camel/storages/vectordb_storages/surreal.py +100 -150
- camel/toolkits/__init__.py +6 -1
- camel/toolkits/base.py +60 -2
- camel/toolkits/excel_toolkit.py +153 -64
- camel/toolkits/file_write_toolkit.py +67 -0
- camel/toolkits/hybrid_browser_toolkit/config_loader.py +136 -413
- camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit.py +131 -1966
- camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit_ts.py +1177 -0
- camel/toolkits/hybrid_browser_toolkit/ts/package-lock.json +4356 -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 +945 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/config-loader.ts +226 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/hybrid-browser-toolkit.ts +522 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/index.ts +7 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/types.ts +110 -0
- camel/toolkits/hybrid_browser_toolkit/ts/tsconfig.json +26 -0
- camel/toolkits/hybrid_browser_toolkit/ts/websocket-server.js +254 -0
- camel/toolkits/hybrid_browser_toolkit/ws_wrapper.py +582 -0
- camel/toolkits/hybrid_browser_toolkit_py/__init__.py +17 -0
- camel/toolkits/hybrid_browser_toolkit_py/config_loader.py +447 -0
- camel/toolkits/hybrid_browser_toolkit_py/hybrid_browser_toolkit.py +2077 -0
- camel/toolkits/mcp_toolkit.py +341 -46
- camel/toolkits/message_integration.py +719 -0
- camel/toolkits/note_taking_toolkit.py +18 -29
- camel/toolkits/notion_mcp_toolkit.py +234 -0
- camel/toolkits/screenshot_toolkit.py +116 -31
- camel/toolkits/search_toolkit.py +20 -2
- camel/toolkits/slack_toolkit.py +43 -48
- camel/toolkits/terminal_toolkit.py +288 -46
- camel/toolkits/video_analysis_toolkit.py +13 -13
- camel/toolkits/video_download_toolkit.py +11 -11
- camel/toolkits/web_deploy_toolkit.py +207 -12
- camel/types/enums.py +6 -0
- {camel_ai-0.2.72a8.dist-info → camel_ai-0.2.73.dist-info}/METADATA +49 -9
- {camel_ai-0.2.72a8.dist-info → camel_ai-0.2.73.dist-info}/RECORD +53 -36
- /camel/toolkits/{hybrid_browser_toolkit → hybrid_browser_toolkit_py}/actions.py +0 -0
- /camel/toolkits/{hybrid_browser_toolkit → hybrid_browser_toolkit_py}/agent.py +0 -0
- /camel/toolkits/{hybrid_browser_toolkit → hybrid_browser_toolkit_py}/browser_session.py +0 -0
- /camel/toolkits/{hybrid_browser_toolkit → hybrid_browser_toolkit_py}/snapshot.py +0 -0
- /camel/toolkits/{hybrid_browser_toolkit → hybrid_browser_toolkit_py}/stealth_script.js +0 -0
- /camel/toolkits/{hybrid_browser_toolkit → hybrid_browser_toolkit_py}/unified_analyzer.js +0 -0
- {camel_ai-0.2.72a8.dist-info → camel_ai-0.2.73.dist-info}/WHEEL +0 -0
- {camel_ai-0.2.72a8.dist-info → camel_ai-0.2.73.dist-info}/licenses/LICENSE +0 -0
|
@@ -97,7 +97,7 @@ class VideoAnalysisToolkit(BaseToolkit):
|
|
|
97
97
|
r"""A class for analysing videos with vision-language model.
|
|
98
98
|
|
|
99
99
|
Args:
|
|
100
|
-
|
|
100
|
+
working_directory (Optional[str], optional): The directory where the
|
|
101
101
|
video will be downloaded to. If not provided, video will be stored
|
|
102
102
|
in a temporary directory and will be cleaned up after use.
|
|
103
103
|
(default: :obj:`None`)
|
|
@@ -123,7 +123,7 @@ class VideoAnalysisToolkit(BaseToolkit):
|
|
|
123
123
|
@dependencies_required("ffmpeg", "scenedetect")
|
|
124
124
|
def __init__(
|
|
125
125
|
self,
|
|
126
|
-
|
|
126
|
+
working_directory: Optional[str] = None,
|
|
127
127
|
model: Optional[BaseModelBackend] = None,
|
|
128
128
|
use_audio_transcription: bool = False,
|
|
129
129
|
use_ocr: bool = False,
|
|
@@ -133,30 +133,30 @@ class VideoAnalysisToolkit(BaseToolkit):
|
|
|
133
133
|
timeout: Optional[float] = None,
|
|
134
134
|
) -> None:
|
|
135
135
|
super().__init__(timeout=timeout)
|
|
136
|
-
self._cleanup =
|
|
136
|
+
self._cleanup = working_directory is None
|
|
137
137
|
self._temp_files: list[str] = [] # Track temporary files for cleanup
|
|
138
138
|
self._use_audio_transcription = use_audio_transcription
|
|
139
139
|
self._use_ocr = use_ocr
|
|
140
140
|
self.output_language = output_language
|
|
141
141
|
self.frame_interval = frame_interval
|
|
142
142
|
|
|
143
|
-
self.
|
|
144
|
-
|
|
143
|
+
self._working_directory = Path(
|
|
144
|
+
working_directory or tempfile.mkdtemp()
|
|
145
145
|
).resolve()
|
|
146
146
|
|
|
147
147
|
self.video_downloader_toolkit = VideoDownloaderToolkit(
|
|
148
|
-
|
|
148
|
+
working_directory=str(self._working_directory),
|
|
149
149
|
cookies_path=cookies_path,
|
|
150
150
|
)
|
|
151
151
|
|
|
152
152
|
try:
|
|
153
|
-
self.
|
|
153
|
+
self._working_directory.mkdir(parents=True, exist_ok=True)
|
|
154
154
|
except OSError as e:
|
|
155
155
|
raise ValueError(
|
|
156
|
-
f"Error creating directory {self.
|
|
156
|
+
f"Error creating directory {self._working_directory}: {e}"
|
|
157
157
|
)
|
|
158
158
|
|
|
159
|
-
logger.info(f"Video will be downloaded to {self.
|
|
159
|
+
logger.info(f"Video will be downloaded to {self._working_directory}")
|
|
160
160
|
|
|
161
161
|
self.vl_model = model
|
|
162
162
|
# Ensure ChatAgent is initialized with a model if provided
|
|
@@ -206,16 +206,16 @@ class VideoAnalysisToolkit(BaseToolkit):
|
|
|
206
206
|
)
|
|
207
207
|
|
|
208
208
|
# Clean up temporary directory if needed
|
|
209
|
-
if self._cleanup and os.path.exists(self.
|
|
209
|
+
if self._cleanup and os.path.exists(self._working_directory):
|
|
210
210
|
try:
|
|
211
211
|
import sys
|
|
212
212
|
|
|
213
213
|
if getattr(sys, 'modules', None) is not None:
|
|
214
214
|
import shutil
|
|
215
215
|
|
|
216
|
-
shutil.rmtree(self.
|
|
216
|
+
shutil.rmtree(self._working_directory)
|
|
217
217
|
logger.debug(
|
|
218
|
-
f"Removed temp directory: {self.
|
|
218
|
+
f"Removed temp directory: {self._working_directory}"
|
|
219
219
|
)
|
|
220
220
|
except (ImportError, AttributeError):
|
|
221
221
|
# Skip cleanup if interpreter is shutting down
|
|
@@ -223,7 +223,7 @@ class VideoAnalysisToolkit(BaseToolkit):
|
|
|
223
223
|
except OSError as e:
|
|
224
224
|
logger.warning(
|
|
225
225
|
f"Failed to remove temporary directory "
|
|
226
|
-
f"{self.
|
|
226
|
+
f"{self._working_directory}: {e}"
|
|
227
227
|
)
|
|
228
228
|
|
|
229
229
|
@dependencies_required("pytesseract", "cv2", "numpy")
|
|
@@ -62,7 +62,7 @@ class VideoDownloaderToolkit(BaseToolkit):
|
|
|
62
62
|
chunks.
|
|
63
63
|
|
|
64
64
|
Args:
|
|
65
|
-
|
|
65
|
+
working_directory (Optional[str], optional): The directory where the
|
|
66
66
|
video will be downloaded to. If not provided, video will be stored
|
|
67
67
|
in a temporary directory and will be cleaned up after use.
|
|
68
68
|
(default: :obj:`None`)
|
|
@@ -73,30 +73,30 @@ class VideoDownloaderToolkit(BaseToolkit):
|
|
|
73
73
|
@dependencies_required("yt_dlp", "ffmpeg")
|
|
74
74
|
def __init__(
|
|
75
75
|
self,
|
|
76
|
-
|
|
76
|
+
working_directory: Optional[str] = None,
|
|
77
77
|
cookies_path: Optional[str] = None,
|
|
78
78
|
timeout: Optional[float] = None,
|
|
79
79
|
) -> None:
|
|
80
80
|
super().__init__(timeout=timeout)
|
|
81
|
-
self._cleanup =
|
|
81
|
+
self._cleanup = working_directory is None
|
|
82
82
|
self._cookies_path = cookies_path
|
|
83
83
|
|
|
84
|
-
self.
|
|
85
|
-
|
|
84
|
+
self._working_directory = Path(
|
|
85
|
+
working_directory or tempfile.mkdtemp()
|
|
86
86
|
).resolve()
|
|
87
87
|
|
|
88
88
|
try:
|
|
89
|
-
self.
|
|
89
|
+
self._working_directory.mkdir(parents=True, exist_ok=True)
|
|
90
90
|
except FileExistsError:
|
|
91
91
|
raise ValueError(
|
|
92
|
-
f"{self.
|
|
92
|
+
f"{self._working_directory} is not a valid directory."
|
|
93
93
|
)
|
|
94
94
|
except OSError as e:
|
|
95
95
|
raise ValueError(
|
|
96
|
-
f"Error creating directory {self.
|
|
96
|
+
f"Error creating directory {self._working_directory}: {e}"
|
|
97
97
|
)
|
|
98
98
|
|
|
99
|
-
logger.info(f"Video will be downloaded to {self.
|
|
99
|
+
logger.info(f"Video will be downloaded to {self._working_directory}")
|
|
100
100
|
|
|
101
101
|
def __del__(self) -> None:
|
|
102
102
|
r"""Deconstructor for the VideoDownloaderToolkit class.
|
|
@@ -111,7 +111,7 @@ class VideoDownloaderToolkit(BaseToolkit):
|
|
|
111
111
|
if getattr(sys, 'modules', None) is not None:
|
|
112
112
|
import shutil
|
|
113
113
|
|
|
114
|
-
shutil.rmtree(self.
|
|
114
|
+
shutil.rmtree(self._working_directory, ignore_errors=True)
|
|
115
115
|
except (ImportError, AttributeError):
|
|
116
116
|
# Skip cleanup if interpreter is shutting down
|
|
117
117
|
pass
|
|
@@ -130,7 +130,7 @@ class VideoDownloaderToolkit(BaseToolkit):
|
|
|
130
130
|
"""
|
|
131
131
|
import yt_dlp
|
|
132
132
|
|
|
133
|
-
video_template = self.
|
|
133
|
+
video_template = self._working_directory / "%(title)s.%(ext)s"
|
|
134
134
|
ydl_opts = {
|
|
135
135
|
'format': 'bestvideo+bestaudio/best',
|
|
136
136
|
'outtmpl': str(video_template),
|
|
@@ -79,7 +79,9 @@ class WebDeployToolkit(BaseToolkit):
|
|
|
79
79
|
self.tag_text = self._sanitize_text(tag_text)
|
|
80
80
|
self.tag_url = self._validate_url(tag_url)
|
|
81
81
|
self.remote_server_ip = (
|
|
82
|
-
self.
|
|
82
|
+
self._validate_ip_or_domain(remote_server_ip)
|
|
83
|
+
if remote_server_ip
|
|
84
|
+
else None
|
|
83
85
|
)
|
|
84
86
|
self.remote_server_port = self._validate_port(remote_server_port)
|
|
85
87
|
self.server_registry_file = os.path.join(
|
|
@@ -87,24 +89,36 @@ class WebDeployToolkit(BaseToolkit):
|
|
|
87
89
|
)
|
|
88
90
|
self._load_server_registry()
|
|
89
91
|
|
|
90
|
-
def
|
|
91
|
-
"""Validate IP address format."""
|
|
92
|
+
def _validate_ip_or_domain(self, address: str) -> str:
|
|
93
|
+
r"""Validate IP address or domain name format."""
|
|
92
94
|
import ipaddress
|
|
95
|
+
import re
|
|
93
96
|
|
|
94
97
|
try:
|
|
95
|
-
|
|
96
|
-
|
|
98
|
+
# Try to validate as IP address first
|
|
99
|
+
ipaddress.ip_address(address)
|
|
100
|
+
return address
|
|
97
101
|
except ValueError:
|
|
98
|
-
|
|
102
|
+
# If not a valid IP, check if it's a valid domain name
|
|
103
|
+
domain_pattern = re.compile(
|
|
104
|
+
r'^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?'
|
|
105
|
+
r'(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$'
|
|
106
|
+
)
|
|
107
|
+
if domain_pattern.match(address) and len(address) <= 253:
|
|
108
|
+
return address
|
|
109
|
+
else:
|
|
110
|
+
raise ValueError(
|
|
111
|
+
f"Invalid IP address or domain name: {address}"
|
|
112
|
+
)
|
|
99
113
|
|
|
100
114
|
def _validate_port(self, port: int) -> int:
|
|
101
|
-
"""Validate port number."""
|
|
115
|
+
r"""Validate port number."""
|
|
102
116
|
if not isinstance(port, int) or port < 1 or port > 65535:
|
|
103
117
|
raise ValueError(f"Invalid port number: {port}")
|
|
104
118
|
return port
|
|
105
119
|
|
|
106
120
|
def _sanitize_text(self, text: str) -> str:
|
|
107
|
-
"""Sanitize text to prevent XSS."""
|
|
121
|
+
r"""Sanitize text to prevent XSS."""
|
|
108
122
|
if not isinstance(text, str):
|
|
109
123
|
return ""
|
|
110
124
|
# Remove any HTML/script tags
|
|
@@ -119,7 +133,7 @@ class WebDeployToolkit(BaseToolkit):
|
|
|
119
133
|
return text[:100] # Limit length
|
|
120
134
|
|
|
121
135
|
def _validate_url(self, url: str) -> str:
|
|
122
|
-
"""Validate URL format."""
|
|
136
|
+
r"""Validate URL format."""
|
|
123
137
|
if not isinstance(url, str):
|
|
124
138
|
raise ValueError("URL must be a string")
|
|
125
139
|
# Basic URL validation
|
|
@@ -139,7 +153,7 @@ class WebDeployToolkit(BaseToolkit):
|
|
|
139
153
|
def _validate_subdirectory(
|
|
140
154
|
self, subdirectory: Optional[str]
|
|
141
155
|
) -> Optional[str]:
|
|
142
|
-
"""Validate subdirectory to prevent path traversal."""
|
|
156
|
+
r"""Validate subdirectory to prevent path traversal."""
|
|
143
157
|
if subdirectory is None:
|
|
144
158
|
return None
|
|
145
159
|
|
|
@@ -157,7 +171,7 @@ class WebDeployToolkit(BaseToolkit):
|
|
|
157
171
|
return subdirectory
|
|
158
172
|
|
|
159
173
|
def _is_port_available(self, port: int) -> bool:
|
|
160
|
-
"""Check if a port is available for binding."""
|
|
174
|
+
r"""Check if a port is available for binding."""
|
|
161
175
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
|
162
176
|
try:
|
|
163
177
|
sock.bind(('127.0.0.1', port))
|
|
@@ -604,7 +618,7 @@ class WebDeployToolkit(BaseToolkit):
|
|
|
604
618
|
return {
|
|
605
619
|
'success': False,
|
|
606
620
|
'error': (
|
|
607
|
-
f'Port {port} is already in use by
|
|
621
|
+
f'Port {port} is already in use by another process'
|
|
608
622
|
),
|
|
609
623
|
}
|
|
610
624
|
|
|
@@ -702,6 +716,44 @@ class WebDeployToolkit(BaseToolkit):
|
|
|
702
716
|
# Validate subdirectory
|
|
703
717
|
subdirectory = self._validate_subdirectory(subdirectory)
|
|
704
718
|
|
|
719
|
+
# Check if remote deployment is configured
|
|
720
|
+
if self.remote_server_ip:
|
|
721
|
+
return self._deploy_folder_to_remote_server(
|
|
722
|
+
folder_path,
|
|
723
|
+
subdirectory,
|
|
724
|
+
domain,
|
|
725
|
+
)
|
|
726
|
+
else:
|
|
727
|
+
return self._deploy_folder_to_local_server(
|
|
728
|
+
folder_path,
|
|
729
|
+
port,
|
|
730
|
+
domain,
|
|
731
|
+
subdirectory,
|
|
732
|
+
)
|
|
733
|
+
|
|
734
|
+
except Exception as e:
|
|
735
|
+
logger.error(f"Error deploying folder: {e}")
|
|
736
|
+
return {'success': False, 'error': str(e)}
|
|
737
|
+
|
|
738
|
+
def _deploy_folder_to_local_server(
|
|
739
|
+
self,
|
|
740
|
+
folder_path: str,
|
|
741
|
+
port: int,
|
|
742
|
+
domain: Optional[str],
|
|
743
|
+
subdirectory: Optional[str],
|
|
744
|
+
) -> Dict[str, Any]:
|
|
745
|
+
r"""Deploy folder to local server (original functionality).
|
|
746
|
+
|
|
747
|
+
Args:
|
|
748
|
+
folder_path (str): Path to the folder to deploy
|
|
749
|
+
port (int): Port to serve on
|
|
750
|
+
domain (Optional[str]): Custom domain
|
|
751
|
+
subdirectory (Optional[str]): Subdirectory path
|
|
752
|
+
|
|
753
|
+
Returns:
|
|
754
|
+
Dict[str, Any]: Deployment result
|
|
755
|
+
"""
|
|
756
|
+
try:
|
|
705
757
|
temp_dir = None
|
|
706
758
|
if self.add_branding_tag:
|
|
707
759
|
# Create temporary directory and copy all files
|
|
@@ -877,6 +929,149 @@ class WebDeployToolkit(BaseToolkit):
|
|
|
877
929
|
logger.error(f"Error deploying folder: {e}")
|
|
878
930
|
return {'success': False, 'error': str(e)}
|
|
879
931
|
|
|
932
|
+
def _deploy_folder_to_remote_server(
|
|
933
|
+
self,
|
|
934
|
+
folder_path: str,
|
|
935
|
+
subdirectory: Optional[str] = None,
|
|
936
|
+
domain: Optional[str] = None,
|
|
937
|
+
) -> Dict[str, Any]:
|
|
938
|
+
r"""Deploy folder to remote server via API.
|
|
939
|
+
|
|
940
|
+
Args:
|
|
941
|
+
folder_path (str): Path to the folder to deploy
|
|
942
|
+
subdirectory (Optional[str]): Subdirectory path for deployment
|
|
943
|
+
domain (Optional[str]): Custom domain
|
|
944
|
+
|
|
945
|
+
Returns:
|
|
946
|
+
Dict[str, Any]: Deployment result
|
|
947
|
+
"""
|
|
948
|
+
try:
|
|
949
|
+
import tempfile
|
|
950
|
+
import zipfile
|
|
951
|
+
|
|
952
|
+
import requests
|
|
953
|
+
|
|
954
|
+
# Validate subdirectory
|
|
955
|
+
subdirectory = self._validate_subdirectory(subdirectory)
|
|
956
|
+
|
|
957
|
+
# Create a temporary zip file of the folder
|
|
958
|
+
with tempfile.NamedTemporaryFile(
|
|
959
|
+
suffix='.zip', delete=False
|
|
960
|
+
) as temp_zip:
|
|
961
|
+
zip_path = temp_zip.name
|
|
962
|
+
|
|
963
|
+
try:
|
|
964
|
+
# Create zip archive
|
|
965
|
+
with zipfile.ZipFile(
|
|
966
|
+
zip_path, 'w', zipfile.ZIP_DEFLATED
|
|
967
|
+
) as zipf:
|
|
968
|
+
for root, _, files in os.walk(folder_path):
|
|
969
|
+
for file in files:
|
|
970
|
+
file_path = os.path.join(root, file)
|
|
971
|
+
# Calculate relative path within the archive
|
|
972
|
+
arcname = os.path.relpath(file_path, folder_path)
|
|
973
|
+
zipf.write(file_path, arcname)
|
|
974
|
+
|
|
975
|
+
# Read zip file as base64
|
|
976
|
+
with open(zip_path, 'rb') as f:
|
|
977
|
+
zip_data = base64.b64encode(f.read()).decode('utf-8')
|
|
978
|
+
|
|
979
|
+
# Prepare deployment data
|
|
980
|
+
deploy_data = {
|
|
981
|
+
"deployment_type": "folder",
|
|
982
|
+
"folder_data": zip_data,
|
|
983
|
+
"subdirectory": subdirectory,
|
|
984
|
+
"domain": domain,
|
|
985
|
+
"timestamp": time.time(),
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
# Add logo data if custom logo is specified
|
|
989
|
+
if self.logo_path and os.path.exists(self.logo_path):
|
|
990
|
+
try:
|
|
991
|
+
logo_ext = os.path.splitext(self.logo_path)[1]
|
|
992
|
+
logo_filename = f"custom_logo{logo_ext}"
|
|
993
|
+
|
|
994
|
+
with open(self.logo_path, 'rb') as logo_file:
|
|
995
|
+
logo_data = base64.b64encode(
|
|
996
|
+
logo_file.read()
|
|
997
|
+
).decode('utf-8')
|
|
998
|
+
|
|
999
|
+
deploy_data.update(
|
|
1000
|
+
{
|
|
1001
|
+
"logo_data": logo_data,
|
|
1002
|
+
"logo_ext": logo_ext,
|
|
1003
|
+
"logo_filename": logo_filename,
|
|
1004
|
+
}
|
|
1005
|
+
)
|
|
1006
|
+
except Exception as logo_error:
|
|
1007
|
+
logger.warning(
|
|
1008
|
+
f"Failed to process custom logo: {logo_error}"
|
|
1009
|
+
)
|
|
1010
|
+
|
|
1011
|
+
# Send to remote server API
|
|
1012
|
+
api_url = f"http://{self.remote_server_ip}:{self.remote_server_port}/api/deploy"
|
|
1013
|
+
|
|
1014
|
+
response = requests.post(
|
|
1015
|
+
api_url,
|
|
1016
|
+
json=deploy_data,
|
|
1017
|
+
timeout=self.timeout
|
|
1018
|
+
or 60, # Extended timeout for folder uploads
|
|
1019
|
+
allow_redirects=False,
|
|
1020
|
+
headers={'Content-Type': 'application/json'},
|
|
1021
|
+
)
|
|
1022
|
+
|
|
1023
|
+
if response.status_code == 200:
|
|
1024
|
+
result = response.json()
|
|
1025
|
+
|
|
1026
|
+
# Build URLs
|
|
1027
|
+
base_url = f"http://{self.remote_server_ip}:{self.remote_server_port}"
|
|
1028
|
+
deployed_url = (
|
|
1029
|
+
f"{base_url}/{subdirectory}/"
|
|
1030
|
+
if subdirectory
|
|
1031
|
+
else base_url
|
|
1032
|
+
)
|
|
1033
|
+
|
|
1034
|
+
return {
|
|
1035
|
+
'success': True,
|
|
1036
|
+
'remote_url': deployed_url,
|
|
1037
|
+
'server_ip': self.remote_server_ip,
|
|
1038
|
+
'subdirectory': subdirectory,
|
|
1039
|
+
'domain': domain,
|
|
1040
|
+
'message': (
|
|
1041
|
+
f'Successfully deployed folder to remote server!\n'
|
|
1042
|
+
f' • Access URL: {deployed_url}\n'
|
|
1043
|
+
f' • Server: '
|
|
1044
|
+
f'{self.remote_server_ip}:{self.remote_server_port}'
|
|
1045
|
+
),
|
|
1046
|
+
'branding_tag_added': self.add_branding_tag,
|
|
1047
|
+
'logo_processed': result.get('logo_processed', False),
|
|
1048
|
+
}
|
|
1049
|
+
else:
|
|
1050
|
+
return {
|
|
1051
|
+
'success': False,
|
|
1052
|
+
'error': (
|
|
1053
|
+
f'Remote folder deployment failed: '
|
|
1054
|
+
f'HTTP {response.status_code}'
|
|
1055
|
+
),
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
finally:
|
|
1059
|
+
# Clean up temporary zip file
|
|
1060
|
+
if os.path.exists(zip_path):
|
|
1061
|
+
os.unlink(zip_path)
|
|
1062
|
+
|
|
1063
|
+
except ImportError:
|
|
1064
|
+
return {
|
|
1065
|
+
'success': False,
|
|
1066
|
+
'error': 'Remote deployment requires requests library. '
|
|
1067
|
+
'Install with: pip install requests',
|
|
1068
|
+
}
|
|
1069
|
+
except Exception as e:
|
|
1070
|
+
return {
|
|
1071
|
+
'success': False,
|
|
1072
|
+
'error': f'Remote folder deployment error: {e!s}',
|
|
1073
|
+
}
|
|
1074
|
+
|
|
880
1075
|
def stop_server(self, port: int) -> Dict[str, Any]:
|
|
881
1076
|
r"""Stop a running server on the specified port.
|
|
882
1077
|
|
camel/types/enums.py
CHANGED
|
@@ -245,6 +245,7 @@ class ModelType(UnifiedModelType, Enum):
|
|
|
245
245
|
QWEN_QWQ_32B = "qwq-32b-preview"
|
|
246
246
|
QWEN_QVQ_72B = "qvq-72b-preview"
|
|
247
247
|
QWEN_QWQ_PLUS = "qwq-plus"
|
|
248
|
+
QWEN_3_CODER_PLUS = "qwen3-coder-plus"
|
|
248
249
|
|
|
249
250
|
# Yi models (01-ai)
|
|
250
251
|
YI_LIGHTNING = "yi-lightning"
|
|
@@ -763,6 +764,7 @@ class ModelType(UnifiedModelType, Enum):
|
|
|
763
764
|
ModelType.QWEN_PLUS_2025_04_28,
|
|
764
765
|
ModelType.QWEN_TURBO_LATEST,
|
|
765
766
|
ModelType.QWEN_TURBO_2025_04_28,
|
|
767
|
+
ModelType.QWEN_3_CODER_PLUS,
|
|
766
768
|
}
|
|
767
769
|
|
|
768
770
|
@property
|
|
@@ -1306,6 +1308,10 @@ class ModelType(UnifiedModelType, Enum):
|
|
|
1306
1308
|
ModelType.NOVITA_LLAMA_4_MAVERICK_17B,
|
|
1307
1309
|
}:
|
|
1308
1310
|
return 1_048_576
|
|
1311
|
+
elif self in {
|
|
1312
|
+
ModelType.QWEN_3_CODER_PLUS,
|
|
1313
|
+
}:
|
|
1314
|
+
return 1_000_000
|
|
1309
1315
|
elif self in {
|
|
1310
1316
|
ModelType.QWEN_LONG,
|
|
1311
1317
|
ModelType.TOGETHER_LLAMA_4_SCOUT,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: camel-ai
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.73
|
|
4
4
|
Summary: Communicative Agents for AI Society Study
|
|
5
5
|
Project-URL: Homepage, https://www.camel-ai.org/
|
|
6
6
|
Project-URL: Repository, https://github.com/camel-ai/camel
|
|
@@ -69,7 +69,7 @@ Requires-Dist: jupyter-client<9,>=8.6.2; extra == 'all'
|
|
|
69
69
|
Requires-Dist: langfuse>=2.60.5; extra == 'all'
|
|
70
70
|
Requires-Dist: linkup-sdk<0.3,>=0.2.1; extra == 'all'
|
|
71
71
|
Requires-Dist: litellm<2,>=1.38.1; extra == 'all'
|
|
72
|
-
Requires-Dist: markitdown
|
|
72
|
+
Requires-Dist: markitdown>=0.1.1; extra == 'all'
|
|
73
73
|
Requires-Dist: math-verify<0.8,>=0.7.0; extra == 'all'
|
|
74
74
|
Requires-Dist: mcp>=1.3.0; extra == 'all'
|
|
75
75
|
Requires-Dist: mem0ai>=0.1.67; extra == 'all'
|
|
@@ -79,9 +79,9 @@ Requires-Dist: mypy<2,>=1.5.1; extra == 'all'
|
|
|
79
79
|
Requires-Dist: nebula3-python==3.8.2; extra == 'all'
|
|
80
80
|
Requires-Dist: neo4j<6,>=5.18.0; extra == 'all'
|
|
81
81
|
Requires-Dist: networkx<4,>=3.4.2; extra == 'all'
|
|
82
|
-
Requires-Dist: newspaper3k<0.3,>=0.2.8; extra == 'all'
|
|
83
82
|
Requires-Dist: notion-client<3,>=2.2.1; extra == 'all'
|
|
84
83
|
Requires-Dist: numpy<=2.2,>=1.2; extra == 'all'
|
|
84
|
+
Requires-Dist: onnxruntime<=1.19.2; extra == 'all'
|
|
85
85
|
Requires-Dist: openapi-spec-validator<0.8,>=0.7.1; extra == 'all'
|
|
86
86
|
Requires-Dist: openpyxl>=3.1.5; extra == 'all'
|
|
87
87
|
Requires-Dist: pandas<2,>=1.5.3; extra == 'all'
|
|
@@ -123,11 +123,12 @@ Requires-Dist: slack-bolt<2,>=1.20.1; extra == 'all'
|
|
|
123
123
|
Requires-Dist: slack-sdk<4,>=3.27.2; extra == 'all'
|
|
124
124
|
Requires-Dist: soundfile<0.14,>=0.13; extra == 'all'
|
|
125
125
|
Requires-Dist: stripe<12,>=11.3.0; extra == 'all'
|
|
126
|
+
Requires-Dist: surrealdb>=1.0.6; extra == 'all'
|
|
126
127
|
Requires-Dist: sympy<2,>=1.13.3; extra == 'all'
|
|
127
128
|
Requires-Dist: tabulate>=0.9.0; extra == 'all'
|
|
128
129
|
Requires-Dist: tavily-python<0.6,>=0.5.0; extra == 'all'
|
|
129
130
|
Requires-Dist: textblob<0.18,>=0.17.1; extra == 'all'
|
|
130
|
-
Requires-Dist: traceroot==0.0.
|
|
131
|
+
Requires-Dist: traceroot==0.0.4a5; extra == 'all'
|
|
131
132
|
Requires-Dist: transformers<5,>=4; extra == 'all'
|
|
132
133
|
Requires-Dist: tree-sitter-python<0.24,>=0.23.6; extra == 'all'
|
|
133
134
|
Requires-Dist: tree-sitter<0.24,>=0.23.2; extra == 'all'
|
|
@@ -140,6 +141,7 @@ Requires-Dist: types-setuptools<70,>=69.2.0; extra == 'all'
|
|
|
140
141
|
Requires-Dist: types-tqdm<5,>=4.66.0; extra == 'all'
|
|
141
142
|
Requires-Dist: unstructured==0.16.20; extra == 'all'
|
|
142
143
|
Requires-Dist: weaviate-client>=4.15.0; extra == 'all'
|
|
144
|
+
Requires-Dist: websockets<15.1,>=13.0; extra == 'all'
|
|
143
145
|
Requires-Dist: wikipedia<2,>=1; extra == 'all'
|
|
144
146
|
Requires-Dist: wolframalpha<6,>=5.0.0; extra == 'all'
|
|
145
147
|
Requires-Dist: xls2xlsx>=0.2.0; extra == 'all'
|
|
@@ -191,7 +193,7 @@ Requires-Dist: ipykernel<7,>=6.0.0; extra == 'dev-tools'
|
|
|
191
193
|
Requires-Dist: jupyter-client<9,>=8.6.2; extra == 'dev-tools'
|
|
192
194
|
Requires-Dist: langfuse>=2.60.5; extra == 'dev-tools'
|
|
193
195
|
Requires-Dist: mcp>=1.3.0; extra == 'dev-tools'
|
|
194
|
-
Requires-Dist: traceroot==0.0.
|
|
196
|
+
Requires-Dist: traceroot==0.0.4a5; extra == 'dev-tools'
|
|
195
197
|
Requires-Dist: tree-sitter-python<0.24,>=0.23.6; extra == 'dev-tools'
|
|
196
198
|
Requires-Dist: tree-sitter<0.24,>=0.23.2; extra == 'dev-tools'
|
|
197
199
|
Requires-Dist: typer>=0.15.2; extra == 'dev-tools'
|
|
@@ -208,8 +210,9 @@ Requires-Dist: chunkr-ai>=0.0.50; extra == 'document-tools'
|
|
|
208
210
|
Requires-Dist: crawl4ai>=0.3.745; extra == 'document-tools'
|
|
209
211
|
Requires-Dist: docx2txt<0.9,>=0.8; extra == 'document-tools'
|
|
210
212
|
Requires-Dist: docx>=0.2.4; extra == 'document-tools'
|
|
211
|
-
Requires-Dist: markitdown
|
|
213
|
+
Requires-Dist: markitdown>=0.1.1; extra == 'document-tools'
|
|
212
214
|
Requires-Dist: numpy<=2.2,>=1.2; extra == 'document-tools'
|
|
215
|
+
Requires-Dist: onnxruntime<=1.19.2; extra == 'document-tools'
|
|
213
216
|
Requires-Dist: openapi-spec-validator<0.8,>=0.7.1; extra == 'document-tools'
|
|
214
217
|
Requires-Dist: openpyxl>=3.1.5; extra == 'document-tools'
|
|
215
218
|
Requires-Dist: pandasai<3,>=2.3.0; extra == 'document-tools'
|
|
@@ -221,6 +224,41 @@ Requires-Dist: reportlab>=4.4.2; extra == 'document-tools'
|
|
|
221
224
|
Requires-Dist: tabulate>=0.9.0; extra == 'document-tools'
|
|
222
225
|
Requires-Dist: unstructured==0.16.20; extra == 'document-tools'
|
|
223
226
|
Requires-Dist: xls2xlsx>=0.2.0; extra == 'document-tools'
|
|
227
|
+
Provides-Extra: eigent
|
|
228
|
+
Requires-Dist: aci-sdk>=1.0.0b1; extra == 'eigent'
|
|
229
|
+
Requires-Dist: anthropic<0.50.0,>=0.47.0; extra == 'eigent'
|
|
230
|
+
Requires-Dist: chunkr-ai>=0.0.41; extra == 'eigent'
|
|
231
|
+
Requires-Dist: chunkr-ai>=0.0.50; extra == 'eigent'
|
|
232
|
+
Requires-Dist: crawl4ai>=0.3.745; extra == 'eigent'
|
|
233
|
+
Requires-Dist: datasets<4,>=3; extra == 'eigent'
|
|
234
|
+
Requires-Dist: docx>=0.2.4; extra == 'eigent'
|
|
235
|
+
Requires-Dist: duckduckgo-search<7,>=6.3.5; extra == 'eigent'
|
|
236
|
+
Requires-Dist: exa-py<2,>=1.10.0; extra == 'eigent'
|
|
237
|
+
Requires-Dist: ffmpeg-python<0.3,>=0.2.0; extra == 'eigent'
|
|
238
|
+
Requires-Dist: html2text>=2024.2.26; extra == 'eigent'
|
|
239
|
+
Requires-Dist: imageio[pyav]<3,>=2.34.2; extra == 'eigent'
|
|
240
|
+
Requires-Dist: markitdown>=0.1.1; extra == 'eigent'
|
|
241
|
+
Requires-Dist: mcp-server-fetch==2025.1.17; extra == 'eigent'
|
|
242
|
+
Requires-Dist: mcp-simple-arxiv==0.2.2; extra == 'eigent'
|
|
243
|
+
Requires-Dist: numpy<=2.2,>=1.2; extra == 'eigent'
|
|
244
|
+
Requires-Dist: onnxruntime<=1.19.2; extra == 'eigent'
|
|
245
|
+
Requires-Dist: openpyxl>=3.1.5; extra == 'eigent'
|
|
246
|
+
Requires-Dist: pandas<2,>=1.5.3; extra == 'eigent'
|
|
247
|
+
Requires-Dist: playwright>=1.50.0; extra == 'eigent'
|
|
248
|
+
Requires-Dist: pyautogui<0.10,>=0.9.54; extra == 'eigent'
|
|
249
|
+
Requires-Dist: pydub<0.26,>=0.25.1; extra == 'eigent'
|
|
250
|
+
Requires-Dist: pylatex>=1.4.2; extra == 'eigent'
|
|
251
|
+
Requires-Dist: pytesseract>=0.3.13; extra == 'eigent'
|
|
252
|
+
Requires-Dist: python-dotenv<2,>=1.0.0; extra == 'eigent'
|
|
253
|
+
Requires-Dist: python-pptx>=1.0.2; extra == 'eigent'
|
|
254
|
+
Requires-Dist: reportlab>=4.4.2; extra == 'eigent'
|
|
255
|
+
Requires-Dist: requests-oauthlib<2,>=1.3.1; extra == 'eigent'
|
|
256
|
+
Requires-Dist: scenedetect>=0.6.5.2; extra == 'eigent'
|
|
257
|
+
Requires-Dist: tabulate>=0.9.0; extra == 'eigent'
|
|
258
|
+
Requires-Dist: websockets<15.1,>=13.0; extra == 'eigent'
|
|
259
|
+
Requires-Dist: wikipedia<2,>=1; extra == 'eigent'
|
|
260
|
+
Requires-Dist: xls2xlsx>=0.2.0; extra == 'eigent'
|
|
261
|
+
Requires-Dist: yt-dlp<2025,>=2024.11.4; extra == 'eigent'
|
|
224
262
|
Provides-Extra: huggingface
|
|
225
263
|
Requires-Dist: datasets<4,>=3; extra == 'huggingface'
|
|
226
264
|
Requires-Dist: diffusers<0.26,>=0.25.0; extra == 'huggingface'
|
|
@@ -259,11 +297,11 @@ Requires-Dist: exa-py<2,>=1.10.0; extra == 'owl'
|
|
|
259
297
|
Requires-Dist: ffmpeg-python<0.3,>=0.2.0; extra == 'owl'
|
|
260
298
|
Requires-Dist: html2text>=2024.2.26; extra == 'owl'
|
|
261
299
|
Requires-Dist: imageio[pyav]<3,>=2.34.2; extra == 'owl'
|
|
262
|
-
Requires-Dist: markitdown
|
|
300
|
+
Requires-Dist: markitdown>=0.1.1; extra == 'owl'
|
|
263
301
|
Requires-Dist: mcp-server-fetch==2025.1.17; extra == 'owl'
|
|
264
302
|
Requires-Dist: mcp-simple-arxiv==0.2.2; extra == 'owl'
|
|
265
|
-
Requires-Dist: newspaper3k<0.3,>=0.2.8; extra == 'owl'
|
|
266
303
|
Requires-Dist: numpy<=2.2,>=1.2; extra == 'owl'
|
|
304
|
+
Requires-Dist: onnxruntime<=1.19.2; extra == 'owl'
|
|
267
305
|
Requires-Dist: openapi-spec-validator<0.8,>=0.7.1; extra == 'owl'
|
|
268
306
|
Requires-Dist: openpyxl>=3.1.5; extra == 'owl'
|
|
269
307
|
Requires-Dist: pandas<2,>=1.5.3; extra == 'owl'
|
|
@@ -290,6 +328,7 @@ Requires-Dist: tree-sitter-python<0.24,>=0.23.6; extra == 'owl'
|
|
|
290
328
|
Requires-Dist: tree-sitter<0.24,>=0.23.2; extra == 'owl'
|
|
291
329
|
Requires-Dist: typer>=0.15.2; extra == 'owl'
|
|
292
330
|
Requires-Dist: unstructured==0.16.20; extra == 'owl'
|
|
331
|
+
Requires-Dist: websockets<15.1,>=13.0; extra == 'owl'
|
|
293
332
|
Requires-Dist: wikipedia<2,>=1; extra == 'owl'
|
|
294
333
|
Requires-Dist: xls2xlsx>=0.2.0; extra == 'owl'
|
|
295
334
|
Requires-Dist: yt-dlp<2025,>=2024.11.4; extra == 'owl'
|
|
@@ -331,6 +370,7 @@ Requires-Dist: pyobvector>=0.1.18; extra == 'storage'
|
|
|
331
370
|
Requires-Dist: pytidb-experimental==0.0.1.dev4; extra == 'storage'
|
|
332
371
|
Requires-Dist: qdrant-client<2,>=1.9.0; extra == 'storage'
|
|
333
372
|
Requires-Dist: redis<6,>=5.0.6; extra == 'storage'
|
|
373
|
+
Requires-Dist: surrealdb>=1.0.6; extra == 'storage'
|
|
334
374
|
Requires-Dist: weaviate-client>=4.15.0; extra == 'storage'
|
|
335
375
|
Provides-Extra: web-tools
|
|
336
376
|
Requires-Dist: apify-client<2,>=1.8.1; extra == 'web-tools'
|
|
@@ -346,13 +386,13 @@ Requires-Dist: google-auth-oauthlib==1.2.1; extra == 'web-tools'
|
|
|
346
386
|
Requires-Dist: googlemaps<5,>=4.10.0; extra == 'web-tools'
|
|
347
387
|
Requires-Dist: html2text>=2024.2.26; extra == 'web-tools'
|
|
348
388
|
Requires-Dist: linkup-sdk<0.3,>=0.2.1; extra == 'web-tools'
|
|
349
|
-
Requires-Dist: newspaper3k<0.3,>=0.2.8; extra == 'web-tools'
|
|
350
389
|
Requires-Dist: playwright>=1.50.0; extra == 'web-tools'
|
|
351
390
|
Requires-Dist: pyowm<4,>=3.3.0; extra == 'web-tools'
|
|
352
391
|
Requires-Dist: requests-oauthlib<2,>=1.3.1; extra == 'web-tools'
|
|
353
392
|
Requires-Dist: scrapegraph-py<2,>=1.12.0; extra == 'web-tools'
|
|
354
393
|
Requires-Dist: sympy<2,>=1.13.3; extra == 'web-tools'
|
|
355
394
|
Requires-Dist: tavily-python<0.6,>=0.5.0; extra == 'web-tools'
|
|
395
|
+
Requires-Dist: websockets<15.1,>=13.0; extra == 'web-tools'
|
|
356
396
|
Requires-Dist: wikipedia<2,>=1; extra == 'web-tools'
|
|
357
397
|
Requires-Dist: wolframalpha<6,>=5.0.0; extra == 'web-tools'
|
|
358
398
|
Description-Content-Type: text/markdown
|