From de975d3bf93bb25bdeddefeb2ef35767ee7e7891 Mon Sep 17 00:00:00 2001 From: Torantulino Date: Sat, 1 Apr 2023 16:01:36 +0100 Subject: [PATCH] Implements code execution command! This allows the AI to execute code inside it's workspace folder. --- scripts/ai_functions.py | 4 +-- scripts/commands.py | 7 +++-- scripts/data/prompt.txt | 5 ++-- scripts/execute_code.py | 56 +++++++++++++++++----------------------- scripts/main.py | 4 +-- scripts/requirements.txt | 4 +-- 6 files changed, 37 insertions(+), 43 deletions(-) diff --git a/scripts/ai_functions.py b/scripts/ai_functions.py index 7d651bd9..0f778093 100644 --- a/scripts/ai_functions.py +++ b/scripts/ai_functions.py @@ -39,9 +39,9 @@ def improve_code(suggestions: List[str], code: str) -> str: ### Writing tests -def write_tests(code: str, focus: Optional[str] = None) -> str: +def write_tests(code: str, focus: List[str]) -> str: function_string = "def create_test_cases(code: str, focus: Optional[str] = None) -> str:" - args = [focus] if focus else [] + args = [code, json.dumps(focus)] description_string = """Generates test cases for the existing code, focusing on specific areas if required.""" result_string = call_ai_function(function_string, args, description_string) diff --git a/scripts/commands.py b/scripts/commands.py index d5be8ffe..b8bcefe8 100644 --- a/scripts/commands.py +++ b/scripts/commands.py @@ -7,6 +7,7 @@ import speak from config import Config import ai_functions as ai from file_operations import read_file, write_to_file, append_to_file, delete_file +from execute_code import execute_python_file cfg = Config() @@ -73,11 +74,13 @@ def execute_command(command_name, arguments): return ai.improve_code(arguments["suggestions"], arguments["code"]) elif command_name == "write_tests": return ai.write_tests(arguments["code"], arguments.get("focus")) + elif command_name == "execute_python_file": # Add this command + return execute_python_file(arguments["file"]) elif command_name == "task_complete": shutdown() else: - return f"unknown command {command_name}" - # All other errors, return "Error: + error message" + return f"Unknown command {command_name}" + # All errors, return "Error: + error message" except Exception as e: return "Error: " + str(e) diff --git a/scripts/data/prompt.txt b/scripts/data/prompt.txt index 744575bc..4ce5424f 100644 --- a/scripts/data/prompt.txt +++ b/scripts/data/prompt.txt @@ -21,8 +21,9 @@ COMMANDS: 14. Delete file: "delete_file", args: "file": "" 15. Evaluate Code: "evaluate_code", args: "code": "" 16. Get Improved Code: "improve_code", args: "suggestions": "", "code": "" -17. Write Tests: "write_tests", args: "code": "", "focus": "" -18. Task Complete (Shutdown): "task_complete", args: "reason": "" +17. Write Tests: "write_tests", args: "code": "", "focus": "" +18. Execute Python File: "execute_python_file", args: "file": "" +19. Task Complete (Shutdown): "task_complete", args: "reason": "" RESOURCES: diff --git a/scripts/execute_code.py b/scripts/execute_code.py index e6fc5443..74f871a7 100644 --- a/scripts/execute_code.py +++ b/scripts/execute_code.py @@ -1,47 +1,37 @@ -from io import StringIO +import docker import os -import sys -import traceback -from RestrictedPython import compile_restricted, safe_globals - def execute_python_file(file): workspace_folder = "auto_gpt_workspace" if not file.endswith(".py"): return "Error: Invalid file type. Only .py files are allowed." - + + file_path = os.path.join(workspace_folder, file) + + if not os.path.isfile(file_path): + return f"Error: File '{file}' does not exist." + try: - # Prepend the workspace folder to the provided file name - file_path = os.path.join(workspace_folder, file) + client = docker.from_env() - # Check if the file exists - if not os.path.isfile(file_path): - return f"Error: File '{file}' does not exist." + # You can replace 'python:3.8' with the desired Python image/version + # You can find available Python images on Docker Hub: https://hub.docker.com/_/python + container = client.containers.run( + 'python:3.8', + f'python {file}', + volumes={os.path.abspath(workspace_folder): {'bind': '/workspace', 'mode': 'ro'}}, + working_dir='/workspace', + stderr=True, + stdout=True, + detach=True, + ) - # Read the content of the file - with open(file_path, 'r') as f: - code = f.read() + output = container.wait() + logs = container.logs().decode('utf-8') + container.remove() - # Capture stdout and stderr - original_stdout = sys.stdout - original_stderr = sys.stderr - sys.stdout = StringIO() - sys.stderr = StringIO() + return logs - # Compile and execute the code in a restricted environment - try: - restricted_code = compile_restricted(code, '', 'exec') - exec(restricted_code, safe_globals) - except Exception as e: - result = f"Error while executing code:\n{traceback.format_exc()}" - else: - result = sys.stdout.getvalue() - - # Restore original stdout and stderr - sys.stdout = original_stdout - sys.stderr = original_stderr - - return result except Exception as e: return f"Error: {str(e)}" \ No newline at end of file diff --git a/scripts/main.py b/scripts/main.py index 63320e1c..fe338ae8 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -191,9 +191,9 @@ while True: # Exectute command if command_name.lower() != "error": - result = cmd.execute_command(command_name, arguments) + result = f"Command {command_name} returned: {cmd.execute_command(command_name, arguments)}" else: - result ="Error: " + arguments + result =f"Command {command_name} threw the following error: " + arguments # Check if there's a result from the command append it to the message history if result != None: diff --git a/scripts/requirements.txt b/scripts/requirements.txt index 8b3c80b0..ca10628d 100644 --- a/scripts/requirements.txt +++ b/scripts/requirements.txt @@ -1,7 +1,7 @@ -beautifulsoup4==4.12.0 +beautifulsoup4==4.9.3 colorama==0.4.6 googlesearch_python==1.1.0 openai==0.27.0 playsound==1.2.2 readability_lxml==0.8.1 -requests==2.28.2 +requests==2.25.1 \ No newline at end of file