from __future__ import annotations from pathlib import Path from fastapi import FastAPI, Request from fastapi.responses import JSONResponse from fastapi.staticfiles import StaticFiles from backend.app.api.errors import AppError from backend.app.api.routes_bookmarks import router as bookmarks_router from backend.app.api.routes_browse import router as browse_router from backend.app.api.routes_copy import router as copy_router from backend.app.api.routes_duplicate import router as duplicate_router from backend.app.api.routes_files import router as files_router from backend.app.api.routes_history import router as history_router from backend.app.api.routes_move import router as move_router from backend.app.api.routes_search import router as search_router from backend.app.api.routes_settings import router as settings_router from backend.app.api.routes_tasks import router as tasks_router from backend.app.dependencies import get_history_repository, get_task_repository from backend.app.logging import configure_logging from backend.app.services.task_recovery_service import reconcile_persisted_incomplete_tasks configure_logging() BASE_DIR = Path(__file__).resolve().parents[3] UI_DIR = Path(__file__).resolve().parents[2] / "html" if not UI_DIR.exists(): raise RuntimeError(f"UI directory does not exist: {UI_DIR}") app = FastAPI(title="WebManager MVP Backend") app.mount("/ui", StaticFiles(directory=str(UI_DIR), html=True), name="ui") app.include_router(browse_router, prefix="/api") app.include_router(files_router, prefix="/api") app.include_router(copy_router, prefix="/api") app.include_router(duplicate_router, prefix="/api") app.include_router(move_router, prefix="/api") app.include_router(search_router, prefix="/api") app.include_router(settings_router, prefix="/api") app.include_router(bookmarks_router, prefix="/api") app.include_router(history_router, prefix="/api") app.include_router(tasks_router, prefix="/api") @app.on_event("startup") async def reconcile_incomplete_tasks_on_startup() -> None: reconcile_persisted_incomplete_tasks( task_repository=get_task_repository(), history_repository=get_history_repository(), ) @app.exception_handler(AppError) async def handle_app_error(_: Request, exc: AppError) -> JSONResponse: return JSONResponse( status_code=exc.status_code, content={ "error": { "code": exc.code, "message": exc.message, "details": exc.details, } }, ) @app.get("/") async def read_root() -> dict[str, str]: return {"status": "ok"}