@@ -163,6 +163,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
163163 } ) ,
164164 )
165165 const autoApproveTimeoutRef = useRef < NodeJS . Timeout | null > ( null )
166+ const userRespondedRef = useRef < boolean > ( false )
166167 const [ currentFollowUpTs , setCurrentFollowUpTs ] = useState < number | null > ( null )
167168
168169 const clineAskRef = useRef ( clineAsk )
@@ -417,6 +418,14 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
417418 setExpandedRows ( { } )
418419 everVisibleMessagesTsRef . current . clear ( ) // Clear for new task
419420 setCurrentFollowUpTs ( null ) // Clear follow-up answered state for new task
421+
422+ // Clear any pending auto-approval timeout from previous task
423+ if ( autoApproveTimeoutRef . current ) {
424+ clearTimeout ( autoApproveTimeoutRef . current )
425+ autoApproveTimeoutRef . current = null
426+ }
427+ // Reset user response flag for new task
428+ userRespondedRef . current = false
420429 } , [ task ?. ts ] )
421430
422431 useEffect ( ( ) => {
@@ -496,11 +505,13 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
496505 } , [ ] )
497506
498507 const handleChatReset = useCallback ( ( ) => {
499- // Clear any pending auto-approval timeout to prevent race conditions
508+ // Clear any pending auto-approval timeout
500509 if ( autoApproveTimeoutRef . current ) {
501510 clearTimeout ( autoApproveTimeoutRef . current )
502511 autoApproveTimeoutRef . current = null
503512 }
513+ // Reset user response flag for new message
514+ userRespondedRef . current = false
504515
505516 // Only reset message-specific state, preserving mode.
506517 setInputValue ( "" )
@@ -519,16 +530,12 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
519530 text = text . trim ( )
520531
521532 if ( text || images . length > 0 ) {
533+ // Mark that user has responded - this prevents any pending auto-approvals
534+ userRespondedRef . current = true
535+
522536 if ( messagesRef . current . length === 0 ) {
523537 vscode . postMessage ( { type : "newTask" , text, images } )
524538 } else if ( clineAskRef . current ) {
525- // Clear auto-approval timeout FIRST to prevent race conditions
526- // This ensures the countdown timer is properly dismounted when users submit custom responses
527- if ( autoApproveTimeoutRef . current ) {
528- clearTimeout ( autoApproveTimeoutRef . current )
529- autoApproveTimeoutRef . current = null
530- }
531-
532539 if ( clineAskRef . current === "followup" ) {
533540 markFollowUpAsAnswered ( )
534541 }
@@ -581,6 +588,9 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
581588 // extension.
582589 const handlePrimaryButtonClick = useCallback (
583590 ( text ?: string , images ?: string [ ] ) => {
591+ // Mark that user has responded
592+ userRespondedRef . current = true
593+
584594 const trimmedInput = text ?. trim ( )
585595
586596 switch ( clineAsk ) {
@@ -625,6 +635,9 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
625635
626636 const handleSecondaryButtonClick = useCallback (
627637 ( text ?: string , images ?: string [ ] ) => {
638+ // Mark that user has responded
639+ userRespondedRef . current = true
640+
628641 const trimmedInput = text ?. trim ( )
629642
630643 if ( isStreaming ) {
@@ -1240,10 +1253,9 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
12401253
12411254 const handleSuggestionClickInRow = useCallback (
12421255 ( suggestion : SuggestionItem , event ?: React . MouseEvent ) => {
1243- // Clear auto-approval timeout to prevent race conditions when suggestion is clicked
1244- if ( autoApproveTimeoutRef . current ) {
1245- clearTimeout ( autoApproveTimeoutRef . current )
1246- autoApproveTimeoutRef . current = null
1256+ // Mark that user has responded if this is a manual click (not auto-approval)
1257+ if ( event ) {
1258+ userRespondedRef . current = true
12471259 }
12481260
12491261 // Mark the current follow-up question as answered when a suggestion is clicked
@@ -1280,11 +1292,8 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
12801292
12811293 // Handler for when FollowUpSuggest component unmounts
12821294 const handleFollowUpUnmount = useCallback ( ( ) => {
1283- // Clear the auto-approve timeout to prevent race conditions
1284- if ( autoApproveTimeoutRef . current ) {
1285- clearTimeout ( autoApproveTimeoutRef . current )
1286- autoApproveTimeoutRef . current = null
1287- }
1295+ // Mark that user has responded
1296+ userRespondedRef . current = true
12881297 } , [ ] )
12891298
12901299 const itemContent = useCallback (
@@ -1351,6 +1360,11 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
13511360 return
13521361 }
13531362
1363+ // Exit early if user has already responded
1364+ if ( userRespondedRef . current ) {
1365+ return
1366+ }
1367+
13541368 const autoApprove = async ( ) => {
13551369 if ( lastMessage ?. ask && isAutoApproved ( lastMessage ) ) {
13561370 // Special handling for follow-up questions
@@ -1367,11 +1381,14 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
13671381 if ( followUpData && followUpData . suggest && followUpData . suggest . length > 0 ) {
13681382 // Wait for the configured timeout before auto-selecting the first suggestion
13691383 await new Promise < void > ( ( resolve ) => {
1370- autoApproveTimeoutRef . current = setTimeout ( resolve , followupAutoApproveTimeoutMs )
1384+ autoApproveTimeoutRef . current = setTimeout ( ( ) => {
1385+ autoApproveTimeoutRef . current = null
1386+ resolve ( )
1387+ } , followupAutoApproveTimeoutMs )
13711388 } )
13721389
1373- // Check if timeout was cleared ( user responded manually)
1374- if ( ! autoApproveTimeoutRef . current ) {
1390+ // Check if user responded manually
1391+ if ( userRespondedRef . current ) {
13751392 return
13761393 }
13771394
@@ -1384,7 +1401,10 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
13841401 }
13851402 } else if ( lastMessage . ask === "tool" && isWriteToolAction ( lastMessage ) ) {
13861403 await new Promise < void > ( ( resolve ) => {
1387- autoApproveTimeoutRef . current = setTimeout ( resolve , writeDelayMs )
1404+ autoApproveTimeoutRef . current = setTimeout ( ( ) => {
1405+ autoApproveTimeoutRef . current = null
1406+ resolve ( )
1407+ } , writeDelayMs )
13881408 } )
13891409 }
13901410
0 commit comments