@red-hat-developer-hub/backstage-plugin-lightspeed 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/components/LightSpeedChat.esm.js +2 -6
- package/dist/components/LightSpeedChat.esm.js.map +1 -1
- package/dist/components/LightspeedChatBox.esm.js +36 -5
- package/dist/components/LightspeedChatBox.esm.js.map +1 -1
- package/dist/hooks/useAutoScroll.esm.js +78 -0
- package/dist/hooks/useAutoScroll.esm.js.map +1 -0
- package/dist/hooks/useBufferedMessages.esm.js +27 -0
- package/dist/hooks/useBufferedMessages.esm.js.map +1 -0
- package/dist/hooks/useConversationMessages.esm.js +2 -2
- package/dist/hooks/useConversationMessages.esm.js.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -111,11 +111,6 @@ const LightspeedChat = ({
|
|
|
111
111
|
onStart
|
|
112
112
|
);
|
|
113
113
|
const [messages, setMessages] = React__default.useState(conversationMessages);
|
|
114
|
-
React__default.useEffect(() => {
|
|
115
|
-
setTimeout(() => {
|
|
116
|
-
scrollToBottomRef.current?.scrollIntoView({ behavior: "auto" });
|
|
117
|
-
}, 10);
|
|
118
|
-
}, [messages, scrollToBottomRef.current]);
|
|
119
114
|
const sendMessage = (message) => {
|
|
120
115
|
if (conversationId !== TEMP_CONVERSATION_ID) {
|
|
121
116
|
setNewChatCreated(false);
|
|
@@ -208,8 +203,9 @@ const LightspeedChat = ({
|
|
|
208
203
|
}
|
|
209
204
|
return c_id;
|
|
210
205
|
});
|
|
206
|
+
scrollToBottomRef.current?.scrollToBottom();
|
|
211
207
|
},
|
|
212
|
-
[setConversationId]
|
|
208
|
+
[setConversationId, scrollToBottomRef]
|
|
213
209
|
);
|
|
214
210
|
const conversationFound = !!conversations.find(
|
|
215
211
|
(c) => c.conversation_id === conversationId
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LightSpeedChat.esm.js","sources":["../../src/components/LightSpeedChat.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\n\nimport { ErrorPanel } from '@backstage/core-components';\n\nimport { Box, makeStyles } from '@material-ui/core';\nimport {\n Chatbot,\n ChatbotContent,\n ChatbotDisplayMode,\n ChatbotFooter,\n ChatbotFootnote,\n ChatbotHeader,\n ChatbotHeaderMain,\n ChatbotHeaderMenu,\n ChatbotHeaderTitle,\n MessageBar,\n MessageProps,\n} from '@patternfly/chatbot';\nimport ChatbotConversationHistoryNav from '@patternfly/chatbot/dist/dynamic/ChatbotConversationHistoryNav';\nimport { DropdownItem, Title } from '@patternfly/react-core';\nimport { useQueryClient } from '@tanstack/react-query';\n\nimport { TEMP_CONVERSATION_ID } from '../const';\nimport {\n useBackstageUserIdentity,\n useConversationMessages,\n useConversations,\n useDeleteConversation,\n useIsMobile,\n useLastOpenedConversation,\n useLightspeedDeletePermission,\n} from '../hooks';\nimport { ConversationSummary } from '../types';\nimport {\n getCategorizeMessages,\n getFootnoteProps,\n} from '../utils/lightspeed-chatbox-utils';\nimport { DeleteModal } from './DeleteModal';\nimport { LightspeedChatBox } from './LightspeedChatBox';\nimport { LightspeedChatBoxHeader } from './LightspeedChatBoxHeader';\n\nconst useStyles = makeStyles(theme => ({\n body: {\n // remove default margin and padding from common elements\n '& h1, & h2, & h3, & h4, & h5, & h6, & p, & ul, & ol, & li': {\n margin: 0,\n padding: 0,\n },\n },\n header: {\n padding: `${theme.spacing(3)}px !important`,\n },\n headerMenu: {\n // align hamburger icon with title\n '& .pf-v6-c-button': {\n display: 'flex',\n alignItems: 'center',\n },\n },\n headerTitle: {\n justifyContent: 'left !important',\n },\n footer: {\n '&>.pf-chatbot__footer-container': {\n width: '95% !important',\n maxWidth: 'unset !important',\n },\n },\n}));\n\ntype LightspeedChatProps = {\n selectedModel: string;\n userName?: string;\n avatar?: string;\n profileLoading: boolean;\n handleSelectedModel: (item: string) => void;\n models: { label: string; value: string }[];\n};\n\nexport const LightspeedChat = ({\n selectedModel,\n userName,\n avatar,\n profileLoading,\n handleSelectedModel,\n models,\n}: LightspeedChatProps) => {\n const isMobile = useIsMobile();\n const classes = useStyles();\n const user = useBackstageUserIdentity();\n const [filterValue, setFilterValue] = React.useState<string>('');\n const [announcement, setAnnouncement] = React.useState<string>('');\n const [conversationId, setConversationId] = React.useState<string>('');\n const [isDrawerOpen, setIsDrawerOpen] = React.useState<boolean>(!isMobile);\n const [newChatCreated, setNewChatCreated] = React.useState<boolean>(false);\n const [isSendButtonDisabled, setIsSendButtonDisabled] =\n React.useState<boolean>(false);\n const [error, setError] = React.useState<Error | null>(null);\n const [targetConversationId, setTargetConversationId] =\n React.useState<string>('');\n const [isDeleteModalOpen, setIsDeleteModalOpen] =\n React.useState<boolean>(false);\n const { isReady, lastOpenedId, setLastOpenedId, clearLastOpenedId } =\n useLastOpenedConversation(user);\n\n // Sync conversationId with lastOpenedId whenever lastOpenedId changes\n React.useEffect(() => {\n if (isReady && lastOpenedId !== null) {\n setConversationId(lastOpenedId);\n }\n }, [lastOpenedId, isReady]);\n\n const queryClient = useQueryClient();\n\n const { data: conversations = [] } = useConversations();\n const { mutateAsync: deleteConversation } = useDeleteConversation();\n const { allowed: hasDeleteAccess } = useLightspeedDeletePermission();\n\n React.useEffect(() => {\n if (user && lastOpenedId === null && isReady) {\n setConversationId(TEMP_CONVERSATION_ID);\n setNewChatCreated(true);\n }\n }, [user, isReady, lastOpenedId, setConversationId]);\n\n React.useEffect(() => {\n // Update last opened conversation whenever `conversationId` changes\n if (conversationId) {\n setLastOpenedId(conversationId);\n }\n }, [conversationId, setLastOpenedId]);\n\n const onStart = (conv_id: string) => {\n setConversationId(conv_id);\n };\n\n const onComplete = (message: string) => {\n setIsSendButtonDisabled(false);\n setAnnouncement(`Message from Bot: ${message}`);\n queryClient.invalidateQueries({\n queryKey: ['conversations'],\n });\n setNewChatCreated(false);\n };\n\n const { conversationMessages, handleInputPrompt, scrollToBottomRef } =\n useConversationMessages(\n conversationId,\n userName,\n selectedModel,\n avatar,\n onComplete,\n onStart,\n );\n\n const [messages, setMessages] =\n React.useState<MessageProps[]>(conversationMessages);\n\n // Auto-scrolls to the latest message\n React.useEffect(() => {\n setTimeout(() => {\n scrollToBottomRef.current?.scrollIntoView({ behavior: 'auto' });\n }, 10);\n // eslint-disable-next-line\n }, [messages, scrollToBottomRef.current]);\n\n const sendMessage = (message: string | number) => {\n if (conversationId !== TEMP_CONVERSATION_ID) {\n setNewChatCreated(false);\n }\n setAnnouncement(\n `Message from User: ${prompt}. Message from Bot is loading.`,\n );\n handleInputPrompt(message.toString());\n setIsSendButtonDisabled(true);\n };\n\n const onNewChat = React.useCallback(() => {\n (async () => {\n setMessages([]);\n setConversationId(TEMP_CONVERSATION_ID);\n setNewChatCreated(true);\n })();\n }, [setConversationId, setMessages]);\n\n const openDeleteModal = (conversation_id: string) => {\n setTargetConversationId(conversation_id);\n setIsDeleteModalOpen(true);\n };\n\n const handleDeleteConversation = React.useCallback(() => {\n (async () => {\n try {\n await deleteConversation({\n conversation_id: targetConversationId,\n invalidateCache: false,\n });\n if (targetConversationId === lastOpenedId) {\n onNewChat();\n clearLastOpenedId();\n }\n setIsDeleteModalOpen(false);\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn(e);\n setError(e);\n }\n })();\n }, [\n deleteConversation,\n clearLastOpenedId,\n lastOpenedId,\n onNewChat,\n targetConversationId,\n ]);\n\n const additionalMessageProps = React.useCallback(\n (conversationSummary: ConversationSummary) => ({\n menuItems: (\n <DropdownItem\n isDisabled={!hasDeleteAccess}\n onClick={() => openDeleteModal(conversationSummary.conversation_id)}\n >\n Delete\n </DropdownItem>\n ),\n }),\n [hasDeleteAccess],\n );\n const categorizedMessages = getCategorizeMessages(\n conversations,\n additionalMessageProps,\n );\n\n const filterConversations = React.useCallback(\n (targetValue: string) => {\n const filteredConversations = Object.entries(categorizedMessages).reduce(\n (acc, [key, items]) => {\n const filteredItems = items.filter(item =>\n item.text\n .toLocaleLowerCase('en-US')\n .includes(targetValue.toLocaleLowerCase('en-US')),\n );\n if (filteredItems.length > 0) {\n acc[key] = filteredItems;\n }\n return acc;\n },\n {} as any,\n );\n return filteredConversations;\n },\n [categorizedMessages],\n );\n\n React.useEffect(() => {\n setMessages(conversationMessages);\n }, [conversationMessages]);\n\n const onSelectActiveItem = React.useCallback(\n (\n _: React.MouseEvent | undefined,\n selectedItem: string | number | undefined,\n ) => {\n setNewChatCreated(false);\n setConversationId((c_id: string) => {\n if (c_id !== selectedItem) {\n return String(selectedItem);\n }\n return c_id;\n });\n },\n [setConversationId],\n );\n\n const conversationFound = !!conversations.find(\n c => c.conversation_id === conversationId,\n );\n\n const welcomePrompts =\n (newChatCreated && conversationMessages.length === 0) ||\n (!conversationFound && conversationMessages.length === 0)\n ? [\n {\n title: 'Topic 1',\n message: 'Helpful prompt for Topic 1',\n onClick: () => sendMessage('Helpful prompt for Topic 1'),\n },\n {\n title: 'Topic 2',\n message: 'Helpful prompt for Topic 2',\n onClick: () => sendMessage('Helpful prompt for Topic 2'),\n },\n ]\n : [];\n\n const handleFilter = React.useCallback((value: string) => {\n setFilterValue(value);\n }, []);\n\n const onDrawerToggle = React.useCallback(() => {\n setIsDrawerOpen(isOpen => !isOpen);\n }, []);\n\n if (error) {\n return (\n <Box padding={1}>\n <ErrorPanel error={error} />\n </Box>\n );\n }\n\n return (\n <>\n {isDeleteModalOpen && (\n <DeleteModal\n isOpen={isDeleteModalOpen}\n onClose={() => setIsDeleteModalOpen(false)}\n onConfirm={handleDeleteConversation}\n />\n )}\n <Chatbot\n displayMode={ChatbotDisplayMode.embedded}\n className={classes.body}\n >\n <ChatbotHeader className={classes.header}>\n <ChatbotHeaderMain>\n <ChatbotHeaderMenu\n aria-expanded={isDrawerOpen}\n onMenuToggle={() => setIsDrawerOpen(!isDrawerOpen)}\n className={classes.headerMenu}\n />\n <ChatbotHeaderTitle className={classes.headerTitle}>\n <Title headingLevel=\"h1\" size=\"3xl\">\n Developer Hub Lightspeed\n </Title>\n </ChatbotHeaderTitle>\n </ChatbotHeaderMain>\n\n <LightspeedChatBoxHeader\n selectedModel={selectedModel}\n handleSelectedModel={item => handleSelectedModel(item)}\n models={models}\n />\n </ChatbotHeader>\n <ChatbotConversationHistoryNav\n drawerPanelContentProps={{ isResizable: true, minSize: '200px' }}\n reverseButtonOrder\n displayMode={ChatbotDisplayMode.embedded}\n onDrawerToggle={onDrawerToggle}\n isDrawerOpen={isDrawerOpen}\n setIsDrawerOpen={setIsDrawerOpen}\n activeItemId={conversationId}\n onSelectActiveItem={onSelectActiveItem}\n conversations={filterConversations(filterValue)}\n onNewChat={newChatCreated ? undefined : onNewChat}\n handleTextInputChange={handleFilter}\n drawerContent={\n <>\n <ChatbotContent>\n <LightspeedChatBox\n userName={userName}\n messages={messages}\n profileLoading={profileLoading}\n announcement={announcement}\n ref={scrollToBottomRef}\n welcomePrompts={welcomePrompts}\n />\n </ChatbotContent>\n <ChatbotFooter className={classes.footer}>\n <MessageBar\n onSendMessage={sendMessage}\n isSendButtonDisabled={isSendButtonDisabled}\n hasAttachButton={false}\n hasMicrophoneButton\n />\n <ChatbotFootnote {...getFootnoteProps()} />\n </ChatbotFooter>\n </>\n }\n />\n </Chatbot>\n </>\n );\n};\n"],"names":["React"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"LightSpeedChat.esm.js","sources":["../../src/components/LightSpeedChat.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\n\nimport { ErrorPanel } from '@backstage/core-components';\n\nimport { Box, makeStyles } from '@material-ui/core';\nimport {\n Chatbot,\n ChatbotContent,\n ChatbotDisplayMode,\n ChatbotFooter,\n ChatbotFootnote,\n ChatbotHeader,\n ChatbotHeaderMain,\n ChatbotHeaderMenu,\n ChatbotHeaderTitle,\n MessageBar,\n MessageProps,\n} from '@patternfly/chatbot';\nimport ChatbotConversationHistoryNav from '@patternfly/chatbot/dist/dynamic/ChatbotConversationHistoryNav';\nimport { DropdownItem, Title } from '@patternfly/react-core';\nimport { useQueryClient } from '@tanstack/react-query';\n\nimport { TEMP_CONVERSATION_ID } from '../const';\nimport {\n useBackstageUserIdentity,\n useConversationMessages,\n useConversations,\n useDeleteConversation,\n useIsMobile,\n useLastOpenedConversation,\n useLightspeedDeletePermission,\n} from '../hooks';\nimport { ConversationSummary } from '../types';\nimport {\n getCategorizeMessages,\n getFootnoteProps,\n} from '../utils/lightspeed-chatbox-utils';\nimport { DeleteModal } from './DeleteModal';\nimport { LightspeedChatBox } from './LightspeedChatBox';\nimport { LightspeedChatBoxHeader } from './LightspeedChatBoxHeader';\n\nconst useStyles = makeStyles(theme => ({\n body: {\n // remove default margin and padding from common elements\n '& h1, & h2, & h3, & h4, & h5, & h6, & p, & ul, & ol, & li': {\n margin: 0,\n padding: 0,\n },\n },\n header: {\n padding: `${theme.spacing(3)}px !important`,\n },\n headerMenu: {\n // align hamburger icon with title\n '& .pf-v6-c-button': {\n display: 'flex',\n alignItems: 'center',\n },\n },\n headerTitle: {\n justifyContent: 'left !important',\n },\n footer: {\n '&>.pf-chatbot__footer-container': {\n width: '95% !important',\n maxWidth: 'unset !important',\n },\n },\n}));\n\ntype LightspeedChatProps = {\n selectedModel: string;\n userName?: string;\n avatar?: string;\n profileLoading: boolean;\n handleSelectedModel: (item: string) => void;\n models: { label: string; value: string }[];\n};\n\nexport const LightspeedChat = ({\n selectedModel,\n userName,\n avatar,\n profileLoading,\n handleSelectedModel,\n models,\n}: LightspeedChatProps) => {\n const isMobile = useIsMobile();\n const classes = useStyles();\n const user = useBackstageUserIdentity();\n const [filterValue, setFilterValue] = React.useState<string>('');\n const [announcement, setAnnouncement] = React.useState<string>('');\n const [conversationId, setConversationId] = React.useState<string>('');\n const [isDrawerOpen, setIsDrawerOpen] = React.useState<boolean>(!isMobile);\n const [newChatCreated, setNewChatCreated] = React.useState<boolean>(false);\n const [isSendButtonDisabled, setIsSendButtonDisabled] =\n React.useState<boolean>(false);\n const [error, setError] = React.useState<Error | null>(null);\n const [targetConversationId, setTargetConversationId] =\n React.useState<string>('');\n const [isDeleteModalOpen, setIsDeleteModalOpen] =\n React.useState<boolean>(false);\n const { isReady, lastOpenedId, setLastOpenedId, clearLastOpenedId } =\n useLastOpenedConversation(user);\n\n // Sync conversationId with lastOpenedId whenever lastOpenedId changes\n React.useEffect(() => {\n if (isReady && lastOpenedId !== null) {\n setConversationId(lastOpenedId);\n }\n }, [lastOpenedId, isReady]);\n\n const queryClient = useQueryClient();\n\n const { data: conversations = [] } = useConversations();\n const { mutateAsync: deleteConversation } = useDeleteConversation();\n const { allowed: hasDeleteAccess } = useLightspeedDeletePermission();\n\n React.useEffect(() => {\n if (user && lastOpenedId === null && isReady) {\n setConversationId(TEMP_CONVERSATION_ID);\n setNewChatCreated(true);\n }\n }, [user, isReady, lastOpenedId, setConversationId]);\n\n React.useEffect(() => {\n // Update last opened conversation whenever `conversationId` changes\n if (conversationId) {\n setLastOpenedId(conversationId);\n }\n }, [conversationId, setLastOpenedId]);\n\n const onStart = (conv_id: string) => {\n setConversationId(conv_id);\n };\n\n const onComplete = (message: string) => {\n setIsSendButtonDisabled(false);\n setAnnouncement(`Message from Bot: ${message}`);\n queryClient.invalidateQueries({\n queryKey: ['conversations'],\n });\n setNewChatCreated(false);\n };\n\n const { conversationMessages, handleInputPrompt, scrollToBottomRef } =\n useConversationMessages(\n conversationId,\n userName,\n selectedModel,\n avatar,\n onComplete,\n onStart,\n );\n\n const [messages, setMessages] =\n React.useState<MessageProps[]>(conversationMessages);\n\n const sendMessage = (message: string | number) => {\n if (conversationId !== TEMP_CONVERSATION_ID) {\n setNewChatCreated(false);\n }\n setAnnouncement(\n `Message from User: ${prompt}. Message from Bot is loading.`,\n );\n handleInputPrompt(message.toString());\n setIsSendButtonDisabled(true);\n };\n\n const onNewChat = React.useCallback(() => {\n (async () => {\n setMessages([]);\n setConversationId(TEMP_CONVERSATION_ID);\n setNewChatCreated(true);\n })();\n }, [setConversationId, setMessages]);\n\n const openDeleteModal = (conversation_id: string) => {\n setTargetConversationId(conversation_id);\n setIsDeleteModalOpen(true);\n };\n\n const handleDeleteConversation = React.useCallback(() => {\n (async () => {\n try {\n await deleteConversation({\n conversation_id: targetConversationId,\n invalidateCache: false,\n });\n if (targetConversationId === lastOpenedId) {\n onNewChat();\n clearLastOpenedId();\n }\n setIsDeleteModalOpen(false);\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn(e);\n setError(e);\n }\n })();\n }, [\n deleteConversation,\n clearLastOpenedId,\n lastOpenedId,\n onNewChat,\n targetConversationId,\n ]);\n\n const additionalMessageProps = React.useCallback(\n (conversationSummary: ConversationSummary) => ({\n menuItems: (\n <DropdownItem\n isDisabled={!hasDeleteAccess}\n onClick={() => openDeleteModal(conversationSummary.conversation_id)}\n >\n Delete\n </DropdownItem>\n ),\n }),\n [hasDeleteAccess],\n );\n const categorizedMessages = getCategorizeMessages(\n conversations,\n additionalMessageProps,\n );\n\n const filterConversations = React.useCallback(\n (targetValue: string) => {\n const filteredConversations = Object.entries(categorizedMessages).reduce(\n (acc, [key, items]) => {\n const filteredItems = items.filter(item =>\n item.text\n .toLocaleLowerCase('en-US')\n .includes(targetValue.toLocaleLowerCase('en-US')),\n );\n if (filteredItems.length > 0) {\n acc[key] = filteredItems;\n }\n return acc;\n },\n {} as any,\n );\n return filteredConversations;\n },\n [categorizedMessages],\n );\n\n React.useEffect(() => {\n setMessages(conversationMessages);\n }, [conversationMessages]);\n\n const onSelectActiveItem = React.useCallback(\n (\n _: React.MouseEvent | undefined,\n selectedItem: string | number | undefined,\n ) => {\n setNewChatCreated(false);\n setConversationId((c_id: string) => {\n if (c_id !== selectedItem) {\n return String(selectedItem);\n }\n return c_id;\n });\n scrollToBottomRef.current?.scrollToBottom();\n },\n [setConversationId, scrollToBottomRef],\n );\n\n const conversationFound = !!conversations.find(\n c => c.conversation_id === conversationId,\n );\n\n const welcomePrompts =\n (newChatCreated && conversationMessages.length === 0) ||\n (!conversationFound && conversationMessages.length === 0)\n ? [\n {\n title: 'Topic 1',\n message: 'Helpful prompt for Topic 1',\n onClick: () => sendMessage('Helpful prompt for Topic 1'),\n },\n {\n title: 'Topic 2',\n message: 'Helpful prompt for Topic 2',\n onClick: () => sendMessage('Helpful prompt for Topic 2'),\n },\n ]\n : [];\n\n const handleFilter = React.useCallback((value: string) => {\n setFilterValue(value);\n }, []);\n\n const onDrawerToggle = React.useCallback(() => {\n setIsDrawerOpen(isOpen => !isOpen);\n }, []);\n\n if (error) {\n return (\n <Box padding={1}>\n <ErrorPanel error={error} />\n </Box>\n );\n }\n\n return (\n <>\n {isDeleteModalOpen && (\n <DeleteModal\n isOpen={isDeleteModalOpen}\n onClose={() => setIsDeleteModalOpen(false)}\n onConfirm={handleDeleteConversation}\n />\n )}\n <Chatbot\n displayMode={ChatbotDisplayMode.embedded}\n className={classes.body}\n >\n <ChatbotHeader className={classes.header}>\n <ChatbotHeaderMain>\n <ChatbotHeaderMenu\n aria-expanded={isDrawerOpen}\n onMenuToggle={() => setIsDrawerOpen(!isDrawerOpen)}\n className={classes.headerMenu}\n />\n <ChatbotHeaderTitle className={classes.headerTitle}>\n <Title headingLevel=\"h1\" size=\"3xl\">\n Developer Hub Lightspeed\n </Title>\n </ChatbotHeaderTitle>\n </ChatbotHeaderMain>\n\n <LightspeedChatBoxHeader\n selectedModel={selectedModel}\n handleSelectedModel={item => handleSelectedModel(item)}\n models={models}\n />\n </ChatbotHeader>\n <ChatbotConversationHistoryNav\n drawerPanelContentProps={{ isResizable: true, minSize: '200px' }}\n reverseButtonOrder\n displayMode={ChatbotDisplayMode.embedded}\n onDrawerToggle={onDrawerToggle}\n isDrawerOpen={isDrawerOpen}\n setIsDrawerOpen={setIsDrawerOpen}\n activeItemId={conversationId}\n onSelectActiveItem={onSelectActiveItem}\n conversations={filterConversations(filterValue)}\n onNewChat={newChatCreated ? undefined : onNewChat}\n handleTextInputChange={handleFilter}\n drawerContent={\n <>\n <ChatbotContent>\n <LightspeedChatBox\n userName={userName}\n messages={messages}\n profileLoading={profileLoading}\n announcement={announcement}\n ref={scrollToBottomRef}\n welcomePrompts={welcomePrompts}\n />\n </ChatbotContent>\n <ChatbotFooter className={classes.footer}>\n <MessageBar\n onSendMessage={sendMessage}\n isSendButtonDisabled={isSendButtonDisabled}\n hasAttachButton={false}\n hasMicrophoneButton\n />\n <ChatbotFootnote {...getFootnoteProps()} />\n </ChatbotFooter>\n </>\n }\n />\n </Chatbot>\n </>\n );\n};\n"],"names":["React"],"mappings":"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"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React__default from 'react';
|
|
2
2
|
import { makeStyles } from '@material-ui/core';
|
|
3
3
|
import { MessageBox, ChatbotWelcomePrompt, Message } from '@patternfly/chatbot';
|
|
4
|
+
import { useAutoScroll } from '../hooks/useAutoScroll.esm.js';
|
|
5
|
+
import { useBufferedMessages } from '../hooks/useBufferedMessages.esm.js';
|
|
4
6
|
|
|
5
7
|
const useStyles = makeStyles((theme) => ({
|
|
6
8
|
prompt: {
|
|
@@ -27,18 +29,47 @@ const LightspeedChatBox = React__default.forwardRef(
|
|
|
27
29
|
profileLoading,
|
|
28
30
|
welcomePrompts
|
|
29
31
|
}, ref) => {
|
|
30
|
-
const [cmessages, setCMessages] = React__default.useState(messages);
|
|
31
32
|
const classes = useStyles();
|
|
33
|
+
const scrollQueued = React__default.useRef(false);
|
|
34
|
+
const containerRef = React__default.useRef(null);
|
|
35
|
+
const cmessages = useBufferedMessages(messages, 30);
|
|
36
|
+
const { autoScroll, scrollToBottom, scrollToTop } = useAutoScroll(containerRef);
|
|
37
|
+
React__default.useImperativeHandle(ref, () => ({
|
|
38
|
+
scrollToBottom: () => {
|
|
39
|
+
if (scrollQueued.current) return;
|
|
40
|
+
scrollQueued.current = true;
|
|
41
|
+
requestAnimationFrame(() => {
|
|
42
|
+
scrollToBottom();
|
|
43
|
+
scrollQueued.current = false;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}));
|
|
32
47
|
React__default.useEffect(() => {
|
|
33
|
-
|
|
34
|
-
|
|
48
|
+
if (!autoScroll || scrollQueued.current) return undefined;
|
|
49
|
+
scrollQueued.current = true;
|
|
50
|
+
const rafId = requestAnimationFrame(() => {
|
|
51
|
+
const container = containerRef.current;
|
|
52
|
+
if (!container) return;
|
|
53
|
+
container.scrollTo({
|
|
54
|
+
top: container.scrollHeight,
|
|
55
|
+
behavior: "auto"
|
|
56
|
+
});
|
|
57
|
+
scrollQueued.current = false;
|
|
58
|
+
});
|
|
59
|
+
return () => {
|
|
60
|
+
cancelAnimationFrame(rafId);
|
|
61
|
+
scrollQueued.current = false;
|
|
62
|
+
};
|
|
63
|
+
}, [autoScroll, cmessages, containerRef]);
|
|
35
64
|
const messageBoxClasses = `${classes.container} ${classes.userMessageText}`;
|
|
36
65
|
return /* @__PURE__ */ React__default.createElement(
|
|
37
66
|
MessageBox,
|
|
38
67
|
{
|
|
39
68
|
className: welcomePrompts.length ? `${messageBoxClasses} ${classes.prompt}` : messageBoxClasses,
|
|
40
69
|
announcement,
|
|
41
|
-
|
|
70
|
+
ref: containerRef,
|
|
71
|
+
onScrollToTopClick: scrollToTop,
|
|
72
|
+
onScrollToBottomClick: scrollToBottom
|
|
42
73
|
},
|
|
43
74
|
welcomePrompts.length ? /* @__PURE__ */ React__default.createElement(
|
|
44
75
|
ChatbotWelcomePrompt,
|
|
@@ -50,7 +81,7 @@ const LightspeedChatBox = React__default.forwardRef(
|
|
|
50
81
|
) : /* @__PURE__ */ React__default.createElement("br", null),
|
|
51
82
|
cmessages.map((message, index) => {
|
|
52
83
|
if (index === cmessages.length - 1) {
|
|
53
|
-
return /* @__PURE__ */ React__default.createElement(React__default.Fragment, { key: `${message.role}-${index}` }, /* @__PURE__ */ React__default.createElement(Message, { key: `${message.role}-${index}`, ...message })
|
|
84
|
+
return /* @__PURE__ */ React__default.createElement(React__default.Fragment, { key: `${message.role}-${index}` }, /* @__PURE__ */ React__default.createElement(Message, { key: `${message.role}-${index}`, ...message }));
|
|
54
85
|
}
|
|
55
86
|
return /* @__PURE__ */ React__default.createElement(Message, { key: `${message.role}-${index}`, ...message });
|
|
56
87
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LightspeedChatBox.esm.js","sources":["../../src/components/LightspeedChatBox.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\n\nimport { makeStyles } from '@material-ui/core';\nimport {\n ChatbotWelcomePrompt,\n Message,\n MessageBox,\n MessageProps,\n WelcomePrompt,\n} from '@patternfly/chatbot';\n\nconst useStyles = makeStyles(theme => ({\n prompt: {\n 'justify-content': 'flex-end',\n },\n container: {\n maxWidth: 'unset !important',\n },\n userMessageText: {\n '& div.pf-chatbot__message--user': {\n '& div.pf-chatbot__message-text': {\n '& p': {\n color: theme.palette.common.white,\n },\n },\n },\n },\n}));\n\ntype LightspeedChatBoxProps = {\n userName?: string;\n messages: MessageProps[];\n profileLoading: boolean;\n announcement: string | undefined;\n welcomePrompts: WelcomePrompt[];\n};\n\nexport const LightspeedChatBox = React.forwardRef(\n (\n {\n userName,\n messages,\n announcement,\n profileLoading,\n welcomePrompts,\n }: LightspeedChatBoxProps,\n ref: React.ForwardedRef<
|
|
1
|
+
{"version":3,"file":"LightspeedChatBox.esm.js","sources":["../../src/components/LightspeedChatBox.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\n\nimport { makeStyles } from '@material-ui/core';\nimport {\n ChatbotWelcomePrompt,\n Message,\n MessageBox,\n MessageProps,\n WelcomePrompt,\n} from '@patternfly/chatbot';\n\nimport { useAutoScroll } from '../hooks/useAutoScroll';\nimport { useBufferedMessages } from '../hooks/useBufferedMessages';\n\nconst useStyles = makeStyles(theme => ({\n prompt: {\n 'justify-content': 'flex-end',\n },\n container: {\n maxWidth: 'unset !important',\n },\n userMessageText: {\n '& div.pf-chatbot__message--user': {\n '& div.pf-chatbot__message-text': {\n '& p': {\n color: theme.palette.common.white,\n },\n },\n },\n },\n}));\n\ntype LightspeedChatBoxProps = {\n userName?: string;\n messages: MessageProps[];\n profileLoading: boolean;\n announcement: string | undefined;\n welcomePrompts: WelcomePrompt[];\n};\n\nexport interface ScrollContainerHandle {\n scrollToBottom: () => void;\n}\n\nexport const LightspeedChatBox = React.forwardRef(\n (\n {\n userName,\n messages,\n announcement,\n profileLoading,\n welcomePrompts,\n }: LightspeedChatBoxProps,\n ref: React.ForwardedRef<ScrollContainerHandle>,\n ) => {\n const classes = useStyles();\n const scrollQueued = React.useRef(false);\n const containerRef = React.useRef<HTMLDivElement>(null);\n\n const cmessages = useBufferedMessages(messages, 30);\n const { autoScroll, scrollToBottom, scrollToTop } =\n useAutoScroll(containerRef);\n\n React.useImperativeHandle(ref, () => ({\n scrollToBottom: () => {\n if (scrollQueued.current) return;\n scrollQueued.current = true;\n\n requestAnimationFrame(() => {\n scrollToBottom();\n scrollQueued.current = false;\n });\n },\n }));\n\n // Auto-scrolls to the latest message\n React.useEffect(() => {\n if (!autoScroll || scrollQueued.current) return undefined;\n\n scrollQueued.current = true;\n\n const rafId = requestAnimationFrame(() => {\n const container = containerRef.current;\n if (!container) return;\n\n container.scrollTo({\n top: container.scrollHeight,\n behavior: 'auto',\n });\n\n scrollQueued.current = false;\n });\n\n return () => {\n cancelAnimationFrame(rafId);\n scrollQueued.current = false;\n };\n\n // eslint-disable-next-line\n }, [autoScroll, cmessages, containerRef]);\n\n const messageBoxClasses = `${classes.container} ${classes.userMessageText}`;\n return (\n <MessageBox\n className={\n welcomePrompts.length\n ? `${messageBoxClasses} ${classes.prompt}`\n : messageBoxClasses\n }\n announcement={announcement}\n ref={containerRef}\n onScrollToTopClick={scrollToTop}\n onScrollToBottomClick={scrollToBottom}\n >\n {welcomePrompts.length ? (\n <ChatbotWelcomePrompt\n title={`Hello, ${profileLoading ? '...' : (userName ?? 'Guest')}`}\n description=\"How can I help you today?\"\n prompts={welcomePrompts}\n />\n ) : (\n <br />\n )}\n {cmessages.map((message, index) => {\n if (index === cmessages.length - 1) {\n return (\n <React.Fragment key={`${message.role}-${index}`}>\n <Message key={`${message.role}-${index}`} {...message} />\n </React.Fragment>\n );\n }\n return <Message key={`${message.role}-${index}`} {...message} />;\n })}\n </MessageBox>\n );\n },\n);\n"],"names":["React"],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
|
|
3
|
+
const useAutoScroll = (containerRef, options = {}) => {
|
|
4
|
+
const { deltaUp = 10, deltaDown = 60, delay = 200 } = options;
|
|
5
|
+
const [autoScroll, setAutoScroll] = React__default.useState(true);
|
|
6
|
+
const lastScrollTop = React__default.useRef(0);
|
|
7
|
+
const manualScrollInterrupted = React__default.useRef(false);
|
|
8
|
+
const debounceTimeout = React__default.useRef(null);
|
|
9
|
+
const onScroll = React__default.useCallback(() => {
|
|
10
|
+
const container = containerRef.current;
|
|
11
|
+
if (!container) return;
|
|
12
|
+
const currentScrollTop = container.scrollTop;
|
|
13
|
+
const isScrollingDown = currentScrollTop > lastScrollTop.current;
|
|
14
|
+
const distanceFromBottom = container.scrollHeight - container.scrollTop - container.clientHeight;
|
|
15
|
+
const delta = isScrollingDown ? deltaDown : deltaUp;
|
|
16
|
+
const isAtBottom = distanceFromBottom <= delta;
|
|
17
|
+
if (debounceTimeout.current) clearTimeout(debounceTimeout.current);
|
|
18
|
+
if (isAtBottom && manualScrollInterrupted.current && isScrollingDown) {
|
|
19
|
+
debounceTimeout.current = setTimeout(() => {
|
|
20
|
+
manualScrollInterrupted.current = false;
|
|
21
|
+
setAutoScroll(true);
|
|
22
|
+
}, delay);
|
|
23
|
+
}
|
|
24
|
+
if (!isAtBottom && !manualScrollInterrupted.current) {
|
|
25
|
+
manualScrollInterrupted.current = true;
|
|
26
|
+
setAutoScroll(false);
|
|
27
|
+
}
|
|
28
|
+
lastScrollTop.current = currentScrollTop;
|
|
29
|
+
}, [containerRef, deltaUp, deltaDown, delay]);
|
|
30
|
+
React__default.useEffect(() => {
|
|
31
|
+
const container = containerRef.current;
|
|
32
|
+
if (!container) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
container.addEventListener("scroll", onScroll, { passive: true });
|
|
36
|
+
return () => {
|
|
37
|
+
container.removeEventListener("scroll", onScroll);
|
|
38
|
+
if (debounceTimeout.current) clearTimeout(debounceTimeout.current);
|
|
39
|
+
};
|
|
40
|
+
}, [onScroll, containerRef]);
|
|
41
|
+
const resumeAutoScroll = React__default.useCallback(() => {
|
|
42
|
+
manualScrollInterrupted.current = false;
|
|
43
|
+
setAutoScroll(true);
|
|
44
|
+
}, []);
|
|
45
|
+
const stopAutoScroll = React__default.useCallback(() => {
|
|
46
|
+
manualScrollInterrupted.current = true;
|
|
47
|
+
setAutoScroll(false);
|
|
48
|
+
}, []);
|
|
49
|
+
const scrollToTop = React__default.useCallback(() => {
|
|
50
|
+
stopAutoScroll();
|
|
51
|
+
const container = containerRef.current;
|
|
52
|
+
if (!container) return;
|
|
53
|
+
container.scrollTo({
|
|
54
|
+
top: 0,
|
|
55
|
+
behavior: "smooth"
|
|
56
|
+
});
|
|
57
|
+
}, [stopAutoScroll, containerRef]);
|
|
58
|
+
const scrollToBottom = React__default.useCallback(() => {
|
|
59
|
+
const container = containerRef.current;
|
|
60
|
+
if (container) {
|
|
61
|
+
container.scrollTo({
|
|
62
|
+
top: container.scrollHeight,
|
|
63
|
+
behavior: "smooth"
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
resumeAutoScroll();
|
|
67
|
+
}, [resumeAutoScroll, containerRef]);
|
|
68
|
+
return {
|
|
69
|
+
autoScroll,
|
|
70
|
+
resumeAutoScroll,
|
|
71
|
+
stopAutoScroll,
|
|
72
|
+
scrollToBottom,
|
|
73
|
+
scrollToTop
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export { useAutoScroll };
|
|
78
|
+
//# sourceMappingURL=useAutoScroll.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAutoScroll.esm.js","sources":["../../src/hooks/useAutoScroll.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\ninterface useAutoScrollOptions {\n deltaUp?: number;\n deltaDown?: number;\n delay?: number;\n}\n\nexport const useAutoScroll = (\n containerRef: React.RefObject<HTMLElement>,\n options: useAutoScrollOptions = {},\n) => {\n const { deltaUp = 10, deltaDown = 60, delay = 200 } = options;\n\n const [autoScroll, setAutoScroll] = React.useState(true);\n const lastScrollTop = React.useRef(0);\n const manualScrollInterrupted = React.useRef(false);\n const debounceTimeout = React.useRef<NodeJS.Timeout | null>(null);\n\n const onScroll = React.useCallback(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const currentScrollTop = container.scrollTop;\n const isScrollingDown = currentScrollTop > lastScrollTop.current;\n\n const distanceFromBottom =\n container.scrollHeight - container.scrollTop - container.clientHeight;\n\n const delta = isScrollingDown ? deltaDown : deltaUp;\n const isAtBottom = distanceFromBottom <= delta;\n\n if (debounceTimeout.current) clearTimeout(debounceTimeout.current);\n\n if (isAtBottom && manualScrollInterrupted.current && isScrollingDown) {\n debounceTimeout.current = setTimeout(() => {\n manualScrollInterrupted.current = false;\n setAutoScroll(true);\n }, delay);\n }\n\n if (!isAtBottom && !manualScrollInterrupted.current) {\n manualScrollInterrupted.current = true;\n setAutoScroll(false);\n }\n\n lastScrollTop.current = currentScrollTop;\n }, [containerRef, deltaUp, deltaDown, delay]);\n\n React.useEffect(() => {\n const container = containerRef.current;\n if (!container) {\n return undefined;\n }\n\n container.addEventListener('scroll', onScroll, { passive: true });\n return () => {\n container.removeEventListener('scroll', onScroll);\n if (debounceTimeout.current) clearTimeout(debounceTimeout.current);\n };\n }, [onScroll, containerRef]);\n\n const resumeAutoScroll = React.useCallback(() => {\n manualScrollInterrupted.current = false;\n setAutoScroll(true);\n }, []);\n\n const stopAutoScroll = React.useCallback(() => {\n manualScrollInterrupted.current = true;\n setAutoScroll(false);\n }, []);\n\n const scrollToTop = React.useCallback(() => {\n stopAutoScroll();\n const container = containerRef.current;\n if (!container) return;\n\n container.scrollTo({\n top: 0,\n behavior: 'smooth',\n });\n }, [stopAutoScroll, containerRef]);\n\n const scrollToBottom = React.useCallback(() => {\n const container = containerRef.current;\n if (container) {\n container.scrollTo({\n top: container.scrollHeight,\n behavior: 'smooth',\n });\n }\n resumeAutoScroll();\n }, [resumeAutoScroll, containerRef]);\n\n return {\n autoScroll,\n resumeAutoScroll,\n stopAutoScroll,\n scrollToBottom,\n scrollToTop,\n };\n};\n"],"names":["React"],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
|
|
3
|
+
const useBufferedMessages = (messages, interval = 30) => {
|
|
4
|
+
const [bufferedMessages, setBufferedMessages] = React__default.useState(messages);
|
|
5
|
+
const lastUpdateTime = React__default.useRef(0);
|
|
6
|
+
const animationFrame = React__default.useRef(null);
|
|
7
|
+
React__default.useEffect(() => {
|
|
8
|
+
const now = Date.now();
|
|
9
|
+
const update = () => {
|
|
10
|
+
setBufferedMessages(messages);
|
|
11
|
+
lastUpdateTime.current = now;
|
|
12
|
+
};
|
|
13
|
+
if (now - lastUpdateTime.current > interval) {
|
|
14
|
+
update();
|
|
15
|
+
} else {
|
|
16
|
+
if (animationFrame.current) cancelAnimationFrame(animationFrame.current);
|
|
17
|
+
animationFrame.current = requestAnimationFrame(update);
|
|
18
|
+
}
|
|
19
|
+
return () => {
|
|
20
|
+
if (animationFrame.current) cancelAnimationFrame(animationFrame.current);
|
|
21
|
+
};
|
|
22
|
+
}, [messages, interval]);
|
|
23
|
+
return bufferedMessages;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export { useBufferedMessages };
|
|
27
|
+
//# sourceMappingURL=useBufferedMessages.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useBufferedMessages.esm.js","sources":["../../src/hooks/useBufferedMessages.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\nexport const useBufferedMessages = <T>(messages: T[], interval = 30): T[] => {\n const [bufferedMessages, setBufferedMessages] = React.useState(messages);\n const lastUpdateTime = React.useRef(0);\n const animationFrame = React.useRef<number | null>(null);\n\n React.useEffect(() => {\n const now = Date.now();\n\n const update = () => {\n setBufferedMessages(messages);\n lastUpdateTime.current = now;\n };\n\n if (now - lastUpdateTime.current > interval) {\n update();\n } else {\n if (animationFrame.current) cancelAnimationFrame(animationFrame.current);\n animationFrame.current = requestAnimationFrame(update);\n }\n\n return () => {\n if (animationFrame.current) cancelAnimationFrame(animationFrame.current);\n };\n }, [messages, interval]);\n\n return bufferedMessages;\n};\n"],"names":["React"],"mappings":";;AAiBO,MAAM,mBAAsB,GAAA,CAAI,QAAe,EAAA,QAAA,GAAW,EAAY,KAAA;AAC3E,EAAA,MAAM,CAAC,gBAAkB,EAAA,mBAAmB,CAAI,GAAAA,cAAA,CAAM,SAAS,QAAQ,CAAA;AACvE,EAAM,MAAA,cAAA,GAAiBA,cAAM,CAAA,MAAA,CAAO,CAAC,CAAA;AACrC,EAAM,MAAA,cAAA,GAAiBA,cAAM,CAAA,MAAA,CAAsB,IAAI,CAAA;AAEvD,EAAAA,cAAA,CAAM,UAAU,MAAM;AACpB,IAAM,MAAA,GAAA,GAAM,KAAK,GAAI,EAAA;AAErB,IAAA,MAAM,SAAS,MAAM;AACnB,MAAA,mBAAA,CAAoB,QAAQ,CAAA;AAC5B,MAAA,cAAA,CAAe,OAAU,GAAA,GAAA;AAAA,KAC3B;AAEA,IAAI,IAAA,GAAA,GAAM,cAAe,CAAA,OAAA,GAAU,QAAU,EAAA;AAC3C,MAAO,MAAA,EAAA;AAAA,KACF,MAAA;AACL,MAAA,IAAI,cAAe,CAAA,OAAA,EAA8B,oBAAA,CAAA,cAAA,CAAe,OAAO,CAAA;AACvE,MAAe,cAAA,CAAA,OAAA,GAAU,sBAAsB,MAAM,CAAA;AAAA;AAGvD,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,cAAe,CAAA,OAAA,EAA8B,oBAAA,CAAA,cAAA,CAAe,OAAO,CAAA;AAAA,KACzE;AAAA,GACC,EAAA,CAAC,QAAU,EAAA,QAAQ,CAAC,CAAA;AAEvB,EAAO,OAAA,gBAAA;AACT;;;;"}
|
|
@@ -43,7 +43,7 @@ const useConversationMessages = (conversationId, userName, selectedModel, avatar
|
|
|
43
43
|
}, [currentConversation, conversationId]);
|
|
44
44
|
const { data: conversationsData = [], ...queryProps } = useFetchConversationMessages(currentConversation);
|
|
45
45
|
React__default.useEffect(() => {
|
|
46
|
-
if (!Array.isArray(conversationsData) || conversationsData.length === 0)
|
|
46
|
+
if (!Array.isArray(conversationsData) || conversationsData.length === 0 && conversationId !== TEMP_CONVERSATION_ID)
|
|
47
47
|
return;
|
|
48
48
|
if (conversations) {
|
|
49
49
|
const _conversations = {
|
|
@@ -123,7 +123,7 @@ const useConversationMessages = (conversationId, userName, selectedModel, avatar
|
|
|
123
123
|
};
|
|
124
124
|
});
|
|
125
125
|
setTimeout(() => {
|
|
126
|
-
scrollToBottomRef.current?.
|
|
126
|
+
scrollToBottomRef.current?.scrollToBottom();
|
|
127
127
|
}, 0);
|
|
128
128
|
const finalMessages = [];
|
|
129
129
|
let buffer = "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useConversationMessages.esm.js","sources":["../../src/hooks/useConversationMessages.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\n\nimport { useApi } from '@backstage/core-plugin-api';\n\nimport { MessageProps } from '@patternfly/chatbot';\nimport { useQuery } from '@tanstack/react-query';\n\nimport { lightspeedApiRef } from '../api/api';\nimport { TEMP_CONVERSATION_ID } from '../const';\nimport logo from '../images/logo.svg';\nimport {\n createBotMessage,\n createUserMessage,\n getMessageData,\n getTimestamp,\n} from '../utils/lightspeed-chatbox-utils';\nimport { useCreateConversationMessage } from './useCreateCoversationMessage';\n\n// Fetch all conversation messages\nexport const useFetchConversationMessages = (currentConversation: string) => {\n const lightspeedApi = useApi(lightspeedApiRef);\n return useQuery({\n queryKey: ['conversationMessages', currentConversation],\n queryFn: currentConversation\n ? async () => {\n const response =\n await lightspeedApi.getConversationMessages(currentConversation);\n\n return response;\n }\n : undefined,\n retry: false,\n });\n};\n\ntype Conversations = { [_key: string]: MessageProps[] };\n\nconst defaultAvatar =\n 'https://img.freepik.com/premium-photo/graphic-designer-digital-avatar-generative-ai_934475-9292.jpg';\n/**\n * Fetches all the messages for given conversation_id\n * @param conversationId\n * @param userName\n * @param selectedModel\n * @param avatar\n *\n */\nexport const useConversationMessages = (\n conversationId: string,\n userName: string | undefined,\n selectedModel: string,\n avatar: string = defaultAvatar,\n onComplete?: (message: string) => void,\n onStart?: (conversation_id: string) => void,\n) => {\n const { mutateAsync: createMessage } = useCreateConversationMessage();\n const scrollToBottomRef = React.useRef<HTMLDivElement>(null);\n\n const [currentConversation, setCurrentConversation] =\n React.useState(conversationId);\n const [conversations, setConversations] = React.useState<Conversations>({\n [currentConversation]: [],\n });\n const streamingConversations = React.useRef<Conversations>({\n [currentConversation]: [],\n });\n\n React.useEffect(() => {\n if (currentConversation !== conversationId) {\n setCurrentConversation(conversationId);\n setConversations(prev => {\n if (prev[conversationId]) return prev;\n\n return {\n ...prev,\n [conversationId]: [],\n };\n });\n }\n }, [currentConversation, conversationId]);\n\n const { data: conversationsData = [], ...queryProps } =\n useFetchConversationMessages(currentConversation);\n\n React.useEffect(() => {\n if (!Array.isArray(conversationsData) || conversationsData.length === 0)\n return;\n\n const newConvoIndex: number[] = [];\n\n if (conversations) {\n const _conversations: { [key: string]: any[] } = {\n [currentConversation]: [],\n };\n\n let index = 0;\n for (let i = 0; i < conversationsData.length; i += 2) {\n const userMessage = conversationsData[i];\n const aiMessage = conversationsData[i + 1];\n\n const { content: humanMessage, timestamp: userTimestamp } =\n getMessageData(userMessage);\n const {\n model,\n content: botMessage,\n timestamp: botTimestamp,\n } = getMessageData(aiMessage);\n\n _conversations[currentConversation].push(\n ...[\n createUserMessage({\n avatar,\n name: userName,\n content: humanMessage,\n timestamp: userTimestamp,\n }),\n createBotMessage({\n avatar: logo,\n isLoading: false,\n name: model ?? selectedModel,\n content: botMessage,\n timestamp: botTimestamp,\n }),\n ],\n );\n\n newConvoIndex.push(index);\n index++;\n }\n\n if (streamingConversations.current[currentConversation]) {\n _conversations[currentConversation].push(\n ...streamingConversations.current[currentConversation],\n );\n }\n\n setConversations(_conversations);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n conversationsData,\n userName,\n avatar,\n currentConversation,\n selectedModel,\n streamingConversations,\n ]);\n\n const handleInputPrompt = React.useCallback(\n async (prompt: string) => {\n let newConversationId = '';\n\n const conversationTuple = [\n createUserMessage({\n avatar,\n name: userName,\n content: prompt,\n timestamp: getTimestamp(Date.now()) ?? '',\n }),\n createBotMessage({\n avatar: logo,\n isLoading: true,\n name: selectedModel,\n content: '',\n timestamp: '',\n }),\n ];\n\n streamingConversations.current = {\n ...streamingConversations.current,\n [currentConversation]: conversationTuple,\n };\n\n setConversations((prevConv: Conversations) => {\n return {\n ...prevConv,\n [currentConversation]: [\n ...(prevConv?.[currentConversation] ?? []),\n ...conversationTuple,\n ],\n };\n });\n\n setTimeout(() => {\n scrollToBottomRef.current?.scrollIntoView({ behavior: 'auto' });\n }, 0);\n const finalMessages: string[] = [];\n let buffer = '';\n\n try {\n const reader = await createMessage({\n prompt,\n selectedModel,\n currentConversation,\n });\n\n const decoder = new TextDecoder('utf-8');\n const keepGoing = true;\n\n while (keepGoing) {\n const { value, done } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n // Process all complete messages separated by double newlines\n const parts = buffer.split('\\n\\n');\n buffer = parts.pop()!;\n\n for (const part of parts) {\n const lines = part\n .split('\\n')\n .filter(line => line.startsWith('data:'));\n\n const jsonString = lines\n .map(line => line.trim().slice(5).trim())\n .join('');\n try {\n const { event, data } = JSON.parse(jsonString);\n if (event === 'start') {\n if (currentConversation === TEMP_CONVERSATION_ID) {\n // If the conversation is temp, we need to set the new conversation id\n newConversationId = data?.conversation_id;\n }\n }\n\n if (event === 'token') {\n const content = data?.token || '';\n\n finalMessages.push(content);\n\n // Store streaming message\n const [humanMessage, aiMessage] =\n streamingConversations.current[currentConversation];\n streamingConversations.current[currentConversation] = [\n humanMessage,\n { ...aiMessage, content: aiMessage.content + content },\n ];\n\n setConversations(prevConversations => {\n const conversation =\n prevConversations[currentConversation] ?? [];\n\n const lastMessageIndex = conversation.length - 1;\n const lastMessage =\n conversation.length === 0\n ? createBotMessage({\n content: '',\n timestamp: getTimestamp(Date.now()),\n })\n : { ...conversation[lastMessageIndex] };\n\n lastMessage.isLoading = false;\n lastMessage.content += content;\n lastMessage.name =\n data?.response_metadata?.model || selectedModel;\n lastMessage.timestamp = getTimestamp(\n data?.response_metadata?.created_at || Date.now(),\n );\n\n const updatedConversation = [\n ...conversation.slice(0, lastMessageIndex),\n lastMessage,\n ];\n\n return {\n ...prevConversations,\n [currentConversation]: updatedConversation,\n };\n });\n }\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('Error parsing JSON:', error);\n if (typeof onComplete === 'function') {\n onComplete('Invalid JSON received');\n }\n }\n }\n }\n } catch (e) {\n setConversations(prevConversations => {\n const conversation = prevConversations[currentConversation] ?? [];\n\n const lastMessageIndex = conversation.length - 1;\n const lastMessage =\n conversation.length === 0\n ? createBotMessage({\n content: '',\n timestamp: getTimestamp(Date.now()),\n })\n : { ...conversation[lastMessageIndex] };\n\n lastMessage.isLoading = false;\n lastMessage.content += e;\n lastMessage.error = {\n title: e.message,\n };\n lastMessage.timestamp = getTimestamp(Date.now());\n\n const updatedConversation = [\n ...conversation.slice(0, lastMessageIndex),\n lastMessage,\n ];\n\n finalMessages.push(`${e}`);\n\n return {\n ...prevConversations,\n [newConversationId.length > 0\n ? newConversationId\n : currentConversation]: updatedConversation,\n };\n });\n }\n // reset current streaming\n streamingConversations.current[currentConversation] = [];\n if (typeof onComplete === 'function') {\n onComplete(finalMessages.join(''));\n }\n // Swap temp conversation messages with new conversation\n\n if (currentConversation === TEMP_CONVERSATION_ID && newConversationId) {\n setConversations(prevConversations => {\n return {\n ...prevConversations,\n [newConversationId]: prevConversations[TEMP_CONVERSATION_ID],\n };\n });\n\n onStart?.(newConversationId);\n\n setConversations(prev => {\n const { temp, ...rest } = prev;\n return rest;\n });\n }\n },\n\n [\n avatar,\n userName,\n onComplete,\n onStart,\n selectedModel,\n createMessage,\n currentConversation,\n ],\n );\n\n return {\n conversationMessages: conversations[currentConversation] ?? [],\n handleInputPrompt,\n conversations,\n scrollToBottomRef,\n ...queryProps,\n };\n};\n"],"names":["React"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useConversationMessages.esm.js","sources":["../../src/hooks/useConversationMessages.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\n\nimport { useApi } from '@backstage/core-plugin-api';\n\nimport { MessageProps } from '@patternfly/chatbot';\nimport { useQuery } from '@tanstack/react-query';\n\nimport { lightspeedApiRef } from '../api/api';\nimport { ScrollContainerHandle } from '../components/LightspeedChatBox';\nimport { TEMP_CONVERSATION_ID } from '../const';\nimport logo from '../images/logo.svg';\nimport {\n createBotMessage,\n createUserMessage,\n getMessageData,\n getTimestamp,\n} from '../utils/lightspeed-chatbox-utils';\nimport { useCreateConversationMessage } from './useCreateCoversationMessage';\n\n// Fetch all conversation messages\nexport const useFetchConversationMessages = (currentConversation: string) => {\n const lightspeedApi = useApi(lightspeedApiRef);\n return useQuery({\n queryKey: ['conversationMessages', currentConversation],\n queryFn: currentConversation\n ? async () => {\n const response =\n await lightspeedApi.getConversationMessages(currentConversation);\n\n return response;\n }\n : undefined,\n retry: false,\n });\n};\n\ntype Conversations = { [_key: string]: MessageProps[] };\n\nconst defaultAvatar =\n 'https://img.freepik.com/premium-photo/graphic-designer-digital-avatar-generative-ai_934475-9292.jpg';\n/**\n * Fetches all the messages for given conversation_id\n * @param conversationId\n * @param userName\n * @param selectedModel\n * @param avatar\n *\n */\nexport const useConversationMessages = (\n conversationId: string,\n userName: string | undefined,\n selectedModel: string,\n avatar: string = defaultAvatar,\n onComplete?: (message: string) => void,\n onStart?: (conversation_id: string) => void,\n) => {\n const { mutateAsync: createMessage } = useCreateConversationMessage();\n const scrollToBottomRef = React.useRef<ScrollContainerHandle>(null);\n\n const [currentConversation, setCurrentConversation] =\n React.useState(conversationId);\n const [conversations, setConversations] = React.useState<Conversations>({\n [currentConversation]: [],\n });\n const streamingConversations = React.useRef<Conversations>({\n [currentConversation]: [],\n });\n\n React.useEffect(() => {\n if (currentConversation !== conversationId) {\n setCurrentConversation(conversationId);\n setConversations(prev => {\n if (prev[conversationId]) return prev;\n\n return {\n ...prev,\n [conversationId]: [],\n };\n });\n }\n }, [currentConversation, conversationId]);\n\n const { data: conversationsData = [], ...queryProps } =\n useFetchConversationMessages(currentConversation);\n\n React.useEffect(() => {\n if (\n !Array.isArray(conversationsData) ||\n (conversationsData.length === 0 &&\n conversationId !== TEMP_CONVERSATION_ID)\n )\n return;\n\n const newConvoIndex: number[] = [];\n\n if (conversations) {\n const _conversations: { [key: string]: any[] } = {\n [currentConversation]: [],\n };\n\n let index = 0;\n for (let i = 0; i < conversationsData.length; i += 2) {\n const userMessage = conversationsData[i];\n const aiMessage = conversationsData[i + 1];\n\n const { content: humanMessage, timestamp: userTimestamp } =\n getMessageData(userMessage);\n const {\n model,\n content: botMessage,\n timestamp: botTimestamp,\n } = getMessageData(aiMessage);\n\n _conversations[currentConversation].push(\n ...[\n createUserMessage({\n avatar,\n name: userName,\n content: humanMessage,\n timestamp: userTimestamp,\n }),\n createBotMessage({\n avatar: logo,\n isLoading: false,\n name: model ?? selectedModel,\n content: botMessage,\n timestamp: botTimestamp,\n }),\n ],\n );\n\n newConvoIndex.push(index);\n index++;\n }\n\n if (streamingConversations.current[currentConversation]) {\n _conversations[currentConversation].push(\n ...streamingConversations.current[currentConversation],\n );\n }\n\n setConversations(_conversations);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n conversationsData,\n userName,\n avatar,\n currentConversation,\n selectedModel,\n streamingConversations,\n ]);\n\n const handleInputPrompt = React.useCallback(\n async (prompt: string) => {\n let newConversationId = '';\n\n const conversationTuple = [\n createUserMessage({\n avatar,\n name: userName,\n content: prompt,\n timestamp: getTimestamp(Date.now()) ?? '',\n }),\n createBotMessage({\n avatar: logo,\n isLoading: true,\n name: selectedModel,\n content: '',\n timestamp: '',\n }),\n ];\n\n streamingConversations.current = {\n ...streamingConversations.current,\n [currentConversation]: conversationTuple,\n };\n\n setConversations((prevConv: Conversations) => {\n return {\n ...prevConv,\n [currentConversation]: [\n ...(prevConv?.[currentConversation] ?? []),\n ...conversationTuple,\n ],\n };\n });\n\n setTimeout(() => {\n scrollToBottomRef.current?.scrollToBottom();\n }, 0);\n const finalMessages: string[] = [];\n let buffer = '';\n\n try {\n const reader = await createMessage({\n prompt,\n selectedModel,\n currentConversation,\n });\n\n const decoder = new TextDecoder('utf-8');\n const keepGoing = true;\n\n while (keepGoing) {\n const { value, done } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n // Process all complete messages separated by double newlines\n const parts = buffer.split('\\n\\n');\n buffer = parts.pop()!;\n\n for (const part of parts) {\n const lines = part\n .split('\\n')\n .filter(line => line.startsWith('data:'));\n\n const jsonString = lines\n .map(line => line.trim().slice(5).trim())\n .join('');\n try {\n const { event, data } = JSON.parse(jsonString);\n if (event === 'start') {\n if (currentConversation === TEMP_CONVERSATION_ID) {\n // If the conversation is temp, we need to set the new conversation id\n newConversationId = data?.conversation_id;\n }\n }\n\n if (event === 'token') {\n const content = data?.token || '';\n\n finalMessages.push(content);\n\n // Store streaming message\n const [humanMessage, aiMessage] =\n streamingConversations.current[currentConversation];\n streamingConversations.current[currentConversation] = [\n humanMessage,\n { ...aiMessage, content: aiMessage.content + content },\n ];\n\n setConversations(prevConversations => {\n const conversation =\n prevConversations[currentConversation] ?? [];\n\n const lastMessageIndex = conversation.length - 1;\n const lastMessage =\n conversation.length === 0\n ? createBotMessage({\n content: '',\n timestamp: getTimestamp(Date.now()),\n })\n : { ...conversation[lastMessageIndex] };\n\n lastMessage.isLoading = false;\n lastMessage.content += content;\n lastMessage.name =\n data?.response_metadata?.model || selectedModel;\n lastMessage.timestamp = getTimestamp(\n data?.response_metadata?.created_at || Date.now(),\n );\n\n const updatedConversation = [\n ...conversation.slice(0, lastMessageIndex),\n lastMessage,\n ];\n\n return {\n ...prevConversations,\n [currentConversation]: updatedConversation,\n };\n });\n }\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('Error parsing JSON:', error);\n if (typeof onComplete === 'function') {\n onComplete('Invalid JSON received');\n }\n }\n }\n }\n } catch (e) {\n setConversations(prevConversations => {\n const conversation = prevConversations[currentConversation] ?? [];\n\n const lastMessageIndex = conversation.length - 1;\n const lastMessage =\n conversation.length === 0\n ? createBotMessage({\n content: '',\n timestamp: getTimestamp(Date.now()),\n })\n : { ...conversation[lastMessageIndex] };\n\n lastMessage.isLoading = false;\n lastMessage.content += e;\n lastMessage.error = {\n title: e.message,\n };\n lastMessage.timestamp = getTimestamp(Date.now());\n\n const updatedConversation = [\n ...conversation.slice(0, lastMessageIndex),\n lastMessage,\n ];\n\n finalMessages.push(`${e}`);\n\n return {\n ...prevConversations,\n [newConversationId.length > 0\n ? newConversationId\n : currentConversation]: updatedConversation,\n };\n });\n }\n // reset current streaming\n streamingConversations.current[currentConversation] = [];\n if (typeof onComplete === 'function') {\n onComplete(finalMessages.join(''));\n }\n // Swap temp conversation messages with new conversation\n\n if (currentConversation === TEMP_CONVERSATION_ID && newConversationId) {\n setConversations(prevConversations => {\n return {\n ...prevConversations,\n [newConversationId]: prevConversations[TEMP_CONVERSATION_ID],\n };\n });\n\n onStart?.(newConversationId);\n\n setConversations(prev => {\n const { temp, ...rest } = prev;\n return rest;\n });\n }\n },\n\n [\n avatar,\n userName,\n onComplete,\n onStart,\n selectedModel,\n createMessage,\n currentConversation,\n ],\n );\n\n return {\n conversationMessages: conversations[currentConversation] ?? [],\n handleInputPrompt,\n conversations,\n scrollToBottomRef,\n ...queryProps,\n };\n};\n"],"names":["React"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@red-hat-developer-hub/backstage-plugin-lightspeed",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"main": "dist/index.esm.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"@material-ui/core": "^4.9.13",
|
|
45
45
|
"@material-ui/lab": "^4.0.0-alpha.61",
|
|
46
46
|
"@mui/icons-material": "^6.1.8",
|
|
47
|
-
"@patternfly/chatbot": "
|
|
48
|
-
"@patternfly/react-core": "6.
|
|
47
|
+
"@patternfly/chatbot": "6.3.0-prerelease.10",
|
|
48
|
+
"@patternfly/react-core": "6.3.0-prerelease.2",
|
|
49
49
|
"@red-hat-developer-hub/backstage-plugin-lightspeed-common": "^0.3.0",
|
|
50
50
|
"@tanstack/react-query": "^5.59.15",
|
|
51
51
|
"openai": "^4.52.6",
|