Erkenntnis aus dem Live-Test: bei gesperrtem Bildschirm greifen Gesten/Tasten
nicht (Android-Sicherheit), der Agent meldete aber still 'ok' -> Verwirrung
(home,home,home, Screenshot zeigt trotzdem alte App). Fix: KeyguardManager.
isKeyguardLocked() gate fuer Steuer-Aktionen (ui_tap/text/swipe/key/app_launch)
-> klare Meldung 'Geraet ist gesperrt - bitte entsperren'. Sehen (screenshot/
ui_dump/info) bleibt auch gesperrt erlaubt. README-Hinweis ergaenzt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Jede Host-Aktion wird als Historie-Eintrag festgehalten und in der Diagnostic
pro User-Nachricht gruppiert aufklappbar dargestellt (mit Screenshot-Thumbnails).
- Brain: trace_id+msg pro chat(); _dispatch_host als Wrapper um _dispatch_host_inner
emittiert je Aktion einen Eintrag an POST /internal/agent-history (Datei-Pfad aus
Screenshot-Text erkannt).
- Bridge: /internal/agent-history persistiert nach /shared/config/agent_history/
<hostId>.jsonl (Ringpuffer 200) + broadcastet agent_history; agent_history_query
-> agent_history_list.
- RVS: agent_history/_query/_list in ALLOWED_TYPES (sonst still verworfen).
- Diagnostic-Server: relay browser<->RVS + /uploads/<file> Bild-Endpoint (nur
/shared/uploads, kein Traversal).
- index.html: 'Historie'-Button je Host, Modal mit Akkordeon (Gruppe=Nachricht,
aufklappbar, Screenshot-Thumbs), Live-Refresh bei agent_history.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Geraet (Android 12) meldete beim Projizieren:
'Media projections require a foreground service ...
FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION'. Der Dienst lief als reiner dataSync.
Fix: foregroundServiceType=dataSync|mediaProjection + Permissions
FOREGROUND_SERVICE_MEDIA_PROJECTION/-DATA_SYNC; beim Projektions-Start
startForeground(..., MEDIA_PROJECTION|DATA_SYNC) VOR getMediaProjection().
Normale Starts nutzen explizit nur dataSync (Android-14-konform). Version 0.0.0.5.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Timeout hiess: kein host_result kam zurueck. Ursachen adressiert:
1) handle() umschliesst JEDE Aktion mit try/catch(Throwable) -> auch OOM/Exception
liefert jetzt ein host_result mit Fehlertext statt Stille (kein Timeout mehr).
2) ScreenCapturer nimmt direkt in gekappter Aufloesung auf (max 1280 lange Seite,
MediaProjection skaliert) statt Vollbild-Bitmap + Nachskalieren -> viel weniger
Speicher/Zeit (kein 10-MB-ARGB-Bitmap -> kein OOM), Frame-Warten bis ~3s.
lastError fliesst in die Screenshot-Fehlermeldung. Version 0.0.0.4/code 4.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Jeder Build signierte bisher mit einem zufaelligen Auto-Debug-Key -> neue APK =
andere Signatur -> Android verweigert Update ('Konflikt mit bestehendem Paket').
Fester signingConfig (rootProject/aria-agent.keystore) fuer debug+release, per
Datei-Existenz-Guard. Keystore liegt nur lokal (gitignored, NICHT im public Repo
— Backup!). Verifiziert: Signer-DN CN=ARIA Host-Agent. Version 0.0.0.3/code 3.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der Projection-Consent kommt per startForegroundService, obwohl der Dienst schon
laeuft. Android verlangt danach binnen ~5s ein startForeground() -> fehlte im
Projection-Zweig -> ForegroundServiceDidNotStartInTimeException -> Prozess-Crash
(Diagnostic zeigt den Host bis zum Ping-Timeout noch gruen). Fix: onStartCommand
ruft IMMER zuerst startForeground(). Zusaetzlich ScreenCapturer.start in try/catch
mit lastError, das in der Screenshot-Fehlermeldung und der Notification erscheint.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Dockerfile.win (tobix/pywine): baut die Windows-.exe via Wine+PyInstaller und
per NSIS ein setup.exe, das den Agent via nssm als Autostart-Windows-Dienst
einrichtet und die .env aus %ProgramData%\ARIA-Host-Agent liest (AppDirectory).
build-win.sh als Einstieg; release_agent.sh baut Windows jetzt mit (SKIP_WINDOWS=1
ueberspringt). _load_dotenv haertet: sucht .env auch neben sys.executable (onefile-
.exe-Ort), nicht nur __file__/CWD. README: Windows-Build + Dienst + Release.
macOS bleibt self-build (nicht aus Docker moeglich).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
release_agent.sh <version> (wie die App-release.sh): setzt Version
(host_agent.py AGENT_VERSION + Android versionName/Code), baut Linux-Binary +
Android-APK per Docker, taggt agent-v<version> (eigener Namespace, keine
Kollision mit App-Tags v<version>), legt Gitea-Release an und laedt Assets hoch.
mac/win optional falls in dist/ vorgebaut. Agent meldet AGENT_VERSION jetzt in
host_hello + info. README-Release-Sektion aktualisiert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Das slim-bullseye-Image bringt kein objdump mit -> PyInstaller bricht mit
'On Linux, objdump is required' ab. binutils per apt nachinstalliert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Screenshot via MediaProjection (ScreenCapturer, gleicher {format,bytes,base64}-
Vertrag wie der Desktop-Agent -> host_screenshot, inkl. Vision). UI-Baum via
AriaAccessibilityService (nur lesend) -> neues Brain-Tool host_ui_dump. Freigabe
einmalig in der App: 'Bildschirm-Zugriff erlauben' + 'Bedienungshilfe oeffnen'.
caps = [info, screenshot, ui_dump]. targetSdk 33 -> keine mediaProjection-FGS-
Typpflicht.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Nativer Kotlin-Agent (host-agent/android/): Gradle-Projekt, AndroidManifest,
RVS-WebSocket-Client (OkHttp) mit host_hello/host_ping/host_command->host_result,
Foreground-Service (Weg A, Auto-Reconnect, BootReceiver), Connect-UI (QR-Scan via
ZXing ODER manuell: host/port/token/name/TLS/Steuerung-Schalter). QR-Format =
{host,port,token,tls} wie die ARIA-App -> derselbe QR nutzbar.
M1-Aktion: info (Modell/Android/Akku). screenshot/ui_* liefern 'kommt in M2/M3'.
Gate: CONTROL_ENABLED-Schalter in der App. Build: Docker (Android-SDK+Gradle) ->
dist/aria-android-agent.apk (Debug, auto-signiert). Kein Google.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Klargestellt: FCM (Google) ist NUR eine Option, keine Pflicht. Akkuschonender
Push geht self-hosted via UnifiedPush + ntfy auf dem ARIA-Server (laeuft auch auf
Custom-ROMs ohne Play Services). Fuer ein dediziertes Ziel-Handy ist der eigene
RVS-Socket (Weg A) oft die einfachste Dauerloesung. Empfehlung entsprechend
angepasst: A -> Push-Hybrid mit ntfy, FCM nur optional.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Akku-optimal wie WhatsApp: idle nur FCM-Push, bei Befehl kurz Socket + Wakelock
fuer die Interaktion, danach wieder schlafen. Requirements (Firebase/Play Services/
Server-Push-Trigger) + Latenz dokumentiert. Empfehlung: erst Foreground-Service
(M1-3, sofort lauffaehig), dann Push-Hybrid als Akku-Ausbau.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Symptom: ARIA laeuft ins Tool-Loop-Limit (host_agent-Exploration), postet die
Meldung, aber die App zeigt eine LEERE Bubble.
Ursache: stripSystemHints (App) entfernt fuehrende [..]-Bloecke (fuer Hinweise
wie '[Kontext:..] Hallo'). Die Tool-Loop-/Fehler-Meldung ist KOMPLETT ein
[..]-Block -> restlos gestrippt -> leer.
Fixes:
- App (ChatScreen): stripSystemHints zeigt das Original, wenn nach dem Strippen
nichts uebrig bleibt -> Fehler-/Meta-Meldungen (auch '[Fehler: ...]') sind
wieder sichtbar statt leer.
- Brain: MAX_TOOL_ITERATIONS 8 -> 20 (env-tunebar) — 8 war zu knapp fuer echte
agentische Arbeit (Host-Exploration); ARIA brach mittendrin ab.
- Brain: Loop-Limit-Meldung ARIA-stimmig + handlungsleitend statt technischer
Marker (liest sich natuerlich in der Bubble).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Raum-Monitor (haette uns die Nacht erspart): der RVS-Log kuerzt Tokens auf 8
Zeichen -> zwei verschiedene Tokens mit gleichem Prefix ergeben zwei Raeume,
die im Log IDENTISCH aussehen (Prefix-Kollision). Jetzt zeigt die Diagnostic
(Satelliten-Tab, Panel 'RVS-Raeume 🚪') alle Raeume mit token8 + laengerem
Fingerprint (sha256) + Token-Laenge + Client-Zahl, ★ = eigener Raum. >1 Raum =
Warnung 'Token-Mismatch'. Keine vollen Tokens (nur Fingerprint).
- rvs: rooms_query -> direkt rooms_info antworten (wie update_check); Typen in
ALLOWED_TYPES; sha256-Fingerprint via crypto.
- diagnostic: rooms_query durchreichen, rooms_info an Browser; Panel + Tabelle.
Dazu: Compute-Flotte-Ueberschrift bekommt statt 🖥️ ein Inline-SVG (Server mit
GPU-Karte, currentColor -> theme-aware).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Host-Agent und Satellit hatten keinen TLS-Fallback (nur die vier Compute-Bridges).
Jetzt konsistent: bei TLS-Fehlschlag einmal auf ws:// zurueckfallen, danach wieder
mit RVS_TLS starten (kein Sticky-Fallback, wie bei den Bridges). uri_host/proto
werden pro Versuch aus use_tls berechnet, damit der RVS_SNI-Pfad nur bei wss gilt.
Hilft nur wo der RVS plaintext erreichbar ist; gegen Caddy-TLS bleibt wss. RVS_TLS_
FALLBACK in beiden .env.example dokumentiert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Symptom mit RVS_SNI: 'server rejected WebSocket connection: HTTP 200'. Ursache:
die IP stand in der URI -> HTTP-Host-Header = IP -> Caddy findet keinen RVS-Site-
Block (routet nach Host) und liefert eine Default-200-Seite statt WS-Upgrade. Der
vorige Fix korrigierte nur SNI/Cert (server_hostname), nicht den Host-Header.
Zudem: host=/port= als websockets.connect-kwargs kollidieren in der Legacy-API
mit dem aus der URI abgeleiteten Host (TypeError).
Loesung (host-agent, satellite, f5tts/whisper/voxtral/llm-adapter): die URI nutzt
den HOSTNAMEN (RVS_SNI) -> Host-Header + SNI + Cert stimmen; ein In-Process-
getaddrinfo-Override mappt RVS_SNI -> RVS_HOST (IP) fuer den TCP-Connect.
Versionsunabhaengig, nicht-blockierend, nur aktiv wenn RVS_SNI gesetzt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Nennt keine realen Kunden-Produktions-/Staging-Domains mehr; die Sicherheits-
regel (nie gegen Produktion testen) bleibt vollstaendig wirksam.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Enthaelt echte Server-IPs fuer den Dev-Zugriff -> gehoert nicht ins oeffentliche
Repo. In .gitignore aufgenommen; lokale Datei bleibt (mit echter IP) erhalten.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
install-service.sh: installiert Binary (/usr/local/bin) + .env (/etc/aria-host-
agent/.env, 0600) + systemd-Unit und macht enable --now. .env-Pfad als Argument
ODER ohne Argument ein ncurses-Dateidialog (dialog --fselect, bietet Installation
von dialog an). Findet die Binary unter dist/ bzw. ./ oder als 2. Argument.
Doku aktualisiert (RVS_SNI fuer RZ-interne Clients + Installer):
- host-agent/README: Installer-Abschnitt + TLS/SNI-Abschnitt.
- README (zentral): Installer + SNI im Host-Agent-Abschnitt (Verweis auf
Satellit/Compute-Nodes).
- satellite/README + xtts/README: RVS_SNI-Hinweis fuer Boxen/Satelliten im
RVS-Netz.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Damit eine AI-Box (f5tts/whisper/voxtral/llm-adapter) auch im selben Netz wie
der RVS direkt auf dessen interne IP verbinden kann (kein NAT-Hairpin ueber den
externen Hostnamen), ohne am SNI/Cert zu scheitern: RVS_HOST=<ip> + RVS_SNI=<name>.
server_hostname im ssl-Context, gated auf use_tls (respektiert den TLS-Fallback).
Leer = Verhalten wie bisher. Szenario: zweite Box im RZ + eine zuhause.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Gleiche Faehigkeit wie beim host-agent: ein Satellit im selben Netz wie der RVS
kann direkt auf die interne IP verbinden und trotzdem den Cert-Namen im TLS-SNI
praesentieren (Caddy findet sonst kein Zertifikat -> tlsv1 alert internal error).
Nuetzlich z.B. fuer einen RZ-internen Satelliten, nur um Credentials zu hinterlegen.
RVS_HOST=<ip> + RVS_SNI=<name>; leer = Verhalten wie bisher.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fuer Agenten im selben Netz wie der RVS: direkt auf die interne IP verbinden
(kein NAT-Hairpin ueber den externen Hostnamen), aber im TLS-Handshake den
Namen praesentieren, fuer den das Caddy-Zertifikat gilt. Ohne das schickt der
Client die IP als SNI -> Caddy findet kein Cert -> 'tlsv1 alert internal error'.
RVS_HOST=<interne-ip> + RVS_SNI=<zert-name>. server_hostname im ssl-Context.
Leeres RVS_SNI = Verhalten wie bisher. Robuster als /etc/hosts (ueberlebt
Reboots, wichtig auf Live-ISOs).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Docker-Build scheitert auf Live-ISOs (overlayfs-Root -> overlay2 kann kein
Overlay-auf-Overlay stapeln: 'failed to mount ... invalid argument'). Ergaenzt:
- build-native.sh: PyInstaller in einem venv, ohne Docker (Warnung: linkt gegen
lokales glibc).
- README: Live-ISO-Ursache erklaert + zwei Auswege (Binary woanders bauen und
kopieren [empfohlen, portabel] oder nativ bauen).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
"Claude Vision direkt (ohne Dateipfad-Umweg)" abgehakt und umformuliert:
Bildanalyse funktioniert bereits (App-Uploads + Screenshots via Read-Tool,
/shared/uploads im Proxy-Container gemountet). Die "direkte" Variante waere
reine Politur (ein Read weniger) und ist bewusst nicht geplant — vermeidet,
dass jemand den heiklen Proxy-Umbau spaeter grundlos wieder aufmacht.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der Host-Agent stand nur in host-agent/README.md, nicht in der zentralen Doku.
Ergaenzt: Zeile in der Deploy-Tabelle + Abschnitt "Host-Agenten" (build.sh ->
Binary, Install, sudo-Faelle inkl. Live-ISO, Sicherheit, Vision via Read-Tool).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der Proxy reduziert Multimodal-Content zu Text (openai-to-cli), ARIA laeuft auf
der Claude-Code-CLI. Aber: der Proxy-Container hat /shared gemountet und ARIA
laeuft mit vollen Tools (--dangerously-skip-permissions) -> sie kann die unter
/shared/uploads/ gespeicherte Screenshot-PNG mit ihrem eigenen Read-Tool
oeffnen, das Claude Code nativ als Bild rendert. Damit SIEHT sie den Bildschirm
und kann 'was ist auf meinem Bildschirm' beantworten — ganz ohne Proxy-/Vision-
Umbau. host_screenshot-Result + Tool-Beschreibung weisen sie an, den Pfad zu
Read'en (sehen) UND als [FILE:]-Marker zu setzen (im Chat zeigen).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Statt den Screenshot nur nach /shared/host-screenshots zu legen und den Pfad
zu nennen, speichert host_screenshot das PNG jetzt nach /shared/uploads/ und
liefert ARIA die Anweisung, den Pfad als [FILE: ...]-Marker in die Antwort zu
schreiben — exakt das flux_generate-Muster. Die Bridge erkennt den Marker,
broadcastet file_from_aria, und App/Diagnostic zeigen das Bild inline im Chat.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diagnostic-Server trackt host_hello/host_ping (hosts-Map), broadcastet
host_update und beantwortet die host_list-Action. UI: neues Panel
"Host-Agenten" im Satelliten-Tab — zeigt Name/OS/Caps/online + ob
CONTROL_ENABLED. Reine Sichtbarkeit; Steuerung laeuft ueber ARIA.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Damit kann ARIA Host-Agenten tatsaechlich nutzen (Ende-zu-Ende):
- RVS: host_hello/host_ping/host_command/host_result in ALLOWED_TYPES.
- Bridge: _hosts-Registry (host_hello/host_ping/host_result), _host_list,
_host_request (requestId->Future wie Satelliten), HTTP-Endpoints
/internal/host-list und /internal/host (op via action).
- Brain: Tools host_list/host_exec/host_read/host_write/host_info/
host_screenshot + _dispatch_host (ruft /internal/host*). host_screenshot
speichert das PNG unter /shared/host-screenshots. host_exec kann sudo=true.
Naechste (optionale) Phase E: Host-Agenten in der Diagnostic-Flotte anzeigen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Schlanker Agent, der DIREKT auf einem Linux-Rechner laeuft und sich ausgehend
zum RVS verbindet -> ARIA steuert den Rechner auch hinter NAT/Firewall, wo er
sonst nicht erreichbar ist. Anders als der Satellit (LAN-Gateway) steuert der
Agent den Rechner, auf dem er laeuft.
Faehigkeiten (host_command -> host_result): exec (opt. sudo), read, write,
info (CPU/RAM/Disk/Uptime via psutil), screenshot (grim/scrot/maim/import).
sudo-Logik: root -> direkt; SUDO_PASSWORD -> sudo -S; SUDO_NOPASSWD (Live-ISO)
-> sudo -n; sonst klare Fehlermeldung. Gate: CONTROL_ENABLED + RVS-Token.
stdout wird wie beim Satelliten gefenstert (contains/offset/max_chars).
Als portable Onefile-Binary verteilbar (PyInstaller im bullseye-Container fuer
breite glibc-Kompatibilitaet): build.sh + Dockerfile.build. Plus .env.example,
systemd-Unit und README.
Naechste Phasen: RVS ALLOWED_TYPES (host_*), Bridge-Registry + /internal/host*,
Brain-Tools host_list/exec/read/write/info/screenshot.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Neuer Credential-Typ 'ssh' (Benutzer + Passwort ODER privater Key, Port) und
Aktion ssh.exec (params: ip, cmd). paramiko-Client; grosse Ausgaben werden wie
bei http.get gefenstert (contains/offset/max_chars gemeinsam via _window_text),
Antwort mit exit_code + stdout + stderr. Auth kommt aus dem Credential-Store,
ARIA muss keine Passwoerter mitgeben.
- satellite: _do_ssh + _ssh_load_key (RSA/Ed25519/ECDSA/DSS aus String),
ssh.exec in _control + Allowlist, 'ssh' in beide Cred-Typ-Listen; paramiko
in requirements; .env.example ergaenzt.
- diagnostic: SSH-Sektion im Credentials-Modal (User/Port/Passwort/Key) +
Save-Logik (User + Passwort|Key).
- brain: satellite_command-Tool um ssh.exec erweitert.
Laeuft ueber den bestehenden sat_command/sat_result-Pfad — keine RVS-Aenderung.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der DocumentPicker war auf images/pdf/docx/plainText beschraenkt -> vom
Smartphone liessen sich nur Bilder/Dokumente hochladen. Auf allFiles
umgestellt; die Komponente verarbeitet beliebige Typen ohnehin (Base64 +
octet-stream-Fallback), und die Server-Seite hat kein MIME-Gate.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wie bei der FritzBox: manche Geraete nutzen HTTP-Basic-Auth nur mit Passwort.
Modal speichert HTTP-Creds jetzt bei User ODER Passwort; _do_http wendet die
Auth auch bei leerem Benutzer an. SNMP v1/v2c hat ohnehin nur die Community
(kein User); v3 braucht den securityName zwingend und bleibt Pflicht.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Das Credentials-Modal speicherte FritzBox-Zugangsdaten nur, wenn das Benutzer-
Feld ausgefuellt war (if fu) — Username war damit faktisch Pflicht. FritzBoxen
ohne benannten Benutzer haben aber nur ein Passwort. Jetzt: gespeichert sobald
User ODER Passwort gesetzt ist; Placeholder kennzeichnet den User als optional.
Backend (_do_fritzbox) verlangte ohnehin nur das Passwort.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der Credential-Store nutzt pathlib.Path, das Modul importierte es aber nicht
-> NameError in _creds_load(), Satellit crashte in Endlosschleife beim Start.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>