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 CHANGED
@@ -14,7 +14,7 @@
14
14
 
15
15
  from camel.logger import disable_logging, enable_logging, set_log_level
16
16
 
17
- __version__ = '0.2.72a2'
17
+ __version__ = '0.2.72a4'
18
18
 
19
19
  __all__ = [
20
20
  '__version__',
@@ -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
- "New Python environment created successfully!\n"
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
- if self.cloned_env_path:
922
- # Use cloned environment
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
- python_path = os.path.join(base_path, "python.exe")
928
- pip_path = os.path.join(base_path, "pip.exe")
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
- python_path = os.path.join(base_path, "python")
932
- pip_path = os.path.join(base_path, "pip")
933
- elif self.initial_env_prepared and self.initial_env_path:
934
- # Use initial prepared environment
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
- python_path = os.path.join(base_path, "python.exe")
940
- pip_path = os.path.join(base_path, "pip.exe")
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
- python_path = os.path.join(base_path, "python")
944
- pip_path = os.path.join(base_path, "pip")
945
- else:
946
- # Fall back to system Python
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
- if command.startswith('python'):
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: camel-ai
3
- Version: 0.2.72a2
3
+ Version: 0.2.72a4
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
@@ -1,4 +1,4 @@
1
- camel/__init__.py,sha256=_mXhIpC52sRjb19FSEYMCMjlTnE6SsVFKIK4fiWKMOI,901
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=_VvSk1iPDNeA8q_D-2ianDhFqaYljSYM6ynTrzMFm4A,59076
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.72a2.dist-info/METADATA,sha256=DCvskziajpL3_f8dK9Nnh1AEAeX2AEGza114yFYimL0,49998
450
- camel_ai-0.2.72a2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
451
- camel_ai-0.2.72a2.dist-info/licenses/LICENSE,sha256=id0nB2my5kG0xXeimIu5zZrbHLS6EQvxvkKkzIHaT2k,11343
452
- camel_ai-0.2.72a2.dist-info/RECORD,,
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,,