"""FlashOps FastAPI 应用。""" from __future__ import annotations import asyncio from contextlib import asynccontextmanager from pathlib import Path from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import RedirectResponse from fastapi.staticfiles import StaticFiles from .api.agents import router as agent_router from .api.routes import router from .config import APP_NAME, APP_TAGLINE, REPO_ROOT, get_settings from .db import init_db, session_scope from .seed import ensure_seed_data from .services.agent_status import run_agent_watchdog, stop_agent_watchdog @asynccontextmanager async def lifespan(_: FastAPI): await init_db() async with session_scope() as session: await ensure_seed_data(session) watchdog = asyncio.create_task(run_agent_watchdog(), name="agent-heartbeat-watchdog") try: yield finally: await stop_agent_watchdog(watchdog) app = FastAPI(title=APP_NAME, description=APP_TAGLINE, version="0.1.0", lifespan=lifespan) app.add_middleware( CORSMiddleware, allow_origins=[origin.strip() for origin in get_settings().cors_origins.split(",")], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) app.include_router(router) app.include_router(agent_router) console_dir = REPO_ROOT.parent / "前端UI八页面完成" if console_dir.exists(): app.mount("/console", StaticFiles(directory=str(console_dir), html=True), name="console") @app.get("/", include_in_schema=False) async def root() -> RedirectResponse: if console_dir.exists(): return RedirectResponse("/console/Dashboard.dc.html") return RedirectResponse("/docs")