camel-ai 0.2.71a3__py3-none-any.whl → 0.2.71a5__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 +1482 -134
- camel/agents/repo_agent.py +2 -1
- camel/benchmarks/browsecomp.py +6 -6
- camel/interpreters/docker_interpreter.py +3 -2
- camel/loaders/base_loader.py +85 -0
- camel/logger.py +1 -1
- camel/messages/base.py +12 -1
- camel/models/azure_openai_model.py +96 -7
- camel/models/base_model.py +68 -10
- camel/models/deepseek_model.py +5 -0
- camel/models/gemini_model.py +5 -0
- camel/models/litellm_model.py +48 -16
- camel/models/model_manager.py +24 -6
- camel/models/openai_compatible_model.py +109 -5
- camel/models/openai_model.py +117 -8
- camel/societies/workforce/prompts.py +68 -5
- camel/societies/workforce/role_playing_worker.py +1 -0
- camel/societies/workforce/single_agent_worker.py +1 -0
- camel/societies/workforce/utils.py +67 -2
- camel/societies/workforce/workforce.py +412 -67
- camel/societies/workforce/workforce_logger.py +0 -8
- camel/tasks/task.py +2 -0
- camel/toolkits/__init__.py +7 -2
- camel/toolkits/craw4ai_toolkit.py +2 -2
- camel/toolkits/file_write_toolkit.py +526 -121
- camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit.py +9 -3
- camel/toolkits/hybrid_browser_toolkit/unified_analyzer.js +31 -8
- camel/toolkits/message_agent_toolkit.py +608 -0
- camel/toolkits/note_taking_toolkit.py +90 -0
- camel/toolkits/openai_image_toolkit.py +292 -0
- camel/toolkits/slack_toolkit.py +4 -4
- camel/toolkits/terminal_toolkit.py +223 -73
- camel/utils/mcp_client.py +37 -1
- {camel_ai-0.2.71a3.dist-info → camel_ai-0.2.71a5.dist-info}/METADATA +48 -7
- {camel_ai-0.2.71a3.dist-info → camel_ai-0.2.71a5.dist-info}/RECORD +38 -35
- camel/toolkits/dalle_toolkit.py +0 -175
- {camel_ai-0.2.71a3.dist-info → camel_ai-0.2.71a5.dist-info}/WHEEL +0 -0
- {camel_ai-0.2.71a3.dist-info → camel_ai-0.2.71a5.dist-info}/licenses/LICENSE +0 -0
|
@@ -134,7 +134,14 @@ class TerminalToolkit(BaseToolkit):
|
|
|
134
134
|
logger.info(f"Terminal output will be redirected to: {self.log_file}")
|
|
135
135
|
|
|
136
136
|
def file_update(output: str):
|
|
137
|
+
import sys
|
|
138
|
+
|
|
137
139
|
try:
|
|
140
|
+
# For macOS/Linux file-based mode, also write to stdout
|
|
141
|
+
# to provide real-time feedback in the user's terminal.
|
|
142
|
+
sys.stdout.write(output)
|
|
143
|
+
sys.stdout.flush()
|
|
144
|
+
|
|
138
145
|
# Initialize file on first write
|
|
139
146
|
if not self._file_initialized:
|
|
140
147
|
with open(self.log_file, "w") as f:
|
|
@@ -147,9 +154,6 @@ class TerminalToolkit(BaseToolkit):
|
|
|
147
154
|
# Directly append to the end of the file
|
|
148
155
|
with open(self.log_file, "a") as f:
|
|
149
156
|
f.write(output)
|
|
150
|
-
# If the output does not end with a newline, add one
|
|
151
|
-
if output and not output.endswith('\n'):
|
|
152
|
-
f.write('\n')
|
|
153
157
|
# Ensure the agent also receives the output
|
|
154
158
|
self.agent_queue.put(output)
|
|
155
159
|
except Exception as e:
|
|
@@ -334,17 +338,24 @@ class TerminalToolkit(BaseToolkit):
|
|
|
334
338
|
def file_find_in_content(
|
|
335
339
|
self, file: str, regex: str, sudo: bool = False
|
|
336
340
|
) -> str:
|
|
337
|
-
r"""Search for
|
|
341
|
+
r"""Search for text within a file's content using a regular expression.
|
|
342
|
+
|
|
343
|
+
This function is useful for finding specific patterns or lines of text
|
|
344
|
+
within a given file. It uses `grep` on Unix-like systems and `findstr`
|
|
345
|
+
on Windows.
|
|
338
346
|
|
|
339
347
|
Args:
|
|
340
|
-
file (str):
|
|
341
|
-
regex (str):
|
|
342
|
-
sudo (bool, optional): Whether to use sudo privileges
|
|
343
|
-
False. Note: Using sudo requires the
|
|
344
|
-
appropriate permissions.
|
|
348
|
+
file (str): The absolute path of the file to search within.
|
|
349
|
+
regex (str): The regular expression pattern to match.
|
|
350
|
+
sudo (bool, optional): Whether to use sudo privileges for the
|
|
351
|
+
search. Defaults to False. Note: Using sudo requires the
|
|
352
|
+
process to have appropriate permissions.
|
|
353
|
+
(default: :obj:`False`)
|
|
345
354
|
|
|
346
355
|
Returns:
|
|
347
|
-
str:
|
|
356
|
+
str: The matching content found in the file. If no matches are
|
|
357
|
+
found, an empty string is returned. Returns an error message
|
|
358
|
+
if the file does not exist or another error occurs.
|
|
348
359
|
"""
|
|
349
360
|
|
|
350
361
|
if not os.path.exists(file):
|
|
@@ -376,14 +387,21 @@ class TerminalToolkit(BaseToolkit):
|
|
|
376
387
|
return f"Error: {e!s}"
|
|
377
388
|
|
|
378
389
|
def file_find_by_name(self, path: str, glob: str) -> str:
|
|
379
|
-
r"""Find files by name
|
|
390
|
+
r"""Find files by name in a specified directory using a glob pattern.
|
|
391
|
+
|
|
392
|
+
This function recursively searches for files matching a given name or
|
|
393
|
+
pattern within a directory. It uses `find` on Unix-like systems and
|
|
394
|
+
`dir` on Windows.
|
|
380
395
|
|
|
381
396
|
Args:
|
|
382
|
-
path (str):
|
|
383
|
-
glob (str):
|
|
397
|
+
path (str): The absolute path of the directory to search in.
|
|
398
|
+
glob (str): The filename pattern to search for, using glob syntax
|
|
399
|
+
(e.g., "*.py", "data*").
|
|
384
400
|
|
|
385
401
|
Returns:
|
|
386
|
-
str:
|
|
402
|
+
str: A newline-separated string containing the paths of the files
|
|
403
|
+
that match the pattern. Returns an error message if the
|
|
404
|
+
directory does not exist or another error occurs.
|
|
387
405
|
"""
|
|
388
406
|
if not os.path.exists(path):
|
|
389
407
|
return f"Directory not found: {path}"
|
|
@@ -649,18 +667,37 @@ class TerminalToolkit(BaseToolkit):
|
|
|
649
667
|
|
|
650
668
|
return True, command
|
|
651
669
|
|
|
652
|
-
def shell_exec(
|
|
653
|
-
|
|
654
|
-
|
|
670
|
+
def shell_exec(
|
|
671
|
+
self, id: str, command: str, interactive: bool = False
|
|
672
|
+
) -> str:
|
|
673
|
+
r"""Executes a shell command in a specified session.
|
|
674
|
+
|
|
675
|
+
This function creates and manages shell sessions to execute commands,
|
|
676
|
+
simulating a real terminal. It can run commands in both non-interactive
|
|
677
|
+
(capturing output) and interactive modes. Each session is identified by
|
|
678
|
+
a unique ID. If a session with the given ID does not exist, it will be
|
|
679
|
+
created.
|
|
655
680
|
|
|
656
681
|
Args:
|
|
657
|
-
id (str):
|
|
658
|
-
|
|
682
|
+
id (str): A unique identifier for the shell session. This is used
|
|
683
|
+
to manage multiple concurrent shell processes.
|
|
684
|
+
command (str): The shell command to be executed.
|
|
685
|
+
interactive (bool, optional): If `True`, the command runs in
|
|
686
|
+
interactive mode, connecting it to the terminal's standard
|
|
687
|
+
input. This is useful for commands that require user input,
|
|
688
|
+
like `ssh`. Defaults to `False`. Interactive mode is only
|
|
689
|
+
supported on macOS and Linux. (default: :obj:`False`)
|
|
659
690
|
|
|
660
691
|
Returns:
|
|
661
|
-
str:
|
|
692
|
+
str: The standard output and standard error from the command. If an
|
|
693
|
+
error occurs during execution, a descriptive error message is
|
|
694
|
+
returned.
|
|
695
|
+
|
|
696
|
+
Note:
|
|
697
|
+
When `interactive` is set to `True`, this function may block if the
|
|
698
|
+
command requires input. In safe mode, some commands that are
|
|
699
|
+
considered dangerous are restricted.
|
|
662
700
|
"""
|
|
663
|
-
# Command execution must be within the working directory
|
|
664
701
|
error_msg = self._enforce_working_dir_for_execution(self.working_dir)
|
|
665
702
|
if error_msg:
|
|
666
703
|
return error_msg
|
|
@@ -673,7 +710,6 @@ class TerminalToolkit(BaseToolkit):
|
|
|
673
710
|
return f"Command rejected: {sanitized_command}"
|
|
674
711
|
command = sanitized_command
|
|
675
712
|
|
|
676
|
-
# If the session does not exist, create a new session
|
|
677
713
|
if id not in self.shell_sessions:
|
|
678
714
|
self.shell_sessions[id] = {
|
|
679
715
|
"process": None,
|
|
@@ -682,7 +718,6 @@ class TerminalToolkit(BaseToolkit):
|
|
|
682
718
|
}
|
|
683
719
|
|
|
684
720
|
try:
|
|
685
|
-
# First, log the command to be executed
|
|
686
721
|
self._update_terminal_output(f"\n$ {command}\n")
|
|
687
722
|
|
|
688
723
|
if command.startswith('python') or command.startswith('pip'):
|
|
@@ -706,42 +741,130 @@ class TerminalToolkit(BaseToolkit):
|
|
|
706
741
|
elif command.startswith('pip'):
|
|
707
742
|
command = command.replace('pip', pip_path, 1)
|
|
708
743
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
744
|
+
if not interactive:
|
|
745
|
+
proc = subprocess.Popen(
|
|
746
|
+
command,
|
|
747
|
+
shell=True,
|
|
748
|
+
cwd=self.working_dir,
|
|
749
|
+
stdout=subprocess.PIPE,
|
|
750
|
+
stderr=subprocess.PIPE,
|
|
751
|
+
stdin=subprocess.PIPE,
|
|
752
|
+
text=True,
|
|
753
|
+
bufsize=1,
|
|
754
|
+
universal_newlines=True,
|
|
755
|
+
env=os.environ.copy(),
|
|
756
|
+
)
|
|
757
|
+
|
|
758
|
+
self.shell_sessions[id]["process"] = proc
|
|
759
|
+
self.shell_sessions[id]["running"] = True
|
|
760
|
+
stdout, stderr = proc.communicate()
|
|
761
|
+
output = stdout or ""
|
|
762
|
+
if stderr:
|
|
763
|
+
output += f"\nStderr Output:\n{stderr}"
|
|
764
|
+
self.shell_sessions[id]["output"] = output
|
|
765
|
+
self._update_terminal_output(output + "\n")
|
|
766
|
+
return output
|
|
767
|
+
|
|
768
|
+
# Interactive mode with real-time streaming via PTY
|
|
769
|
+
if self.os_type not in ['Darwin', 'Linux']:
|
|
770
|
+
return (
|
|
771
|
+
"Interactive mode is not supported on "
|
|
772
|
+
f"{self.os_type} due to PTY limitations."
|
|
773
|
+
)
|
|
774
|
+
|
|
775
|
+
import pty
|
|
776
|
+
import select
|
|
777
|
+
import sys
|
|
778
|
+
import termios
|
|
779
|
+
import tty
|
|
780
|
+
|
|
781
|
+
# Fork a new process with a PTY
|
|
782
|
+
pid, master_fd = pty.fork()
|
|
783
|
+
|
|
784
|
+
if pid == 0: # Child process
|
|
785
|
+
# Execute the command in the child process
|
|
786
|
+
try:
|
|
787
|
+
import shlex
|
|
788
|
+
|
|
789
|
+
parts = shlex.split(command)
|
|
790
|
+
if not parts:
|
|
791
|
+
logger.error("Error: Empty command")
|
|
792
|
+
os._exit(1)
|
|
793
|
+
|
|
794
|
+
os.chdir(self.working_dir)
|
|
795
|
+
os.execvp(parts[0], parts)
|
|
796
|
+
except (ValueError, IndexError, OSError) as e:
|
|
797
|
+
logger.error(f"Command execution error: {e}")
|
|
798
|
+
os._exit(127)
|
|
799
|
+
except Exception as e:
|
|
800
|
+
logger.error(f"Unexpected error: {e}")
|
|
801
|
+
os._exit(1)
|
|
721
802
|
|
|
722
|
-
#
|
|
723
|
-
self.shell_sessions[id]["
|
|
803
|
+
# Parent process
|
|
804
|
+
self.shell_sessions[id]["process_id"] = pid
|
|
724
805
|
self.shell_sessions[id]["running"] = True
|
|
806
|
+
output_lines: List[str] = []
|
|
807
|
+
original_settings = termios.tcgetattr(sys.stdin)
|
|
725
808
|
|
|
726
|
-
|
|
727
|
-
|
|
809
|
+
try:
|
|
810
|
+
tty.setraw(sys.stdin.fileno())
|
|
728
811
|
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
812
|
+
while True:
|
|
813
|
+
# Check if the child process has exited
|
|
814
|
+
try:
|
|
815
|
+
wait_pid, status = os.waitpid(pid, os.WNOHANG)
|
|
816
|
+
if wait_pid == pid:
|
|
817
|
+
self.shell_sessions[id]["running"] = False
|
|
818
|
+
break
|
|
819
|
+
except OSError:
|
|
820
|
+
# Process already reaped
|
|
821
|
+
self.shell_sessions[id]["running"] = False
|
|
822
|
+
break
|
|
823
|
+
|
|
824
|
+
# Use select to wait for I/O on stdin or master PTY
|
|
825
|
+
r, _, _ = select.select(
|
|
826
|
+
[sys.stdin, master_fd], [], [], 0.1
|
|
827
|
+
)
|
|
732
828
|
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
829
|
+
if master_fd in r:
|
|
830
|
+
try:
|
|
831
|
+
data = os.read(master_fd, 1024)
|
|
832
|
+
if not data:
|
|
833
|
+
break
|
|
834
|
+
decoded_data = data.decode(
|
|
835
|
+
'utf-8', errors='replace'
|
|
836
|
+
)
|
|
837
|
+
# Echo to user's terminal and log
|
|
838
|
+
self._update_terminal_output(decoded_data)
|
|
839
|
+
output_lines.append(decoded_data)
|
|
840
|
+
except OSError:
|
|
841
|
+
break # PTY has been closed
|
|
736
842
|
|
|
737
|
-
|
|
843
|
+
if sys.stdin in r:
|
|
844
|
+
try:
|
|
845
|
+
user_input = os.read(sys.stdin.fileno(), 1024)
|
|
846
|
+
if not user_input:
|
|
847
|
+
break
|
|
848
|
+
os.write(master_fd, user_input)
|
|
849
|
+
except OSError:
|
|
850
|
+
break
|
|
851
|
+
|
|
852
|
+
finally:
|
|
853
|
+
if original_settings is not None:
|
|
854
|
+
termios.tcsetattr(
|
|
855
|
+
sys.stdin, termios.TCSADRAIN, original_settings
|
|
856
|
+
)
|
|
857
|
+
if master_fd:
|
|
858
|
+
os.close(master_fd)
|
|
859
|
+
|
|
860
|
+
final_output = "".join(output_lines)
|
|
861
|
+
self.shell_sessions[id]["output"] = final_output
|
|
862
|
+
return final_output
|
|
738
863
|
|
|
739
864
|
except Exception as e:
|
|
740
865
|
error_msg = f"Command execution error: {e!s}"
|
|
741
866
|
logger.error(error_msg)
|
|
742
867
|
self._update_terminal_output(f"\nError: {error_msg}\n")
|
|
743
|
-
|
|
744
|
-
# More detailed error information
|
|
745
868
|
import traceback
|
|
746
869
|
|
|
747
870
|
detailed_error = traceback.format_exc()
|
|
@@ -751,13 +874,19 @@ class TerminalToolkit(BaseToolkit):
|
|
|
751
874
|
)
|
|
752
875
|
|
|
753
876
|
def shell_view(self, id: str) -> str:
|
|
754
|
-
r"""View the
|
|
877
|
+
r"""View the full output history of a specified shell session.
|
|
878
|
+
|
|
879
|
+
Retrieves the accumulated output (both stdout and stderr) generated by
|
|
880
|
+
commands in the specified session since its creation. This is useful
|
|
881
|
+
for checking the complete history of a session, especially after a
|
|
882
|
+
command has finished execution.
|
|
755
883
|
|
|
756
884
|
Args:
|
|
757
|
-
id (str):
|
|
885
|
+
id (str): The unique identifier of the shell session to view.
|
|
758
886
|
|
|
759
887
|
Returns:
|
|
760
|
-
str:
|
|
888
|
+
str: The complete output history of the shell session. Returns an
|
|
889
|
+
error message if the session is not found.
|
|
761
890
|
"""
|
|
762
891
|
if id not in self.shell_sessions:
|
|
763
892
|
return f"Shell session not found: {id}"
|
|
@@ -788,16 +917,22 @@ class TerminalToolkit(BaseToolkit):
|
|
|
788
917
|
return f"Error: {e!s}"
|
|
789
918
|
|
|
790
919
|
def shell_wait(self, id: str, seconds: Optional[int] = None) -> str:
|
|
791
|
-
r"""Wait for
|
|
792
|
-
|
|
920
|
+
r"""Wait for a command to finish in a specified shell session.
|
|
921
|
+
|
|
922
|
+
Blocks execution and waits for the running process in a shell session
|
|
923
|
+
to complete. This is useful for ensuring a long-running command has
|
|
924
|
+
finished before proceeding.
|
|
793
925
|
|
|
794
926
|
Args:
|
|
795
|
-
id (str):
|
|
796
|
-
seconds (Optional[int], optional):
|
|
797
|
-
If None
|
|
927
|
+
id (str): The unique identifier of the target shell session.
|
|
928
|
+
seconds (Optional[int], optional): The maximum time to wait, in
|
|
929
|
+
seconds. If `None`, it waits indefinitely.
|
|
930
|
+
(default: :obj:`None`)
|
|
798
931
|
|
|
799
932
|
Returns:
|
|
800
|
-
str:
|
|
933
|
+
str: A message indicating that the process has completed, including
|
|
934
|
+
the final output. If the process times out, it returns a
|
|
935
|
+
timeout message.
|
|
801
936
|
"""
|
|
802
937
|
if id not in self.shell_sessions:
|
|
803
938
|
return f"Shell session not found: {id}"
|
|
@@ -857,13 +992,20 @@ class TerminalToolkit(BaseToolkit):
|
|
|
857
992
|
) -> str:
|
|
858
993
|
r"""Write input to a running process in a specified shell session.
|
|
859
994
|
|
|
995
|
+
Sends a string of text to the standard input of a running process.
|
|
996
|
+
This is useful for interacting with commands that require input. This
|
|
997
|
+
function cannot be used with a command that was started in
|
|
998
|
+
interactive mode.
|
|
999
|
+
|
|
860
1000
|
Args:
|
|
861
|
-
id (str):
|
|
862
|
-
input (str):
|
|
863
|
-
press_enter (bool):
|
|
1001
|
+
id (str): The unique identifier of the target shell session.
|
|
1002
|
+
input (str): The text to write to the process's stdin.
|
|
1003
|
+
press_enter (bool): If `True`, a newline character (`\n`) is
|
|
1004
|
+
appended to the input, simulating pressing the Enter key.
|
|
864
1005
|
|
|
865
1006
|
Returns:
|
|
866
|
-
str:
|
|
1007
|
+
str: A status message indicating whether the input was sent, or an
|
|
1008
|
+
error message if the operation fails.
|
|
867
1009
|
"""
|
|
868
1010
|
if id not in self.shell_sessions:
|
|
869
1011
|
return f"Shell session not found: {id}"
|
|
@@ -899,11 +1041,17 @@ class TerminalToolkit(BaseToolkit):
|
|
|
899
1041
|
def shell_kill_process(self, id: str) -> str:
|
|
900
1042
|
r"""Terminate a running process in a specified shell session.
|
|
901
1043
|
|
|
1044
|
+
Forcibly stops a command that is currently running in a shell session.
|
|
1045
|
+
This is useful for ending processes that are stuck, running too long,
|
|
1046
|
+
or need to be cancelled.
|
|
1047
|
+
|
|
902
1048
|
Args:
|
|
903
|
-
id (str):
|
|
1049
|
+
id (str): The unique identifier of the shell session containing the
|
|
1050
|
+
process to be terminated.
|
|
904
1051
|
|
|
905
1052
|
Returns:
|
|
906
|
-
str:
|
|
1053
|
+
str: A status message indicating that the process has been
|
|
1054
|
+
terminated, or an error message if the operation fails.
|
|
907
1055
|
"""
|
|
908
1056
|
if id not in self.shell_sessions:
|
|
909
1057
|
return f"Shell session not found: {id}"
|
|
@@ -939,22 +1087,24 @@ class TerminalToolkit(BaseToolkit):
|
|
|
939
1087
|
return f"Error killing process: {e!s}"
|
|
940
1088
|
|
|
941
1089
|
def ask_user_for_help(self, id: str) -> str:
|
|
942
|
-
r"""
|
|
1090
|
+
r"""Pause the agent and ask a human for help with a command.
|
|
943
1091
|
|
|
944
|
-
This function should be
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
specified
|
|
948
|
-
to the
|
|
1092
|
+
This function should be used when the agent is stuck and requires
|
|
1093
|
+
manual intervention, such as solving a CAPTCHA or debugging a complex
|
|
1094
|
+
issue. It pauses the agent's execution and allows a human to take
|
|
1095
|
+
control of a specified shell session. The human can execute one
|
|
1096
|
+
command to resolve the issue, and then control is returned to the
|
|
1097
|
+
agent.
|
|
949
1098
|
|
|
950
1099
|
Args:
|
|
951
|
-
id (str):
|
|
952
|
-
interact with. If the session does not
|
|
953
|
-
created
|
|
1100
|
+
id (str): The identifier of the shell session for the human to
|
|
1101
|
+
interact with. If the session does not exist, it will be
|
|
1102
|
+
created.
|
|
954
1103
|
|
|
955
1104
|
Returns:
|
|
956
1105
|
str: A status message indicating that the human has finished,
|
|
957
|
-
including the number of commands executed.
|
|
1106
|
+
including the number of commands executed. If the takeover
|
|
1107
|
+
times out or fails, an error message is returned.
|
|
958
1108
|
"""
|
|
959
1109
|
# Input validation
|
|
960
1110
|
if not id or not isinstance(id, str):
|
camel/utils/mcp_client.py
CHANGED
|
@@ -113,7 +113,11 @@ class ServerConfig(BaseModel):
|
|
|
113
113
|
# Advanced options
|
|
114
114
|
sse_read_timeout: float = 300.0 # 5 minutes
|
|
115
115
|
terminate_on_close: bool = True
|
|
116
|
-
|
|
116
|
+
|
|
117
|
+
# New transport type parameter
|
|
118
|
+
type: Optional[str] = None
|
|
119
|
+
|
|
120
|
+
# Legacy parameter for backward compatibility
|
|
117
121
|
prefer_sse: bool = False
|
|
118
122
|
|
|
119
123
|
@model_validator(mode='after')
|
|
@@ -128,11 +132,43 @@ class ServerConfig(BaseModel):
|
|
|
128
132
|
if self.command and self.url:
|
|
129
133
|
raise ValueError("Cannot specify both 'command' and 'url'")
|
|
130
134
|
|
|
135
|
+
# Validate type if provided
|
|
136
|
+
if self.type is not None:
|
|
137
|
+
valid_types = {"stdio", "sse", "streamable_http", "websocket"}
|
|
138
|
+
if self.type not in valid_types:
|
|
139
|
+
raise ValueError(
|
|
140
|
+
f"Invalid type: "
|
|
141
|
+
f"'{self.type}'. "
|
|
142
|
+
f"Valid options: {valid_types}"
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
# Issue deprecation warning if prefer_sse is used
|
|
146
|
+
if self.prefer_sse and self.type is None:
|
|
147
|
+
import warnings
|
|
148
|
+
|
|
149
|
+
warnings.warn(
|
|
150
|
+
"The 'prefer_sse' parameter is deprecated. "
|
|
151
|
+
"Use 'type=\"sse\"' instead.",
|
|
152
|
+
DeprecationWarning,
|
|
153
|
+
stacklevel=2,
|
|
154
|
+
)
|
|
155
|
+
|
|
131
156
|
return self
|
|
132
157
|
|
|
133
158
|
@property
|
|
134
159
|
def transport_type(self) -> TransportType:
|
|
135
160
|
r"""Automatically detect transport type based on configuration."""
|
|
161
|
+
# Use explicit transport type if provided
|
|
162
|
+
if self.type is not None:
|
|
163
|
+
transport_map = {
|
|
164
|
+
"stdio": TransportType.STDIO,
|
|
165
|
+
"sse": TransportType.SSE,
|
|
166
|
+
"streamable_http": TransportType.STREAMABLE_HTTP,
|
|
167
|
+
"websocket": TransportType.WEBSOCKET,
|
|
168
|
+
}
|
|
169
|
+
return transport_map[self.type]
|
|
170
|
+
|
|
171
|
+
# If no type is provided, fall back to automatic detection
|
|
136
172
|
if self.command:
|
|
137
173
|
return TransportType.STDIO
|
|
138
174
|
elif self.url:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: camel-ai
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.71a5
|
|
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
|
|
@@ -15,7 +15,7 @@ Requires-Dist: docstring-parser<0.16,>=0.15
|
|
|
15
15
|
Requires-Dist: httpx<1.0.0dev,>=0.28.0
|
|
16
16
|
Requires-Dist: jsonschema<5,>=4
|
|
17
17
|
Requires-Dist: mcp>=1.3.0
|
|
18
|
-
Requires-Dist: openai<2,>=1.
|
|
18
|
+
Requires-Dist: openai<2,>=1.86.0
|
|
19
19
|
Requires-Dist: pillow<11.0.0,>=10.1.0
|
|
20
20
|
Requires-Dist: psutil<6,>=5.9.8
|
|
21
21
|
Requires-Dist: pydantic>=2.10.6
|
|
@@ -39,7 +39,7 @@ Requires-Dist: dappier<0.4,>=0.3.3; extra == 'all'
|
|
|
39
39
|
Requires-Dist: datacommons-pandas<0.0.4,>=0.0.3; extra == 'all'
|
|
40
40
|
Requires-Dist: datacommons<2,>=1.4.3; extra == 'all'
|
|
41
41
|
Requires-Dist: datasets<4,>=3; extra == 'all'
|
|
42
|
-
Requires-Dist: daytona-sdk
|
|
42
|
+
Requires-Dist: daytona-sdk==0.20.0; extra == 'all'
|
|
43
43
|
Requires-Dist: diffusers<0.26,>=0.25.0; extra == 'all'
|
|
44
44
|
Requires-Dist: discord-py<3,>=2.3.2; extra == 'all'
|
|
45
45
|
Requires-Dist: docker<8,>=7.1.0; extra == 'all'
|
|
@@ -98,7 +98,6 @@ Requires-Dist: pygithub<3,>=2.6.0; extra == 'all'
|
|
|
98
98
|
Requires-Dist: pylatex>=1.4.2; extra == 'all'
|
|
99
99
|
Requires-Dist: pymilvus<3,>=2.4.0; extra == 'all'
|
|
100
100
|
Requires-Dist: pymupdf<2,>=1.22.5; extra == 'all'
|
|
101
|
-
Requires-Dist: pymupdf>=1.26.1; extra == 'all'
|
|
102
101
|
Requires-Dist: pyobvector>=0.1.18; extra == 'all'
|
|
103
102
|
Requires-Dist: pyowm<4,>=3.3.0; extra == 'all'
|
|
104
103
|
Requires-Dist: pytelegrambotapi<5,>=4.18.0; extra == 'all'
|
|
@@ -112,6 +111,7 @@ Requires-Dist: qdrant-client<2,>=1.9.0; extra == 'all'
|
|
|
112
111
|
Requires-Dist: rank-bm25<0.3,>=0.2.2; extra == 'all'
|
|
113
112
|
Requires-Dist: redis<6,>=5.0.6; extra == 'all'
|
|
114
113
|
Requires-Dist: reka-api<4,>=3.0.8; extra == 'all'
|
|
114
|
+
Requires-Dist: reportlab>=4.4.2; extra == 'all'
|
|
115
115
|
Requires-Dist: requests-oauthlib<2,>=1.3.1; extra == 'all'
|
|
116
116
|
Requires-Dist: rlcard<1.3.0,>=1.0.0; extra == 'all'
|
|
117
117
|
Requires-Dist: rouge<2,>=1.0.1; extra == 'all'
|
|
@@ -127,6 +127,7 @@ Requires-Dist: sympy<2,>=1.13.3; extra == 'all'
|
|
|
127
127
|
Requires-Dist: tabulate>=0.9.0; extra == 'all'
|
|
128
128
|
Requires-Dist: tavily-python<0.6,>=0.5.0; extra == 'all'
|
|
129
129
|
Requires-Dist: textblob<0.18,>=0.17.1; extra == 'all'
|
|
130
|
+
Requires-Dist: traceroot==0.0.3a2; extra == 'all'
|
|
130
131
|
Requires-Dist: transformers<5,>=4; extra == 'all'
|
|
131
132
|
Requires-Dist: tree-sitter-python<0.24,>=0.23.6; extra == 'all'
|
|
132
133
|
Requires-Dist: tree-sitter<0.24,>=0.23.2; extra == 'all'
|
|
@@ -183,13 +184,14 @@ Requires-Dist: uv<0.8,>=0.7.0; extra == 'dev'
|
|
|
183
184
|
Provides-Extra: dev-tools
|
|
184
185
|
Requires-Dist: aci-sdk>=1.0.0b1; extra == 'dev-tools'
|
|
185
186
|
Requires-Dist: agentops<0.4,>=0.3.21; extra == 'dev-tools'
|
|
186
|
-
Requires-Dist: daytona-sdk
|
|
187
|
+
Requires-Dist: daytona-sdk==0.20.0; extra == 'dev-tools'
|
|
187
188
|
Requires-Dist: docker<8,>=7.1.0; extra == 'dev-tools'
|
|
188
189
|
Requires-Dist: e2b-code-interpreter<2,>=1.0.3; extra == 'dev-tools'
|
|
189
190
|
Requires-Dist: ipykernel<7,>=6.0.0; extra == 'dev-tools'
|
|
190
191
|
Requires-Dist: jupyter-client<9,>=8.6.2; extra == 'dev-tools'
|
|
191
192
|
Requires-Dist: langfuse>=2.60.5; extra == 'dev-tools'
|
|
192
193
|
Requires-Dist: mcp>=1.3.0; extra == 'dev-tools'
|
|
194
|
+
Requires-Dist: traceroot==0.0.3a2; extra == 'dev-tools'
|
|
193
195
|
Requires-Dist: tree-sitter-python<0.24,>=0.23.6; extra == 'dev-tools'
|
|
194
196
|
Requires-Dist: tree-sitter<0.24,>=0.23.2; extra == 'dev-tools'
|
|
195
197
|
Requires-Dist: typer>=0.15.2; extra == 'dev-tools'
|
|
@@ -214,8 +216,8 @@ Requires-Dist: pandasai<3,>=2.3.0; extra == 'document-tools'
|
|
|
214
216
|
Requires-Dist: prance<24,>=23.6.21.0; extra == 'document-tools'
|
|
215
217
|
Requires-Dist: pylatex>=1.4.2; extra == 'document-tools'
|
|
216
218
|
Requires-Dist: pymupdf<2,>=1.22.5; extra == 'document-tools'
|
|
217
|
-
Requires-Dist: pymupdf>=1.26.1; extra == 'document-tools'
|
|
218
219
|
Requires-Dist: python-pptx>=1.0.2; extra == 'document-tools'
|
|
220
|
+
Requires-Dist: reportlab>=4.4.2; extra == 'document-tools'
|
|
219
221
|
Requires-Dist: tabulate>=0.9.0; extra == 'document-tools'
|
|
220
222
|
Requires-Dist: unstructured==0.16.20; extra == 'document-tools'
|
|
221
223
|
Requires-Dist: xls2xlsx>=0.2.0; extra == 'document-tools'
|
|
@@ -272,10 +274,10 @@ Requires-Dist: pyautogui<0.10,>=0.9.54; extra == 'owl'
|
|
|
272
274
|
Requires-Dist: pydub<0.26,>=0.25.1; extra == 'owl'
|
|
273
275
|
Requires-Dist: pylatex>=1.4.2; extra == 'owl'
|
|
274
276
|
Requires-Dist: pymupdf<2,>=1.22.5; extra == 'owl'
|
|
275
|
-
Requires-Dist: pymupdf>=1.26.1; extra == 'owl'
|
|
276
277
|
Requires-Dist: pytesseract>=0.3.13; extra == 'owl'
|
|
277
278
|
Requires-Dist: python-dotenv<2,>=1.0.0; extra == 'owl'
|
|
278
279
|
Requires-Dist: python-pptx>=1.0.2; extra == 'owl'
|
|
280
|
+
Requires-Dist: reportlab>=4.4.2; extra == 'owl'
|
|
279
281
|
Requires-Dist: requests-oauthlib<2,>=1.3.1; extra == 'owl'
|
|
280
282
|
Requires-Dist: rouge<2,>=1.0.1; extra == 'owl'
|
|
281
283
|
Requires-Dist: scenedetect>=0.6.5.2; extra == 'owl'
|
|
@@ -753,6 +755,45 @@ Practical guides and tutorials for implementing specific functionalities in CAME
|
|
|
753
755
|
| **[3 Ways to Ingest Data from Websites with Firecrawl](https://docs.camel-ai.org/cookbooks/data_processing/ingest_data_from_websites_with_Firecrawl.html)** | Explore three methods for extracting and processing data from websites using Firecrawl. |
|
|
754
756
|
| **[Create AI Agents that work with your PDFs](https://docs.camel-ai.org/cookbooks/data_processing/agent_with_chunkr_for_pdf_parsing.html)** | Learn how to create AI agents that work with your PDFs using Chunkr and Mistral AI. |
|
|
755
757
|
|
|
758
|
+
<br>
|
|
759
|
+
|
|
760
|
+
## Real-World Usecases
|
|
761
|
+
|
|
762
|
+
Real-world usecases demonstrating how CAMEL’s multi-agent framework enables real business value across infrastructure automation, productivity workflows, retrieval-augmented conversations, intelligent document/video analysis, and collaborative research.
|
|
763
|
+
|
|
764
|
+
### 1 Infrastructure Automation
|
|
765
|
+
|
|
766
|
+
| Usecase | Description |
|
|
767
|
+
| :----------------------------------------------------------- | :----------------------------------------------------------- |
|
|
768
|
+
| **[ACI MCP](https://github.com/camel-ai/camel/tree/master/examples/usecases/aci_mcp)** | Real-world usecases demonstrating how CAMEL’s multi-agent framework enables real business value across infrastructure automation, productivity workflows, retrieval-augmented conversations, intelligent document/video analysis, and collaborative research. |
|
|
769
|
+
| **[Cloudflare MCP CAMEL](https://github.com/camel-ai/camel/tree/master/examples/usecases/cloudfare_mcp_camel)** | Intelligent agents manage Cloudflare resources dynamically, enabling scalable and efficient cloud security and performance tuning. |
|
|
770
|
+
|
|
771
|
+
### 2 Productivity & Business Workflows
|
|
772
|
+
|
|
773
|
+
| Usecase | Description |
|
|
774
|
+
| :----------------------------------------------------------- | :----------------------------------------------------------- |
|
|
775
|
+
| **[Airbnb MCP](https://github.com/camel-ai/camel/tree/master/examples/usecases/airbnb_mcp)** | Coordinate agents to optimize and manage Airbnb listings and host operations. |
|
|
776
|
+
| **[PPTX Toolkit Usecase](https://github.com/camel-ai/camel/tree/master/examples/usecases/pptx_toolkit_usecase)** | Analyze PowerPoint documents and extract structured insights through multi-agent collaboration. |
|
|
777
|
+
|
|
778
|
+
### 3 Retrieval-Augmented Multi-Agent Chat
|
|
779
|
+
|
|
780
|
+
| Usecase | Description |
|
|
781
|
+
| :----------------------------------------------------------- | :----------------------------------------------------------- |
|
|
782
|
+
| **[Chat with GitHub](https://github.com/camel-ai/camel/tree/master/examples/usecases/chat_with_github)** | Query and understand GitHub codebases through CAMEL agents leveraging RAG-style workflows, accelerating developer onboarding and codebase navigation. |
|
|
783
|
+
| **[Chat with YouTube](https://github.com/camel-ai/camel/tree/master/examples/usecases/chat_with_youtube)** | Conversational agents extract and summarize video transcripts, enabling faster content understanding and repurposing. |
|
|
784
|
+
|
|
785
|
+
### 4 Video & Document Intelligence
|
|
786
|
+
|
|
787
|
+
| Usecase | Description |
|
|
788
|
+
| :----------------------------------------------------------- | :----------------------------------------------------------- |
|
|
789
|
+
| **[YouTube OCR](https://github.com/camel-ai/camel/tree/master/examples/usecases/youtube_ocr)** | Agents perform OCR on video screenshots to summarize visual content, supporting media monitoring and compliance. |
|
|
790
|
+
| **[Mistral OCR](https://github.com/camel-ai/camel/tree/master/examples/usecases/mistral_OCR)** | CAMEL agents use OCR with Mistral to analyze documents, reducing manual effort in document understanding workflows. |
|
|
791
|
+
|
|
792
|
+
### 5 Research & Collaboration
|
|
793
|
+
|
|
794
|
+
| Usecase | Description |
|
|
795
|
+
| :----------------------------------------------------------- | :----------------------------------------------------------- |
|
|
796
|
+
| **[Multi-Agent Research Assistant](https://github.com/camel-ai/camel/tree/master/examples/usecases/multi_agent_research_assistant)** | Simulates a team of research agents collaborating on literature review, improving efficiency in exploratory analysis and reporting. |
|
|
756
797
|
|
|
757
798
|
<br>
|
|
758
799
|
|