"""K8S 智能诊断平台 - FastAPI 主应用""" import os from datetime import datetime from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles from pydantic import BaseModel from typing import Optional from backend.config import PORT from backend.diagnosis import run_full_diagnosis, build_diagnosis_report, ALL_CHECKS from backend.ai_agent import analyze_with_ai, chat_with_ai app = FastAPI(title="K8S 智能诊断平台", version="1.0.0") app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"], ) # 存储最近诊断结果 (内存) _last_diagnosis: Optional[dict] = None _last_report: str = "" class DiagnoseRequest(BaseModel): namespace: str = "" checks: Optional[list[str]] = None class AnalyzeRequest(BaseModel): question: str = "" class ChatRequest(BaseModel): messages: list[dict] @app.get("/api/health") async def health(): return {"status": "ok", "time": datetime.now().isoformat()} @app.get("/api/checks") async def list_checks(): """列出所有可用诊断项""" return { "checks": [ {"name": name, "title": fn.__doc__ or name} for name, fn in ALL_CHECKS.items() ] } @app.post("/api/diagnose") async def diagnose(req: DiagnoseRequest): """执行一键诊断""" global _last_diagnosis, _last_report _last_diagnosis = await run_full_diagnosis(namespace=req.namespace, checks=req.checks) _last_report = build_diagnosis_report(_last_diagnosis) return _last_diagnosis @app.get("/api/diagnosis/latest") async def get_latest(): """获取最近一次诊断结果""" if _last_diagnosis is None: raise HTTPException(status_code=404, detail="暂无诊断记录,请先执行诊断") return _last_diagnosis @app.post("/api/analyze") async def analyze(req: AnalyzeRequest): """AI 分析诊断结果""" global _last_diagnosis, _last_report if _last_diagnosis is None: _last_diagnosis = await run_full_diagnosis() _last_report = build_diagnosis_report(_last_diagnosis) result = await analyze_with_ai(_last_report, question=req.question) return result @app.post("/api/chat") async def chat(req: ChatRequest): """AI 多轮对话 (基于诊断上下文追问)""" result = await chat_with_ai(req.messages, context=_last_report) return result @app.get("/api/report") async def get_report(): """获取诊断报告文本""" if not _last_report: raise HTTPException(status_code=404, detail="暂无诊断报告") return {"report": _last_report} # 静态文件服务 (前端) static_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "frontend", "dist") if os.path.isdir(static_dir): app.mount("/", StaticFiles(directory=static_dir, html=True), name="static") if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=PORT)