diff --git a/app/src/pages/conversations/components/ToolTimelineBlock.tsx b/app/src/pages/conversations/components/ToolTimelineBlock.tsx
index e19b80c90..e4545c925 100644
--- a/app/src/pages/conversations/components/ToolTimelineBlock.tsx
+++ b/app/src/pages/conversations/components/ToolTimelineBlock.tsx
@@ -12,6 +12,7 @@ import {
stripToolCallEnvelopes,
} from '../../../utils/toolTimelineFormatting';
import { parseWorkerThreadRef } from '../utils/workerThreadRef';
+import { BubbleMarkdown } from './AgentMessageBubble';
import { agentNameTone, AgentTimelineRail } from './AgentTimelineRail';
import { WorkerThreadRefCard, type WorkerThreadStatus } from './WorkerThreadRefCard';
@@ -99,20 +100,30 @@ function ToolCallRow({
}) {
const tone = toolCallTone(call.status);
return (
-
-
•
-
+
+
+ •
+
+
{call.displayName ?? formatToolName(call.toolName)}
+ {/* The contextual arg (path / recipient / query) can be long, so it
+ truncates to a single line and absorbs the row's spare width — the
+ full value stays available on hover — instead of wrapping into a
+ multi-line box that knocks the name and status out of alignment. */}
{call.detail ? (
-
+
{call.detail}
) : null}
{/* Status reads as a tinted "Done" / "Failed" / "Running" tag. */}
-
+
+
+
{call.elapsedMs != null && call.status !== 'running' ? (
-
+
{call.elapsedMs >= 1000
? `${(call.elapsedMs / 1000).toFixed(1)}s`
: `${call.elapsedMs}ms`}
@@ -132,14 +143,21 @@ function ToolCallRow({
*/
function ThoughtBlock({ text }: { text: string }) {
// Drop any inline `…` envelope the model emitted as
- // text — the call already shows as its own row — then flatten to one line.
- const clean = stripToolCallEnvelopes(text).replace(/\s+/g, ' ').trim();
+ // text — the call already shows as its own row. Keep the original newlines
+ // (only trim the ends) so the markdown renderer can see headings, lists,
+ // code fences and emphasis instead of flattening them to one plain line.
+ const clean = stripToolCallEnvelopes(text).trim();
if (!clean) return null;
+ // Rendered through the shared `BubbleMarkdown` so a thought formats markdown
+ // (bold, code, lists) — but scaled back to the original quiet thought look:
+ // small (12px) and light/muted, not the larger, darker agent-bubble prose.
+ // Descendant overrides on `.prose` beat the typography plugin's base sizing;
+ // code keeps its accent colour so inline `tool_names` still read clearly.
return (
- “{clean}”
+ className="my-0.5 break-words [&_.prose]:text-[12px] [&_.prose]:leading-relaxed [&_.prose]:text-content-muted [&_.prose_strong]:text-content-muted [&_.prose_:is(h1,h2,h3,h4,h5,h6)]:text-[12px] [&_.prose_:is(h1,h2,h3,h4,h5,h6)]:text-content-muted">
+
);
}