@@ -596,11 +596,13 @@ function updateContentLines() {
596596 chatState . contentLines = lines
597597}
598598
599- function renderChat ( ) {
600- // Clear screen and move cursor to top
601- process . stdout . write ( CLEAR_SCREEN )
602- process . stdout . write ( MOVE_CURSOR ( 1 , 1 ) )
599+ function padLine ( line : string , width : number ) : string {
600+ const visibleWidth = stringWidth ( line )
601+ const padding = Math . max ( 0 , width - visibleWidth )
602+ return line + ' ' . repeat ( padding )
603+ }
603604
605+ function renderChat ( ) {
604606 const metrics = getTerminalMetrics ( )
605607 const inputAreaHeight = calculateInputAreaHeight ( metrics )
606608 const maxContentLines = computeMaxContentLines ( metrics )
@@ -616,14 +618,22 @@ function renderChat() {
616618 // Don't reset userHasScrolled flag here - let user keep control
617619 }
618620
621+ // Build the complete screen content
622+ const screenLines : string [ ] = [ ]
623+
619624 // Display chat content
620625 const visibleLines = chatState . contentLines . slice (
621626 chatState . scrollOffset ,
622627 chatState . scrollOffset + maxContentLines ,
623628 )
624- process . stdout . write ( visibleLines . join ( '\n' ) )
625629
626- // Position input area and status at bottom of terminal
630+ // Pad visible lines to fill the available content area
631+ for ( let i = 0 ; i < maxContentLines ; i ++ ) {
632+ const line = visibleLines [ i ] || ''
633+ screenLines . push ( padLine ( line , metrics . width ) )
634+ }
635+
636+ // Add input area lines
627637 let currentLine = metrics . height - inputAreaHeight
628638
629639 // Display queued message preview if there are queued messages
@@ -639,26 +649,24 @@ function renderChat() {
639649 queueCount ,
640650 metrics ,
641651 )
642-
643- process . stdout . write ( MOVE_CURSOR ( currentLine , 1 ) )
644- process . stdout . write ( ' ' . repeat ( metrics . sidePadding ) + gray ( previewText ) )
652+ const queueLine = ' ' . repeat ( metrics . sidePadding ) + gray ( previewText )
653+ screenLines . push ( padLine ( queueLine , metrics . width ) )
645654 currentLine ++
646655 }
647656
648657 // Display separator line
649- process . stdout . write ( MOVE_CURSOR ( currentLine , 1 ) )
650- process . stdout . write (
658+ const separatorContent =
651659 ' ' . repeat ( metrics . sidePadding ) +
652- gray ( SEPARATOR_CHAR . repeat ( metrics . contentWidth ) ) ,
653- )
660+ gray ( SEPARATOR_CHAR . repeat ( metrics . contentWidth ) )
661+ screenLines . push ( padLine ( separatorContent , metrics . width ) )
654662 currentLine ++
655663
656664 // Show placeholder or user input
657665 if ( chatState . currentInput . length === 0 ) {
658666 // Show placeholder text
659667 const placeholder = `\x1b[2m${ gray ( PLACEHOLDER_TEXT ) } \x1b[22m`
660- process . stdout . write ( MOVE_CURSOR ( currentLine , 1 ) )
661- process . stdout . write ( ' ' . repeat ( metrics . sidePadding ) + placeholder )
668+ const placeholderContent = ' ' . repeat ( metrics . sidePadding ) + placeholder
669+ screenLines . push ( padLine ( placeholderContent , metrics . width ) )
662670 currentLine ++
663671 } else {
664672 // Show user input
@@ -668,15 +676,23 @@ function renderChat() {
668676 )
669677
670678 wrappedInputLines . forEach ( ( line , index ) => {
671- process . stdout . write ( MOVE_CURSOR ( currentLine , 1 ) )
672- process . stdout . write ( ' ' . repeat ( metrics . sidePadding ) + line )
679+ const inputContent = ' ' . repeat ( metrics . sidePadding ) + line
680+ screenLines . push ( padLine ( inputContent , metrics . width ) )
673681 currentLine ++
674682 } )
675683 }
676684
685+ // Pad remaining input area with empty lines, leaving one for the status bar
686+ while ( screenLines . length < metrics . height - 1 ) {
687+ screenLines . push ( ' ' . repeat ( metrics . width ) )
688+ }
689+
677690 // Status line with side padding - position at very bottom of screen
678- process . stdout . write ( MOVE_CURSOR ( metrics . height , 1 ) )
679- process . stdout . write ( ' ' . repeat ( metrics . sidePadding ) + gray ( STATUS_TEXT ) )
691+ const statusContent = ' ' . repeat ( metrics . sidePadding ) + gray ( STATUS_TEXT )
692+ screenLines . push ( padLine ( statusContent , metrics . width ) )
693+
694+ // Write the entire screen content at once
695+ process . stdout . write ( MOVE_CURSOR ( 1 , 1 ) + screenLines . join ( '\n' ) )
680696
681697 // Position the real cursor at input location
682698 positionRealCursor ( )
@@ -875,13 +891,6 @@ async function sendMessage(message: string, addToChat: boolean = true) {
875891 )
876892 } finally {
877893 chatState . isWaitingForResponse = false
878-
879- // Auto-focus the latest assistant message if it has subagents
880- const latestMessageId = findLatestAssistantMessageWithChildren ( )
881- if ( latestMessageId ) {
882- autoFocusLatestToggle ( )
883- }
884-
885894 renderChat ( )
886895
887896 // Process queued messages
0 commit comments