@@ -816,6 +816,9 @@ export default function ChatView(props: ChatViewProps) {
816816 const attachmentPreviewHandoffTimeoutByMessageIdRef = useRef < Record < string , number > > ( { } ) ;
817817 const sendInFlightRef = useRef ( false ) ;
818818 const dragDepthRef = useRef ( 0 ) ;
819+ const inputHistoryRef = useRef < string [ ] > ( [ ] ) ;
820+ const historyIdxRef = useRef ( - 1 ) ;
821+ const historyDraftRef = useRef ( '' ) ;
819822 const terminalOpenByThreadRef = useRef < Record < string , boolean > > ( { } ) ;
820823 const setMessagesScrollContainerRef = useCallback ( ( element : HTMLDivElement | null ) => {
821824 messagesScrollRef . current = element ;
@@ -2509,6 +2512,14 @@ export default function ChatView(props: ChatViewProps) {
25092512 composerTerminalContextsRef . current = composerTerminalContexts ;
25102513 } , [ composerTerminalContexts ] ) ;
25112514
2515+ useEffect ( ( ) => {
2516+ inputHistoryRef . current = ( activeThread ?. messages ?? [ ] )
2517+ . filter ( ( m ) => m . role === 'user' && m . text . trim ( ) )
2518+ . map ( ( m ) => m . text . trim ( ) )
2519+ . reverse ( ) ;
2520+ historyIdxRef . current = - 1 ;
2521+ } , [ activeThread ?. id ] ) ; // eslint-disable-line react-hooks/exhaustive-deps
2522+
25122523 useEffect ( ( ) => {
25132524 if ( ! activeThread ?. id ) return ;
25142525 if ( activeThread . messages . length === 0 ) {
@@ -3178,6 +3189,7 @@ export default function ChatView(props: ChatViewProps) {
31783189 description : toastCopy . description ,
31793190 } ) ;
31803191 }
3192+ if ( promptForSend . trim ( ) ) { inputHistoryRef . current . unshift ( promptForSend . trim ( ) ) ; historyIdxRef . current = - 1 ; }
31813193 promptRef . current = "" ;
31823194 clearComposerDraftContent ( scopeThreadRef ( activeThread . environmentId , threadIdForSend ) ) ;
31833195 setComposerHighlightedItemId ( null ) ;
@@ -4066,6 +4078,18 @@ export default function ChatView(props: ChatViewProps) {
40664078 }
40674079 }
40684080
4081+ if ( key === 'ArrowUp' && inputHistoryRef . current . length > 0 && ! promptRef . current . includes ( '\n' ) ) {
4082+ if ( historyIdxRef . current === - 1 ) historyDraftRef . current = promptRef . current ;
4083+ historyIdxRef . current = Math . min ( historyIdxRef . current + 1 , inputHistoryRef . current . length - 1 ) ;
4084+ setPrompt ( inputHistoryRef . current [ historyIdxRef . current ] ! ) ;
4085+ return true ;
4086+ }
4087+ if ( key === 'ArrowDown' && historyIdxRef . current >= 0 ) {
4088+ const next = historyIdxRef . current - 1 ;
4089+ historyIdxRef . current = next ;
4090+ setPrompt ( next >= 0 ? inputHistoryRef . current [ next ] ! : historyDraftRef . current ) ;
4091+ return true ;
4092+ }
40694093 if ( key === "Enter" && ! event . shiftKey ) {
40704094 void onSend ( ) ;
40714095 return true ;
0 commit comments