diff --git a/.gitignore b/.gitignore index d960957..c0f8bf4 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ build run-venv/ .mypy_cache/ .benchmarks/ -site/ \ No newline at end of file +site/ +uv.lock \ No newline at end of file diff --git a/README.md b/README.md index c23de06..51a38da 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,6 @@ Clone the github repository and start immediately with a standalone REST API. ```bash git clone https://github.com/Jonathan-Adly/agentrun cd agentrun/agentrun-api -cp .env.example .env.dev docker-compose up -d --build ``` @@ -86,7 +85,11 @@ fetch('http://localhost:8000/v1/run/', { Or if you prefer the terminal. -`curl -X POST http://localhost:8000/v1/run/ -H "Content-Type: application/json" -d '{"code": "print(\'hello, world!\')"}'` +```bash +curl -X POST http://localhost:8000/v1/run/ \ +-H "Content-Type: application/json" \ +-d '{"code": "print(\"hello, world!\")"}' +``` ### pip install @@ -140,7 +143,6 @@ Here is the steps to run the API: ```bash git clone https://github.com/Jonathan-Adly/agentrun cd agentrun/agentrun-api -cp .env.example .env.dev docker-compose up -d --build ``` @@ -338,12 +340,12 @@ AgentRun Median execution time is <200ms without dependencies and ~400ms with 1 To contribute to this library, first checkout the code. Then create a new virtual environment: ```bash cd agentrun -python -m venv venv -source venv/bin/activate +uv venv +source .venv/bin/activate ``` Now install the dependencies and test dependencies: ```bash -pip install -e '.[test]' +uv sync --all-extras ``` To run the tests: ```bash diff --git a/agentrun-api/.env.dev b/agentrun-api/.env.dev deleted file mode 100644 index d676597..0000000 --- a/agentrun-api/.env.dev +++ /dev/null @@ -1,2 +0,0 @@ -# Container name - can change depending on your docker setup -CONTAINER_NAME="agentrun-api-python_runner-1" diff --git a/agentrun-api/.env.example b/agentrun-api/.env.example deleted file mode 100644 index d676597..0000000 --- a/agentrun-api/.env.example +++ /dev/null @@ -1,2 +0,0 @@ -# Container name - can change depending on your docker setup -CONTAINER_NAME="agentrun-api-python_runner-1" diff --git a/agentrun-api/docker-compose.yml b/agentrun-api/docker-compose.yml index 40155e9..75c2de3 100644 --- a/agentrun-api/docker-compose.yml +++ b/agentrun-api/docker-compose.yml @@ -9,10 +9,9 @@ services: - /var/run/docker.sock:/var/run/docker.sock ports: - "8000:8000" - env_file: - - ./.env.dev python_runner: + container_name: agentrun-api-python-runner-1 build: context: ./ dockerfile: docker/code_runner/Dockerfile diff --git a/agentrun-api/src/api/main.py b/agentrun-api/src/api/main.py index 257a84a..2d963e8 100644 --- a/agentrun-api/src/api/main.py +++ b/agentrun-api/src/api/main.py @@ -6,9 +6,25 @@ from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import RedirectResponse from pydantic import BaseModel +from contextlib import asynccontextmanager from agentrun import AgentRun +# Create a global runner variable +runner = None + + +@asynccontextmanager +async def lifespan(app: FastAPI): + # Initialize the runner when FastAPI starts + global runner + runner = AgentRun( + container_name=os.environ.get("CONTAINER_NAME", "agentrun-api-python-runner-1"), + cached_dependencies=["requests", "yfinance"], + default_timeout=60 * 5, + ) + yield + class CodeSchema(BaseModel): code: str @@ -18,7 +34,7 @@ class OutputSchema(BaseModel): output: str -app = FastAPI() +app = FastAPI(lifespan=lifespan) # allow all origins app.add_middleware( @@ -44,11 +60,6 @@ async def redirect_docs(): @app.post("/v1/run/", response_model=OutputSchema) async def run_code(code_schema: CodeSchema): - runner = AgentRun( - container_name=os.environ.get("CONTAINER_NAME", "agentrun-api-python_runner-1"), - cached_dependencies=["requests", "yfinance"], - default_timeout=60 * 5, - ) python_code = code_schema.code with ThreadPoolExecutor() as executor: future = executor.submit(runner.execute_code_in_container, python_code) diff --git a/agentrun/__init__.py b/agentrun/__init__.py index b5e00fd..56310e1 100644 --- a/agentrun/__init__.py +++ b/agentrun/__init__.py @@ -77,7 +77,7 @@ def __init__( ): raise ValueError("Some cached dependencies are not in the whitelist.") container = self.client.containers.get(self.container_name) - command = f"pip install uv" + command = "pip install uv" exit_code, output = self.execute_command_in_container( container, command, timeout=120 ) @@ -238,7 +238,7 @@ def safety_check(self, python_code: str) -> dict[str, object]: try: # Compile the code using RestrictedPython with a filename indicating its dynamic nature - compiled_code = compile_restricted( + compile_restricted( python_code, filename="", mode="exec" ) # Note: Execution step is omitted to only check the code without running it @@ -350,7 +350,6 @@ def copy_code_to_container( Returns: Success message or error message """ - result = {"success": False, "message": ""} script_name = f"script_{uuid4().hex}.py" temp_script_path = os.path.join("/tmp", script_name) @@ -379,7 +378,7 @@ def clean_up( if script_name: os.remove(os.path.join("/tmp", script_name)) container.exec_run(cmd=f"rm /code/{script_name}", workdir="/code") - dep_uninstall_result = self.uninstall_dependencies(container, dependencies) + self.uninstall_dependencies(container, dependencies) return None def execute_code_in_container(self, python_code: str) -> str: diff --git a/pyproject.toml b/pyproject.toml index 5ba484e..1cc0d2a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "agentrun" -version = "0.2.5" +version = "0.2.6" description = "The easiest way to run AI or user generated python code safely in a docker container" readme = "README.md" requires-python = ">=3.10"