"""FastAPI application entrypoint.""" from __future__ import annotations import asyncio import logging from contextlib import asynccontextmanager from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from sqlalchemy import select from app.api import auth, balance, devices, llm, mcp, rules, tasks, users, vessels from app.config import settings from app.core.security import hash_password from app.database import SessionLocal, init_db from app.models.enums import Role from app.models.user import User from app.services.balance import balance_poller_loop logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) async def _seed_admin() -> None: async with SessionLocal() as db: res = await db.execute(select(User).where(User.email == settings.first_admin_email)) if res.scalar_one_or_none(): return admin = User( email=settings.first_admin_email, full_name="Administrator", hashed_password=hash_password(settings.first_admin_password), role=Role.admin, ) db.add(admin) await db.commit() logger.info("Seeded first admin user: %s", settings.first_admin_email) @asynccontextmanager async def lifespan(app: FastAPI): await init_db() await _seed_admin() poller = asyncio.create_task(balance_poller_loop()) yield poller.cancel() app = FastAPI(title="Agentic OS", version="0.1.0", lifespan=lifespan) app.add_middleware( CORSMiddleware, allow_origins=settings.cors_origin_list, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) for r in (auth.router, users.router, vessels.router, devices.router, tasks.router, mcp.router, balance.router, llm.router, rules.router): app.include_router(r) @app.get("/api/health") async def health(): return {"status": "ok", "version": app.version}