@@ -47,6 +47,7 @@ import { NoKeyOverlay } from './NoKeyOverlay';
47
47
import { useAutoAgentSelect } from './useAgentAutoSelect' ;
48
48
import { useOpenRouterModels } from './useOpenRouterModels' ;
49
49
import type { MentionItem } from '../../chunks/MarkdownEditor/AIChatInput/types' ;
50
+ import { flushSync } from 'react-dom' ;
50
51
51
52
const AIChatInput = React . lazy (
52
53
( ) => import ( '../../chunks/MarkdownEditor/AIChatInput/AsyncAIChatInput' ) ,
@@ -82,6 +83,7 @@ interface SimpleAIChatProps {
82
83
React . SetStateAction < AIMessageContext [ ] >
83
84
> ;
84
85
onDeleteMessage : ( message : AIChatDisplayMessage ) => void ;
86
+ onRegenerateMessage : ( message : AIChatDisplayMessage ) => Promise < void > ;
85
87
}
86
88
87
89
export const SimpleAIChat : React . FC <
@@ -94,6 +96,7 @@ export const SimpleAIChat: React.FC<
94
96
setExternalContextItems,
95
97
onNewMessage,
96
98
onDeleteMessage,
99
+ onRegenerateMessage,
97
100
children,
98
101
} ) => {
99
102
const abortSignalRef = useRef < AbortController > ( null ) ;
@@ -140,11 +143,12 @@ export const SimpleAIChat: React.FC<
140
143
const [ tokensUsed , setTokensUsed ] = useState < [ number , number ] > ( [ 0 , 0 ] ) ;
141
144
142
145
const getToolsForAgent = useTools ( ) ;
143
- const [ hasToolResultFollowUp , setHasToolResultFollowUp ] = useState ( false ) ;
144
146
145
147
const [ agentConfigOpen , setAgentConfigOpen ] = useState ( false ) ;
146
148
const pickAgent = useAutoAgentSelect ( ) ;
147
149
150
+ const [ shouldRegenMessages , setShouldRegenMessages ] = useState ( false ) ;
151
+
148
152
const normalizeAndApplyContext = useProcessMessages ( ) ;
149
153
150
154
const { tools : atomicTools } = useAtomicMCPTools ( {
@@ -225,7 +229,12 @@ export const SimpleAIChat: React.FC<
225
229
setUserSelectedContextItems ( newContextItems ) ;
226
230
} ;
227
231
228
- const sendMessage = async ( isFollowUp = false ) => {
232
+ const sendMessage = async ( {
233
+ regenerate = false ,
234
+ } : {
235
+ /** Whether to regenerate the response */
236
+ regenerate ?: boolean ;
237
+ } = { } ) => {
229
238
if ( readonly ) {
230
239
toast . error ( 'You do not have the permissions to edit this chat.' ) ;
231
240
@@ -281,21 +290,28 @@ export const SimpleAIChat: React.FC<
281
290
...userSelectedContextItems ,
282
291
] ;
283
292
284
- if ( ! isFollowUp ) {
293
+ if ( regenerate ) {
294
+ messagesToUse = messages ;
295
+ } else {
285
296
const userMessage = prepareUserMessage (
286
297
userInput ,
287
298
attachedFile ,
288
299
allContextItems ,
289
300
) ;
290
301
messagesToUse = [ ...messages , userMessage ] ;
291
302
onNewMessage ( userMessage ) ;
292
- } else {
293
- messagesToUse = messages ;
294
303
}
295
304
296
305
// Filter message to only include non-error messages, error messages are only intended for the user.
297
306
const filteredMessages = await normalizeAndApplyContext ( messagesToUse ) ;
298
307
308
+ console . log (
309
+ 'last message sent as context: "' ,
310
+ filteredMessages . at ( - 1 ) . content [ 0 ] . text ,
311
+ 'other mgss' ,
312
+ filteredMessages ,
313
+ ) ;
314
+
299
315
// Update messages with the user message first
300
316
setExternalContextItems ( [ ] ) ;
301
317
setUserSelectedContextItems ( [ ] ) ;
@@ -545,13 +561,6 @@ export const SimpleAIChat: React.FC<
545
561
}
546
562
} ;
547
563
548
- useEffect ( ( ) => {
549
- if ( hasToolResultFollowUp ) {
550
- setHasToolResultFollowUp ( false ) ;
551
- sendMessage ( true ) ;
552
- }
553
- } , [ hasToolResultFollowUp ] ) ;
554
-
555
564
// Combine both context item lists when needed
556
565
const allContextItems = [
557
566
...externalContextItems ,
@@ -564,18 +573,37 @@ export const SimpleAIChat: React.FC<
564
573
} ) ;
565
574
} ;
566
575
576
+ const regenerateMessage = async ( message : AIChatDisplayMessage ) => {
577
+ flushSync ( async ( ) => {
578
+ // Removes the following messages
579
+ await onRegenerateMessage ( message ) ;
580
+
581
+ setShouldRegenMessages ( true ) ;
582
+ } ) ;
583
+ } ;
584
+
585
+ useEffect ( ( ) => {
586
+ if ( shouldRegenMessages ) {
587
+ sendMessage ( {
588
+ regenerate : true ,
589
+ } ) ;
590
+ setShouldRegenMessages ( false ) ;
591
+ }
592
+ } , [ shouldRegenMessages ] ) ;
593
+
567
594
return (
568
595
< ChatWindow fullView = { fullView } >
569
596
{ children }
570
597
< ChatMessagesContainer
571
598
enableAutoScroll = { aiState !== AIState . Stopped }
572
599
fullView = { fullView }
573
600
>
574
- { messages . filter ( cleanMessages ) . map ( message => (
601
+ { messages . filter ( cleanMessages ) . map ( ( message , index ) => (
575
602
< AIChatMessage
576
- key = { JSON . stringify ( message ) }
603
+ key = { ` ${ JSON . stringify ( message ) } - ${ index } ` }
577
604
message = { message }
578
605
onDeleteMessage = { onDeleteMessage }
606
+ onRegenerateMessage = { regenerateMessage }
579
607
/>
580
608
) ) }
581
609
{ ongoingMessage . text && (
0 commit comments