Files
JARVIS/backend/app/main.py

130 lines
3.6 KiB
Python
Raw Normal View History

2026-03-21 10:13:29 +08:00
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.exceptions import RequestValidationError
2026-03-21 10:13:29 +08:00
from fastapi.middleware.cors import CORSMiddleware
from starlette.exceptions import HTTPException as StarletteHTTPException
from app.database import init_db, async_session
import app.models # noqa: F401 - 注册所有模型
2026-03-21 10:13:29 +08:00
from app.routers import (
auth_router,
conversation_router,
document_router,
task_router,
forum_router,
graph_router,
agent_router,
todo_router,
reminder_router,
goal_router,
schedule_center_router,
2026-03-21 10:13:29 +08:00
settings_router,
folder_router,
skill_router,
log_router,
system_router,
brain_router,
2026-03-21 10:13:29 +08:00
)
from app.routers.scheduler import router as scheduler_router
from app.services.scheduler_service import start_scheduler, stop_scheduler, get_scheduler_status
from app.services.admin_bootstrap_service import ensure_admin_user, ensure_builtin_skills
2026-03-21 10:13:29 +08:00
from app.config import settings
from app.logging_utils import (
setup_logging,
request_logging_middleware,
log_http_exception,
log_validation_exception,
log_unhandled_exception,
persist_system_log,
)
2026-03-21 10:13:29 +08:00
import os
INSECURE_SECRET_KEYS = {
'change-me-in-production',
'change-me-to-a-random-secret-key',
'jarvis-secret-key-change-in-production',
}
def validate_startup_security() -> None:
if not settings.DEBUG and settings.SECRET_KEY in INSECURE_SECRET_KEYS:
raise RuntimeError('SECRET_KEY must be changed before running with DEBUG disabled')
async def run_startup() -> None:
validate_startup_security()
2026-03-21 10:13:29 +08:00
await init_db()
async with async_session() as session:
await ensure_admin_user(session, settings)
await ensure_builtin_skills(session)
await persist_system_log(
message="application_started",
source="app",
operation="app.startup",
details={"version": settings.APP_VERSION},
)
2026-03-21 10:13:29 +08:00
start_scheduler()
@asynccontextmanager
async def lifespan(app: FastAPI):
# 启动
setup_logging(settings.DEBUG)
os.makedirs(settings.DATA_DIR, exist_ok=True)
os.makedirs(settings.UPLOAD_DIR, exist_ok=True)
os.makedirs(settings.CHROMA_PERSIST_DIR, exist_ok=True)
await run_startup()
2026-03-21 10:13:29 +08:00
yield
# 关闭
stop_scheduler()
app = FastAPI(
title=settings.APP_NAME,
version=settings.APP_VERSION,
lifespan=lifespan,
)
# CORS
app.add_middleware(
CORSMiddleware,
allow_origins=settings.CORS_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.middleware("http")(request_logging_middleware)
app.add_exception_handler(StarletteHTTPException, log_http_exception)
app.add_exception_handler(RequestValidationError, log_validation_exception)
app.add_exception_handler(Exception, log_unhandled_exception)
2026-03-21 10:13:29 +08:00
# 注册路由
app.include_router(auth_router)
app.include_router(conversation_router)
app.include_router(document_router)
app.include_router(task_router)
app.include_router(forum_router)
app.include_router(graph_router)
app.include_router(agent_router)
app.include_router(todo_router)
app.include_router(reminder_router)
app.include_router(goal_router)
app.include_router(schedule_center_router)
2026-03-21 10:13:29 +08:00
app.include_router(settings_router)
app.include_router(folder_router)
app.include_router(skill_router)
app.include_router(log_router)
app.include_router(system_router)
app.include_router(brain_router)
2026-03-21 10:13:29 +08:00
app.include_router(scheduler_router)
@app.get("/api/health")
async def health():
return {
"status": "ok",
"version": settings.APP_VERSION,
"llm_provider": settings.LLM_PROVIDER,
"scheduler": get_scheduler_status(),
}