"""FastAPI app for Bookly. Hosts /api/chat, /health, and the static chat UI.""" from __future__ import annotations import logging from fastapi import FastAPI, HTTPException from fastapi.responses import RedirectResponse from fastapi.staticfiles import StaticFiles from pydantic import BaseModel, Field import agent logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s %(message)s") logger = logging.getLogger("bookly.server") app = FastAPI(title="Bookly", docs_url=None, redoc_url=None) class ChatRequest(BaseModel): session_id: str = Field(..., min_length=1, max_length=128) message: str = Field(..., min_length=1, max_length=4000) class ChatResponse(BaseModel): session_id: str reply: str @app.get("/health") def health() -> dict: return {"status": "ok"} @app.get("/") def root() -> RedirectResponse: return RedirectResponse(url="/static/index.html") @app.post("/api/chat", response_model=ChatResponse) def chat(request: ChatRequest) -> ChatResponse: try: reply = agent.run_turn(request.session_id, request.message) except Exception: logger.exception("chat_failed session=%s", request.session_id) raise HTTPException(status_code=500, detail="Something went wrong handling that message.") return ChatResponse(session_id=request.session_id, reply=reply) app.mount("/static", StaticFiles(directory="static"), name="static")