# ARIA — Changelog Alle Änderungen am Projekt. Format: [Keep a Changelog](https://keepachangelog.com/de/1.1.0/) > **Hinweis:** Dieser Changelog hatte eine große Lücke — er endete bei `0.0.0.5` > (2026-03), das Projekt lief aber bis `0.2.0.2` (2026-07) weiter (u. a. OAuth, > Voice-Streaming, Speaker-ID, Datei-Manager). Ab dem Projekte-/Multi-Threading- > Epos (2026-07) wird wieder gepflegt; die dazwischenliegenden Versionen > `0.0.0.6`–`0.1.9.6` sind nicht rückwirkend nacherfasst. --- ## [0.2.1.9] — 2026-07-17 — Kompakt ↔ Cockpit: Umschalter für den Kachel-Desktop ### Hinzugefügt - **Ansichts-Umschalter im Header** („⧉ Kompakt" / „⧉ Cockpit"): Die App startet in **Kompakt** — der klassische Vollbild-Chat, **exakt wie vor dem Umbau** (Default, Mama-tauglich). Ein Tap auf den Button oben rechts schaltet auf **Cockpit** — den zoom-/verschiebbaren Kachel-Desktop. Persistiert über Neustart (`aria_view_mode`). - **Warum:** Nach dem 0.2.1.8-Deploy sah die App „unverändert" aus — korrekt, denn im normalen Chat gibt es nur eine Kachel (= Vollbild-Chat). Der Umschalter macht den Cockpit-Modus jetzt **explizit sichtbar/steuerbar**, statt nur bei Code-Projekten aufzutauchen. - Im Cockpit ist die **Übersicht jetzt immer erreichbar** (auch im Hauptchat mit nur einer Kachel): „⤢ Übersicht"-Button (unten rechts, weg von den Chat-Kopf-Icons), 2-Finger-Pinch/Pan, Hardware-Back. --- ## [0.2.1.8] — 2026-07-17 — Desktop-Workspace: zoombarer Canvas, Live-Code-Editor, QEMU/VNC ### Hinzugefügt **Zoom-/verschiebbarer Workspace-Canvas (App)** - Die App ist jetzt eine desktop-artige Arbeitsfläche: rausgezoomt sieht man eine **Landkarte aus Kacheln** (Chat, Editor, Desktop, Vorschau), die man mit **2 Fingern zoomt und verschiebt**. Tippt man eine Kachel an, zoomt sie voll auf und wird **echt bedienbar** („Übersicht + Fokus"). „⤢ Übersicht" bzw. der Hardware-Back führen zurück zur Landkarte. - Technisch: `react-native-gesture-handler` + `react-native-reanimated` (60 fps auf dem UI-Thread). Zwei Ebenen — eine skalierte Thumbnail-Welt und eine **Identity-Content-Ebene** (Scale 1), in der die schweren Inhalte (ChatScreen + WebViews) immer gemountet sind und nur die fokussierte sichtbar ist. Dadurch bleiben Touch-Koordinaten/Keyboard korrekt und nichts remountet beim Fokuswechsel. **Reiner Chat verhält sich exakt wie bisher** (eine Kachel, dauerhaft fokussiert). **Live-Code-Editor für Code-Projekte (App + Bridge + Proxy)** - Wird ein Projekt zum Code-Projekt (ARIA ruft `set_project_kind('code')`), erscheinen Editor- und Desktop-Kachel. Der Editor (WebView, selbstenthaltener Highlight-Editor, offline) **zeigt live, was ARIA schreibt** — und Stefan kann selbst editieren; Änderungen gehen zurück an ARIA. - Fluss: ARIAs `Write`/`Edit` unter `/shared/projects//` werden im Proxy abgefangen und als `code_file` über die Bridge/RVS an die App gespiegelt; Stefans Edits kommen als `code_file_edit` pfad-sicher zurück ins selbe Verzeichnis. **QEMU für alle Architekturen + Live-Desktop per VNC (Host + Bridge + App)** - ARIA kann jetzt VMs für **jede Architektur** bauen/testen (x86, ARM, MIPS, PPC, RISC-V, SPARC) — Host-Helper `aria-vm` (`create/boot/screenshot/list/stop`), installiert via `host-provisioning/qemu-setup.sh`. KVM für x86-Gäste, sonst TCG. Beispiel: ein Win-3.11-System bauen und in QEMU testen. - Der **VNC-Live-Desktop wird durch den RVS-Server getunnelt**: die Bridge brückt rohes RFB-TCP (QEMU `127.0.0.1:5901`) ↔ RVS (`vnc_data`/`vnc_input`, Base64-in-JSON), der noVNC-Client läuft in der App-WebView (`window.WebSocket`-Shim). Stefan bedient die VM **live mit Maus/Tastatur** in der Desktop-Kachel — NAT-sicher, kein offener Port am Host, kein websockify/noVNC auf dem Host nötig. **Kleineres** - Pro-Projekt-Layout: die zuletzt fokussierte Kachel wird pro Projekt gemerkt (`aria_workspace_layout`). - Projekt-Modell bekommt `kind` ('chat'|'code'); Seed-Regel lehrt ARIA den Code-Projekt-Workflow (Arbeitsverzeichnis `/shared/projects//`, `aria-vm`, VNC landet automatisch in der App). ### Deploy `git pull && docker compose up -d --build brain bridge proxy` · RVS-Stack `up -d --build` · Host: `bash host-provisioning/qemu-setup.sh` (einmalig, als root) · APK neu bauen (nach `npm install` einmalig `npm start --reset-cache` + `gradlew clean`, wegen der neuen nativen Module). --- ## [0.2.1.5] — 2026-07-12 — Pro-Projekt-Queue mit Rückfrage-Loop ### Hinzugefügt **Nachrichten-Queue pro Projekt (App + Diagnostic)** - Eine zweite Nachricht, während ARIA am aktuellen Task arbeitet, wird jetzt **angestellt** statt den laufenden Task abzubrechen (vorher: Barge-In-Cancel). Sie läuft der Reihe nach, **pro Projekt unabhängig** (paralleles Arbeiten in mehreren Projekten bleibt). Wartende Nachrichten zeigen als ⏸-Bubble — tippen entfernt sie aus der Warteschlange. - **Rückfrage-Loop:** Stellt ARIA eine echte, blockierende Rückfrage, **pausiert** die Queue und deine nächste Eingabe beantwortet sie — bis eine finale Antwort kommt, dann läuft der nächste Queue-Eintrag (gleiches Muster). Banner „❓ ARIA fragt nach — deine Eingabe beantwortet das". Der Stop-Button bricht den aktuellen Task ab und schaltet zum nächsten. - ARIA signalisiert eine Rückfrage über einen **unsichtbaren `[[AWAIT]]`-Marker** — wie speak/converse deklariert das Modell den Zustand selbst (kein „endet-mit-?"-Raten). Brain strippt ihn, gibt `awaiting_reply` durch `chat()` → `ChatOut` → Bridge-Chat-Payload. Local (tool-los) und Fast-Path markieren nie. **Pro-Projekt-Textfeld-Entwürfe (App + Diagnostic)** - Der Feldinhalt bleibt beim Projektwechsel erhalten: in Projekt X tippen, zu Y wechseln (leeres Feld), zurück zu X → dein Entwurf steht wieder da. In Storage persistiert. **TTS-Abspiel-Queue (App)** - Zwei fast gleichzeitig fertige Antworten sprechen jetzt garantiert **nacheinander** statt sich gegenseitig abzuschneiden. Vorher war das Timing-Glück (`PcmStreamPlayer.start()` ruft `stopInternal()` = flush/release, hätte die laufende gecuttet). Jetzt: „spielt hörbar" gilt bis zum echten `PcmPlaybackFinished` (nicht nur bis Stream-Ende); eine neue hörbare Antwort, die währenddessen ankommt, wird gepuffert und danach nachgespielt (Kette für 3, 4, …). Harter Stop/Barge-In/Mund-Button verwirft die Queue. ### Geändert - **Voice bricht nicht mehr ab:** eine neue Sprachnachricht während ARIA arbeitet stoppt nur akustisch das TTS (sauberes Mikro) und wird über den Brain-Projekt-Lock serialisiert, statt den laufenden Task abzubrechen (passend zu „immer anstellen + Stop-Button"). Text-Senden erkennt Brain-busy als Fallback, damit auch nach einem voice-gestarteten Turn korrekt angestellt wird. Grenze: eine per Sprache gestartete Aufgabe erscheint nicht als löschbare ⏸-Bubble (Aufnahme wird live gestreamt, nicht app-seitig gepuffert). --- ## [0.2.1.4] — 2026-07-12 — Lokales LLM: der ehrliche Rückbau ### Geändert **Lokales LLM wieder tool-los (B1a) — ein 8B ist ein schlechter Tool-Caller** - B1b hatte dem lokalen Modell Werkzeuge (`run_*`/`web_search`) gegeben — die gemeinsame Wurzel von **zwei** Problemen: (1) ein 8B erfindet mit Werkzeug in der Hand lieber eine plausible Antwort („der Song ist X") statt es zu rufen → Halluzination; (2) das erzwang per-Skill-Guards (skaliert nicht). Local ist jetzt wieder **tool-los** = reines Reden; alles mit Grundwahrheit (Fakt/Live-Zustand/Gedächtnis/Aktion) gehört an Claude oder den deterministischen Fast-Path. Kein Skill-Ergebnis mehr fälschbar - **Keine Input-Wortliste im Router:** eine kurz eingeführte `_LIVE_HINTS`-Blacklist (Wetter/Musik/… → Claude) wieder entfernt — aus offenem Freitext die Absicht per Wortliste zu raten ist nie vollständig, jeder Miss = ein Halo (nur von per-Skill auf per-Wort verschoben). Generisch = das Modell entscheidet **selbst** (`<>`); ein stärkeres lokales Modell übernimmt die Selbst-Erkennung später, bis dahin ist local per Einstellung abschaltbar (aus, nicht raus) - Expliziter Nutzer-Wunsch „nimm Claude/Clodi" wird im Router respektiert (geht nie lokal) ### Behoben - **Info-Halluzination:** local nannte manchmal aktuellen Song/Restzeit/Skip-Titel ohne `run_spotify` zu rufen (mal echt, mal frei erfunden — „Midnight City von M83" nie aufgerufen). Neuer Output-Guard `_claims_live_media_state` eskaliert behauptete Live-Auskünfte ohne echten Skill-Call an Claude; Local-Prompt zusätzlich gehärtet (nie Titel/Zeit/Gerät ohne Tool-Ergebnis; bei „OK: next" keinen Titel erfinden) - **Leeres `` machte TTS stumm:** Claude hängt reflexartig manchmal ein leeres Voice-Tag an → `clean_text_for_tts` nahm den leeren Inhalt → gar keine Sprachausgabe (Playlist „Fliegen" gesprochen, „Prodigy" stumm — reiner Claude-Output-Zufall, nicht Skill/Playlist-Name). Leeres/whitespace-Tag wird jetzt ignoriert, der normale Anzeigetext gelesen - **Datei-Anhang erschien erst nach Seitenwechsel:** die Live-`chat`-Payload trug keine `files` (Anhänge kamen nur als separates `file_from_aria`-Event) → an der Nachricht tauchte die Datei erst nach Reload aus `chat_backup` auf. Bridge schickt die `files` jetzt in der chat-Payload, App hängt sie live an die Text-Bubble (wie der Reload-Pfad) und entfernt die redundante Solo-Bubble - **TDZ-Zeitbombe (App):** `sendTextMessage` stand vor seinen Dependencies (`interruptAriaIfBusy`, `sendPendingAttachments`) im deps-Array — Temporal Dead Zone; lief nur dank Babels `const`→`var`-Hebung, ein strengerer Bundler hätte beim Mount weißgescreent. Deklaration hinter die Deps verschoben - **QRScanner tsc-clean:** toter Prop `colorForScannerFrame` (existiert in `react-native-camera-kit` v13 nicht) entfernt; die fehlerhaften Lib-Typen (optionale Props als required markiert) lokal + dokumentiert umgangen → **Projekt komplett tsc-clean (0 Fehler)** **Spotify-Skill — von ARIA live im Gespräch weiter geschärft** - Skip (`next`/`previous`) sagt jetzt den **echten** neuen Titel an (holt den Track nach dem Skip via API) statt local einen erfinden zu lassen - `playlist_play`/`search_and_play`/`play` nennen das **tatsächliche** Wiedergabegerät (aus `GET /v1/me/player`, kein Raten — verhinderte den Fehler, dass Claude ein falsch geratenes Gerät auch noch ansteuerte) und lesen konsistent vor; saubere „Sprach-Grammatik": Ansagen sprechen, Steuerbefehle (play/pause/transfer/volume) schweigen - `yt-dlp-download`-Skill um einen MP3-Modus erweitert — ARIA hat das fehlende Werkzeug **selbst gebaut**, als eine deutsche Titelmelodie nicht auf Spotify lag (Web-Suche → YouTube-Download → MP3 in den Chat, in <1 min) --- ## [0.2.1.3] — 2026-07-11 ### Hinzugefügt - **`skill_get`-Tool:** ARIA liest den echten Quellcode + Manifest + Readme eines Skills, **bevor** sie ihn ändert — kein Blind-Rewrite mehr (vorher wurde ein guter Skill durch eine schlechtere Neufassung ersetzt, weil das referenzierte `skill_get` gar nicht existierte) ### Behoben - **`converse` folgt dem Skill (Fast-Path):** auch ein Fast-Path-Befehl kann einen Skill auslösen, nach dem noch etwas zu sagen ist — `converse` kommt jetzt aus Manifest/Skill-Output statt hart auf `False` - **Sprachnachricht-Bubble verschwand nach manuellem Stop:** bei „ohne Ohr" aufgenommener Sprachnachricht + Stop entfernte ein leeres stream-end-Endpoint die schon gefüllte Bubble; jetzt wird nur noch der unaufgelöste Platzhalter entfernt --- ## [0.2.1.2] — 2026-07-11 — Standort-Intelligenz + Skill steuert seine Ausgabe ### Hinzugefügt **GPS → Ortsname im Standort-Präfix (keyless, keine Tokens)** - Reverse-Geocoding der Koordinaten in der Bridge (Nominatim zoom=18: Straße+Hausnr, PLZ+Ort, Bundesland; Straßen-Ref + Autobahn-km via Overpass) — damit das lokale Modell nicht „Berlin" für Oldenburg rät; Ortsname wird **vor** dem Präfix-Bau awaited (rechtzeitig für die erste Nachricht) - Fahrtrichtung als Himmelsrichtung **+ exakte Peilung in Grad** (Haversine/Bearing aus aufeinanderfolgenden Fixes, `MIN_MOVE_M`-Schwelle gegen Zittern) **Skill steuert seine Ausgabe selbst — `speak` + `converse` pro Aufruf** - Ein Skill entscheidet per JSON-Output `{speak, converse}` pro Operation, ob vorgelesen wird und ob danach 30 s weitergelauscht wird (Manifest-Default, Output überschreibt) — z. B. „was läuft" vorlesen aber kein Dialog, „nächstes Lied" stumm. In der Skill-Bauanleitung **mit dem WARUM** dokumentiert, damit die KI die Flags beim Bauen versteht (kein Hardcode im Brain) ### Behoben / Geändert - **Generischer Skill-Prompt (kein Hardcode):** der Router beschreibt `run_*`-Skills generisch (weiß nicht mehr, welche „schwer" sind); ein Stop im 30-s-Lauschen beendet dieses jetzt wirklich (kein zweiter Gong / erneutes Öffnen) - **Anti-Halluzination:** behauptet local eine Steuerbefehl-Quittung („Spotify: …", „Playlist abspielen") ohne das Tool wirklich zu rufen → Eskalation an Claude statt erfundene Bestätigung durchzulassen --- ## [0.2.1.1] — 2026-07-11 ### Hinzugefügt - **Skill entscheidet selbst, ob vorgelesen wird (`manifest.speak`):** Grundlage der späteren `speak`/`converse`-Architektur — der `speak`-Flag greift sowohl im lokalen als auch im Claude-Pfad, statt am fragilen leeren ``-Hack zu hängen --- ## [0.2.0.6] — 2026-07-11 ### Hinzugefügt **Diagnostic + App — Projekte verstecken** - Neues `hidden`-Flag pro Projekt (bleibt voll nutzbar, nur aus Listen ausgeblendet — unabhängig von `status`/`archived`); `PATCH /projects/{id} {hidden}` - Diagnostic: 👁-Auge pro Projekt-Bubble (🙈 verstecken / 👁 dauerhaft sichtbar), Header-Toggle „Versteckte anzeigen (N)" blendet sie temporär gedimmt + „versteckt"-Badge ein — zum Ansehen/Auswählen ohne permanentes Enttarnen - App (`ProjectsBrowser`): versteckte standardmäßig ausgeblendet (Mama sieht sie nicht), Auge pro Zeile + Toggle spiegeln das Diagnostic-Verhalten; geteilter `hidden`-Status übers Brain **Diagnostic — Token-Ersparnis durch lokales LLM** - `metrics.jsonl` trägt jetzt `source` (claude | local | fast-path); lokale Calls nutzen echte `usage`-Tokens vom Adapter, Fast-Path = 0 Prompt-Tokens (`by_source`-Aggregation, rückwärts-kompatibel) - Neue Card „Lokales LLM & Claude-Ersparnis": pro Fenster (1h/5h/24h/30d) gesparte Claude-Calls (local + fast-path) + lokale Token-Last (eigene HW, kein Quota) **Spotify-Skill — von ARIA selbst geschärft** - Geräte-Transfer startet die Wiedergabe direkt mit (`play=true`) statt nur zu übertragen, inkl. Verifikation (`is_playing`-Check + expliziter Play-Fallback), Fuzzy-Gerätenamen und sauberen Exit-Codes; neue semantische Actions `play_on_device`/`search_and_play`/`playlist_play`/`queue_add` ### Behoben - **Spotify-Resume (App):** nach einem Voice-Befehl blieb Spotify auf dem Handy pausiert. Statt des auf manchen Geräten (OnePlus) flakigen Audio-Focus-Nudge jetzt ein echter `KEYCODE_MEDIA_PLAY`-KeyEvent an die aktive MediaSession — gegated: nur wenn vor dem Dialog Musik lief (`isMusicActive`). Deterministisch, geräteunabhängig - **TTS-Zahlen:** freistehende Ganzzahlen werden jetzt tag-unabhängig ausgeschrieben („23°C" → „dreiundzwanzig Grad Celsius", „100%" → „einhundert Prozent"). Regression, seit das lokale LLM (bewusst ohne ``-Tag) leichte Turns übernahm; neuer vollständiger Zahl→Wort-Konverter (0…999999) am Ende von `clean_text_for_tts`, lange Ziffernfolgen (IDs) bleiben Ziffern - **„ARIA denkt" hängt:** Indikator + Abbrechen blieben stehen, obwohl der Turn laut Diagnostic fertig war. Die App räumt den kontext-scoped Indikator jetzt beim Eintreffen der Antwort selbst; die Bridge sendet zusätzlich ein `idle` für die Request-`projectId`, falls der Turn umgeroutet wurde (thinking ging mit Request-, idle mit Turn-`projectId`) - **Lokale Tool-Fehler:** Action-Skills, die bei Exit 0 einen Fehlschlag nur im stdout-Text melden (Spotify: „Fehler beim Übertragen", „Gerät nicht gefunden"), eskalieren jetzt generisch an Claude statt vom lokalen LLM vorgelesen zu werden (Info-Tools wie web_search ausgenommen) --- ## [0.2.0.4 – 0.2.0.5] — 2026-07-11 — Plan B: Lokales LLM („Gemini-Feeling") Ein kleines, schnelles Modell (**Qwen3 8B** via llama.cpp/llama-swap auf der Gamebox-GPU) übernimmt einfache Turns in **<1 s**; alles Schwere/Technische/Werkzeug-artige reicht ein Router automatisch an **Claude** weiter. Ziel: schnelle Antworten ohne die Claude-Max-Subscription aufzugeben. ### Hinzugefügt **Lokales LLM (Brain + Bridge + Adapter)** - Router (B1a): Heuristik + `<>`-Selbstabbruch entscheidet pro Turn lokal vs. Claude; schlanker System-Prompt mit demselben `IDENTITY_ANCHOR` wie Claude (Rolle hält), nur letzte 8 Turns (Speed) - Lokale Tool-Fast-Lane (B1b): kuratierte Tools — `web_search` (self-hosted **SearXNG**, local-only), `memory_search`, `trigger_timer`, Spotify; Eskalation bei Tool-Fehler statt Raten - Consumer-Kette gespiegelt zu FLUX: Brain → Bridge `/internal/local-llm` → RVS → `llm-adapter` → llama.cpp; `enable_thinking:false` (Qwen wickelte sonst die ganze Antwort in ``) - **B0.5:** llama-swap (Hot-Swap der Modelle on-demand) + Modellauswahl-Dropdown + Live-Lade-Status (loading/ready + Download-Hinweis) in Diagnostic - **SearXNG** als 6. Container auf der ARIA-VM (keyless Meta-Suche, JSON-API) **Quell-Badge (local / claude / fast-path)** - Diagnostic: immer an den ARIA-Bubbles - App: optionaler Schalter in den Einstellungen, pro Gerät gemerkt, default aus („ich will's, meine Mama nicht") **TTS — System-Flag `speak` (ja/nein) pro Antwort** - Die Quelle entscheidet übers Vorlesen (Fast-Path/Steuerbefehl = stumm, ARIA-Antwort = vorlesen), robust statt des fragilen leeren ``-Hacks der beim Skill-Rebuild verloren ging ### Behoben / Geändert - **Identität (Hauptchat):** Proxy nutzt jetzt `--system-prompt` (voller Replace) statt `--append-system-prompt` — die Claude-Code-Basis-Identität leakt nicht mehr in den Hauptchat (ARIA antwortete dort als „Claude Code" bzw. deutete die Persona als Injection). Dazu `IDENTITY_SEED` (synthetischer Grounding-Turn) + Gift-Wächter (Identity-Breaks werden nie in die History persistiert, Retry+Fallback) + Cleanup-Script gegen bereits vergiftete Turns - **Datenschutz (kritisch):** harte Diskretions-Regel im `IDENTITY_ANCHOR` — ARIA kennt intime/private Details, gibt sie aber **NIE ungefragt** preis (nicht in Vorstellungen, „was weißt du über mich", Zusammenfassungen, Triggern); nur auf konkrete Nachfrage, knapp. Bereits ausgeplauderte Turns bereinigt. Lokales Tier eskaliert Personen-/Beziehungs-/Gedächtnisfragen an Claude (kennt das Gedächtnis + antwortet diskret) - **Lokale Antwort nicht in ``** wickeln (Qwen imitierte den Tag aus dem Kontext → Anzeige war leer); **generische** Tool-Fehler-Eskalation statt per-Skill-Router-Hardcode (Router muss nicht wissen, welche Skills „schwer" sind) --- ## [0.2.0.3] — 2026-07-10 ### Hinzugefügt **Proxy — ARIA-Persona über echten System-Prompt-Kanal** - Persona + Tool-Use-Format gehen jetzt über `--append-system-prompt` der Claude-CLI statt als ``-getaggter User-Content im Prompt (`openai-to-cli.js`: Prompt = nur Verlauf, `systemPrompt` separat; neue `sed`-Zeile schleust `--append-system-prompt`,`options.systemPrompt` ins `buildArgs`-Array von `manager.js`) **Multi-Threading — echte Parallelität in der App** - `agent_activity`-Events tragen jetzt die `projectId` (Brain → Proxy `aria_project_id` → Bridge → App); der „ARIA denkt"-Indikator zeigt nur noch den **fokussierten** Kontext statt global zu flackern (`agentActivityByCtx`-Map) - Kontext-scoped Cancel: neuer Proxy-Endpoint `/cancel {projectId}` killt nur die Subprozesse *eines* Kontexts (`/cancel-all` bleibt fürs NOT-AUS); Bridge-soft-Cancel + App-Abbrechen tragen die fokussierte `projectId` **Diagnostic — Datei-Zuordnung** - Projekt-Dropdown pro Datei im Datei-Manager (nutzt `/api/files-set-project`) — auch alt-hochgeladene Dateien nachträglich einem Projekt zuweisen ### Behoben - **Identität:** fester `IDENTITY_ANCHOR` ganz oben im System-Prompt — ARIA verliert in (Pentest-)Projekten nicht mehr die Rolle bzw. deutet ihre eigene Aufgabe nicht mehr als Prompt-Injection - **Barge-In kontext-scoped:** eine Frage im Hauptchat blockiert/killt nicht mehr die parallele Arbeit in einem Projekt (Busy-Status kontextgenau aus `queueStatus` statt global) --- ## [0.1.9.7 – 0.2.0.2] — 2026-07-02 … 2026-07-10 — Projekte & Multi-Threading Der große Epos: Themen-Bündel („Projekte") im Hauptchat, echt nebenläufig verarbeitet. ### Hinzugefügt **Projekte (Brain + App + Diagnostic)** - Named Themen-Bündel, im Hauptchat verankert, per Sprache adressierbar („steige in Projekt X ein", „für Frankreich: …"), CRUD via Meta-Tools + UI - App: Focus-One-View + Drawer + Queue-Status-Dots + „← Hauptchat"-Button - Diagnostic: Kontext-Strip + Focus-Filter + Queue-Polling - Dateien pro Projekt getaggt (Manifest `file_projects.json`, Filter im Datei-Manager) **Multi-Threading (Brain)** - Per-Request `project_id` statt globalem `active_project`; per-Projekt-`asyncio.Lock` = Queue-Verhalten pro Kontext, verschiedene Kontexte laufen parallel - Queue-Aware-Prompting (spätere Nachricht kann laufenden Task als überholt markieren) ohne Extra-LLM-Call **Voice-Router (Bridge)** - 30s-Sticky-Kontext, Prefix-Adressierung, Meta-Command-Interception („zurück zum Hauptchat" ohne Brain-Call), Voice folgt App-Focus **Migration** - Alt-getaggte Projekt-Nachrichten (in `conversation.jsonl`, aber ohne Tag im `chat_backup.jsonl`) werden nachträglich einsortiert — idempotent, nicht-destruktiv, reihenfolge-erhaltend ### Behoben - **Leere Projekte:** Drawer resettete den App-Focus beim Öffnen auf `status.active` (im Multi-Threading = null); Diagnostic warf `project_id` beim `chat_history`-Reload weg (server.js + Renderer); untagged ARIA-Bubbles/Backup-Writes aus dem toten Gateway-Watch-Pfad - **Voice → falscher Kontext:** Registry-Race (`stt_stream_end` poppte die Focus-`projectId` vor dem finalen `stt_endpoint`); App übernimmt jetzt die autoritative Server-`projectId` der STT-Bubble - **STT-Endpointing:** akustische Stille als robustes Signal statt rein semantischer Stagnation (nicht mehr „hört nach zwei Worten auf" / „merkt Ende nicht") - **Anhänge:** Bild/Datei + Frage landen im gewählten Projekt statt im Hauptchat (projectId durch die ganze Anhang-Kette) - **Bild-Bubbles im Diagnostic:** ARIA-Datei-Bubbles tragen `project_id`, werden nicht mehr fälschlich vom Focus-Filter ausgeblendet --- ## [0.0.0.5] — 2026-03-13 ### Hinzugefügt **Diagnostic — Pipeline-Tab** - Neuer "Pipeline"-Tab im Log-Bereich — zeigt den kompletten Nachrichtenfluss wenn eine Chat-Nachricht über die Diagnostic-UI gesendet wird - Tracking aller Schritte: Senden → Gateway ACK → Streaming Deltas → Finale Antwort (oder Fehler) - Zeitmessung: Jeder Schritt zeigt Elapsed-Time seit Pipeline-Start - Farbcodierung: Blau (Schritte), Grün (Erfolg), Rot (Fehler) - 60s Timeout — markiert Pipeline als fehlgeschlagen wenn keine Antwort kommt - Funktioniert für Gateway-direkt und RVS-Nachrichten ### Behoben **OpenClaw Gateway Event-Format — ARIA antwortet jetzt** - OpenClaw sendet `event: "agent"` (Streaming-Deltas in `payload.data.delta`) und `event: "chat"` mit `payload.state: "delta"|"final"|"error"` — **nicht** `chat:delta`/`chat:final`/`chat:error` wie angenommen - Antworttext steckt in `payload.message.content[0].text` (Array von Content-Blöcken, nicht flacher String) — `text.slice is not a function` Fehler behoben - `ackReactionScope` von `"group-mentions"` auf `"all"` geändert — Agent reagierte nur auf @mentions, nicht auf direkte Nachrichten - Diagnostic Server und Bridge auf neues Event-Format umgestellt - Legacy-Event-Namen (`chat:delta`, `chat:final`, `chat:error`) als Fallback beibehalten ### Geändert **OpenClaw Config — Custom Provider Format** - `openclaw.json` nutzt `models.providers` (Object, nicht Array) mit `api: "openai-completions"` - Model-Einträge brauchen sowohl `id` als auch `name` Feld - `aria-setup.sh` schreibt korrekte Config mit Heredoc-Pattern (`'"'"'INNEREOF'"'"'`) - `DEFAULT_MODEL=proxy/claude-sonnet-4` — mit Provider-Prefix für Custom Provider - `OPENAI_BASE_URL` und `OPENAI_API_KEY` entfernt — OpenClaw ignoriert diese Env-Vars, nutzt nur `models.providers` Config --- ## [0.0.0.4] — 2026-03-11 / 2026-03-12 ### Hinzugefügt **Diagnostic Container — Selbstcheck-UI** - Neuer Container `aria-diagnostic` mit Web-UI auf Port 3001 - Status-Karten: OpenClaw Gateway, RVS, Claude Proxy — jeweils mit Dot-Indicator - Claude Proxy Test: Prüft Erreichbarkeit (`/v1/models`) und sendet Test-Prompt an Claude — zeigt verfügbare Modelle als Tags + `DEFAULT_MODEL` Hinweis für docker-compose.yml - Auth-Check: "Auth prüfen" Button durchsucht alle bekannten Credential-Pfade im Proxy-Container (`/root/.config/claude/`, `/root/.claude/`, `/root/.claude/auth/`) rekursiv — zeigt gefundene Dateien und deren Inhalt - Claude Login via UI: "Login starten" Button öffnet interaktives Terminal (xterm.js) in einem Modal-Overlay — führt `claude login` im Proxy-Container aus, volle TUI-Unterstützung (kein ANSI-Stripping mehr nötig) - xterm.js Terminal: Bidirektionaler Stream über Docker Exec API mit `Tty: true` + HTTP Upgrade auf Raw-TCP-Socket — echtes interaktives Terminal im Browser - UTF-8 Fix: Eingehende Daten werden als `Uint8Array` an xterm.write() übergeben (statt `atob()` → Latin-1 String, der Multi-Byte UTF-8 zerstört), ausgehende Daten über `TextEncoder` UTF-8-safe kodiert - Credentials manuell einfügen: "Credentials einfügen" Button — JSON von einem eingeloggten Rechner kopieren und direkt in den Container schreiben (schreibt in beide mögliche Pfade: `.config/claude/` und `.claude/`) - Docker Exec API: Generische `dockerExec()` (nicht-interaktiv, multiplexed stream) + `attachTerminal()` (interaktiv, Tty, raw TCP socket) für Befehle in laufenden Containern (via Docker Socket) - Chat-Test: Nachrichten direkt über Gateway oder via RVS senden - Tabbed Logs: Separate Tabs für Alle, Gateway, RVS, Proxy, Server — mit Zähler pro Tab - Autoscroll-Pause: Automatisch wenn hochgescrollt, "Nach unten" Button zum Fortsetzen - TLS Fallback für RVS-Verbindung (wie Bridge und App) ### Geändert **Bridge → aria-core: OpenClaw Gateway Protokoll** - Bridge nutzt jetzt das echte OpenClaw Gateway WebSocket-Protokoll (Port 18789 statt 8080) - Vollständiger Handshake: `connect.challenge` → `connect` Request (mit Auth-Token) → `hello-ok` - Nachrichten über `chat.send` Method mit `message` und `idempotencyKey` - Antworten über `chat:final` Events (statt custom JSON) - Streaming-Support vorbereitet (`chat:delta` Events werden empfangen) - Fehlerbehandlung für `chat:error` Events — werden an die App weitergeleitet - Client-ID: `gateway-client` / Mode: `backend` (OpenClaw akzeptiert nur bestimmte Werte) **Docker-Compose Überarbeitung** - Bridge + Diagnostic nutzen `network_mode: "service:aria"` — teilen Netzwerk mit aria-core, kein separates Netz nötig - `ANTHROPIC_API_KEY` + `ANTHROPIC_BASE_URL` entfernt — OpenClaw rief damit die echte Anthropic API direkt an (401 `invalid x-api-key`), statt den Proxy zu nutzen. Nur noch `OPENAI_*` Vars aktiv - `DEFAULT_MODEL=openai/claude-sonnet-4-6` — mit `openai/` Prefix, damit OpenClaw den OpenAI-Provider und somit den Proxy nutzt - `openclaw.env` erstellt — Volume-Mount schlug fehl weil die Datei nicht existierte (Docker erstellte stattdessen ein leeres Verzeichnis) - `OPENCLAW_GATEWAY_TOKEN` statt `AUTH_TOKEN` — korrekter Env-Var-Name - `ARIA_AUTH_TOKEN` an Bridge und Diagnostic durchgereicht - Port 3001 auf aria-Service gemappt (für Diagnostic Web-UI) - Proxy Claude-Config Volume `:ro` → `:rw` — Login via Diagnostic-UI braucht Schreibzugriff **OpenClaw Config-Persistenz** - Named Docker Volume `openclaw-config` für `/home/node/.openclaw` — OpenClaw-Konfiguration (Model, Auth, Sessions) überlebt Container-Neustarts - `aria-setup.sh` — Einmaliges Setup-Skript: wartet auf aria-core, setzt Model auf `openai/claude-sonnet-4-6`, startet Container neu ### Behoben - Handshake fehlgeschlagen `[object Object]` — Fehlermeldung wurde nicht korrekt stringifiziert - `client.id` und `client.mode` im Connect-Request — OpenClaw akzeptiert nur vordefinierte Werte (`cli`, `gateway-client`, `webchat` etc.) - `chat.send` nutzt `message` statt `text` als Parameter — OpenClaw Schema-Validierung - **Claude Proxy bindet auf 0.0.0.0** — `claude-max-api-proxy` bindet hardcoded auf `127.0.0.1`, nicht erreichbar im Docker-Netz. Fix: `standalone.js` wird beim Start gepatcht, liest jetzt `HOST` Env-Var (Upstream-Bug: `startServer()` unterstützt `host`, aber CLI übergibt es nicht) - **Claude Proxy Crash bei Chat-Completion** — `normalizeModelName()` in `cli-to-openai.js` crasht wenn `model` undefined ist (`TypeError: Cannot read properties of undefined`). Fix: Null-Guard-Patch mit Fallback auf `claude-sonnet-4` - **OpenClaw 401 `invalid x-api-key`** — OpenClaw rief mit `ANTHROPIC_BASE_URL` + `ANTHROPIC_API_KEY=not-needed` die echte Anthropic API an, nicht den Proxy. Fix: Anthropic-Vars entfernt, nur OpenAI-Provider aktiv (`OPENAI_BASE_URL=http://proxy:3456/v1`). Proxy unterstützt nur `/v1/chat/completions` (OpenAI-Format), nicht `/v1/messages` (Anthropic-Format) - **App Echo-Bug** — Chat-Nachrichten von RVS wurden ohne Sender-Prüfung als ARIA-Nachricht angezeigt. Bei Ghost-Clients (Doppel-Connections nach Reconnect) erschien die eigene Nachricht nochmals. Fix: `message.payload.sender` wird geprüft, Nachrichten von `user` und `diagnostic` werden ignoriert --- ## [0.0.0.3] — 2026-03-09 ### Geändert **RVS — Architektur-Umbau** - RVS ist jetzt reiner Relay — kennt keine Tokens, keine Expiry, leitet nur durch - `TOKEN_EXPIRY` und `RVS_PUBLIC_HOST`/`RVS_PUBLIC_PORT` entfernt - Rooms leben solange Clients verbunden sind (statt fester Ablaufzeit) - Multi-Instanz: Mehrere ARIA-VMs können denselben RVS nutzen (z.B. Stefan + Papa) **Token-Erzeugung auf ARIA-VM statt RVS** - `generate-token.js` aus `rvs/` entfernt - Neues `generate-token.sh` im Hauptverzeichnis (läuft auf ARIA-VM) - Token wird automatisch in `.env` geschrieben - `./generate-token.sh show` zeigt bestehendes Token als QR nochmal an **Konfiguration vereinfacht** - `RVS_URL` ersetzt durch `RVS_HOST`, `RVS_PORT`, `RVS_TLS` (klare Einzelfelder) - Port einmal in `.env` ändern → wirkt auf RVS docker-compose, Bridge und QR-Code - `rvs/docker-compose.yml` nutzt `${RVS_PORT:-443}` statt hardcoded Port **Android App — QR-Code Scanner** - Echter QR-Code Scanner statt Platzhalter-Alert (`react-native-camera-kit`) - Vollbild-Kamera mit Overlay, Validierung des QR-Formats - Kamera-Berechtigung (Android Runtime Permission) - `AndroidManifest.xml` — `CAMERA` Permission hinzugefügt **Voice Bridge — RVS-Anbindung** - Bridge verbindet sich jetzt parallel zu aria-core (lokal) UND zum RVS (öffentlich) - Nachrichten von der App werden über RVS → Bridge → aria-core weitergeleitet - Antworten von aria-core werden über Bridge → RVS → App zurückgeschickt - Auto-Reconnect mit Exponential Backoff für beide WebSocket-Verbindungen - Neue Message-Handler: chat, mode, location, file, audio **Android Build-Fixes** - `kotlin_version` (snake_case) in `build.gradle` hinzugefügt — `react-native-camera-kit` braucht beide Varianten - `build.sh` schreibt `org.gradle.java.home` dynamisch in `gradle.properties` — verhindert dass Gradle kaputte JVM-Pfade findet (`/usr/lib/jvm/openjdk-17` ohne bin/java) - `minSdkVersion` 21 → 23 — `react-native-camera-kit` braucht mindestens API 23 **Android App — Credentials Persistenz** - Verbindungsdaten (Host, Port, Token) werden nach QR-Scan in AsyncStorage gespeichert - Beim App-Start automatisch geladen und verbunden — einmal scannen, nie wieder - Neue Dependency: `@react-native-async-storage/async-storage` **Docker & Infrastruktur** - OpenClaw Image fix: `openclaw/openclaw:latest` → `ghcr.io/openclaw/openclaw:latest` - Proxy fix: Binary heißt `claude-max-api`, braucht `@anthropic-ai/claude-code` als Peer-Dependency - Proxy Binary-Name fix: `claude-max-api-proxy` → `claude-max-api` (npm-Paket heißt anders als die Binary) - `libportaudio2` in Bridge Dockerfile hinzugefügt — `sounddevice` braucht PortAudio - `aria-data/config/aria.env.example` hinzugefügt — Voice Bridge Konfigurationsvorlage **Wake-Word Fix (openwakeword)** - `WakeWordDetector` umgebaut — sucht Custom-Modell `/voices/wake_aria.onnx`, Fallback auf eingebautes `hey_jarvis` - Alter Code crashte: `wakeword_models=["aria"]` erwartet Dateipfad, kein Keyword **TLS Fallback (Bridge → RVS)** - Bridge versucht zuerst `wss://` (TLS), bei `ssl.SSLError` automatisch Fallback auf `ws://` - Konfigurierbar über `RVS_TLS_FALLBACK=true` in `.env` - Loggt deutlich wenn TLS gewollt aber nicht verfügbar ist **Audio-Rendering für App (Piper TTS via RVS)** - Bridge rendert Piper TTS → WAV → base64, sendet Text UND Audio gleichzeitig über RVS - App spielt Audio ab und zeigt Text parallel — Modus entscheidet ob Sprache oder nur Text - Voice Engine initialisiert IMMER (auch ohne Soundkarte in der VM) - STT/Wake-Word nur wenn Audio-Hardware vorhanden — graceful degradation - Neue Dependency: `react-native-fs` (base64 → temp WAV → Sound abspielen) **Chat-Persistenz (Android App)** - Chat-Verlauf wird in AsyncStorage gespeichert (letzte 500 Nachrichten) - Beim App-Start automatisch geladen — Konversation bleibt erhalten - Linearer 1:1 Chat, keine Threads **TLS Fallback + Verbindungslog (Android App)** - App versucht zuerst `wss://`, bei Fehler automatisch Fallback auf `ws://` - `network_security_config.xml` hinzugefuegt — Android 9+ blockiert sonst `ws://` (Cleartext) - Verbindungslog im Settings-Tab — zeigt jeden Verbindungsversuch, Fehler, Fallback (scrollbar, max 200px) - Gespeicherte Config wird beim Start in die Einstellungsfelder geladen - Fix: TLS-Fallback erzeugte Doppel-Verbindungen (onerror + onclose beide reconnected) **RVS — Ghost-Client Fix** - Heartbeat-Intervall 30s → 15s, Cleanup 60s → 30s — tote Clients werden schneller entfernt - `heartbeat` als erlaubter Nachrichtentyp hinzugefuegt — App-Heartbeats halten Verbindung lebendig - App-seitiger JSON-Heartbeat zaehlt als Lebenszeichen (zusaetzlich zu WebSocket Ping/Pong) **Neues Script: `get-voices.sh`** - Lädt Piper Stimmen (Ramona + Thorsten) von HuggingFace herunter - Neuer Installationsschritt in README **ARIA Persönlichkeit** - `AGENT.md` überarbeitet — ARIA ist jetzt Partnerin auf Augenhöhe (Claude-Charakter) - Direkt, ehrlich, humorvoll, lösungsorientiert, kein Theater --- ## [0.0.0.2] — 2026-03-08 ### Geändert **Build-Fixes** - `CI=true` in `build.sh` — verhindert EMFILE durch Metro File-Watcher im Release-Build - `setup.sh` erstellt Metro-Config-Dateien automatisch (metro.config.js, babel.config.js, .watchmanconfig) **Release-Script** - `release.sh` komplett umgebaut — Kennwort wird interaktiv abgefragt statt Token in `.env` - Gitea-Upload fix: `-F` multipart statt `--data-binary` - Login-Test vor Release, CHANGELOG.md-Integration für Release Notes --- ## [0.0.0.1] — 2026-03-08 ### Hinzugefügt **Infrastruktur** - `docker-compose.yml` — ARIA-VM mit Proxy, OpenClaw, Voice Bridge - `.env.example` — Konfigurationsvorlage (ohne Secrets) - `release.sh` — Automatisiertes Release (Build, Tag, Gitea Upload mit Kennwort-Abfrage) **RVS (Rendezvous-Server)** - WebSocket Relay Server (`rvs/server.js`) — Token-Rooms, Heartbeat, Message Types - Docker Setup (`rvs/Dockerfile`, `rvs/docker-compose.yml`) **Token & Pairing** - `generate-token.sh` — Token-Generator mit QR-Code (läuft auf ARIA-VM, schreibt Token in `.env`) **Voice Bridge** - Python Voice Bridge (`bridge/aria_bridge.py`) — Whisper STT, Piper TTS, Wake-Word - 5 Betriebsmodi (`bridge/modes.py`) — Normal, DND, Whisper, Hangar, Gaming - Docker Setup (`bridge/Dockerfile`, `bridge/requirements.txt`) **Android App (ARIA Cockpit)** - Chat-Screen mit Texteingabe, Voice-Button, Datei/Kamera-Upload - Settings-Screen mit Verbindungsstatus, Token-Eingabe, Modus-Auswahl, GPS-Toggle, Log-Viewer - WebSocket-Service mit Auto-Reconnect und Exponential Backoff - Audio-Service (Mikrofon-Aufnahme, TTS-Wiedergabe) - Push-to-Talk Button mit Puls-Animation - Modus-Selektor (5 Modi) - Build-Tooling: `setup.sh` (7-Schritt Dev-Setup), `build.sh` (Release/Debug APK) - Metro-Config, Babel-Config, Watchman-Config **Konfiguration & Daten** - `aria-data/config/AGENT.md` — ARIAs Persönlichkeit und Sicherheitsregeln - `aria-data/config/USER.md` — Stefans Präferenzen - `aria-data/config/TOOLING.md` — VM-Tooling Liste - `aria-data/skills/README.md` — Skill-Bauanleitung ### Bekannte Probleme - Android Release-Build: `EMFILE: too many open files` — Fix: `CI=true` in `build.sh` - JDK 21 inkompatibel mit AGP 8.1 — Fix: Automatischer Fallback auf JDK 17 - `react-native-screens` > 3.27.0 inkompatibel mit RN 0.73.4 — Fix: Version gepinnt