cff3f0b1a8
Backend-Services: fit/caps/sources (portiert), discover (live HF + Fit + Caps + ranked recommendation), llama-swap write/register + groups (Ko- Residenz swap:false), LiteLLM-Gateway-Config + gateway-Service (model:auto + Fallbacks). Router: discover/fit/register/groups/routing; health zeigt gateway_reachable. Frontend: Modelle&Routing mit Caps-Chips, Fit-Badges, Discover-Tab (live), Routing-View. Lokal verifiziert: Backend-Smoke (alle Endpunkte) + Frontend-Build + Browser (Shell, Discover, Caps/Fit). Box-Verifikation offen. Docs: README + docs/STATUS.md (Phasen-Tracker + Resume-Guide). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
52 lines
1.6 KiB
Python
52 lines
1.6 KiB
Python
"""
|
|
Mission Control 2.0 — dünner FastAPI-Einstieg.
|
|
|
|
Hängt die Router ein, liefert (in Prod) das gebaute React-Frontend aus und
|
|
setzt eine no-cache-Middleware. Im Dev läuft das Frontend über den Vite-Dev-
|
|
Server (proxyt /api hierher), daher CORS für localhost offen.
|
|
"""
|
|
|
|
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.responses import FileResponse
|
|
from fastapi.staticfiles import StaticFiles
|
|
from starlette.requests import Request
|
|
|
|
from config import FRONTEND_DIST, VERSION
|
|
from routers import health, models, routing
|
|
|
|
app = FastAPI(title="Mission Control 2.0", version=VERSION)
|
|
|
|
# Dev: Vite-Dev-Server (5173) ruft das Backend per /api auf.
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["http://localhost:5173", "http://127.0.0.1:5173"],
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
|
|
@app.middleware("http")
|
|
async def no_cache(request: Request, call_next):
|
|
resp = await call_next(request)
|
|
if request.url.path.startswith("/api"):
|
|
resp.headers["Cache-Control"] = "no-cache"
|
|
return resp
|
|
|
|
|
|
app.include_router(health.router)
|
|
app.include_router(models.router)
|
|
app.include_router(routing.router)
|
|
|
|
|
|
# Prod: gebautes Frontend ausliefern (falls vorhanden). SPA-Fallback auf index.html.
|
|
if FRONTEND_DIST.exists():
|
|
app.mount("/assets", StaticFiles(directory=FRONTEND_DIST / "assets"), name="assets")
|
|
|
|
@app.get("/{full_path:path}")
|
|
def spa(full_path: str):
|
|
index = FRONTEND_DIST / "index.html"
|
|
if index.exists():
|
|
return FileResponse(index)
|
|
return {"detail": "frontend not built"}
|