Spaces:
Paused
Paused
File size: 3,409 Bytes
97250c4 47c142f 97250c4 47c142f 97250c4 47c142f 97250c4 47c142f 97250c4 47c142f 97250c4 47c142f 97250c4 47c142f 97250c4 47c142f 97250c4 47c142f 97250c4 | 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 | """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"}
@app.get("/health")
async def health():
return {"status": "ok", "backend": "cloud-proxy", "version": "1.0.0"}
@app.get("/ready")
async def ready():
return {"status": "ready", "service": "openhands-cloud-proxy", "api_key_configured": bool(OPENHANDS_API_KEY)}
@app.get("/server_info")
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,
}
@app.get("/api/conversations")
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()
@app.post("/api/conversations")
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()
@app.get("/api/conversations/{conv_id}")
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()
@app.websocket("/ws/conversations/{conv_id}/events")
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)
|