From 2dd4d38dce02a285f7422d5657354c09fee71609 Mon Sep 17 00:00:00 2001 From: duffyduck Date: Mon, 11 May 2026 01:58:44 +0200 Subject: [PATCH] feat: "ARIA hart neu starten"-Button (docker restart aria-core) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Zweiter Eskalations-Button neben dem Reparieren-Button β€” fuer Faelle wo doctor --fix nicht reicht (Run alive aber haengt im Tool-Call). Mit Confirmation-Dialog damit's nicht versehentlich gedrueckt wird. Wege: - App-Settings: Reparatur-Sektion, zwei Buttons (Reparieren + Hart neu) - App-Thinking-Bubble: πŸ”§ + 🚨 + Abbrechen - Diagnostic-Thinking-Indicator: πŸ”§ + 🚨 + Abbrechen - Diagnostic-Server: POST /api/aria-restart β†’ child_process exec `docker restart aria-core` - Bridge: rvs aria_restart β†’ HTTP zu Diagnostic Co-Authored-By: Claude Opus 4.7 (1M context) --- android/src/screens/ChatScreen.tsx | 18 +++++++++++++++++- android/src/screens/SettingsScreen.tsx | 23 +++++++++++++++++++++++ bridge/aria_bridge.py | 26 ++++++++++++++++++++++++++ diagnostic/index.html | 16 ++++++++++++++++ diagnostic/server.js | 21 +++++++++++++++++++++ rvs/server.js | 1 + 6 files changed, 104 insertions(+), 1 deletion(-) diff --git a/android/src/screens/ChatScreen.tsx b/android/src/screens/ChatScreen.tsx index 0647f94..a52c1ea 100644 --- a/android/src/screens/ChatScreen.tsx +++ b/android/src/screens/ChatScreen.tsx @@ -21,6 +21,7 @@ import { ToastAndroid, AppState, NativeModules, + Alert, } from 'react-native'; import AsyncStorage from '@react-native-async-storage/async-storage'; import RNFS from 'react-native-fs'; @@ -1251,7 +1252,22 @@ const ChatScreen: React.FC = () => { rvs.send('doctor_fix' as any, {})}> - {'πŸ”§ Reparieren'} + {'πŸ”§'} + + { + Alert.alert( + 'ARIA hart neu starten?', + 'Container-Restart (~15s). Laufende Anfragen gehen verloren.', + [ + { text: 'Abbrechen', style: 'cancel' }, + { text: 'Neu starten', style: 'destructive', onPress: () => rvs.send('aria_restart' as any, {}) }, + ], + ); + }} + > + {'🚨'} Abbrechen diff --git a/android/src/screens/SettingsScreen.tsx b/android/src/screens/SettingsScreen.tsx index 6d7080c..1c537b9 100644 --- a/android/src/screens/SettingsScreen.tsx +++ b/android/src/screens/SettingsScreen.tsx @@ -1306,6 +1306,29 @@ const SettingsScreen: React.FC = () => { > {'πŸ”§ ARIA reparieren'} + + Wenn auch Reparieren nicht hilft β€” Container hart neu starten. + ARIA ist dann ~15 Sekunden weg und kommt mit frischem State zurueck. + Laufende Anfragen gehen verloren. + + { + Alert.alert( + 'ARIA hart neu starten?', + 'Container-Restart (~15s). Laufende Anfragen gehen verloren.', + [ + { text: 'Abbrechen', style: 'cancel' }, + { text: 'Neu starten', style: 'destructive', onPress: () => { + rvs.send('aria_restart' as any, {}); + ToastAndroid.show('Container-Restart angestossen…', ToastAndroid.LONG); + }}, + ], + ); + }} + > + {'🚨 ARIA hart neu starten'} + )} diff --git a/bridge/aria_bridge.py b/bridge/aria_bridge.py index 2b887e6..b993ee8 100644 --- a/bridge/aria_bridge.py +++ b/bridge/aria_bridge.py @@ -1580,6 +1580,32 @@ class ARIABridge: except Exception as e: logger.warning("[rvs] file_saved konnte nicht an App gesendet werden: %s", e) + elif msg_type == "aria_restart": + # App-Button "ARIA hart neu starten" β†’ docker restart aria-core + # via Diagnostic (der hat den Docker-Socket gemountet). + logger.warning("[rvs] aria_restart Request von App β€” harter Container-Restart") + try: + req = urllib.request.Request( + "http://localhost:3001/api/aria-restart", + data=b"{}", + method="POST", + headers={"Content-Type": "application/json"}, + ) + def _do_restart(): + try: + with urllib.request.urlopen(req, timeout=45) as resp: + return resp.status, resp.read().decode("utf-8", errors="ignore") + except Exception as e: + return None, str(e) + status, body = await asyncio.get_event_loop().run_in_executor(None, _do_restart) + logger.info("[rvs] aria_restart Result: status=%s", status) + # Note: bei erfolgreichem Restart ist die RVS-Verbindung sehr + # wahrscheinlich kurz weg (aria-bridge ist im service:aria-Network). + # Die Antwort kommt evtl. nicht mehr durch β€” egal. + except Exception as e: + logger.warning("[rvs] aria_restart Weiterleitung fehlgeschlagen: %s", e) + return + elif msg_type == "doctor_fix": # App-Button "ARIA reparieren" β†’ openclaw doctor --fix anstossen. # Bridge erreicht aria-core nicht via docker (kein docker-socket diff --git a/diagnostic/index.html b/diagnostic/index.html index 1dafbd4..993f728 100644 --- a/diagnostic/index.html +++ b/diagnostic/index.html @@ -290,6 +290,7 @@ 💭 ARIA denkt...
+
@@ -1875,6 +1876,21 @@ .catch(err => addLog('error', 'server', 'Reparatur Request fehlgeschlagen: ' + err.message)); } + // ── Hard-Restart β€” docker restart aria-core ────── + function ariaRestart() { + if (!confirm('ARIA wird hart neu gestartet (Container-Restart, ~15s).\n\nLaufende Anfragen gehen verloren. Sicher?')) return; + fetch('/api/aria-restart', { method: 'POST' }) + .then(r => r.json()) + .then(data => { + if (data.ok) { + addLog('info', 'server', 'ARIA neu gestartet β€” wartet auf Reconnect'); + } else { + addLog('error', 'server', 'Restart fehlgeschlagen: ' + (data.error || '')); + } + }) + .catch(err => addLog('error', 'server', 'Restart Request fehlgeschlagen: ' + err.message)); + } + // ── Abbrechen ────────────────────────────── function cancelRequest() { send({ action: 'cancel_request' }); diff --git a/diagnostic/server.js b/diagnostic/server.js index 388ec19..c278dac 100644 --- a/diagnostic/server.js +++ b/diagnostic/server.js @@ -1358,6 +1358,27 @@ const server = http.createServer((req, res) => { res.end(JSON.stringify({ ok: false, error: err.message })); }); return; + } else if (req.url === "/api/aria-restart" && req.method === "POST") { + // Harter Restart β€” fuer Faelle wo doctor --fix nicht reicht (alive aber + // haengender Run). docker restart killt PID 1 vom Container, alle Locks + // weg, neuer State. Dauert ~10-20s bis ARIA wieder antwortet. + log("warn", "server", "HTTP /api/aria-restart β€” harter Container-Restart"); + broadcast({ type: "watchdog", status: "fixing", message: "ARIA wird hart neu gestartet (~15s)" }); + const exec = require("child_process").exec; + exec("docker restart aria-core", { timeout: 30000 }, (err, stdout, stderr) => { + if (err) { + log("error", "server", `aria-restart fehlgeschlagen: ${err.message}`); + broadcast({ type: "watchdog", status: "error", message: `Restart fehlgeschlagen: ${err.message}` }); + res.writeHead(500, { "Content-Type": "application/json" }); + res.end(JSON.stringify({ ok: false, error: err.message })); + return; + } + log("info", "server", `aria-restart OK: ${(stdout || "").trim()}`); + broadcast({ type: "watchdog", status: "fixed", message: "ARIA wurde neu gestartet β€” sollte gleich antworten" }); + res.writeHead(200, { "Content-Type": "application/json" }); + res.end(JSON.stringify({ ok: true, output: stdout })); + }); + return; } else if (req.url.startsWith("/shared/")) { // Dateien aus Shared Volume ausliefern (Bilder, Uploads) const filePath = decodeURIComponent(req.url); diff --git a/rvs/server.js b/rvs/server.js index e67c9ed..55570e6 100644 --- a/rvs/server.js +++ b/rvs/server.js @@ -20,6 +20,7 @@ const ALLOWED_TYPES = new Set([ "audio_pcm", "file_from_aria", "doctor_fix", + "aria_restart", "xtts_delete_voice", "voice_preload", "voice_ready", "stt_request", "stt_response",