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)