"""FastAPI server: oficial VannaFastAPIServer + estáticos do web component.""" from __future__ import annotations import os from fastapi.responses import FileResponse, HTMLResponse from fastapi.staticfiles import StaticFiles from vanna.servers.fastapi import VannaFastAPIServer import csv_cleanup from agent import RequestContextUserResolver, build_agent from chat_filter import FilteringChatHandler from events_sink import EventSink def _build_app(): agent = build_agent(user_resolver=RequestContextUserResolver()) cors_origins = [ o.strip() for o in os.environ.get("VANNA_CORS_ORIGINS", "*").split(",") if o.strip() ] or ["*"] server = VannaFastAPIServer( agent, config={ "cors": { "allow_origins": cors_origins, "allow_methods": ["*"], "allow_headers": ["*"], "allow_credentials": True, }, "api_base_url": "", }, ) server.chat_handler = FilteringChatHandler(agent, event_sink=EventSink()) fastapi_app = server.create_app() here = os.path.dirname(os.path.abspath(__file__)) dist = os.path.join(here, "vanna", "frontends", "webcomponent", "dist") if os.path.isdir(dist): fastapi_app.mount("/static", StaticFiles(directory=dist), name="static") @fastapi_app.get("/vanna-theme.css") async def vanna_theme(): path = os.path.join(here, "static", "vanna-theme.css") return FileResponse(path, media_type="text/css") @fastapi_app.get("/vanna-embed-bootstrap.js") async def vanna_embed_bootstrap(): path = os.path.join(here, "static", "vanna-embed-bootstrap.js") return FileResponse(path, media_type="application/javascript") @fastapi_app.get("/clubpetro-logo.png") async def clubpetro_logo(): path = os.path.join(here, "static", "clubpetro-logo.png") return FileResponse(path, media_type="image/png") @fastapi_app.get("/clubpetro-logo.svg") async def clubpetro_logo_svg(): path = os.path.join(here, "static", "clubpetro-logo.svg") return FileResponse(path, media_type="image/svg+xml") @fastapi_app.get("/dashboard-bg.png") async def dashboard_bg(): path = os.path.join(here, "static", "dashboard-bg.png") return FileResponse(path, media_type="image/png") @fastapi_app.get("/embed-demo.html", response_class=HTMLResponse) async def embed_demo(): path = os.path.join(here, "static", "embed-demo.html") with open(path, "r", encoding="utf-8") as f: html = f.read() return ( html .replace("__PROGRAM_ID__", os.environ.get("RLS_PROGRAM_ID", "")) .replace("__STORE_ID__", os.environ.get("RLS_STORE_ID", "")) .replace("__USER_ID__", os.environ.get("RLS_USER_ID", "")) ) return fastapi_app app = _build_app() @app.on_event("startup") async def _csv_cleanup_startup() -> None: await csv_cleanup.startup() @app.on_event("shutdown") async def _csv_cleanup_shutdown() -> None: await csv_cleanup.shutdown()