Skip to content

feat(tui): scrollback-first TUI rewrite (tui_sb) - #441

Merged
lsdefine merged 3 commits into
lsdefine:mainfrom
YinZT1:feat/tui-scrollback
May 20, 2026
Merged

feat(tui): scrollback-first TUI rewrite (tui_sb)#441
lsdefine merged 3 commits into
lsdefine:mainfrom
YinZT1:feat/tui-scrollback

Conversation

@YinZT1

@YinZT1 YinZT1 commented May 20, 2026

Copy link
Copy Markdown
Contributor

Scrollback-first terminal UI — finalized output goes to the terminal's
real scrollback buffer (no alt-screen), so native Cmd+C / mouse select /
cross-page copy work cleanly. Only a small bottom region is live-redrawn
(streaming tail + status bar + input box).

Motivation: v2 (Textual-based) has ANSI escape leakage during streaming,
broken native copy due to alt-screen, race conditions between Textual's
event loop and agent's display_queue, and heavy deps (Textual+Tkinter+PIL).

  • Scrollback engine: completed turns are plain stdout lines; terminal
    handles scroll/search natively. Live region uses cursor-addressed
    repaints with exact row accounting (CJK cell-width aware, no
    soft-wrap drift).
  • Input box: multiline (Shift+Enter / bracketed paste), Ctrl+A/E/K/W
    readline bindings, history (up/down), @file attachment with glob.
  • Commands: /btw (side question via subagent), /review (inline code
    review), /rewind N (checkpoint restore), /continue (session restore),
    /clear, /cost, /verbose (tool call audit viewer in alt-screen overlay),
    /export, /stop.
  • Streaming: token-level display with tok/s counter; ANSI sanitization
    via renderer.py strips stray CSI/OSC before Rich parse.
  • Session persistence: state_store.py saves/loads conversation state;
    checkpoint_index.py indexes rewind points.
  • Protocol bridge: protocol.py yields typed StreamEvent/ToolCallEvent/
    AskUserEvent/DoneEvent from agent's display_queue — decouples UI from
    agent internals.
  • Zero extra deps beyond rich (already in project).
  • ~1500 LOC across 15 files (vs 4300 LOC single-file v2).

Files: frontends/tui_sb/ (new directory, 17 source files + README.md).

@YinZT1
YinZT1 force-pushed the feat/tui-scrollback branch 8 times, most recently from cfaf099 to 441c43d Compare May 20, 2026 08:34
YinZT1 and others added 3 commits May 20, 2026 17:34
Replace _history_lines (pre-rendered) with _blocks (source + kind) so
_repaint_screen can re-render every chip, banner, user panel at the
current width. \x1b[3J wipes scrollback on resize/Ctrl+L so the entire
conversation reflows, not just the visible viewport.

SIGWINCH delivery via self-pipe + select() — PEP 475 auto-retry on
os.read makes signal-driven InterruptedError unreliable under iTerm
split panes, so a dedicated pipe wakes the loop deterministically.

Streaming tracks a single _streaming_block whose source grows monotonically
through safe-position commits; mid-stream resize re-renders both the
committed source and the volatile live_tail.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
macOS Terminal.app quantises truecolor to its nearest 256 slot (so
#5e6ad2 lavender lands on slot 62 #5f5fd7, visibly more blue) and
renders \x1b[2m as a heavy multiply instead of a gentle blend, producing
the "blue border + heavy shadow" against iTerm's identical code.

Branch on TERM_PROGRAM: iTerm keeps its truecolor accent and \x1b[2m
dim; Apple_Terminal switches to pinned 256-slot accent (105) and an
explicit mid-gray (244) for dim. Box border (146) was already 256-slot
so it carries unchanged.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@lsdefine
lsdefine merged commit b48065b into lsdefine:main May 20, 2026
lsdefine added a commit that referenced this pull request Jul 23, 2026
feat(tui): scrollback-first TUI rewrite (tui_sb)
Imzl-zl pushed a commit to Imzl-zl/GenericAgent that referenced this pull request Aug 5, 2026
feat(tui): scrollback-first TUI rewrite (tui_sb)
Imzl-zl pushed a commit to Imzl-zl/GenericAgent that referenced this pull request Aug 5, 2026
feat(tui): scrollback-first TUI rewrite (tui_sb)
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.

2 participants