From 5c54b9b9e37e7400bc95b2ff66327c19f9d76d0b Mon Sep 17 00:00:00 2001 From: Bruno Deanoz Date: Sun, 21 Jun 2026 18:40:19 +0200 Subject: [PATCH] fix: rewrite ToolEventsBlock to match web frontend logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Parse tool events into thinking/analyzing/inProgress/completed states instead of showing all as generic "Tool" rows. Handles type "thinking" (shows "Verarbeitet…"), "analyzing" (shows filename), "start"/"end"/ "error" with proper icons and elapsed time. Empty/thinking-only events no longer show a confusing wrench icon. --- .../java/dev/kaizen/app/chat/StreamBlocks.kt | 96 +++++++++++-------- app/src/main/res/values-en/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + 3 files changed, 61 insertions(+), 39 deletions(-) diff --git a/app/src/main/java/dev/kaizen/app/chat/StreamBlocks.kt b/app/src/main/java/dev/kaizen/app/chat/StreamBlocks.kt index e5b81ad..af25bda 100644 --- a/app/src/main/java/dev/kaizen/app/chat/StreamBlocks.kt +++ b/app/src/main/java/dev/kaizen/app/chat/StreamBlocks.kt @@ -26,7 +26,9 @@ import androidx.compose.material.icons.rounded.ExpandLess import androidx.compose.material.icons.rounded.ExpandMore import androidx.compose.material.icons.rounded.Language import androidx.compose.material.icons.rounded.Psychology +import androidx.compose.material.icons.rounded.AutoAwesome import androidx.compose.material.icons.rounded.Build +import androidx.compose.material.icons.rounded.Description import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -45,8 +47,10 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import dev.kaizen.app.net.SearchSource import dev.kaizen.app.net.ToolEvent +import dev.kaizen.app.R import dev.kaizen.app.ui.shape.KaizenShapes import dev.kaizen.app.ui.theme.LocalKaizenAccent +import androidx.compose.ui.res.stringResource @Composable fun ReasoningBlock(reasoning: String, streaming: Boolean = false) { @@ -103,52 +107,66 @@ fun ToolEventsBlock(tools: List, streaming: Boolean = false) { val cs = MaterialTheme.colorScheme val isDark = isSystemInDarkTheme() val accent = LocalKaizenAccent.current - val bg = if (isDark) Color.White.copy(alpha = 0.04f) else Color.Black.copy(alpha = 0.02f) - val borderColor = if (isDark) Color.White.copy(alpha = 0.06f) else Color.Black.copy(alpha = 0.04f) - Column( - Modifier - .fillMaxWidth() - .clip(KaizenShapes.sm) - .background(bg) - .border(1.dp, borderColor, KaizenShapes.sm) - .padding(horizontal = 12.dp, vertical = 8.dp), - verticalArrangement = Arrangement.spacedBy(4.dp), - ) { - tools.forEach { tool -> + val completed = mutableListOf() + val inProgress = mutableListOf() + val seen = mutableSetOf() + var thinking = false + var analyzing: String? = null + + for (ev in tools) { + when (ev.type) { + "thinking" -> { thinking = true; analyzing = null } + "analyzing" -> { analyzing = ev.name; thinking = false } + "start" -> { + analyzing = null; thinking = false + if (ev.name !in seen) { seen.add(ev.name); inProgress.add(ev.name) } + } + "end", "error" -> { + inProgress.remove(ev.name) + completed.add(ev) + } + } + } + + val hasContent = analyzing != null || thinking || completed.isNotEmpty() || inProgress.isNotEmpty() + if (!hasContent) return + + Column(verticalArrangement = Arrangement.spacedBy(4.dp)) { + if (analyzing != null) { Row(verticalAlignment = Alignment.CenterVertically) { - val icon = when (tool.type) { - "end" -> Icons.Rounded.Check - "error" -> Icons.Rounded.Error - else -> Icons.Rounded.Build - } - val tint = when (tool.type) { - "end" -> Color(0xFF10B981) - "error" -> Color(0xFFEF4444) - else -> accent.primary - } + Icon(Icons.Rounded.Description, null, tint = accent.primary.copy(alpha = 0.6f), modifier = Modifier.size(14.dp)) + Spacer(Modifier.width(6.dp)) + Text(stringResource(R.string.stream_tool_analyzing, analyzing!!), color = cs.onSurfaceVariant.copy(alpha = 0.6f), fontSize = 12.sp) + } + } + if (thinking && analyzing == null && completed.isEmpty() && inProgress.isEmpty()) { + Row(verticalAlignment = Alignment.CenterVertically) { + Icon(Icons.Rounded.AutoAwesome, null, tint = accent.primary.copy(alpha = 0.6f), modifier = Modifier.size(14.dp)) + Spacer(Modifier.width(6.dp)) + Text(stringResource(R.string.stream_tool_thinking), color = cs.onSurfaceVariant.copy(alpha = 0.6f), fontSize = 12.sp) + } + } + completed.forEach { tool -> + Row(verticalAlignment = Alignment.CenterVertically) { + val icon = if (tool.type == "error") Icons.Rounded.Error else Icons.Rounded.Check + val tint = if (tool.type == "error") Color(0xFFEF4444) else Color(0xFF10B981) Icon(icon, null, tint = tint, modifier = Modifier.size(14.dp)) - Spacer(Modifier.width(8.dp)) - Text( - tool.name.ifEmpty { "Tool" }, - color = cs.onBackground, - fontSize = 13.sp, - fontWeight = FontWeight.Medium, - ) + Spacer(Modifier.width(6.dp)) + Text(tool.name, color = cs.onSurfaceVariant.copy(alpha = 0.6f), fontSize = 12.sp) if (tool.elapsed != null) { - Spacer(Modifier.width(6.dp)) - Text( - "${tool.elapsed}ms", - color = cs.onSurfaceVariant.copy(alpha = 0.5f), - fontSize = 11.sp, - ) - } - if (tool.error != null) { - Spacer(Modifier.width(6.dp)) - Text(tool.error, color = Color(0xFFEF4444), fontSize = 11.sp, maxLines = 1, overflow = TextOverflow.Ellipsis) + Spacer(Modifier.width(4.dp)) + Text("${tool.elapsed}ms", color = cs.onSurfaceVariant.copy(alpha = 0.35f), fontSize = 11.sp) } } } + inProgress.forEach { name -> + Row(verticalAlignment = Alignment.CenterVertically) { + Icon(Icons.Rounded.Build, null, tint = accent.primary.copy(alpha = 0.6f), modifier = Modifier.size(14.dp)) + Spacer(Modifier.width(6.dp)) + Text(name, color = cs.onSurfaceVariant.copy(alpha = 0.7f), fontSize = 12.sp, fontWeight = FontWeight.Medium) + } + } } } diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index faebf64..eee8728 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -22,6 +22,8 @@ Reasoning Sources + Processing … + Analyzing %1$s … Session expired. Please sign in again. diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7866a1f..1a9b95e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -24,6 +24,8 @@ Gedankengang Quellen + Verarbeitet … + Analysiert %1$s … Sitzung abgelaufen. Bitte erneut anmelden.