avocet/app/api.py
pyr0ball 95afddb772 feat: add nodes.py scaffold with set_config_dir and router mount
- Create app/nodes.py with _CONFIG_DIR testability seam, _load_config,
  _profiles_dir, _profile_path, _load_profile, _get_ollama_url helpers,
  and stub list_nodes endpoint returning [] when no coordinator_url is set
- Mount nodes router at /api/nodes-mgmt in app/api.py
- Add profiles_dir comment to config/label_tool.yaml.example cforch section
- Create tests/test_nodes.py with autouse fixture and two passing tests
2026-05-05 19:35:28 -07:00

66 lines
2.2 KiB
Python

"""Avocet -- FastAPI app factory.
Mounts all domain routers and serves the Vue SPA.
All business logic lives in the domain modules below.
"""
from __future__ import annotations
from pathlib import Path
from fastapi import FastAPI
app = FastAPI(title="Avocet API")
# -- Domain routers --------------------------------------------------------
from app.data.label import router as label_router
app.include_router(label_router, prefix="/api")
from app.data.fetch import router as fetch_router
app.include_router(fetch_router, prefix="/api")
from app.data.corrections import router as corrections_router
app.include_router(corrections_router, prefix="/api/corrections")
# Backward-compat alias -- remove when Vue SPA is updated to /api/corrections/*
app.include_router(corrections_router, prefix="/api/sft")
from app.data.imitate import router as imitate_router
app.include_router(imitate_router, prefix="/api/imitate")
from app.eval.cforch import router as eval_router
app.include_router(eval_router, prefix="/api")
from app.train.train import router as train_router
app.include_router(train_router, prefix="/api/train")
from app.plans_bench import router as plans_bench_router
app.include_router(plans_bench_router, prefix="/api/plans-bench")
# In-memory last-action store (single user, local tool — in-memory is fine)
_last_action: dict | None = None
from app.dashboard import router as dashboard_router
app.include_router(dashboard_router, prefix="/api")
from app.models import router as models_router
app.include_router(models_router, prefix="/api/models")
from app.nodes import router as nodes_router
app.include_router(nodes_router, prefix="/api/nodes-mgmt")
# -- Static SPA -- MUST be last (catches all unmatched paths) ---------------
_ROOT = Path(__file__).parent.parent
_DIST = _ROOT / "web" / "dist"
if _DIST.exists():
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
_NO_CACHE = {"Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache"}
@app.get("/")
def get_spa_root():
return FileResponse(str(_DIST / "index.html"), headers=_NO_CACHE)
app.mount("/", StaticFiles(directory=str(_DIST), html=True), name="spa")