| """ |
| backend/main.py |
| --------------- |
| FastAPI application entry point for Notiflow. |
| |
| Startup: |
| 1. Loads .env file from project root (python-dotenv) |
| 2. Configures logging |
| 3. Mounts the notification API router |
| 4. Exposes health check endpoint |
| |
| Run: |
| uvicorn backend.main:app --reload |
| |
| The server expects to be started from the project root so that |
| all relative imports (app/, agent/, services/, etc.) resolve correctly. |
| """ |
|
|
| from __future__ import annotations |
|
|
| import logging |
| import sys |
| from pathlib import Path |
|
|
| |
| |
| |
|
|
| try: |
| from dotenv import load_dotenv |
| _env_path = Path(__file__).parent.parent / ".env" |
| load_dotenv(dotenv_path=_env_path, override=False) |
| except ImportError: |
| pass |
|
|
| |
| |
| |
|
|
| _PROJECT_ROOT = str(Path(__file__).parent.parent) |
| if _PROJECT_ROOT not in sys.path: |
| sys.path.insert(0, _PROJECT_ROOT) |
|
|
| |
| |
| |
|
|
| logging.basicConfig( |
| level=logging.INFO, |
| format="%(asctime)s %(levelname)-8s %(name)s β %(message)s", |
| datefmt="%H:%M:%S", |
| ) |
| logger = logging.getLogger(__name__) |
|
|
| |
| |
| |
|
|
| from fastapi import FastAPI |
| from fastapi.middleware.cors import CORSMiddleware |
|
|
| from api.notification_routes import router as notification_router |
|
|
| app = FastAPI( |
| title = "Notiflow API", |
| description = ( |
| "AI operations assistant for small businesses.\n\n" |
| "Converts informal Hinglish business notifications into " |
| "structured operations β powered by Amazon Nova 2 Lite." |
| ), |
| version = "1.0.0", |
| docs_url = "/docs", |
| redoc_url = "/redoc", |
| ) |
|
|
| |
| |
| |
|
|
| app.add_middleware( |
| CORSMiddleware, |
| allow_origins = ["*"], |
| allow_credentials = True, |
| allow_methods = ["*"], |
| allow_headers = ["*"], |
| ) |
|
|
| |
| |
| |
|
|
| app.include_router(notification_router) |
|
|
| |
| |
| |
|
|
| @app.get("/health", tags=["Meta"]) |
| async def health(): |
| """ |
| Basic health check. |
| |
| Returns service status and configuration summary. |
| """ |
| from app.config import DEMO_MODE, BEDROCK_MODEL_ID, GEMINI_API_KEY, EXCEL_SYNC_FILE |
| return { |
| "status": "ok", |
| "demo_mode": DEMO_MODE, |
| "bedrock_model": BEDROCK_MODEL_ID, |
| "gemini_enabled": bool(GEMINI_API_KEY), |
| "excel_file": str(EXCEL_SYNC_FILE), |
| } |
|
|
|
|
| |
| |
| |
|
|
| |
| |
| |
|
|
| from fastapi.staticfiles import StaticFiles |
| from fastapi.responses import FileResponse |
|
|
| _frontend_dist = Path(_PROJECT_ROOT) / "dashboard" / "dist" |
|
|
| if _frontend_dist.is_dir(): |
|
|
| |
| app.mount( |
| "/assets", |
| StaticFiles(directory=str(_frontend_dist / "assets")), |
| name="assets" |
| ) |
|
|
| |
| @app.get("/", include_in_schema=False) |
| async def root(): |
| return FileResponse(_frontend_dist / "index.html") |
|
|
| else: |
| @app.get("/", include_in_schema=False) |
| async def root(): |
| from fastapi.responses import RedirectResponse |
| return RedirectResponse(url="/docs") |
|
|
|
|
| |
| |
| |
|
|
| @app.on_event("startup") |
| async def on_startup(): |
| from app.config import DEMO_MODE, GEMINI_API_KEY, EXCEL_SYNC_FILE |
| logger.info("=" * 55) |
| logger.info(" Notiflow API starting up") |
| logger.info(" Demo mode : %s", DEMO_MODE) |
| logger.info(" Gemini : %s", "enabled" if GEMINI_API_KEY else "disabled (no API key)") |
| logger.info(" Excel file : %s", EXCEL_SYNC_FILE) |
| logger.info("=" * 55) |
|
|
|
|
| @app.on_event("shutdown") |
| async def on_shutdown(): |
| logger.info("Notiflow API shutting down.") |