from __future__ import annotations import os from contextlib import asynccontextmanager from pathlib import Path from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles from app.config import DATA_DIR, DB_PATH, STORAGE_DIR, WORKSPACE_ROOT from app.db import Database from app.node_manager import NodeManager from app.routers import apps, instances, nodes, workflows from app.scheduler import WorkflowScheduler from app.seed import seed_demo_workflow, seed_nodes @asynccontextmanager async def lifespan(app: FastAPI): DATA_DIR.mkdir(parents=True, exist_ok=True) STORAGE_DIR.mkdir(parents=True, exist_ok=True) db = Database(DB_PATH) manager = NodeManager(db) manager.start_reaper() if os.getenv("WOV_AUTO_SEED", "1") == "1": seed_nodes(db, WORKSPACE_ROOT) seed_demo_workflow(db) scheduler = WorkflowScheduler(db, manager, STORAGE_DIR) if os.getenv("WOV_SCHEDULER_ENABLED", "1") == "1": scheduler.start() app.state.db = db app.state.node_manager = manager app.state.scheduler = scheduler yield scheduler.stop() manager.shutdown() app = FastAPI(title="WOV API", version="0.1.0", lifespan=lifespan) app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"], ) app.include_router(nodes.router) app.include_router(instances.router) app.include_router(workflows.router) app.include_router(apps.router) @app.get("/health") def health() -> dict: return {"status": "ok", "service": "wov-api"} FRONTEND_DIR = Path(__file__).resolve().parent.parent.parent / "wov-web" app.mount("/", StaticFiles(directory=FRONTEND_DIR, html=True), name="frontend")