Skip to content

Latest commit

 

History

History
220 lines (171 loc) · 8.9 KB

File metadata and controls

220 lines (171 loc) · 8.9 KB

LLM-Proxy — Entwicklungs-Stand (Checkpoint 2026-05-06)

Diese Datei dokumentiert den aktuellen Zustand des Projekts nach dem OpenRouter-Integration & Admin-UI-Refactoring. Sie dient als Ausgangspunkt für spätere Optimierungen.

Git-Stand

  • Branch: master
  • Commit: 91a470e feat(providers): dynamic OpenRouter model sync (200+ models)
  • Vorhergehend:
    • a41ef14 refactor(providers): complete overhaul of provider configuration UI
    • d8b4156 fix(admin): sync provider toggle to provider_configs table
    • 8dc7637 fix(health): nil pointer panic when ENCRYPTION_KEY is not set
    • 225ebfc fix(admin-ui): mount Svelte 5 with mount() instead of new App()

Deploy-Status (Server dockerfarm 164.92.79.92)

Container Status Port Image
llm-proxy-backend ✅ Healthy 127.0.0.1:8080 latest
llm-proxy-admin-ui ✅ Healthy 127.0.0.1:3005 latest
llm-proxy-postgres ✅ Healthy 127.0.0.1:5433 postgres:14
llm-proxy-redis ✅ Healthy 127.0.0.1:6380 redis:7
llm-proxy-grafana ✅ Healthy 127.0.0.1:3002 grafana
llm-proxy-prometheus ✅ Healthy 127.0.0.1:9092 prometheus

Reverse Proxy: Caddy auf scrubgate.tech → 127.0.0.1:3005 (Admin UI) / 127.0.0.1:8080 (API)


Was wurde implementiert

1. OpenRouter als vollwertiger Provider

  • Neuer Client: internal/infrastructure/providers/openrouter/client.go

    • OpenAI-kompatible API (/chat/completions)
    • OpenRouter-Header: HTTP-Referer, X-Title
    • SSE-Streaming (OpenRouter liefert schon OpenAI-Format)
    • ListModels(), Health(), GetAPIKey() (maskiert)
    • CreateMessage(), CreateMessageStream()
  • ProviderManager (manager.go):

    • openrouterStates []*clientState für weighted load balancing
    • GetOpenRouterClient() mit weighted round-robin + RPM-Limiting
    • DetermineProvider() routet openrouter:-Prefix, unknown models → OpenRouter
    • GetProviderKeyCounts() gibt Config-Key-Anzahl zurück
    • ReloadKeys() supportet Hot-Reload für OpenRouter
  • ChatHandler (chat_handler.go):

    • handleOpenRouterCompletion() — Non-Streaming (klont Request vor Mutation)
    • handleOpenRouterStreamingCompletion() — SSE-Piping direkt durch
    • Prefix-Strip: entfernt openrouter: vor dem Senden
  • ModelsHandler (models_handler.go):

    • Lädt jetzt auch OpenRouter-Modelle
    • getProviderFromModelName() erkennt openrouter: und abacus: Präfixe
  • ModelSyncService (model_sync_service.go):

    • 16 populäre OpenRouter-Modelle hardgecoded (Claude, GPT, Llama, DeepSeek, Grok, Gemini)
    • DB-Sync erfolgreich: 26 neue Models eingelesen

2. Dynamic OpenRouter Model Sync (370+ Modelle)

  • SyncProviderModels fragt jetzt https://openrouter.ai/api/v1/models ab
  • Built-in providers (Claude, OpenAI) nutzen weiterhin hardcoded Liste
  • Ergebnis: 386 OpenRouter-Modelle in der Datenbank (statt 16)

3. Provider Configuration UI (komplett überarbeitet)

  • Karte pro Provider: Icon, Name, Typ-Label, Build-in-Badge
  • Zwei Status-Pills:
    • 🟢 Enabled / 🔴 Disabled (ob der Provider aktiv ist)
    • 🟢 Healthy / 🔴 Unhealthy / ⚪ Unknown (Health-Check-Status)
  • 4 Statistiken: Models | DB Keys | Config Keys | Routing
  • Built-in Badge für Claude/OpenAI → Disable-Button ist deaktiviert
  • Saubere Modals: Test, Models, Keys
  • Getrennte Key-Anzeige: db_keys (verschlüsselt in DB) vs config_keys (aus config.yaml)

4. Bugfixes

  • nil pointer panic in Health Checker (wenn ENCRYPTION_KEY nicht gesetzt)
  • Provider Toggle synchronisiert jetzt beide Tabellen (provider_configs + provider_settings)
  • Svelte 5 Mount — new App() → mount(App, ...) (hat weißen Screen verursacht)
  • Admin API Key Trim in stores.js (Whitespace-Probleme)
  • API Key Masking in Logs
  • unchecked json.Encode in Admin/Filter Handlern
  • OAuth Refresh Scope Escalation
  • ReDoS Detection für Content Filter Regex
  • ResponseWriter.Unwrap() für Middleware-Kompatibilität

Bekannte Probleme / TODOs für spätere Optimierung

A. Provider-Health-Status

  • Problem: Health Check schreibt nach provider_configs.health_status, aber GetProviderDetails liest von dort. Der Health Checker crasht aber manchmal bei nil providerAPIKeyRepo.
  • File: internal/application/health/provider_health_checker.go
  • Fix-Status: ✅ nil-check hinzugefügt, aber UpdateHealthStatus braucht robustes Error Handling

B. Model-Sync Deduplizierung

  • Problem: Wenn man "Sync Models" mehrfach klickt, werden OpenRouter-Modelle nicht mehrfach eingefügt (UNIQUE Constraint auf (provider_id, model_id)), aber skipped_count könnte genauer sein.
  • File: internal/interfaces/api/provider_management_handler.go

C. Caddy / Browser Caching

  • Problem: Docker Build schreibt neue JS-Hashes, aber Browsercache/Caddy hält alte Referenzen.
  • Workaround: --no-cache Build + docker rm -f statt up --force-recreate
  • Lösung: Cache-busting Header in Caddy oder nginx config hinzufügen

D. Admin-UI Build-Prozess

  • Problem: npm ci im Docker-Build verwendet manchmal alte node_modules Layer
  • Lösung: Multi-stage Build mit npm ci --prefer-offline=false
  • File: admin-ui/Dockerfile

E. Content Filter Regex #14

  • Problem: \b[0-9]{5}\b(?=\s+[A-ZÄÖÜ]) verwendet Lookahead (?=, wird von Go Regex nicht unterstützt
  • File: internal/application/filtering/service.go
  • Status: Warning im Log, Filter wird übersprungen

F. Grafana/Prometheus

  • Status: Laufen, aber nicht für die Produktion optimiert
  • User hat gesagt: "Vergiss Grafana und Prometheus"

G. OpenRouter Config Key Import

  • Problem: config_keys zeigt nur Keys aus config.yaml, nicht die dynamisch in der DB gespeicherten
  • Erweiterung: Import-Button sollte auch config.yaml Keys in DB migrieren können

H. Dashboard 502 Error (gelöst)

  • Ursache: Health Checker Panic → Container restart → laufende Requests broken
  • Fix: ENCRYPTION_KEY gesetzt + nil-check im Health Checker

Server-Konfiguration (Wichtig!)

.env auf Server (/opt/llm-proxy/.env)

ADMIN_API_KEYS=admin_dev_key_12345678901234567890123456789012
ENCRYPTION_KEY=39f03e83...        # 32-byte AES-256 hex key
DB_PASSWORD=G5pwa5ZluH7EZdygm2zYH7pr4d6ovfbp
GRAFANA_ADMIN_USER=admin
GRAFANA_ADMIN_PASSWORD=admin

Database Schema (wichtige Tabellen)

Tabelle Zweck
provider_configs Build-time Konfiguration (name, type, enabled, health_status)
provider_settings Runtime Overrides (enabled, config) — wird von Toggle geschrieben
provider_models Model-Katalog (387 OpenRouter, 15 Claude, 56 OpenAI, 10 Abacus)
provider_api_keys Verschlüsselte API Keys (AES-256-GCM)
request_logs Request-History
filter_matches Content Filter Matches

Migration-Status

  • schema_migrations.version = 1 (nur Init-Migration)
  • provider_settings war falsch geschema (Key-Vault statt Runtime-Settings) → wurde manuell migriert
  • provider_configs hat jetzt korrekte Spalten

Nächste Schritte (wenn Fortsetzung)

  1. Provider Health Checker robust machen

    • Nil-checks für alle Repositories
    • UpdateHealthStatus sollte bei fehlenden Keys nicht crashen
  2. Model-Sync Vollständigkeit

    • Claude/OpenAI Model-Sync von APIs abholen statt hardcoden?
    • OpenRouter Sync via Cronjob/Timer statt manuell?
  3. Cache-Busting fixen

    • Caddy Config: Cache-Control: no-cache für index.html
    • Oder: index.html mit ?v=<hash> referenzieren
  4. Provider API Key Import aus Config

    • Button "Import Config Keys to DB" → migriert config.yaml Keys
  5. Admin-UI Verbesserungen

    • Responsive Design für Mobile
    • Dark Mode
    • Echte Health-Status-Rechtfertigung in Echtzeit
  6. Monitoring

    • Prometheus Metrics exportieren für LLM-Usage
    • Grafana Dashboard für Provider-Health
  7. Content Filter Regex #14

    • Go-kompatible Alternative ohne Lookahead (?=
  8. Tests

    • Go Tests für OpenRouter Client
    • Integration Tests für Provider Routing
    • Frontend Tests mit Playwright

Letzte erfolgreiche Kommandos

# Build Backend
docker build -t llm-proxy-backend:latest -f deployments/docker/Dockerfile .
docker save llm-proxy-backend:latest | ssh dockerfarm "docker load"

# Build Admin UI (CLEAN)
cd admin-ui
rm -rf node_modules dist package-lock.json
npm install
npm run build
docker build --no-cache -t llm-proxy-admin-ui:latest .
docker save llm-proxy-admin-ui:latest | ssh dockerfarm "docker load"

# Deploy
ssh dockerfarm "cd /opt/llm-proxy/deployments/docker && docker compose -f docker-compose.prod.yml up -d"

# Sync Models (OpenRouter dynamisch)
curl -X POST -H 'X-Admin-API-Key: admin_dev_key_...' \
  https://scrubgate.tech/admin/providers/sync-models

# Verify
curl -H 'X-Admin-API-Key: admin_dev_key_...' \
  https://scrubgate.tech/admin/providers

Letzte Aktualisierung: 2026-05-06