feat: Modell pro Chat waehlen — und sehen, welches gerade laeuft

Nach einem Sicherheitsfilter-Treffer fuhr ein Projekt still auf dem
Ausweich-Modell weiter, und nirgends war zu sehen, auf welchem. Zurueck ging
nur ueber "Liste leeren" im Filter-Panel, und das gleich fuer alle Chats.

Jetzt drei Ebenen (aria-brain/context_model.py):
  Einstellung (brainModel) < pro Chat < Ausweich (Sicherheitsfilter)

- Pro Chat: Hauptchat und jedes Projekt koennen ein eigenes Modell haben, in
  /shared/config/context_models.json. Bewusst kein Feld im Projekt-Manifest —
  der Hauptchat ist kein Projekt und waere sonst aussen vor.
- "↩ zurueck" pro Chat: loescht nur die Filter-Vermerke DIESES Chats. Blockt
  der Filter erneut, weicht das Brain eben wieder aus.
- Angezeigt wird, was wirklich laeuft: chat() gibt das Modell aus modelUsage
  der CLI zurueck (aufgeloeste Version statt Alias) samt Grund; Brain → Bridge
  → chat_backup + Live-Payload → App und Diagnostic. Als Grundeinstellung
  zaehlt das Modell, mit dem das Brain laeuft, nicht der Dateiwert — so faellt
  ein ausstehender Neustart nach brainModel-Aenderung auf.

Diagnostic: 🧠-Auswahl neben "+ Projekt" fuer den fokussierten Chat, Modell im
Untertitel jeder Kontext-Karte, Modell statt "Claude" am Bubble-Badge (orange
mit ↪ bei Ausweich).

App: hinter der Quell-Anzeige (Einstellungen, Default aus — Kopfzeile bleibt
fuer Mama unveraendert) ein Modell-Chip in der Kopfzeile; Tippen oeffnet die
Auswahl fuer diesen Chat inkl. "Zurueck". Laeuft ueber den vorhandenen
brain_request-Kanal, also keine neuen RVS-Typen.

Tests: 47/47 (12 neue fuer die Aufloesungsreihenfolge gegen agent.chat()),
tsc ohne Fehler.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 13:39:30 +02:00
co-authored by Claude Opus 5.5
parent d221c1a320
commit 6d978d72b3
9 changed files with 596 additions and 19 deletions
+1
View File
@@ -545,6 +545,7 @@ Erreichbar unter `http://<VM-IP>:3001`. Teilt das Netzwerk mit der Bridge.
- `GET /api/agent-stream?lines=N` — gleiche Mechanik fuer den persistierten Live-Stream (Tool-Calls + Inputs + Outputs).
- **OAuth-Callback-Pipeline**: Caddy davor terminiert TLS via Let's Encrypt, RVS hat einen HTTP-Listener auf demselben Port wie der WebSocket. Provider (Spotify/Dropbox/Discord/...) redirecten den User an `https://{RVS_HOST}/oauth/callback/{service}` → RVS broadcastet als `oauth_callback`-WS-Message → aria-bridge forwarded an Brain → Brain matched `state`, tauscht `code` gegen Token, persistiert in `/shared/config/oauth_tokens.json`. Token-Refresh laeuft automatisch. ARIA hat fuenf Brain-Tools: **`oauth_register_provider`** (legt URLs eines neuen Providers wie Dropbox/Discord/Notion/... on-demand in `oauth_apps.json` an — Credentials bleiben Stefans Job), `oauth_authorize`, `oauth_get_token`, **`oauth_call`**, `oauth_revoke`
- **Sprachmodell**: die Auswahlliste kommt aus **Anthropics eigenem Modell-Katalog** (`downloads.claude.ai/model-catalog/v1/catalog.json`, Surface `cc`) — dieselbe Quelle, aus der sich Claude Code bedient. Oeffentlich, ohne API-Key. Oben die **Tier-Aliase** (opus/sonnet/haiku/fable), die automatisch der neuesten Version folgen; darunter die **exakten Versionen**, aeltere als solche markiert. „↻ Aktualisieren" holt frisch, sonst 6h-Cache mit Datei-Fallback fuer offline. **🔬 Testen** schickt eine echte Mini-Anfrage durch den ganzen Weg und zeigt, welches Modell tatsaechlich geantwortet hat (aus `modelUsage.canonicalModel` der CLI — das Modell selbst zu fragen waere unzuverlaessig). Vier Ergebnisse: Tier aufgeloest (gruen), exakte Version (gruen), **nicht erkannt** (gelb — der Proxy haette still `opus` eingesetzt), ungueltig (rot, mit CLI-Begruendung)
- **Modell pro Chat**: jeder Chat (Hauptchat und jedes Projekt) kann sein eigenes Modell haben, ohne die Einstellung fuer alle umzustellen. Reihenfolge: **Einstellung** (`brainModel`) < **pro Chat** (`/shared/config/context_models.json`, gesetzt per 🧠-Auswahl neben „+ Projekt") < **Ausweich** (Sicherheitsfilter, s.u.). Angezeigt wird immer, was der **naechste Turn wirklich nutzt**: in den Kontext-Karten, in der Auswahl (orange „↪ läuft auf …" plus **„↩ zurück zu …"**, wenn gerade ausgewichen wird) und an jeder ARIA-Bubble — dort das Modell, das tatsaechlich geantwortet hat (aus `modelUsage` der CLI, also die aufgeloeste Version statt des Alias). Als Grundeinstellung zaehlt das Modell, mit dem das Brain **laeuft**, nicht der Dateiwert — ein ausstehender Neustart nach Aenderung von `brainModel` faellt so auf. In der **App** dasselbe hinter der Quell-Anzeige (Einstellungen, Default aus): Modell-Chip in der Kopfzeile, Tippen oeffnet die Auswahl fuer diesen Chat, die Bubbles zeigen das Modell statt nur „Claude"
- **Sicherheitsfilter-Rettung** (🛡 Sicherheitsfilter): Anthropics Filter („*... safeguards flagged this message*", `Details: [cyber]`) trifft gern genau die Themen, um die es hier geht — Ports, Tunnel, Zugangsdaten. Die Meldung kommt **nicht** als HTTP-Fehler: die CLI liefert ein normales Ergebnis mit `is_error:true` und dem Fehlertext im `content`, also genau dort, wo sonst ARIAs Antwort steht. Ungeprueft landete dieser Text als ARIAs Wort im Verlauf — und weil der Verlauf bei jedem Turn mitgeht, kippte danach **jede** weitere Frage im selben Projekt an derselben Stelle. Jetzt zwei Stufen: **(1)** derselbe Turn wird automatisch mit dem **Ausweich-Modell** neu gefragt (einstellbar unter Sprachmodell, Default: anderes Tier — der Filter haengt am Modell, Anthropic raet selbst zu „change your model"); der ausloesende Turn wird vermerkt, damit die naechsten Turns nicht erst wieder gegen die Wand laufen, und der Vermerk verfaellt von selbst, sobald der Turn aus dem Rolling Window gerollt ist. **(2)** Blockt auch das Ausweich-Modell, liegt es am Verlauf: der ausloesende Turn fliegt aus dem Prompt-Fenster (**Quarantaene**) — nicht geloescht, er bleibt in `conversation.jsonl`, steht mit Text im Panel und ist per „↩ Zurueckholen" wieder drin. Der rohe API-Fehlertext wird nie persistiert; ARIA sagt in eigenen Worten, was passiert ist. Das Panel zeigt pro Vorfall Projekt, Modell, Klassifikator-Code und ob die Blockade **noch wirkt** (= Turn liegt noch im Fenster). Zustand in `/data/safeguard.json`, Code in [`aria-brain/safeguard.py`](aria-brain/safeguard.py); gilt auch fuer das Memory-Destillat, das denselben Verlauf nochmal durchschickt. **Altlasten** — Fehlertexte, die vor diesem Fix schon in `conversation.jsonl` stehen und dort weiter vergiften — raeumt [`aria-brain/clean_poisoned_turns.py`](aria-brain/clean_poisoned_turns.py) einmalig weg (Dry-Run per Default, `--apply` schreibt mit Backup; findet jetzt beide Giftsorten und in Projekten genauso wie im Hauptchat)
- **Datenschutz-Schalter**: die drei Kanaele, ueber die Claude Code zusaetzlich sendet (`DISABLE_ERROR_REPORTING`, `DISABLE_TELEMETRY`, `DISABLE_FEEDBACK_COMMAND`) pruefen und setzen. Geschrieben wird nach `~/.claude/settings.json` unter `env` — die CLI liest das bei jedem Aufruf, **kein Neustart noetig**. Geprueft wird, was wirklich im Prozess ankommt: eine per docker-compose gesetzte Variable gewinnt und wird als gesperrt angezeigt, statt einen wirkungslosen Haken anzubieten. **Nicht** dasselbe wie die Trainings-Einstellung — die steht im Anthropic-Konto (Link daneben)
- **Warnung bei veralteten Proxy-Patches**: der Proxy kopiert `proxy-patches/` beim **Start**. Wer nach einem `git pull` nur neu startet — oder neu startet, bevor der Pull durch ist — laeuft still mit der alten Fassung. Nichts deutet darauf hin. Die Einstellungen vergleichen jetzt die Zeitstempel und zeigen den fertigen Befehl (`--force-recreate proxy`)