Spaces:
Paused
Paused
| """Proxy server to OpenHands Cloud API""" | |
| import os | |
| from fastapi import FastAPI, HTTPException | |
| from fastapi.middleware.cors import CORSMiddleware | |
| import httpx | |
| app = FastAPI(title="OpenHands Backend", version="1.0.0") | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| OPENHANDS_API_KEY = os.getenv("OPENHANDS_API_KEY", "") | |
| OPENHANDS_BASE_URL = os.getenv("OPENHANDS_BASE_URL", "https://app.all-hands.dev") | |
| def get_headers(): | |
| return {"Authorization": f"Bearer {OPENHANDS_API_KEY}", "Content-Type": "application/json"} | |
| async def health(): | |
| return {"status": "ok", "backend": "cloud-proxy", "version": "1.0.0"} | |
| async def ready(): | |
| return {"status": "ready", "service": "openhands-cloud-proxy", "api_key_configured": bool(OPENHANDS_API_KEY)} | |
| async def server_info(): | |
| return { | |
| "version": "1.0.0", | |
| "llm_proxy": os.getenv("LLM_PROXY_URL", "https://llm-proxy.app.all-hands.dev"), | |
| "e2b_enabled": bool(os.getenv("E2B_API_KEY")), | |
| "redis_enabled": False, | |
| "supabase_enabled": False, | |
| "openhands_cloud": True, | |
| } | |
| async def list_conversations(): | |
| if not OPENHANDS_API_KEY: | |
| # Return mock data for demo | |
| return {"conversations": [], "mock": True} | |
| async with httpx.AsyncClient(timeout=30.0) as client: | |
| resp = await client.get( | |
| f"{OPENHANDS_BASE_URL}/api/conversations", | |
| headers=get_headers() | |
| ) | |
| resp.raise_for_status() | |
| return resp.json() | |
| async def create_conversation(data: dict): | |
| if not OPENHANDS_API_KEY: | |
| # Return mock for demo | |
| import uuid | |
| return {"conversation_id": str(uuid.uuid4()), "message": "Mock response - configure API key for real agent", "mock": True} | |
| async with httpx.AsyncClient(timeout=60.0) as client: | |
| resp = await client.post( | |
| f"{OPENHANDS_BASE_URL}/api/conversations", | |
| headers=get_headers(), | |
| json=data | |
| ) | |
| resp.raise_for_status() | |
| return resp.json() | |
| async def get_conversation(conv_id: str): | |
| if not OPENHANDS_API_KEY: | |
| return {"id": conv_id, "messages": [], "mock": True} | |
| async with httpx.AsyncClient(timeout=30.0) as client: | |
| resp = await client.get( | |
| f"{OPENHANDS_BASE_URL}/api/conversations/{conv_id}", | |
| headers=get_headers() | |
| ) | |
| resp.raise_for_status() | |
| return resp.json() | |
| async def websocket_events(conv_id: str, websocket): | |
| await websocket.accept() | |
| if not OPENHANDS_API_KEY: | |
| await websocket.send_json({"type": "error", "message": "API key not configured"}) | |
| await websocket.close() | |
| return | |
| # Proxy to OpenHands Cloud WebSocket | |
| async with httpx.AsyncClient(timeout=httpx.Timeout(300.0)) as client: | |
| async with client.stream( | |
| "GET", | |
| f"{OPENHANDS_BASE_URL}/ws/conversations/{conv_id}/events", | |
| headers={"Authorization": f"Bearer {OPENHANDS_API_KEY}"} | |
| ) as resp: | |
| async for line in resp.aiter_lines(): | |
| if line: | |
| await websocket.send_text(line) | |