|
|
""" |
|
|
Stealth Browser Stack - FastAPI on Port 8888 |
|
|
============================================= |
|
|
This handles healthchecks and API tasks. |
|
|
noVNC moved to 6080 to avoid conflict. |
|
|
""" |
|
|
|
|
|
import os |
|
|
import asyncio |
|
|
import logging |
|
|
from datetime import datetime |
|
|
from typing import Dict, Any, Optional |
|
|
|
|
|
from fastapi import FastAPI, HTTPException |
|
|
from fastapi.middleware.cors import CORSMiddleware |
|
|
from pydantic import BaseModel |
|
|
|
|
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') |
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
from agent import BrowserSession, validate_order |
|
|
|
|
|
app = FastAPI(title="Stealth Browser Worker", version="2.5.0") |
|
|
|
|
|
app.add_middleware( |
|
|
CORSMiddleware, |
|
|
allow_origins=["*"], |
|
|
allow_credentials=True, |
|
|
allow_methods=["*"], |
|
|
allow_headers=["*"], |
|
|
) |
|
|
|
|
|
browser_session: Optional[BrowserSession] = None |
|
|
|
|
|
|
|
|
class TaskRequest(BaseModel): |
|
|
task_id: str |
|
|
task_type: str |
|
|
data: Dict[str, Any] |
|
|
|
|
|
|
|
|
class TaskResponse(BaseModel): |
|
|
task_id: str |
|
|
status: str |
|
|
result: Optional[Dict[str, Any]] = None |
|
|
error: Optional[str] = None |
|
|
logs: Optional[list] = None |
|
|
execution_time_ms: int = 0 |
|
|
|
|
|
|
|
|
@app.get("/") |
|
|
async def root(): |
|
|
return { |
|
|
"service": "AI System Bridge", |
|
|
"status": "active", |
|
|
"timestamp": datetime.now().isoformat() |
|
|
} |
|
|
|
|
|
|
|
|
@app.get("/health") |
|
|
async def health(): |
|
|
return { |
|
|
"status": "healthy", |
|
|
"display": os.environ.get("DISPLAY", ":99"), |
|
|
"browser": browser_session is not None and browser_session.is_active |
|
|
} |
|
|
|
|
|
|
|
|
@app.post("/run-task", response_model=TaskResponse) |
|
|
async def run_task(request: TaskRequest): |
|
|
global browser_session |
|
|
start_time = datetime.now() |
|
|
|
|
|
try: |
|
|
if request.task_type in ["validate_order", "validate_email"]: |
|
|
order_data = {**request.data, "task_id": request.task_id} |
|
|
result = await validate_order(order_data, browser_session) |
|
|
execution_time = int((datetime.now() - start_time).total_seconds() * 1000) |
|
|
|
|
|
return TaskResponse( |
|
|
task_id=request.task_id, |
|
|
status="success", |
|
|
result=result, |
|
|
logs=result.get("logs", []), |
|
|
execution_time_ms=execution_time |
|
|
) |
|
|
else: |
|
|
raise HTTPException(status_code=400, detail="Invalid task_type") |
|
|
|
|
|
except Exception as e: |
|
|
return TaskResponse(task_id=request.task_id, status="error", error=str(e)) |
|
|
|
|
|
|
|
|
@app.on_event("startup") |
|
|
async def startup(): |
|
|
global browser_session |
|
|
try: |
|
|
browser_session = await BrowserSession.create() |
|
|
logger.info("✅ Persistent browser session created!") |
|
|
except Exception as e: |
|
|
logger.error(f"⚠️ Browser fail: {e}") |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
import uvicorn |
|
|
|
|
|
uvicorn.run(app, host="0.0.0.0", port=8888) |
|
|
|