llmrouter: Claude Code/Desktop — nackte claude-IDs -> alt/anthropic/<id>[:effort]

- anthropicModus (alt|openrouter), Normalisierung der IDs (Datum, [1m], Punkte),
  Client-Effort aus output_config.effort als Stufe, HEAD /api/hello -> 200
- Auswahl: nicht gemessene Stufe faellt auf die naechste gemessene darunter
  (sonst darueber, sonst Modellzahl) -- Sonnet 5 hat nur max/none
- /models: alt/ nur bei bestimmbarer Klasse; opencode-normalize nimmt
  openrouter/+alt/ genau dann (GLM 5.3 Flash war weggefallen)
- README: Abschnitt Claude Code und Claude Desktop
Verifiziert per claude -p mit claude-sonnet-5, claude-opus-5, claude-haiku-4-5-20251001.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-09-05 16:23:26 +02:00
committed by andreas
co-authored by Claude Fable 5.1
parent 0d971b81dc
commit 91e68d9ea9
4 changed files with 98 additions and 13 deletions
+59 -2
View File
@@ -20,6 +20,7 @@ reicht Durchreichen. Entscheidung Andreas, 2026-09-05.
| `openrouter/<id>[:effort]` | 1:1 an OpenRouter, Effort als `reasoning.effort` |
| `alt/<id>[:effort]` | **günstigste Alternative derselben Klasse** wie `<id>` auf dieser Stufe |
| `role/<name>` | Rolle aus `rollen`, zeigt auf einen der obigen Namen |
| `claude-*` (nackte Anthropic-ID) | Claude Code/Desktop: wird zu `alt/anthropic/<id>[:effort]` (siehe unten) |
| alles andere | Durchreiche an LiteLLM (`fallback`), unverändert mit Client-Key |
**Klasse** (`alt/`): Intelligence-, Coding- und Agentic-Index jeweils mindestens
@@ -45,8 +46,64 @@ Präfix-Muster (`openrouter/*`, `alt/*`, `role/*`); `[]` = alles. Geprüft wird
der angefragte Name, vor der Rollenauflösung.
`/v1/models` zeigt je Key alles Erlaubte: Aliasse, Rollen, alle OpenRouter-
Modelle des Kontos als `openrouter/…` und `alt/…`, jeweils auch mit den bei AA
gemessenen Effort-Stufen, plus die LiteLLM-Liste im Parallelbetrieb.
Modelle des Kontos als `openrouter/…`, als `alt/…` nur die mit bestimmbarer
Klasse (Index bei OpenRouter oder Stufen bei AA), jeweils mit den gemessenen
Effort-Stufen, plus die LiteLLM-Liste im Parallelbetrieb.
## Claude Code und Claude Desktop
Claude Code spricht Anthropics Messages-Format (`/v1/messages`,
`/v1/messages/count_tokens`). Der Router reicht beide Pfade an OpenRouters
Messages-Endpunkt durch, der dasselbe Format für alle Modelle bietet, mit
`x-api-key`, `anthropic-version` und `anthropic-beta` des Clients. Das ist die
einzige Format-Übersetzung, die wir nicht selbst schreiben. Nur für
OpenRouter-Ziele; das lokale Qwen spricht kein Messages-Format und antwortet
mit 400. `HEAD /api/hello`, Claude Codes Start-Ping, bekommt 200.
**Modellnamen.** Claude Code schickt nackte Anthropic-IDs (`claude-sonnet-5`,
`claude-opus-5-20260723`, `claude-haiku-4-5-20251001`, `claude-sonnet-4-5[1m]`).
Der Router normalisiert sie (Datum, `-latest`, `[1m]` weg; Versionsziffern mit
Punkt wie bei OpenRouter) und bildet sie je `anthropicModus` ab:
- `alt` (Standard): `claude-opus-5``alt/anthropic/claude-opus-5` — die Wahl
in Claude bestimmt die **Klasse**, der Router sucht das günstigste Modell dazu.
- `openrouter`: `openrouter/anthropic/claude-opus-5` — 1:1 das echte Modell.
Die Rechte prüfen den abgebildeten Namen; ein Key braucht also `alt/*` bzw.
`openrouter/*`. Eigene Namen gehen weiter per `/model alt/x-ai/grok-4.6:high`
oder `/model 42i/marvin-2609:high`.
**Effort.** Claude Code schickt seine Effort-Einstellung als
`output_config.effort` mit (`/effort` bzw. Settings). Der Router hängt sie als
Stufe an: `claude-opus-5` + high → `alt/anthropic/claude-opus-5:high`. Hat AA
die Stufe für das Referenzmodell nicht gemessen (Sonnet 5 hat nur max und
none), vertritt die nächste gemessene Stufe darunter die Referenz, sonst die
nächste darüber; ohne jede Stufe die Modellzahl. Am Ziel wird die Stufe des
**Ziels** gesetzt, `thinking` und `output_config` des Clients werden verworfen.
**Anschluss.** Die Base-URL muss aus der **Prozessumgebung** kommen; der
`env`-Block einer `settings.json` greift dafür nicht (Claude Code 2.1.220 liest
`ANTHROPIC_BASE_URL` vor den Settings). Der Key kann per `apiKeyHelper` aus
OpenBao kommen (der Router trimmt den Zeilenumbruch):
```bash
ANTHROPIC_BASE_URL=http://llm.lan:4010 claude --model claude-sonnet-5
# settings.json: "apiKeyHelper": "/Users/andreas/.agents/bin/secret get elton litellm key"
```
Für Claude Desktop (GUI erbt keine Shell-Umgebung): `launchctl setenv
ANTHROPIC_BASE_URL http://llm.lan:4010` vor dem App-Start; wirkt dann auf alle
Sessions. Testprojekt mit README: `~/src/lab/llmrouter-claude`.
Verifiziert 2026-09-05: `claude -p --model claude-opus-5``alt/anthropic/claude-opus-5:high`
`openai/gpt-5.6-sol:xhigh`; `claude-sonnet-5``:high` → Rückfall auf max → `z-ai/glm-5.3-flash`;
`claude-haiku-4-5-20251001``inclusionai/ling-3.0-flash`. Kosten kommen auch über den
Messages-Endpunkt von OpenRouter mit.
**opencode** braucht nichts davon: `~/.agents/bin/opencode-normalize` erzeugt den
`llmlan`-Provider aus `/v1/models` des Routers, Stufen als `variants`; die Stufe
steckt im Modellnamen. `openrouter/` und `alt/` nur für die Anbieter in `ANBIETER`
und nur, wo der Router ein `alt/` anbietet (Index bekannt).
## Auflösung und Takt