from __future__ import annotations from contextlib import asynccontextmanager from pathlib import Path from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles from sqlalchemy import text from app import __version__ from app.agents.runtime import get_agent_runtime from app.api.v1.router import api_router from app.core.config import settings from app.core.errors import install_exception_handlers from app.core.logging import setup_logging from app.core.middleware import RequestContextMiddleware from app.db.init_db import init_db from app.db.session import SessionLocal PROJECT_ROOT = Path(__file__).resolve().parents[1] FRONTEND_DIR = PROJECT_ROOT / "frontend" class FrontendStaticFiles(StaticFiles): async def get_response(self, path: str, scope): response = await super().get_response(path, scope) response.headers["Cache-Control"] = "no-store, no-cache, must-revalidate, max-age=0" response.headers["Pragma"] = "no-cache" response.headers["Expires"] = "0" return response @asynccontextmanager async def lifespan(_: FastAPI): setup_logging() init_db() if settings.seed_demo_data: from app.db.seed import seed_demo_data with SessionLocal() as db: seed_demo_data(db) yield app = FastAPI( title=settings.app_name, version=__version__, description=( "基于 FastAPI 与 DeepAgent 的矿山通防业务智能管控平台后端。" "普通业务数据通过 REST API 管理,诊断、评价和知识问答通过 DeepAgent 工作流增强。" ), lifespan=lifespan, docs_url="/docs", redoc_url="/redoc", openapi_url="/openapi.json", ) app.add_middleware( CORSMiddleware, allow_origins=settings.cors_origin_list, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) app.add_middleware(RequestContextMiddleware) install_exception_handlers(app) app.include_router(api_router, prefix=settings.api_v1_prefix) if FRONTEND_DIR.is_dir(): app.mount( "/app", FrontendStaticFiles(directory=FRONTEND_DIR, html=True), name="frontend", ) @app.get("/", tags=["系统"], summary="服务入口") def root() -> dict: return { "name": settings.app_name, "version": __version__, "docs": "/docs", "api": settings.api_v1_prefix, "app": "/app/", } @app.get("/health", tags=["系统"], summary="服务健康检查") def health() -> dict: database_status = "ok" database_error = "" try: with SessionLocal() as db: db.execute(text("SELECT 1")) except Exception as exc: # pragma: no cover - depends on external DB database_status = "error" database_error = f"{type(exc).__name__}: {exc}" return { "status": "ok" if database_status == "ok" else "down", "version": __version__, "environment": settings.app_env, "database": { "dialect": settings.database_dialect, "status": database_status, "error": database_error, }, "agent": get_agent_runtime().describe(), } if __name__ == "__main__": import uvicorn uvicorn.run( "app.main:app", host=settings.host, port=settings.port, reload=settings.debug, )