fix(tui): hide empty reasoning summaries (#31652)

## Why

Reasoning summaries can contain an empty HTML comment placeholder, `<!--
-->`, when a generated summary part has no prose. The TUI treated that
placeholder as visible summary content, so it leaked into both the
completed conversation history and persisted transcript. Multi-part
empty summaries could also leave later generated status headings visible
as orphaned transcript content.

## What

- Strip the empty reasoning-summary placeholder at the shared
`ReasoningSummaryCell` boundary.
- Suppress the cell when removing placeholders leaves only generated
bold status headings.
- Cover the multi-part placeholder-only shape with a rendering
regression test for both normal history and transcript output.

## How to Test

1. Start Codex TUI with reasoning summaries visible, for example with
`hide_agent_reasoning = false` and `model_reasoning_summary =
"detailed"`.
2. Run a turn that receives an empty generated reasoning-summary part.
3. Confirm that the in-progress status heading may appear while the turn
is running, but the completed history and transcript contain neither
literal `<!-- -->` tokens nor orphaned reasoning headings.
4. Confirm that a reasoning summary with actual prose still renders
normally.

The model output is nondeterministic, so the targeted regression covers
the exact multi-part placeholder shape from the report:

- `just test -p codex-tui
reasoning_summary_block_hides_empty_html_comment_parts`
This commit is contained in:
Felipe Coury authored and GitHub committed 2026-07-09 16:27:50 +00:00
1 parent 8dc77faf51
commit f46b53bd85
11 files changed
+286 -72

No files matched your search

+11 -6
View File
@@ -113,13 +113,18 @@ impl ChatWidget {
summary, content, ..
} => {
if from_replay {
for delta in summary {
self.on_agent_reasoning_delta(delta);
}
if self.config.show_raw_agent_reasoning {
for delta in content {
self.on_agent_reasoning_delta(delta);
let reasoning_parts = summary.into_iter().chain(
self.config
.show_raw_agent_reasoning
.then_some(content)
.into_iter()
.flatten(),
);
for (index, delta) in reasoning_parts.enumerate() {
if index > 0 {
self.on_reasoning_section_break();
}
self.on_agent_reasoning_delta(delta);
}
}
self.on_agent_reasoning_final();