Skip to content

feat(tui): render think→reply pairs as independent cards - #32

Merged
jkyberneees merged 1 commit into
mainfrom
feat/tui-reply-pairs
Aug 22, 2026
Merged

feat(tui): render think→reply pairs as independent cards#32
jkyberneees merged 1 commit into
mainfrom
feat/tui-reply-pairs

Conversation

@jkyberneees

Copy link
Copy Markdown
Contributor

What

Long turns (e.g. "scan this repo") previously merged every response segment into one trailing answer card inside a single turn box, decoupling prose from the reasoning that produced it and producing unexpected interactions on long turns.

Response text is now a first-class timeline kind. Each token/token_delta stream opens — or extends — a reply segment, so every think→reply cycle renders its own raised card in chronological order:

⬡ odek  ⚡2.3s · ⌂12k · ⎇450
  … first thought
  ┌───────────────────────────┐
  │ Starting the scan.        │
  └───────────────────────────┘
  ▶ ✓ 🔍 search_files TODO
  … second thought
  ┌───────────────────────────┐
  │ Found one TODO.           │
  └───────────────────────────┘

Details

  • turnItem gains a reply kind with a per-segment glamour cache; resize re-renders segments.
  • appendReply keeps msg.content as the \n\n-joined blob (export/stats/hand-built compat); distinct cycles join with a blank line.
  • setTurnMarker attaches **Cancelled.** / interrupt / error markers to the last reply segment so they land on the final card.
  • closeTurn shared by finalize + session replay; replayTranscript now builds one thinking+reply pair per persisted record — resumed sessions render identically to live ones.
  • Turn-body assembly switched to an exact line slice: mouse hit-testing refs land on true header rows (fixes latent misalignment for steps after multiple work items).

Checklist

  • make fmt / vet / lint (0 issues) / race tests green
  • New regression tests (pairs_test.go): segmentation, marker attachment, residual-blob safety, hit-test accuracy

Long agentic turns merged every response segment into one trailing
card, decoupling prose from the reasoning that produced it. Response
text is now a first-class timeline kind: each token stream opens (or
extends) a reply segment, so every think→reply cycle renders its own
raised card in arrival order.

- appendReply keeps msg.content as the \n\n-joined blob for export,
  stats, and hand-built messages; setTurnMarker attaches cancel /
  interrupt / error markers to the last reply segment
- closeTurn (shared by finalize and session replay) caches a glamour
  render per segment; resize re-renders them
- replayTranscript builds one thinking+reply pair per persisted record,
  making resumed sessions identical to live turns
- turn body assembly switched to an exact line slice: mouse hit-test
  refs now land on true header rows (fixes latent misalignment for
  steps after multiple work items)
@jkyberneees
jkyberneees merged commit 689bfeb into main Aug 22, 2026
5 checks passed
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