@@ -507,6 +513,11 @@
if (msg.type === 'state') { updateState(msg.state); return; }
if (msg.type === 'log') { addLog(msg.entry.level, msg.entry.source, msg.entry.message, msg.entry.ts); return; }
+ if (msg.type === 'agent_activity') {
+ updateThinkingIndicator(msg);
+ return;
+ }
+
if (msg.type === 'chat_final') {
addChat('received', msg.text, 'chat:final');
return;
@@ -883,6 +894,10 @@
return `
${match}
`;
});
const html = `${linked}
${escapeHtml(meta)} — ${new Date().toLocaleTimeString('de-DE')}
`;
+
+ // Thinking-Indikator ausblenden bei neuer Nachricht
+ updateThinkingIndicator({ activity: 'idle' });
+
// In beide Chat-Boxen schreiben (normal + Vollbild)
for (const box of [chatBox, document.getElementById('chat-box-fs')]) {
if (!box) continue;
@@ -930,6 +945,52 @@
if (e.key === 'Escape' && chatFullscreen) toggleChatFullscreen();
});
+ // ── Thinking-Indikator ─────────────────────────────
+ let thinkingTimeout = null;
+ const TOOL_LABELS = {
+ 'Bash': '\uD83D\uDDA5\uFE0F Shell-Befehl',
+ 'WebFetch': '\uD83C\uDF10 Webseite abrufen',
+ 'WebSearch': '\uD83D\uDD0D Suche',
+ 'Read': '\uD83D\uDCC4 Datei lesen',
+ 'Write': '\u270D\uFE0F Datei schreiben',
+ 'Edit': '\u270D\uFE0F Datei bearbeiten',
+ 'Grep': '\uD83D\uDD0D Code durchsuchen',
+ 'Glob': '\uD83D\uDCC1 Dateien suchen',
+ 'Agent': '\uD83E\uDD16 Sub-Agent',
+ };
+ function updateThinkingIndicator(msg) {
+ const indicators = [
+ document.getElementById('thinking-indicator'),
+ document.getElementById('thinking-indicator-fs'),
+ ];
+ const texts = [
+ document.getElementById('thinking-text'),
+ document.getElementById('thinking-text-fs'),
+ ];
+
+ if (msg.activity === 'idle') {
+ indicators.forEach(el => { if (el) el.style.display = 'none'; });
+ if (thinkingTimeout) { clearTimeout(thinkingTimeout); thinkingTimeout = null; }
+ return;
+ }
+
+ let label = 'ARIA denkt...';
+ if (msg.activity === 'tool' && msg.tool) {
+ label = TOOL_LABELS[msg.tool] || `\uD83D\uDD27 ${msg.tool}`;
+ } else if (msg.activity === 'assistant') {
+ label = 'ARIA schreibt...';
+ }
+
+ indicators.forEach(el => { if (el) el.style.display = 'block'; });
+ texts.forEach(el => { if (el) el.textContent = label; });
+
+ // Auto-Hide nach 2min (falls idle Event verpasst wird — ARIA arbeitet max 15min)
+ if (thinkingTimeout) clearTimeout(thinkingTimeout);
+ thinkingTimeout = setTimeout(() => {
+ indicators.forEach(el => { if (el) el.style.display = 'none'; });
+ }, 120000);
+ });
+
function openLightbox(mediaType, url) {
const lb = document.getElementById('lightbox');
if (mediaType === 'video') {
diff --git a/diagnostic/server.js b/diagnostic/server.js
index 0fb1d4e..95c6596 100644
--- a/diagnostic/server.js
+++ b/diagnostic/server.js
@@ -74,8 +74,8 @@ function pipelineStart(method, text) {
pipelineStartTime = Date.now();
if (pipelineTimeout) clearTimeout(pipelineTimeout);
pipelineTimeout = setTimeout(() => {
- if (pipelineActive) pipelineEnd(false, "Timeout — keine Antwort nach 60s");
- }, 60000);
+ if (pipelineActive) pipelineEnd(false, "Timeout — keine Antwort nach 10min");
+ }, 600000);
plog(`━━━ Pipeline Start: ${method} ━━━`);
plog(`Nachricht: "${text}"`);
}
@@ -319,10 +319,23 @@ function handleGatewayMessage(msg) {
if (event === "agent") {
const data = payload.data || {};
const delta = data.delta || "";
- if (delta && payload.stream === "assistant") {
+ const stream = payload.stream || "";
+
+ if (delta && stream === "assistant") {
broadcast({ type: "chat_delta", delta, payload });
}
- // agent Events nicht einzeln loggen (zu viele)
+
+ // Tool-Nutzung erkennen und broadcasten
+ if (stream === "tool_use" || data.type === "tool_use") {
+ const toolName = data.name || data.tool || payload.tool || "";
+ if (toolName) {
+ broadcast({ type: "agent_activity", activity: "tool", tool: toolName, data });
+ log("info", "gateway", `Tool: ${toolName}`);
+ }
+ }
+
+ // Genereller Activity-Heartbeat (ARIA denkt)
+ broadcast({ type: "agent_activity", activity: stream || "thinking" });
return;
}
@@ -338,6 +351,7 @@ function handleGatewayMessage(msg) {
log("info", "gateway", `ANTWORT: "${text.slice(0, 200)}"`);
if (pipelineActive) pipelineEnd(true, `"${text.slice(0, 120)}"`);
broadcast({ type: "chat_final", text, payload });
+ broadcast({ type: "agent_activity", activity: "idle" });
return;
}
diff --git a/issue.md b/issue.md
index 006a5f8..b56b77c 100644
--- a/issue.md
+++ b/issue.md
@@ -4,3 +4,4 @@ cache leeren, bilder werden nicht neu geladen beim antippen.
autoload geht nicht
wenn man auf das ohr zum hören klickt stürzt ab
aria liest die nachrichten nicht vor
+autoscroll geht doch noch nicht zur letzten nachricht
diff --git a/release.sh b/release.sh
index 68c2f62..e915378 100755
--- a/release.sh
+++ b/release.sh
@@ -58,17 +58,19 @@ echo -e "${GREEN}[1/5] Versionsnummern auf $VERSION setzen...${NC}"
sed -i "s/\"version\": \"[^\"]*\"/\"version\": \"$VERSION\"/" android/package.json
echo -e " ${GREEN}✓${NC} package.json → $VERSION"
-# build.gradle: versionName + versionCode (aus Major.Minor.Patch berechnen)
-MAJOR=$(echo "$VERSION" | cut -d. -f1)
-MINOR=$(echo "$VERSION" | cut -d. -f2)
-PATCH=$(echo "$VERSION" | cut -d. -f3)
-VERSION_CODE=$((MAJOR * 10000 + MINOR * 100 + PATCH))
+# build.gradle: versionName + versionCode (aus Version berechnen)
+# Unterstuetzt 3-stellig (1.2.3) und 4-stellig (0.0.1.7)
+IFS='.' read -ra VER_PARTS <<< "$VERSION"
+V1=${VER_PARTS[0]:-0}; V2=${VER_PARTS[1]:-0}; V3=${VER_PARTS[2]:-0}; V4=${VER_PARTS[3]:-0}
+VERSION_CODE=$((V1 * 1000000 + V2 * 10000 + V3 * 100 + V4))
+# Mindestens 1 (Android erfordert versionCode >= 1)
+[ "$VERSION_CODE" -lt 1 ] && VERSION_CODE=1
sed -i "s/versionName \"[^\"]*\"/versionName \"$VERSION\"/" android/android/app/build.gradle
sed -i "s/versionCode [0-9]*/versionCode $VERSION_CODE/" android/android/app/build.gradle
echo -e " ${GREEN}✓${NC} build.gradle → versionName $VERSION, versionCode $VERSION_CODE"
-# SettingsScreen: Anzeige-Version
-sed -i "s/Version [0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]* [^<]*/Version $VERSION /" android/src/screens/SettingsScreen.tsx
+# SettingsScreen: Anzeige-Version (beliebiges Versionsformat)
+sed -i "s/Version [0-9][0-9.]*[^<]*/Version $VERSION /" android/src/screens/SettingsScreen.tsx
echo -e " ${GREEN}✓${NC} SettingsScreen → Version $VERSION"
echo ""