FN-6339: combine consecutive thinking entries
Render grouped task-chat thinking logs as one continuous section. - Concatenate grouped thinking entry text before markdown rendering. - Keep the thinking disclosure summary stable as "Thinking" instead of showing entry counts. - Move spacing to tool groups and remove multi-thinking divider styling. - Cover the combined thinking rendering behavior in TaskChatTab tests. Files changed: packages/dashboard/app/components/TaskChatTab.css | 10 ++++----- packages/dashboard/app/components/TaskChatTab.tsx | 25 ++++++++++------------ .../app/components/__tests__/TaskChatTab.test.tsx | 23 +++++++++++++++++++- 3 files changed, 37 insertions(+), 21 deletions(-) Fusion-Task-Id: FN-6339 Fusion-Task-Lineage: 51a2ea27-a56a-4844-a27b-389d1d24613f
This commit is contained in:
@@ -147,10 +147,13 @@
|
||||
.task-chat-thinking-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-sm);
|
||||
padding: 0 var(--space-md) var(--space-md);
|
||||
}
|
||||
|
||||
.task-chat-tool-group-entries {
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.task-chat-tool-entry {
|
||||
min-width: 0;
|
||||
padding: var(--space-sm) var(--space-md);
|
||||
@@ -176,11 +179,6 @@
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.task-chat-thinking-markdown + .task-chat-thinking-markdown {
|
||||
padding-top: var(--space-sm);
|
||||
border-top: var(--btn-border-width) solid color-mix(in srgb, var(--color-warning) 24%, var(--border));
|
||||
}
|
||||
|
||||
.task-chat-entry-kicker {
|
||||
margin-bottom: var(--space-xs);
|
||||
color: var(--text-muted);
|
||||
|
||||
@@ -301,23 +301,20 @@ function TaskChatToolGroup({ entries }: { entries: AgentLogEntry[] }) {
|
||||
}
|
||||
|
||||
function TaskChatThinking({ entries }: { entries: AgentLogEntry[] }) {
|
||||
const combinedThinkingText = entries.map((entry) => entry.text).join("");
|
||||
|
||||
return (
|
||||
<details className="task-chat-thinking" data-testid="task-chat-thinking" open>
|
||||
<summary className="task-chat-thinking-summary">
|
||||
{entries.length === 1 ? "Thinking" : `${entries.length} thinking entries`}
|
||||
</summary>
|
||||
<summary className="task-chat-thinking-summary">Thinking</summary>
|
||||
<div className="task-chat-thinking-body">
|
||||
{entries.map((entry, entryIndex) => (
|
||||
<div
|
||||
className="markdown-body task-chat-markdown task-chat-thinking-markdown"
|
||||
data-testid="task-chat-entry-thinking"
|
||||
key={getEntryKey(entry, entryIndex)}
|
||||
>
|
||||
<ReactMarkdown remarkPlugins={[remarkGfm]} components={markdownComponents}>
|
||||
{entry.text}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
))}
|
||||
<div
|
||||
className="markdown-body task-chat-markdown task-chat-thinking-markdown"
|
||||
data-testid="task-chat-entry-thinking"
|
||||
>
|
||||
<ReactMarkdown remarkPlugins={[remarkGfm]} components={markdownComponents}>
|
||||
{combinedThinkingText}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
);
|
||||
|
||||
@@ -377,8 +377,9 @@ describe("TaskChatTab", () => {
|
||||
|
||||
const thinking = screen.getByTestId("task-chat-thinking");
|
||||
expect(thinking).toHaveAttribute("open");
|
||||
expect(screen.getByText("Thinking")).toBeVisible();
|
||||
expect(within(thinking).getByText("Thinking")).toBeVisible();
|
||||
expect(screen.getByText("I am considering options")).toBeVisible();
|
||||
expect(within(thinking).getAllByTestId("task-chat-entry-thinking")).toHaveLength(1);
|
||||
|
||||
await user.click(within(thinking).getByText("Thinking"));
|
||||
|
||||
@@ -386,6 +387,25 @@ describe("TaskChatTab", () => {
|
||||
expect(screen.getByText("I am considering options")).not.toBeVisible();
|
||||
});
|
||||
|
||||
it("renders consecutive thinking entries as one continuous section", () => {
|
||||
mockLogs([
|
||||
makeEntry({ agent: "triage", type: "thinking", text: "First" }),
|
||||
makeEntry({ agent: "triage", type: "thinking", text: "Second", timestamp: "2026-06-12T00:00:01.000Z" }),
|
||||
]);
|
||||
|
||||
render(<TaskChatTab task={makeTask()} active addToast={vi.fn()} />);
|
||||
|
||||
const thinking = screen.getByTestId("task-chat-thinking");
|
||||
const summary = thinking.querySelector("summary");
|
||||
expect(summary).toBeTruthy();
|
||||
expect(within(summary as HTMLElement).getByText("Thinking")).toBeVisible();
|
||||
expect(screen.queryByText("2 thinking entries")).not.toBeInTheDocument();
|
||||
const thinkingBlocks = within(thinking).getAllByTestId("task-chat-entry-thinking");
|
||||
expect(thinkingBlocks).toHaveLength(1);
|
||||
expect(thinkingBlocks[0]).toHaveTextContent("FirstSecond");
|
||||
expect(thinkingBlocks[0].nextElementSibling).toBeNull();
|
||||
});
|
||||
|
||||
it("creates distinct tool segments when text or thinking entries are interleaved", () => {
|
||||
mockLogs([
|
||||
makeEntry({ agent: "executor", type: "tool", text: "first tool", detail: "first detail" }),
|
||||
@@ -820,5 +840,6 @@ describe("TaskChatTab", () => {
|
||||
expect(css).toContain(".task-chat-tool-group-names");
|
||||
expect(css).toContain(".task-chat-tool-group-error-count");
|
||||
expect(css).toContain(".task-chat-thinking-summary");
|
||||
expect(css).not.toContain(".task-chat-thinking-markdown + .task-chat-thinking-markdown");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user