Skip to content

Commit 8fbfbec

Browse files
committed
feat: inline single-line reasoning trace
1 parent b7aa9a6 commit 8fbfbec

File tree

2 files changed

+51
-13
lines changed

2 files changed

+51
-13
lines changed

src/browser/App.stories.tsx

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,34 @@ export const ActiveWorkspaceWithChat: Story = {
871871
},
872872
});
873873

874+
// Assistant quick update with a single-line reasoning trace to exercise inline display
875+
callback({
876+
id: "msg-9a",
877+
role: "assistant",
878+
parts: [
879+
{
880+
type: "reasoning",
881+
text: "Cache is warm already; rerunning the full suite would be redundant.",
882+
},
883+
{
884+
type: "text",
885+
text: "Cache is warm from the last test run, so I'll shift focus to documentation next.",
886+
},
887+
],
888+
metadata: {
889+
historySequence: 10,
890+
timestamp: STABLE_TIMESTAMP - 165000,
891+
model: "anthropic:claude-sonnet-4-5",
892+
usage: {
893+
inputTokens: 1200,
894+
outputTokens: 180,
895+
totalTokens: 1380,
896+
reasoningTokens: 20,
897+
},
898+
duration: 900,
899+
},
900+
});
901+
874902
// Assistant message with status_set tool to show agent status
875903
callback({
876904
id: "msg-10",
@@ -899,7 +927,7 @@ export const ActiveWorkspaceWithChat: Story = {
899927
},
900928
],
901929
metadata: {
902-
historySequence: 10,
930+
historySequence: 11,
903931
timestamp: STABLE_TIMESTAMP - 160000,
904932
model: "anthropic:claude-sonnet-4-5",
905933
usage: {
@@ -922,7 +950,7 @@ export const ActiveWorkspaceWithChat: Story = {
922950
},
923951
],
924952
metadata: {
925-
historySequence: 11,
953+
historySequence: 12,
926954
timestamp: STABLE_TIMESTAMP - 150000,
927955
},
928956
});
@@ -936,7 +964,7 @@ export const ActiveWorkspaceWithChat: Story = {
936964
workspaceId: workspaceId,
937965
messageId: "msg-12",
938966
model: "anthropic:claude-sonnet-4-5",
939-
historySequence: 12,
967+
historySequence: 13,
940968
});
941969

942970
// Send reasoning delta

src/browser/components/Messages/ReasoningMessage.tsx

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ export const ReasoningMessage: React.FC<ReasoningMessageProps> = ({ message, cla
1616

1717
const content = message.content;
1818
const isStreaming = message.isStreaming;
19+
const trimmedContent = content?.trim() ?? "";
20+
const hasContent = trimmedContent.length > 0;
21+
// OpenAI models often emit terse, single-line traces; surface them inline instead of hiding behind the label.
22+
const isSingleLineTrace = !isStreaming && hasContent && !/[\r\n]/.test(trimmedContent);
23+
const isCollapsible = !isStreaming && hasContent && !isSingleLineTrace;
1924

2025
// Auto-collapse when streaming ends
2126
useEffect(() => {
@@ -25,9 +30,11 @@ export const ReasoningMessage: React.FC<ReasoningMessageProps> = ({ message, cla
2530
}, [isStreaming]);
2631

2732
const toggleExpanded = () => {
28-
if (!isStreaming) {
29-
setIsExpanded(!isExpanded);
33+
if (!isCollapsible) {
34+
return;
3035
}
36+
37+
setIsExpanded(!isExpanded);
3138
};
3239

3340
// Render appropriate content based on state
@@ -55,24 +62,27 @@ export const ReasoningMessage: React.FC<ReasoningMessageProps> = ({ message, cla
5562
>
5663
<div
5764
className={cn(
58-
"flex cursor-pointer items-center justify-between gap-2 select-none",
59-
isExpanded && "mb-1.5"
65+
"flex items-center justify-between gap-2 select-none",
66+
isCollapsible && "cursor-pointer",
67+
isExpanded && !isSingleLineTrace && "mb-1.5"
6068
)}
61-
onClick={toggleExpanded}
69+
onClick={isCollapsible ? toggleExpanded : undefined}
6270
>
63-
<div className="text-thinking-mode flex items-center gap-1 text-xs opacity-80">
71+
<div className="text-thinking-mode flex flex-1 items-center gap-1 text-xs opacity-80 min-w-0">
6472
<span className="text-xs">
6573
<Lightbulb className={cn("size-3.5", isStreaming && "animate-pulse")} />
6674
</span>
67-
<span>
75+
<span className="truncate">
6876
{isStreaming ? (
6977
<Shimmer colorClass="var(--color-thinking-mode)">Thinking...</Shimmer>
78+
) : isSingleLineTrace ? (
79+
trimmedContent
7080
) : (
71-
"Thought..."
81+
"Thought"
7282
)}
7383
</span>
7484
</div>
75-
{!isStreaming && (
85+
{isCollapsible && (
7686
<span
7787
className={cn(
7888
"text-thinking-mode opacity-60 transition-transform duration-200 ease-in-out text-xs",
@@ -84,7 +94,7 @@ export const ReasoningMessage: React.FC<ReasoningMessageProps> = ({ message, cla
8494
)}
8595
</div>
8696

87-
{isExpanded && (
97+
{isExpanded && !isSingleLineTrace && (
8898
<div className="font-primary text-sm leading-6 italic opacity-85 [&_p]:mt-0 [&_p]:mb-1 [&_p:last-child]:mb-0">
8999
{renderContent()}
90100
</div>

0 commit comments

Comments
 (0)