Das 64K-Output-Gate war global und trieb auto/mass:fast auf solar-pro4 (0,42 statt 0,27 $/1M), weil ling-3.0-flash mit 32768 Output-Token durchfiel. Gemessen 09.09.: 1.415 Masse-Requests, 1.146 davon unter 100 Completion-Token — das Gate verfehlte dort seinen Zweck. Jetzt kann je Schwelle-Profil minOutput gesetzt werden (Default 65536); auto/mass:fast laeuft mit 32768, max_output unbekannt bleibt abgelehnt. Dazu role/coder -> auto/coding:junior (ACL fuer persona-spark), damit Code-Arbeit nicht ueber role/worker in die Masse faellt; der engineer-Agent der Mac-opencode.json wechselt auf role/coder. Refs #1283
llmrouter
Leichtgewichtiger OpenAI-kompatibler Reverse-Proxy in Bun/TypeScript, der vor
den Upstreams sitzt und llm.lan bedient (seit 2026-09-05, Nachfolger des
LiteLLM-Gateways). Er kennt vier Eingriffe je Anfrage: Client-Key prüfen,
Alias auf ein Modell auflösen, Usage und Kosten aus der Antwort mitlesen, eine
Log-Zeile schreiben. Keine Format-Übersetzung, keine Datenbank, kein Admin-UI
— alle Upstreams sprechen OpenAI-Format.
Seit 2026-09-08 lebt das Projekt hier in spine/llmrouter (vorher
Unterverzeichnis llmrouter/ im Repo 42i/agents).
Dokumentation
- docs/referenz.md — Namensräume, Auflösung, Claude-Code- Anschluss, Keys, Sprechtext-Normalisierung, Log-Wege: die technische Referenz.
- docs/betrieb.md — wo der Router läuft (LXC 185020,
llm.lan), Deploy-Runbook, Störungstabelle, Verlauf.
Schnellstart (Docker)
cp config.json key-acls.json data/
cp .env.example .env # Upstream-Keys eintragen (Quelle: OpenBao)
docker compose up -d
curl -s http://localhost:4010/health
Alle Caches und Einstellungen liegen unter ./data (siehe
data/README.md); das Image selbst enthält nur Code und die
Demo-Konfiguration. Ohne Keys startet der Router trotzdem — /health ist
bedienbar, das Auffrischen der Modelllisten scheitert dann graceful.
Entwicklung
bun install # keine Dependencies, nur für Konvention
bun test # Tests (u. a. Sprechtext-Normalisierung)
bun run start # Router lokal starten
bun run src/resolver.ts --force # Auflösung jetzt fahren, Tabelle zeigen
bun run build # statisches Linux-Binary nach dist/
Für lokale Läufe ohne Last-Probe (spart ~210k Token je Wechsel):
LLMROUTER_LASTTEST=0 bun run src/resolver.ts --force.
Der Router liest config.json aus dem Repo-Verzeichnis, wenn
LLMROUTER_CONFIG nicht gesetzt ist; Logs landen relativ dazu unter log/.
CI
.gitea/workflows/ci.yml nach dem Muster der live-Workflows: bun test und
Build je Push/PR, und jeder Push nach main published
git.42i.org/spine/llmrouter:latest (plus sha-<kurz>-Tag) in die Registry
und verifiziert den Pull per /health. Tags: latest und sha-<kurz>, nur
linux/amd64.