Skip to content

feat(seer): collapse each response into one ThinkingBlock - #121972

Draft
natemoo-re wants to merge 3 commits into
nm/seer/tool-embedfrom
nm/seer/tool-group
Draft

feat(seer): collapse each response into one ThinkingBlock#121972
natemoo-re wants to merge 3 commits into
nm/seer/tool-embedfrom
nm/seer/tool-group

Conversation

@natemoo-re

@natemoo-re natemoo-re commented Aug 13, 2026

Copy link
Copy Markdown
Member

The Seer Explorer renders the flat block list 1:1, and thinking is drawn once per tool_use block — so a single assistant turn shows a wall of separate "Thinking" and tool-call rows (see the many stacked rows in the current UI).

This groups the transcript into responses and renders each as a single top-level ThinkingBlock:

  • Grouping (groupTranscript): a user block is its own segment; every maximal run of assistant/tool_use blocks after it is one response.
  • One ThinkingBlock per response (ResponseGroup): reasoning, intermediate narration, and every tool call are interleaved in run order inside the block. The block is active/expanded while streaming and collapses (with elapsed time) once done — matching ThinkingBlock's existing behavior.
  • Final answer hoisted out: the terminal assistant content renders as a sibling below the ThinkingBlock (its reasoning still lives inside). A direct answer with no reasoning renders with no ThinkingBlock at all.
  • Thinking prose stays gated on the showThinking toggle; tool calls always render.

Nested tool rows reuse the shared ToolCall wiring from the stack (ToolCallList is now exported).

@github-actions github-actions Bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Aug 13, 2026
@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Story previews

Preview the stories changed in this PR on the Vercel deployment:

Preview deployment: https://sentry-cmmvclial.sentry.dev

@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

📊 Type Coverage Diff

Metric Before After Delta
Coverage 94.36% 94.36% ±0%
Typed 134,733 134,823 🟢 +90
Untyped 8,058 8,064 🔴 +6
🔍 6 new type safety issues introduced

Non-null assertions (!) (6 new)

File Line Detail
static/app/views/seerExplorer/components/chat/responseGroup.tsx 101 records[i]!
static/app/views/seerExplorer/components/chat/responseGroup.tsx 111 labels[i]!
static/app/views/seerExplorer/components/chat/responseGroup.tsx 125 group[i]!
static/app/views/seerExplorer/components/chat/responseGroup.tsx 178 group[0]!
static/app/views/seerExplorer/components/chat/responseGroup.tsx 179 group[group.length - 1]!
static/app/views/seerExplorer/components/seerExplorerContent.tsx 606 segment.indices[0]!

This is informational only and does not block the PR.

The Explorer rendered the flat block list 1:1, and thinking was drawn once per
tool_use block, so a single assistant turn showed a wall of separate 'Thinking'
and tool-call rows.

Group the transcript into responses (a user block, then the run of
assistant/tool_use blocks that follows) and render each response as one top-level
ThinkingBlock: reasoning, intermediate narration, and every tool call interleaved
in run order inside it, with the final answer hoisted out as a sibling below.
Thinking prose stays gated on the showThinking toggle; a direct answer with no
reasoning renders without a ThinkingBlock.

Reuses the shared ToolCall wiring (now exported ToolCallList) for the nested tool
rows.
Title the per-response ThinkingBlock with the most recent thing the agent did
(the current tool while streaming) instead of a static "Thinking", so the block
summarizes itself and ThinkingBlock's decode animation replays as each step
lands. Prefers Code Mode call-record labels, falls back to a classic tool label
(skipping Code Mode's own non-descriptive tool names), and falls back to
"Thinking" before any tool runs. Never reads thinking_content, so the title never
leaks reasoning when the toggle is off.
// Wrap a value that would otherwise re-tokenize wrong (spaces, quotes, parens) so the assembled
// query parses back to the same filter.
function quoteValue(value: string): string {
return /[\s"()]/.test(value) ? `"${value.replace(/"/g, '\\"')}"` : value;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants