in src/components/Widget/index.js [278:332]
handleBotUtterance(botUtterance) {
const { dispatch, isChatOpen } = this.props;
this.clearCustomStyle();
this.eventListenerCleaner();
dispatch(clearMetadata());
// Handle is_final parameter for bot processing state
// If is_final is explicitly set to false, keep WIP active
// If is_final is explicitly set to true or missing, hide WIP after message is shown
const isFinal = botUtterance.metadata?.is_final ?? botUtterance.is_final ?? true;
logger.debug('handleBotUtterance:', {
text: botUtterance.text?.substring(0, 50),
isFinal,
isChatOpen
});
// Store last is_final value to check in newMessageTimeout
this.lastIsFinal = isFinal;
// If chat is not open, message is displayed immediately without delay
// So we can set isBotProcessing based on is_final immediately
// If chat is open, message will have delay, so keep WIP active until message is shown
if (!isChatOpen) {
dispatch(setBotProcessing(!isFinal));
if (isFinal) {
// Clear timeout when receiving final message
clearBotProcessingTimeout();
} else {
// Start timeout when receiving non-final message
startBotProcessingTimeout(dispatch);
}
} else if (!isFinal) {
// If not final and chat is open, keep showing WIP
dispatch(setBotProcessing(true));
// Start timeout when receiving non-final message
startBotProcessingTimeout(dispatch);
} else {
// If final and chat is open, clear the timeout (WIP will be hidden after message delay)
clearBotProcessingTimeout();
}
// If isFinal and chat is open, WIP will be hidden after message delay in newMessageTimeout
if (botUtterance.metadata) this.propagateMetadata(botUtterance.metadata);
// Fix: Convert \n to hard breaks (2 spaces + \n) for proper Markdown rendering
// This ensures single line breaks are preserved in the output
const fixedText = String(botUtterance.text).replace(/\n/g, ' \n');
const newMessage = { ...botUtterance, text: fixedText };
if (botUtterance.metadata && botUtterance.metadata.customCss) {
newMessage.customCss = botUtterance.metadata.customCss;
}
this.handleMessageReceived(newMessage);
}