Skip to content

fix(tui): keep reasoning-only assistant turns visible on session resume#44402

Closed
AIalliAI wants to merge 1 commit into
NousResearch:mainfrom
AIalliAI:fix/44022-thinking-only-message-invisible
Closed

fix(tui): keep reasoning-only assistant turns visible on session resume#44402
AIalliAI wants to merge 1 commit into
NousResearch:mainfrom
AIalliAI:fix/44022-thinking-only-message-invisible

Conversation

@AIalliAI

Copy link
Copy Markdown
Contributor

Problem

On the desktop/TUI app, an assistant turn that produced only a thinking/reasoning block (extended-thinking turns, thinking-only recovery responses) disappears from the session view on resume/reload — while the turn is still in the transcript DB, so a new session can recall "what was said." This is the second symptom reported on #44022 (scorpio-dot's comment):

after 2 or 3 messages, mainly when the LLM starts to use its "thinking" block, the message disappears entirely. I tested by opening a new session and getting the agent to recall what was said in that session and it can see the messages but they are still invisible in the session.

Root cause

tui_gateway/server.py::_history_to_messages drops any message whose coerced text is empty before the assistant reasoning fields are attached:

if not content_text.strip():
    continue
msg = {"role": role, "text": content_text}
if role == "assistant":
    for key in ("reasoning", "reasoning_content", "reasoning_details", "codex_reasoning_items"):
        if key in m and m.get(key) is not None:
            msg[key] = m.get(key)   # <- never reached for a reasoning-only turn

A reasoning-only assistant turn has empty content but non-empty reasoning, so it is filtered out of the resume payload entirely. The turn is still persisted (gateway/session.py stores the reasoning fields), which is why recall from a fresh session works — the asymmetry is display-only, on the history→messages serialization path used by desktop/TUI resume and reload.

Fix

Keep an assistant turn when it carries any reasoning content, even with empty visible text, so the desktop's reasoning ("Thinking…") disclosure has something to render. Genuinely empty turns (no text, no reasoning, no tool calls) are still filtered out, and tool-call-only turns are unaffected.

Tests

  • test_history_to_messages_keeps_reasoning_only_assistant_turn — a reasoning-only turn survives with its reasoning field intact.
  • test_history_to_messages_still_drops_empty_assistant_without_reasoning — empty/whitespace turns with no reasoning are still dropped.

Both pass; full tests/test_tui_gateway_server.py shows no new failures (one pre-existing unrelated browser_manage failure present on main as well).

Scope

This is the display/serialization half of #44022's reports. The separate "resume fails with No LLM provider configured" provider-restore bug is addressed by #44062 (the complete restore-side fix) / #44151, and the persist-side by #44109. Using Refs #44022 rather than Fixes so the provider bug isn't auto-closed.

Refs #44022

🤖 Generated with Claude Code

A thinking-only assistant turn (reasoning present, empty visible text) is
persisted with its reasoning fields and stays recallable from the transcript,
but `_history_to_messages` dropped it as "empty" before its reasoning was
attached. On desktop/TUI resume or reload the turn therefore vanished from the
session view while the agent could still recall it from a fresh session --
exactly the "messages disappear when the LLM uses its thinking block, but a new
session can recall them" symptom reported on NousResearch#44022.

Keep an assistant turn when it carries reasoning, even with empty text, so the
desktop "Thinking…" disclosure has something to render. Genuinely empty turns
(no text, no reasoning, no tool calls) are still filtered out.

Refs NousResearch#44022

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@alt-glitch alt-glitch added type/bug Something isn't working comp/tui Terminal UI (ui-tui/ + tui_gateway/) P2 Medium — degraded but workaround exists labels Jun 11, 2026
@liuhao1024

Copy link
Copy Markdown
Contributor

Verification review — this PR looks correct.

Checked:

  • The has_reasoning guard correctly scopes to role == "assistant" — user turns with empty text still get filtered.
  • Empty-string reasoning ("") is falsy per Python, so any(m.get(key) for key in reasoning_keys) correctly skips it — the "genuinely empty" test confirms this.
  • The reasoning_keys tuple is hoisted above the skip check and reused below for the msg dict population — no duplication, no drift risk.
  • Edge case: content_text.strip() is empty but reasoning exists → kept. content_text.strip() is non-empty → kept (unchanged behavior). Both empty → dropped. All three paths are tested.

Looks good to merge.

@AIalliAI

Copy link
Copy Markdown
Contributor Author

Requesting maintainer review — this is ready to land from my side. Standalone fork CI is pending first-run approval here; the rollup branch in #44061 carrying this session's batch is fully green on upstream CI (all test shards, typecheck, e2e).

@teknium1

Copy link
Copy Markdown
Contributor

Merged via PR #45578 with your commit cherry-picked onto current main and authorship preserved.

Thanks for the focused reasoning-only display fix: Desktop/TUI resume now keeps assistant turns that contain reasoning/thinking fields even when visible text is empty.

#45578

@teknium1 teknium1 closed this Jun 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/tui Terminal UI (ui-tui/ + tui_gateway/) P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants