Stefans Repro "nichts geht mehr" kam NICHT von den Marker/Guard-Aenderungen,
sondern von der Speaker-ID: die Bridge-Logs zeigten fast durchgehend
"stt_endpoint mit leerem Text — ignoriert (reason=speaker_mismatch)" — ein aus
einem kaputten Enroll (AAC-als-PCM) entstandener Muell-Fingerprint hat Stefans
EIGENE Stimme abgelehnt und damit die komplette STT lahmgelegt.
Fix: Speaker-ID-Gating ist jetzt ein expliziter Schalter, Default AUS. Bei aus
laeuft die Pruefung GAR NICHT (fail-open, alle Stimmen durch) — ein schlechter
Enroll kann nie wieder alles abwuergen. Damit ist Stefans Problem schon durch den
Voxtral-Rebuild geloest (kein Loeschen noetig, der Check greift einfach nicht).
- voxtral + whisper bridge: SPEAKER_ID_ENABLED (Default False, ENV VOICE_ID_ENABLED),
_check_speaker faellt bei aus sofort fail-open zurueck; config-Broadcast
voiceIdEnabled setzt es zur Laufzeit.
- diagnostic: Schalter "Nur meine Stimme" in der Voice-ID-Sektion (Default aus,
Hinweis: erst an wenn enrollt), broadcastet + persistiert voiceIdEnabled.
Reihenfolge lt. Stefan: erst Konversation sauber, dann Multi-Person/nur-ich.
Deploy: docker compose up -d --build voxtral-bridge; aria-diagnostic neu starten.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Voice-ID-Enrollment scheiterte immer mit "zu kurz". Ursache: die App nimmt die
Samples mit dem Legacy-Recorder als AAC im MP4-Container auf (16kHz mono), die
Bridge dekodierte das base64 aber als ROHES int16-PCM. 4s AAC sind stark
komprimiert (< 32KB = MIN_SAMPLE_BYTES) → faelschlich als "zu kurz" verworfen,
und selbst darueber waere das Embedding Muell.
Fix (bridge-seitig, kein APK): _normalize_audio_bytes erkennt jetzt den MP4/M4A/
AAC-Container ('ftyp' bei Offset 4) und dekodiert ihn via ffmpeg (im Container) auf
16kHz mono int16 PCM — zusaetzlich zu rohem PCM und WAV. enroll_from_samples
dekodiert erst, prueft DANN die Laenge aufs dekodierte PCM (nicht die komprimierten
Bytes). Input via Temp-Datei, da Androids moov-Atom am Ende seekbaren Input braucht.
Gleich in voxtral + whisper (identische Kopien).
Deploy: docker compose up -d --build voxtral-bridge; danach in Einstellungen →
Voice-ID neu einlernen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stefans Repro: nach dem Senden ging sofort ein Passiv-Fenster auf (waehrend ARIA
noch arbeitete), und obwohl er nichts sagte, kam eine "Nachricht von ihm" — Voxtral
halluzinierte aus Fast-Nichts einen Fuellsatz. Der ging als Phantom-Turn ans Brain
und liess das Gespraech entgleisen (Antwort drauf, dann Konversation-Ende).
Ursache war eine Nebenwirkung des "Sprache erkannt"-Pings (9e78d75): der feuerte
beim ERSTEN Voice-Frame — also auch bei einem kurzen Geraeusch-Blip. Damit war der
App-No-Speech-Watchdog geloescht, der akustische Endpoint feuerte, und Voxtral
transkribierte den Blip → Halluzination. (Vorher haette der Watchdog den Blip
verworfen.)
Fix: voiced_frames-Zaehler (Endpointer-Frames mit echter Stimme). Erst ab
STREAM_MIN_VOICED_FRAMES (=2, ~400ms, env-tunebar) gilt es als Sprache:
- Der Speech-Ping feuert erst ab dieser Schwelle (ein Blip loescht den Watchdog
also nicht mehr).
- _finalize transkribiert unter der Schwelle NICHT, sondern schickt ein leeres
Endpoint (no-speech) → App re-armt still, kein Phantom-Turn. Manueller Stop
(stream_end) ist ausgenommen (bewusst gesprochen, kurze Woerter ok).
Deploy: docker compose up -d --build voxtral-bridge.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Beobachtung Stefan: ARIA haelt die Konversation offen (Default, korrekt), aber
auf "Konversation Ende" hin schloss sie NICHT — sie hat den [[ENDE]]-Marker nicht
gesetzt. Das aufs LLM allein zu verlassen ist zu unzuverlaessig fuer einen festen
Trigger.
Fix: _user_wants_conversation_end() erkennt explizite Beenden-Phrasen im User-Text
(konversation/gespraech/befehlskette + ende/beenden/aus/stop/schluss, beide
Reihenfolgen, ein Satzteil) und erzwingt converse=false an ALLEN drei Returns
(fast-path/local/claude). ARIA beantwortet eine evtl. enthaltene Frage noch normal
(speak bleibt), danach zurueck aufs Wake-Word. "befehls?kette" statt bare "kette",
damit "Lieferkette" u.ae. nicht faelschlich matchen (per Test abgesichert).
Deploy: Brain-Neustart (nicht waehrend ARIA arbeitet).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Im Ohr-Modus (Wake/Passiv/Barge) beendete die App die Aufnahme am Konversations-
fenster (~conv window), obwohl Stefan noch redete — nur dort, nicht beim normalen
Button. Ursache: der App-No-Speech-Watchdog cancelt, solange KEIN stt_partial kam
(streamGotPartial=false). Voxtral schickt aber seit dem Cutoff-Fix keine Live-
Partials mehr → streamGotPartial blieb immer false → Timer feuerte mitten im Satz.
Der normale Button nutzt noSpeechTimeoutMs=0 (Watchdog aus) → dort nie aufgefallen.
Fix: Voxtral-Bridge feuert EIN leeres stt_partial beim ersten Voice-Frame (nach
der Speaker-ID-Pruefung, fremde Stimmen signalisieren also nicht). Die App setzt
darauf streamGotPartial=true und loescht den Watchdog — bestehender Handler, keine
App-Aenderung. Der akustische Endpoint (Stille >= endpointMs) bleibt der einzige
Turn-Ende-Ausloeser.
Deploy: docker compose up -d --build voxtral-bridge (keine neue APK noetig).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Voice-First: ARIA deklariert die Phase aus dem Text per Inline-Marker — dasselbe
Muster wie [[AWAIT]], die Marker werden vor Anzeige/TTS/History entfernt. Loest:
- Claude-Pfad las Steuerbefehle vor, obwohl das Skill lief (Manifest-speak-Flag
kennt den Unterschied Befehl/Frage nicht — dasselbe Skill ist mal Aktion, mal
Auskunft). Jetzt entscheidet ARIA aus dem Kontext.
- Befehlsketten (VNC oeffnen, Menue klicken, ...): Mikro soll offen bleiben und
stumm gearbeitet werden, bis Stefan die Kette beendet.
Marker (ARIA haengt sie ans Antwort-Ende):
[[STUMM]] -> Steuerbefehl, nicht vorlesen. Allein = Einzelbefehl -> danach Stop.
[[WEITER]] -> Konversation/Kette laeuft weiter -> Mikro offen halten.
[[ENDE]] -> Konversation/Kette beenden -> zurueck aufs Wake-Word.
Brain:
- _extract_flow_markers() zieht [[STUMM]]/[[WEITER]]/[[ENDE]] aus dem Claude-Reply
und ueberschreibt speak/converse (Marker ist autoritativ ueber Skill-Flag).
[[STUMM]] allein impliziert converse=false; [[ENDE]] schlaegt [[WEITER]].
- prompts.py: neue Sektion build_voice_flow_section() bringt ARIA Marker +
Befehl/Frage-Klassifikation + Ketten-/Ende-Erkennung bei.
App (ChatScreen): stiller Antwort-Zweig verzweigt jetzt auf converse —
converse=true (Kette) -> endConversation(false), Mikro bleibt offen fuer den
naechsten Kettenbefehl; converse=false -> ariaStopRecording (Stop wie gehabt).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Steuerbefehle laufen stumm (speak=false in Fast-Path/Local/Claude-Pfad) — ohne
TTS feuert aber onPlaybackFinished nie, und daran hing bisher das Aufraeumen der
Aufnahme. Folge: nach "spotify play" blieb das Mikro-/Konversations-Fenster offen
(30s Leerlauf), obwohl der Befehl laengst ausgefuehrt war.
Neu: ariaStopRecording() — das programmatische Gegenstueck zum Stop-Button. Nach
einer stillen Antwort (speak=false) schliesst ARIA jede offene Aufnahme selbst und
geht zurueck aufs Wake-Word, egal in welchem Zustand: passives Lauschen sauber
beenden, offene Streaming-Aufnahme (aktiv/Barge) verwerfen, sonst endConversation.
Vorher nur der conversing-Fall abgedeckt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stop finalisierte die Aufnahme, aber die danach kommende onPlaybackFinished oeffnete via converseRef erneut das 30s-Passiv-Fenster. Jetzt setzt handleVoiceButtonStop converse=false → nach manuellem Stop kein Passiv-Lauschen mehr.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
converse defaultete true → jeder Befehl mit gesprochener Bestaetigung ('Spiele Spotify') ging ins 30s-Passiv-Fenster. Jetzt nur bei explizitem converse:true vom Brain; einzelne Befehle enden sofort → zurueck aufs Wake-Word, Spotify resumed gleich.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Voxtral hatte 0 Speaker-Filter (mit Voxtral reagierte ARIA auf JEDE Stimme). Jetzt portiert aus der whisper-Bridge: speaker_id.py (ECAPA/speechbrain) kopiert, Einmal-Check auf die ersten 1.5s (fremde Stimme → leeres stt_endpoint reason=speaker_mismatch, kein Transcribe/Brain), voice_id_enroll/status/delete-RVS-Handler + voiceIdThreshold-config. voice-id-Volume gemountet, speechbrain in requirements. Ohne Enrollment fail-open.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Behebt den Konversations-Mischmasch: (1) Barge-in-Einstellung (Default AUS = Halb-Duplex) gated das Mikro-Lauschen waehrend TTS -> ARIA spricht ungestoert zu Ende. (2) interruptAriaIfBusy bricht die Brain-Antwort WIRKLICH ab (cancel_request) statt nur TTS zu muten -> sie antwortet nicht mehr weiter waehrend man redet. (3) Stop-Button stoppt vorhersehbar alles (TTS + Brain-Cancel). Musik: nativer Focus ist schon GAIN_TRANSIENT (pausiert) -> der saubere Flow behebt das Focus-Geflacker.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
STT_ENDPOINT_MAX_MS 4000->8000. Der (in a) auf den aktiven Endpoint umgeklemmte 'Stille-Toleranz'-Regler geht damit bis 8s statt nur 4s — genug Zeit zum Nachdenken, ohne dass die Aufnahme endet. Fliesst per endpointMs an Voxtral/Whisper.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ursache: Voxtral-3B transkribiert den ganzen wachsenden Buffer (~5-6s bei langen Aufnahmen). Diese Partial-Latenz war groesser als der semantische Endpoint-Timeout (4.8s) → 'Text waechst nicht mehr' feuerte faelschlich → Abbruch nach 20-40s. Fix: keine Live-Partials mehr, kein semantischer Endpoint — Turn-Ende rein akustisch (Stille-VAD), transkribiert wird nur EINMAL im _finalize. max_new_tokens 512->4096 (512 schnitt lange Diktate ab).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
VoxtralProcessor.apply_transcription_request -> load_audio_as braucht librosa zum Einlesen der Audiodatei. Fehlte im Image.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
VoxtralProcessor.apply_transcription_request verlangt bei rohen Arrays ein 'format'. Fix: Buffer in ein temp-WAV (PCM_16, 16kHz) schreiben und den Pfad uebergeben — Processor liest Format+Samplerate selbst. Temp-Datei wird nach dem Transkribieren geloescht.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Profile getauscht: voxtral-bridge laeuft jetzt bei jedem 'docker compose up', whisper-bridge nur noch mit --profile whisper. Loest das 'nach down/up startet whisper statt voxtral'-Problem. Immer nur EIN STT gleichzeitig (sonst stt_*-Kollision).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Modell laedt knapp nicht (12GB-Karte hatte 3.13GB durch Fremdprozess belegt). Anti-Fragmentierungs-Schalter reduziert den Peak-Bedarf beim Warmup; zusaetzlich muss GPU 1 frei sein (whisper stoppen).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Backports brachte keinen neueren Treiber (bleibt 550/CUDA 12.4). Statt Upgrade: Voxtral-Mini-3B-2507 via Transformers mit torch 2.6.0+cu124 (F5-Trick) — laeuft auf 550, ~9 GB bf16 auf GPU 1. Chunked wie whisper mit dem adaptiven M0.1-Endpointer, RVS-Protokoll identisch (drop-in). Ersetzt den vLLM-Realtime-4B-Ansatz (der brauchte 16 GB). Compose: ein Container, GPU-1-gepinnt, Profil 'voxtral'. Transformers-API in einer Methode gekapselt (verify-on-run).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fuer Voxtral/modernes CUDA: --upgrade-driver zieht einen neueren nvidia-driver aus trixie-backports, baut das DKMS-Modul (Kernel-Header sind da), und weist auf den noetigen Reboot hin. Ohne den Flag bleibt der laufende 550er unangetastet. Fallback-Hinweis auf NVIDIAs CUDA-Repo, falls backports nichts Neueres hat.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der sichtbare 'Stille-Toleranz'-Regler verstellte den toten Legacy-dB-VAD-Pfad; jetzt steuert er STT_ENDPOINT_MS (die echte Streaming-Pausen-Toleranz, 1-4s). Der obsolete 'Stille-Pegel (dB)'-Regler ist entfernt — der aktive STT nutzt adaptiven Rausch-Boden, Rauschen-als-Wort verhindert der no_speech_prob-Filter des Modells.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wake-Word/Barge-In waren hart auf 60s gecappt (schnitt lange Diktate bei 1 min ab). Jetzt lesen sie loadMaxRecordingMs() — der bestehende, aber vom Streaming-Pfad abgeklemmte 'Maximale Aufnahmedauer'-Regler (1-30 min) steuert nun wirklich. Voice-Bubbles zeigen die Aufnahmedauer (durationS aus stt_endpoint) als 'M:SS'.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adaptiver Re-Pin scheiterte: f5-tts zieht torch 2.13.0, aber cu124-Wheels enden bei 2.6.0 (torch 2.7+ nur noch cu126+, was Treiber 550/CUDA12.4 nicht kann). Jetzt: torch/torchaudio 2.6.0+cu124 vor f5-tts installiert, Constraint-Datei haelt f5-tts vom Hochziehen ab. Treiber-Upgrade bleibt der strategische Fix fuer Voxtral/modernes CUDA.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
f5-tts>=1.0.0 zieht als Dependency ein neueres torch mit zu neuem CUDA-Build und ueberschreibt den cu121-Pin → 'NVIDIA driver too old (found 12040)' auf Treiber 550. Nach der Installation wird dieselbe torch/torchaudio-Version als cu124-Build force-reinstalled (--no-deps), kompatibel mit 550/CUDA 12.4.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die zwei 3060 sind ungleich (GPU0=8GB, GPU1=12GB), nicht 12+12. Groesstes Modell (STT, spaeter Voxtral-STT-3B ~9GB) muss auf die 12GB-Karte: whisper->GPU1. TTS(F5)+LLM auf die 8GB-Karte: ->GPU0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ohne linux-headers ueberspringt DKMS den Modulbau ('No kernel headers were found') → nvidia-smi kann nicht mit dem Treiber reden. Jetzt: linux-headers-amd64 + linux-headers-$(uname -r) vor dem Treiber, plus 'dkms autoinstall' als Reparatur, falls nvidia-kernel-dkms schon ohne Header installiert war.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der apt-cache-policy|grep-Check meldete faelschlich 'kein Kandidat' (locale-/pipefail-fragil), obwohl nvidia-driver installierbar war. Ersetzt durch direkten Install als Test: apt-get install; bei Fehlschlag volles apt-get update + zweiter Versuch, erst dann Abbruch mit Quellen-Diagnose.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Das schnelle 'apt-get update -qq' indiziert non-free gelegentlich nicht sauber (InRelease-Cache). Wenn kein Kandidat gefunden wird, erzwingt das Script jetzt ein vollstaendiges 'apt-get update' und prueft erneut, bevor es mit klarer Meldung abbricht.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
add_component ersetzt durch add_components: ergaenzt contrib/non-free/non-free-firmware in JEDER Components:-Zeile aller .sources-Dateien (ganze-Wort-Adressen, idempotent), verifiziert die Aenderung per md5sum statt sie nur zu melden. Vor dem nvidia-driver-Install wird der apt-Kandidat geprueft — bei fehlendem non-free klare Fehlermeldung + Anzeige der aktiven Quellen statt kryptischem 'kein Installationskandidat'.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Alte Gamebox ist retired (RAM zur ai-box gewandert) → voice-id/voices lassen sich nicht mehr kopieren. Hinweis angepasst: ohne Fingerprint laeuft Speaker-ID fail-open, Stimme + F5-Referenz einfach in der App neu anlegen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Neuer xtts/voxtral-Container (RVS<->vLLM-Realtime-WS, adaptiver Endpointer), hinter Compose-Profil 'voxtral' (braucht >=16GB VRAM, startet nicht im Default). Bestehende Satelliten auf die zwei 3060 gepinnt: whisper->GPU0, f5tts->GPU1, llama-swap->GPU0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
GPS: near()/entered_near()/left_near()-Watcher schalten das Tracking automatisch an bzw. beim Loeschen des letzten wieder aus; gpsTracking.start() sichert jetzt die Background-Permission. Cockpit-Fundament: neues Brain-Tool present_view emittiert aria_view (Orb + Karten), Bridge/RVS leiten weiter, ariaView.ts haelt die Spec App-seitig.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Feste RMS-Grenze (0.012) durch rauschboden-relativen Schwellwert ersetzt (fast-down/slow-up, geklammert). Leises/entferntes Sprechen gilt nicht mehr faelschlich als Stille und wird nicht mitten im Satz gecuttet. audio.ts: Fallback-endpointMs 1500->2400 vereinheitlicht.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ursache gefunden (WS-Direkttest beweist: Server-Pfad + Docker-Prune-API
funktionieren, aber der Klick kam nie an): runDiskCleanup() rief confirm()
VOR dem send(). Hatte der Browser Dialoge unterdrueckt ('Verhindern, dass
diese Seite weitere Dialoge erstellt' — bei dem vielen alert()/confirm()
im Diagnostic leicht passiert), gab confirm() automatisch false zurueck →
return vor send() → Button tat sichtbar nichts.
Fix: 'safe' laeuft OHNE confirm (Build-Cache + ungenutzte Images sind
ungefaehrlich, keine Volumes/Daten). Nur 'aggressive' (Volumes!) fragt
noch. Ergebnis wird am Button + Banner gezeigt, nicht nur per alert()
(das koennte genauso unterdrueckt sein).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Native Crashes/OOM schreiben keinen JS-Fehler → tauchten in app.log
nirgends auf (nur der Whisper-Reboot als Symptom). Jetzt: ein RUN_MARKER
bleibt gesetzt solange die App aktiv laeuft, wird bei sauberem Hintergrund-
Wechsel geloescht. Ist er beim naechsten Start noch da, ist der vorige Lauf
unsauber gestorben → Report via RVS ('app.crash-detected') mit dem letzten
Breadcrumb (was die App zuletzt tat) + Zeitabstand. Breadcrumbs kommen aus
reportAppError/reportAppDebug, throttled in AsyncStorage persistiert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ursache: Bridge-/chat-Aufruf hatte 1200s (20min) Timeout, der Proxy aber
24h. Lange Software-Dev-Turns dauern >20min → Bridge gab auf ('/chat
fehlgeschlagen: timed out'), der Brain lieferte die Antwort Minuten spaeter
(nur im Log, keine Bubble), und der Diagnostic-Kontext blieb auf 'running'
haengen (Folgenachrichten in die Queue trotz idler ARIA; nur Ctrl+R half,
verlor aber die Queue-Nachricht).
- Bridge: /chat-Timeout 1200s → 24h (env BRAIN_CHAT_TIMEOUT_SEC), passend
zum Proxy.
- Diagnostic: reconcileDiagStates() gleicht lokalen 'running'-Zustand gegen
die Brain-queue-status ab (2 Polls Karenz). Haengt ein Kontext, obwohl der
Brain nicht busy ist → Queue weiterschalten: angestellte Nachricht geht
automatisch raus statt verloren.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der Button rief copyDiskCmd() → kopierte nur den docker-Befehl in die
Zwischenablage (ueber http scheitert navigator.clipboard oft still →
'keine Funktion'). Jetzt fuehrt runDiskCleanup() das Aufraeumen echt aus:
Server-seitig ueber die Docker-Daemon-API (Socket ist gemountet) —
/build/prune?all=true + /images/prune (dangling=false), ohne Volumes =
keine Daten weg. 'Aggressiv' (zusaetzlich Container+Volumes) als eigener
'Jetzt ausfuehren'-Button mit Warnung. Rueckmeldung: wieviel frei wurde;
Banner aktualisiert sich per periodischem disk_status.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der Sprachmodell-Picker zeigte veraltete Eintraege ("Opus 4.8", kein
Fable). Ursache: DEFAULT_MODELS/models.json waren stale. CLI-Tiers loesen
real auf fable→Fable 5, opus→Opus 5, sonnet→Sonnet 5, haiku→Haiku 4.5.
Jetzt Tier-Aliase als id (versions-robust) + Fable 5 ergaenzt; MODEL_MAP
kennt fable + die vollen aktuellen IDs. models.json auf dem Stack live
aktualisiert (wird pro Request neu gelesen → 'Aktualisieren' reicht).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Neben Senden ein 'Zwischenruf' (App: oranger Button, nur wenn ARIA im
aktiven Kontext arbeitet; Diagnostic: Buttons neben beiden Senden). Geht
NICHT in die Queue und bricht NICHT ab — die Nachricht wird in den
laufenden claude-Subprozess geschoben; er greift sie an der naechsten
Tool-Grenze auf.
Technik:
- proxy-patches/manager.js: claude laeuft jetzt im --input-format
stream-json-Modus, initialer Prompt als stream-json User-Message,
stdin bleibt OFFEN; sendMessage() schiebt weitere User-Messages nach;
bei 'result' wird stdin geschlossen (Turn endet sauber). Ersetzt die
bisherigen sed-Patches (jetzt volle Datei via cp, docker-compose.yml).
- proxy-patches/routes.js: Side-Channel POST /interject {projectId,text}
→ subprocess.sendMessage der Kontext-Subprozesse.
- rvs: 'interject' erlaubt. bridge: RVS interject → Proxy /interject.
- App/Diagnostic: Zwischenruf-Buttons + lokale '📣 Zwischenruf'-Bubble.
Empirisch verifiziert: mid-turn injizierte Message wird an der naechsten
Tool-Grenze aufgegriffen (nicht mitten in einem blockierenden Befehl).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die App schickt Datei (fire-and-forget) und Text (ACK-getrackt, bei Queue
verzoegert) als getrennte RVS-Nachrichten; die Datei trug keine clientMsgId.
Die Bridge mergte gepufferte Files rein per Timing an den naechsten Text →
bei mehreren schnellen Nachrichten landeten Bilder beim falschen Text.
App: file-Send traegt jetzt dieselbe clientMsgId wie der Text.
Bridge: puffert Files mit cmid und merged beim Text-Flush NUR die Files mit
passender cmid; Rest bleibt fuer seine eigene Nachricht gepuffert. Fallback
(Legacy/kein Treffer) = altes Verhalten, damit nie ein Bild verloren geht.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der cancel_request-Handler rief openclaw doctor --fix auf dem Container
aria-core auf, den es im aktuellen Stack nicht mehr gibt → der laufende
claude-Subprozess wurde nie gekillt, ARIA lief weiter. Jetzt sendet er
RVS cancel_request{hard:true} → Bridge → Proxy /cancel-all killt den Run.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
_fire() rief agent.chat() (synchroner, bis zu 24h blockierender Proxy-
Call) DIREKT im asyncio-Loop auf → ein feuernder Timer/Watcher fror den
GESAMTEN Brain ein (kein /health, kein weiterer Request, Self-Deadlock
wenn der Turn via brain_request auf den Brain zurueckgreift). Jetzt wie
der /chat-Pfad in run_in_executor ausgelagert; Event-Loop bleibt frei.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Androids Zurueck-Taste versteckt die Tastatur ohne den TextInput zu
blurren → ⌨-Button blieb an, erst der uebernaechste Tap oeffnete wieder.
Jetzt setzt keyboardDidShow/Hide den Button-Zustand; Oeffnen erzwingt
blur→focus, damit ein noch fokussiertes Feld die Tastatur neu aufklappt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die Software-Tastatur liefert weder Enter (Haken) noch Esc/Pfeile/F-Tasten/
Strg/Alt. Neu:
- Haken der Tastatur → onSubmitEditing sendet jetzt Enter (returnKeyType=send).
- Fn-Leiste (Toggle in der ctlBar): Esc, Tab, Pfeile, Pos1/Ende/Bild, Einfg/
Entf, Enter, F1–F12, Strg+Alt+Entf — direkt an rfb.sendKey.
- Sticky-Modifier Strg/Alt/Shift (one-shot): kombinieren mit der naechsten
Taste ODER dem naechsten getippten Zeichen → Strg+C, Strg+Alt+Entf, Alt+F …
- noVNC: window.ariaVncKey.combo(mods,ks) haelt Modifier, tappt, laesst los.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Badge haing bisher am globalen desktop_status (irgendwo ein Desktop
erreichbar) → wurde generell angezeigt. Jetzt aus der projektbezogenen
VM-Liste (listProjectVms → running), pid-Guard, 6s-Refresh fuer Start/Stop.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der versteckte WebView-Input oeffnete die Android-Software-Tastatur
unzuverlaessig. Jetzt haelt VncTile ein echtes RN-<TextInput>
(keyboardType=visible-password), der ⌨-Button fokussiert es. Getippte
Zeichen gehen per injectJavaScript an window.ariaVncKey.char/keysym →
rfb.sendKey. Prefix-Diff fuer Druckbares, onKeyPress fuer Backspace/Enter.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Im Hauptchat (projectId='') riefen FilesTile/DesktopTile /projects//files bzw.
/vms auf → Brain 404. Beide guarden jetzt leere projectId: kein Fetch, klare
Meldung "Kein aktives Projekt — wechsle in ein Projekt".
tsc clean. App-only, Deploy: APK.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der ⤢-Knopf war nur der Fit/1:1-Umschalter (Zoom) INNERHALB des eingerahmten
Streifens (Header+Dock drumrum) — sah deshalb wie Zoom aus, fuellte nie das
Display. Jetzt oeffnet "Verbinden" die VM in einem Fullscreen-Modal: randlos
ueber alles (Header + Dock weg), scaleViewport passt den VM-Screen sauber ein,
Landscape erlaubt. Buttons schweben drueber (‹ VMs links, ⌨/Strg+Alt+Entf/⤢
rechts, unter der Statusleiste). Android-Back verlaesst Vollbild.
tsc clean. App-only, Deploy: APK.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Screenshot: aria-vm lief als User 'aria', SHOT_DIR war aber /root/... →
"mkdir: cannot create directory /root". Jetzt schreibt aria-vm das PNG ins
VM-Verzeichnis (aria-schreibbar) und der Brain holt es per SSH (base64,
_ssh_host) — unabhaengig von Volume-Rechten. End-to-end validiert (gueltiges
PNG). Wird weiter ins Projekt (screenshots/) kopiert.
VNC-Tastatur: verstecktes Input-Feld war off-screen (opacity:0, left:-1000px) →
Android oeffnete die Tastatur oft nicht / lieferte keine Events. Jetzt on-screen
(bottom, 1px, opacity:0, pointer-events:none) + beforeinput als primaerer
Handler (Android-robust) mit input-Fallback. Strg+Alt+Entf ging schon.
py/bash/tsc clean. aria-vm bereits live. Deploy: brain rebuild + APK.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Kern des "Verbinde..."-Hangs: host.docker.internal loeste zu 172.17.0.1 (docker0)
auf, QEMUs VNC ist aber ans aria-net-Gateway 192.168.64.1 gebunden (dorthin
bindet der Brain) → Connection refused. Die Bridge ermittelt den VNC-Host jetzt
selbst per _docker_gateway() (/proc/net/route) = dasselbe Gateway wie der Brain.
ARIA_VNC_HOST-Env hat weiter Vorrang.
Live belegt: Bridge->192.168.64.1:5901 liefert RFB-Handshake, ->host.docker.
internal:5901 (172.17.0.1) = refused.
py_compile clean. Deploy: bridge rebuild.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- project_vms.add_vm: VNC-Display wird GLOBAL eindeutig vergeben (ueber alle
Projekte). vnc_display<=0 oder belegtes Display → naechstes freies. Updates
behalten ihr Display. Verhindert Port-Konflikt (5901) wenn mehrere VMs laufen.
Getestet: vm1..3 → 1,2,3; Wunsch 2 (belegt) → 4; Update behaelt Display.
- vm_register-Tool + Seed-Regel: vnc_display weglassen, wird auto-vergeben.
- Gateway-IP: der Brain liest sie aus /proc/net/route bei JEDEM Boot frisch
(Docker-IP-Aenderung nach Netz-Neuaufbau wird abgefangen); boot-Antwort
enthaelt vnc_bind zur Transparenz.
py_compile clean. Brain-only, Deploy: brain rebuild.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Live-VNC rendert nie, weil die Bridge die VM nie erreichte: QEMU band 127.0.0.1
(Host-Loopback) und host.docker.internal resolved in der Bridge gar nicht.
- aria-vm: --vnc-bind <ip> (Default 127.0.0.1 / env ARIA_VM_VNC_BIND).
- Brain: _docker_gateway() (aus /proc/net/route) → boot bindet VNC an die
Docker-Gateway-IP (container-erreichbar, NICHT im LAN/Internet).
- docker-compose: bridge bekommt extra_hosts host.docker.internal:host-gateway.
- Screenshot-Endpoint kopiert das PNG zusaetzlich nach
/shared/projects/<pid>/screenshots/ → erscheint im Dateien-Panel.
End-to-end auf dem Host validiert: Bridge liest den RFB-Handshake
(b'RFB 003.008\n') von der Gateway-gebundenen VNC. aria-vm bereits live.
py/bash clean. Deploy: brain rebuild + bridge NEU (extra_hosts).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Neues 📁-Panel listet ALLE Projektdateien (/shared/projects/<id>/) — auch
erzeugte Bilder, nicht nur Code; dieselben, die in der Projektliste als 📄
gezaehlt werden. Bild antippen → Vollbild-Vorschau; Textdatei → Text-Vorschau.
- Brain: /projects/<id>/file?binary=1 → Base64 + MIME (fuer Bilder, max 8 MB).
- App: brainApi.readProjectFileBinary; layout 'files'-Tile; Dock-Reihenfolge
Chat · Dateien · Code · Desktop; FilesTile mit Bild-/Text-Modal.
py/tsc clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Solange das Live-VNC-Bild noch hakt, ist ein Standbild der pragmatische Weg die
VM zu sehen — genau wie ARIA es beim basic_os-Test gemacht hat.
- Brain: POST /projects/<pid>/vms/<name>/screenshot → aria-vm screenshot (PNG in
/shared/uploads) → als Base64 zurueck. End-to-end auf dem Host validiert
(Brain-Container sieht die Datei unter /shared/uploads).
- App: 📷-Knopf pro laufender VM im DesktopTile → zeigt den Screenshot im Modal.
py/tsc clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Start aus der App scheiterte: aria-vm boot verlangte zwingend disk.qcow2 —
basic_os bootet aber von floppy.img/ISO ohne Festplatte (OS-Bau). Jetzt:
- aria-vm boot: Disk optional; --floppy (-fda), --iso, --disk; Auto-Erkennung
von disk.qcow2/floppy.img/cdrom.iso im VM-Ordner; Boot-Reihenfolge automatisch
(ISO→d, nur Diskette→a, sonst c); braucht nur >=1 Boot-Medium.
- aria-vm create: groesse='none' → VM ohne Disk.
- Seed-Regel (Grundwissen) neu: volle aria-vm-Optionen inkl. disk-los, PFLICHT
vm_register nach Bau (sonst leere Desktop-Liste), Dateien in /shared/projects,
VNC komplett durch RVS. So weiss ARIA selbst was zu tun ist.
Live getestet auf dem Host: boot basicos (floppy-Autodetect) → laeuft :5901.
aria-vm bereits auf den Host gepusht. bash -n / py_compile OK.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Brain: /projects/status + /list liefern has_files + file_count pro Projekt
(Scan /shared/projects/<id>/). Ersetzt das manuelle Code-Flag als primaeren
Indikator. VM-Liste liefert boot_cmd (lesbarer aria-vm-Startbefehl).
- App: 📄-Symbol (+ Anzahl) an Projekten mit Dateien im ProjectsBrowser.
DesktopTile zeigt pro VM den Start-Befehl als Wert dahinter.
- Diagnostic: 📄-Symbol (+ Anzahl, Tooltip) an Projekten mit Dateien.
Hinweis (kein Code): der VNC-Stream laeuft komplett durch RVS — der Port ist nur
der interne QEMU-Display-Port, den die Bridge lokal auf dem Host nutzt; die App
oeffnet nie einen Port (firewall-unabhaengig).
py/tsc clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Brain: project_vms.py (Registry /shared/config/project_vms.json pro Projekt) +
Endpoints GET/POST/DELETE /projects/<id>/vms + boot/stop (via SSH aria-wohnung
aria-vm auf dem Host; Status aus `aria-vm list`).
- ARIA-Tools vm_register/vm_list (aufs Request-Projekt) + Seed-Regel: nach dem
VM-Bau registrieren, damit sie in Stefans Desktop-Panel auftaucht.
- App: brainApi VM-Methoden + ProjectVm-Typ. Neues DesktopTile — pro Projekt die
VM-Liste (leer bis registriert), Start/Stop/Verbinden; Verbinden oeffnet noVNC
(VncTile mit dem VNC-Port der VM). Deck rendert DesktopTile statt VncTile.
py/tsc clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Editor zeigte "keine Datei", obwohl ARIA schon Dateien geschrieben hatte — er las
NUR den Live-code_file-Stream, nie den Bestand. Jetzt:
- Brain: GET /projects/<id>/files + /file (liest /shared/projects/<id>/, pfad-sicher,
512KB-Cap). kind in ProjectUpdateBody (PATCH akzeptiert 'code'|'chat').
- App: brainApi.listProjectFiles/readProjectFile/setProjectKind. CodeEditorTile
holt beim Oeffnen die vorhandene Dateiliste + laedt Inhalt (Live-Version hat
Vorrang). ProjectsBrowser-Edit: Code-Projekt-Toggle (spiegelt sofort in
projectFocus → Cockpit-Panels).
- Diagnostic: </> Code-Toggle je Projektzeile + Code-Badge.
py/node/tsc clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New-ScheduledTaskSettings existiert nicht (CommandNotFound). Korrekt ist
New-ScheduledTaskSettingsSet. venv/Requirements liefen bereits; nur die
Task-Registrierung brach ab.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Nativer Start crashte an `SCAN_INTERVAL_SEC=300 # Hintergrund-Rescan-Intervall`
(int('300 # ...') → ValueError), weil der .env-Parser den Wert ungekuerzt
nahm. Jetzt: ungequotete Werte werden am ersten " #" (Whitespace+#) abgeschnitten,
gequotete Werte bleiben unangetastet (auch mit # im Inhalt). Getestet.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Nativ gestartet (python satellite.py) las das Script nichts aus der .env — nur
os.environ. Die Variablen mit Default (SATELLITE_ID, CONTROL_ENABLED …) wirkten
"ok", aber RVS_HOST/RVS_TOKEN (ohne Default) blieben leer → Verbindungsfehler.
Jetzt laedt _load_dotenv() eine .env neben dem Script (oder im CWD), bevor die
Config gelesen wird. Bestehende echte Umgebungsvariablen gewinnen (Docker via
env_file bleibt unberuehrt). Kein python-dotenv noetig. README Weg B vereinfacht.
Getestet: Parser liest Keys inkl. Quotes + export-Praefix.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Symptom: Satellit fand nur Docker-Container (192.168.65.x / 172.18.x) statt der
echten LAN-Geraete. Ursache ist kein Bug, sondern das Deployment-Netz: auf Docker
Desktop (Mac/Windows) ist network_mode:host das Docker-VM-NAT, nicht das echte LAN
— mDNS/SSDP erreichen die realen Geraete nicht.
- satellite.py: _net_context() ermittelt primary_ip + alle IPs und WARNT, wenn der
Satellit in einem Docker-/NAT-Netz laeuft (192.168.65.x oder 172.16-31.x). Netz-
Info wird in sat_hello + sat_devices mitgeschickt und beim Start geloggt.
- Diagnostic: zeigt Netz (primary_ip) pro Satellit + eine rote ⚠-Box mit der
Warnung, wenn er im falschen Netz sitzt.
- README/compose: klar dokumentiert, dass der Satellit im ECHTEN Ziel-LAN laufen
muss (Linux Docker Engine ODER nativ python satellite.py); Docker-Desktop-Falle.
py/node clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Das Diagnostic haengt selbst am RVS-Raum und kennt die sat_*-Broadcasts jetzt:
- server.js: Satelliten-Registry (sat_hello), leitet sat_devices an den Browser,
gibt die Liste beim init mit; Browser-Aktionen sat_list + sat_discover.
- index.html: neuer Haupt-Tab "Satelliten" — Karten pro Satellit (online/offline,
Standort, Capabilities, read-only/steuerbar) mit "Geraete scannen" → Live-Liste
der erkannten Geraete (Typ/IP/Modell/DIAL/MAC).
Kein Brain/Bridge-Rebuild fuer diesen Teil noetig (nur diagnostic). node -c OK.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
"Hol dir die Infos aus Projekt X" lieferte fast immer leer: project_summary las
nur das rollende Conversation-Window (~50 Turns ueber alle Projekte), aeltere
Projekt-Chats sind da rausdistilliert. Jetzt liest _read_project_history die
echte volle Historie aus /shared/config/chat_backup.jsonl (im Brain gemountet),
letzte ~20 Turns des Zielprojekts, Standort-Hints gefiltert, Fallback aufs
Window. Tool-Beschreibung geschaerft. Live gegen echte Daten getestet
(basic_os 20 / vdi 20 / mac_os_update_fehler 6 Turns).
Kein APK-Rebuild noetig (nur Brain).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der Voice-Projektwechsel ist zurueck, aber nur fuer das ausloesende Geraet:
- App merkt sich die IDs eigener Anfragen (Text-clientMsgId via dispatchWithAck +
Voice-audioRequestId an allen 4 Aufnahme-Stellen) in myRequestIdsRef.
- Bridge haengt an project_changed die ausloesende clientMsgId an — in beiden
Voice-Pfaden: send_to_core (ARIAs project_enter/exit) und _process_endpoint_text
(Voice-Router back_to_main / project_prefix).
- App folgt einem project_changed-Wechsel nur, wenn die clientMsgId eine eigene
ist → andere App-Instanzen + Diagnostic bleiben unberuehrt.
Nur Bridge + App betroffen. py-compile + tsc clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Zwei Kopplungs-Bugs behoben:
- set_project_kind nutzte den globalen active_project statt des Request-Projekts
→ markierte das falsche Projekt (belegt: global aktiv war mac_os_update_fehler,
das kind=code bekam, obwohl die App in basic_os war). _dispatch_tool bekommt
jetzt die project_id des Requests durchgereicht; set_project_kind wirkt darauf.
- Die App erzwang bei project_changed-Broadcasts (ARIA-Tool/Diagnostic/andere
App-Instanz) einen Fokuswechsel → alle Geraete wurden mitgezogen. Fokus ist
jetzt rein geraetelokal; Broadcasts aktualisieren nur Namen/Typ. Wechseln nur
noch lokal ueber den Drawer.
py-compile + tsc clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Zwei Nachbesserungen am Cockpit-Modus (noch Teil von 0.2.1.9):
- Im Cockpit werden IMMER alle vier Kacheln gezeigt (Chat/Editor/Desktop/
Vorschau) statt erst bei Code-Projekten — Editor/Desktop/Vorschau als
Platzhalter mit Status-Untertitel. Vorher wirkten sie "verschwunden".
- Der "⤢ Uebersicht"-Button hing im Chat genau ueber dem Abbrechen-Button der
"ARIA denkt"-Leiste. Jetzt sitzt er im Navigations-Header links (nur sichtbar
im Cockpit + Fokus), via neuem cockpitNav-Signal-Singleton. In-Content-Button
entfernt.
tsc clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Nach dem 0.2.1.8-Deploy sah die App "unveraendert" aus — korrekt, weil der
Hauptchat nur eine Kachel hat (= Vollbild-Chat). Jetzt explizit umschaltbar:
- services/viewMode.ts: 'compact' | 'cockpit', persistiert (aria_view_mode),
Default 'compact' (nichts aendert sich fuer normale Nutzung).
- ViewModeToggle im Navigations-Header (rechts, kollisionsfrei): "⧉ Kompakt" /
"⧉ Cockpit".
- WorkspaceScreen: compact → klassische ChatScreen direkt; cockpit → Canvas.
- Canvas: Uebersicht/Gesten/Back jetzt auch bei einer Kachel erreichbar (der
single-Force-Fokus entfaellt), damit sich Cockpit auch im Hauptchat wie ein
Desktop anfuehlt. "⤢ Uebersicht"-Button nach unten rechts verschoben (weg von
ChatScreens Kopf-Icons).
Changelog: Workspace-Release als 0.2.1.8 gefuehrt, Umschalter als 0.2.1.9.
tsc clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
qemu-setup.sh laeuft NICHT ueber docker compose (QEMU sitzt auf dem Host, nicht
im Container). Neuer optionaler Schritt 6 im Installations-Abschnitt: einmalig
`sudo bash host-provisioning/qemu-setup.sh` fuer den Desktop-Workspace (VM-Bauen/
VNC), plus Hinweis auf den noetigen App-Rebuild (neue native Module).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Progressive Reveal: ChatScreen spiegelt bei project_changed den Projekt-Typ
sofort in projectFocus (kind_changed nach set_project_kind) → Editor/Desktop-
Kacheln erscheinen live, nicht erst beim Reconnect.
- useWorkspaceLayout: merkt pro Projekt die zuletzt fokussierte Kachel
(AsyncStorage aria_workspace_layout) und stellt sie beim Zurueckkehren in ein
Code-Projekt wieder her.
tsc clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
QEMU-VNC erscheint live in der App-Desktop-Kachel, komplett ueber RVS:
- Bridge: TCP↔RVS-VNC-Bruecke. vnc_open oeffnet asyncio-Verbindung zu
host.docker.internal:5901, Reader-Loop streamt RFB-Bytes als vnc_data;
vnc_input schreibt zurueck; vnc_close raeumt auf. check_desktop probt den
Port und meldet desktop_status. Base64-in-JSON, kein websockify/noVNC auf
dem Host noetig.
- App: novncHtml.ts laedt noVNC (CDN) und ersetzt window.WebSocket durch einen
Shim, der RFB-Bytes per postMessage ueber RVS brueckt (server-speaks-first →
timing-robust). VncTile mountet die WebView nur im Fokus, oeffnet bei 'ready'
den Tunnel (desktop.openVnc), speist Server-Bytes ein und schickt Eingaben
als vnc_input; beim Verlassen wird der Tunnel geschlossen (VM laeuft weiter).
tsc/py clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>