Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ build
run-venv/
.mypy_cache/
.benchmarks/
site/
site/
uv.lock
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```

Expand All @@ -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

Expand Down Expand Up @@ -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
```

Expand Down Expand Up @@ -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
Expand Down
2 changes: 0 additions & 2 deletions agentrun-api/.env.dev

This file was deleted.

2 changes: 0 additions & 2 deletions agentrun-api/.env.example

This file was deleted.

3 changes: 1 addition & 2 deletions agentrun-api/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 17 additions & 6 deletions agentrun-api/src/api/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -18,7 +34,7 @@ class OutputSchema(BaseModel):
output: str


app = FastAPI()
app = FastAPI(lifespan=lifespan)

# allow all origins
app.add_middleware(
Expand All @@ -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)
Expand Down
7 changes: 3 additions & 4 deletions agentrun/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand Down Expand Up @@ -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="<dynamic>", mode="exec"
)
# Note: Execution step is omitted to only check the code without running it
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -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"
Expand Down