from fastapi import FastAPI, Request, HTTPException from fastapi.responses import PlainTextResponse import os import requests # Default model used internally; the client only sends plain text DEFAULT_MODEL = "kwaipilot/kat-coder-pro:free" api_key = os.getenv("OPENROUTER_API_KEY") app = FastAPI() @app.get("/") def health(): if not api_key: return {"status": "no key"} return {"status": "ok"} @app.post("/chat") async def chat(request: Request): # Accept plain text body; fallback to JSON {"text": "..."} body = await request.body() text = (body or b"").decode().strip() if not text: try: data = await request.json() text = str(data.get("text", "")).strip() except Exception: pass if not text: raise HTTPException(status_code=400, detail="Send plain text body or JSON {'text': '...'}") if not api_key: raise HTTPException(status_code=500, detail="OPENROUTER_API_KEY not set") try: r = requests.post( "https://openrouter.ai/api/v1/chat/completions", # OpenRouter chat completions [web:21] headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, json={ "model": DEFAULT_MODEL, "messages": [{"role": "user", "content": text}], }, timeout=60, ) except requests.RequestException as e: raise HTTPException(status_code=502, detail=str(e)) # Try to extract assistant text; if not possible, return the raw body from OpenRouter content = None try: data = r.json() if r.status_code >= 400: return PlainTextResponse(str(data), status_code=r.status_code) content = data["choices"][0]["message"]["content"] except Exception: # Fall back to raw text (may be JSON or error text) return PlainTextResponse(r.text, status_code=r.status_code) return PlainTextResponse(content)