Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7f862ce1f4 | |||
| 528fe97b59 | |||
| 3483d1bfce | |||
| 158423c155 |
@@ -79,8 +79,8 @@ android {
|
|||||||
applicationId "com.ariacockpit"
|
applicationId "com.ariacockpit"
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode 10102
|
versionCode 10104
|
||||||
versionName "0.1.1.2"
|
versionName "0.1.1.4"
|
||||||
// Fallback fuer Libraries mit Product Flavors
|
// Fallback fuer Libraries mit Product Flavors
|
||||||
missingDimensionStrategy 'react-native-camera', 'general'
|
missingDimensionStrategy 'react-native-camera', 'general'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "aria-cockpit",
|
"name": "aria-cockpit",
|
||||||
"version": "0.1.1.2",
|
"version": "0.1.1.4",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"android": "react-native run-android",
|
"android": "react-native run-android",
|
||||||
|
|||||||
@@ -1249,9 +1249,14 @@ const ChatScreen: React.FC = () => {
|
|||||||
? '\u270D\uFE0F ARIA schreibt...'
|
? '\u270D\uFE0F ARIA schreibt...'
|
||||||
: '\uD83D\uDCAD ARIA denkt...'}
|
: '\uD83D\uDCAD ARIA denkt...'}
|
||||||
</Text>
|
</Text>
|
||||||
<TouchableOpacity style={styles.thinkingCancel} onPress={cancelRequest}>
|
<View style={{flexDirection: 'row', gap: 6}}>
|
||||||
<Text style={styles.thinkingCancelText}>Abbrechen</Text>
|
<TouchableOpacity style={[styles.thinkingCancel, {borderColor: '#FF9500'}]} onPress={() => rvs.send('doctor_fix' as any, {})}>
|
||||||
</TouchableOpacity>
|
<Text style={[styles.thinkingCancelText, {color: '#FF9500'}]}>{'🔧 Reparieren'}</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.thinkingCancel} onPress={cancelRequest}>
|
||||||
|
<Text style={styles.thinkingCancelText}>Abbrechen</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -1363,11 +1368,17 @@ const ChatScreen: React.FC = () => {
|
|||||||
onPress={() => setFullscreenImage(null)}
|
onPress={() => setFullscreenImage(null)}
|
||||||
>
|
>
|
||||||
{fullscreenImage && (
|
{fullscreenImage && (
|
||||||
<Image
|
/\.svg(?:\?|$)/i.test(fullscreenImage) ? (
|
||||||
source={{ uri: fullscreenImage }}
|
<View style={styles.fullscreenImage}>
|
||||||
style={styles.fullscreenImage}
|
<SvgUri uri={fullscreenImage} width="100%" height="100%" preserveAspectRatio="xMidYMid meet" />
|
||||||
resizeMode="contain"
|
</View>
|
||||||
/>
|
) : (
|
||||||
|
<Image
|
||||||
|
source={{ uri: fullscreenImage }}
|
||||||
|
style={styles.fullscreenImage}
|
||||||
|
resizeMode="contain"
|
||||||
|
/>
|
||||||
|
)
|
||||||
)}
|
)}
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
@@ -1288,6 +1288,26 @@ const SettingsScreen: React.FC = () => {
|
|||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
{/* === ARIA Reparatur === */}
|
||||||
|
<Text style={[styles.sectionTitle, {marginTop: 16}]}>Reparatur</Text>
|
||||||
|
<View style={styles.card}>
|
||||||
|
<Text style={styles.toggleHint}>
|
||||||
|
Wenn ARIA gar nicht mehr antwortet oder auf jede Anfrage mit
|
||||||
|
"Antwort ohne Text" zurueckkommt — meistens ein steckengebliebener
|
||||||
|
Run im aria-core. Dieser Button fuehrt {'“'}openclaw doctor --fix{'”'}
|
||||||
|
aus und macht ARIA wieder ansprechbar.
|
||||||
|
</Text>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[styles.clearButton, {marginTop: 8, backgroundColor: 'rgba(255,149,0,0.15)'}]}
|
||||||
|
onPress={() => {
|
||||||
|
rvs.send('doctor_fix' as any, {});
|
||||||
|
ToastAndroid.show('Reparatur-Befehl gesendet — Antwort kommt gleich', ToastAndroid.SHORT);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text style={[styles.clearButtonText, {color: '#FF9500'}]}>{'🔧 ARIA reparieren'}</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
</>)}
|
</>)}
|
||||||
|
|
||||||
{/* === Logs === */}
|
{/* === Logs === */}
|
||||||
|
|||||||
@@ -1580,6 +1580,43 @@ class ARIABridge:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning("[rvs] file_saved konnte nicht an App gesendet werden: %s", e)
|
logger.warning("[rvs] file_saved konnte nicht an App gesendet werden: %s", e)
|
||||||
|
|
||||||
|
elif msg_type == "doctor_fix":
|
||||||
|
# App-Button "ARIA reparieren" → openclaw doctor --fix anstossen.
|
||||||
|
# Bridge erreicht aria-core nicht via docker (kein docker-socket
|
||||||
|
# gemountet), aber der Diagnostic-Server hat den Socket. HTTP-Call
|
||||||
|
# an http://localhost:3001/api/doctor-fix.
|
||||||
|
logger.info("[rvs] doctor_fix Request von App — leite an Diagnostic weiter")
|
||||||
|
try:
|
||||||
|
req = urllib.request.Request(
|
||||||
|
"http://localhost:3001/api/doctor-fix",
|
||||||
|
data=b"{}",
|
||||||
|
method="POST",
|
||||||
|
headers={"Content-Type": "application/json"},
|
||||||
|
)
|
||||||
|
# Blocking call ist OK weil openclaw doctor schnell durchlaeuft.
|
||||||
|
# In Executor laufen lassen damit der asyncio-Loop nicht blockt.
|
||||||
|
def _do_fix():
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen(req, timeout=30) 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_fix)
|
||||||
|
ok = status == 200
|
||||||
|
logger.info("[rvs] doctor_fix Result: status=%s ok=%s", status, ok)
|
||||||
|
await self._send_to_rvs({
|
||||||
|
"type": "chat",
|
||||||
|
"payload": {
|
||||||
|
"text": "[Reparatur] ARIA wurde durchgecheckt — sollte wieder antworten." if ok
|
||||||
|
else f"[Reparatur] Fehlgeschlagen: {body[:200]}",
|
||||||
|
"sender": "aria",
|
||||||
|
},
|
||||||
|
"timestamp": int(asyncio.get_event_loop().time() * 1000),
|
||||||
|
})
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("[rvs] doctor_fix Weiterleitung fehlgeschlagen: %s", e)
|
||||||
|
return
|
||||||
|
|
||||||
elif msg_type == "file_request":
|
elif msg_type == "file_request":
|
||||||
# App fordert eine Datei an (Re-Download nach Cache-Leerung)
|
# App fordert eine Datei an (Re-Download nach Cache-Leerung)
|
||||||
server_path = payload.get("serverPath", "")
|
server_path = payload.get("serverPath", "")
|
||||||
|
|||||||
+18
-1
@@ -288,7 +288,10 @@
|
|||||||
<div class="chat-box" id="chat-box"></div>
|
<div class="chat-box" id="chat-box"></div>
|
||||||
<div id="thinking-indicator" style="display:none;padding:6px 10px;font-size:12px;color:#FFD60A;background:#1E1E2E;border-radius:0 0 6px 6px;margin-top:-8px;margin-bottom:8px;align-items:center;justify-content:space-between;">
|
<div id="thinking-indicator" style="display:none;padding:6px 10px;font-size:12px;color:#FFD60A;background:#1E1E2E;border-radius:0 0 6px 6px;margin-top:-8px;margin-bottom:8px;align-items:center;justify-content:space-between;">
|
||||||
<span><span style="animation:pulse 1s infinite;">💭</span> <span id="thinking-text">ARIA denkt...</span></span>
|
<span><span style="animation:pulse 1s infinite;">💭</span> <span id="thinking-text">ARIA denkt...</span></span>
|
||||||
<button class="btn secondary" onclick="cancelRequest()" style="padding:2px 10px;font-size:11px;color:#FF3B30;border-color:#FF3B30;">Abbrechen</button>
|
<div style="display:flex;gap:6px;">
|
||||||
|
<button class="btn secondary" onclick="doctorFix()" style="padding:2px 10px;font-size:11px;color:#FF9500;border-color:#FF9500;" title="ARIA reparieren — openclaw doctor --fix">🔧 Reparieren</button>
|
||||||
|
<button class="btn secondary" onclick="cancelRequest()" style="padding:2px 10px;font-size:11px;color:#FF3B30;border-color:#FF3B30;">Abbrechen</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="diag-pending-attachments" style="display:none;padding:6px 10px;background:#1E1E2E;border-radius:6px 6px 0 0;margin-bottom:-4px;display:flex;gap:6px;flex-wrap:wrap;align-items:center;">
|
<div id="diag-pending-attachments" style="display:none;padding:6px 10px;background:#1E1E2E;border-radius:6px 6px 0 0;margin-bottom:-4px;display:flex;gap:6px;flex-wrap:wrap;align-items:center;">
|
||||||
</div>
|
</div>
|
||||||
@@ -1858,6 +1861,20 @@
|
|||||||
renderDiagPending();
|
renderDiagPending();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Reparieren — openclaw doctor --fix ──────
|
||||||
|
function doctorFix() {
|
||||||
|
fetch('/api/doctor-fix', { method: 'POST' })
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.ok) {
|
||||||
|
addLog('info', 'server', 'Reparatur ausgefuehrt: ' + (data.output || 'OK').slice(0, 200));
|
||||||
|
} else {
|
||||||
|
addLog('error', 'server', 'Reparatur fehlgeschlagen: ' + (data.error || ''));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => addLog('error', 'server', 'Reparatur Request fehlgeschlagen: ' + err.message));
|
||||||
|
}
|
||||||
|
|
||||||
// ── Abbrechen ──────────────────────────────
|
// ── Abbrechen ──────────────────────────────
|
||||||
function cancelRequest() {
|
function cancelRequest() {
|
||||||
send({ action: 'cancel_request' });
|
send({ action: 'cancel_request' });
|
||||||
|
|||||||
@@ -1342,6 +1342,22 @@ const server = http.createServer((req, res) => {
|
|||||||
dockerExec("aria-core", "openclaw doctor --fix 2>/dev/null || true").catch(() => {});
|
dockerExec("aria-core", "openclaw doctor --fix 2>/dev/null || true").catch(() => {});
|
||||||
res.writeHead(200, { "Content-Type": "application/json" });
|
res.writeHead(200, { "Content-Type": "application/json" });
|
||||||
res.end(JSON.stringify({ ok: true }));
|
res.end(JSON.stringify({ ok: true }));
|
||||||
|
} else if (req.url === "/api/doctor-fix" && req.method === "POST") {
|
||||||
|
// Manueller "ARIA reparieren"-Button — stuck OpenClaw-Runs aufloesen.
|
||||||
|
log("info", "server", "HTTP /api/doctor-fix — manueller Reparatur-Trigger");
|
||||||
|
dockerExec("aria-core", "openclaw doctor --fix 2>&1")
|
||||||
|
.then(out => {
|
||||||
|
const summary = (out || "").split("\n").filter(l => l.trim()).slice(-3).join(" | ");
|
||||||
|
broadcast({ type: "watchdog", status: "fixed", message: `Reparatur ausgefuehrt: ${summary || "OK"}` });
|
||||||
|
res.writeHead(200, { "Content-Type": "application/json" });
|
||||||
|
res.end(JSON.stringify({ ok: true, output: out }));
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
broadcast({ type: "watchdog", status: "error", message: `Reparatur fehlgeschlagen: ${err.message}` });
|
||||||
|
res.writeHead(500, { "Content-Type": "application/json" });
|
||||||
|
res.end(JSON.stringify({ ok: false, error: err.message }));
|
||||||
|
});
|
||||||
|
return;
|
||||||
} else if (req.url.startsWith("/shared/")) {
|
} else if (req.url.startsWith("/shared/")) {
|
||||||
// Dateien aus Shared Volume ausliefern (Bilder, Uploads)
|
// Dateien aus Shared Volume ausliefern (Bilder, Uploads)
|
||||||
const filePath = decodeURIComponent(req.url);
|
const filePath = decodeURIComponent(req.url);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ const ALLOWED_TYPES = new Set([
|
|||||||
"agent_activity", "cancel_request",
|
"agent_activity", "cancel_request",
|
||||||
"audio_pcm",
|
"audio_pcm",
|
||||||
"file_from_aria",
|
"file_from_aria",
|
||||||
|
"doctor_fix",
|
||||||
"xtts_delete_voice",
|
"xtts_delete_voice",
|
||||||
"voice_preload", "voice_ready",
|
"voice_preload", "voice_ready",
|
||||||
"stt_request", "stt_response",
|
"stt_request", "stt_response",
|
||||||
|
|||||||
Reference in New Issue
Block a user