diff --git a/ui/src/components/transcript/RunTranscriptView.tsx b/ui/src/components/transcript/RunTranscriptView.tsx index 110fa7ac..05defa14 100644 --- a/ui/src/components/transcript/RunTranscriptView.tsx +++ b/ui/src/components/transcript/RunTranscriptView.tsx @@ -1,14 +1,11 @@ import { useEffect, useMemo, useState, type ReactNode } from "react"; import type { TranscriptEntry } from "../../adapters"; import { MarkdownBody } from "../MarkdownBody"; -import { cn, formatTokens, relativeTime } from "../../lib/utils"; +import { cn, formatTokens } from "../../lib/utils"; import { - Bot, - BrainCircuit, ChevronDown, ChevronRight, CircleAlert, - Info, TerminalSquare, User, Wrench, @@ -84,12 +81,6 @@ function stripMarkdown(value: string): string { ); } -function formatTimestamp(ts: string): string { - const date = new Date(ts); - if (Number.isNaN(date.getTime())) return ts; - return date.toLocaleTimeString("en-US", { hour12: false }); -} - function formatUnknown(value: unknown): string { if (typeof value === "string") return value; if (value === null || value === undefined) return ""; @@ -326,22 +317,10 @@ function normalizeTranscript(entries: TranscriptEntry[], streaming: boolean): Tr } function TranscriptDisclosure({ - icon, - label, - tone, - summary, - timestamp, defaultOpen, - compact, children, }: { - icon: typeof BrainCircuit; - label: string; - tone: "thinking" | "tool"; - summary: string; - timestamp: string; defaultOpen: boolean; - compact: boolean; children: ReactNode; }) { const [open, setOpen] = useState(defaultOpen); @@ -353,43 +332,20 @@ function TranscriptDisclosure({ } }, [defaultOpen, touched]); - const Icon = icon; - const borderTone = - tone === "thinking" - ? "border-amber-500/25 bg-amber-500/[0.07]" - : "border-cyan-500/25 bg-cyan-500/[0.07]"; - const iconTone = - tone === "thinking" - ? "text-amber-700 dark:text-amber-300" - : "text-cyan-700 dark:text-cyan-300"; - return ( -
+
- {open &&
{children}
} + {open &&
{children}
}
); } @@ -402,35 +358,16 @@ function TranscriptMessageBlock({ density: TranscriptDensity; }) { const isAssistant = block.role === "assistant"; - const Icon = isAssistant ? Bot : User; - const panelTone = isAssistant - ? "border-emerald-500/25 bg-emerald-500/[0.08]" - : "border-violet-500/20 bg-violet-500/[0.07]"; - const iconTone = isAssistant - ? "text-emerald-700 dark:text-emerald-300" - : "text-violet-700 dark:text-violet-300"; const compact = density === "compact"; return ( -
-
- - - - - {isAssistant ? "Assistant" : "User"} - - {formatTimestamp(block.ts)} - {block.streaming && ( - - - - - - Streaming - - )} -
+
+ {!isAssistant && ( +
+ + User +
+ )} {compact ? (
{truncate(stripMarkdown(block.text), 360)} @@ -440,6 +377,15 @@ function TranscriptMessageBlock({ {block.text} )} + {block.streaming && ( +
+ + + + + Streaming +
+ )}
); } @@ -451,21 +397,15 @@ function TranscriptThinkingBlock({ block: Extract; density: TranscriptDensity; }) { - const compact = density === "compact"; return ( - -
- {block.text} -
-
+ {block.text} +
); } @@ -485,57 +425,68 @@ function TranscriptToolCard({ : "Completed"; const statusTone = block.status === "running" - ? "border-cyan-500/25 bg-cyan-500/10 text-cyan-700 dark:text-cyan-300" + ? "text-cyan-700 dark:text-cyan-300" : block.status === "error" - ? "border-red-500/25 bg-red-500/10 text-red-700 dark:text-red-300" - : "border-emerald-500/25 bg-emerald-500/10 text-emerald-700 dark:text-emerald-300"; + ? "text-red-700 dark:text-red-300" + : "text-emerald-700 dark:text-emerald-300"; + const detailsClass = cn( + "space-y-3", + block.status === "error" && "rounded-xl border border-red-500/20 bg-red-500/[0.06] p-3", + ); return ( - -
-
- - {statusLabel} - - {block.toolUseId && ( - - {truncate(block.toolUseId, compact ? 24 : 40)} +
+
+ +
+
+ + {block.name} - )} -
-
-
-
- Input -
-
-              {formatToolPayload(block.input) || ""}
-            
+ + {statusLabel} + + {block.toolUseId && ( + + {truncate(block.toolUseId, compact ? 24 : 40)} + + )}
-
-
- Result -
-
-              {block.result ? formatToolPayload(block.result) : "Waiting for result..."}
-            
+
+ {block.status === "running" + ? summarizeToolInput(block.name, block.input, density) + : summarizeToolResult(block.result, block.isError, density)}
- + +
+
+
+
+ Input +
+
+                {formatToolPayload(block.input) || ""}
+              
+
+
+
+ Result +
+
+                {block.result ? formatToolPayload(block.result) : "Waiting for result..."}
+              
+
+
+
+
+
); } @@ -549,37 +500,34 @@ function TranscriptEventRow({ const compact = density === "compact"; const toneClasses = block.tone === "error" - ? "border-red-500/20 bg-red-500/[0.06] text-red-700 dark:text-red-300" + ? "rounded-xl border border-red-500/20 bg-red-500/[0.06] p-3 text-red-700 dark:text-red-300" : block.tone === "warn" - ? "border-amber-500/20 bg-amber-500/[0.06] text-amber-700 dark:text-amber-300" + ? "text-amber-700 dark:text-amber-300" : block.tone === "info" - ? "border-sky-500/20 bg-sky-500/[0.06] text-sky-700 dark:text-sky-300" - : "border-border/70 bg-background/70 text-foreground/75"; + ? "text-sky-700 dark:text-sky-300" + : "text-foreground/75"; return ( -
+
{block.tone === "error" ? ( ) : block.tone === "warn" ? ( ) : ( - + )}
{block.label} - - {compact ? relativeTime(block.ts) : formatTimestamp(block.ts)} -
{block.text}
{block.detail && ( -
+            
               {block.detail}
             
)} @@ -598,23 +546,16 @@ function RawTranscriptView({ }) { const compact = density === "compact"; return ( -
+
{entries.map((entry, idx) => (
- {formatTimestamp(entry.ts)} - + {entry.kind}