From 573caaa681f48fae493c95fe517b3206affd10ba Mon Sep 17 00:00:00 2001 From: dullfig Date: Sun, 11 Jan 2026 15:30:53 -0800 Subject: [PATCH] Fix bottom detection - consider last 3 lines as "at bottom" - is_at_bottom() now checks if on last 3 lines (not exact end) - Page Down snaps to bottom when within 3 lines of end - Added scroll_to_bottom() helper method Co-Authored-By: Claude Opus 4.5 --- agentserver/console/tui_console.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/agentserver/console/tui_console.py b/agentserver/console/tui_console.py index b38a1cb..4e211a8 100644 --- a/agentserver/console/tui_console.py +++ b/agentserver/console/tui_console.py @@ -132,8 +132,14 @@ class OutputBuffer: ) def is_at_bottom(self) -> bool: - """Check if output is scrolled to bottom.""" - return self.buffer.cursor_position >= len(self.buffer.text) + """Check if output is scrolled to bottom (or near bottom).""" + doc = self.buffer.document + # Consider "at bottom" if on last 3 lines + return doc.cursor_position_row >= doc.line_count - 3 + + def scroll_to_bottom(self): + """Scroll to the very bottom.""" + self.buffer.cursor_position = len(self.buffer.text) def clear(self): """Clear output.""" @@ -232,12 +238,16 @@ class TUIConsole: @kb.add("pagedown") def handle_pagedown(event): - """Scroll output down a page.""" + """Scroll output down a page (snap to bottom if near end).""" buf = self.output.buffer doc = buf.document - new_row = min(doc.line_count - 1, doc.cursor_position_row + 20) - new_pos = doc.translate_row_col_to_index(new_row, 0) - buf.cursor_position = new_pos + new_row = doc.cursor_position_row + 20 + # Snap to bottom if within 3 lines of end + if new_row >= doc.line_count - 3: + self.output.scroll_to_bottom() + else: + new_pos = doc.translate_row_col_to_index(new_row, 0) + buf.cursor_position = new_pos @kb.add("c-home") def handle_ctrl_home(event): @@ -247,7 +257,7 @@ class TUIConsole: @kb.add("c-end") def handle_ctrl_end(event): """Scroll to bottom of output.""" - self.output.buffer.cursor_position = len(self.output.buffer.text) + self.output.scroll_to_bottom() # Output uses BufferControl for scrolling (not focusable - input keeps focus) output_control = BufferControl(