Files
JARVIS/backend/app/main.py

148 lines
4.1 KiB
Python

from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.exceptions import RequestValidationError
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 - 注册所有模型
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,
settings_router,
folder_router,
skill_router,
log_router,
system_router,
brain_router,
hooks_router,
plugins_router,
marketplace_router,
agent_skills_router,
agent_sessions_router,
terminal_router,
tools_router,
remote_mount_router,
office_router,
)
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
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,
)
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()
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},
)
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()
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)
# 注册路由
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)
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)
app.include_router(scheduler_router)
app.include_router(hooks_router)
app.include_router(plugins_router)
app.include_router(marketplace_router)
app.include_router(agent_skills_router)
app.include_router(agent_sessions_router)
app.include_router(terminal_router)
app.include_router(tools_router)
app.include_router(remote_mount_router)
app.include_router(office_router)
@app.get("/api/health")
async def health():
return {
"status": "ok",
"version": settings.APP_VERSION,
"llm_provider": settings.LLM_PROVIDER,
"scheduler": get_scheduler_status(),
}