@@ -116,6 +116,24 @@ export type AgentFlowExecutedData = {
116116 status ?: ExecutionState ;
117117} ;
118118
119+ export type MessageResponseVersion = {
120+ message ?: string ;
121+ messageId ?: string ;
122+ id ?: string ;
123+ sourceDocuments ?: any ;
124+ fileAnnotations ?: any ;
125+ agentReasoning ?: IAgentReasoning [ ] ;
126+ agentFlowExecutedData ?: any ;
127+ usedTools ?: any [ ] ;
128+ action ?: IAction | null ;
129+ artifacts ?: Partial < FileUpload > [ ] ;
130+ thinking ?: string ;
131+ thinkingDuration ?: number ;
132+ isThinking ?: boolean ;
133+ rating ?: FeedbackRatingType ;
134+ dateTime ?: string ;
135+ } ;
136+
119137export type MessageType = {
120138 messageId ?: string ;
121139 message : string ;
@@ -137,6 +155,8 @@ export type MessageType = {
137155 thinking ?: string ;
138156 thinkingDuration ?: number ;
139157 isThinking ?: boolean ;
158+ responseVersions ?: MessageResponseVersion [ ] ;
159+ responseVersionIndex ?: number ;
140160} ;
141161
142162type IUploads = {
@@ -496,6 +516,7 @@ export const Bot = (botProps: BotProps & { class?: string }) => {
496516 const [ isMessageStopping , setIsMessageStopping ] = createSignal ( false ) ;
497517 const [ starterPrompts , setStarterPrompts ] = createSignal < string [ ] > ( [ ] , { equals : false } ) ;
498518 const [ chatFeedbackStatus , setChatFeedbackStatus ] = createSignal < boolean > ( false ) ;
519+ const [ chatFeedbackRegenerateResponseStatus , setChatFeedbackRegenerateResponseStatus ] = createSignal < boolean > ( false ) ;
499520 const [ fullFileUpload , setFullFileUpload ] = createSignal < boolean > ( false ) ;
500521 const [ uploadsConfig , setUploadsConfig ] = createSignal < UploadsConfig > ( ) ;
501522 const [ leadsConfig , setLeadsConfig ] = createSignal < LeadsConfig > ( ) ;
@@ -881,6 +902,51 @@ export const Bot = (botProps: BotProps & { class?: string }) => {
881902 handleSubmit ( prompt ) ;
882903 } ;
883904
905+ const createResponseVersion = ( message : Partial < MessageType > ) : MessageResponseVersion => ( {
906+ message : message . message ?? '' ,
907+ messageId : message . messageId ,
908+ id : message . id ,
909+ sourceDocuments : message . sourceDocuments ,
910+ fileAnnotations : message . fileAnnotations ,
911+ agentReasoning : message . agentReasoning ,
912+ agentFlowExecutedData : message . agentFlowExecutedData ,
913+ usedTools : message . usedTools ,
914+ action : message . action ,
915+ artifacts : message . artifacts ,
916+ thinking : message . thinking ,
917+ thinkingDuration : message . thinkingDuration ,
918+ isThinking : message . isThinking ,
919+ rating : message . rating ,
920+ dateTime : message . dateTime ,
921+ } ) ;
922+
923+ const parseConfigBoolean = ( value : unknown , defaultValue : boolean ) => {
924+ if ( typeof value === 'boolean' ) return value ;
925+ if ( typeof value === 'string' ) {
926+ const normalized = value . trim ( ) . toLowerCase ( ) ;
927+ if ( normalized === 'true' ) return true ;
928+ if ( normalized === 'false' ) return false ;
929+ }
930+ return defaultValue ;
931+ } ;
932+
933+ const getLastApiMessageIndex = ( ) => {
934+ const currentMessages = messages ( ) ;
935+ for ( let i = currentMessages . length - 1 ; i >= 0 ; i -- ) {
936+ if ( currentMessages [ i ] . type === 'apiMessage' ) return i ;
937+ }
938+ return - 1 ;
939+ } ;
940+
941+ const canRegenerateResponse = ( messageIndex : number ) => {
942+ if ( ! chatFeedbackStatus ( ) || ! chatFeedbackRegenerateResponseStatus ( ) || loading ( ) ) return false ;
943+ if ( messageIndex !== getLastApiMessageIndex ( ) ) return false ;
944+ const previousMessage = messages ( ) [ messageIndex - 1 ] ;
945+ if ( ! previousMessage || previousMessage . type !== 'userMessage' ) return false ;
946+ if ( previousMessage . fileUploads ?. length ) return false ;
947+ return true ;
948+ } ;
949+
884950 const handleRegenerateResponse = async ( messageIndex : number ) => {
885951 if ( loading ( ) ) return ;
886952 if ( previews ( ) . length ) return ;
@@ -893,14 +959,22 @@ export const Bot = (botProps: BotProps & { class?: string }) => {
893959 const previousMessage = currentMessages [ messageIndex - 1 ] ;
894960 if ( ! previousMessage || previousMessage . type !== 'userMessage' || previousMessage . fileUploads ?. length ) return ;
895961
962+ const existingResponseVersions =
963+ targetMessage . responseVersions && targetMessage . responseVersions . length > 0
964+ ? [ ...targetMessage . responseVersions ]
965+ : [ createResponseVersion ( targetMessage ) ] ;
966+
896967 setFollowUpPrompts ( [ ] ) ;
897968 const updatedMessages = currentMessages . slice ( 0 , messageIndex ) ;
898969 addChatMessage ( updatedMessages ) ;
899970 setMessages ( updatedMessages ) ;
900971
901972 // Note: chatId is kept so the server retains conversation context up to this point.
902973 // The server's history will still include messages that were removed client-side
903- await handleSubmit ( previousMessage . message , undefined , undefined , { skipAddUserMessage : true } ) ;
974+ await handleSubmit ( previousMessage . message , undefined , undefined , {
975+ skipAddUserMessage : true ,
976+ responseVersions : existingResponseVersions ,
977+ } ) ;
904978 } ;
905979
906980 const updateMetadata = ( data : any , input : string ) => {
@@ -945,7 +1019,11 @@ export const Bot = (botProps: BotProps & { class?: string }) => {
9451019 }
9461020 } ;
9471021
948- const fetchResponseFromEventStream = async ( chatflowid : string , params : any ) => {
1022+ const fetchResponseFromEventStream = async (
1023+ chatflowid : string ,
1024+ params : any ,
1025+ options ?: { skipAddUserMessage ?: boolean ; responseVersions ?: MessageResponseVersion [ ] } ,
1026+ ) => {
9491027 const chatId = params . chatId ;
9501028 const input = params . question ;
9511029 params . streaming = true ;
@@ -988,7 +1066,15 @@ export const Bot = (botProps: BotProps & { class?: string }) => {
9881066 const payload = JSON . parse ( ev . data ) ;
9891067 switch ( payload . event ) {
9901068 case 'start' :
991- setMessages ( ( prevMessages ) => [ ...prevMessages , { message : '' , type : 'apiMessage' } ] ) ;
1069+ setMessages ( ( prevMessages ) => {
1070+ const newMessage : MessageType = { message : '' , type : 'apiMessage' } ;
1071+ if ( options ?. responseVersions && options . responseVersions . length > 0 ) {
1072+ const responseVersions = [ ...options . responseVersions , createResponseVersion ( newMessage ) ] ;
1073+ newMessage . responseVersions = responseVersions ;
1074+ newMessage . responseVersionIndex = responseVersions . length - 1 ;
1075+ }
1076+ return [ ...prevMessages , newMessage ] ;
1077+ } ) ;
9921078 break ;
9931079 case 'token' :
9941080 updateLastMessage ( payload . data ) ;
@@ -1192,7 +1278,7 @@ export const Bot = (botProps: BotProps & { class?: string }) => {
11921278 value : string | object ,
11931279 action ?: IAction | undefined | null ,
11941280 humanInput ?: any ,
1195- options ?: { skipAddUserMessage ?: boolean } ,
1281+ options ?: { skipAddUserMessage ?: boolean ; responseVersions ?: MessageResponseVersion [ ] } ,
11961282 ) => {
11971283 if ( typeof value === 'string' && value . trim ( ) === '' ) {
11981284 const containsFile = previews ( ) . filter ( ( item ) => ! item . mime . startsWith ( 'image' ) && item . type !== 'audio' ) . length > 0 ;
@@ -1259,7 +1345,7 @@ export const Bot = (botProps: BotProps & { class?: string }) => {
12591345 if ( humanInput ) body . humanInput = humanInput ;
12601346
12611347 if ( isChatFlowAvailableToStream ( ) ) {
1262- fetchResponseFromEventStream ( props . chatflowid , body ) ;
1348+ fetchResponseFromEventStream ( props . chatflowid , body , options ) ;
12631349 } else {
12641350 const result = await sendMessageQuery ( {
12651351 chatflowid : props . chatflowid ,
@@ -1281,7 +1367,7 @@ export const Bot = (botProps: BotProps & { class?: string }) => {
12811367 playReceiveSound ( ) ;
12821368
12831369 setMessages ( ( prevMessages ) => {
1284- const newMessage = {
1370+ const baseResponseMessage = {
12851371 message : text ,
12861372 id : data ?. chatMessageId ,
12871373 sourceDocuments : data ?. sourceDocuments ,
@@ -1297,6 +1383,21 @@ export const Bot = (botProps: BotProps & { class?: string }) => {
12971383 feedback : null ,
12981384 dateTime : new Date ( ) . toISOString ( ) ,
12991385 } ;
1386+
1387+ const responseVersions =
1388+ options ?. responseVersions && options . responseVersions . length > 0
1389+ ? [ ...options . responseVersions , createResponseVersion ( baseResponseMessage ) ]
1390+ : undefined ;
1391+
1392+ const newMessage = {
1393+ ...baseResponseMessage ,
1394+ ...( responseVersions
1395+ ? {
1396+ responseVersions,
1397+ responseVersionIndex : responseVersions . length - 1 ,
1398+ }
1399+ : { } ) ,
1400+ } ;
13001401 const allMessages = [ ...prevMessages , newMessage ] ;
13011402 addChatMessage ( allMessages ) ;
13021403 return allMessages ;
@@ -1491,6 +1592,14 @@ export const Bot = (botProps: BotProps & { class?: string }) => {
14911592 rating : message . rating ,
14921593 dateTime : message . dateTime ,
14931594 } ;
1595+ if ( message . responseVersionIndex !== undefined ) chatHistory . responseVersionIndex = message . responseVersionIndex ;
1596+ if ( ( message as any ) . responseVersions ) {
1597+ const responseVersions =
1598+ typeof ( message as any ) . responseVersions === 'string'
1599+ ? JSON . parse ( ( message as any ) . responseVersions )
1600+ : ( message as any ) . responseVersions ;
1601+ if ( Array . isArray ( responseVersions ) ) chatHistory . responseVersions = responseVersions ;
1602+ }
14941603 if ( message . sourceDocuments ) chatHistory . sourceDocuments = message . sourceDocuments ;
14951604 if ( message . fileAnnotations ) chatHistory . fileAnnotations = message . fileAnnotations ;
14961605 if ( message . fileUploads ) chatHistory . fileUploads = message . fileUploads ;
@@ -2633,6 +2742,7 @@ export const Bot = (botProps: BotProps & { class?: string }) => {
26332742 avatarSrc = { props . botMessage ?. avatarSrc }
26342743 chatFeedbackStatus = { chatFeedbackStatus ( ) }
26352744 onRegenerateResponse = { ( ) => handleRegenerateResponse ( index ( ) ) }
2745+ showRegenerateResponseButton = { canRegenerateResponse ( index ( ) ) }
26362746 fontSize = { props . fontSize }
26372747 isLoading = { loading ( ) && index ( ) === messages ( ) . length - 1 }
26382748 showAgentMessages = { props . showAgentMessages }
0 commit comments