From 9767b428147d9ca3105108c5981250d9c387f567 Mon Sep 17 00:00:00 2001 From: Phodal Huang Date: Thu, 4 Dec 2025 13:31:47 +0800 Subject: [PATCH 1/3] fix(renderer): simplify toolName formatting for file tools Remove file path from toolName and use only displayName for clarity. --- .../kotlin/cc/unitmesh/agent/render/RendererUtils.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/render/RendererUtils.kt b/mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/render/RendererUtils.kt index 41500be7d0..cec66a353d 100644 --- a/mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/render/RendererUtils.kt +++ b/mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/render/RendererUtils.kt @@ -18,13 +18,13 @@ object RendererUtils { return when (toolType) { ToolType.ReadFile -> ToolCallDisplayInfo( - toolName = "${params["path"] ?: "unknown"} - ${toolType.displayName}", + toolName = toolType.displayName, description = "file reader", details = "Reading file: ${params["path"] ?: "unknown"}" ) ToolType.WriteFile -> ToolCallDisplayInfo( - toolName = "${params["path"] ?: "unknown"} - ${toolType.displayName}", + toolName = toolType.displayName, description = "file writer", details = "Writing to file: ${params["path"] ?: "unknown"}" ) From b149c5142a5dd2c63b18c9bf4a21b6eb61a944f8 Mon Sep 17 00:00:00 2001 From: Phodal Huang Date: Thu, 4 Dec 2025 13:39:35 +0800 Subject: [PATCH 2/3] fix(process): use project basePath and update bubble default Use project.basePath for process execution and set terminal output bubble to collapsed by default. --- .../kotlin/cc/unitmesh/devti/sketch/run/ProcessExecutor.kt | 3 +-- .../idea/components/timeline/IdeaTerminalOutputBubble.kt | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/core/src/main/kotlin/cc/unitmesh/devti/sketch/run/ProcessExecutor.kt b/core/src/main/kotlin/cc/unitmesh/devti/sketch/run/ProcessExecutor.kt index b180d34918..1f01f0cf64 100644 --- a/core/src/main/kotlin/cc/unitmesh/devti/sketch/run/ProcessExecutor.kt +++ b/core/src/main/kotlin/cc/unitmesh/devti/sketch/run/ProcessExecutor.kt @@ -26,7 +26,6 @@ import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.progress.Task import com.intellij.openapi.progress.impl.BackgroundableProcessIndicator import com.intellij.openapi.project.Project -import com.intellij.openapi.project.ProjectManager import com.intellij.openapi.projectRoots.ProjectJdkTable import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.roots.ProjectRootManager @@ -126,7 +125,7 @@ class ProcessExecutor(val project: Project) { } private fun createProcess(shellScript: String): Process { - val basedir = ProjectManager.getInstance().openProjects.firstOrNull()?.basePath + val basedir = project.basePath val commandLine = PtyCommandLine() commandLine.withConsoleMode(false) commandLine.withUnixOpenTtyToPreserveOutputAfterTermination(true) diff --git a/mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/components/timeline/IdeaTerminalOutputBubble.kt b/mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/components/timeline/IdeaTerminalOutputBubble.kt index 052f95d2e1..79c813ac67 100644 --- a/mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/components/timeline/IdeaTerminalOutputBubble.kt +++ b/mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/components/timeline/IdeaTerminalOutputBubble.kt @@ -45,7 +45,7 @@ fun IdeaTerminalOutputBubble( modifier: Modifier = Modifier, project: Project? = null ) { - var expanded by remember { mutableStateOf(true) } + var expanded by remember { mutableStateOf(false) } Box( modifier = modifier From 094e8801e6a5d65306c57892816b8f6a951f1554 Mon Sep 17 00:00:00 2001 From: Phodal Huang Date: Thu, 4 Dec 2025 14:51:56 +0800 Subject: [PATCH 3/3] feat(ui): show dynamic output summary in tool call bubble Display tool output in the timeline bubble header, truncating with ellipsis and falling back to params if output is unavailable. UI now handles overflow without fixed truncation. --- .../components/timeline/IdeaToolCallBubble.kt | 52 +++++++++++++------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/components/timeline/IdeaToolCallBubble.kt b/mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/components/timeline/IdeaToolCallBubble.kt index 2f82880e33..8049142375 100644 --- a/mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/components/timeline/IdeaToolCallBubble.kt +++ b/mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/components/timeline/IdeaToolCallBubble.kt @@ -13,8 +13,10 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import cc.unitmesh.agent.render.TimelineItem @@ -68,7 +70,7 @@ fun IdeaToolCallBubble( .padding(8.dp) ) { Column { - // Header row: Status + Tool name + Summary + Expand icon + // Header row: Status + Tool name + Output (dynamic) + Time + Expand icon Row( modifier = Modifier .fillMaxWidth() @@ -99,17 +101,17 @@ fun IdeaToolCallBubble( } ) - // Tool name + // Tool name (fixed width, no shrink) Text( text = item.toolName, style = JewelTheme.defaultTextStyle.copy(fontWeight = FontWeight.Bold), - modifier = Modifier.weight(1f) + maxLines = 1 ) - // Summary (truncated params as summary) - if (hasParams && !expanded) { + // Output summary (dynamic width, fills remaining space) + if (hasOutput && !expanded) { Text( - text = "-> ${item.params.take(40)}${if (item.params.length > 40) "..." else ""}", + text = "-> ${item.output?.replace("\n", " ")?.trim() ?: ""}", style = JewelTheme.defaultTextStyle.copy( fontSize = 12.sp, color = when { @@ -118,8 +120,32 @@ fun IdeaToolCallBubble( else -> JewelTheme.globalColors.text.info } ), - maxLines = 1 + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier + .weight(1f) + .clipToBounds() ) + } else if (!expanded) { + // Show params as fallback when no output + if (hasParams) { + Text( + text = "-> ${item.params.replace("\n", " ").trim()}", + style = JewelTheme.defaultTextStyle.copy( + fontSize = 12.sp, + color = JewelTheme.globalColors.text.info + ), + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier + .weight(1f) + .clipToBounds() + ) + } else { + Spacer(modifier = Modifier.weight(1f)) + } + } else { + Spacer(modifier = Modifier.weight(1f)) } // Execution time (if available) @@ -376,14 +402,8 @@ private fun copyToClipboard(text: String) { /** * Format tool output for better readability. - * Returns output as-is to avoid breaking valid JSON/table formats. + * Returns output as-is to preserve valid JSON/table formats. + * No fixed truncation - UI handles overflow dynamically. */ -private fun formatToolOutput(output: String): String { - return when { - output.contains("|") -> output // Table format - output.contains("\n") -> output // Already formatted - output.length > 100 -> "${output.take(100)}..." // Truncate long single-line output - else -> output - } -} +private fun formatToolOutput(output: String): String = output