fix: 500er bei register/update_model/install-recipe, Download & favicon

- write_config schreibt atomar (tmp + os.replace) -> llama-swap (-watch-config)
  sieht nie eine halb geschriebene config.yaml; PermissionError wird in eine
  klare Klartext-Meldung uebersetzt (Hinweis auf chown)
- generischer Exception-Handler: unerwartete Fehler kommen als lesbare JSON-
  Meldung im UI an statt als nackter 500 (Anfaenger-Diagnose)
- Download: nutzt die `hf`-CLI aus dem venv (Dienst-PATH kennt venv/bin nicht)
  + HF_HUB_DISABLE_XET=1 statt HF_XET_HIGH_PERFORMANCE (XET-Haenger bei ~6 MB)
- huggingface_hub als Dependency ergaenzt (liefert `hf`)
- favicon.ico: themed SVG (Link-Tag + Route) -> kein 404 mehr

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-06-21 17:53:49 +02:00
parent 3a4de152b0
commit f07a8440b2
5 changed files with 51 additions and 6 deletions
+21 -1
View File
@@ -17,7 +17,7 @@ Neue Bereiche kommen als routers/<bereich>.py + static/js/panels/<bereich>.js da
from pathlib import Path
from fastapi import FastAPI, HTTPException
from fastapi.responses import FileResponse, JSONResponse
from fastapi.responses import FileResponse, JSONResponse, Response
from fastapi.staticfiles import StaticFiles
from routers import jobs, maintenance, models, system, cookbook, integration, news
@@ -52,9 +52,29 @@ def index():
return FileResponse(_STATIC / "index.html")
_FAVICON = (
b"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'>"
b"<rect width='32' height='32' rx='7' fill='#0f1720'/>"
b"<circle cx='16' cy='16' r='8' fill='none' stroke='#2dd4bf' stroke-width='3'/>"
b"<circle cx='16' cy='16' r='2.5' fill='#2dd4bf'/></svg>"
)
@app.get("/favicon.ico")
def favicon():
return Response(content=_FAVICON, media_type="image/svg+xml")
app.mount("/static", StaticFiles(directory=_STATIC), name="static")
@app.exception_handler(HTTPException)
def _http_exc(_req, exc: HTTPException):
return JSONResponse(status_code=exc.status_code, content={"error": exc.detail})
@app.exception_handler(Exception)
def _any_exc(_req, exc: Exception):
"""Unerwartete Fehler als lesbare Meldung ans (vertrauenswuerdige LAN-)UI geben,
statt nur einen generischen 500 ohne Hinweis. Erleichtert Anfaengern die Diagnose."""
return JSONResponse(status_code=500, content={"error": str(exc) or exc.__class__.__name__})