diff --git a/android/src/screens/SettingsScreen.tsx b/android/src/screens/SettingsScreen.tsx
index 1c537b9..9895032 100644
--- a/android/src/screens/SettingsScreen.tsx
+++ b/android/src/screens/SettingsScreen.tsx
@@ -1329,6 +1329,31 @@ const SettingsScreen: React.FC = () => {
>
{'π¨ ARIA hart neu starten'}
+
+ Konversation komplett zuruecksetzen β alle bisherigen Nachrichten
+ aus ARIA's Session loeschen + Container neu. Anders als der harte
+ Restart wird hier auch ARIA's Erinnerung an die laufende
+ Konversation gewipt. Geschieht automatisch alle 140 Nachrichten
+ (Bridge-Setting COMPACT_AFTER_MESSAGES).
+
+ {
+ Alert.alert(
+ 'Konversation komprimieren?',
+ 'Alle Nachrichten in ARIAs aktueller Session werden geloescht und der Container neu gestartet. ARIA vergisst den bisherigen Gespraechsverlauf.',
+ [
+ { text: 'Abbrechen', style: 'cancel' },
+ { text: 'Komprimieren', style: 'destructive', onPress: () => {
+ rvs.send('aria_session_reset' as any, {});
+ ToastAndroid.show('Session wird zurueckgesetztβ¦', ToastAndroid.LONG);
+ }},
+ ],
+ );
+ }}
+ >
+ {'π§Ή Konversation komprimieren'}
+
>)}
diff --git a/bridge/aria_bridge.py b/bridge/aria_bridge.py
index b993ee8..36b4e41 100644
--- a/bridge/aria_bridge.py
+++ b/bridge/aria_bridge.py
@@ -549,6 +549,12 @@ class ARIABridge:
# Beeinflusst das Timeout fuer stt_request β bei "loading" warten wir laenger,
# weil das Modell beim ersten Request noch ~1-2 Min runtergeladen werden kann.
self._remote_stt_ready: bool = False
+ # User-Message-Counter fuer Auto-Compact. Bei zu langer Konversation
+ # sprengt die argv-Liste beim Claude-Subprocess-Spawn (E2BIG). Bei
+ # COMPACT_AFTER erreicht β Sessions reset + Container restart.
+ # Counter ueberlebt Bridge-Restart nicht (frischer Zaehler beim Start ok).
+ self._user_message_count: int = 0
+ self._compact_after = int(os.getenv("COMPACT_AFTER_MESSAGES", "140"))
# Pending Files: wenn die App ein Bild + Text gleichzeitig schickt, kommen
# zwei separate RVS-Events ('file' und 'chat') β wir buffern die Files
# kurz und mergen sie mit dem nachfolgenden Chat-Text zu einer einzigen
@@ -1170,12 +1176,53 @@ class ARIABridge:
await self.send_to_core(text, source="app-file+chat")
return True
+ async def _trigger_session_reset(self) -> None:
+ """Sessions loeschen + Container restart via Diagnostic HTTP-API."""
+ try:
+ req = urllib.request.Request(
+ "http://localhost:3001/api/aria-session-reset",
+ data=b"{}",
+ method="POST",
+ headers={"Content-Type": "application/json"},
+ )
+ def _do_reset():
+ try:
+ with urllib.request.urlopen(req, timeout=45) as resp:
+ return resp.status
+ except Exception as e:
+ return f"err:{e}"
+ result = await asyncio.get_event_loop().run_in_executor(None, _do_reset)
+ logger.info("[core] Session-Reset Result: %s", result)
+ except Exception as e:
+ logger.warning("[core] Session-Reset Trigger fehlgeschlagen: %s", e)
+
async def send_to_core(self, text: str, source: str = "bridge") -> None:
"""Sendet Text an aria-core (OpenClaw chat.send Protokoll)."""
if self.ws_core is None:
logger.error("[core] Nicht verbunden β Nachricht verworfen: '%s'", text[:60])
return
+ # Auto-Compact: bei zu vielen User-Messages laeuft argv beim Subprocess-
+ # Spawn ueber (E2BIG). Vor send pruefen, ggf. Sessions resetten.
+ if source.startswith("app") and self._compact_after > 0:
+ self._user_message_count += 1
+ if self._user_message_count >= self._compact_after:
+ logger.warning("[core] Auto-Compact: %d Messages erreicht β Session-Reset",
+ self._user_message_count)
+ self._user_message_count = 0
+ # Reset triggern via Diagnostic (asynchron, blockiert send nicht)
+ asyncio.create_task(self._trigger_session_reset())
+ # User informieren β der naechste Request kommt erst nach Restart durch
+ await self._send_to_rvs({
+ "type": "chat",
+ "payload": {
+ "text": f"[Compact] Konversation war lang ({self._compact_after} Nachrichten) β Session wurde geleert, ARIA startet frisch. Deine letzte Nachricht bitte gleich nochmal senden.",
+ "sender": "aria",
+ },
+ "timestamp": int(asyncio.get_event_loop().time() * 1000),
+ })
+ return
+
# Aktive Session vom Diagnostic holen
self._fetch_active_session()
@@ -1580,6 +1627,13 @@ class ARIABridge:
except Exception as e:
logger.warning("[rvs] file_saved konnte nicht an App gesendet werden: %s", e)
+ elif msg_type == "aria_session_reset":
+ # Manueller Compact-Trigger: Sessions weg + Restart
+ logger.warning("[rvs] aria_session_reset Request von App")
+ self._user_message_count = 0
+ asyncio.create_task(self._trigger_session_reset())
+ return
+
elif msg_type == "aria_restart":
# App-Button "ARIA hart neu starten" β docker restart aria-core
# via Diagnostic (der hat den Docker-Socket gemountet).
diff --git a/diagnostic/index.html b/diagnostic/index.html
index 993f728..3cb1d75 100644
--- a/diagnostic/index.html
+++ b/diagnostic/index.html
@@ -290,6 +290,7 @@
💭 ARIA denkt...
+
@@ -1891,6 +1892,18 @@
.catch(err => addLog('error', 'server', 'Restart Request fehlgeschlagen: ' + err.message));
}
+ // ββ Compact / Session-Reset ββββββ
+ function ariaSessionReset() {
+ if (!confirm('Konversation komprimieren: alle Nachrichten in ARIAs aktueller Session werden geloescht und der Container neu gestartet. ARIA vergisst den bisherigen Gespraechsverlauf. Sicher?')) return;
+ fetch('/api/aria-session-reset', { method: 'POST' })
+ .then(r => r.json())
+ .then(data => {
+ if (data.ok) addLog('info', 'server', 'Session geleert, ARIA neu gestartet');
+ else addLog('error', 'server', 'Reset fehlgeschlagen: ' + (data.error || ''));
+ })
+ .catch(err => addLog('error', 'server', 'Reset Request fehlgeschlagen: ' + err.message));
+ }
+
// ββ Abbrechen ββββββββββββββββββββββββββββββ
function cancelRequest() {
send({ action: 'cancel_request' });
diff --git a/diagnostic/server.js b/diagnostic/server.js
index c3ff2dc..6136c91 100644
--- a/diagnostic/server.js
+++ b/diagnostic/server.js
@@ -1358,6 +1358,43 @@ const server = http.createServer((req, res) => {
res.end(JSON.stringify({ ok: false, error: err.message }));
});
return;
+ } else if (req.url === "/api/aria-session-reset" && req.method === "POST") {
+ // Sessions weg + Container neu β fuer Compact-After-N-Messages.
+ // E2BIG bei zu langen Sessions: argv beim Subprocess-spawn ueberschritten.
+ log("warn", "server", "HTTP /api/aria-session-reset β Sessions loeschen + Restart");
+ broadcast({ type: "watchdog", status: "fixing", message: "Sessions werden geleert β ARIA bekommt frischen Start" });
+ dockerExec("aria-core", "rm -f /home/node/.openclaw/agents/main/sessions/*.jsonl /home/node/.openclaw/agents/main/sessions/*.lock 2>&1 && echo '{}' > /home/node/.openclaw/agents/main/sessions/sessions.json")
+ .then(() => {
+ // Restart via Docker-API (gleicher Pfad wie /api/aria-restart)
+ const restartReq = http.request({
+ socketPath: "/var/run/docker.sock",
+ path: "/containers/aria-core/restart?t=10",
+ method: "POST",
+ headers: { "Content-Length": 0 },
+ timeout: 30000,
+ }, (dRes) => {
+ if (dRes.statusCode === 204) {
+ log("info", "server", "aria-session-reset OK");
+ broadcast({ type: "watchdog", status: "fixed", message: "Sessions geleert, ARIA neu gestartet" });
+ res.writeHead(200, { "Content-Type": "application/json" });
+ res.end(JSON.stringify({ ok: true }));
+ } else {
+ res.writeHead(500, { "Content-Type": "application/json" });
+ res.end(JSON.stringify({ ok: false, error: `Docker-API ${dRes.statusCode}` }));
+ }
+ });
+ restartReq.on("error", (err) => {
+ res.writeHead(500, { "Content-Type": "application/json" });
+ res.end(JSON.stringify({ ok: false, error: err.message }));
+ });
+ restartReq.end();
+ })
+ .catch((err) => {
+ log("error", "server", `aria-session-reset Cleanup fehlgeschlagen: ${err.message}`);
+ res.writeHead(500, { "Content-Type": "application/json" });
+ 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). Geht ueber Docker-API (Socket), kein CLI noetig.
diff --git a/docker-compose.yml b/docker-compose.yml
index b58483c..a612513 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -87,6 +87,7 @@ services:
- RVS_TLS=${RVS_TLS:-true}
- RVS_TLS_FALLBACK=${RVS_TLS_FALLBACK:-true}
- RVS_TOKEN=${RVS_TOKEN:-}
+ - COMPACT_AFTER_MESSAGES=${COMPACT_AFTER_MESSAGES:-140}
restart: unless-stopped
# βββ Diagnostic (Selbstcheck-UI und Einstellungen) ββββ
diff --git a/rvs/server.js b/rvs/server.js
index 55570e6..fd8a086 100644
--- a/rvs/server.js
+++ b/rvs/server.js
@@ -21,6 +21,7 @@ const ALLOWED_TYPES = new Set([
"file_from_aria",
"doctor_fix",
"aria_restart",
+ "aria_session_reset",
"xtts_delete_voice",
"voice_preload", "voice_ready",
"stt_request", "stt_response",