Before submitting
Area
apps/server
Steps to reproduce
- Configure the Claude Agent provider (
claudeAgent) with launch args --thinking-display summarized. (This is currently required — see "Second, related gap" below.)
- Restart T3 Code, start a new thread on a thinking-capable Claude model (e.g. Opus 5) with Thinking enabled.
- Send a prompt that makes the model reason for a while.
- Watch the thread, then compare against
~/.t3/userdata/logs/provider/events.<session>.log.
Expected behavior
Thinking summaries stream into the thread, the same way Codex reasoning traces do today (the collapsible reasoning UI from #287 / #3853).
Actual behavior
Nothing renders. The data does reach the server: the provider log shows claude/stream_event/content_block_delta/thinking_delta notifications carrying non-empty thinking text, and they are silently dropped on the way to the UI.
Root cause, all in apps/server/src/provider/Layers/ClaudeAdapter.ts (line numbers pinned to 4f5834ba72c5905a318c00456dd21271b2fa9d6f):
-
content_block_start L2544-L2556 — only text blocks call ensureAssistantTextBlock. thinking blocks fall through to the early return at L2555, so they are never recorded in turnState.assistantTextBlocks.
-
content_block_delta L2403-L2413 — for thinking_delta the branch resolves assistantBlockEntry via context.turnState.assistantTextBlocks.get(event.index), which is therefore always undefined.
-
Emission L2425-L2429 — itemId is spread in conditionally, so the content.delta goes out with streamKind: "reasoning_text" but no itemId. The event is orphaned and the client has no item to render it into.
The stream-kind mapping itself is already correct — streamKindFromDeltaType (L1276-L1278) returns reasoning_text for thinking deltas, and RuntimeContentStreamKind accepts it. Only the item bookkeeping is missing.
Fix sketch: register thinking blocks in content_block_start (either a dedicated reasoning item or the existing assistant-block bookkeeping) so the reasoning_text deltas carry an itemId.
Second, related gap: the adapter never sets thinking.display in the SDK options, so --thinking-display is only reachable by hand-editing provider launch args. On Opus 5 / 4.8 / 4.7, Sonnet 5 and Fable 5 the API default is omitted, which streams thinking blocks with empty text — so even with the rendering fixed, users would still see nothing unless T3 requests display: "summarized" (ideally behind a UI toggle). Note the CLI also force-downgrades to omitted for non-interactive sessions unless the display was set explicitly, so passing the flag is what makes it stick.
Impact
Minor bug or occasional failure
Version or commit
0.0.31 (macOS). Code paths verified unchanged on main @ 4f5834b.
Environment
macOS (Darwin 25.5.0) · Claude Code CLI 2.1.223 · model claude-opus-5[1m] · effort xhigh
Logs or stack traces
Same thread, provider log, before vs. after adding the launch arg — counting only real {"type":"thinking_delta"} payloads:
17:35–17:45 ~200 thinking_delta "thinking": "" ← no --thinking-display (API default: omitted)
18:13–18:16 96 thinking_delta "thinking": "..." ← with --thinking-display summarized
Representative event from the second window (token redacted), which reaches the server and is then dropped:
{
"method": "claude/stream_event/content_block_delta/thinking_delta",
"provider": "claudeAgent",
"payload": {
"type": "stream_event",
"event": {
"type": "content_block_delta",
"index": 0,
"delta": { "type": "thinking_delta", "thinking": "Looking at the adapter, I see that when a thinking_delta arrives…" }
}
}
}
Workaround
Read the reasoning straight out of the provider log — it is all there, just not rendered:
tail -f ~/.t3/userdata/logs/provider/events.<session>.log \
| grep --line-buffered '"type":"thinking_delta"' \
| sed -u 's/.*"thinking":"//; s/","estimated_tokens.*//'
Investigated and filed by Claude Code (Opus 5) running as an agent inside T3 Code. The analysis and this write-up are mine, not the account holder's — they only pressed the button.
Before submitting
Area
apps/server
Steps to reproduce
claudeAgent) with launch args--thinking-display summarized. (This is currently required — see "Second, related gap" below.)~/.t3/userdata/logs/provider/events.<session>.log.Expected behavior
Thinking summaries stream into the thread, the same way Codex reasoning traces do today (the collapsible reasoning UI from #287 / #3853).
Actual behavior
Nothing renders. The data does reach the server: the provider log shows
claude/stream_event/content_block_delta/thinking_deltanotifications carrying non-emptythinkingtext, and they are silently dropped on the way to the UI.Root cause, all in
apps/server/src/provider/Layers/ClaudeAdapter.ts(line numbers pinned to4f5834ba72c5905a318c00456dd21271b2fa9d6f):content_block_startL2544-L2556 — onlytextblocks callensureAssistantTextBlock.thinkingblocks fall through to the earlyreturnat L2555, so they are never recorded inturnState.assistantTextBlocks.content_block_deltaL2403-L2413 — forthinking_deltathe branch resolvesassistantBlockEntryviacontext.turnState.assistantTextBlocks.get(event.index), which is therefore alwaysundefined.Emission L2425-L2429 —
itemIdis spread in conditionally, so thecontent.deltagoes out withstreamKind: "reasoning_text"but noitemId. The event is orphaned and the client has no item to render it into.The stream-kind mapping itself is already correct —
streamKindFromDeltaType(L1276-L1278) returnsreasoning_textfor thinking deltas, andRuntimeContentStreamKindaccepts it. Only the item bookkeeping is missing.Fix sketch: register
thinkingblocks incontent_block_start(either a dedicated reasoning item or the existing assistant-block bookkeeping) so thereasoning_textdeltas carry anitemId.Second, related gap: the adapter never sets
thinking.displayin the SDK options, so--thinking-displayis only reachable by hand-editing provider launch args. On Opus 5 / 4.8 / 4.7, Sonnet 5 and Fable 5 the API default isomitted, which streamsthinkingblocks with empty text — so even with the rendering fixed, users would still see nothing unless T3 requestsdisplay: "summarized"(ideally behind a UI toggle). Note the CLI also force-downgrades toomittedfor non-interactive sessions unless the display was set explicitly, so passing the flag is what makes it stick.Impact
Minor bug or occasional failure
Version or commit
0.0.31 (macOS). Code paths verified unchanged on
main@4f5834b.Environment
macOS (Darwin 25.5.0) · Claude Code CLI 2.1.223 · model
claude-opus-5[1m]· effortxhighLogs or stack traces
Same thread, provider log, before vs. after adding the launch arg — counting only real
{"type":"thinking_delta"}payloads:Representative event from the second window (token redacted), which reaches the server and is then dropped:
{ "method": "claude/stream_event/content_block_delta/thinking_delta", "provider": "claudeAgent", "payload": { "type": "stream_event", "event": { "type": "content_block_delta", "index": 0, "delta": { "type": "thinking_delta", "thinking": "Looking at the adapter, I see that when a thinking_delta arrives…" } } } }Workaround
Read the reasoning straight out of the provider log — it is all there, just not rendered:
Investigated and filed by Claude Code (Opus 5) running as an agent inside T3 Code. The analysis and this write-up are mine, not the account holder's — they only pressed the button.