Spaces:
Sleeping
Sleeping
File size: 5,489 Bytes
f871fed |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# Load environment variables
from dotenv import load_dotenv
load_dotenv()
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from loguru import logger
from api.auth import PasswordAuthMiddleware
from api.routers import (
auth,
chat,
config,
context,
embedding,
embedding_rebuild,
episode_profiles,
insights,
knowledge_graph,
models,
monitoring,
notebooks,
notes,
ocr,
podcasts,
quiz,
research,
search,
settings,
source_chat,
sources,
speaker_profiles,
study_plans,
transformations,
diagrams,
)
from api.routers import commands as commands_router
from open_notebook.database.async_migrate import AsyncMigrationManager
# Import commands to register them in the API process
try:
logger.info("Commands imported in API process")
except Exception as e:
logger.error(f"Failed to import commands in API process: {e}")
@asynccontextmanager
async def lifespan(app: FastAPI):
"""
Lifespan event handler for the FastAPI application.
Runs database migrations automatically on startup.
"""
# Startup: Run database migrations
logger.info("Starting API initialization...")
try:
migration_manager = AsyncMigrationManager()
current_version = await migration_manager.get_current_version()
logger.info(f"Current database version: {current_version}")
if await migration_manager.needs_migration():
logger.warning("Database migrations are pending. Running migrations...")
await migration_manager.run_migration_up()
new_version = await migration_manager.get_current_version()
logger.success(f"Migrations completed successfully. Database is now at version {new_version}")
else:
logger.info("Database is already at the latest version. No migrations needed.")
except Exception as e:
logger.error(f"CRITICAL: Database migration failed: {str(e)}")
logger.exception(e)
# Fail fast - don't start the API with an outdated database schema
raise RuntimeError(f"Failed to run database migrations: {str(e)}") from e
logger.success("API initialization completed successfully")
# Yield control to the application
yield
# Shutdown: cleanup if needed
logger.info("API shutdown complete")
app = FastAPI(
title="Open Notebook API",
description="API for Open Notebook - Research Assistant",
version="0.2.2",
lifespan=lifespan,
)
# Add password authentication middleware first
# Exclude /api/auth/status and /api/config from authentication
app.add_middleware(PasswordAuthMiddleware, excluded_paths=["/", "/health", "/docs", "/openapi.json", "/redoc", "/api/auth/status", "/api/config"])
# Add CORS middleware last (so it processes first)
# Allow requests from:
# - localhost development (http://localhost:3000)
# - Hugging Face Space backend (https://baveshraam-open-notebook.hf.space)
# - Any frontend deployment (can be restricted further in production)
app.add_middleware(
CORSMiddleware,
allow_origins=[
"http://localhost:3000",
"http://127.0.0.1:3000",
"https://baveshraam-open-notebook.hf.space",
"*" # Allow all origins - can be restricted later
],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Include routers
app.include_router(auth.router, prefix="/api", tags=["auth"])
app.include_router(config.router, prefix="/api", tags=["config"])
app.include_router(notebooks.router, prefix="/api", tags=["notebooks"])
app.include_router(search.router, prefix="/api", tags=["search"])
app.include_router(models.router, prefix="/api", tags=["models"])
app.include_router(transformations.router, prefix="/api", tags=["transformations"])
app.include_router(notes.router, prefix="/api", tags=["notes"])
app.include_router(embedding.router, prefix="/api", tags=["embedding"])
app.include_router(embedding_rebuild.router, prefix="/api/embeddings", tags=["embeddings"])
app.include_router(settings.router, prefix="/api", tags=["settings"])
app.include_router(context.router, prefix="/api", tags=["context"])
app.include_router(sources.router, prefix="/api", tags=["sources"])
app.include_router(insights.router, prefix="/api", tags=["insights"])
app.include_router(commands_router.router, prefix="/api", tags=["commands"])
app.include_router(podcasts.router, prefix="/api", tags=["podcasts"])
app.include_router(episode_profiles.router, prefix="/api", tags=["episode-profiles"])
app.include_router(speaker_profiles.router, prefix="/api", tags=["speaker-profiles"])
app.include_router(chat.router, prefix="/api", tags=["chat"])
app.include_router(source_chat.router, prefix="/api", tags=["source-chat"])
app.include_router(quiz.router, prefix="/api", tags=["quiz"])
app.include_router(research.router, prefix="/api", tags=["research"])
app.include_router(knowledge_graph.router, prefix="/api", tags=["knowledge-graph"])
app.include_router(monitoring.router, prefix="/api", tags=["monitoring"])
app.include_router(ocr.router, prefix="/api", tags=["ocr"])
app.include_router(study_plans.router, prefix="/api", tags=["study-plans"])
app.include_router(diagrams.router, prefix="/api", tags=["diagrams"])
@app.get("/")
async def root():
return {"message": "Open Notebook API is running"}
@app.get("/health")
async def health():
return {"status": "healthy"}
|