camel-ai 0.2.72a2__py3-none-any.whl → 0.2.72a4__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/toolkits/terminal_toolkit.py +99 -124
- {camel_ai-0.2.72a2.dist-info → camel_ai-0.2.72a4.dist-info}/METADATA +1 -1
- {camel_ai-0.2.72a2.dist-info → camel_ai-0.2.72a4.dist-info}/RECORD +6 -6
- {camel_ai-0.2.72a2.dist-info → camel_ai-0.2.72a4.dist-info}/WHEEL +0 -0
- {camel_ai-0.2.72a2.dist-info → camel_ai-0.2.72a4.dist-info}/licenses/LICENSE +0 -0
camel/__init__.py
CHANGED
|
@@ -93,7 +93,7 @@ class TerminalToolkit(BaseToolkit):
|
|
|
93
93
|
|
|
94
94
|
self.python_executable = sys.executable
|
|
95
95
|
self.is_macos = platform.system() == 'Darwin'
|
|
96
|
-
self.initial_env_path = None
|
|
96
|
+
self.initial_env_path: Optional[str] = None
|
|
97
97
|
self.initial_env_prepared = False
|
|
98
98
|
|
|
99
99
|
atexit.register(self.__del__)
|
|
@@ -194,14 +194,50 @@ class TerminalToolkit(BaseToolkit):
|
|
|
194
194
|
return
|
|
195
195
|
|
|
196
196
|
self._update_terminal_output(
|
|
197
|
-
f"Creating new Python environment at:{self.cloned_env_path}\n"
|
|
197
|
+
f"Creating new Python environment at: {self.cloned_env_path}\n"
|
|
198
198
|
)
|
|
199
199
|
|
|
200
|
+
# Create virtual environment with pip
|
|
200
201
|
venv.create(self.cloned_env_path, with_pip=True)
|
|
202
|
+
|
|
203
|
+
# Ensure pip is properly available by upgrading it
|
|
204
|
+
if self.os_type == 'Windows':
|
|
205
|
+
python_path = os.path.join(
|
|
206
|
+
self.cloned_env_path, "Scripts", "python.exe"
|
|
207
|
+
)
|
|
208
|
+
else:
|
|
209
|
+
python_path = os.path.join(
|
|
210
|
+
self.cloned_env_path, "bin", "python"
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
# Verify python executable exists
|
|
214
|
+
if os.path.exists(python_path):
|
|
215
|
+
# Use python -m pip to ensure pip is available
|
|
216
|
+
subprocess.run(
|
|
217
|
+
[python_path, "-m", "pip", "install", "--upgrade", "pip"],
|
|
218
|
+
check=True,
|
|
219
|
+
capture_output=True,
|
|
220
|
+
cwd=self.working_dir,
|
|
221
|
+
timeout=60,
|
|
222
|
+
)
|
|
223
|
+
self._update_terminal_output(
|
|
224
|
+
"New Python environment created successfully with pip!\n"
|
|
225
|
+
)
|
|
226
|
+
else:
|
|
227
|
+
self._update_terminal_output(
|
|
228
|
+
f"Warning: Python executable not found at {python_path}\n"
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
except subprocess.CalledProcessError as e:
|
|
232
|
+
error_msg = e.stderr.decode() if e.stderr else str(e)
|
|
201
233
|
self._update_terminal_output(
|
|
202
|
-
"
|
|
234
|
+
f"Failed to upgrade pip in cloned environment: {error_msg}\n"
|
|
235
|
+
)
|
|
236
|
+
logger.error(f"Failed to upgrade pip: {error_msg}")
|
|
237
|
+
except subprocess.TimeoutExpired:
|
|
238
|
+
self._update_terminal_output(
|
|
239
|
+
"Pip upgrade timed out, but environment may still be usable\n"
|
|
203
240
|
)
|
|
204
|
-
|
|
205
241
|
except Exception as e:
|
|
206
242
|
self._update_terminal_output(
|
|
207
243
|
f"Failed to create environment: {e!s}\n"
|
|
@@ -259,6 +295,9 @@ class TerminalToolkit(BaseToolkit):
|
|
|
259
295
|
|
|
260
296
|
def _setup_initial_env_with_uv(self):
|
|
261
297
|
r"""Set up initial environment using uv."""
|
|
298
|
+
if self.initial_env_path is None:
|
|
299
|
+
raise Exception("Initial environment path not set")
|
|
300
|
+
|
|
262
301
|
try:
|
|
263
302
|
# Create virtual environment with Python 3.10 using uv
|
|
264
303
|
subprocess.run(
|
|
@@ -312,6 +351,9 @@ class TerminalToolkit(BaseToolkit):
|
|
|
312
351
|
|
|
313
352
|
def _setup_initial_env_with_venv(self):
|
|
314
353
|
r"""Set up initial environment using standard venv."""
|
|
354
|
+
if self.initial_env_path is None:
|
|
355
|
+
raise Exception("Initial environment path not set")
|
|
356
|
+
|
|
315
357
|
try:
|
|
316
358
|
# Create virtual environment with system Python
|
|
317
359
|
venv.create(
|
|
@@ -532,108 +574,6 @@ class TerminalToolkit(BaseToolkit):
|
|
|
532
574
|
logger.error(f"Failed to copy file: {e}")
|
|
533
575
|
return None
|
|
534
576
|
|
|
535
|
-
def file_find_in_content(
|
|
536
|
-
self, file: str, regex: str, sudo: bool = False
|
|
537
|
-
) -> str:
|
|
538
|
-
r"""Search for text within a file's content using a regular expression.
|
|
539
|
-
|
|
540
|
-
This function is useful for finding specific patterns or lines of text
|
|
541
|
-
within a given file. It uses `grep` on Unix-like systems and `findstr`
|
|
542
|
-
on Windows.
|
|
543
|
-
|
|
544
|
-
Args:
|
|
545
|
-
file (str): The absolute path of the file to search within.
|
|
546
|
-
regex (str): The regular expression pattern to match.
|
|
547
|
-
sudo (bool, optional): Whether to use sudo privileges for the
|
|
548
|
-
search. Defaults to False. Note: Using sudo requires the
|
|
549
|
-
process to have appropriate permissions.
|
|
550
|
-
(default: :obj:`False`)
|
|
551
|
-
|
|
552
|
-
Returns:
|
|
553
|
-
str: The matching content found in the file. If no matches are
|
|
554
|
-
found, an empty string is returned. Returns an error message
|
|
555
|
-
if the file does not exist or another error occurs.
|
|
556
|
-
"""
|
|
557
|
-
|
|
558
|
-
if not os.path.exists(file):
|
|
559
|
-
return f"File not found: {file}"
|
|
560
|
-
|
|
561
|
-
if not os.path.isfile(file):
|
|
562
|
-
return f"The path provided is not a file: {file}"
|
|
563
|
-
|
|
564
|
-
command = []
|
|
565
|
-
if sudo:
|
|
566
|
-
error_msg = self._enforce_working_dir_for_execution(file)
|
|
567
|
-
if error_msg:
|
|
568
|
-
return error_msg
|
|
569
|
-
command.extend(["sudo"])
|
|
570
|
-
|
|
571
|
-
if self.os_type in ['Darwin', 'Linux']: # macOS or Linux
|
|
572
|
-
command.extend(["grep", "-E", regex, file])
|
|
573
|
-
else: # Windows
|
|
574
|
-
# For Windows, we could use PowerShell or findstr
|
|
575
|
-
command.extend(["findstr", "/R", regex, file])
|
|
576
|
-
|
|
577
|
-
try:
|
|
578
|
-
result = subprocess.run(
|
|
579
|
-
command, check=False, capture_output=True, text=True
|
|
580
|
-
)
|
|
581
|
-
return result.stdout.strip()
|
|
582
|
-
except subprocess.SubprocessError as e:
|
|
583
|
-
logger.error(f"Error searching in file content: {e}")
|
|
584
|
-
return f"Error: {e!s}"
|
|
585
|
-
|
|
586
|
-
def file_find_by_name(self, path: str, glob: str) -> str:
|
|
587
|
-
r"""Find files by name in a specified directory using a glob pattern.
|
|
588
|
-
|
|
589
|
-
This function recursively searches for files matching a given name or
|
|
590
|
-
pattern within a directory. It uses `find` on Unix-like systems and
|
|
591
|
-
`dir` on Windows.
|
|
592
|
-
|
|
593
|
-
Args:
|
|
594
|
-
path (str): The absolute path of the directory to search in.
|
|
595
|
-
glob (str): The filename pattern to search for, using glob syntax
|
|
596
|
-
(e.g., "*.py", "data*").
|
|
597
|
-
|
|
598
|
-
Returns:
|
|
599
|
-
str: A newline-separated string containing the paths of the files
|
|
600
|
-
that match the pattern. Returns an error message if the
|
|
601
|
-
directory does not exist or another error occurs.
|
|
602
|
-
"""
|
|
603
|
-
if not os.path.exists(path):
|
|
604
|
-
return f"Directory not found: {path}"
|
|
605
|
-
|
|
606
|
-
if not os.path.isdir(path):
|
|
607
|
-
return f"The path provided is not a directory: {path}"
|
|
608
|
-
|
|
609
|
-
command = []
|
|
610
|
-
if self.os_type in ['Darwin', 'Linux']: # macOS or Linux
|
|
611
|
-
command.extend(["find", path, "-name", glob])
|
|
612
|
-
else: # Windows
|
|
613
|
-
# For Windows, we use dir command with /s for recursive search
|
|
614
|
-
# and /b for bare format
|
|
615
|
-
|
|
616
|
-
pattern = glob
|
|
617
|
-
file_path = os.path.join(path, pattern).replace('/', '\\')
|
|
618
|
-
command.extend(["cmd", "/c", "dir", "/s", "/b", file_path])
|
|
619
|
-
|
|
620
|
-
try:
|
|
621
|
-
result = subprocess.run(
|
|
622
|
-
command,
|
|
623
|
-
check=False,
|
|
624
|
-
capture_output=True,
|
|
625
|
-
text=True,
|
|
626
|
-
shell=False,
|
|
627
|
-
)
|
|
628
|
-
|
|
629
|
-
output = result.stdout.strip()
|
|
630
|
-
if self.os_type == 'Windows':
|
|
631
|
-
output = output.replace('\\', '/')
|
|
632
|
-
return output
|
|
633
|
-
except subprocess.SubprocessError as e:
|
|
634
|
-
logger.error(f"Error finding files by name: {e}")
|
|
635
|
-
return f"Error: {e!s}"
|
|
636
|
-
|
|
637
577
|
def _sanitize_command(self, command: str, exec_dir: str) -> Tuple:
|
|
638
578
|
r"""Check and modify command to ensure safety.
|
|
639
579
|
|
|
@@ -918,38 +858,75 @@ class TerminalToolkit(BaseToolkit):
|
|
|
918
858
|
self._update_terminal_output(f"\n$ {command}\n")
|
|
919
859
|
|
|
920
860
|
if command.startswith('python') or command.startswith('pip'):
|
|
921
|
-
|
|
922
|
-
|
|
861
|
+
python_path = None
|
|
862
|
+
pip_path = None
|
|
863
|
+
|
|
864
|
+
# Try cloned environment first
|
|
865
|
+
if self.cloned_env_path and os.path.exists(
|
|
866
|
+
self.cloned_env_path
|
|
867
|
+
):
|
|
923
868
|
if self.os_type == 'Windows':
|
|
924
869
|
base_path = os.path.join(
|
|
925
870
|
self.cloned_env_path, "Scripts"
|
|
926
871
|
)
|
|
927
|
-
|
|
928
|
-
|
|
872
|
+
python_candidate = os.path.join(
|
|
873
|
+
base_path, "python.exe"
|
|
874
|
+
)
|
|
875
|
+
pip_candidate = os.path.join(base_path, "pip.exe")
|
|
929
876
|
else:
|
|
930
877
|
base_path = os.path.join(self.cloned_env_path, "bin")
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
#
|
|
878
|
+
python_candidate = os.path.join(base_path, "python")
|
|
879
|
+
pip_candidate = os.path.join(base_path, "pip")
|
|
880
|
+
|
|
881
|
+
# Verify the executables exist
|
|
882
|
+
if os.path.exists(python_candidate):
|
|
883
|
+
python_path = python_candidate
|
|
884
|
+
# For pip, use python -m pip if pip executable doesn't
|
|
885
|
+
# exist
|
|
886
|
+
if os.path.exists(pip_candidate):
|
|
887
|
+
pip_path = pip_candidate
|
|
888
|
+
else:
|
|
889
|
+
pip_path = f'"{python_path}" -m pip'
|
|
890
|
+
|
|
891
|
+
# Try initial environment if cloned environment failed
|
|
892
|
+
if (
|
|
893
|
+
python_path is None
|
|
894
|
+
and self.initial_env_prepared
|
|
895
|
+
and self.initial_env_path
|
|
896
|
+
and os.path.exists(self.initial_env_path)
|
|
897
|
+
):
|
|
935
898
|
if self.os_type == 'Windows':
|
|
936
899
|
base_path = os.path.join(
|
|
937
900
|
self.initial_env_path, "Scripts"
|
|
938
901
|
)
|
|
939
|
-
|
|
940
|
-
|
|
902
|
+
python_candidate = os.path.join(
|
|
903
|
+
base_path, "python.exe"
|
|
904
|
+
)
|
|
905
|
+
pip_candidate = os.path.join(base_path, "pip.exe")
|
|
941
906
|
else:
|
|
942
907
|
base_path = os.path.join(self.initial_env_path, "bin")
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
#
|
|
908
|
+
python_candidate = os.path.join(base_path, "python")
|
|
909
|
+
pip_candidate = os.path.join(base_path, "pip")
|
|
910
|
+
|
|
911
|
+
# Verify the executables exist
|
|
912
|
+
if os.path.exists(python_candidate):
|
|
913
|
+
python_path = python_candidate
|
|
914
|
+
# For pip, use python -m pip if pip executable doesn't
|
|
915
|
+
# exist
|
|
916
|
+
if os.path.exists(pip_candidate):
|
|
917
|
+
pip_path = pip_candidate
|
|
918
|
+
else:
|
|
919
|
+
pip_path = f'"{python_path}" -m pip'
|
|
920
|
+
|
|
921
|
+
# Fall back to system Python
|
|
922
|
+
if python_path is None:
|
|
947
923
|
python_path = self.python_executable
|
|
948
924
|
pip_path = f'"{python_path}" -m pip'
|
|
949
925
|
|
|
950
|
-
|
|
926
|
+
# Ensure we have valid paths before replacement
|
|
927
|
+
if python_path and command.startswith('python'):
|
|
951
928
|
command = command.replace('python', f'"{python_path}"', 1)
|
|
952
|
-
elif command.startswith('pip'):
|
|
929
|
+
elif pip_path and command.startswith('pip'):
|
|
953
930
|
command = command.replace('pip', pip_path, 1)
|
|
954
931
|
|
|
955
932
|
if not interactive:
|
|
@@ -1548,8 +1525,6 @@ class TerminalToolkit(BaseToolkit):
|
|
|
1548
1525
|
functions in the toolkit.
|
|
1549
1526
|
"""
|
|
1550
1527
|
return [
|
|
1551
|
-
FunctionTool(self.file_find_in_content),
|
|
1552
|
-
FunctionTool(self.file_find_by_name),
|
|
1553
1528
|
FunctionTool(self.shell_exec),
|
|
1554
1529
|
FunctionTool(self.shell_view),
|
|
1555
1530
|
FunctionTool(self.shell_wait),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
camel/__init__.py,sha256
|
|
1
|
+
camel/__init__.py,sha256=-uCv1AX5Ap45hQH56gS_ZVzKQCGj0wr5aWajREYrato,901
|
|
2
2
|
camel/generators.py,sha256=JRqj9_m1PF4qT6UtybzTQ-KBT9MJQt18OAAYvQ_fr2o,13844
|
|
3
3
|
camel/human.py,sha256=Xg8x1cS5KK4bQ1SDByiHZnzsRpvRP-KZViNvmu38xo4,5475
|
|
4
4
|
camel/logger.py,sha256=WgEwael_eT6D-lVAKHpKIpwXSTjvLbny5jbV1Ab8lnA,5760
|
|
@@ -373,7 +373,7 @@ camel/toolkits/slack_toolkit.py,sha256=ZT6Ndlce2qjGsyZaNMfQ54nSEi7DOC9Ro7YqtK-u5
|
|
|
373
373
|
camel/toolkits/stripe_toolkit.py,sha256=07swo5znGTnorafC1uYLKB4NRcJIOPOx19J7tkpLYWk,10102
|
|
374
374
|
camel/toolkits/sympy_toolkit.py,sha256=BAQnI8EFJydNUpKQWXBdleQ1Cm-srDBhFlqp9V9pbPQ,33757
|
|
375
375
|
camel/toolkits/task_planning_toolkit.py,sha256=Ttw9fHae4omGC1SA-6uaeXVHJ1YkwiVloz_hO-fm1gw,4855
|
|
376
|
-
camel/toolkits/terminal_toolkit.py,sha256=
|
|
376
|
+
camel/toolkits/terminal_toolkit.py,sha256=i01BSPGs3hbM76SXNt5XpUjco2AoUkWl5K0wUxxm5JQ,58349
|
|
377
377
|
camel/toolkits/thinking_toolkit.py,sha256=nZYLvKWIx2BM1DYu69I9B5EISAG7aYcLYXKv9663BVk,8000
|
|
378
378
|
camel/toolkits/twitter_toolkit.py,sha256=Px4N8aUxUzy01LhGSWkdrC2JgwKkrY3cvxgMeJ2XYfU,15939
|
|
379
379
|
camel/toolkits/video_analysis_toolkit.py,sha256=Wh08MAVvs3PtgXN88Sk0TXYaGfVmQAol8FPCXMPPpIM,23375
|
|
@@ -446,7 +446,7 @@ camel/verifiers/math_verifier.py,sha256=tA1D4S0sm8nsWISevxSN0hvSVtIUpqmJhzqfbuMo
|
|
|
446
446
|
camel/verifiers/models.py,sha256=GdxYPr7UxNrR1577yW4kyroRcLGfd-H1GXgv8potDWU,2471
|
|
447
447
|
camel/verifiers/physics_verifier.py,sha256=c1grrRddcrVN7szkxhv2QirwY9viIRSITWeWFF5HmLs,30187
|
|
448
448
|
camel/verifiers/python_verifier.py,sha256=ogTz77wODfEcDN4tMVtiSkRQyoiZbHPY2fKybn59lHw,20558
|
|
449
|
-
camel_ai-0.2.
|
|
450
|
-
camel_ai-0.2.
|
|
451
|
-
camel_ai-0.2.
|
|
452
|
-
camel_ai-0.2.
|
|
449
|
+
camel_ai-0.2.72a4.dist-info/METADATA,sha256=kOuH0htxiRDCQnwwcynOhM_PqLTFaIicdxG9lmE-kqw,49998
|
|
450
|
+
camel_ai-0.2.72a4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
451
|
+
camel_ai-0.2.72a4.dist-info/licenses/LICENSE,sha256=id0nB2my5kG0xXeimIu5zZrbHLS6EQvxvkKkzIHaT2k,11343
|
|
452
|
+
camel_ai-0.2.72a4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|