Self-hosted, Docker-based agentic troubleshooting platform: FastAPI backend + LangGraph agent, Next.js UI, tiered LLM routing (local Ollama -> Gemini -> DeepSeek -> OpenRouter), MCP server manager, encrypted device credentials, RBAC, audit log, project-memory + Obsidian integrations, and editable troubleshooting decision rules tuned for the GeneseasX vessel stack. Co-authored-by: Cursor <cursoragent@cursor.com>
66 lines
1.9 KiB
Python
66 lines
1.9 KiB
Python
"""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}
|