""" MC2-Gateway — der /v1-Datenpfad als EIGENER Prozess (UMBAU v3, P1). Befund der Live-Inspektion 15.07.2026: Jeder LLM-Aufruf der Box (Lucys Haupt-Hirn, Nacht-Crons, Worker-Delegation, Vision, Decomposer/Specifier/Curator) lief durch den Steuerpult-Prozess auf :9001 — den am häufigsten neu gestarteten Dienst des Stacks. Dieser Einstieg hebt denselben Gateway-Router (routers/gateway_proxy.py) UNVERÄNDERT in einen bewusst winzigen, langweiligen Prozess: Unit mc2-gateway.service, Loopback :9010, Restart=always. Das Steuerpult darf beliebig neu starten — die Wirbelsäule steht. Bewusst NICHT hier: weitere Router, Hintergrund-Loops, CORS, Frontend-Auslieferung. LAN-Clients (IDE-Lane) erreichen /v1 weiter über MC2 :9001, das roh hierher durchreicht (routers/gateway_forward.py, MC_V1_UPSTREAM). """ import logging import os from contextlib import asynccontextmanager from typing import AsyncGenerator import httpx from fastapi import FastAPI, Request from config import LLAMA_SWAP_URL, VERSION from routers import gateway_proxy logging.basicConfig( level=os.environ.get("MC_LOG_LEVEL", "INFO").upper(), format="%(asctime)s %(levelname)-7s %(name)s: %(message)s", ) log = logging.getLogger(__name__) @asynccontextmanager async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]: # Gleiche Client-Parameter wie zuvor in app.py: Keep-Alive/Pooling statt neuer # Client pro Anfrage (Sockets/TIME_WAIT unter parallelen Agent-Strömen). app.state.gw_client = httpx.AsyncClient( timeout=httpx.Timeout(connect=10.0, read=None, write=None, pool=10.0), limits=httpx.Limits(max_keepalive_connections=100, max_connections=200), ) log.info("mc2-gateway bereit (Engine: %s)", LLAMA_SWAP_URL) try: yield finally: await app.state.gw_client.aclose() app = FastAPI(title="MC2 Gateway", version=VERSION, lifespan=lifespan) app.include_router(gateway_proxy.router) @app.get("/gw/health") async def health(request: Request): """Eigener Health-Pfad (nicht /api/health — das gehört dem Steuerpult): beweist Prozess UND Engine-Erreichbarkeit, für deploy.sh/stack-postcheck.sh.""" engine = False try: r = await request.app.state.gw_client.get(f"{LLAMA_SWAP_URL}/v1/models", timeout=5.0) engine = r.status_code == 200 except httpx.HTTPError: pass return {"status": "ok", "service": "mc2-gateway", "version": VERSION, "engine_reachable": engine}