diff --git a/src/ai/chat.js b/src/ai/chat.js index 0b2b896..0b3117d 100644 --- a/src/ai/chat.js +++ b/src/ai/chat.js @@ -32,19 +32,44 @@ const initialState = { chatsLoading: {}, }; +/** + * Sanitizes the chat history to remove any unsupported properties. + * + * @since n.e.x.t + * + * @param {Object[]} history Chat history. + * @return {Object[]} Sanitized chat history. + */ +function sanitizeHistory( history ) { + return history.map( ( content ) => { + if ( + content.role && + content.parts && + Object.keys( content ).length > 2 + ) { + return { + role: content.role, + parts: content.parts, + }; + } + return content; + } ); +} + const actions = { /** * Starts a chat session. * * @since 0.1.0 * - * @param {string} chatId Identifier to use for the chat. - * @param {Object} options Chat options. - * @param {string} options.service AI service to use. - * @param {Object} options.modelParams Model parameters (including optional model slug). + * @param {string} chatId Identifier to use for the chat. + * @param {Object} options Chat options. + * @param {string} options.service AI service to use. + * @param {Object} options.modelParams Model parameters (including optional model slug). + * @param {Object[]} options.history Chat history. * @return {Function} Action creator. */ - startChat( chatId, { service, modelParams } ) { + startChat( chatId, { service, modelParams, history } ) { return async ( { dispatch, select } ) => { if ( select.getServices() === undefined ) { await resolveSelect( STORE_NAME ).getServices(); @@ -74,11 +99,8 @@ const actions = { service || SERVICE_ARGS ); - // TODO: Support history persistence. - const history = []; - const model = aiService.getModel( modelParams ); - const session = model.startChat( history ); + const session = model.startChat( sanitizeHistory( history || [] ) ); dispatch.receiveChat( chatId, { session, diff --git a/src/chatbot/components/Chatbot/index.js b/src/chatbot/components/Chatbot/index.js index 15fe6fa..90bfd61 100644 --- a/src/chatbot/components/Chatbot/index.js +++ b/src/chatbot/components/Chatbot/index.js @@ -25,12 +25,13 @@ import './style.scss'; * * @since n.e.x.t * - * @param {Object} props Component props. - * @param {Function} props.onClose Function to call when the close button is clicked. - * @param {string} props.className Class name to use on the chatbot container. + * @param {Object} props Component props. + * @param {Function} props.onUpdateMessages Function to call when the history of messages is updated. + * @param {Function} props.onClose Function to call when the close button is clicked. + * @param {string} props.className Class name to use on the chatbot container. * @return {Component} The component to be rendered. */ -export default function Chatbot( { onClose, className } ) { +export default function Chatbot( { onUpdateMessages, onClose, className } ) { const chatId = useChatbotConfig( 'chatId' ); const labels = useChatbotConfig( 'labels' ); const initialBotMessage = useChatbotConfig( 'initialBotMessage' ); @@ -98,6 +99,14 @@ export default function Chatbot( { onClose, className } ) { select( aiStore ).isChatLoading( chatId ) ); + useEffect( () => { + if ( ! onUpdateMessages ) { + return; + } + const timeout = setTimeout( () => onUpdateMessages( messages ), 500 ); + return () => clearTimeout( timeout ); + }, [ messages, onUpdateMessages ] ); + const handleSubmit = ( event ) => { event.preventDefault(); diff --git a/src/chatbot/components/ChatbotApp/index.js b/src/chatbot/components/ChatbotApp/index.js index 3a9f91a..78a5f20 100644 --- a/src/chatbot/components/ChatbotApp/index.js +++ b/src/chatbot/components/ChatbotApp/index.js @@ -50,6 +50,20 @@ const storeVisibility = ( isVisible ) => { } }; +const retrieveHistory = () => { + const chatbotHistory = window.sessionStorage.getItem( + 'ai-services-built-in-chatbot-history' + ); + return chatbotHistory ? JSON.parse( chatbotHistory ) : []; +}; + +const storeHistory = ( history ) => { + window.sessionStorage.setItem( + 'ai-services-built-in-chatbot-history', + JSON.stringify( history ) + ); +}; + const getErrorChatResponse = ( error ) => { return ( __( @@ -175,6 +189,7 @@ export default function ChatbotApp() { modelParams: { feature: 'ai-services-chatbot', }, + history: retrieveHistory(), } ); } } @@ -214,7 +229,10 @@ export default function ChatbotApp() { > { isVisible && hasChat && ( - + ) }