"""FastAPI application for web interface.""" from src.api.routes import dashboard, chat, tasks, calendar, projects from fastapi import FastAPI, Request, Depends, HTTPException, status from fastapi.responses import HTMLResponse, StreamingResponse from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates from fastapi.security import HTTPBasic, HTTPBasicCredentials import secrets from pathlib import Path from src.config import settings from src.api.agent_instance import agent # Initialize FastAPI app app = FastAPI( title="MyOrg Assistant", description="AI-powered personal assistant for GTD task management", version="1.0.0", ) # Set up templates and static files BASE_DIR = Path(__file__).resolve().parent.parent templates = Jinja2Templates(directory=str(BASE_DIR / "web" / "templates")) app.mount("/static", StaticFiles(directory=str(BASE_DIR / "web" / "static")), name="static") # Security security = HTTPBasic() def verify_credentials(credentials: HTTPBasicCredentials = Depends(security)) -> bool: """Verify HTTP Basic Auth credentials. Args: credentials: HTTP Basic credentials Returns: True if valid Raises: HTTPException: If credentials are invalid """ if not settings.web_password: # No password set, allow access return True correct_password = settings.web_password.encode("utf8") provided_password = credentials.password.encode("utf8") is_correct = secrets.compare_digest(provided_password, correct_password) if not is_correct: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect password", headers={"WWW-Authenticate": "Basic"}, ) return True # Import routes # Include routers app.include_router(dashboard.router, dependencies=[ Depends(verify_credentials)]) app.include_router(chat.router, dependencies=[Depends(verify_credentials)]) app.include_router(tasks.router, dependencies=[Depends(verify_credentials)]) app.include_router(calendar.router, dependencies=[Depends(verify_credentials)]) app.include_router(projects.router, dependencies=[Depends(verify_credentials)]) @app.get("/", response_class=HTMLResponse) async def root(request: Request, _: bool = Depends(verify_credentials)): """Redirect to dashboard.""" from fastapi.responses import RedirectResponse return RedirectResponse(url="/dashboard") @app.get("/health") async def health(): """Health check endpoint.""" return {"status": "healthy", "service": "myorg-assistant"} def run_web() -> None: """Run the web server.""" import uvicorn print("🌐 Starting MyOrg Assistant Web Server...") print( f"📊 Dashboard: http://{settings.web_host}:{settings.web_port}/dashboard") print(f"💬 Chat: http://{settings.web_host}:{settings.web_port}/chat") if settings.web_password: print("🔒 Authentication enabled") else: print("⚠️ Warning: No password set (WEB_PASSWORD not configured)") uvicorn.run( "src.api.app:app", host=settings.web_host, port=settings.web_port, reload=False, )