feat(protocol): carry reasoning, and show it in the desktop - #230
Merged
Conversation
The protocol carried reasoningTokens and nothing else, so DeepSeek's reasoner produced its most distinctive output and every client dropped it. The CLI got this in #218; the desktop could not, because there was nothing on the wire to render. Adds a `reasoning.delta` transient event behind a `reasoningDeltas` capability. Separate from `item.delta` rather than a flag on it: reasoning is not the answer, it is never persisted as a completed item, and a client that doesn't understand the type has to be able to drop it rather than accidentally render it as assistant text. The app-server forwards the agent loop's thinking_delta events; the desktop projects them onto the assistant turn as a distinct `reasoning` field — kept out of `text` precisely so it can be rendered as its own channel — and shows a collapsed `▸ thinking · N lines` block above the answer. Collapsed because reasoner output is long and is not the response; the line count is there because while a turn streams it is often the only thing to look at. VS Code and the LSP bridge forward protocol events unchanged, so they receive the new event without changes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The conflict boundary fell inside a describe(), so the file lost its closing braces and esbuild refused it. Same shape as the CSS seam in #220 — resolving a conflict by keeping both sides needs a structural check, not just "no markers left". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
oratis
force-pushed
the
feat/protocol-reasoning
branch
from
August 3, 2026 05:47
59e847e to
c929642
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The protocol carried
reasoningTokensand nothing else. DeepSeek's reasoner produced its most distinctive output and every client dropped it — the CLI got this in #218, but the desktop couldn't, because there was nothing on the wire to render.A new transient event, not a flag on
item.deltaSeparate on purpose: reasoning is not the answer, it is never persisted as a completed item, and a client that doesn't understand the type must be able to drop it rather than accidentally render it as assistant text. Gated by a new
reasoningDeltascapability, so a client can tell whether silence means "no reasoning" or "server too old".The app-server forwards the agent loop's
thinking_deltaevents. VS Code and the LSP bridge forward protocol events unchanged, so they receive it without any change.Desktop
Reasoning lands on the assistant turn as a distinct
reasoningfield — deliberately not concatenated intotext, which is how it would get lost again — and renders as a collapsed block above the answer:Collapsed because reasoner output is long and is not the response. The line count is in the summary because while a turn is streaming it is often the only thing there is to look at.
appendReasoningDeltacan open a turn on its own, since reasoning usually arrives before any answer text.Verification
4 unit tests on the stream reducer (opening a turn from reasoning alone, accumulating without touching the answer, starting a fresh turn after one finishes, no leakage into
text), the capability assertion updated in the protocol runtime test, and a Playwright case that asserts the block is present, collapsed, and reveals the reasoning on click. Screenshotted the rendered result.pnpm typecheck·lint·format:checkclean; protocol 24 · core 750/16 skipped · desktop 94 · server 41 · cli 208 · vscode 12 · lsp 13 · scripts 21;playwright test→ 6 passed.🤖 Generated with Claude Code