""" 🦊 Foxy Dev Team — Backend API v2.0 FastAPI application with WebSocket support for real-time dashboard. """ import logging from contextlib import asynccontextmanager from fastapi import FastAPI, WebSocket, WebSocketDisconnect from fastapi.middleware.cors import CORSMiddleware from app.config import settings from app.database import init_db from app.routers import projects, agents, logs, workflows, config from app.routers.ws import manager # ─── Logging ─────────────────────────────────────────────────────────────────── logging.basicConfig( level=getattr(logging, settings.LOG_LEVEL.upper(), logging.INFO), format="[%(asctime)s] %(levelname)s %(name)s — %(message)s", datefmt="%Y-%m-%dT%H:%M:%SZ", ) log = logging.getLogger("foxy.main") # ─── Lifespan ────────────────────────────────────────────────────────────────── @asynccontextmanager async def lifespan(app: FastAPI): log.info("🦊 Foxy Dev Team API v2.0 — Starting...") await init_db() log.info("✅ Database initialized") yield log.info("🛑 Foxy Dev Team API — Shutting down") # ─── App ─────────────────────────────────────────────────────────────────────── app = FastAPI( title="🦊 Foxy Dev Team API", description="Backend API for the Foxy Dev Team multi-agent orchestration system", version="2.0.0", lifespan=lifespan, ) # CORS app.add_middleware( CORSMiddleware, allow_origins=settings.cors_origins_list, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # ─── Routers ─────────────────────────────────────────────────────────────────── app.include_router(projects.router) app.include_router(agents.router) app.include_router(logs.router) app.include_router(workflows.router) app.include_router(config.router) # ─── WebSocket ───────────────────────────────────────────────────────────────── @app.websocket("/ws/live") async def websocket_endpoint(websocket: WebSocket): await manager.connect(websocket) try: while True: # Keep connection alive; client-initiated messages can be handled here data = await websocket.receive_text() # Echo ping/pong or handle subscriptions if data == "ping": await websocket.send_text('{"type":"pong"}') except WebSocketDisconnect: await manager.disconnect(websocket) except Exception: await manager.disconnect(websocket) # ─── Health ──────────────────────────────────────────────────────────────────── @app.get("/api/health") async def health(): return {"status": "ok", "version": "2.0.0", "service": "foxy-dev-team"}