from fastapi import FastAPI, HTTPException, Request from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse from pathlib import Path from app.config import settings from app.middleware import RequestContextMiddleware from app.routers import admin, analysis, auth, children, reports, training, videos CONTRACTS_OPENAPI = Path(__file__).resolve().parents[3] / "contracts" / "openapi.yaml" app = FastAPI( title="Kids AI Posture Platform API", version="0.6.0", description=( "儿童 AI 体态管理平台 API · Sprint 5。" "MediaPipe 帧级评分 + PDF 导出 + OSS 生产配置 + H5/小程序对接。" ), ) app.add_middleware(RequestContextMiddleware) _cors_origins = ["*"] if settings.app_debug else settings.cors_origin_list app.add_middleware( CORSMiddleware, allow_origins=_cors_origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) app.include_router(auth.router) app.include_router(children.router) app.include_router(videos.router) app.include_router(analysis.router) app.include_router(reports.router) app.include_router(training.router) app.include_router(admin.router) @app.exception_handler(HTTPException) async def http_exception_handler(request: Request, exc: HTTPException): if isinstance(exc.detail, dict) and "meta" in exc.detail: return JSONResponse(status_code=exc.status_code, content=exc.detail) return JSONResponse(status_code=exc.status_code, content={"detail": exc.detail}) @app.get("/health") def health(): return {"status": "ok", "env": settings.app_env, "stage": "sprint5"} @app.get("/") def root(): return { "name": settings.app_name, "docs": "/docs", "contract": str(CONTRACTS_OPENAPI), "stage": "sprint5-mediapipe-pdf-oss", }