feat(3c): OpenRouter-Modelle live & selbst-aktualisierend statt erfunden

- Neuer Endpunkt GET /api/admin/openrouter/models (10 Min gecacht) liefert
  die echte Modell-Liste von OpenRouter (live 339 Modelle).
- Konfiguration: openrouter_llm_model/-tts_model nutzen jetzt ein
  <datalist> aus dieser Live-Liste (tippen/auswählen) — die fest
  verdrahteten, teils erfundenen Namen (z.B. gemini-3.1-flash-lite) sind weg.
- Test mit gemocktem httpx. app.js v=48. 220 passed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-06-25 05:01:05 +02:00
commit 2bec4e72db
4 changed files with 75 additions and 3 deletions

View file

@ -215,3 +215,23 @@ def test_admin_can_flag_user_as_admin():
assert r.status_code == 200 and r.json()["is_admin"] is True
users = client.get("/api/admin/users", headers=ADM_HDR).json()
assert next(u for u in users if u["user_id"] == uid)["is_admin"] is True
def test_openrouter_models_endpoint_returns_sorted_ids(monkeypatch):
import app.api.admin as adm
import httpx
adm._OR_MODELS_CACHE.update(ts=0.0, ids=[])
class FakeResp:
def raise_for_status(self):
pass
def json(self):
return {"data": [{"id": "b/model"}, {"id": "a/model"}, {"x": 1}]}
async def fake_get(self, url, headers=None):
return FakeResp()
monkeypatch.setattr(httpx.AsyncClient, "get", fake_get)
r = client.get("/api/admin/openrouter/models", headers=ADM_HDR)
assert r.status_code == 200
assert r.json()["models"] == ["a/model", "b/model"]