Skip to content

fix(cli, render): Fix structured fence leaks and missing headers#603

Merged
JeanMertz merged 1 commit into
mainfrom
prr171
May 6, 2026
Merged

fix(cli, render): Fix structured fence leaks and missing headers#603
JeanMertz merged 1 commit into
mainfrom
prr171

Conversation

@JeanMertz
Copy link
Copy Markdown
Collaborator

Three related rendering bugs are addressed in TurnView and the TurnCoordinator:

  1. Unclosed structured fences. A conversation ending on a ChatResponse::Structured would print an opening ```json with no matching close. flush() only drained the chat sub-renderer; the structured renderer was left open. Content boundaries (begin_turn, render_user_request, render_chat_response, enter_tool_call, reconfigure) now each call structured.flush() before proceeding, and the top-level flush() (formerly flush_all()) closes both renderers. The old flush() (chat-only) is removed; flush_all() is renamed to flush().

  2. Missing assistant header after Continue-before-first-chunk. reset_for_continuation unconditionally set assistant_header_rendered = true, so if the user interrupted before any chunk arrived the flag was forced on and the resumed output had no ── jp … boundary. The flag is now left as-is; if no header had been emitted yet it stays false and the next assistant event renders one normally.

  3. Missing user header on Reply interrupt (live vs replay gap). When the user replied mid-stream, the new ChatRequest was pushed to the conversation but never rendered in live mode, so the terminal showed no ── alice … boundary. coordinator.rs now calls view.render_user_request() before pushing the event, matching what replay emits.

Three related rendering bugs are addressed in `TurnView` and the
`TurnCoordinator`:

1. **Unclosed structured fences.** A conversation ending on a
   `ChatResponse::Structured` would print an opening ` ```json ` with no
   matching close. `flush()` only drained the chat sub-renderer; the
   structured renderer was left open. Content boundaries (`begin_turn`,
   `render_user_request`, `render_chat_response`, `enter_tool_call`,
   `reconfigure`) now each call `structured.flush()` before proceeding,
   and the top-level `flush()` (formerly `flush_all()`) closes both
   renderers. The old `flush()` (chat-only) is removed; `flush_all()` is
   renamed to `flush()`.

2. **Missing assistant header after Continue-before-first-chunk.**
   `reset_for_continuation` unconditionally set
   `assistant_header_rendered = true`, so if the user interrupted before
   any chunk arrived the flag was forced on and the resumed output had
   no `── jp …` boundary. The flag is now left as-is; if no header had
   been emitted yet it stays `false` and the next assistant event
   renders one normally.

3. **Missing user header on Reply interrupt (live vs replay gap).** When
   the user replied mid-stream, the new `ChatRequest` was pushed to the
   conversation but never rendered in live mode, so the terminal showed
   no `── alice …` boundary. `coordinator.rs` now calls
   `view.render_user_request()` before pushing the event, matching what
   replay emits.

Signed-off-by: Jean Mertz <git@jeanmertz.com>
@JeanMertz JeanMertz merged commit 698ac5e into main May 6, 2026
13 checks passed
@JeanMertz JeanMertz deleted the prr171 branch May 6, 2026 13:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant