1- import { useRenderer } from '@opentui/react'
1+ import { useRenderer , useTerminalDimensions } from '@opentui/react'
22import React , { useCallback , useEffect , useMemo , useRef , useState } from 'react'
33import { useShallow } from 'zustand/react/shallow'
4+ import stringWidth from 'string-width'
45
56import { AgentModeToggle } from './components/agent-mode-toggle'
67import { LoginScreen } from './components/login-screen'
@@ -91,8 +92,10 @@ export const App = ({
9192 hasInvalidCredentials : boolean | null
9293} ) => {
9394 const renderer = useRenderer ( )
95+ const { width : terminalWidth } = useTerminalDimensions ( )
9496 const scrollRef = useRef < ScrollBoxRenderable | null > ( null )
9597 const inputRef = useRef < InputRenderable | null > ( null )
98+ const separatorWidth = Math . max ( 0 , terminalWidth - 2 )
9699
97100 const themeName = useSystemThemeDetector ( )
98101 const theme = chatThemes [ themeName ]
@@ -172,6 +175,13 @@ export const App = ({
172175 } ) ) ,
173176 )
174177
178+ const agentToggleLabel = agentMode === 'FAST' ? 'FAST' : '💪 MAX'
179+ const agentTogglePadding = agentMode === 'FAST' ? 4 : 2 // paddingLeft + paddingRight inside the button
180+ const agentToggleGap = 2 // paddingLeft on the container box next to the input
181+ const estimatedToggleWidth =
182+ agentTogglePadding + agentToggleGap + stringWidth ( agentToggleLabel )
183+ const inputWidth = Math . max ( 1 , separatorWidth - estimatedToggleWidth )
184+
175185 const activeAgentStreamsRef = useRef < number > ( 0 )
176186 const isChainInProgressRef = useRef < boolean > ( isChainInProgress )
177187
@@ -614,7 +624,7 @@ export const App = ({
614624 messages,
615625 messageTree,
616626 topLevelMessages : virtualTopLevelMessages ,
617- availableWidth : renderer ?. width ?? 80 ,
627+ availableWidth : separatorWidth ,
618628 theme,
619629 markdownPalette,
620630 collapsedAgents,
@@ -733,14 +743,14 @@ export const App = ({
733743 { ' ' }
734744 { formatQueuedPreview (
735745 queuedMessages ,
736- Math . max ( 30 , renderer . width - 25 ) ,
746+ Math . max ( 30 , terminalWidth - 25 ) ,
737747 ) } { ' ' }
738748 </ span >
739749 ) }
740750 </ text >
741751 </ box >
742752 ) }
743- < Separator theme = { theme } width = { renderer . width } />
753+ < Separator theme = { theme } width = { separatorWidth } />
744754 { slashContext . active && slashSuggestionItems . length > 0 ? (
745755 < SuggestionMenu
746756 items = { slashSuggestionItems }
@@ -761,33 +771,40 @@ export const App = ({
761771 prefix = "@"
762772 />
763773 ) : null }
764- < MultilineInput
765- value = { inputValue }
766- onChange = { setInputValue }
767- onSubmit = { handleSubmit }
768- placeholder = "Share your thoughts and press Enter…"
769- focused = { inputFocused }
770- maxHeight = { 5 }
771- theme = { theme }
772- width = { renderer . width }
773- onKeyIntercept = { handleSuggestionMenuKey }
774- />
775- < Separator theme = { theme } width = { renderer . width } />
776774 < box
777775 style = { {
778776 flexDirection : 'row' ,
779- alignItems : 'center' ,
780- justifyContent : 'flex-end' ,
777+ alignItems : 'flex-start' ,
781778 width : '100%' ,
782- paddingTop : 1 ,
783779 } }
784780 >
785- < AgentModeToggle
786- mode = { agentMode }
787- theme = { theme }
788- onToggle = { toggleAgentMode }
789- />
781+ < box style = { { flexGrow : 1 } } >
782+ < MultilineInput
783+ value = { inputValue }
784+ onChange = { setInputValue }
785+ onSubmit = { handleSubmit }
786+ placeholder = "Share your thoughts and press Enter…"
787+ focused = { inputFocused }
788+ maxHeight = { 5 }
789+ theme = { theme }
790+ width = { inputWidth }
791+ onKeyIntercept = { handleSuggestionMenuKey }
792+ />
793+ </ box >
794+ < box
795+ style = { {
796+ flexShrink : 0 ,
797+ paddingLeft : 2 ,
798+ } }
799+ >
800+ < AgentModeToggle
801+ mode = { agentMode }
802+ theme = { theme }
803+ onToggle = { toggleAgentMode }
804+ />
805+ </ box >
790806 </ box >
807+ < Separator theme = { theme } width = { separatorWidth } />
791808 </ box >
792809 </ box >
793810 )
0 commit comments