{"version":3,"file":"ChatContainer.mjs","names":["React","useState","useEffect","useRef","useCallback","AmbientTextField","FluentButton","useUser","ChatMessage","Link","Typography","makeStyles","apiMutate","useChatBot","useTranslation","useSnackbar","ConfigService","useStyles","theme","loadingContainer","display","fontSize","pulseEllipsis","animation","animationDelay","transform","opacity","ChatContainer","props","classes","messageHistory","addMessage","removeMessageHistory","removeLoadingMessage","user","newMessageContent","setNewMessageContent","messageEndRef","productId","config","UNITY_PRODUCT_ID","aiSearchUrl","AI_SEARCH_URL","aiSearchIndexName","AI_SEARCH_INDEX_NAME","aiSearchKey","AI_SEARCH_KEY","udpAiApiBase","UDPAI_API_BASE","enqueueSnackbar","t","youName","defaultValue","aiAssistantName","handleSendMessage","name","addLoadingMessage","sendMessage","error","console","handleNewSession","variant","anchorOrigin","vertical","horizontal","messageContent","loading","current","scrollIntoView","behavior","formatCitations","citations","map","citation","url","whiteSpace","title","parseAiResponse","response","gptResponseMessage","data","LLMResponse","choices","message","messageText","content","context","showCitations","toString","includes","textContent","replaceAll","responseMessage","wordWrap","length","e","errorMessage","executeQuery","aiModelId","method","headers","currentProductId","messageHistoryTextArray","item","role","createdBy","body","modelName","useCache","payload","max_tokens","temperature","n","presence_penalty","messages","data_sources","type","parameters","endpoint","semantic_configuration","query_type","in_scope","strictness","top_n_documents","authentication","key","index_name","filter","aiResponse","flexDirection","height","gap","padding","overflowY","flexGrow","index","marginTop","position","bottom","zIndex","background","target","value","shiftKey","preventDefault"],"sources":["../../src/chatBot/ChatContainer.jsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback } from 'react';\nimport { AmbientTextField } from '../UI/inputs/textField/AmbientTextField';\nimport { FluentButton } from '../UI/inputs/buttons/FluentButton';\nimport { useUser } from '../utilities/auth/useUser';\nimport { ChatMessage } from './ChatMessage';\nimport { Link, Typography } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { apiMutate } from '../utilities/useAxiosMutate';\nimport { useChatBot } from '../utilities/chatBot/useChatBot';\nimport { useTranslation } from 'react-i18next';\nimport { useSnackbar } from 'notistack';\nimport { ConfigService } from '../configService';\n\nconst useStyles = makeStyles((theme) => ({\n  loadingContainer: {\n    display: 'inline-block',\n    fontSize: '2em', // Adjust the font size to make the whole section bigger\n  },\n  pulseEllipsis: {\n    display: 'inline-block',\n    animation: '$pulse 1.5s infinite',\n    '&:nth-of-type(2)': {\n      animationDelay: '0.5s',\n    },\n    '&:nth-of-type(3)': {\n      animationDelay: '1s',\n    },\n  },\n  '@keyframes pulse': {\n    '0%': {\n      transform: 'scale(1)',\n      opacity: 0.6,\n    },\n    '50%': {\n      transform: 'scale(1.2)',\n      opacity: 1,\n    },\n    '100%': {\n      transform: 'scale(1)',\n      opacity: 0.6,\n    },\n  },\n}));\n\n\nexport const ChatContainer = (props) => {\n  const classes = useStyles();\n  const { messageHistory, addMessage, removeMessageHistory, removeLoadingMessage } = useChatBot()\n  const user = useUser();\n  const [newMessageContent, setNewMessageContent] = useState('');\n  const messageEndRef = useRef(null);\n  const productId = ConfigService.config.UNITY_PRODUCT_ID;\n  const aiSearchUrl = ConfigService.config.AI_SEARCH_URL;\n  const aiSearchIndexName = ConfigService.config.AI_SEARCH_INDEX_NAME;\n  const aiSearchKey = ConfigService.config.AI_SEARCH_KEY;\n  const udpAiApiBase = ConfigService.config.UDPAI_API_BASE;\n  const { enqueueSnackbar } = useSnackbar();\n  const { t } = useTranslation();\n  const youName = t('chatBot.sender.you', { defaultValue: 'You' });\n  const aiAssistantName = t('chatBot.sender.aiAssistant', {\n    defaultValue: 'AI Assistant'\n  });\n\n  const handleSendMessage = async () => {\n    addMessage(newMessageContent, { ...user, name: youName }, newMessageContent);\n    setNewMessageContent('');\n    addLoadingMessage();\n\n    try {\n      await sendMessage(newMessageContent, addMessage);\n      removeLoadingMessage();\n    } catch (error) {\n      console.error('Error sending message:', error);\n    }\n  };\n\n  const handleNewSession = async () => {\n    try {\n      await removeMessageHistory();\n      enqueueSnackbar(t('chatBot.session.cleared', { defaultValue: 'Chat Session Cleared' }), {\n        variant: 'success',\n        anchorOrigin: {\n          vertical: 'top',\n          horizontal: 'center',\n        }\n      });\n    } catch (error) {\n      console.error('Error create new chat session:', error);\n    }\n  }\n\n  const addLoadingMessage = () => {\n    const messageContent = (\n      <div className={classes.loadingContainer}>\n        <span className={classes.pulseEllipsis}>.</span>\n        <span className={classes.pulseEllipsis}>.</span>\n        <span className={classes.pulseEllipsis}>.</span>\n      </div>\n    );\n    addMessage(messageContent, { name: aiAssistantName, loading: true }, \"\");\n  };\n\n\n  useEffect(() => {\n    messageEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n  }, [messageHistory]);\n\n\n  const formatCitations = (citations) => {\n    return (\n      <div>\n        <ol>\n          {citations.map((citation) => {\n            return (\n              <li key={citation.url}>\n                <Link href={citation.url} target='_blank' rel='noopener'>\n                  <Typography variant='body2' style={{ whiteSpace: 'pre-line' }}>\n                    {citation.title}\n                  </Typography>\n                </Link>\n              </li>\n            );\n          })}\n        </ol>\n      </div>\n    );\n  };\n\n  const parseAiResponse = (response, addMessage) => {\n    try {\n      const gptResponseMessage = response.data.LLMResponse.choices[0].message;\n      const messageText = gptResponseMessage.content;\n      const citations = gptResponseMessage.context.citations;\n      const showCitations = messageText.toString().includes('[doc');\n      const textContent = messageText.toString().replaceAll('[doc', '[');\n\n      const responseMessage = (\n        <div>\n          <div style={{ wordWrap: 'break-word' }}>\n            <Typography variant='body2' style={{ whiteSpace: 'pre-line' }}>\n              {textContent}\n            </Typography>\n          </div>\n          {citations.length > 0 && showCitations && (\n            <div>\n              <br />\n              <Typography variant='body2' style={{ whiteSpace: 'pre-line' }}>\n                {t('chatBot.citations.referTo', {\n                  defaultValue: 'Refer to the XWiki documents for more info:'\n                })}\n              </Typography>\n              {formatCitations(citations)}\n            </div>\n          )}\n        </div>\n      );\n      addMessage(responseMessage, { name: aiAssistantName }, textContent);\n    } catch (e) {\n      const errorMessage = t('chatBot.errors.generic', {\n        defaultValue: 'Sorry, an error has occurred.'\n      });\n      addMessage(errorMessage, { name: aiAssistantName }, errorMessage);\n    }\n\n  };\n\n  const executeQuery = useCallback(\n    async (data, aiModelId) =>\n      apiMutate(\n        udpAiApiBase,\n        `aiservice/llm`,\n        {\n          method: 'post',\n          headers: {\n            currentProductId: productId, //temporary bypass -> //currentProductId: '1'\n          }\n        },\n        data\n      ),\n    [productId, udpAiApiBase]\n  );\n\n\n\n  const sendMessage = async (newMessageContent, addMessage) => {\n    const messageHistoryTextArray = messageHistory\n      .map(item => ({\n        role: item.createdBy.name === aiAssistantName ? 'assistant' : item.createdBy.name === youName ? 'user' : item.createdBy.name,\n        content: item.messageText\n      }));\n\n    const body = {\n      modelName: 'gpt-4o',\n      useCache: 'false',\n      payload: {\n        max_tokens: 4096,\n        temperature: 0.5,\n        n: 1,\n        presence_penalty: 0,\n        messages: [\n          {\n            role: 'system',\n            content:\n              'You are an assistant helping a user using existing knowledge supplemented by additional data.'\n          },\n          ...messageHistoryTextArray,\n          {\n            role: 'user',\n            content: newMessageContent\n          }\n        ],\n        data_sources: [\n          {\n            type: 'azure_search',\n            parameters: {\n              endpoint: aiSearchUrl,\n              // set sematic configuration name to match index name\n              semantic_configuration: aiSearchIndexName,\n              query_type: \"semantic\",\n              in_scope: false,\n              //role_information: \"You are an AI search assistant having access to wiki documentation data. Please be helpful to the user answer any questions to the best of your ability.\",\n              strictness: 1,\n              top_n_documents: 5,\n              authentication: {\n                type: 'api_key',\n                key: aiSearchKey\n              },\n              index_name: aiSearchIndexName,\n              filter: `Products/any(p: p eq '${productId}')`\n            }\n          }\n        ]\n      }\n    };\n\n    const aiResponse = await executeQuery({ data: body });\n    parseAiResponse(aiResponse, addMessage);\n  }\n\n\n  return (\n    <div style={{ display: 'flex', flexDirection: 'column', height: '100%'}}>\n      <FluentButton id='udpRecord-ChatContainer-NewSession' onClick={handleNewSession}>\n        {t('chatBot.actions.clearChat', { defaultValue: 'Clear Chat' })}\n      </FluentButton>\n      <div\n        style={{\n          display: 'flex',\n          flexDirection: 'column',\n          gap: '10px',\n          padding: '3px',\n          height: '100%',\n          overflowY: 'auto',\n          flexGrow: 1\n        }}\n      >\n        {messageHistory.map((message, index) => (\n          <ChatMessage key={index} message={message} />\n        ))}\n        <div ref={messageEndRef} />\n      </div>\n      <div style={{ display: 'flex', flexDirection: 'column', marginTop: '5px', position: 'sticky', bottom: 0, padding: '3px', zIndex: 1, background: 'white' }}>\n        <div style={{ flexGrow: 1 }}>\n          <AmbientTextField\n            id='udpRecord-ChatContainer-Enter'\n            multiline\n            value={newMessageContent}\n            onChange={(e) => setNewMessageContent(e.target.value)}\n            onKeyDown={(e) => {\n              if (e.key === 'Enter' && !e.shiftKey) {\n                e.preventDefault();\n                handleSendMessage();\n              }\n            }}\n          />\n        </div>\n        <FluentButton\n          id='udpRecord-ChatContainer-Send'\n          onClick={handleSendMessage}\n          autoFocus\n          variant='outlined'\n        >\n          {t('common.send', { defaultValue: 'Send' })}\n        </FluentButton>\n      </div>\n    </div>\n  );\n};\n"],"mappings":"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"}