@red-hat-developer-hub/backstage-plugin-intelligent-assistant 5.0.0 → 5.0.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 +9 -0
- package/dist/components/Attachment.esm.js +4 -2
- package/dist/components/Attachment.esm.js.map +1 -1
- package/dist/components/DeleteModal.esm.js +1 -0
- package/dist/components/DeleteModal.esm.js.map +1 -1
- package/dist/components/LightspeedChatBox.esm.js +44 -71
- package/dist/components/LightspeedChatBox.esm.js.map +1 -1
- package/dist/components/RagSourceLabel.esm.js +22 -0
- package/dist/components/RagSourceLabel.esm.js.map +1 -0
- package/dist/components/SourcesChipModal.esm.js +94 -89
- package/dist/components/SourcesChipModal.esm.js.map +1 -1
- package/dist/hooks/useFeedbackActions.esm.js.map +1 -1
- package/dist/types.esm.js.map +1 -1
- package/dist/utils/lightspeed-chatbox-utils.esm.js +13 -6
- package/dist/utils/lightspeed-chatbox-utils.esm.js.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @red-hat-developer-hub/backstage-plugin-intelligent-assistant
|
|
2
2
|
|
|
3
|
+
## 5.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 0f8225e: Show the LCORE `source` field as a label on each referenced document card so that RAG sources are distinguishable.
|
|
8
|
+
- fe51be2: Backstage version bump to v1.54.6
|
|
9
|
+
- Updated dependencies [fe51be2]
|
|
10
|
+
- @red-hat-developer-hub/backstage-plugin-intelligent-assistant-common@5.0.1
|
|
11
|
+
|
|
3
12
|
## 5.0.0
|
|
4
13
|
|
|
5
14
|
### Major Changes
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { makeStyles } from '@material-ui/core';
|
|
3
|
-
import {
|
|
3
|
+
import { ChatbotDisplayMode } from '@patternfly/chatbot';
|
|
4
|
+
import { AttachmentEdit } from '@patternfly/chatbot/dist/dynamic/AttachmentEdit';
|
|
5
|
+
import { PreviewAttachment } from '@patternfly/chatbot/dist/dynamic/PreviewAttachment';
|
|
4
6
|
import { useTranslation } from '../hooks/useTranslation.esm.js';
|
|
5
7
|
import { useFileAttachmentContext } from './AttachmentContext.esm.js';
|
|
6
8
|
|
|
@@ -65,7 +67,7 @@ const Attachment = () => {
|
|
|
65
67
|
secondaryActionButtonText: t("modal.cancel"),
|
|
66
68
|
primaryActionButtonText: t("modal.save"),
|
|
67
69
|
modalFooterClassName: classes.modalFooter,
|
|
68
|
-
onSave: (
|
|
70
|
+
onSave: (_event, content) => {
|
|
69
71
|
setCurrentFileContent({
|
|
70
72
|
...currentFileContent,
|
|
71
73
|
content
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Attachment.esm.js","sources":["../../src/components/Attachment.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 { makeStyles } from '@material-ui/core';\nimport {
|
|
1
|
+
{"version":3,"file":"Attachment.esm.js","sources":["../../src/components/Attachment.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 { makeStyles } from '@material-ui/core';\nimport { ChatbotDisplayMode } from '@patternfly/chatbot';\nimport { AttachmentEdit } from '@patternfly/chatbot/dist/dynamic/AttachmentEdit';\nimport { PreviewAttachment } from '@patternfly/chatbot/dist/dynamic/PreviewAttachment';\n\nimport { useTranslation } from '../hooks/useTranslation';\nimport { useFileAttachmentContext } from './AttachmentContext';\n\nconst useStyles = makeStyles(() => ({\n modalFooter: {\n '&>button': {\n width: '12% !important',\n },\n },\n}));\nconst Attachment = () => {\n const {\n currentFileContent,\n setFileContents,\n modalState,\n setCurrentFileContent,\n } = useFileAttachmentContext();\n const classes = useStyles();\n const { t } = useTranslation();\n\n if (!currentFileContent) {\n return null;\n }\n const {\n previewModalKey,\n isPreviewModalOpen,\n isEditModalOpen,\n setPreviewModalKey,\n setIsEditModalOpen,\n setIsPreviewModalOpen,\n } = modalState;\n\n return (\n <>\n <PreviewAttachment\n key={previewModalKey}\n code={currentFileContent?.content}\n fileName={currentFileContent?.name}\n isModalOpen={isPreviewModalOpen}\n secondaryActionButtonText={t('modal.close')}\n primaryActionButtonText={t('modal.edit')}\n title={t('modal.title.preview')}\n modalFooterClassName={classes.modalFooter}\n onEdit={() => {\n setIsPreviewModalOpen(false);\n setIsEditModalOpen(true);\n }}\n onDismiss={() => {\n setCurrentFileContent(undefined);\n setIsPreviewModalOpen(false);\n }}\n handleModalToggle={() => setIsPreviewModalOpen(false)}\n displayMode={ChatbotDisplayMode.fullscreen}\n />\n <AttachmentEdit\n key={currentFileContent?.content}\n code={currentFileContent?.content}\n fileName={currentFileContent?.name}\n isModalOpen={isEditModalOpen}\n title={t('modal.title.edit')}\n secondaryActionButtonText={t('modal.cancel')}\n primaryActionButtonText={t('modal.save')}\n modalFooterClassName={classes.modalFooter}\n onSave={(_event, content) => {\n setCurrentFileContent({\n ...currentFileContent,\n content,\n });\n setFileContents(prev => {\n const existingIndex = prev.findIndex(\n f => f.name === currentFileContent?.name,\n );\n\n if (existingIndex !== -1) {\n // Update the existing file's content\n const updated = [...prev];\n updated[existingIndex] = {\n ...updated[existingIndex],\n content: content as string,\n };\n return updated;\n }\n\n // File doesn't exist, add a new one\n return [\n ...prev,\n {\n name: currentFileContent?.name,\n type: currentFileContent?.type,\n content: content as string,\n },\n ];\n });\n\n setPreviewModalKey(prev => prev + 1);\n setIsEditModalOpen(false);\n setIsPreviewModalOpen(true);\n }}\n onCancel={() => setCurrentFileContent(undefined)}\n handleModalToggle={() => setIsEditModalOpen(false)}\n displayMode={ChatbotDisplayMode.fullscreen}\n />\n </>\n );\n};\n\nexport default Attachment;\n"],"names":[],"mappings":"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"}
|
|
@@ -9,6 +9,7 @@ import '@mui/material/styles';
|
|
|
9
9
|
import '@patternfly/chatbot';
|
|
10
10
|
import '@patternfly/react-icons';
|
|
11
11
|
import '@patternfly/react-icons/dist/esm/icons/rh-ui-ai-info-icon';
|
|
12
|
+
import '@mui/material/Box';
|
|
12
13
|
import { useDeleteConversation } from '../hooks/useDeleteConversation.esm.js';
|
|
13
14
|
import '../api/notebooksApi.esm.js';
|
|
14
15
|
import '@backstage/plugin-permission-react';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeleteModal.esm.js","sources":["../../src/components/DeleteModal.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 {\n Alert,\n Button,\n Modal,\n ModalBody,\n ModalFooter,\n ModalHeader,\n} from '@patternfly/react-core';\n\nimport { useDeleteConversation } from '../hooks';\nimport { useTranslation } from '../hooks/useTranslation';\n\nexport const DeleteModal = ({\n isOpen,\n conversationId,\n chatName,\n onClose,\n onConfirm,\n}: {\n isOpen: boolean;\n conversationId: string;\n chatName?: string;\n onClose: () => void;\n onConfirm: () => void;\n}) => {\n const { t } = useTranslation();\n const {\n mutateAsync: deleteConversation,\n isError,\n error,\n isPending,\n } = useDeleteConversation();\n\n const handleDeleteConversation = async () => {\n try {\n await deleteConversation({\n conversation_id: conversationId,\n invalidateCache: false,\n });\n onConfirm();\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn(e);\n }\n };\n\n return (\n <Modal\n variant=\"small\"\n isOpen={isOpen}\n onClose={onClose}\n aria-labelledby=\"delete-modal\"\n aria-describedby=\"delete-modal-confirmation\"\n >\n <ModalHeader\n title={t('conversation.delete.confirm.title' as any, {\n chatName: chatName || '',\n })}\n labelId=\"delete-modal\"\n descriptorId=\"delete-modal-confirmation\"\n />\n <ModalBody id=\"delete-modal-confirmation\">\n {t('conversation.delete.confirm.message')}\n {isError && (\n <Alert\n variant=\"danger\"\n isInline\n title={String(error)}\n className=\"pf-v6-u-mt-md\"\n />\n )}\n </ModalBody>\n <ModalFooter>\n <Button\n variant=\"danger\"\n onClick={handleDeleteConversation}\n isDisabled={isPending}\n >\n {t('conversation.delete.confirm.action')}\n </Button>\n <Button variant=\"link\" onClick={onClose}>\n {t('common.cancel')}\n </Button>\n </ModalFooter>\n </Modal>\n );\n};\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DeleteModal.esm.js","sources":["../../src/components/DeleteModal.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 {\n Alert,\n Button,\n Modal,\n ModalBody,\n ModalFooter,\n ModalHeader,\n} from '@patternfly/react-core';\n\nimport { useDeleteConversation } from '../hooks';\nimport { useTranslation } from '../hooks/useTranslation';\n\nexport const DeleteModal = ({\n isOpen,\n conversationId,\n chatName,\n onClose,\n onConfirm,\n}: {\n isOpen: boolean;\n conversationId: string;\n chatName?: string;\n onClose: () => void;\n onConfirm: () => void;\n}) => {\n const { t } = useTranslation();\n const {\n mutateAsync: deleteConversation,\n isError,\n error,\n isPending,\n } = useDeleteConversation();\n\n const handleDeleteConversation = async () => {\n try {\n await deleteConversation({\n conversation_id: conversationId,\n invalidateCache: false,\n });\n onConfirm();\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn(e);\n }\n };\n\n return (\n <Modal\n variant=\"small\"\n isOpen={isOpen}\n onClose={onClose}\n aria-labelledby=\"delete-modal\"\n aria-describedby=\"delete-modal-confirmation\"\n >\n <ModalHeader\n title={t('conversation.delete.confirm.title' as any, {\n chatName: chatName || '',\n })}\n labelId=\"delete-modal\"\n descriptorId=\"delete-modal-confirmation\"\n />\n <ModalBody id=\"delete-modal-confirmation\">\n {t('conversation.delete.confirm.message')}\n {isError && (\n <Alert\n variant=\"danger\"\n isInline\n title={String(error)}\n className=\"pf-v6-u-mt-md\"\n />\n )}\n </ModalBody>\n <ModalFooter>\n <Button\n variant=\"danger\"\n onClick={handleDeleteConversation}\n isDisabled={isPending}\n >\n {t('conversation.delete.confirm.action')}\n </Button>\n <Button variant=\"link\" onClick={onClose}>\n {t('common.cancel')}\n </Button>\n </ModalFooter>\n </Modal>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AA4BO,MAAM,cAAc,CAAC;AAAA,EAC1B,MAAA;AAAA,EACA,cAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA,KAMM;AACJ,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,cAAA,EAAe;AAC7B,EAAA,MAAM;AAAA,IACJ,WAAA,EAAa,kBAAA;AAAA,IACb,OAAA;AAAA,IACA,KAAA;AAAA,IACA;AAAA,MACE,qBAAA,EAAsB;AAE1B,EAAA,MAAM,2BAA2B,YAAY;AAC3C,IAAA,IAAI;AACF,MAAA,MAAM,kBAAA,CAAmB;AAAA,QACvB,eAAA,EAAiB,cAAA;AAAA,QACjB,eAAA,EAAiB;AAAA,OAClB,CAAA;AACD,MAAA,SAAA,EAAU;AAAA,IACZ,SAAS,CAAA,EAAG;AAEV,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAChB;AAAA,EACF,CAAA;AAEA,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAQ,OAAA;AAAA,MACR,MAAA;AAAA,MACA,OAAA;AAAA,MACA,iBAAA,EAAgB,cAAA;AAAA,MAChB,kBAAA,EAAiB,2BAAA;AAAA,MAEjB,QAAA,EAAA;AAAA,wBAAA,GAAA;AAAA,UAAC,WAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAO,EAAE,mCAAA,EAA4C;AAAA,cACnD,UAAU,QAAA,IAAY;AAAA,aACvB,CAAA;AAAA,YACD,OAAA,EAAQ,cAAA;AAAA,YACR,YAAA,EAAa;AAAA;AAAA,SACf;AAAA,wBACA,IAAA,CAAC,SAAA,EAAA,EAAU,EAAA,EAAG,2BAAA,EACX,QAAA,EAAA;AAAA,UAAA,CAAA,CAAE,qCAAqC,CAAA;AAAA,UACvC,OAAA,oBACC,GAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,OAAA,EAAQ,QAAA;AAAA,cACR,QAAA,EAAQ,IAAA;AAAA,cACR,KAAA,EAAO,OAAO,KAAK,CAAA;AAAA,cACnB,SAAA,EAAU;AAAA;AAAA;AACZ,SAAA,EAEJ,CAAA;AAAA,6BACC,WAAA,EAAA,EACC,QAAA,EAAA;AAAA,0BAAA,GAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,OAAA,EAAQ,QAAA;AAAA,cACR,OAAA,EAAS,wBAAA;AAAA,cACT,UAAA,EAAY,SAAA;AAAA,cAEX,YAAE,oCAAoC;AAAA;AAAA,WACzC;AAAA,0BACA,GAAA,CAAC,UAAO,OAAA,EAAQ,MAAA,EAAO,SAAS,OAAA,EAC7B,QAAA,EAAA,CAAA,CAAE,eAAe,CAAA,EACpB;AAAA,SAAA,EACF;AAAA;AAAA;AAAA,GACF;AAEJ;;;;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import { forwardRef, useRef, useImperativeHandle, useEffect } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { keyframes, styled } from '@mui/material/styles';
|
|
4
|
+
import { MessageBox, ChatbotDisplayMode, ChatbotWelcomePrompt, ToolCall, DeepThinking, Message } from '@patternfly/chatbot';
|
|
5
5
|
import { Alert } from '@patternfly/react-core';
|
|
6
6
|
import { useAutoScroll } from '../hooks/useAutoScroll.esm.js';
|
|
7
7
|
import { useBufferedMessages } from '../hooks/useBufferedMessages.esm.js';
|
|
@@ -11,57 +11,48 @@ import { parseReasoning } from '../utils/reasoningParser.esm.js';
|
|
|
11
11
|
import { mapToPatternFlyToolCall } from '../utils/toolCallMapper.esm.js';
|
|
12
12
|
import { SourcesChipModal } from './SourcesChipModal.esm.js';
|
|
13
13
|
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
userMessageText: {
|
|
14
|
+
const DEEP_THINKING_CLASS = "lightspeed-deep-thinking";
|
|
15
|
+
const deepThinkingPulse = keyframes`
|
|
16
|
+
0% { opacity: 0.65 }
|
|
17
|
+
50% { opacity: 1 }
|
|
18
|
+
100% { opacity: 0.65 }
|
|
19
|
+
`;
|
|
20
|
+
const StyledMessageBox = styled(MessageBox, {
|
|
21
|
+
shouldForwardProp: (prop) => prop !== "$isNewChat" && prop !== "$hasWelcomePrompts" && prop !== "$showPromptSuggestions"
|
|
22
|
+
})(
|
|
23
|
+
({ theme, $isNewChat, $hasWelcomePrompts, $showPromptSuggestions }) => ({
|
|
24
|
+
maxWidth: "unset !important",
|
|
25
|
+
[`& .${DEEP_THINKING_CLASS}`]: {
|
|
26
|
+
animation: `${deepThinkingPulse} 1.6s ease-in-out infinite`
|
|
27
|
+
},
|
|
30
28
|
"& div.pf-chatbot__message--user": {
|
|
31
29
|
"& div.pf-chatbot__message-text": {
|
|
32
30
|
"& p": {
|
|
33
31
|
color: theme.palette.common.white
|
|
34
32
|
}
|
|
35
33
|
}
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
deepThinking: {
|
|
39
|
-
animation: "$deepThinking 1.6s ease-in-out infinite"
|
|
40
|
-
},
|
|
41
|
-
"@keyframes deepThinking": {
|
|
42
|
-
"0%": {
|
|
43
|
-
opacity: 0.65
|
|
44
34
|
},
|
|
45
|
-
|
|
46
|
-
|
|
35
|
+
...$isNewChat ? {
|
|
36
|
+
flex: "none",
|
|
37
|
+
height: "auto",
|
|
38
|
+
overflow: "visible"
|
|
39
|
+
} : {
|
|
40
|
+
flex: 1,
|
|
41
|
+
minHeight: 0
|
|
47
42
|
},
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
height: "auto",
|
|
62
|
-
overflow: "visible"
|
|
63
|
-
}
|
|
64
|
-
}));
|
|
43
|
+
...$hasWelcomePrompts ? {
|
|
44
|
+
justifyContent: "flex-end"
|
|
45
|
+
} : {},
|
|
46
|
+
...$showPromptSuggestions ? {
|
|
47
|
+
"& div.pf-chatbot__prompt-suggestions": {
|
|
48
|
+
flexDirection: "column !important"
|
|
49
|
+
}
|
|
50
|
+
} : {}
|
|
51
|
+
})
|
|
52
|
+
);
|
|
53
|
+
const DisclaimerAlert = styled(Alert)({
|
|
54
|
+
background: "unset !important"
|
|
55
|
+
});
|
|
65
56
|
const LightspeedChatBox = forwardRef(
|
|
66
57
|
({
|
|
67
58
|
userName,
|
|
@@ -75,7 +66,6 @@ const LightspeedChatBox = forwardRef(
|
|
|
75
66
|
displayMode,
|
|
76
67
|
showSourcesChipPopover: showSourcesChipModal = false
|
|
77
68
|
}, ref) => {
|
|
78
|
-
const classes = useStyles();
|
|
79
69
|
const scrollQueued = useRef(false);
|
|
80
70
|
const containerRef = useRef(null);
|
|
81
71
|
const { t } = useTranslation();
|
|
@@ -115,24 +105,16 @@ const LightspeedChatBox = forwardRef(
|
|
|
115
105
|
scrollQueued.current = false;
|
|
116
106
|
};
|
|
117
107
|
}, [autoScroll, cmessages, containerRef]);
|
|
118
|
-
const messageBoxClasses = `${classes.container} ${classes.userMessageText}`;
|
|
119
108
|
const isEmbeddedMode = displayMode === ChatbotDisplayMode.embedded;
|
|
120
109
|
const isNewChat = welcomePrompts.length > 0 && messages.length === 0;
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
if (!welcomePrompts.length) {
|
|
124
|
-
return base;
|
|
125
|
-
}
|
|
126
|
-
const withPrompt = `${base} ${classes.prompt}`;
|
|
127
|
-
if (isEmbeddedMode) {
|
|
128
|
-
return withPrompt;
|
|
129
|
-
}
|
|
130
|
-
return `${withPrompt} ${classes.promptSuggestions}`;
|
|
131
|
-
};
|
|
110
|
+
const hasWelcomePrompts = welcomePrompts.length > 0;
|
|
111
|
+
const showPromptSuggestions = hasWelcomePrompts && !isEmbeddedMode;
|
|
132
112
|
return /* @__PURE__ */ jsxs(
|
|
133
|
-
|
|
113
|
+
StyledMessageBox,
|
|
134
114
|
{
|
|
135
|
-
|
|
115
|
+
$isNewChat: isNewChat,
|
|
116
|
+
$hasWelcomePrompts: hasWelcomePrompts,
|
|
117
|
+
$showPromptSuggestions: showPromptSuggestions,
|
|
136
118
|
announcement,
|
|
137
119
|
ref: containerRef,
|
|
138
120
|
onScrollToTopClick: scrollToTop,
|
|
@@ -143,16 +125,7 @@ const LightspeedChatBox = forwardRef(
|
|
|
143
125
|
jumpButtonTopTooltipProps: { content: t("tooltip.backToTop") },
|
|
144
126
|
children: [
|
|
145
127
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
146
|
-
/* @__PURE__ */ jsx(
|
|
147
|
-
Alert,
|
|
148
|
-
{
|
|
149
|
-
title: t("aria.important"),
|
|
150
|
-
variant: "info",
|
|
151
|
-
isInline: true,
|
|
152
|
-
className: classes.alert,
|
|
153
|
-
children: topicRestrictionEnabled ? t("disclaimer.withValidation") : t("disclaimer.withoutValidation")
|
|
154
|
-
}
|
|
155
|
-
),
|
|
128
|
+
/* @__PURE__ */ jsx(DisclaimerAlert, { title: t("aria.important"), variant: "info", isInline: true, children: topicRestrictionEnabled ? t("disclaimer.withValidation") : t("disclaimer.withoutValidation") }),
|
|
156
129
|
/* @__PURE__ */ jsx("br", {})
|
|
157
130
|
] }),
|
|
158
131
|
welcomePrompts.length ? /* @__PURE__ */ jsx(
|
|
@@ -181,7 +154,7 @@ const LightspeedChatBox = forwardRef(
|
|
|
181
154
|
cardBodyProps: {
|
|
182
155
|
id: `deep-thinking-${index}`,
|
|
183
156
|
style: { whiteSpace: "pre-line" },
|
|
184
|
-
className: parsedReasoning.isReasoningInProgress ?
|
|
157
|
+
className: parsedReasoning.isReasoningInProgress ? DEEP_THINKING_CLASS : void 0
|
|
185
158
|
},
|
|
186
159
|
toggleContent: t("reasoning.thinking"),
|
|
187
160
|
body: reasoningContent,
|
|
@@ -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 {\n ForwardedRef,\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n} from 'react';\n\nimport { makeStyles } from '@material-ui/core';\nimport {\n ChatbotDisplayMode,\n ChatbotWelcomePrompt,\n DeepThinking,\n DeepThinkingProps,\n Message,\n MessageBox,\n MessageBoxHandle,\n MessageProps,\n ToolCall as PatternFlyToolCall,\n WelcomePrompt,\n} from '@patternfly/chatbot';\nimport { Alert } from '@patternfly/react-core';\n\nimport { useAutoScroll } from '../hooks/useAutoScroll';\nimport { useBufferedMessages } from '../hooks/useBufferedMessages';\nimport { useFeedbackActions } from '../hooks/useFeedbackActions';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { ToolCall } from '../types';\nimport { parseReasoning } from '../utils/reasoningParser';\nimport { mapToPatternFlyToolCall } from '../utils/toolCallMapper';\nimport { SourcesChipModal } from './SourcesChipModal';\n\nconst useStyles = makeStyles(theme => ({\n prompt: {\n 'justify-content': 'flex-end',\n },\n container: {\n maxWidth: 'unset !important',\n },\n alert: {\n background: 'unset !important',\n },\n promptSuggestions: {\n '& div.pf-chatbot__prompt-suggestions': {\n 'flex-direction': 'column !important',\n },\n },\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 deepThinking: {\n animation: '$deepThinking 1.6s ease-in-out infinite',\n },\n\n '@keyframes deepThinking': {\n '0%': {\n opacity: 0.65,\n },\n '50%': {\n opacity: 1,\n },\n '100%': {\n opacity: 0.65,\n },\n },\n // Message box fills remaining height and scrolls when there are messages.\n messageBoxFlex: {\n flex: 1,\n minHeight: 0,\n },\n // New chat: message box sizes to content so ChatbotContent is the scroll container.\n // overflow: visible so full height is included in parent's scrollHeight (no clipping).\n messageBoxAutoHeight: {\n flex: 'none',\n height: 'auto',\n overflow: 'visible',\n },\n}));\n\n// Extended message type that includes tool calls\ninterface ExtendedMessageProps extends MessageProps {\n toolCalls?: ToolCall[];\n}\n\ntype LightspeedChatBoxProps = {\n userName?: string;\n messages: ExtendedMessageProps[];\n profileLoading: boolean;\n announcement: string | undefined;\n topicRestrictionEnabled: boolean;\n welcomePrompts: WelcomePrompt[];\n conversationId: string;\n isStreaming: boolean;\n displayMode?: ChatbotDisplayMode;\n /** When true, sources are shown as a compact chip + popover instead of the inline SourcesCard. */\n showSourcesChipPopover?: boolean;\n};\n\nexport interface ScrollContainerHandle {\n scrollToBottom: () => void;\n}\n\nexport const LightspeedChatBox = forwardRef(\n (\n {\n userName,\n messages,\n announcement,\n conversationId,\n profileLoading,\n welcomePrompts,\n isStreaming,\n topicRestrictionEnabled,\n displayMode,\n showSourcesChipPopover: showSourcesChipModal = false,\n }: LightspeedChatBoxProps,\n ref: ForwardedRef<ScrollContainerHandle | null>,\n ) => {\n const classes = useStyles();\n const scrollQueued = useRef(false);\n const containerRef = useRef<MessageBoxHandle>(null);\n const { t } = useTranslation();\n\n const cmessages = useBufferedMessages(messages, 30);\n const { autoScroll, scrollToBottom, scrollToTop } =\n useAutoScroll(containerRef);\n const conversationMessages = useFeedbackActions(\n cmessages,\n conversationId,\n isStreaming,\n );\n\n 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 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 setTimeout(() => {\n container.scrollTo({\n top: container.scrollHeight,\n behavior: 'auto',\n });\n }, 0);\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 const isEmbeddedMode = displayMode === ChatbotDisplayMode.embedded;\n\n const isNewChat = welcomePrompts.length > 0 && messages.length === 0;\n const getMessageBoxClassName = () => {\n const base = isNewChat\n ? `${messageBoxClasses} ${classes.messageBoxAutoHeight}`\n : `${messageBoxClasses} ${classes.messageBoxFlex}`;\n if (!welcomePrompts.length) {\n return base;\n }\n const withPrompt = `${base} ${classes.prompt}`;\n if (isEmbeddedMode) {\n return withPrompt;\n }\n return `${withPrompt} ${classes.promptSuggestions}`;\n };\n\n return (\n <MessageBox\n className={getMessageBoxClassName()}\n announcement={announcement}\n ref={containerRef}\n onScrollToTopClick={scrollToTop}\n onScrollToBottomClick={scrollToBottom}\n jumpButtonBottomProps={{ 'aria-label': t('aria.scroll.down') }}\n jumpButtonTopProps={{ 'aria-label': t('aria.scroll.up') }}\n jumpButtonBottomTooltipProps={{ content: t('tooltip.backToBottom') }}\n jumpButtonTopTooltipProps={{ content: t('tooltip.backToTop') }}\n >\n <div>\n <Alert\n title={t('aria.important')}\n variant=\"info\"\n isInline\n className={classes.alert}\n >\n {topicRestrictionEnabled\n ? t('disclaimer.withValidation')\n : t('disclaimer.withoutValidation')}\n </Alert>\n <br />\n </div>\n {welcomePrompts.length ? (\n <ChatbotWelcomePrompt\n title={t('chatbox.welcome.greeting' as any, {\n userName: profileLoading\n ? t('user.loading')\n : (userName ?? t('user.guest')),\n })}\n description={t('chatbox.welcome.description')}\n prompts={welcomePrompts}\n style={{ paddingBottom: '0' }}\n />\n ) : (\n <br />\n )}\n {conversationMessages.map((message, index) => {\n const messageContent = message.content as string;\n const parsedReasoning = parseReasoning(messageContent || '');\n\n // Map first tool call to PatternFly's toolCall prop\n const firstToolCall = message.toolCalls?.[0];\n const toolCallProp = firstToolCall\n ? mapToPatternFlyToolCall(firstToolCall, t, message.role)\n : undefined;\n\n // Handle additional tool calls (if any) via extraContent\n const additionalToolCalls = message.toolCalls?.slice(1);\n\n const extraContentParts: {\n beforeMainContent?: React.ReactNode;\n afterMainContent?: React.ReactNode;\n endContent?: React.ReactNode;\n } = {};\n\n let deepThinking: DeepThinkingProps | undefined = undefined;\n\n if (\n parsedReasoning.isReasoningInProgress ||\n parsedReasoning.hasReasoning\n ) {\n const reasoningContent = parsedReasoning.reasoning;\n\n if (reasoningContent) {\n deepThinking = {\n cardBodyProps: {\n id: `deep-thinking-${index}`,\n style: { whiteSpace: 'pre-line' },\n className: parsedReasoning.isReasoningInProgress\n ? classes.deepThinking\n : undefined,\n },\n toggleContent: t('reasoning.thinking'),\n body: reasoningContent,\n isDefaultExpanded: false,\n };\n }\n }\n\n const allToolCalls: React.ReactNode[] = [];\n\n // Add first tool call if it exists\n if (toolCallProp && firstToolCall) {\n allToolCalls.push(\n <div\n key={`tool-${firstToolCall.id}-${firstToolCall.toolName}`}\n style={{ marginTop: '8px' }}\n >\n <PatternFlyToolCall {...toolCallProp} />\n </div>,\n );\n }\n\n // Add additional tool calls\n if (additionalToolCalls && additionalToolCalls.length > 0) {\n additionalToolCalls.forEach(tc => {\n const tcProps = mapToPatternFlyToolCall(tc, t, message.role);\n allToolCalls.push(\n <div\n key={`tool-${tc.id}-${tc.toolName}`}\n style={{ marginTop: '8px' }}\n >\n <PatternFlyToolCall {...tcProps} />\n </div>,\n );\n });\n }\n\n // Show Thinking first, then tool calls\n if (deepThinking || allToolCalls.length > 0) {\n extraContentParts.beforeMainContent = (\n <>\n {deepThinking && <DeepThinking {...deepThinking} />}\n {allToolCalls.length > 0 && (\n <div style={{ marginTop: deepThinking ? '8px' : '0' }}>\n {allToolCalls}\n </div>\n )}\n </>\n );\n }\n\n const messageToPrepare =\n parsedReasoning.hasReasoning ||\n parsedReasoning.isReasoningInProgress\n ? { ...message, content: parsedReasoning.mainContent }\n : message;\n\n let finalMessage = messageToPrepare;\n\n if (showSourcesChipModal) {\n const { sources: messageSources, ...messageWithoutSources } =\n messageToPrepare;\n\n if (messageSources?.sources?.length) {\n extraContentParts.endContent = (\n <SourcesChipModal sources={messageSources} />\n );\n }\n\n finalMessage = messageWithoutSources;\n }\n\n const extraContent =\n extraContentParts.beforeMainContent ||\n extraContentParts.afterMainContent ||\n extraContentParts.endContent\n ? extraContentParts\n : undefined;\n\n return (\n <Message\n key={`${message.role}-${index}`}\n extraContent={extraContent}\n {...finalMessage}\n />\n );\n })}\n </MessageBox>\n );\n },\n);\n"],"names":["PatternFlyToolCall"],"mappings":"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"}
|
|
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 {\n ForwardedRef,\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n} from 'react';\n\nimport { keyframes, styled } from '@mui/material/styles';\nimport {\n ChatbotDisplayMode,\n ChatbotWelcomePrompt,\n DeepThinking,\n DeepThinkingProps,\n Message,\n MessageBox,\n MessageBoxHandle,\n MessageProps,\n ToolCall as PatternFlyToolCall,\n WelcomePrompt,\n} from '@patternfly/chatbot';\nimport { Alert } from '@patternfly/react-core';\n\nimport { useAutoScroll } from '../hooks/useAutoScroll';\nimport { useBufferedMessages } from '../hooks/useBufferedMessages';\nimport { useFeedbackActions } from '../hooks/useFeedbackActions';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { ToolCall } from '../types';\nimport { parseReasoning } from '../utils/reasoningParser';\nimport { mapToPatternFlyToolCall } from '../utils/toolCallMapper';\nimport { SourcesChipModal } from './SourcesChipModal';\n\nconst DEEP_THINKING_CLASS = 'lightspeed-deep-thinking';\n\nconst deepThinkingPulse = keyframes`\n 0% { opacity: 0.65 }\n 50% { opacity: 1 }\n 100% { opacity: 0.65 }\n`;\n\ntype StyledMessageBoxProps = {\n $isNewChat: boolean;\n $hasWelcomePrompts: boolean;\n $showPromptSuggestions: boolean;\n};\n\nconst StyledMessageBox = styled(MessageBox, {\n shouldForwardProp: prop =>\n prop !== '$isNewChat' &&\n prop !== '$hasWelcomePrompts' &&\n prop !== '$showPromptSuggestions',\n})<StyledMessageBoxProps>(\n ({ theme, $isNewChat, $hasWelcomePrompts, $showPromptSuggestions }) => ({\n maxWidth: 'unset !important',\n [`& .${DEEP_THINKING_CLASS}`]: {\n animation: `${deepThinkingPulse} 1.6s ease-in-out infinite`,\n },\n '& div.pf-chatbot__message--user': {\n '& div.pf-chatbot__message-text': {\n '& p': {\n color: theme.palette.common.white,\n },\n },\n },\n ...($isNewChat\n ? {\n flex: 'none',\n height: 'auto',\n overflow: 'visible',\n }\n : {\n flex: 1,\n minHeight: 0,\n }),\n ...($hasWelcomePrompts\n ? {\n justifyContent: 'flex-end',\n }\n : {}),\n ...($showPromptSuggestions\n ? {\n '& div.pf-chatbot__prompt-suggestions': {\n flexDirection: 'column !important',\n },\n }\n : {}),\n }),\n);\n\nconst DisclaimerAlert = styled(Alert)({\n background: 'unset !important',\n});\n\n// Extended message type that includes tool calls\ninterface ExtendedMessageProps extends MessageProps {\n toolCalls?: ToolCall[];\n}\n\ntype LightspeedChatBoxProps = {\n userName?: string;\n messages: ExtendedMessageProps[];\n profileLoading: boolean;\n announcement: string | undefined;\n topicRestrictionEnabled: boolean;\n welcomePrompts: WelcomePrompt[];\n conversationId: string;\n isStreaming: boolean;\n displayMode?: ChatbotDisplayMode;\n /** When true, sources are shown as a compact chip + popover instead of the inline SourcesCard. */\n showSourcesChipPopover?: boolean;\n};\n\nexport interface ScrollContainerHandle {\n scrollToBottom: () => void;\n}\n\nexport const LightspeedChatBox = forwardRef(\n (\n {\n userName,\n messages,\n announcement,\n conversationId,\n profileLoading,\n welcomePrompts,\n isStreaming,\n topicRestrictionEnabled,\n displayMode,\n showSourcesChipPopover: showSourcesChipModal = false,\n }: LightspeedChatBoxProps,\n ref: ForwardedRef<ScrollContainerHandle | null>,\n ) => {\n const scrollQueued = useRef(false);\n const containerRef = useRef<MessageBoxHandle>(null);\n const { t } = useTranslation();\n\n const cmessages = useBufferedMessages(messages, 30);\n const { autoScroll, scrollToBottom, scrollToTop } =\n useAutoScroll(containerRef);\n const conversationMessages = useFeedbackActions(\n cmessages,\n conversationId,\n isStreaming,\n );\n\n 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 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 setTimeout(() => {\n container.scrollTo({\n top: container.scrollHeight,\n behavior: 'auto',\n });\n }, 0);\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 isEmbeddedMode = displayMode === ChatbotDisplayMode.embedded;\n const isNewChat = welcomePrompts.length > 0 && messages.length === 0;\n const hasWelcomePrompts = welcomePrompts.length > 0;\n const showPromptSuggestions = hasWelcomePrompts && !isEmbeddedMode;\n\n return (\n <StyledMessageBox\n $isNewChat={isNewChat}\n $hasWelcomePrompts={hasWelcomePrompts}\n $showPromptSuggestions={showPromptSuggestions}\n announcement={announcement}\n ref={containerRef}\n onScrollToTopClick={scrollToTop}\n onScrollToBottomClick={scrollToBottom}\n jumpButtonBottomProps={{ 'aria-label': t('aria.scroll.down') }}\n jumpButtonTopProps={{ 'aria-label': t('aria.scroll.up') }}\n jumpButtonBottomTooltipProps={{ content: t('tooltip.backToBottom') }}\n jumpButtonTopTooltipProps={{ content: t('tooltip.backToTop') }}\n >\n <div>\n <DisclaimerAlert title={t('aria.important')} variant=\"info\" isInline>\n {topicRestrictionEnabled\n ? t('disclaimer.withValidation')\n : t('disclaimer.withoutValidation')}\n </DisclaimerAlert>\n <br />\n </div>\n {welcomePrompts.length ? (\n <ChatbotWelcomePrompt\n title={t('chatbox.welcome.greeting' as any, {\n userName: profileLoading\n ? t('user.loading')\n : (userName ?? t('user.guest')),\n })}\n description={t('chatbox.welcome.description')}\n prompts={welcomePrompts}\n style={{ paddingBottom: '0' }}\n />\n ) : (\n <br />\n )}\n {conversationMessages.map((message, index) => {\n const messageContent = message.content as string;\n const parsedReasoning = parseReasoning(messageContent || '');\n\n // Map first tool call to PatternFly's toolCall prop\n const firstToolCall = message.toolCalls?.[0];\n const toolCallProp = firstToolCall\n ? mapToPatternFlyToolCall(firstToolCall, t, message.role)\n : undefined;\n\n // Handle additional tool calls (if any) via extraContent\n const additionalToolCalls = message.toolCalls?.slice(1);\n\n const extraContentParts: {\n beforeMainContent?: React.ReactNode;\n afterMainContent?: React.ReactNode;\n endContent?: React.ReactNode;\n } = {};\n\n let deepThinking: DeepThinkingProps | undefined = undefined;\n\n if (\n parsedReasoning.isReasoningInProgress ||\n parsedReasoning.hasReasoning\n ) {\n const reasoningContent = parsedReasoning.reasoning;\n\n if (reasoningContent) {\n deepThinking = {\n cardBodyProps: {\n id: `deep-thinking-${index}`,\n style: { whiteSpace: 'pre-line' },\n className: parsedReasoning.isReasoningInProgress\n ? DEEP_THINKING_CLASS\n : undefined,\n },\n toggleContent: t('reasoning.thinking'),\n body: reasoningContent,\n isDefaultExpanded: false,\n };\n }\n }\n\n const allToolCalls: React.ReactNode[] = [];\n\n // Add first tool call if it exists\n if (toolCallProp && firstToolCall) {\n allToolCalls.push(\n <div\n key={`tool-${firstToolCall.id}-${firstToolCall.toolName}`}\n style={{ marginTop: '8px' }}\n >\n <PatternFlyToolCall {...toolCallProp} />\n </div>,\n );\n }\n\n // Add additional tool calls\n if (additionalToolCalls && additionalToolCalls.length > 0) {\n additionalToolCalls.forEach(tc => {\n const tcProps = mapToPatternFlyToolCall(tc, t, message.role);\n allToolCalls.push(\n <div\n key={`tool-${tc.id}-${tc.toolName}`}\n style={{ marginTop: '8px' }}\n >\n <PatternFlyToolCall {...tcProps} />\n </div>,\n );\n });\n }\n\n // Show Thinking first, then tool calls\n if (deepThinking || allToolCalls.length > 0) {\n extraContentParts.beforeMainContent = (\n <>\n {deepThinking && <DeepThinking {...deepThinking} />}\n {allToolCalls.length > 0 && (\n <div style={{ marginTop: deepThinking ? '8px' : '0' }}>\n {allToolCalls}\n </div>\n )}\n </>\n );\n }\n\n const messageToPrepare =\n parsedReasoning.hasReasoning ||\n parsedReasoning.isReasoningInProgress\n ? { ...message, content: parsedReasoning.mainContent }\n : message;\n\n let finalMessage = messageToPrepare;\n\n if (showSourcesChipModal) {\n const { sources: messageSources, ...messageWithoutSources } =\n messageToPrepare;\n\n if (messageSources?.sources?.length) {\n extraContentParts.endContent = (\n <SourcesChipModal sources={messageSources} />\n );\n }\n\n finalMessage = messageWithoutSources;\n }\n\n const extraContent =\n extraContentParts.beforeMainContent ||\n extraContentParts.afterMainContent ||\n extraContentParts.endContent\n ? extraContentParts\n : undefined;\n\n return (\n <Message\n key={`${message.role}-${index}`}\n extraContent={extraContent}\n {...finalMessage}\n />\n );\n })}\n </StyledMessageBox>\n );\n },\n);\n"],"names":["PatternFlyToolCall"],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import Box from '@mui/material/Box';
|
|
3
|
+
|
|
4
|
+
const ragSourceLabelSx = {
|
|
5
|
+
display: "inline-block",
|
|
6
|
+
boxSizing: "border-box",
|
|
7
|
+
margin: 0,
|
|
8
|
+
paddingBlock: 0,
|
|
9
|
+
paddingInline: "var(--pf-t--global--spacer--sm)",
|
|
10
|
+
borderRadius: "var(--pf-t--global--border--radius--pill)",
|
|
11
|
+
backgroundColor: "var(--pf-t--global--background--color--secondary--default)",
|
|
12
|
+
color: "var(--pf-t--global--text--color--regular)",
|
|
13
|
+
fontSize: "var(--pf-t--global--font--size--body--sm)",
|
|
14
|
+
fontWeight: "var(--pf-t--global--font--weight--body--bold)",
|
|
15
|
+
lineHeight: "var(--pf-t--global--font--line-height--body)",
|
|
16
|
+
whiteSpace: "nowrap",
|
|
17
|
+
verticalAlign: "middle"
|
|
18
|
+
};
|
|
19
|
+
const RagSourceLabel = ({ source }) => /* @__PURE__ */ jsx(Box, { component: "span", sx: ragSourceLabelSx, children: source });
|
|
20
|
+
|
|
21
|
+
export { RagSourceLabel, ragSourceLabelSx };
|
|
22
|
+
//# sourceMappingURL=RagSourceLabel.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RagSourceLabel.esm.js","sources":["../../src/components/RagSourceLabel.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 Box from '@mui/material/Box';\nimport { CSSObject } from '@mui/material/styles';\n\n/** Shared pill styles for LCORE RAG `source` labels (SourcesCard header + modal). */\nexport const ragSourceLabelSx: CSSObject = {\n display: 'inline-block',\n boxSizing: 'border-box',\n margin: 0,\n paddingBlock: 0,\n paddingInline: 'var(--pf-t--global--spacer--sm)',\n borderRadius: 'var(--pf-t--global--border--radius--pill)',\n backgroundColor: 'var(--pf-t--global--background--color--secondary--default)',\n color: 'var(--pf-t--global--text--color--regular)',\n fontSize: 'var(--pf-t--global--font--size--body--sm)',\n fontWeight: 'var(--pf-t--global--font--weight--body--bold)',\n lineHeight: 'var(--pf-t--global--font--line-height--body)',\n whiteSpace: 'nowrap',\n verticalAlign: 'middle',\n};\n\ntype RagSourceLabelProps = {\n source: string;\n};\n\nexport const RagSourceLabel = ({ source }: RagSourceLabelProps) => (\n <Box component=\"span\" sx={ragSourceLabelSx}>\n {source}\n </Box>\n);\n"],"names":[],"mappings":";;;AAoBO,MAAM,gBAAA,GAA8B;AAAA,EACzC,OAAA,EAAS,cAAA;AAAA,EACT,SAAA,EAAW,YAAA;AAAA,EACX,MAAA,EAAQ,CAAA;AAAA,EACR,YAAA,EAAc,CAAA;AAAA,EACd,aAAA,EAAe,iCAAA;AAAA,EACf,YAAA,EAAc,2CAAA;AAAA,EACd,eAAA,EAAiB,4DAAA;AAAA,EACjB,KAAA,EAAO,2CAAA;AAAA,EACP,QAAA,EAAU,2CAAA;AAAA,EACV,UAAA,EAAY,+CAAA;AAAA,EACZ,UAAA,EAAY,8CAAA;AAAA,EACZ,UAAA,EAAY,QAAA;AAAA,EACZ,aAAA,EAAe;AACjB;AAMO,MAAM,cAAA,GAAiB,CAAC,EAAE,MAAA,EAAO,qBACtC,GAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAU,MAAA,EAAO,EAAA,EAAI,gBAAA,EACvB,QAAA,EAAA,MAAA,EACH;;;;"}
|
|
@@ -1,85 +1,62 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
2
|
+
import Box from '@mui/material/Box';
|
|
3
|
+
import { styled } from '@mui/material/styles';
|
|
4
|
+
import { Popover, Button, HelperText, List, ListItem, HelperTextItem, Tooltip } from '@patternfly/react-core';
|
|
4
5
|
import { LinkIcon, InfoCircleIcon } from '@patternfly/react-icons';
|
|
5
6
|
import { useTranslation } from '../hooks/useTranslation.esm.js';
|
|
6
7
|
import { FileTypeIcon } from './notebooks/FileTypeIcon.esm.js';
|
|
8
|
+
import { RagSourceLabel } from './RagSourceLabel.esm.js';
|
|
7
9
|
|
|
8
10
|
const POPOVER_WIDTH = "400px";
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
"
|
|
12
|
-
alignItems: "flex-start"
|
|
13
|
-
},
|
|
14
|
-
"& .pf-v6-c-popover__title-text": {
|
|
15
|
-
margin: 0
|
|
16
|
-
},
|
|
17
|
-
"& .pf-v6-c-popover__header": {
|
|
18
|
-
paddingBlockEnd: theme.spacing(2)
|
|
19
|
-
},
|
|
20
|
-
"& .pf-v6-c-popover__body": {
|
|
21
|
-
paddingBlockStart: 0
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
chipButton: {
|
|
25
|
-
padding: "4px 12px",
|
|
26
|
-
fontSize: "0.8125rem",
|
|
27
|
-
fontWeight: 500,
|
|
28
|
-
borderRadius: 16,
|
|
29
|
-
backgroundColor: "transparent",
|
|
30
|
-
color: "var(--pf-t--global--text--color--regular, #1b1d21)",
|
|
31
|
-
"&:hover": {
|
|
32
|
-
backgroundColor: "var(--pf-t--global--background--color--secondary--default, #e0e0e0)"
|
|
33
|
-
},
|
|
34
|
-
"& .pf-v6-c-button__icon": {
|
|
35
|
-
color: "inherit"
|
|
36
|
-
}
|
|
11
|
+
const SourcesPopover = styled(Popover)(({ theme }) => ({
|
|
12
|
+
"& .pf-v6-c-popover__title": {
|
|
13
|
+
alignItems: "flex-start"
|
|
37
14
|
},
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
color: "var(--pf-t--global--text--color--subtle, #c7c7c7)"
|
|
15
|
+
"& .pf-v6-c-popover__title-text": {
|
|
16
|
+
margin: 0
|
|
41
17
|
},
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
overflowY: "auto"
|
|
18
|
+
"& .pf-v6-c-popover__header": {
|
|
19
|
+
paddingBlockEnd: theme.spacing(2)
|
|
45
20
|
},
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
overflow: "hidden",
|
|
60
|
-
textOverflow: "ellipsis",
|
|
61
|
-
whiteSpace: "nowrap"
|
|
21
|
+
"& .pf-v6-c-popover__body": {
|
|
22
|
+
paddingBlockStart: 0
|
|
23
|
+
}
|
|
24
|
+
}));
|
|
25
|
+
const ChipButton = styled(Button)({
|
|
26
|
+
padding: "4px 12px",
|
|
27
|
+
fontSize: "0.8125rem",
|
|
28
|
+
fontWeight: 500,
|
|
29
|
+
borderRadius: 16,
|
|
30
|
+
backgroundColor: "transparent",
|
|
31
|
+
color: "var(--pf-t--global--text--color--regular)",
|
|
32
|
+
"&:hover": {
|
|
33
|
+
backgroundColor: "var(--pf-t--global--background--color--secondary--default)"
|
|
62
34
|
},
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
color: "var(--pf-t--global--text--color--subtle, #c7c7c7)",
|
|
66
|
-
marginTop: 2,
|
|
67
|
-
overflow: "hidden",
|
|
68
|
-
textOverflow: "ellipsis",
|
|
69
|
-
display: "-webkit-box",
|
|
70
|
-
WebkitLineClamp: 2,
|
|
71
|
-
WebkitBoxOrient: "vertical"
|
|
35
|
+
"& .pf-v6-c-button__icon": {
|
|
36
|
+
color: "inherit"
|
|
72
37
|
}
|
|
38
|
+
});
|
|
39
|
+
const SourcesHelperText = styled(HelperText)(({ theme }) => ({
|
|
40
|
+
marginBottom: theme.spacing(1.5),
|
|
41
|
+
color: "var(--pf-t--global--text--color--subtle)"
|
|
73
42
|
}));
|
|
43
|
+
const SourcesList = styled(List)({
|
|
44
|
+
maxHeight: 320,
|
|
45
|
+
overflowY: "auto"
|
|
46
|
+
});
|
|
47
|
+
const SourceListItem = styled(ListItem)({
|
|
48
|
+
alignItems: "center",
|
|
49
|
+
"& .pf-v6-c-list__item-text": {
|
|
50
|
+
minWidth: 0
|
|
51
|
+
}
|
|
52
|
+
});
|
|
74
53
|
const SourcesChipModal = ({ sources }) => {
|
|
75
|
-
const classes = useStyles();
|
|
76
54
|
const { t } = useTranslation();
|
|
77
55
|
const count = sources.sources?.length ?? 0;
|
|
78
56
|
if (count === 0) return null;
|
|
79
57
|
return /* @__PURE__ */ jsx(
|
|
80
|
-
|
|
58
|
+
SourcesPopover,
|
|
81
59
|
{
|
|
82
|
-
className: classes.sourcesPopover,
|
|
83
60
|
position: "top-start",
|
|
84
61
|
triggerAction: "click",
|
|
85
62
|
"aria-label": t("sources.modal.title"),
|
|
@@ -90,32 +67,60 @@ const SourcesChipModal = ({ sources }) => {
|
|
|
90
67
|
maxWidth: POPOVER_WIDTH,
|
|
91
68
|
appendTo: () => document.body,
|
|
92
69
|
bodyContent: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
93
|
-
/* @__PURE__ */ jsx(
|
|
94
|
-
/* @__PURE__ */ jsx(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
70
|
+
/* @__PURE__ */ jsx(SourcesHelperText, { children: /* @__PURE__ */ jsx(HelperTextItem, { variant: "indeterminate", icon: /* @__PURE__ */ jsx(InfoCircleIcon, {}), children: t("sources.modal.description") }) }),
|
|
71
|
+
/* @__PURE__ */ jsx(SourcesList, { isPlain: true, "aria-label": t("sources.modal.title"), children: sources.sources.map((source, index) => {
|
|
72
|
+
const title = source.title ?? `Source ${index + 1}`;
|
|
73
|
+
const ragSource = source.ragSource;
|
|
74
|
+
const titleNode = /* @__PURE__ */ jsx(
|
|
75
|
+
Box,
|
|
76
|
+
{
|
|
77
|
+
sx: {
|
|
78
|
+
fontSize: "0.875rem",
|
|
79
|
+
fontWeight: 500,
|
|
80
|
+
overflow: "hidden",
|
|
81
|
+
textOverflow: "ellipsis",
|
|
82
|
+
whiteSpace: "nowrap",
|
|
83
|
+
minWidth: 0
|
|
84
|
+
},
|
|
85
|
+
children: title
|
|
86
|
+
}
|
|
87
|
+
);
|
|
88
|
+
return /* @__PURE__ */ jsx(
|
|
89
|
+
SourceListItem,
|
|
90
|
+
{
|
|
91
|
+
icon: /* @__PURE__ */ jsx(FileTypeIcon, { fileName: title }),
|
|
92
|
+
children: /* @__PURE__ */ jsxs(Box, { sx: { flex: 1, minWidth: 0 }, children: [
|
|
93
|
+
/* @__PURE__ */ jsx(Tooltip, { content: title, children: titleNode }),
|
|
94
|
+
ragSource && /* @__PURE__ */ jsx(
|
|
95
|
+
Box,
|
|
96
|
+
{
|
|
97
|
+
sx: { marginTop: "var(--pf-t--global--spacer--xs)" },
|
|
98
|
+
children: /* @__PURE__ */ jsx(RagSourceLabel, { source: ragSource })
|
|
99
|
+
}
|
|
100
|
+
),
|
|
101
|
+
source.body && /* @__PURE__ */ jsx(
|
|
102
|
+
Box,
|
|
103
|
+
{
|
|
104
|
+
sx: {
|
|
105
|
+
fontSize: "0.8125rem",
|
|
106
|
+
color: "var(--pf-t--global--text--color--subtle)",
|
|
107
|
+
marginTop: "2px",
|
|
108
|
+
overflow: "hidden",
|
|
109
|
+
textOverflow: "ellipsis",
|
|
110
|
+
display: "-webkit-box",
|
|
111
|
+
WebkitLineClamp: 2,
|
|
112
|
+
WebkitBoxOrient: "vertical"
|
|
113
|
+
},
|
|
114
|
+
children: source.body
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
] })
|
|
118
|
+
},
|
|
119
|
+
`${source.title}-${index}`
|
|
120
|
+
);
|
|
121
|
+
}) })
|
|
117
122
|
] }),
|
|
118
|
-
children: /* @__PURE__ */ jsx(
|
|
123
|
+
children: /* @__PURE__ */ jsx(ChipButton, { variant: "link", icon: /* @__PURE__ */ jsx(LinkIcon, {}), children: t("sources.chip.label", { count }) })
|
|
119
124
|
}
|
|
120
125
|
);
|
|
121
126
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SourcesChipModal.esm.js","sources":["../../src/components/SourcesChipModal.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 {
|
|
1
|
+
{"version":3,"file":"SourcesChipModal.esm.js","sources":["../../src/components/SourcesChipModal.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 Box from '@mui/material/Box';\nimport { styled } from '@mui/material/styles';\nimport { SourcesCardProps } from '@patternfly/chatbot';\nimport {\n Button,\n HelperText,\n HelperTextItem,\n List,\n ListItem,\n Popover,\n Tooltip,\n} from '@patternfly/react-core';\nimport { InfoCircleIcon, LinkIcon } from '@patternfly/react-icons';\n\nimport { useTranslation } from '../hooks/useTranslation';\nimport { SourceWithRagId } from '../utils/lightspeed-chatbox-utils';\nimport { FileTypeIcon } from './notebooks/FileTypeIcon';\nimport { RagSourceLabel } from './RagSourceLabel';\n\nconst POPOVER_WIDTH = '400px';\n\nconst SourcesPopover = styled(Popover)(({ theme }) => ({\n '& .pf-v6-c-popover__title': {\n alignItems: 'flex-start',\n },\n '& .pf-v6-c-popover__title-text': {\n margin: 0,\n },\n '& .pf-v6-c-popover__header': {\n paddingBlockEnd: theme.spacing(2),\n },\n '& .pf-v6-c-popover__body': {\n paddingBlockStart: 0,\n },\n}));\n\nconst ChipButton = styled(Button)({\n padding: '4px 12px',\n fontSize: '0.8125rem',\n fontWeight: 500,\n borderRadius: 16,\n backgroundColor: 'transparent',\n color: 'var(--pf-t--global--text--color--regular)',\n '&:hover': {\n backgroundColor:\n 'var(--pf-t--global--background--color--secondary--default)',\n },\n '& .pf-v6-c-button__icon': {\n color: 'inherit',\n },\n});\n\nconst SourcesHelperText = styled(HelperText)(({ theme }) => ({\n marginBottom: theme.spacing(1.5),\n color: 'var(--pf-t--global--text--color--subtle)',\n}));\n\nconst SourcesList = styled(List)({\n maxHeight: 320,\n overflowY: 'auto',\n});\n\nconst SourceListItem = styled(ListItem)({\n alignItems: 'center',\n '& .pf-v6-c-list__item-text': {\n minWidth: 0,\n },\n});\n\ntype SourcesChipModalProps = {\n sources: SourcesCardProps;\n};\n\nexport const SourcesChipModal = ({ sources }: SourcesChipModalProps) => {\n const { t } = useTranslation();\n\n const count = sources.sources?.length ?? 0;\n if (count === 0) return null;\n\n return (\n <SourcesPopover\n position=\"top-start\"\n triggerAction=\"click\"\n aria-label={t('sources.modal.title')}\n headerContent={t('sources.modal.title')}\n headerIcon={<LinkIcon />}\n closeBtnAriaLabel={t('sources.popover.closeAriaLabel')}\n minWidth={POPOVER_WIDTH}\n maxWidth={POPOVER_WIDTH}\n appendTo={() => document.body}\n bodyContent={\n <>\n <SourcesHelperText>\n <HelperTextItem variant=\"indeterminate\" icon={<InfoCircleIcon />}>\n {t('sources.modal.description')}\n </HelperTextItem>\n </SourcesHelperText>\n <SourcesList isPlain aria-label={t('sources.modal.title')}>\n {sources.sources.map((source, index) => {\n const title = source.title ?? `Source ${index + 1}`;\n const ragSource = (source as SourceWithRagId).ragSource;\n const titleNode = (\n <Box\n sx={{\n fontSize: '0.875rem',\n fontWeight: 500,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n minWidth: 0,\n }}\n >\n {title}\n </Box>\n );\n return (\n <SourceListItem\n key={`${source.title}-${index}`}\n icon={<FileTypeIcon fileName={title} />}\n >\n <Box sx={{ flex: 1, minWidth: 0 }}>\n <Tooltip content={title}>{titleNode}</Tooltip>\n {ragSource && (\n <Box\n sx={{ marginTop: 'var(--pf-t--global--spacer--xs)' }}\n >\n <RagSourceLabel source={ragSource} />\n </Box>\n )}\n {source.body && (\n <Box\n sx={{\n fontSize: '0.8125rem',\n color: 'var(--pf-t--global--text--color--subtle)',\n marginTop: '2px',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n display: '-webkit-box',\n WebkitLineClamp: 2,\n WebkitBoxOrient: 'vertical',\n }}\n >\n {source.body}\n </Box>\n )}\n </Box>\n </SourceListItem>\n );\n })}\n </SourcesList>\n </>\n }\n >\n <ChipButton variant=\"link\" icon={<LinkIcon />}>\n {(t as Function)('sources.chip.label', { count })}\n </ChipButton>\n </SourcesPopover>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFeedbackActions.esm.js","sources":["../../src/hooks/useFeedbackActions.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 */\nimport { useCallback, useEffect, useMemo, useRef } from 'react';\n\nimport { MessageProps } from '@patternfly/chatbot';\nimport { UserFeedbackProps } from '@patternfly/chatbot/dist/cjs/Message/UserFeedback/UserFeedback';\nimport { UserFeedbackCompleteProps } from '@patternfly/chatbot/dist/cjs/Message/UserFeedback/UserFeedbackComplete';\n\nimport { useCaptureFeedback } from '../hooks/useCaptureFeedback';\nimport { CaptureFeedback } from '../types';\nimport { Sentiment, useFeedbackState } from './useFeedbackState';\nimport { useFeedbackStatus } from './useFeedbackStatus';\nimport { useTranslation } from './useTranslation';\n\nexport const useFeedbackActions = <T extends MessageProps>(\n messages: T[],\n conversationId: string,\n isStreaming: boolean,\n): T[] => {\n const copyButtonRef = useRef<HTMLButtonElement>(null);\n const speakingButtonRef = useRef<HTMLButtonElement>(null);\n const currentSpeakingIdRef = useRef<string | null>(null);\n\n const { data: feedbackEnabled } = useFeedbackStatus();\n const { state, ...dispatch } = useFeedbackState();\n const { mutateAsync: captureFeedback } = useCaptureFeedback();\n const { t } = useTranslation();\n\n const createQuickResponses = useMemo(\n () => ({\n positive: [\n { id: '1', content: t('feedback.quickResponses.positive.helpful') },\n {\n id: '2',\n content: t('feedback.quickResponses.positive.easyToUnderstand'),\n },\n {\n id: '3',\n content: t('feedback.quickResponses.positive.resolvedIssue'),\n },\n ],\n negative: [\n { id: '1', content: t('feedback.quickResponses.negative.didntAnswer') },\n {\n id: '2',\n content: t('feedback.quickResponses.negative.hardToUnderstand'),\n },\n { id: '3', content: t('feedback.quickResponses.negative.notHelpful') },\n ],\n }),\n [t],\n );\n\n const getFeedbackForm = useCallback(\n (messageId: string, sentiment: 'positive' | 'negative') => ({\n key: `feedback-${sentiment}`,\n id: `feedback-${sentiment}-${messageId}`,\n hasTextArea: true,\n title: t('feedback.form.title'),\n textAreaPlaceholder: t('feedback.form.textAreaPlaceholder'),\n submitWord: t('feedback.form.submitWord'),\n quickResponses: createQuickResponses[sentiment],\n onSubmit: (\n quickResponse: string | undefined = '0',\n additionalFeedback: string | undefined,\n ) => {\n const quickIndex = Number(quickResponse) - 1;\n const quickText =\n quickResponse !== '0'\n ? createQuickResponses[sentiment]?.[quickIndex]?.content\n : undefined;\n\n let user_feedback = '';\n\n if (quickText && additionalFeedback) {\n user_feedback = `${quickText}\\nAdditional feedback: ${additionalFeedback}`;\n } else if (quickText) {\n user_feedback = quickText;\n } else if (additionalFeedback) {\n user_feedback = additionalFeedback;\n }\n\n const botAnswerId = Number(messageId.split('-').pop());\n const userQuestionId = botAnswerId - 1;\n\n const payload: CaptureFeedback = {\n conversation_id: conversationId,\n user_feedback,\n sentiment: sentiment === 'positive' ? 1 : -1,\n user_question: messages[userQuestionId].content || '',\n llm_response: messages[botAnswerId].content || '',\n };\n\n captureFeedback(payload).then(() => {\n dispatch.hideFeedbackForm(messageId, sentiment);\n dispatch.showCompletionForm(messageId, sentiment);\n dispatch.updateButtonState(messageId, {\n sentiment: sentiment,\n feedbackSubmitted: true,\n });\n\n setTimeout(() => {\n dispatch.hideCompletionForm(messageId, sentiment);\n }, 1000);\n });\n },\n\n // eslint-disable-next-line no-console\n onClose: () => {\n dispatch.hideFeedbackForm(messageId, sentiment);\n dispatch.resetButtonState(messageId);\n dispatch.updateButtonState(messageId, { sentiment: undefined });\n },\n focusOnLoad: true,\n }),\n [\n captureFeedback,\n conversationId,\n dispatch,\n messages,\n createQuickResponses,\n t,\n ],\n );\n\n const feedbackForms = useCallback(\n (messageId: string): { [key in Sentiment]: UserFeedbackProps } => ({\n positive: getFeedbackForm(messageId, 'positive'),\n negative: getFeedbackForm(messageId, 'negative'),\n }),\n [getFeedbackForm],\n );\n\n const getUserFeedbackComplete = useCallback(\n (\n messageId: string,\n sentiment: Sentiment,\n ): UserFeedbackCompleteProps | undefined => {\n const isVisible = state[messageId]?.completionForm?.[sentiment];\n if (!isVisible) return undefined;\n\n return {\n id: `feebback-completion-${sentiment}-${messageId}`,\n title: t('feedback.completion.title'),\n body: t('feedback.completion.body'),\n onClose: () => {\n dispatch.hideCompletionForm(messageId, sentiment);\n dispatch.resetButtonState(messageId);\n },\n };\n },\n [state, dispatch, t],\n );\n\n const scrollToFeedbackForm = useCallback(\n (messageId: string, sentiment: Sentiment) => {\n setTimeout(() => {\n const el = document.getElementById(\n `feedback-${sentiment}-${messageId}`,\n );\n if (el) {\n el.scrollIntoView({ behavior: 'auto', block: 'start' });\n el.focus();\n }\n }, 0);\n },\n [],\n );\n\n const speakMessage = useCallback(\n (messageId: string, content: string) => {\n if (window.speechSynthesis.speaking || window.speechSynthesis.pending) {\n window.speechSynthesis.cancel();\n\n if (\n currentSpeakingIdRef.current &&\n currentSpeakingIdRef.current !== messageId\n ) {\n dispatch.updateButtonState(currentSpeakingIdRef.current, {\n isSpeaking: false,\n });\n }\n }\n\n // Track the current SpeakingId\n currentSpeakingIdRef.current = messageId;\n\n const utterance = new SpeechSynthesisUtterance(content);\n\n utterance.onstart = () => {\n dispatch.updateButtonState(messageId, { isSpeaking: true });\n };\n\n utterance.onend = () => {\n dispatch.updateButtonState(messageId, { isSpeaking: false });\n currentSpeakingIdRef.current = null;\n };\n\n utterance.onerror = () => {\n dispatch.updateButtonState(messageId, { isSpeaking: false });\n currentSpeakingIdRef.current = null;\n };\n\n window.speechSynthesis.speak(utterance);\n },\n [dispatch],\n );\n\n const cancelSpeaking = useCallback(\n (messageId?: string) => {\n window.speechSynthesis.cancel();\n\n currentSpeakingIdRef.current = null;\n\n if (messageId) {\n // Cancel just this one message\n dispatch.updateButtonState(messageId, { isSpeaking: false });\n } else {\n // Cancel all messages\n Object.keys(state).forEach(id => {\n if (state[id].buttonState?.isSpeaking) {\n dispatch.updateButtonState(id, { isSpeaking: false });\n }\n });\n }\n setTimeout(() => {\n const el = document.getElementById(`listen-${messageId}`);\n if (el) {\n el.blur();\n }\n }, 10);\n },\n [state, dispatch],\n );\n\n useEffect(() => {\n return () => {\n // Stop any ongoing speech when component unmounts\n cancelSpeaking();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [conversationId]);\n\n return useMemo(() => {\n return feedbackEnabled\n ? messages.map((message, index) => {\n if (\n message.role === 'user' ||\n (isStreaming && messages.length - 1 === index)\n )\n return message;\n\n const messageId = `${conversationId}-${message.role}-${index}`;\n const { sentiment, copied, isSpeaking } =\n state[messageId]?.buttonState || {};\n const showFeedbackForm = state[messageId]?.feedbackForm?.[sentiment];\n const userFeedbackForm =\n showFeedbackForm && feedbackForms(messageId)[sentiment];\n\n const userFeedbackComplete = getUserFeedbackComplete(\n messageId,\n sentiment,\n );\n\n const createSentimentAction = (selected: Sentiment) => ({\n isClicked: sentiment === selected,\n onClick: () => {\n if (sentiment !== selected) {\n dispatch.toggleFeedbackForm(messageId, selected);\n dispatch.updateButtonState(messageId, { sentiment: selected });\n scrollToFeedbackForm(messageId, sentiment);\n }\n },\n tooltipContent:\n selected === 'positive'\n ? t('feedback.tooltips.goodResponse')\n : t('feedback.tooltips.badResponse'),\n 'aria-expanded': sentiment === selected,\n 'aria-controls': showFeedbackForm\n ? `feedback-${sentiment}-${messageId}`\n : `feebback-completion-${sentiment}-${messageId}`,\n });\n\n const copyAction = {\n isClicked: copied,\n ref: copyButtonRef,\n tooltipContent: copied\n ? t('feedback.tooltips.copied')\n : t('feedback.tooltips.copy'),\n onClick: async () => {\n await window.navigator.clipboard.writeText(\n message.content as string,\n );\n dispatch.updateButtonState(messageId, {\n copied: true,\n });\n\n setTimeout(() => {\n dispatch.updateButtonState(messageId, { copied: false });\n copyButtonRef?.current?.blur();\n }, 1000);\n },\n };\n\n const listenAction = {\n isClicked: isSpeaking,\n ref: speakingButtonRef,\n id: `listen-${messageId}`,\n tooltipContent: isSpeaking\n ? t('feedback.tooltips.listening')\n : t('feedback.tooltips.listen'),\n onClick: () => {\n const isCurrentlySpeaking =\n state[messageId]?.buttonState?.isSpeaking;\n\n if (isCurrentlySpeaking) {\n // Stop if it's already speaking this message\n cancelSpeaking(messageId);\n } else {\n cancelSpeaking();\n speakMessage(messageId, message.content as string);\n }\n },\n };\n\n return {\n ...message,\n userFeedbackForm,\n userFeedbackComplete,\n actions: {\n positive: createSentimentAction('positive'),\n negative: createSentimentAction('negative'),\n copy: copyAction,\n listen: listenAction,\n },\n };\n })\n : messages;\n }, [\n t,\n conversationId,\n messages,\n state,\n dispatch,\n isStreaming,\n speakMessage,\n feedbackForms,\n cancelSpeaking,\n feedbackEnabled,\n getUserFeedbackComplete,\n scrollToFeedbackForm,\n ]);\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useFeedbackActions.esm.js","sources":["../../src/hooks/useFeedbackActions.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 */\nimport { useCallback, useEffect, useMemo, useRef } from 'react';\n\nimport {\n MessageProps,\n UserFeedbackCompleteProps,\n UserFeedbackProps,\n} from '@patternfly/chatbot';\n\nimport { useCaptureFeedback } from '../hooks/useCaptureFeedback';\nimport { CaptureFeedback } from '../types';\nimport { Sentiment, useFeedbackState } from './useFeedbackState';\nimport { useFeedbackStatus } from './useFeedbackStatus';\nimport { useTranslation } from './useTranslation';\n\nexport const useFeedbackActions = <T extends MessageProps>(\n messages: T[],\n conversationId: string,\n isStreaming: boolean,\n): T[] => {\n const copyButtonRef = useRef<HTMLButtonElement>(null);\n const speakingButtonRef = useRef<HTMLButtonElement>(null);\n const currentSpeakingIdRef = useRef<string | null>(null);\n\n const { data: feedbackEnabled } = useFeedbackStatus();\n const { state, ...dispatch } = useFeedbackState();\n const { mutateAsync: captureFeedback } = useCaptureFeedback();\n const { t } = useTranslation();\n\n const createQuickResponses = useMemo(\n () => ({\n positive: [\n { id: '1', content: t('feedback.quickResponses.positive.helpful') },\n {\n id: '2',\n content: t('feedback.quickResponses.positive.easyToUnderstand'),\n },\n {\n id: '3',\n content: t('feedback.quickResponses.positive.resolvedIssue'),\n },\n ],\n negative: [\n { id: '1', content: t('feedback.quickResponses.negative.didntAnswer') },\n {\n id: '2',\n content: t('feedback.quickResponses.negative.hardToUnderstand'),\n },\n { id: '3', content: t('feedback.quickResponses.negative.notHelpful') },\n ],\n }),\n [t],\n );\n\n const getFeedbackForm = useCallback(\n (messageId: string, sentiment: 'positive' | 'negative') => ({\n key: `feedback-${sentiment}`,\n id: `feedback-${sentiment}-${messageId}`,\n hasTextArea: true,\n title: t('feedback.form.title'),\n textAreaPlaceholder: t('feedback.form.textAreaPlaceholder'),\n submitWord: t('feedback.form.submitWord'),\n quickResponses: createQuickResponses[sentiment],\n onSubmit: (\n quickResponse: string | undefined = '0',\n additionalFeedback: string | undefined,\n ) => {\n const quickIndex = Number(quickResponse) - 1;\n const quickText =\n quickResponse !== '0'\n ? createQuickResponses[sentiment]?.[quickIndex]?.content\n : undefined;\n\n let user_feedback = '';\n\n if (quickText && additionalFeedback) {\n user_feedback = `${quickText}\\nAdditional feedback: ${additionalFeedback}`;\n } else if (quickText) {\n user_feedback = quickText;\n } else if (additionalFeedback) {\n user_feedback = additionalFeedback;\n }\n\n const botAnswerId = Number(messageId.split('-').pop());\n const userQuestionId = botAnswerId - 1;\n\n const payload: CaptureFeedback = {\n conversation_id: conversationId,\n user_feedback,\n sentiment: sentiment === 'positive' ? 1 : -1,\n user_question: messages[userQuestionId].content || '',\n llm_response: messages[botAnswerId].content || '',\n };\n\n captureFeedback(payload).then(() => {\n dispatch.hideFeedbackForm(messageId, sentiment);\n dispatch.showCompletionForm(messageId, sentiment);\n dispatch.updateButtonState(messageId, {\n sentiment: sentiment,\n feedbackSubmitted: true,\n });\n\n setTimeout(() => {\n dispatch.hideCompletionForm(messageId, sentiment);\n }, 1000);\n });\n },\n\n // eslint-disable-next-line no-console\n onClose: () => {\n dispatch.hideFeedbackForm(messageId, sentiment);\n dispatch.resetButtonState(messageId);\n dispatch.updateButtonState(messageId, { sentiment: undefined });\n },\n focusOnLoad: true,\n }),\n [\n captureFeedback,\n conversationId,\n dispatch,\n messages,\n createQuickResponses,\n t,\n ],\n );\n\n const feedbackForms = useCallback(\n (messageId: string): { [key in Sentiment]: UserFeedbackProps } => ({\n positive: getFeedbackForm(messageId, 'positive'),\n negative: getFeedbackForm(messageId, 'negative'),\n }),\n [getFeedbackForm],\n );\n\n const getUserFeedbackComplete = useCallback(\n (\n messageId: string,\n sentiment: Sentiment,\n ): UserFeedbackCompleteProps | undefined => {\n const isVisible = state[messageId]?.completionForm?.[sentiment];\n if (!isVisible) return undefined;\n\n return {\n id: `feebback-completion-${sentiment}-${messageId}`,\n title: t('feedback.completion.title'),\n body: t('feedback.completion.body'),\n onClose: () => {\n dispatch.hideCompletionForm(messageId, sentiment);\n dispatch.resetButtonState(messageId);\n },\n };\n },\n [state, dispatch, t],\n );\n\n const scrollToFeedbackForm = useCallback(\n (messageId: string, sentiment: Sentiment) => {\n setTimeout(() => {\n const el = document.getElementById(\n `feedback-${sentiment}-${messageId}`,\n );\n if (el) {\n el.scrollIntoView({ behavior: 'auto', block: 'start' });\n el.focus();\n }\n }, 0);\n },\n [],\n );\n\n const speakMessage = useCallback(\n (messageId: string, content: string) => {\n if (window.speechSynthesis.speaking || window.speechSynthesis.pending) {\n window.speechSynthesis.cancel();\n\n if (\n currentSpeakingIdRef.current &&\n currentSpeakingIdRef.current !== messageId\n ) {\n dispatch.updateButtonState(currentSpeakingIdRef.current, {\n isSpeaking: false,\n });\n }\n }\n\n // Track the current SpeakingId\n currentSpeakingIdRef.current = messageId;\n\n const utterance = new SpeechSynthesisUtterance(content);\n\n utterance.onstart = () => {\n dispatch.updateButtonState(messageId, { isSpeaking: true });\n };\n\n utterance.onend = () => {\n dispatch.updateButtonState(messageId, { isSpeaking: false });\n currentSpeakingIdRef.current = null;\n };\n\n utterance.onerror = () => {\n dispatch.updateButtonState(messageId, { isSpeaking: false });\n currentSpeakingIdRef.current = null;\n };\n\n window.speechSynthesis.speak(utterance);\n },\n [dispatch],\n );\n\n const cancelSpeaking = useCallback(\n (messageId?: string) => {\n window.speechSynthesis.cancel();\n\n currentSpeakingIdRef.current = null;\n\n if (messageId) {\n // Cancel just this one message\n dispatch.updateButtonState(messageId, { isSpeaking: false });\n } else {\n // Cancel all messages\n Object.keys(state).forEach(id => {\n if (state[id].buttonState?.isSpeaking) {\n dispatch.updateButtonState(id, { isSpeaking: false });\n }\n });\n }\n setTimeout(() => {\n const el = document.getElementById(`listen-${messageId}`);\n if (el) {\n el.blur();\n }\n }, 10);\n },\n [state, dispatch],\n );\n\n useEffect(() => {\n return () => {\n // Stop any ongoing speech when component unmounts\n cancelSpeaking();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [conversationId]);\n\n return useMemo(() => {\n return feedbackEnabled\n ? messages.map((message, index) => {\n if (\n message.role === 'user' ||\n (isStreaming && messages.length - 1 === index)\n )\n return message;\n\n const messageId = `${conversationId}-${message.role}-${index}`;\n const { sentiment, copied, isSpeaking } =\n state[messageId]?.buttonState || {};\n const showFeedbackForm = state[messageId]?.feedbackForm?.[sentiment];\n const userFeedbackForm =\n showFeedbackForm && feedbackForms(messageId)[sentiment];\n\n const userFeedbackComplete = getUserFeedbackComplete(\n messageId,\n sentiment,\n );\n\n const createSentimentAction = (selected: Sentiment) => ({\n isClicked: sentiment === selected,\n onClick: () => {\n if (sentiment !== selected) {\n dispatch.toggleFeedbackForm(messageId, selected);\n dispatch.updateButtonState(messageId, { sentiment: selected });\n scrollToFeedbackForm(messageId, sentiment);\n }\n },\n tooltipContent:\n selected === 'positive'\n ? t('feedback.tooltips.goodResponse')\n : t('feedback.tooltips.badResponse'),\n 'aria-expanded': sentiment === selected,\n 'aria-controls': showFeedbackForm\n ? `feedback-${sentiment}-${messageId}`\n : `feebback-completion-${sentiment}-${messageId}`,\n });\n\n const copyAction = {\n isClicked: copied,\n ref: copyButtonRef,\n tooltipContent: copied\n ? t('feedback.tooltips.copied')\n : t('feedback.tooltips.copy'),\n onClick: async () => {\n await window.navigator.clipboard.writeText(\n message.content as string,\n );\n dispatch.updateButtonState(messageId, {\n copied: true,\n });\n\n setTimeout(() => {\n dispatch.updateButtonState(messageId, { copied: false });\n copyButtonRef?.current?.blur();\n }, 1000);\n },\n };\n\n const listenAction = {\n isClicked: isSpeaking,\n ref: speakingButtonRef,\n id: `listen-${messageId}`,\n tooltipContent: isSpeaking\n ? t('feedback.tooltips.listening')\n : t('feedback.tooltips.listen'),\n onClick: () => {\n const isCurrentlySpeaking =\n state[messageId]?.buttonState?.isSpeaking;\n\n if (isCurrentlySpeaking) {\n // Stop if it's already speaking this message\n cancelSpeaking(messageId);\n } else {\n cancelSpeaking();\n speakMessage(messageId, message.content as string);\n }\n },\n };\n\n return {\n ...message,\n userFeedbackForm,\n userFeedbackComplete,\n actions: {\n positive: createSentimentAction('positive'),\n negative: createSentimentAction('negative'),\n copy: copyAction,\n listen: listenAction,\n },\n };\n })\n : messages;\n }, [\n t,\n conversationId,\n messages,\n state,\n dispatch,\n isStreaming,\n speakMessage,\n feedbackForms,\n cancelSpeaking,\n feedbackEnabled,\n getUserFeedbackComplete,\n scrollToFeedbackForm,\n ]);\n};\n"],"names":[],"mappings":"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"}
|
package/dist/types.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.esm.js","sources":["../src/types.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 { SourcesCardProps } from '@patternfly/chatbot';\nimport { AlertProps } from '@patternfly/react-core';\n\nexport type Conversations = {\n [key: string]: {\n user: string;\n bot: string;\n model: string;\n loading: boolean;\n timestamp: string;\n botTimestamp: string;\n error?: AlertProps;\n };\n};\n\n/**\n * @public\n * Referenced document metadata\n */\nexport type ReferencedDocument = {\n doc_title: string;\n doc_url: string;\n doc_description?: string;\n};\n\n/**\n * @public\n * List of referenced documents\n */\nexport type ReferencedDocuments = ReferencedDocument[];\n\n/**\n * @public\n * LCS model type - embedding or llm\n */\nexport type LCSModelType = 'embedding' | 'llm';\n\n/**\n * @public\n * LCS model API model type\n */\nexport type LCSModelApiModelType = 'embedding' | 'llm';\n\n/**\n * @public\n * LCS Model interface\n */\nexport interface LCSModel {\n identifier: string;\n metadata: {\n embedding_dimension: number;\n };\n api_model_type: LCSModelApiModelType;\n provider_id: string;\n type: 'model';\n provider_resource_id: string;\n model_type: LCSModelType;\n}\nexport interface LCSConversation {\n provider: string;\n model: string;\n messages: BaseMessage[];\n started_at: string;\n completed_at: string;\n referenced_documents?: ReferencedDocuments;\n}\n\nexport interface LCSShield {\n identifier: string;\n provider_id: string;\n type: 'shield';\n params: {};\n provider_resource_id: string;\n}\n\n/**\n * @public\n * Base message interface for chat messages\n */\nexport interface BaseMessage {\n name: string;\n type: string;\n id: number;\n content: string;\n model: string;\n timestamp: string;\n sources?: SourcesCardProps;\n referenced_documents?: ReferencedDocuments;\n error?: AlertProps;\n}\n\n/**\n * @public\n * Conversation summary type\n */\nexport type ConversationSummary = {\n conversation_id: string;\n last_message_timestamp: number;\n topic_summary: string | null;\n};\n\nexport enum SupportedFileType {\n JSON = 'application/json',\n YAML = 'application/x-yaml',\n TEXT = 'text/plain',\n}\nexport interface FileContent {\n content: string;\n type: string;\n name: string;\n}\n\n/**\n * @public\n * Attachment type for file attachments in chat messages\n */\nexport type Attachment = {\n attachment_type: string;\n content_type: string;\n content: string;\n};\n\n/**\n * @public\n * List of conversation summaries\n */\nexport type ConversationList = ConversationSummary[];\n\nexport type SamplePrompt =\n | {\n title: string;\n message: string;\n }\n | {\n titleKey: string;\n messageKey: string;\n };\n\nexport type SamplePrompts = SamplePrompt[];\n\n/**\n * @public\n * Feedback capture payload for user feedback on AI responses\n */\nexport type CaptureFeedback = {\n conversation_id: string;\n user_question: string;\n llm_response: string;\n user_feedback: string;\n sentiment: number;\n};\n\n// Tool Calling Types\nexport interface ToolCall {\n id: number | string;\n toolName: string;\n description?: string;\n arguments: Record<string, any>;\n response?: string;\n startTime: number;\n endTime?: number;\n executionTime?: number; // in seconds\n isLoading: boolean;\n}\n\nexport interface ToolCallEvent {\n id: number | string;\n token?: string | { tool_name: string; arguments: Record<string, any> };\n name?: string;\n args?: Record<string, any>;\n arguments?: Record<string, any>;\n type?: string;\n}\n\nexport interface ToolResultEvent {\n id: number | string;\n token?: { tool_name: string; response: string };\n status?: string;\n content?: string;\n}\n\n/**\n * @public\n * Notebook session metadata from AI Notebooks API\n */\nexport type NotebookSessionMetadata = {\n category?: string;\n tags?: string[];\n project?: string;\n document_ids?: string[];\n conversation_id?: string;\n};\n\n/**\n * @public\n * Notebook session from AI Notebooks API\n */\nexport type NotebookSession = {\n session_id: string;\n user_id: string;\n name: string;\n description?: string;\n created_at: string;\n updated_at: string;\n document_count?: number;\n metadata?: NotebookSessionMetadata;\n};\n\n/**\n * @public\n * Supported file types for notebook document uploads\n */\nexport type NotebookDocumentSourceType =\n 'text' | 'pdf' | 'md' | 'json' | 'yaml' | 'log';\n\n/**\n * @public\n * Document within a notebook session\n */\nexport type SessionDocument = {\n document_id: string;\n title: string;\n session_id: string;\n user_id: string;\n source_type: NotebookDocumentSourceType;\n created_at: string;\n metadata?: Record<string, any>;\n};\n\n/**\n * @public\n * Response from the document upload endpoint (HTTP 202)\n */\nexport type UploadDocumentResponse = {\n status: 'processing';\n document_id: string;\n session_id: string;\n message: string;\n};\n\n/**\n * @public\n * Document processing status from the status polling endpoint\n */\nexport type DocumentStatus = {\n status: 'in_progress' | 'completed' | 'failed' | 'cancelled';\n document_id: string;\n session_id: string;\n error?: string;\n};\n\n/**\n * @public\n * Response wrapper for session creation\n */\nexport type SessionResponse = {\n status: 'success' | 'error';\n session?: NotebookSession;\n message?: string;\n error?: string;\n};\n\n/**\n * @public\n * Response wrapper for document list\n */\nexport type DocumentListResponse = {\n status: 'success' | 'error';\n session_id?: string;\n documents?: SessionDocument[];\n count?: number;\n error?: string;\n};\n"],"names":["SupportedFileType"],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.esm.js","sources":["../src/types.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 { SourcesCardProps } from '@patternfly/chatbot';\nimport { AlertProps } from '@patternfly/react-core';\n\nexport type Conversations = {\n [key: string]: {\n user: string;\n bot: string;\n model: string;\n loading: boolean;\n timestamp: string;\n botTimestamp: string;\n error?: AlertProps;\n };\n};\n\n/**\n * @public\n * Referenced document metadata\n */\nexport type ReferencedDocument = {\n doc_title: string;\n doc_url: string;\n doc_description?: string;\n source?: string;\n};\n\n/**\n * @public\n * List of referenced documents\n */\nexport type ReferencedDocuments = ReferencedDocument[];\n\n/**\n * @public\n * LCS model type - embedding or llm\n */\nexport type LCSModelType = 'embedding' | 'llm';\n\n/**\n * @public\n * LCS model API model type\n */\nexport type LCSModelApiModelType = 'embedding' | 'llm';\n\n/**\n * @public\n * LCS Model interface\n */\nexport interface LCSModel {\n identifier: string;\n metadata: {\n embedding_dimension: number;\n };\n api_model_type: LCSModelApiModelType;\n provider_id: string;\n type: 'model';\n provider_resource_id: string;\n model_type: LCSModelType;\n}\nexport interface LCSConversation {\n provider: string;\n model: string;\n messages: BaseMessage[];\n started_at: string;\n completed_at: string;\n referenced_documents?: ReferencedDocuments;\n}\n\nexport interface LCSShield {\n identifier: string;\n provider_id: string;\n type: 'shield';\n params: {};\n provider_resource_id: string;\n}\n\n/**\n * @public\n * Base message interface for chat messages\n */\nexport interface BaseMessage {\n name: string;\n type: string;\n id: number;\n content: string;\n model: string;\n timestamp: string;\n sources?: SourcesCardProps;\n referenced_documents?: ReferencedDocuments;\n error?: AlertProps;\n}\n\n/**\n * @public\n * Conversation summary type\n */\nexport type ConversationSummary = {\n conversation_id: string;\n last_message_timestamp: number;\n topic_summary: string | null;\n};\n\nexport enum SupportedFileType {\n JSON = 'application/json',\n YAML = 'application/x-yaml',\n TEXT = 'text/plain',\n}\nexport interface FileContent {\n content: string;\n type: string;\n name: string;\n}\n\n/**\n * @public\n * Attachment type for file attachments in chat messages\n */\nexport type Attachment = {\n attachment_type: string;\n content_type: string;\n content: string;\n};\n\n/**\n * @public\n * List of conversation summaries\n */\nexport type ConversationList = ConversationSummary[];\n\nexport type SamplePrompt =\n | {\n title: string;\n message: string;\n }\n | {\n titleKey: string;\n messageKey: string;\n };\n\nexport type SamplePrompts = SamplePrompt[];\n\n/**\n * @public\n * Feedback capture payload for user feedback on AI responses\n */\nexport type CaptureFeedback = {\n conversation_id: string;\n user_question: string;\n llm_response: string;\n user_feedback: string;\n sentiment: number;\n};\n\n// Tool Calling Types\nexport interface ToolCall {\n id: number | string;\n toolName: string;\n description?: string;\n arguments: Record<string, any>;\n response?: string;\n startTime: number;\n endTime?: number;\n executionTime?: number; // in seconds\n isLoading: boolean;\n}\n\nexport interface ToolCallEvent {\n id: number | string;\n token?: string | { tool_name: string; arguments: Record<string, any> };\n name?: string;\n args?: Record<string, any>;\n arguments?: Record<string, any>;\n type?: string;\n}\n\nexport interface ToolResultEvent {\n id: number | string;\n token?: { tool_name: string; response: string };\n status?: string;\n content?: string;\n}\n\n/**\n * @public\n * Notebook session metadata from AI Notebooks API\n */\nexport type NotebookSessionMetadata = {\n category?: string;\n tags?: string[];\n project?: string;\n document_ids?: string[];\n conversation_id?: string;\n};\n\n/**\n * @public\n * Notebook session from AI Notebooks API\n */\nexport type NotebookSession = {\n session_id: string;\n user_id: string;\n name: string;\n description?: string;\n created_at: string;\n updated_at: string;\n document_count?: number;\n metadata?: NotebookSessionMetadata;\n};\n\n/**\n * @public\n * Supported file types for notebook document uploads\n */\nexport type NotebookDocumentSourceType =\n 'text' | 'pdf' | 'md' | 'json' | 'yaml' | 'log';\n\n/**\n * @public\n * Document within a notebook session\n */\nexport type SessionDocument = {\n document_id: string;\n title: string;\n session_id: string;\n user_id: string;\n source_type: NotebookDocumentSourceType;\n created_at: string;\n metadata?: Record<string, any>;\n};\n\n/**\n * @public\n * Response from the document upload endpoint (HTTP 202)\n */\nexport type UploadDocumentResponse = {\n status: 'processing';\n document_id: string;\n session_id: string;\n message: string;\n};\n\n/**\n * @public\n * Document processing status from the status polling endpoint\n */\nexport type DocumentStatus = {\n status: 'in_progress' | 'completed' | 'failed' | 'cancelled';\n document_id: string;\n session_id: string;\n error?: string;\n};\n\n/**\n * @public\n * Response wrapper for session creation\n */\nexport type SessionResponse = {\n status: 'success' | 'error';\n session?: NotebookSession;\n message?: string;\n error?: string;\n};\n\n/**\n * @public\n * Response wrapper for document list\n */\nexport type DocumentListResponse = {\n status: 'success' | 'error';\n session_id?: string;\n documents?: SessionDocument[];\n count?: number;\n error?: string;\n};\n"],"names":["SupportedFileType"],"mappings":"AAsHO,IAAK,iBAAA,qBAAAA,kBAAAA,KAAL;AACL,EAAAA,mBAAA,MAAA,CAAA,GAAO,kBAAA;AACP,EAAAA,mBAAA,MAAA,CAAA,GAAO,oBAAA;AACP,EAAAA,mBAAA,MAAA,CAAA,GAAO,YAAA;AAHG,EAAA,OAAAA,kBAAAA;AAAA,CAAA,EAAA,iBAAA,IAAA,EAAA;;;;"}
|
|
@@ -3,6 +3,7 @@ import { ChatbotFootnote } from '@patternfly/chatbot';
|
|
|
3
3
|
import { Spinner } from '@patternfly/react-core';
|
|
4
4
|
import { ThumbtackIcon } from '@patternfly/react-icons';
|
|
5
5
|
import { RhUiAiInfoIcon } from '@patternfly/react-icons/dist/esm/icons/rh-ui-ai-info-icon';
|
|
6
|
+
import { RagSourceLabel } from '../components/RagSourceLabel.esm.js';
|
|
6
7
|
|
|
7
8
|
const getFootnoteProps = (t) => ({
|
|
8
9
|
label: t?.("footer.accuracy.label") || "Always review AI generated content prior to use."
|
|
@@ -151,12 +152,18 @@ const transformDocumentsToSources = (referenced_documents) => {
|
|
|
151
152
|
return void 0;
|
|
152
153
|
}
|
|
153
154
|
return {
|
|
154
|
-
sources: referenced_documents.map(
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
155
|
+
sources: referenced_documents.map(
|
|
156
|
+
(doc) => ({
|
|
157
|
+
body: doc.doc_description,
|
|
158
|
+
title: doc.doc_title,
|
|
159
|
+
link: doc?.doc_url,
|
|
160
|
+
isExternal: !!doc?.doc_url,
|
|
161
|
+
...doc.source ? {
|
|
162
|
+
headerContent: /* @__PURE__ */ jsx(RagSourceLabel, { source: doc.source }),
|
|
163
|
+
ragSource: doc.source
|
|
164
|
+
} : {}
|
|
165
|
+
})
|
|
166
|
+
)
|
|
160
167
|
};
|
|
161
168
|
};
|
|
162
169
|
const sortConversations = (messages, sortOption) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lightspeed-chatbox-utils.esm.js","sources":["../../src/utils/lightspeed-chatbox-utils.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 */\nimport {\n ChatbotFootnote,\n Conversation,\n SourcesCardProps,\n} from '@patternfly/chatbot';\nimport { Spinner } from '@patternfly/react-core';\nimport { ThumbtackIcon } from '@patternfly/react-icons';\nimport { RhUiAiInfoIcon } from '@patternfly/react-icons/dist/esm/icons/rh-ui-ai-info-icon';\n\nimport {\n BaseMessage,\n ConversationList,\n ConversationSummary,\n LCSConversation,\n ReferencedDocument,\n ReferencedDocuments,\n ToolCall,\n} from '../types';\n\nexport const getFootnoteProps = (\n t?: (key: string, params?: any) => string,\n) => ({\n label:\n t?.('footer.accuracy.label') ||\n 'Always review AI generated content prior to use.',\n});\n\nexport const ChatbotFootnoteWithIcon = ({ label }: { label: string }) => (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '4px',\n }}\n >\n <RhUiAiInfoIcon style={{ width: '14px', height: '14px', flexShrink: 0 }} />\n <ChatbotFootnote label={label} />\n </div>\n);\n\nexport const getTimestampVariablesString = (v: number) => {\n if (v < 10) {\n return `0${v}`;\n }\n return `${v}`;\n};\n\nconst isBlankLine = (line: string) => !line.trim();\n\n/** Ordered list item at line start (CommonMark), ignoring leading spaces. */\nconst isOrderedListLine = (line: string) => /^\\s*\\d+\\.\\s/.test(line);\n\n/** ASCII bullets; also U+2022 (•) — not a CommonMark marker, but users paste it as a list. */\nconst isBulletListLine = (line: string) =>\n /^\\s*[-*+]\\s/.test(line) || /^\\s*\\u2022(?:\\s+|\\S|$)/u.test(line);\n\nconst escapeBulletListMarker = (line: string) => {\n if (/^\\s*\\u2022/u.test(line)) {\n return line;\n }\n return line.replace(/^(\\s*)([*+-])(\\s)/, '$1\\\\$2$3');\n};\n\nconst escapeOrderedListMarker = (line: string) =>\n line.replace(/^(\\s*)(\\d+)\\.(\\s)/, '$1$2\\\\.$3');\n\n/**\n * When intro lines (no blank lines among them) are followed by a contiguous run of\n * list lines, join intro + list into one Markdown paragraph using hard breaks and\n * per-line escaping so the block does not split awkwardly in the chat UI.\n */\nconst foldListWithIntro = (\n s: string,\n isListItemLine: (line: string) => boolean,\n escapeListLine: (line: string) => string,\n): string => {\n const lines = s.split('\\n');\n let firstListIdx = -1;\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (line !== undefined && isListItemLine(line)) {\n firstListIdx = i;\n break;\n }\n }\n if (firstListIdx < 0) {\n return s;\n }\n\n const intro = lines.slice(0, firstListIdx);\n if (intro.some(isBlankLine)) {\n return s;\n }\n\n const rest = lines.slice(firstListIdx);\n const restItems = rest.filter(l => !isBlankLine(l));\n if (restItems.length === 0 || !restItems.every(isListItemLine)) {\n return s;\n }\n\n const escaped = restItems.map(escapeListLine);\n if (intro.length === 0) {\n return escaped.join(' \\n');\n }\n return `${intro.join(' \\n')} \\n${escaped.join(' \\n')}`;\n};\n\n/**\n * Paragraph + ordered list (even with a single newline) parses as two blocks; merge\n * intro + contiguous numbered lines into one paragraph using hard breaks (two spaces\n * + newline) and escaped `1.` markers so Markdown stays a single block.\n */\nconst foldOrderedListWithIntro = (s: string) =>\n foldListWithIntro(s, isOrderedListLine, escapeOrderedListMarker);\n\n/** Same idea as ordered lists for intro + bullet lines. */\nconst foldBulletListWithIntro = (s: string) =>\n foldListWithIntro(s, isBulletListLine, escapeBulletListMarker);\n\n/**\n * Trims user chat input and reduces blank lines that split Markdown blocks\n * (e.g. paragraph + blank line + ordered list) so PatternFly renders one user bubble.\n */\nexport const normalizeChatUserInput = (input: string): string => {\n let s = input.replace(/\\r\\n/g, '\\n').trim();\n if (!s) {\n return s;\n }\n s = s.replace(/\\n{3,}/g, '\\n\\n');\n s = s.replace(/\\n\\n(?=\\s*\\d+\\.\\s)/gm, '\\n');\n s = s.replace(/\\n\\n(?=\\s*[-*+]\\s)/gm, '\\n');\n s = s.replace(/\\n\\n(?=\\s*\\u2022)/gm, '\\n');\n s = foldOrderedListWithIntro(s);\n s = foldBulletListWithIntro(s);\n return s.trim();\n};\n\nexport const getTimestamp = (unix_timestamp: number) => {\n if (typeof unix_timestamp !== 'number' || Number.isNaN(unix_timestamp)) {\n // eslint-disable-next-line no-console\n console.error('Invalid Unix timestamp provided');\n return '';\n }\n\n const a = new Date(unix_timestamp);\n const month = getTimestampVariablesString(a.getMonth() + 1);\n const year = a.getFullYear();\n const date = getTimestampVariablesString(a.getDate());\n const hour = getTimestampVariablesString(a.getHours());\n const min = getTimestampVariablesString(a.getMinutes());\n const sec = getTimestampVariablesString(a.getSeconds());\n const time = `${date}/${month}/${year}, ${hour}:${min}:${sec}`;\n return time;\n};\n\nexport const splitJsonStrings = (jsonString: string): string[] => {\n const chunks = jsonString.split('}{');\n\n if (chunks.length <= 1) {\n return [jsonString];\n }\n\n return chunks.map((chunk, index, arr) => {\n if (index === 0) {\n return `${chunk}}`;\n } else if (index === arr.length - 1) {\n return `{${chunk}`;\n }\n return `{${chunk}}`;\n });\n};\n\ntype MessageProps = {\n content: string;\n timestamp: string;\n name?: string;\n avatar?: string | any;\n isLoading?: boolean;\n error?: {\n title: string;\n };\n sources?: SourcesCardProps;\n toolCalls?: ToolCall[];\n};\n\nexport const createMessage = ({\n role,\n name,\n avatar,\n isLoading = false,\n content,\n timestamp,\n error,\n sources,\n toolCalls,\n defaultUserName = 'Guest',\n}: MessageProps & { role: 'user' | 'bot'; defaultUserName?: string }) => ({\n role,\n name: name || defaultUserName,\n avatar,\n isLoading,\n content,\n timestamp,\n error,\n sources,\n toolCalls,\n});\n\nexport const createUserMessage = (\n props: MessageProps & { defaultUserName?: string },\n) =>\n createMessage({\n ...props,\n role: 'user',\n defaultUserName: props.defaultUserName,\n });\n\nexport const createBotMessage = (props: MessageProps) =>\n createMessage({\n ...props,\n role: 'bot',\n });\n\nexport const getConversationsData = (\n conversation: LCSConversation,\n): [BaseMessage, BaseMessage] => {\n const [userMessage, botMessage] = conversation.messages || [];\n return [\n {\n ...userMessage,\n timestamp: getTimestamp(\n conversation.started_at\n ? new Date(conversation.started_at).getTime()\n : Date.now(),\n ),\n },\n {\n ...botMessage,\n timestamp: getTimestamp(\n conversation.completed_at\n ? new Date(conversation.completed_at).getTime()\n : Date.now(),\n ),\n referenced_documents: botMessage?.referenced_documents ?? [],\n },\n ];\n};\n\nexport const transformDocumentsToSources = (\n referenced_documents: ReferencedDocuments,\n): SourcesCardProps | undefined => {\n if (!referenced_documents || referenced_documents?.length === 0) {\n return undefined;\n }\n return {\n sources: referenced_documents.map((doc: ReferencedDocument) => ({\n body: doc.doc_description,\n title: doc.doc_title,\n link: doc?.doc_url,\n isExternal: !!doc?.doc_url,\n })),\n };\n};\n\nexport type SortOption =\n 'newest' | 'oldest' | 'alphabeticalAsc' | 'alphabeticalDesc';\n\nconst sortConversations = (\n messages: ConversationList,\n sortOption: SortOption,\n): ConversationList => {\n return [...messages].sort((a, b) => {\n const aTopicSummary = a.topic_summary || '';\n const bTopicSummary = b.topic_summary || '';\n switch (sortOption) {\n case 'oldest':\n return a.last_message_timestamp - b.last_message_timestamp;\n case 'alphabeticalAsc':\n return aTopicSummary.localeCompare(bTopicSummary, undefined, {\n sensitivity: 'base',\n });\n case 'alphabeticalDesc':\n return bTopicSummary.localeCompare(aTopicSummary, undefined, {\n sensitivity: 'base',\n });\n case 'newest':\n default:\n return b.last_message_timestamp - a.last_message_timestamp;\n }\n });\n};\n\nexport const getCategorizeMessages = (\n messages: ConversationList,\n pinnedChats: string[],\n addProps: (c: ConversationSummary) => { [k: string]: any },\n t?: (key: string, params?: any) => string,\n sortOption: SortOption = 'newest',\n): { [k: string]: Conversation[] } => {\n const pinnedChatsKey =\n t?.('conversation.category.pinnedChats') || 'Pinned chats';\n const recentKey = t?.('conversation.category.recent') || 'Chats';\n const categorizedMessages: { [k: string]: Conversation[] } = {\n [pinnedChatsKey]: [],\n [recentKey]: [],\n };\n const sortedMessages = sortConversations(messages, sortOption);\n sortedMessages.forEach(c => {\n const message: Conversation = {\n id: c.conversation_id,\n text: c.topic_summary ?? '',\n icon: c.topic_summary ? undefined : <Spinner size=\"sm\" />,\n label: t?.('message.options.label') || 'Options',\n additionalProps: {\n 'aria-label': t?.('aria.options.label') || 'Options',\n },\n ...addProps(c),\n };\n\n if (pinnedChats.includes(c.conversation_id)) {\n categorizedMessages[pinnedChatsKey].push({\n ...message,\n icon: (\n <ThumbtackIcon\n style={{\n width: '1rem',\n height: '1rem',\n display: 'flex',\n alignItems: 'center',\n }}\n />\n ),\n });\n } else {\n categorizedMessages[recentKey].push(message);\n }\n });\n\n const filteredCategories = Object.keys(categorizedMessages).reduce(\n (result, category) => {\n result[category] = categorizedMessages[category];\n return result;\n },\n {} as any,\n );\n\n return filteredCategories;\n};\n"],"names":[],"mappings":";;;;;;AAkCO,MAAM,gBAAA,GAAmB,CAC9B,CAAA,MACI;AAAA,EACJ,KAAA,EACE,CAAA,GAAI,uBAAuB,CAAA,IAC3B;AACJ,CAAA;AAEO,MAAM,uBAAA,GAA0B,CAAC,EAAE,KAAA,EAAM,qBAC9C,IAAA;AAAA,EAAC,KAAA;AAAA,EAAA;AAAA,IACC,KAAA,EAAO;AAAA,MACL,OAAA,EAAS,MAAA;AAAA,MACT,UAAA,EAAY,QAAA;AAAA,MACZ,cAAA,EAAgB,QAAA;AAAA,MAChB,GAAA,EAAK;AAAA,KACP;AAAA,IAEA,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,cAAA,EAAA,EAAe,OAAO,EAAE,KAAA,EAAO,QAAQ,MAAA,EAAQ,MAAA,EAAQ,UAAA,EAAY,CAAA,EAAE,EAAG,CAAA;AAAA,sBACzE,GAAA,CAAC,mBAAgB,KAAA,EAAc;AAAA;AAAA;AACjC;AAGK,MAAM,2BAAA,GAA8B,CAAC,CAAA,KAAc;AACxD,EAAA,IAAI,IAAI,EAAA,EAAI;AACV,IAAA,OAAO,IAAI,CAAC,CAAA,CAAA;AAAA,EACd;AACA,EAAA,OAAO,GAAG,CAAC,CAAA,CAAA;AACb;AAEA,MAAM,WAAA,GAAc,CAAC,IAAA,KAAiB,CAAC,KAAK,IAAA,EAAK;AAGjD,MAAM,iBAAA,GAAoB,CAAC,IAAA,KAAiB,aAAA,CAAc,KAAK,IAAI,CAAA;AAGnE,MAAM,gBAAA,GAAmB,CAAC,IAAA,KACxB,aAAA,CAAc,KAAK,IAAI,CAAA,IAAK,yBAAA,CAA0B,IAAA,CAAK,IAAI,CAAA;AAEjE,MAAM,sBAAA,GAAyB,CAAC,IAAA,KAAiB;AAC/C,EAAA,IAAI,aAAA,CAAc,IAAA,CAAK,IAAI,CAAA,EAAG;AAC5B,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,mBAAA,EAAqB,UAAU,CAAA;AACrD,CAAA;AAEA,MAAM,0BAA0B,CAAC,IAAA,KAC/B,IAAA,CAAK,OAAA,CAAQ,qBAAqB,WAAW,CAAA;AAO/C,MAAM,iBAAA,GAAoB,CACxB,CAAA,EACA,cAAA,EACA,cAAA,KACW;AACX,EAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,KAAA,CAAM,IAAI,CAAA;AAC1B,EAAA,IAAI,YAAA,GAAe,EAAA;AACnB,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,MAAM,IAAA,GAAO,MAAM,CAAC,CAAA;AACpB,IAAA,IAAI,IAAA,KAAS,MAAA,IAAa,cAAA,CAAe,IAAI,CAAA,EAAG;AAC9C,MAAA,YAAA,GAAe,CAAA;AACf,MAAA;AAAA,IACF;AAAA,EACF;AACA,EAAA,IAAI,eAAe,CAAA,EAAG;AACpB,IAAA,OAAO,CAAA;AAAA,EACT;AAEA,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,YAAY,CAAA;AACzC,EAAA,IAAI,KAAA,CAAM,IAAA,CAAK,WAAW,CAAA,EAAG;AAC3B,IAAA,OAAO,CAAA;AAAA,EACT;AAEA,EAAA,MAAM,IAAA,GAAO,KAAA,CAAM,KAAA,CAAM,YAAY,CAAA;AACrC,EAAA,MAAM,YAAY,IAAA,CAAK,MAAA,CAAO,OAAK,CAAC,WAAA,CAAY,CAAC,CAAC,CAAA;AAClD,EAAA,IAAI,UAAU,MAAA,KAAW,CAAA,IAAK,CAAC,SAAA,CAAU,KAAA,CAAM,cAAc,CAAA,EAAG;AAC9D,IAAA,OAAO,CAAA;AAAA,EACT;AAEA,EAAA,MAAM,OAAA,GAAU,SAAA,CAAU,GAAA,CAAI,cAAc,CAAA;AAC5C,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,OAAO,OAAA,CAAQ,KAAK,MAAM,CAAA;AAAA,EAC5B;AACA,EAAA,OAAO,CAAA,EAAG,KAAA,CAAM,IAAA,CAAK,MAAM,CAAC,CAAA;AAAA,EAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA,CAAA;AACzD,CAAA;AAOA,MAAM,2BAA2B,CAAC,CAAA,KAChC,iBAAA,CAAkB,CAAA,EAAG,mBAAmB,uBAAuB,CAAA;AAGjE,MAAM,0BAA0B,CAAC,CAAA,KAC/B,iBAAA,CAAkB,CAAA,EAAG,kBAAkB,sBAAsB,CAAA;AAMxD,MAAM,sBAAA,GAAyB,CAAC,KAAA,KAA0B;AAC/D,EAAA,IAAI,IAAI,KAAA,CAAM,OAAA,CAAQ,OAAA,EAAS,IAAI,EAAE,IAAA,EAAK;AAC1C,EAAA,IAAI,CAAC,CAAA,EAAG;AACN,IAAA,OAAO,CAAA;AAAA,EACT;AACA,EAAA,CAAA,GAAI,CAAA,CAAE,OAAA,CAAQ,SAAA,EAAW,MAAM,CAAA;AAC/B,EAAA,CAAA,GAAI,CAAA,CAAE,OAAA,CAAQ,sBAAA,EAAwB,IAAI,CAAA;AAC1C,EAAA,CAAA,GAAI,CAAA,CAAE,OAAA,CAAQ,sBAAA,EAAwB,IAAI,CAAA;AAC1C,EAAA,CAAA,GAAI,CAAA,CAAE,OAAA,CAAQ,qBAAA,EAAuB,IAAI,CAAA;AACzC,EAAA,CAAA,GAAI,yBAAyB,CAAC,CAAA;AAC9B,EAAA,CAAA,GAAI,wBAAwB,CAAC,CAAA;AAC7B,EAAA,OAAO,EAAE,IAAA,EAAK;AAChB;AAEO,MAAM,YAAA,GAAe,CAAC,cAAA,KAA2B;AACtD,EAAA,IAAI,OAAO,cAAA,KAAmB,QAAA,IAAY,MAAA,CAAO,KAAA,CAAM,cAAc,CAAA,EAAG;AAEtE,IAAA,OAAA,CAAQ,MAAM,iCAAiC,CAAA;AAC/C,IAAA,OAAO,EAAA;AAAA,EACT;AAEA,EAAA,MAAM,CAAA,GAAI,IAAI,IAAA,CAAK,cAAc,CAAA;AACjC,EAAA,MAAM,KAAA,GAAQ,2BAAA,CAA4B,CAAA,CAAE,QAAA,KAAa,CAAC,CAAA;AAC1D,EAAA,MAAM,IAAA,GAAO,EAAE,WAAA,EAAY;AAC3B,EAAA,MAAM,IAAA,GAAO,2BAAA,CAA4B,CAAA,CAAE,OAAA,EAAS,CAAA;AACpD,EAAA,MAAM,IAAA,GAAO,2BAAA,CAA4B,CAAA,CAAE,QAAA,EAAU,CAAA;AACrD,EAAA,MAAM,GAAA,GAAM,2BAAA,CAA4B,CAAA,CAAE,UAAA,EAAY,CAAA;AACtD,EAAA,MAAM,GAAA,GAAM,2BAAA,CAA4B,CAAA,CAAE,UAAA,EAAY,CAAA;AACtD,EAAA,MAAM,IAAA,GAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA,EAAI,IAAI,CAAA,EAAA,EAAK,IAAI,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA;AAC5D,EAAA,OAAO,IAAA;AACT;AAgCO,MAAM,gBAAgB,CAAC;AAAA,EAC5B,IAAA;AAAA,EACA,IAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA,GAAY,KAAA;AAAA,EACZ,OAAA;AAAA,EACA,SAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,eAAA,GAAkB;AACpB,CAAA,MAA0E;AAAA,EACxE,IAAA;AAAA,EACA,MAAM,IAAA,IAAQ,eAAA;AAAA,EACd,MAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA;AAEO,MAAM,iBAAA,GAAoB,CAC/B,KAAA,KAEA,aAAA,CAAc;AAAA,EACZ,GAAG,KAAA;AAAA,EACH,IAAA,EAAM,MAAA;AAAA,EACN,iBAAiB,KAAA,CAAM;AACzB,CAAC;AAEI,MAAM,gBAAA,GAAmB,CAAC,KAAA,KAC/B,aAAA,CAAc;AAAA,EACZ,GAAG,KAAA;AAAA,EACH,IAAA,EAAM;AACR,CAAC;AAEI,MAAM,oBAAA,GAAuB,CAClC,YAAA,KAC+B;AAC/B,EAAA,MAAM,CAAC,WAAA,EAAa,UAAU,CAAA,GAAI,YAAA,CAAa,YAAY,EAAC;AAC5D,EAAA,OAAO;AAAA,IACL;AAAA,MACE,GAAG,WAAA;AAAA,MACH,SAAA,EAAW,YAAA;AAAA,QACT,YAAA,CAAa,UAAA,GACT,IAAI,IAAA,CAAK,YAAA,CAAa,UAAU,CAAA,CAAE,OAAA,EAAQ,GAC1C,IAAA,CAAK,GAAA;AAAI;AACf,KACF;AAAA,IACA;AAAA,MACE,GAAG,UAAA;AAAA,MACH,SAAA,EAAW,YAAA;AAAA,QACT,YAAA,CAAa,YAAA,GACT,IAAI,IAAA,CAAK,YAAA,CAAa,YAAY,CAAA,CAAE,OAAA,EAAQ,GAC5C,IAAA,CAAK,GAAA;AAAI,OACf;AAAA,MACA,oBAAA,EAAsB,UAAA,EAAY,oBAAA,IAAwB;AAAC;AAC7D,GACF;AACF;AAEO,MAAM,2BAAA,GAA8B,CACzC,oBAAA,KACiC;AACjC,EAAA,IAAI,CAAC,oBAAA,IAAwB,oBAAA,EAAsB,MAAA,KAAW,CAAA,EAAG;AAC/D,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,oBAAA,CAAqB,GAAA,CAAI,CAAC,GAAA,MAA6B;AAAA,MAC9D,MAAM,GAAA,CAAI,eAAA;AAAA,MACV,OAAO,GAAA,CAAI,SAAA;AAAA,MACX,MAAM,GAAA,EAAK,OAAA;AAAA,MACX,UAAA,EAAY,CAAC,CAAC,GAAA,EAAK;AAAA,KACrB,CAAE;AAAA,GACJ;AACF;AAKA,MAAM,iBAAA,GAAoB,CACxB,QAAA,EACA,UAAA,KACqB;AACrB,EAAA,OAAO,CAAC,GAAG,QAAQ,EAAE,IAAA,CAAK,CAAC,GAAG,CAAA,KAAM;AAClC,IAAA,MAAM,aAAA,GAAgB,EAAE,aAAA,IAAiB,EAAA;AACzC,IAAA,MAAM,aAAA,GAAgB,EAAE,aAAA,IAAiB,EAAA;AACzC,IAAA,QAAQ,UAAA;AAAY,MAClB,KAAK,QAAA;AACH,QAAA,OAAO,CAAA,CAAE,yBAAyB,CAAA,CAAE,sBAAA;AAAA,MACtC,KAAK,iBAAA;AACH,QAAA,OAAO,aAAA,CAAc,aAAA,CAAc,aAAA,EAAe,MAAA,EAAW;AAAA,UAC3D,WAAA,EAAa;AAAA,SACd,CAAA;AAAA,MACH,KAAK,kBAAA;AACH,QAAA,OAAO,aAAA,CAAc,aAAA,CAAc,aAAA,EAAe,MAAA,EAAW;AAAA,UAC3D,WAAA,EAAa;AAAA,SACd,CAAA;AAAA,MACH,KAAK,QAAA;AAAA,MACL;AACE,QAAA,OAAO,CAAA,CAAE,yBAAyB,CAAA,CAAE,sBAAA;AAAA;AACxC,EACF,CAAC,CAAA;AACH,CAAA;AAEO,MAAM,wBAAwB,CACnC,QAAA,EACA,aACA,QAAA,EACA,CAAA,EACA,aAAyB,QAAA,KACW;AACpC,EAAA,MAAM,cAAA,GACJ,CAAA,GAAI,mCAAmC,CAAA,IAAK,cAAA;AAC9C,EAAA,MAAM,SAAA,GAAY,CAAA,GAAI,8BAA8B,CAAA,IAAK,OAAA;AACzD,EAAA,MAAM,mBAAA,GAAuD;AAAA,IAC3D,CAAC,cAAc,GAAG,EAAC;AAAA,IACnB,CAAC,SAAS,GAAG;AAAC,GAChB;AACA,EAAA,MAAM,cAAA,GAAiB,iBAAA,CAAkB,QAAA,EAAU,UAAU,CAAA;AAC7D,EAAA,cAAA,CAAe,QAAQ,CAAA,CAAA,KAAK;AAC1B,IAAA,MAAM,OAAA,GAAwB;AAAA,MAC5B,IAAI,CAAA,CAAE,eAAA;AAAA,MACN,IAAA,EAAM,EAAE,aAAA,IAAiB,EAAA;AAAA,MACzB,MAAM,CAAA,CAAE,aAAA,GAAgB,yBAAY,GAAA,CAAC,OAAA,EAAA,EAAQ,MAAK,IAAA,EAAK,CAAA;AAAA,MACvD,KAAA,EAAO,CAAA,GAAI,uBAAuB,CAAA,IAAK,SAAA;AAAA,MACvC,eAAA,EAAiB;AAAA,QACf,YAAA,EAAc,CAAA,GAAI,oBAAoB,CAAA,IAAK;AAAA,OAC7C;AAAA,MACA,GAAG,SAAS,CAAC;AAAA,KACf;AAEA,IAAA,IAAI,WAAA,CAAY,QAAA,CAAS,CAAA,CAAE,eAAe,CAAA,EAAG;AAC3C,MAAA,mBAAA,CAAoB,cAAc,EAAE,IAAA,CAAK;AAAA,QACvC,GAAG,OAAA;AAAA,QACH,IAAA,kBACE,GAAA;AAAA,UAAC,aAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAO;AAAA,cACL,KAAA,EAAO,MAAA;AAAA,cACP,MAAA,EAAQ,MAAA;AAAA,cACR,OAAA,EAAS,MAAA;AAAA,cACT,UAAA,EAAY;AAAA;AACd;AAAA;AACF,OAEH,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,mBAAA,CAAoB,SAAS,CAAA,CAAE,IAAA,CAAK,OAAO,CAAA;AAAA,IAC7C;AAAA,EACF,CAAC,CAAA;AAED,EAAA,MAAM,kBAAA,GAAqB,MAAA,CAAO,IAAA,CAAK,mBAAmB,CAAA,CAAE,MAAA;AAAA,IAC1D,CAAC,QAAQ,QAAA,KAAa;AACpB,MAAA,MAAA,CAAO,QAAQ,CAAA,GAAI,mBAAA,CAAoB,QAAQ,CAAA;AAC/C,MAAA,OAAO,MAAA;AAAA,IACT,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,OAAO,kBAAA;AACT;;;;"}
|
|
1
|
+
{"version":3,"file":"lightspeed-chatbox-utils.esm.js","sources":["../../src/utils/lightspeed-chatbox-utils.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 */\nimport {\n ChatbotFootnote,\n Conversation,\n SourcesCardProps,\n} from '@patternfly/chatbot';\nimport { Spinner } from '@patternfly/react-core';\nimport { ThumbtackIcon } from '@patternfly/react-icons';\nimport { RhUiAiInfoIcon } from '@patternfly/react-icons/dist/esm/icons/rh-ui-ai-info-icon';\n\nimport { RagSourceLabel } from '../components/RagSourceLabel';\nimport {\n BaseMessage,\n ConversationList,\n ConversationSummary,\n LCSConversation,\n ReferencedDocument,\n ReferencedDocuments,\n ToolCall,\n} from '../types';\n\nexport const getFootnoteProps = (\n t?: (key: string, params?: any) => string,\n) => ({\n label:\n t?.('footer.accuracy.label') ||\n 'Always review AI generated content prior to use.',\n});\n\nexport const ChatbotFootnoteWithIcon = ({ label }: { label: string }) => (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '4px',\n }}\n >\n <RhUiAiInfoIcon style={{ width: '14px', height: '14px', flexShrink: 0 }} />\n <ChatbotFootnote label={label} />\n </div>\n);\n\nexport const getTimestampVariablesString = (v: number) => {\n if (v < 10) {\n return `0${v}`;\n }\n return `${v}`;\n};\n\nconst isBlankLine = (line: string) => !line.trim();\n\n/** Ordered list item at line start (CommonMark), ignoring leading spaces. */\nconst isOrderedListLine = (line: string) => /^\\s*\\d+\\.\\s/.test(line);\n\n/** ASCII bullets; also U+2022 (•) — not a CommonMark marker, but users paste it as a list. */\nconst isBulletListLine = (line: string) =>\n /^\\s*[-*+]\\s/.test(line) || /^\\s*\\u2022(?:\\s+|\\S|$)/u.test(line);\n\nconst escapeBulletListMarker = (line: string) => {\n if (/^\\s*\\u2022/u.test(line)) {\n return line;\n }\n return line.replace(/^(\\s*)([*+-])(\\s)/, '$1\\\\$2$3');\n};\n\nconst escapeOrderedListMarker = (line: string) =>\n line.replace(/^(\\s*)(\\d+)\\.(\\s)/, '$1$2\\\\.$3');\n\n/**\n * When intro lines (no blank lines among them) are followed by a contiguous run of\n * list lines, join intro + list into one Markdown paragraph using hard breaks and\n * per-line escaping so the block does not split awkwardly in the chat UI.\n */\nconst foldListWithIntro = (\n s: string,\n isListItemLine: (line: string) => boolean,\n escapeListLine: (line: string) => string,\n): string => {\n const lines = s.split('\\n');\n let firstListIdx = -1;\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (line !== undefined && isListItemLine(line)) {\n firstListIdx = i;\n break;\n }\n }\n if (firstListIdx < 0) {\n return s;\n }\n\n const intro = lines.slice(0, firstListIdx);\n if (intro.some(isBlankLine)) {\n return s;\n }\n\n const rest = lines.slice(firstListIdx);\n const restItems = rest.filter(l => !isBlankLine(l));\n if (restItems.length === 0 || !restItems.every(isListItemLine)) {\n return s;\n }\n\n const escaped = restItems.map(escapeListLine);\n if (intro.length === 0) {\n return escaped.join(' \\n');\n }\n return `${intro.join(' \\n')} \\n${escaped.join(' \\n')}`;\n};\n\n/**\n * Paragraph + ordered list (even with a single newline) parses as two blocks; merge\n * intro + contiguous numbered lines into one paragraph using hard breaks (two spaces\n * + newline) and escaped `1.` markers so Markdown stays a single block.\n */\nconst foldOrderedListWithIntro = (s: string) =>\n foldListWithIntro(s, isOrderedListLine, escapeOrderedListMarker);\n\n/** Same idea as ordered lists for intro + bullet lines. */\nconst foldBulletListWithIntro = (s: string) =>\n foldListWithIntro(s, isBulletListLine, escapeBulletListMarker);\n\n/**\n * Trims user chat input and reduces blank lines that split Markdown blocks\n * (e.g. paragraph + blank line + ordered list) so PatternFly renders one user bubble.\n */\nexport const normalizeChatUserInput = (input: string): string => {\n let s = input.replace(/\\r\\n/g, '\\n').trim();\n if (!s) {\n return s;\n }\n s = s.replace(/\\n{3,}/g, '\\n\\n');\n s = s.replace(/\\n\\n(?=\\s*\\d+\\.\\s)/gm, '\\n');\n s = s.replace(/\\n\\n(?=\\s*[-*+]\\s)/gm, '\\n');\n s = s.replace(/\\n\\n(?=\\s*\\u2022)/gm, '\\n');\n s = foldOrderedListWithIntro(s);\n s = foldBulletListWithIntro(s);\n return s.trim();\n};\n\nexport const getTimestamp = (unix_timestamp: number) => {\n if (typeof unix_timestamp !== 'number' || Number.isNaN(unix_timestamp)) {\n // eslint-disable-next-line no-console\n console.error('Invalid Unix timestamp provided');\n return '';\n }\n\n const a = new Date(unix_timestamp);\n const month = getTimestampVariablesString(a.getMonth() + 1);\n const year = a.getFullYear();\n const date = getTimestampVariablesString(a.getDate());\n const hour = getTimestampVariablesString(a.getHours());\n const min = getTimestampVariablesString(a.getMinutes());\n const sec = getTimestampVariablesString(a.getSeconds());\n const time = `${date}/${month}/${year}, ${hour}:${min}:${sec}`;\n return time;\n};\n\nexport const splitJsonStrings = (jsonString: string): string[] => {\n const chunks = jsonString.split('}{');\n\n if (chunks.length <= 1) {\n return [jsonString];\n }\n\n return chunks.map((chunk, index, arr) => {\n if (index === 0) {\n return `${chunk}}`;\n } else if (index === arr.length - 1) {\n return `{${chunk}`;\n }\n return `{${chunk}}`;\n });\n};\n\ntype MessageProps = {\n content: string;\n timestamp: string;\n name?: string;\n avatar?: string | any;\n isLoading?: boolean;\n error?: {\n title: string;\n };\n sources?: SourcesCardProps;\n toolCalls?: ToolCall[];\n};\n\nexport const createMessage = ({\n role,\n name,\n avatar,\n isLoading = false,\n content,\n timestamp,\n error,\n sources,\n toolCalls,\n defaultUserName = 'Guest',\n}: MessageProps & { role: 'user' | 'bot'; defaultUserName?: string }) => ({\n role,\n name: name || defaultUserName,\n avatar,\n isLoading,\n content,\n timestamp,\n error,\n sources,\n toolCalls,\n});\n\nexport const createUserMessage = (\n props: MessageProps & { defaultUserName?: string },\n) =>\n createMessage({\n ...props,\n role: 'user',\n defaultUserName: props.defaultUserName,\n });\n\nexport const createBotMessage = (props: MessageProps) =>\n createMessage({\n ...props,\n role: 'bot',\n });\n\nexport const getConversationsData = (\n conversation: LCSConversation,\n): [BaseMessage, BaseMessage] => {\n const [userMessage, botMessage] = conversation.messages || [];\n return [\n {\n ...userMessage,\n timestamp: getTimestamp(\n conversation.started_at\n ? new Date(conversation.started_at).getTime()\n : Date.now(),\n ),\n },\n {\n ...botMessage,\n timestamp: getTimestamp(\n conversation.completed_at\n ? new Date(conversation.completed_at).getTime()\n : Date.now(),\n ),\n referenced_documents: botMessage?.referenced_documents ?? [],\n },\n ];\n};\n\nexport type SourceWithRagId = SourcesCardProps['sources'][number] & {\n /** Full LCORE RAG source id for chip-modal labels. */\n ragSource?: string;\n};\n\nexport const transformDocumentsToSources = (\n referenced_documents: ReferencedDocuments,\n): SourcesCardProps | undefined => {\n if (!referenced_documents || referenced_documents?.length === 0) {\n return undefined;\n }\n return {\n sources: referenced_documents.map(\n (doc: ReferencedDocument): SourceWithRagId => ({\n body: doc.doc_description,\n title: doc.doc_title,\n link: doc?.doc_url,\n isExternal: !!doc?.doc_url,\n ...(doc.source\n ? {\n headerContent: <RagSourceLabel source={doc.source} />,\n ragSource: doc.source,\n }\n : {}),\n }),\n ),\n };\n};\n\nexport type SortOption =\n 'newest' | 'oldest' | 'alphabeticalAsc' | 'alphabeticalDesc';\n\nconst sortConversations = (\n messages: ConversationList,\n sortOption: SortOption,\n): ConversationList => {\n return [...messages].sort((a, b) => {\n const aTopicSummary = a.topic_summary || '';\n const bTopicSummary = b.topic_summary || '';\n switch (sortOption) {\n case 'oldest':\n return a.last_message_timestamp - b.last_message_timestamp;\n case 'alphabeticalAsc':\n return aTopicSummary.localeCompare(bTopicSummary, undefined, {\n sensitivity: 'base',\n });\n case 'alphabeticalDesc':\n return bTopicSummary.localeCompare(aTopicSummary, undefined, {\n sensitivity: 'base',\n });\n case 'newest':\n default:\n return b.last_message_timestamp - a.last_message_timestamp;\n }\n });\n};\n\nexport const getCategorizeMessages = (\n messages: ConversationList,\n pinnedChats: string[],\n addProps: (c: ConversationSummary) => { [k: string]: any },\n t?: (key: string, params?: any) => string,\n sortOption: SortOption = 'newest',\n): { [k: string]: Conversation[] } => {\n const pinnedChatsKey =\n t?.('conversation.category.pinnedChats') || 'Pinned chats';\n const recentKey = t?.('conversation.category.recent') || 'Chats';\n const categorizedMessages: { [k: string]: Conversation[] } = {\n [pinnedChatsKey]: [],\n [recentKey]: [],\n };\n const sortedMessages = sortConversations(messages, sortOption);\n sortedMessages.forEach(c => {\n const message: Conversation = {\n id: c.conversation_id,\n text: c.topic_summary ?? '',\n icon: c.topic_summary ? undefined : <Spinner size=\"sm\" />,\n label: t?.('message.options.label') || 'Options',\n additionalProps: {\n 'aria-label': t?.('aria.options.label') || 'Options',\n },\n ...addProps(c),\n };\n\n if (pinnedChats.includes(c.conversation_id)) {\n categorizedMessages[pinnedChatsKey].push({\n ...message,\n icon: (\n <ThumbtackIcon\n style={{\n width: '1rem',\n height: '1rem',\n display: 'flex',\n alignItems: 'center',\n }}\n />\n ),\n });\n } else {\n categorizedMessages[recentKey].push(message);\n }\n });\n\n const filteredCategories = Object.keys(categorizedMessages).reduce(\n (result, category) => {\n result[category] = categorizedMessages[category];\n return result;\n },\n {} as any,\n );\n\n return filteredCategories;\n};\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@red-hat-developer-hub/backstage-plugin-intelligent-assistant",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.1",
|
|
4
4
|
"main": "./dist/index.esm.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -108,12 +108,12 @@
|
|
|
108
108
|
"@mui/icons-material": "^6.1.8",
|
|
109
109
|
"@mui/material": "^5.12.2",
|
|
110
110
|
"@mui/styles": "5.18.0",
|
|
111
|
-
"@patternfly/chatbot": "6.
|
|
111
|
+
"@patternfly/chatbot": "6.9.0-prerelease.2",
|
|
112
112
|
"@patternfly/react-core": "6.6.0",
|
|
113
113
|
"@patternfly/react-icons": "^6.5.0",
|
|
114
114
|
"@patternfly/react-table": "^6.4.1",
|
|
115
115
|
"@red-hat-developer-hub/backstage-plugin-app-react": "^1.0.0",
|
|
116
|
-
"@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common": "^5.0.
|
|
116
|
+
"@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common": "^5.0.1",
|
|
117
117
|
"@red-hat-developer-hub/backstage-plugin-theme": "^0.14.10",
|
|
118
118
|
"@tanstack/react-query": "^5.59.15",
|
|
119
119
|
"html2canvas-pro": "^1.5.0",
|