-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathremote_server.py
More file actions
111 lines (89 loc) · 3.18 KB
/
remote_server.py
File metadata and controls
111 lines (89 loc) · 3.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import asyncio
import os
from contextlib import asynccontextmanager
from fastapi import Request
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from fastapi import FastAPI, HTTPException, APIRouter
from pydantic import BaseModel
from asyncio import Task
from starlette.middleware.cors import CORSMiddleware
from remote_server_lib.api.async_process import router as async_process_router, cleanup_old_processes
from remote_server_lib.api.sync_process import router as sync_process_router
from remote_server_lib.api.git_functions import router as git_router
from remote_server_lib.api.str_replace import router as file_operations_router
from loguru import logger
API_VERSION_NUMBER = "0.1"
ALLOWED_HOSTS = os.environ.get("ALLOWED_HOSTS")
DEBUG = os.environ.get("DEBUG")
# Store running processes and their metadata
cleanup_task: Task | None = None
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup: create the cleanup task
global cleanup_task
cleanup_task = asyncio.create_task(cleanup_old_processes())
yield # Run the FastAPI application
# Shutdown: cancel the cleanup task
if cleanup_task:
cleanup_task.cancel()
try:
await cleanup_task
except asyncio.CancelledError:
pass
app = FastAPI(
docs_url="/api/docs/",
redoc_url="/api/redocs/",
version=API_VERSION_NUMBER,
title="AI Agents API",
lifespan=lifespan,
)
allowed_hosts = [] if ALLOWED_HOSTS is None else ALLOWED_HOSTS
allowed_hosts.extend(
[
"http://localhost:3001",
"http://0.0.0.0:3001",
"http://127.0.0.1:3001",
]
)
origins = ["*"] if DEBUG else allowed_hosts
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_origin_regex="https://.*\\.techarge\\.co\\.uk",
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
api_router = APIRouter(responses={404: {"description": "Not found"}})
api_router.include_router(async_process_router)
api_router.include_router(sync_process_router)
api_router.include_router(git_router)
api_router.include_router(file_operations_router)
app.include_router(api_router)
os.chdir(os.environ.get("AIAGENTS_WORKING_DIR", "/data"))
# this is a simple server that provides a rest interface into a docker container to be able to run
# arbitragy commands
# Custom exception handler for validation errors (422)
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
error_details = []
for error in exc.errors():
error_details.append({
"loc": error.get("loc", []),
"msg": error.get("msg", ""),
"type": error.get("type", "")
})
logger.error(f"Failed {request=}")
logger.error(f"Validation Error: {error_details} {exc=}") # Log the exception for debugging
return JSONResponse(
status_code=422,
content={
"detail": "Validation Error",
"errors": error_details,
"body": exc.body # Include the request body for debugging
},
)
@app.get("/health")
async def health_check():
return {"status": "healthy"}