diff --git a/ui/src/components/ActiveAgentsPanel.tsx b/ui/src/components/ActiveAgentsPanel.tsx index cbbeb225..8712bfda 100644 --- a/ui/src/components/ActiveAgentsPanel.tsx +++ b/ui/src/components/ActiveAgentsPanel.tsx @@ -91,7 +91,7 @@ function AgentRunCard({ }) { return (
{run.issueId && ( -
+
-
+
; + } | { type: "event"; ts: string; @@ -266,6 +279,50 @@ function parseSystemActivity(text: string): { activityId?: string; name: string; }; } +function groupCommandBlocks(blocks: TranscriptBlock[]): TranscriptBlock[] { + const grouped: TranscriptBlock[] = []; + let pending: Array["items"][number]> = []; + let groupTs: string | null = null; + let groupEndTs: string | undefined; + + const flush = () => { + if (pending.length === 0 || !groupTs) return; + grouped.push({ + type: "command_group", + ts: groupTs, + endTs: groupEndTs, + items: pending, + }); + pending = []; + groupTs = null; + groupEndTs = undefined; + }; + + for (const block of blocks) { + if (block.type === "tool" && isCommandTool(block.name, block.input)) { + if (!groupTs) { + groupTs = block.ts; + } + groupEndTs = block.endTs ?? block.ts; + pending.push({ + ts: block.ts, + endTs: block.endTs, + input: block.input, + result: block.result, + isError: block.isError, + status: block.status, + }); + continue; + } + + flush(); + grouped.push(block); + } + + flush(); + return grouped; +} + function normalizeTranscript(entries: TranscriptEntry[], streaming: boolean): TranscriptBlock[] { const blocks: TranscriptBlock[] = []; const pendingToolBlocks = new Map>(); @@ -432,7 +489,7 @@ function normalizeTranscript(entries: TranscriptEntry[], streaming: boolean): Tr }); } - return blocks; + return groupCommandBlocks(blocks); } function TranscriptMessageBlock({ @@ -503,9 +560,7 @@ function TranscriptToolCard({ }) { const [open, setOpen] = useState(block.status === "error"); const compact = density === "compact"; - const commandTool = isCommandTool(block.name, block.input); const parsedResult = parseStructuredToolResult(block.result); - const commandPreview = summarizeToolInput(block.name, block.input, density); const statusLabel = block.status === "running" ? "Running" @@ -531,9 +586,7 @@ function TranscriptToolCard({ : "text-cyan-600 dark:text-cyan-300", ); const summary = block.status === "running" - ? commandTool - ? commandPreview - : summarizeToolInput(block.name, block.input, density) + ? summarizeToolInput(block.name, block.input, density) : block.status === "completed" && parsedResult?.body ? truncate(parsedResult.body.split("\n")[0] ?? parsedResult.body, compact ? 84 : 140) : summarizeToolResult(block.result, block.isError, density); @@ -543,10 +596,8 @@ function TranscriptToolCard({
{block.status === "error" ? ( - ) : block.status === "completed" && !commandTool ? ( + ) : block.status === "completed" ? ( - ) : commandTool ? ( - ) : ( )} @@ -555,32 +606,13 @@ function TranscriptToolCard({ {block.name} - {!commandTool && ( - - {statusLabel} - - )} + + {statusLabel} +
-
- {commandTool ? ( - - {summary} - - ) : ( - - {summary} - - )} +
+ {summary}
- {commandTool && block.status !== "running" && ( -
- {block.status === "error" - ? "Command failed" - : parsedResult?.status === "completed" - ? "Command completed" - : statusLabel} -
- )}
+
+ {open && ( +
+ {block.items.map((item, index) => ( +
+
+ + + {summarizeToolInput("command_execution", item.input, density)} + +
+ {item.result && ( +
+                  {formatToolPayload(item.result)}
+                
+ )} +
+ ))} +
+ )} +
+ ); +} + function TranscriptActivityRow({ block, density, @@ -777,6 +935,7 @@ export function RunTranscriptView({ {block.type === "message" && } {block.type === "thinking" && } {block.type === "tool" && } + {block.type === "command_group" && } {block.type === "activity" && } {block.type === "event" && }
diff --git a/ui/src/pages/RunTranscriptUxLab.tsx b/ui/src/pages/RunTranscriptUxLab.tsx index 3885431a..80759cf9 100644 --- a/ui/src/pages/RunTranscriptUxLab.tsx +++ b/ui/src/pages/RunTranscriptUxLab.tsx @@ -60,7 +60,7 @@ function RunDetailPreview({ density: TranscriptDensity; }) { return ( -
+
@@ -97,7 +97,7 @@ function LiveWidgetPreview({ density: TranscriptDensity; }) { return ( -
+
Live Runs @@ -149,7 +149,7 @@ function DashboardPreview({ return (
-
+
{runTranscriptFixtureMeta.issueIdentifier} - {runTranscriptFixtureMeta.issueTitle}
-
+
-
+