feat: [TBB] render streaming thinking blocks in chat turns (Thinking Part 3)#157
feat: [TBB] render streaming thinking blocks in chat turns (Thinking Part 3)#157ethanyhou wants to merge 5 commits into
Conversation
Adds the protocol surface for streaming model-thinking content from the language server: - Thinking record + ThinkingTypeAdapter (tolerates the server's mixed wire shape for ext: string delta or array of fragments). - ChatProgressValue.thinking field (with equals/hashCode/toString updates). - thinking/generateTitle JSON request (GenerateThinkingTitleParams/Response, server interface, connection wrapper). - Register ThinkingTypeAdapter.Factory in CopilotLauncherBuilder. No behavior change yet; UI plumbing follows in a stacked PR.
63c65c1 to
a55b8af
Compare
Renders the model's thinking deltas in a collapsible banner above each assistant turn (Copilot and subagent), backed by the LSP plumbing added in the previous PR. - ThinkingBlock: collapsible streaming banner (spinner -> generated title / cancelled), markdown body parsed into titled sections. - ThinkingSection: gutter dot + bold title + markdown body for each parsed section. - ThinkingTurnWidget: extends BaseTurnWidget, accumulates Thinking deltas, seals on first reply/agent round, fires thinking/generateTitle, and finalizes on cancel. - BaseTurnWidget: onChatMessageCancelled hook (default no-op) so subclasses can react to cancel events. - CopilotTurnWidget / SubagentTurnWidget / SubagentMessageBlock: re-parented onto ThinkingTurnWidget. - ChatContentViewer: routes thinking deltas to the active turn, seals before reply/agent rounds, seals at WorkDoneProgressKind.end. - ChatView: don't drop progress reports that carry only thinking content. - Messages / messages.properties: NLS keys for the in-progress / cancelled / expand / collapse strings. - dark.css / light.css: shared secondary-text color rule for the new ThinkingBlock selector.
a55b8af to
f7e9bd0
Compare
|
Why not directly merge into main? Then we can roll out it first in nightly |
|
@jdneo, because this PR is based on the branch |
I see. #156 is merged, pls update the pr to resolve conflict |
Co-authored-by: Copilot <copilot@github.com>
|
@jdneo Conflict is resolved. |
There was a problem hiding this comment.
Pull request overview
Adds UI support in the chat view to render streaming “thinking” deltas from the language server as collapsible banners on assistant/subagent turns, leveraging the LSP protocol surface introduced in the prior PR.
Changes:
- Introduces
ThinkingBlock/ThinkingSectionUI components and aThinkingTurnWidgetbase class to manage streaming, sealing, and cancellation. - Wires thinking deltas into turn processing (
ChatContentViewer,ChatView) and adds NLS + CSS styling for the new UI. - Updates Copilot/subagent turn widgets to use the new thinking-enabled base type.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/ThinkingTurnWidget.java | New base widget to accumulate thinking deltas, manage blocks, and seal/finalize with generated titles. |
| com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/ThinkingBlock.java | New collapsible “Thinking” banner UI with spinner, parsing into sections, and finalize/cancel visuals. |
| com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/ThinkingSection.java | New section widget (gutter + markdown body) used by ThinkingBlock during streaming. |
| com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/CopilotTurnWidget.java | Switches Copilot assistant turn to ThinkingTurnWidget base. |
| com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/SubagentTurnWidget.java | Switches subagent turn to ThinkingTurnWidget base. |
| com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/SubagentMessageBlock.java | Updates stored/returned subagent widget type to ThinkingTurnWidget. |
| com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/ChatContentViewer.java | Plumbs thinking deltas into turn rendering; seals thinking when reply/tool output begins and on turn end. |
| com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/ChatView.java | Avoids dropping “thinking-only” progress events by extending the empty-report guard. |
| com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/BaseTurnWidget.java | Adds cancel hook (onChatMessageCancelled) and clarifies reset behavior relative to thinking/subagent blocks. |
| com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/messages.properties | Adds localized strings for thinking banner titles/tooltips. |
| com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/Messages.java | Adds NLS fields for the new thinking banner strings. |
| com.microsoft.copilot.eclipse.ui/css/light.css | Extends secondary-text styling to thinking widgets in light theme. |
| com.microsoft.copilot.eclipse.ui/css/dark.css | Extends secondary-text styling to thinking widgets in dark theme. |
| if (hasRenderableOutput(value)) { | ||
| // Seal before appending the reply so the spinner stops and the title is fetched. | ||
| thinkingTurn.sealThinking(); |
There was a problem hiding this comment.
Q:
the thinking will be sealed when WorkDoneProgressKind.end comes, why do we need this logic?
There was a problem hiding this comment.
This is the mid-turn seal to kick off the title fetch and prevent subsequent thinking stream from being appended to the same block (a new block will be opened instead).
The WorkDoneProgressKind.end seal is a safety net for turns where the mid-turn seal never fired(ex. the model only produced thinking with no renderable output), so the block doesn't stay spinning forever.
Should be reviewed after: #156
Renders the model's thinking deltas in a collapsible banner above each assistant turn (Copilot and subagent), backed by the LSP plumbing added in the previous PR.
Test:
Chat using Claude or GPT advance model and let the model think.
On thinking, the spinner should rotate with thinking body appending (The subtitle is selectable, GPT model prefers it):
The thinking block should auto collapse once thinking is finished but user can click to check the thinking content:
Cancel an ongoing thinking:
If you are lucky, sometimes the GPT model will think twice a time. This is a mock: