@red-hat-developer-hub/backstage-plugin-intelligent-assistant 3.0.0

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.
Files changed (238) hide show
  1. package/CHANGELOG.md +681 -0
  2. package/README.md +378 -0
  3. package/config.d.ts +70 -0
  4. package/dist/alpha.d.ts +285 -0
  5. package/dist/alpha.esm.js +3 -0
  6. package/dist/alpha.esm.js.map +1 -0
  7. package/dist/api/LightspeedApiClient.esm.js +234 -0
  8. package/dist/api/LightspeedApiClient.esm.js.map +1 -0
  9. package/dist/api/NotebooksApiClient.esm.js +179 -0
  10. package/dist/api/NotebooksApiClient.esm.js.map +1 -0
  11. package/dist/api/api.esm.js +8 -0
  12. package/dist/api/api.esm.js.map +1 -0
  13. package/dist/api/notebooksApi.esm.js +10 -0
  14. package/dist/api/notebooksApi.esm.js.map +1 -0
  15. package/dist/components/Attachment.esm.js +108 -0
  16. package/dist/components/Attachment.esm.js.map +1 -0
  17. package/dist/components/AttachmentContext.esm.js +125 -0
  18. package/dist/components/AttachmentContext.esm.js.map +1 -0
  19. package/dist/components/CollapsedHistoryStrip.esm.js +87 -0
  20. package/dist/components/CollapsedHistoryStrip.esm.js.map +1 -0
  21. package/dist/components/DeleteModal.esm.js +92 -0
  22. package/dist/components/DeleteModal.esm.js.map +1 -0
  23. package/dist/components/FilePreview.esm.js +49 -0
  24. package/dist/components/FilePreview.esm.js.map +1 -0
  25. package/dist/components/LightSpeedChat.esm.js +1898 -0
  26. package/dist/components/LightSpeedChat.esm.js.map +1 -0
  27. package/dist/components/LightspeedChatBox.esm.js +252 -0
  28. package/dist/components/LightspeedChatBox.esm.js.map +1 -0
  29. package/dist/components/LightspeedChatBoxHeader.esm.js +210 -0
  30. package/dist/components/LightspeedChatBoxHeader.esm.js.map +1 -0
  31. package/dist/components/LightspeedChatContainer.esm.js +162 -0
  32. package/dist/components/LightspeedChatContainer.esm.js.map +1 -0
  33. package/dist/components/LightspeedChatModelsState.esm.js +198 -0
  34. package/dist/components/LightspeedChatModelsState.esm.js.map +1 -0
  35. package/dist/components/LightspeedDrawerContext.esm.js +15 -0
  36. package/dist/components/LightspeedDrawerContext.esm.js.map +1 -0
  37. package/dist/components/LightspeedDrawerProvider.esm.js +44 -0
  38. package/dist/components/LightspeedDrawerProvider.esm.js.map +1 -0
  39. package/dist/components/LightspeedDrawerStateExposer.esm.js +34 -0
  40. package/dist/components/LightspeedDrawerStateExposer.esm.js.map +1 -0
  41. package/dist/components/LightspeedFAB.esm.js +6 -0
  42. package/dist/components/LightspeedFAB.esm.js.map +1 -0
  43. package/dist/components/LightspeedFABContent.esm.js +65 -0
  44. package/dist/components/LightspeedFABContent.esm.js.map +1 -0
  45. package/dist/components/LightspeedIcon.esm.js +46 -0
  46. package/dist/components/LightspeedIcon.esm.js.map +1 -0
  47. package/dist/components/LightspeedPage.esm.js +31 -0
  48. package/dist/components/LightspeedPage.esm.js.map +1 -0
  49. package/dist/components/McpServersSettings.esm.js +953 -0
  50. package/dist/components/McpServersSettings.esm.js.map +1 -0
  51. package/dist/components/McpSettingsIcon.esm.js +18 -0
  52. package/dist/components/McpSettingsIcon.esm.js.map +1 -0
  53. package/dist/components/MessageBarModelSelector.esm.js +92 -0
  54. package/dist/components/MessageBarModelSelector.esm.js.map +1 -0
  55. package/dist/components/PermissionRequiredIcon.esm.js +18 -0
  56. package/dist/components/PermissionRequiredIcon.esm.js.map +1 -0
  57. package/dist/components/PermissionRequiredState.esm.js +88 -0
  58. package/dist/components/PermissionRequiredState.esm.js.map +1 -0
  59. package/dist/components/RenameConversationModal.esm.js +157 -0
  60. package/dist/components/RenameConversationModal.esm.js.map +1 -0
  61. package/dist/components/Router.esm.js +35 -0
  62. package/dist/components/Router.esm.js.map +1 -0
  63. package/dist/components/SourcesChipModal.esm.js +124 -0
  64. package/dist/components/SourcesChipModal.esm.js.map +1 -0
  65. package/dist/components/ToolCallContent.esm.js +208 -0
  66. package/dist/components/ToolCallContent.esm.js.map +1 -0
  67. package/dist/components/Trans.esm.js +33 -0
  68. package/dist/components/Trans.esm.js.map +1 -0
  69. package/dist/components/notebooks/AddDocumentModal.esm.js +271 -0
  70. package/dist/components/notebooks/AddDocumentModal.esm.js.map +1 -0
  71. package/dist/components/notebooks/DeleteDocumentModal.esm.js +131 -0
  72. package/dist/components/notebooks/DeleteDocumentModal.esm.js.map +1 -0
  73. package/dist/components/notebooks/DeleteNotebookModal.esm.js +143 -0
  74. package/dist/components/notebooks/DeleteNotebookModal.esm.js.map +1 -0
  75. package/dist/components/notebooks/DocumentSidebar.esm.js +235 -0
  76. package/dist/components/notebooks/DocumentSidebar.esm.js.map +1 -0
  77. package/dist/components/notebooks/FileListItem.esm.js +94 -0
  78. package/dist/components/notebooks/FileListItem.esm.js.map +1 -0
  79. package/dist/components/notebooks/FileTypeIcon.esm.js +59 -0
  80. package/dist/components/notebooks/FileTypeIcon.esm.js.map +1 -0
  81. package/dist/components/notebooks/NotebookCard.esm.js +118 -0
  82. package/dist/components/notebooks/NotebookCard.esm.js.map +1 -0
  83. package/dist/components/notebooks/NotebookView.esm.js +681 -0
  84. package/dist/components/notebooks/NotebookView.esm.js.map +1 -0
  85. package/dist/components/notebooks/NotebooksTab.esm.js +71 -0
  86. package/dist/components/notebooks/NotebooksTab.esm.js.map +1 -0
  87. package/dist/components/notebooks/OverwriteConfirmModal.esm.js +142 -0
  88. package/dist/components/notebooks/OverwriteConfirmModal.esm.js.map +1 -0
  89. package/dist/components/notebooks/RenameNotebookModal.esm.js +187 -0
  90. package/dist/components/notebooks/RenameNotebookModal.esm.js.map +1 -0
  91. package/dist/components/notebooks/SidebarCollapseIcon.esm.js +50 -0
  92. package/dist/components/notebooks/SidebarCollapseIcon.esm.js.map +1 -0
  93. package/dist/components/notebooks/UploadResourceScreen.esm.js +79 -0
  94. package/dist/components/notebooks/UploadResourceScreen.esm.js.map +1 -0
  95. package/dist/const.esm.js +74 -0
  96. package/dist/const.esm.js.map +1 -0
  97. package/dist/dev.d.ts +2 -0
  98. package/dist/dev.esm.js +48 -0
  99. package/dist/dev.esm.js.map +1 -0
  100. package/dist/hooks/notebooks/useCreateNotebook.esm.js +19 -0
  101. package/dist/hooks/notebooks/useCreateNotebook.esm.js.map +1 -0
  102. package/dist/hooks/notebooks/useCreateNotebookMessage.esm.js +24 -0
  103. package/dist/hooks/notebooks/useCreateNotebookMessage.esm.js.map +1 -0
  104. package/dist/hooks/notebooks/useDeleteNotebook.esm.js +19 -0
  105. package/dist/hooks/notebooks/useDeleteNotebook.esm.js.map +1 -0
  106. package/dist/hooks/notebooks/useDocumentStatusPolling.esm.js +40 -0
  107. package/dist/hooks/notebooks/useDocumentStatusPolling.esm.js.map +1 -0
  108. package/dist/hooks/notebooks/useLightspeedNotebooksPermission.esm.js +15 -0
  109. package/dist/hooks/notebooks/useLightspeedNotebooksPermission.esm.js.map +1 -0
  110. package/dist/hooks/notebooks/useNotebookDocuments.esm.js +18 -0
  111. package/dist/hooks/notebooks/useNotebookDocuments.esm.js.map +1 -0
  112. package/dist/hooks/notebooks/useNotebookSession.esm.js +18 -0
  113. package/dist/hooks/notebooks/useNotebookSession.esm.js.map +1 -0
  114. package/dist/hooks/notebooks/useNotebookSessions.esm.js +18 -0
  115. package/dist/hooks/notebooks/useNotebookSessions.esm.js.map +1 -0
  116. package/dist/hooks/notebooks/useRenameNotebook.esm.js +19 -0
  117. package/dist/hooks/notebooks/useRenameNotebook.esm.js.map +1 -0
  118. package/dist/hooks/notebooks/useUploadDocument.esm.js +28 -0
  119. package/dist/hooks/notebooks/useUploadDocument.esm.js.map +1 -0
  120. package/dist/hooks/toolCallsCacheStore.esm.js +61 -0
  121. package/dist/hooks/toolCallsCacheStore.esm.js.map +1 -0
  122. package/dist/hooks/useAllModels.esm.js +20 -0
  123. package/dist/hooks/useAllModels.esm.js.map +1 -0
  124. package/dist/hooks/useAutoScroll.esm.js +78 -0
  125. package/dist/hooks/useAutoScroll.esm.js.map +1 -0
  126. package/dist/hooks/useBackstageUserIdentity.esm.js +14 -0
  127. package/dist/hooks/useBackstageUserIdentity.esm.js.map +1 -0
  128. package/dist/hooks/useBufferedMessages.esm.js +27 -0
  129. package/dist/hooks/useBufferedMessages.esm.js.map +1 -0
  130. package/dist/hooks/useCaptureFeedback.esm.js +21 -0
  131. package/dist/hooks/useCaptureFeedback.esm.js.map +1 -0
  132. package/dist/hooks/useConversationMessages.esm.js +544 -0
  133. package/dist/hooks/useConversationMessages.esm.js.map +1 -0
  134. package/dist/hooks/useConversations.esm.js +25 -0
  135. package/dist/hooks/useConversations.esm.js.map +1 -0
  136. package/dist/hooks/useCreateCoversationMessage.esm.js +33 -0
  137. package/dist/hooks/useCreateCoversationMessage.esm.js.map +1 -0
  138. package/dist/hooks/useDeleteConversation.esm.js +39 -0
  139. package/dist/hooks/useDeleteConversation.esm.js.map +1 -0
  140. package/dist/hooks/useDisplayModeSettings.esm.js +57 -0
  141. package/dist/hooks/useDisplayModeSettings.esm.js.map +1 -0
  142. package/dist/hooks/useFeedbackActions.esm.js +275 -0
  143. package/dist/hooks/useFeedbackActions.esm.js.map +1 -0
  144. package/dist/hooks/useFeedbackState.esm.js +93 -0
  145. package/dist/hooks/useFeedbackState.esm.js.map +1 -0
  146. package/dist/hooks/useFeedbackStatus.esm.js +14 -0
  147. package/dist/hooks/useFeedbackStatus.esm.js.map +1 -0
  148. package/dist/hooks/useIsMobile.esm.js +14 -0
  149. package/dist/hooks/useIsMobile.esm.js.map +1 -0
  150. package/dist/hooks/useLastOpenedConversation.esm.js +51 -0
  151. package/dist/hooks/useLastOpenedConversation.esm.js.map +1 -0
  152. package/dist/hooks/useLightspeedDeletePermission.esm.js +12 -0
  153. package/dist/hooks/useLightspeedDeletePermission.esm.js.map +1 -0
  154. package/dist/hooks/useLightspeedDrawerContext.esm.js +15 -0
  155. package/dist/hooks/useLightspeedDrawerContext.esm.js.map +1 -0
  156. package/dist/hooks/useLightspeedProviderState.esm.js +277 -0
  157. package/dist/hooks/useLightspeedProviderState.esm.js.map +1 -0
  158. package/dist/hooks/useLightspeedUpdatePermission.esm.js +12 -0
  159. package/dist/hooks/useLightspeedUpdatePermission.esm.js.map +1 -0
  160. package/dist/hooks/useLightspeedViewPermission.esm.js +18 -0
  161. package/dist/hooks/useLightspeedViewPermission.esm.js.map +1 -0
  162. package/dist/hooks/useNotebookConversationIds.esm.js +19 -0
  163. package/dist/hooks/useNotebookConversationIds.esm.js.map +1 -0
  164. package/dist/hooks/useNotebookWelcomePrompts.esm.js +14 -0
  165. package/dist/hooks/useNotebookWelcomePrompts.esm.js.map +1 -0
  166. package/dist/hooks/usePinnedChatsSettings.esm.js +118 -0
  167. package/dist/hooks/usePinnedChatsSettings.esm.js.map +1 -0
  168. package/dist/hooks/useQuestionValidation.esm.js +16 -0
  169. package/dist/hooks/useQuestionValidation.esm.js.map +1 -0
  170. package/dist/hooks/useRenameConversation.esm.js +44 -0
  171. package/dist/hooks/useRenameConversation.esm.js.map +1 -0
  172. package/dist/hooks/useSortSettings.esm.js +60 -0
  173. package/dist/hooks/useSortSettings.esm.js.map +1 -0
  174. package/dist/hooks/useStopConversation.esm.js +18 -0
  175. package/dist/hooks/useStopConversation.esm.js.map +1 -0
  176. package/dist/hooks/useTranslation.esm.js +7 -0
  177. package/dist/hooks/useTranslation.esm.js.map +1 -0
  178. package/dist/hooks/useWelcomePrompts.esm.js +36 -0
  179. package/dist/hooks/useWelcomePrompts.esm.js.map +1 -0
  180. package/dist/images/bot-avatar-dark.svg +4 -0
  181. package/dist/images/bot-avatar.svg +4 -0
  182. package/dist/images/permission-required.svg +319 -0
  183. package/dist/images/user-avatar.svg +4 -0
  184. package/dist/index.d.ts +113 -0
  185. package/dist/index.esm.js +137 -0
  186. package/dist/index.esm.js.map +1 -0
  187. package/dist/intelligent-assistant-fab-module.d.ts +4 -0
  188. package/dist/intelligent-assistant-fab-module.esm.js +2 -0
  189. package/dist/intelligent-assistant-fab-module.esm.js.map +1 -0
  190. package/dist/intelligent-assistant-translations-module.d.ts +4 -0
  191. package/dist/intelligent-assistant-translations-module.esm.js +2 -0
  192. package/dist/intelligent-assistant-translations-module.esm.js.map +1 -0
  193. package/dist/legacy.d.ts +75 -0
  194. package/dist/legacy.esm.js +13 -0
  195. package/dist/legacy.esm.js.map +1 -0
  196. package/dist/plugin.esm.js +84 -0
  197. package/dist/plugin.esm.js.map +1 -0
  198. package/dist/routes.esm.js +23 -0
  199. package/dist/routes.esm.js.map +1 -0
  200. package/dist/translations/de.esm.js +278 -0
  201. package/dist/translations/de.esm.js.map +1 -0
  202. package/dist/translations/es.esm.js +278 -0
  203. package/dist/translations/es.esm.js.map +1 -0
  204. package/dist/translations/fr.esm.js +278 -0
  205. package/dist/translations/fr.esm.js.map +1 -0
  206. package/dist/translations/index.esm.js +16 -0
  207. package/dist/translations/index.esm.js.map +1 -0
  208. package/dist/translations/it.esm.js +278 -0
  209. package/dist/translations/it.esm.js.map +1 -0
  210. package/dist/translations/ja.esm.js +278 -0
  211. package/dist/translations/ja.esm.js.map +1 -0
  212. package/dist/translations/ref.esm.js +315 -0
  213. package/dist/translations/ref.esm.js.map +1 -0
  214. package/dist/types.esm.js +9 -0
  215. package/dist/types.esm.js.map +1 -0
  216. package/dist/utils/attachment-utils.esm.js +30 -0
  217. package/dist/utils/attachment-utils.esm.js.map +1 -0
  218. package/dist/utils/formatToolResponseForMarkdown.esm.js +98 -0
  219. package/dist/utils/formatToolResponseForMarkdown.esm.js.map +1 -0
  220. package/dist/utils/generateClassName.esm.js +12 -0
  221. package/dist/utils/generateClassName.esm.js.map +1 -0
  222. package/dist/utils/lightspeed-chatbox-utils.esm.js +232 -0
  223. package/dist/utils/lightspeed-chatbox-utils.esm.js.map +1 -0
  224. package/dist/utils/notebook-upload-utils.esm.js +48 -0
  225. package/dist/utils/notebook-upload-utils.esm.js.map +1 -0
  226. package/dist/utils/notebooks-utils.esm.js +25 -0
  227. package/dist/utils/notebooks-utils.esm.js.map +1 -0
  228. package/dist/utils/prompt-utils.esm.js +17 -0
  229. package/dist/utils/prompt-utils.esm.js.map +1 -0
  230. package/dist/utils/queryClient.esm.js +6 -0
  231. package/dist/utils/queryClient.esm.js.map +1 -0
  232. package/dist/utils/reasoningParser.esm.js +33 -0
  233. package/dist/utils/reasoningParser.esm.js.map +1 -0
  234. package/dist/utils/toolCallMapper.esm.js +15 -0
  235. package/dist/utils/toolCallMapper.esm.js.map +1 -0
  236. package/dist/utils/user-utils.esm.js +7 -0
  237. package/dist/utils/user-utils.esm.js.map +1 -0
  238. package/package.json +182 -0
@@ -0,0 +1,1898 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import { useState, useEffect, useRef, useLayoutEffect, useCallback, useMemo } from 'react';
3
+ import { useNavigate, useMatch, useLocation } from 'react-router-dom';
4
+ import { useApi, configApiRef } from '@backstage/core-plugin-api';
5
+ import { makeStyles, Button } from '@material-ui/core';
6
+ import Tab from '@mui/material/Tab';
7
+ import Tabs from '@mui/material/Tabs';
8
+ import { ChatbotDisplayMode, ChatbotContent, ChatbotFooter, MessageBar, Settings, Chatbot, ChatbotHeader, ChatbotHeaderMain, ChatbotHeaderMenu, ChatbotHeaderTitle, FileDropZone, ChatbotAlert } from '@patternfly/chatbot';
9
+ import ChatbotConversationHistoryNav from '@patternfly/chatbot/dist/dynamic/ChatbotConversationHistoryNav';
10
+ import { DropdownItem, Tooltip, MenuToggle, Select, SelectList, SelectOption, AlertGroup, Alert, AlertVariant, AlertActionCloseButton, Title, Label } from '@patternfly/react-core';
11
+ import { PenIcon, ThumbtackIcon, TrashIcon, SortAmountDownAltIcon, SortAmountDownIcon, PlusIcon, SearchIcon } from '@patternfly/react-icons';
12
+ import { RhUiAiExperienceIcon } from '@patternfly/react-icons/dist/esm/icons/rh-ui-ai-experience-icon';
13
+ import { useQueryClient } from '@tanstack/react-query';
14
+ import { LIGHTSPEED_PATH, UNTITLED_NOTEBOOK_NAME, TEMP_CONVERSATION_ID, supportedFileTypes } from '../const.esm.js';
15
+ import '../api/api.esm.js';
16
+ import { useBackstageUserIdentity } from '../hooks/useBackstageUserIdentity.esm.js';
17
+ import { useConversationMessages } from '../hooks/useConversationMessages.esm.js';
18
+ import { useConversations } from '../hooks/useConversations.esm.js';
19
+ import '../api/notebooksApi.esm.js';
20
+ import { useIsMobile } from '../hooks/useIsMobile.esm.js';
21
+ import { useLastOpenedConversation } from '../hooks/useLastOpenedConversation.esm.js';
22
+ import { useLightspeedDeletePermission } from '../hooks/useLightspeedDeletePermission.esm.js';
23
+ import { useLightspeedNotebooksPermission } from '../hooks/notebooks/useLightspeedNotebooksPermission.esm.js';
24
+ import '@backstage/plugin-permission-react';
25
+ import '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common';
26
+ import { useNotebookConversationIds } from '../hooks/useNotebookConversationIds.esm.js';
27
+ import { useNotebookSession } from '../hooks/notebooks/useNotebookSession.esm.js';
28
+ import { useNotebookSessions } from '../hooks/notebooks/useNotebookSessions.esm.js';
29
+ import { usePinnedChatsSettings } from '../hooks/usePinnedChatsSettings.esm.js';
30
+ import { useSortSettings } from '../hooks/useSortSettings.esm.js';
31
+ import { useStopConversation } from '../hooks/useStopConversation.esm.js';
32
+ import { useTranslation } from '../hooks/useTranslation.esm.js';
33
+ import { useCreateNotebook } from '../hooks/notebooks/useCreateNotebook.esm.js';
34
+ import { useNotebookDocuments } from '../hooks/notebooks/useNotebookDocuments.esm.js';
35
+ import { useLightspeedDrawerContext } from '../hooks/useLightspeedDrawerContext.esm.js';
36
+ import { useLightspeedUpdatePermission } from '../hooks/useLightspeedUpdatePermission.esm.js';
37
+ import { useWelcomePrompts } from '../hooks/useWelcomePrompts.esm.js';
38
+ import { getAttachments } from '../utils/attachment-utils.esm.js';
39
+ import { getCategorizeMessages, ChatbotFootnoteWithIcon, getFootnoteProps } from '../utils/lightspeed-chatbox-utils.esm.js';
40
+ import Attachment from './Attachment.esm.js';
41
+ import { useFileAttachmentContext } from './AttachmentContext.esm.js';
42
+ import { CollapsedHistoryStrip } from './CollapsedHistoryStrip.esm.js';
43
+ import { DeleteModal } from './DeleteModal.esm.js';
44
+ import FilePreview from './FilePreview.esm.js';
45
+ import { LightspeedChatBox } from './LightspeedChatBox.esm.js';
46
+ import { LightspeedChatBoxHeader } from './LightspeedChatBoxHeader.esm.js';
47
+ import { McpServersSettings } from './McpServersSettings.esm.js';
48
+ import { MessageBarModelSelector } from './MessageBarModelSelector.esm.js';
49
+ import { DeleteNotebookModal } from './notebooks/DeleteNotebookModal.esm.js';
50
+ import { NotebooksTab } from './notebooks/NotebooksTab.esm.js';
51
+ import { NotebookView } from './notebooks/NotebookView.esm.js';
52
+ import { RenameNotebookModal } from './notebooks/RenameNotebookModal.esm.js';
53
+ import PermissionRequiredState from './PermissionRequiredState.esm.js';
54
+ import { RenameConversationModal } from './RenameConversationModal.esm.js';
55
+
56
+ const COLLAPSE_PANEL_ICON_SVG = `url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M16 21V3H14V21H16ZM12 17V7L7 12L12 17Z' fill='black'/%3E%3C/svg%3E") no-repeat center`;
57
+ const ConditionalWrapper = ({
58
+ condition,
59
+ wrapper,
60
+ children
61
+ }) => condition ? wrapper(children) : children;
62
+ const useStyles = makeStyles((theme) => ({
63
+ body: {
64
+ // remove default margin and padding from common elements
65
+ // lists excluded for proper formatting
66
+ "& h1, & h2, & h3, & h4, & h5, & h6, & p, & li": {
67
+ margin: 0,
68
+ padding: 0
69
+ },
70
+ "& .pf-chatbot__content": {
71
+ backgroundColor: "var(--pf-t--global--background--color--floating--default) !important"
72
+ },
73
+ "& .pf-v6-svg > .pf-v6-icon-rh-ui": {
74
+ display: "none !important",
75
+ width: 0,
76
+ height: 0,
77
+ overflow: "hidden"
78
+ }
79
+ },
80
+ header: {
81
+ padding: `${theme.spacing(3)}px ${theme.spacing(3)}px 0 ${theme.spacing(
82
+ 3
83
+ )}px !important`,
84
+ backgroundColor: "var(--pf-t--global--background--color--floating--default) !important"
85
+ },
86
+ errorContainer: {
87
+ padding: theme.spacing(3)
88
+ },
89
+ drawerFileDropZone: {
90
+ gap: 0,
91
+ rowGap: 0,
92
+ columnGap: 0,
93
+ "--pf-v6-c-multiple-file-upload--Gap": "0",
94
+ "--pf-v5-c-multiple-file-upload--Gap": "0",
95
+ flex: 1,
96
+ minWidth: 0,
97
+ backgroundColor: "var(--pf-t--global--background--color--floating--default) !important"
98
+ },
99
+ headerMenu: {
100
+ // align hamburger icon with title
101
+ "& .pf-v6-c-button": {
102
+ display: "flex",
103
+ alignItems: "center"
104
+ }
105
+ },
106
+ headerLogo: {
107
+ width: 48,
108
+ height: 48,
109
+ marginRight: theme.spacing(1.5),
110
+ flexShrink: 0
111
+ },
112
+ headerTitle: {
113
+ justifyContent: "left !important"
114
+ },
115
+ headerDivider: {
116
+ paddingTop: 8,
117
+ borderBottom: "1px solid var(--pf-t--global--border--color--default)",
118
+ backgroundColor: "var(--pf-t--global--background--color--floating--default)"
119
+ },
120
+ notebooksContainer: {
121
+ padding: theme.spacing(3),
122
+ height: "100%",
123
+ display: "flex",
124
+ flexDirection: "column",
125
+ flex: 1,
126
+ minHeight: 0,
127
+ overflowY: "auto",
128
+ backgroundColor: "var(--pf-t--global--background--color--floating--default)"
129
+ },
130
+ notebooksHeader: {
131
+ display: "flex",
132
+ alignItems: "center",
133
+ justifyContent: "space-between",
134
+ marginBottom: theme.spacing(4)
135
+ },
136
+ notebooksHeading: {
137
+ marginBottom: 0
138
+ },
139
+ notebooksHeadingEmpty: {
140
+ "&&": {
141
+ marginBottom: theme.spacing(1),
142
+ paddingBottom: theme.spacing(1)
143
+ }
144
+ },
145
+ notebooksEmptyState: {
146
+ flex: 1,
147
+ display: "flex",
148
+ flexDirection: "column",
149
+ alignItems: "center",
150
+ justifyContent: "center",
151
+ textAlign: "center"
152
+ },
153
+ notebooksIcon: {
154
+ fontSize: 48,
155
+ color: "var(--pf-t--global--icon--color--subtle)",
156
+ marginBottom: theme.spacing(1.5),
157
+ "& > .pf-v6-icon-rh-ui": {
158
+ display: "none !important"
159
+ }
160
+ },
161
+ notebooksDescription: {
162
+ marginTop: theme.spacing(1),
163
+ marginBottom: theme.spacing(3),
164
+ maxWidth: 420
165
+ },
166
+ notebooksAction: {
167
+ textTransform: "none",
168
+ borderRadius: 999,
169
+ paddingLeft: theme.spacing(3),
170
+ paddingRight: theme.spacing(3)
171
+ },
172
+ notebooksActionEmpty: {
173
+ textTransform: "none",
174
+ borderRadius: 999,
175
+ paddingLeft: theme.spacing(3),
176
+ paddingRight: theme.spacing(3),
177
+ marginTop: theme.spacing(3)
178
+ },
179
+ notebooksGrid: {
180
+ display: "grid",
181
+ gridTemplateColumns: "repeat(3, minmax(0, 1fr))",
182
+ gap: theme.spacing(2),
183
+ width: "100%",
184
+ maxWidth: "100%",
185
+ paddingBottom: theme.spacing(3),
186
+ [theme.breakpoints.down("md")]: {
187
+ gridTemplateColumns: "repeat(2, minmax(0, 1fr))"
188
+ },
189
+ [theme.breakpoints.down("sm")]: {
190
+ gridTemplateColumns: "repeat(1, minmax(0, 1fr))"
191
+ }
192
+ },
193
+ notebookCard: {
194
+ borderRadius: theme.spacing(1.5),
195
+ display: "flex",
196
+ flexDirection: "column",
197
+ "&:hover": {
198
+ borderColor: "var(--pf-t--global--border--color--hover)",
199
+ borderWidth: "1px",
200
+ borderStyle: "solid",
201
+ cursor: "pointer"
202
+ }
203
+ },
204
+ notebookCardHeader: {
205
+ padding: theme.spacing(2),
206
+ paddingBottom: 0,
207
+ alignItems: "center"
208
+ },
209
+ notebookCardDivider: {
210
+ borderTop: "1px solid var(--pf-t--global--border--color--default)",
211
+ marginTop: theme.spacing(1)
212
+ },
213
+ notebookCardBody: {
214
+ padding: theme.spacing(2),
215
+ paddingTop: theme.spacing(1.5)
216
+ },
217
+ notebookDocuments: {
218
+ paddingTop: theme.spacing(1),
219
+ paddingLeft: theme.spacing(2)
220
+ },
221
+ notebookUpdated: {
222
+ paddingBottom: theme.spacing(5),
223
+ paddingLeft: theme.spacing(2),
224
+ paddingTop: theme.spacing(2)
225
+ },
226
+ notebookTitle: {
227
+ display: "flex",
228
+ alignItems: "center",
229
+ gap: theme.spacing(1),
230
+ minWidth: 0,
231
+ flex: 1
232
+ },
233
+ notebookCardHeaderActions: {
234
+ marginLeft: theme.spacing(1)
235
+ },
236
+ notebookTitleText: {
237
+ overflow: "hidden",
238
+ textOverflow: "ellipsis",
239
+ whiteSpace: "nowrap"
240
+ },
241
+ notebookMenuButton: {
242
+ color: theme.palette.text.secondary
243
+ },
244
+ notebookDropdownList: {
245
+ paddingTop: 0,
246
+ paddingBottom: 0,
247
+ paddingInlineStart: 0
248
+ },
249
+ notebookDropdownMenu: {
250
+ "--pf-v6-c-menu--PaddingBlockStart": "0",
251
+ "--pf-v6-c-menu--PaddingBlockEnd": "0"
252
+ },
253
+ notebookDropdownItem: {
254
+ justifyContent: "flex-start",
255
+ textAlign: "left",
256
+ paddingLeft: theme.spacing(1.5),
257
+ paddingRight: theme.spacing(1.5)
258
+ },
259
+ footer: {
260
+ "&.pf-chatbot__footer": {
261
+ backgroundColor: "var(--pf-t--global--background--color--floating--default) !important"
262
+ },
263
+ "&>.pf-chatbot__footer-container": {
264
+ width: "95% !important",
265
+ maxWidth: "unset !important"
266
+ },
267
+ "& .pf-chatbot__message-bar": {
268
+ backgroundColor: theme.palette.type === "light" ? theme.palette.grey[100] : "var(--pf-t--global--background--color--secondary--default)"
269
+ },
270
+ "& .pf-chatbot__button--stop, & .pf-chatbot__button--attach, & .pf-chatbot__button--send, & .pf-chatbot__button--microphone": {
271
+ borderRadius: "var(--pf-t--global--border--radius--pill) !important"
272
+ }
273
+ },
274
+ fullscreenFooter: {
275
+ "&>.pf-chatbot__footer-container": {
276
+ width: "100% !important",
277
+ padding: `${theme.spacing(1.5)}px !important`,
278
+ maxWidth: "unset !important",
279
+ margin: "0 auto"
280
+ }
281
+ },
282
+ messageBar: {
283
+ border: "1px solid var(--pf-t--global--border--color--default)",
284
+ borderRadius: 24,
285
+ padding: theme.spacing(0.5),
286
+ "&::after": {
287
+ display: "none"
288
+ }
289
+ },
290
+ sortDropdown: {
291
+ padding: 0,
292
+ margin: 0
293
+ },
294
+ // Outer content wrapper (library may override overflow; we rely on inner scroll wrapper).
295
+ chatbotContent: {
296
+ minHeight: 0,
297
+ display: "flex",
298
+ flexDirection: "column",
299
+ flex: 1,
300
+ "& .pf-chatbot__jump": {
301
+ left: "50% !important",
302
+ right: "auto !important",
303
+ transform: "translateX(-50%)",
304
+ visibility: "hidden",
305
+ pointerEvents: "none"
306
+ },
307
+ "& .pf-chatbot__message-contents": {
308
+ overflowX: "hidden",
309
+ overflowWrap: "break-word",
310
+ wordBreak: "break-word"
311
+ }
312
+ },
313
+ chatbotContentHasOverflow: {
314
+ "& .pf-chatbot__jump": {
315
+ visibility: "visible",
316
+ pointerEvents: "auto"
317
+ }
318
+ },
319
+ // Inner scroll container we control: always scrollable so zoomed-in users see full content.
320
+ chatbotContentScroll: {
321
+ minHeight: 0,
322
+ flex: 1,
323
+ display: "flex",
324
+ flexDirection: "column",
325
+ overflowY: "auto",
326
+ WebkitOverflowScrolling: "touch"
327
+ },
328
+ chatbotContentScrollNewChat: {
329
+ backgroundColor: "var(--pf-t--global--background--color--floating--default) !important"
330
+ },
331
+ toastAlertGroup: {
332
+ "--pf-v6-c-alert-group--m-toast--InsetInlineEnd": `${theme.spacing(2.5)}px`,
333
+ "--pf-v6-c-alert-group--m-toast--InsetBlockStart": `${theme.spacing(2.5)}px`,
334
+ "--pf-v6-c-alert-group--m-toast--MaxWidth": "350px",
335
+ "--pf-v6-c-alert-group--m-toast--ZIndex": "9999"
336
+ },
337
+ toastAlert: {
338
+ maxWidth: "350px",
339
+ "& .pf-v6-c-alert__title": {
340
+ margin: 0
341
+ }
342
+ },
343
+ // When present, pushes welcome content to bottom (zoom out). Scroll up to see important box (zoom in).
344
+ chatbotContentSpacer: {
345
+ flex: 1,
346
+ minHeight: 0
347
+ },
348
+ settingsFlat: {
349
+ height: "100%",
350
+ width: "100%",
351
+ "&.pf-chatbot__settings-form-container": {
352
+ background: "var(--pf-v6-c-table--BackgroundColor, var(--pf-t--global--background--color--primary--default))",
353
+ padding: 0,
354
+ margin: 0,
355
+ minHeight: "100%",
356
+ display: "flex",
357
+ flexDirection: "column",
358
+ width: "100%",
359
+ maxWidth: "none"
360
+ },
361
+ "& .pf-chatbot__settings-form": {
362
+ margin: 0,
363
+ padding: 0,
364
+ background: "var(--pf-v6-c-table--BackgroundColor, var(--pf-t--global--background--color--primary--default))",
365
+ minHeight: "100%",
366
+ display: "flex",
367
+ flexDirection: "column",
368
+ width: "100%",
369
+ maxWidth: "none"
370
+ },
371
+ "& .pf-chatbot__settings-form-row": {
372
+ background: "var(--pf-v6-c-table--BackgroundColor, var(--pf-t--global--background--color--primary--default))",
373
+ border: 0,
374
+ margin: 0,
375
+ padding: 0,
376
+ minHeight: "100%",
377
+ display: "flex",
378
+ flexDirection: "column",
379
+ width: "100%",
380
+ maxWidth: "none"
381
+ },
382
+ "& .pf-chatbot__settings-label": {
383
+ display: "none"
384
+ }
385
+ },
386
+ mcpFullscreenLayout: {
387
+ display: "grid",
388
+ gridTemplateColumns: "minmax(0, 1fr) minmax(0, 1fr)",
389
+ minHeight: 0,
390
+ height: "100%",
391
+ flex: 1,
392
+ width: "100%",
393
+ minWidth: 0,
394
+ overflow: "hidden"
395
+ },
396
+ mcpChatPane: {
397
+ display: "flex",
398
+ flexDirection: "column",
399
+ minHeight: 0,
400
+ width: "100%",
401
+ minWidth: 0,
402
+ whiteSpace: "normal",
403
+ wordBreak: "break-word",
404
+ overflowWrap: "break-word"
405
+ },
406
+ mcpSettingsPane: {
407
+ width: "100%",
408
+ minWidth: 0,
409
+ borderLeft: `1px solid ${theme.palette.divider}`,
410
+ backgroundColor: "var(--pf-v6-c-table--BackgroundColor, var(--pf-t--global--background--color--primary--default))",
411
+ display: "flex",
412
+ flexDirection: "column",
413
+ minHeight: 0,
414
+ overflow: "auto"
415
+ },
416
+ mcpCollapsedDrawerOrderFix: {
417
+ "& .pf-v6-c-drawer.pf-m-panel-left > .pf-v6-c-drawer__main > .pf-v6-c-drawer__content, & .pf-v5-c-drawer.pf-m-panel-left > .pf-v5-c-drawer__main > .pf-v5-c-drawer__content": {
418
+ order: "unset"
419
+ },
420
+ "& .pf-v6-c-drawer:not(.pf-m-expanded) > .pf-v6-c-drawer__main > .pf-v6-c-drawer__panel, & .pf-v5-c-drawer:not(.pf-m-expanded) > .pf-v5-c-drawer__main > .pf-v5-c-drawer__panel": {
421
+ visibility: "hidden",
422
+ opacity: 0,
423
+ transition: "none !important"
424
+ }
425
+ },
426
+ // TODO: These PF Chatbot overrides are fragile (version-specific class names).
427
+ // Remove once the upstream issues are addressed:
428
+ // - https://github.com/patternfly/chatbot/issues/834 (custom close/collapse icon & positioning)
429
+ // - https://github.com/patternfly/chatbot/issues/848 (sidebar padding & spacing customization)
430
+ fullscreenChatLayout: {
431
+ display: "flex",
432
+ flexDirection: "row",
433
+ flex: 1,
434
+ minHeight: 0,
435
+ height: "100%",
436
+ width: "100%",
437
+ "& .pf-v6-c-drawer, & .pf-v5-c-drawer": {
438
+ flex: 1,
439
+ minWidth: 0
440
+ },
441
+ "& .pf-v6-c-drawer__content, & .pf-v5-c-drawer__content": {
442
+ flex: 1,
443
+ minWidth: 0
444
+ },
445
+ "& .pf-v6-c-drawer:not(.pf-m-expanded) > .pf-v6-c-drawer__main > .pf-v6-c-drawer__panel, & .pf-v5-c-drawer:not(.pf-m-expanded) > .pf-v5-c-drawer__main > .pf-v5-c-drawer__panel": {
446
+ display: "none"
447
+ },
448
+ // TODO(#834): Remove close button overrides once PF supports custom icon/positioning
449
+ "& .pf-v6-c-drawer__close, & .pf-v5-c-drawer__close": {
450
+ marginTop: 0,
451
+ marginRight: 0
452
+ },
453
+ // TODO(#848): Remove drawer head padding overrides once PF exposes drawerHeadProps
454
+ "& .pf-v6-c-drawer__head, & .pf-v5-c-drawer__head": {
455
+ paddingInlineStart: "var(--pf-t--global--spacer--lg)",
456
+ paddingInlineEnd: "var(--pf-t--global--spacer--lg)"
457
+ },
458
+ // TODO(#834): Remove icon replacement hack once PF supports drawerCloseButtonProps.icon
459
+ "& .pf-v6-c-drawer__close .pf-v6-c-button svg, & .pf-v5-c-drawer__close .pf-v5-c-button svg": {
460
+ display: "none"
461
+ },
462
+ "& .pf-v6-c-drawer__close .pf-v6-c-button, & .pf-v5-c-drawer__close .pf-v5-c-button": {
463
+ display: "flex",
464
+ alignItems: "center",
465
+ justifyContent: "center",
466
+ "&::before": {
467
+ content: '""',
468
+ display: "block",
469
+ width: 24,
470
+ height: 24,
471
+ mask: COLLAPSE_PANEL_ICON_SVG,
472
+ WebkitMask: COLLAPSE_PANEL_ICON_SVG,
473
+ backgroundColor: "currentColor"
474
+ }
475
+ },
476
+ // TODO(#848): Remove heading padding overrides once PF exposes drawerHeadProps
477
+ "& .pf-chatbot__heading-container": {
478
+ paddingInlineStart: "var(--pf-t--global--spacer--lg)",
479
+ paddingInlineEnd: "var(--pf-t--global--spacer--lg)"
480
+ },
481
+ // TODO(#848): Remove menu item padding overrides once PF exposes menuItemPaddingInline
482
+ "& .pf-chatbot__menu-item-header > .pf-v6-c-menu__group-title": {
483
+ "--pf-v6-c-menu__group-title--PaddingInlineStart": "var(--pf-t--global--spacer--md)",
484
+ "--pf-v6-c-menu__group-title--PaddingInlineEnd": "var(--pf-t--global--spacer--md)"
485
+ },
486
+ "& .pf-chatbot__menu-item": {
487
+ cursor: "pointer",
488
+ "--pf-v6-c-menu__item--PaddingInlineStart": "var(--pf-t--global--spacer--md)",
489
+ "--pf-v6-c-menu__item--PaddingInlineEnd": "var(--pf-t--global--spacer--md)"
490
+ },
491
+ // TODO(#848): Remove menu toggle hover hack once PF supports menuToggleVisibility
492
+ "& .pf-chatbot__menu-item .pf-v6-c-menu-toggle, & .pf-chatbot__menu-item .pf-v5-c-menu-toggle": {
493
+ opacity: 0,
494
+ transition: "opacity 0.15s ease-in-out"
495
+ },
496
+ "& .pf-chatbot__menu-item:hover .pf-v6-c-menu-toggle, & .pf-chatbot__menu-item:hover .pf-v5-c-menu-toggle": {
497
+ opacity: 1
498
+ }
499
+ },
500
+ fullscreenMainContent: {
501
+ display: "flex",
502
+ flexDirection: "column",
503
+ flex: 1,
504
+ minHeight: 0,
505
+ minWidth: 0,
506
+ overflow: "hidden"
507
+ }
508
+ }));
509
+ const LightspeedChat = ({
510
+ selectedModel,
511
+ topicRestrictionEnabled,
512
+ selectedProvider,
513
+ userName,
514
+ avatar,
515
+ profileLoading,
516
+ handleSelectedModel,
517
+ models
518
+ }) => {
519
+ const isMobile = useIsMobile();
520
+ const classes = useStyles();
521
+ const { t } = useTranslation();
522
+ const navigate = useNavigate();
523
+ const configApi = useApi(configApiRef);
524
+ const notebooksEnabled = configApi.getOptionalBoolean("intelligent-assistant.notebooks.enabled") ?? false;
525
+ const notebooksRouteMatch = useMatch(`${LIGHTSPEED_PATH}/notebooks`);
526
+ const notebookViewRouteMatch = useMatch(
527
+ `${LIGHTSPEED_PATH}/notebooks/:notebookId`
528
+ );
529
+ const routeNotebookId = notebookViewRouteMatch?.params?.notebookId;
530
+ const isOnNotebookRoute = Boolean(
531
+ notebooksRouteMatch || notebookViewRouteMatch
532
+ );
533
+ const shouldShowTabs = notebooksEnabled || isOnNotebookRoute;
534
+ const {
535
+ displayMode,
536
+ setDisplayMode,
537
+ currentConversationId: routeConversationId,
538
+ setCurrentConversationId,
539
+ draftMessage,
540
+ setDraftMessage,
541
+ consumePendingOverlayThreadHandoff,
542
+ shellViewTab,
543
+ setShellViewTab
544
+ } = useLightspeedDrawerContext();
545
+ const isFullscreenMode = displayMode === ChatbotDisplayMode.embedded;
546
+ const location = useLocation();
547
+ const isNotebooksFullscreenPath = location.pathname === `${LIGHTSPEED_PATH}/notebooks` || location.pathname.startsWith(`${LIGHTSPEED_PATH}/notebooks/`);
548
+ const user = useBackstageUserIdentity();
549
+ const [filterValue, setFilterValue] = useState("");
550
+ const [announcement, setAnnouncement] = useState("");
551
+ const [activeTab, setActiveTab] = useState(() => {
552
+ if (!isFullscreenMode) {
553
+ return 0;
554
+ }
555
+ if (notebooksRouteMatch || notebookViewRouteMatch) {
556
+ return 1;
557
+ }
558
+ const p = location.pathname;
559
+ if (p.startsWith(`${LIGHTSPEED_PATH}/conversation/`)) {
560
+ return 0;
561
+ }
562
+ if (shellViewTab === 1) {
563
+ return 1;
564
+ }
565
+ return 0;
566
+ });
567
+ const { allowed: hasNotebooksAccess, loading: notebooksPermissionLoading } = useLightspeedNotebooksPermission();
568
+ const notebooksPermissionResolved = !notebooksPermissionLoading && hasNotebooksAccess;
569
+ const { data: notebookConversationIdsArray = [] } = useNotebookConversationIds();
570
+ const { data: notebooks = [], refetch: refetchNotebooks } = useNotebookSessions(notebooksPermissionResolved);
571
+ const hasNotebooks = notebooks.length > 0;
572
+ const [openNotebookMenuId, setOpenNotebookMenuId] = useState(
573
+ null
574
+ );
575
+ const [renameNotebookId, setRenameNotebookId] = useState(null);
576
+ const [deleteNotebookId, setDeleteNotebookId] = useState(null);
577
+ const [activeNotebook, setActiveNotebook] = useState(
578
+ null
579
+ );
580
+ const {
581
+ data: routeNotebook,
582
+ isLoading: routeNotebookLoading,
583
+ isError: routeNotebookError
584
+ } = useNotebookSession(routeNotebookId);
585
+ useEffect(() => {
586
+ if (routeNotebookId && routeNotebook && !routeNotebookLoading) {
587
+ setActiveNotebook(routeNotebook);
588
+ } else if (routeNotebookId && routeNotebookError) {
589
+ navigate(`${LIGHTSPEED_PATH}/notebooks`, { replace: true });
590
+ } else if (!routeNotebookId && notebooksRouteMatch) {
591
+ setActiveNotebook(null);
592
+ }
593
+ }, [
594
+ routeNotebookId,
595
+ routeNotebook,
596
+ routeNotebookLoading,
597
+ routeNotebookError,
598
+ notebooksRouteMatch,
599
+ navigate
600
+ ]);
601
+ const [notebookAlerts, setNotebookAlerts] = useState(
602
+ []
603
+ );
604
+ const createNotebookMutation = useCreateNotebook();
605
+ const { data: notebookDocuments = [], isFetching: isDocumentsFetching } = useNotebookDocuments(activeNotebook?.session_id);
606
+ const [conversationId, setConversationId] = useState("");
607
+ const [requestId, setRequestId] = useState("");
608
+ const [newChatCreated, setNewChatCreated] = useState(false);
609
+ const [isSendButtonDisabled, setIsSendButtonDisabled] = useState(false);
610
+ const [targetConversationId, setTargetConversationId] = useState("");
611
+ const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
612
+ const [isRenameModalOpen, setIsRenameModalOpen] = useState(false);
613
+ const [isSortSelectOpen, setIsSortSelectOpen] = useState(false);
614
+ const [isMcpSettingsOpen, setIsMcpSettingsOpen] = useState(false);
615
+ const [chatHeaderBgColor, setChatHeaderBgColor] = useState();
616
+ const contentScrollRef = useRef(null);
617
+ const bottomSentinelRef = useRef(null);
618
+ const [messageBarKey, setMessageBarKey] = useState(0);
619
+ const [hasChatContentOverflow, setHasChatContentOverflow] = useState(false);
620
+ const wasStoppedByUserRef = useRef(false);
621
+ const { isReady, lastOpenedId, setLastOpenedId, clearLastOpenedId } = useLastOpenedConversation(user);
622
+ const showChatPanel = !isFullscreenMode || activeTab === 0;
623
+ const showNotebooksPanel = (notebooksEnabled || isOnNotebookRoute) && activeTab !== 0;
624
+ const [isChatHistoryDrawerOpen, setIsChatHistoryDrawerOpen] = useState(!isMobile && isFullscreenMode);
625
+ useLayoutEffect(() => {
626
+ if (!isFullscreenMode) {
627
+ return;
628
+ }
629
+ if (isNotebooksFullscreenPath) {
630
+ setActiveTab(1);
631
+ setShellViewTab(1);
632
+ return;
633
+ }
634
+ const isBaseLightspeedChatRoute = location.pathname === LIGHTSPEED_PATH || location.pathname === `${LIGHTSPEED_PATH}/`;
635
+ if (shellViewTab === 1 && isBaseLightspeedChatRoute) {
636
+ navigate(`${LIGHTSPEED_PATH}/notebooks`, { replace: true });
637
+ return;
638
+ }
639
+ setActiveTab(0);
640
+ setShellViewTab(0);
641
+ }, [
642
+ isFullscreenMode,
643
+ isNotebooksFullscreenPath,
644
+ shellViewTab,
645
+ location.pathname,
646
+ navigate,
647
+ setShellViewTab
648
+ ]);
649
+ const handleNotebookTabSelect = (_event, nextTab) => {
650
+ setActiveTab(nextTab);
651
+ setShellViewTab(nextTab);
652
+ if (nextTab === 1) {
653
+ navigate(`${LIGHTSPEED_PATH}/notebooks`);
654
+ if (notebooksPermissionResolved) {
655
+ refetchNotebooks();
656
+ }
657
+ } else {
658
+ navigate(
659
+ routeConversationId ? `${LIGHTSPEED_PATH}/conversation/${routeConversationId}` : LIGHTSPEED_PATH
660
+ );
661
+ }
662
+ };
663
+ const setDisplayModeFromHeader = useCallback(
664
+ (mode) => {
665
+ if (mode !== ChatbotDisplayMode.embedded) {
666
+ setDisplayMode(mode);
667
+ return;
668
+ }
669
+ if (activeTab === 1) {
670
+ const sid = activeNotebook?.session_id;
671
+ setDisplayMode(
672
+ mode,
673
+ void 0,
674
+ sid ? { notebookSessionId: sid } : "notebooks"
675
+ );
676
+ } else {
677
+ setDisplayMode(mode);
678
+ }
679
+ },
680
+ [setDisplayMode, activeTab, activeNotebook?.session_id]
681
+ );
682
+ const handleCreateNotebook = useCallback(() => {
683
+ createNotebookMutation.mutate(
684
+ { name: UNTITLED_NOTEBOOK_NAME },
685
+ {
686
+ onSuccess: (session) => {
687
+ navigate(`${LIGHTSPEED_PATH}/notebooks/${session.session_id}`);
688
+ }
689
+ }
690
+ );
691
+ }, [createNotebookMutation, navigate]);
692
+ const handleCloseNotebook = useCallback(() => {
693
+ navigate(`${LIGHTSPEED_PATH}/notebooks`);
694
+ refetchNotebooks();
695
+ }, [navigate, refetchNotebooks]);
696
+ const handleRemoveNotebookAlert = (key) => {
697
+ setNotebookAlerts(
698
+ (prevAlerts) => prevAlerts.filter((alert) => alert.key !== key)
699
+ );
700
+ };
701
+ const handleNotebookDeleted = () => {
702
+ const key = Date.now();
703
+ setNotebookAlerts((prevAlerts) => [
704
+ { title: t("notebooks.delete.toast"), variant: "success", key },
705
+ ...prevAlerts
706
+ ]);
707
+ };
708
+ useEffect(() => {
709
+ if (!isMobile && isFullscreenMode) {
710
+ setIsChatHistoryDrawerOpen(true);
711
+ }
712
+ }, [isMobile, isFullscreenMode]);
713
+ useEffect(() => {
714
+ if (typeof window === "undefined") return;
715
+ const headerElement = document.querySelector(".pf-chatbot__header");
716
+ if (!headerElement) return;
717
+ const computedBg = window.getComputedStyle(headerElement).backgroundColor;
718
+ if (computedBg) {
719
+ setChatHeaderBgColor(computedBg);
720
+ }
721
+ }, [displayMode, isMcpSettingsOpen]);
722
+ const {
723
+ isPinningChatsEnabled,
724
+ pinnedChats,
725
+ handlePinningChatsToggle,
726
+ pinChat,
727
+ unpinChat
728
+ } = usePinnedChatsSettings(user);
729
+ const { selectedSort, handleSortChange } = useSortSettings(user);
730
+ const {
731
+ uploadError,
732
+ showAlert,
733
+ fileContents,
734
+ setShowAlert,
735
+ setFileContents,
736
+ handleFileUpload,
737
+ setUploadError
738
+ } = useFileAttachmentContext();
739
+ useLayoutEffect(() => {
740
+ if (!isReady) return;
741
+ if (isFullscreenMode) {
742
+ return;
743
+ }
744
+ const handoff = consumePendingOverlayThreadHandoff?.() ?? false;
745
+ if (handoff) {
746
+ if (routeConversationId) {
747
+ setConversationId(routeConversationId);
748
+ setNewChatCreated(false);
749
+ } else {
750
+ setConversationId(TEMP_CONVERSATION_ID);
751
+ setNewChatCreated(true);
752
+ }
753
+ return;
754
+ }
755
+ if (routeConversationId && routeConversationId !== conversationId) {
756
+ setConversationId(routeConversationId);
757
+ setNewChatCreated(false);
758
+ } else if (!routeConversationId && conversationId === "" && lastOpenedId !== null) {
759
+ setConversationId(lastOpenedId);
760
+ }
761
+ }, [
762
+ isReady,
763
+ isFullscreenMode,
764
+ routeConversationId,
765
+ conversationId,
766
+ lastOpenedId,
767
+ consumePendingOverlayThreadHandoff
768
+ ]);
769
+ useEffect(() => {
770
+ if (!isReady || !isFullscreenMode) {
771
+ return;
772
+ }
773
+ if (lastOpenedId !== null) {
774
+ setConversationId(lastOpenedId);
775
+ }
776
+ }, [lastOpenedId, isReady, isFullscreenMode]);
777
+ const queryClient = useQueryClient();
778
+ const {
779
+ data: conversations = [],
780
+ isLoading,
781
+ isRefetching
782
+ } = useConversations();
783
+ const { allowed: hasDeleteAccess } = useLightspeedDeletePermission();
784
+ const { allowed: hasUpdateAccess } = useLightspeedUpdatePermission();
785
+ const samplePrompts = useWelcomePrompts();
786
+ useEffect(() => {
787
+ if (!user || !isReady) return;
788
+ const onOverlayLikeSurface = isFullscreenMode || !routeConversationId;
789
+ const stillOnProvisionalThread = !conversationId || conversationId === TEMP_CONVERSATION_ID;
790
+ if (lastOpenedId === null) {
791
+ if (onOverlayLikeSurface && stillOnProvisionalThread) {
792
+ setConversationId(TEMP_CONVERSATION_ID);
793
+ }
794
+ }
795
+ if (lastOpenedId === TEMP_CONVERSATION_ID || lastOpenedId === null) {
796
+ if (onOverlayLikeSurface && stillOnProvisionalThread) {
797
+ setNewChatCreated(true);
798
+ }
799
+ }
800
+ }, [
801
+ user,
802
+ isReady,
803
+ lastOpenedId,
804
+ setConversationId,
805
+ isFullscreenMode,
806
+ routeConversationId,
807
+ conversationId
808
+ ]);
809
+ useEffect(() => {
810
+ if (!isLoading && !isRefetching && conversations.length === 0 && lastOpenedId) {
811
+ clearLastOpenedId();
812
+ setConversationId(TEMP_CONVERSATION_ID);
813
+ setNewChatCreated(true);
814
+ setCurrentConversationId(void 0);
815
+ }
816
+ }, [
817
+ isLoading,
818
+ isRefetching,
819
+ conversations,
820
+ lastOpenedId,
821
+ clearLastOpenedId,
822
+ setCurrentConversationId
823
+ ]);
824
+ useEffect(() => {
825
+ if (!isLoading && !isRefetching && routeConversationId && isFullscreenMode) {
826
+ const conversationExists = conversations.some(
827
+ (c) => c.conversation_id === routeConversationId
828
+ );
829
+ if (!conversationExists) {
830
+ if (routeConversationId !== conversationId) {
831
+ setConversationId(TEMP_CONVERSATION_ID);
832
+ setCurrentConversationId(void 0);
833
+ setNewChatCreated(true);
834
+ }
835
+ } else if (conversationId !== routeConversationId) {
836
+ setConversationId(routeConversationId);
837
+ }
838
+ }
839
+ }, [
840
+ isLoading,
841
+ isRefetching,
842
+ routeConversationId,
843
+ conversations,
844
+ displayMode,
845
+ conversationId,
846
+ setCurrentConversationId,
847
+ isFullscreenMode
848
+ ]);
849
+ useEffect(() => {
850
+ if (conversationId) {
851
+ setLastOpenedId(conversationId);
852
+ }
853
+ }, [conversationId, setLastOpenedId]);
854
+ const viewConversationId = useMemo(
855
+ () => !isFullscreenMode && routeConversationId ? routeConversationId : conversationId,
856
+ [isFullscreenMode, routeConversationId, conversationId]
857
+ );
858
+ const onStart = (conv_id) => {
859
+ setConversationId(conv_id);
860
+ setCurrentConversationId(conv_id);
861
+ };
862
+ const onRequestIdReady = (request_id) => {
863
+ setRequestId(request_id);
864
+ };
865
+ const onComplete = (message) => {
866
+ setIsSendButtonDisabled(false);
867
+ if (!wasStoppedByUserRef.current) {
868
+ setAnnouncement(`Message from Bot: ${message}`);
869
+ }
870
+ wasStoppedByUserRef.current = false;
871
+ queryClient.invalidateQueries({
872
+ queryKey: ["conversations"]
873
+ });
874
+ queryClient.invalidateQueries({
875
+ queryKey: ["conversationMessages", viewConversationId]
876
+ });
877
+ setNewChatCreated(false);
878
+ };
879
+ const {
880
+ conversationMessages,
881
+ handleInputPrompt,
882
+ scrollToBottomRef,
883
+ streamingConversationId
884
+ } = useConversationMessages(
885
+ viewConversationId,
886
+ userName,
887
+ selectedModel,
888
+ selectedProvider,
889
+ avatar,
890
+ onComplete,
891
+ onStart,
892
+ void 0,
893
+ onRequestIdReady
894
+ );
895
+ const streamingUiMatchesView = isSendButtonDisabled && streamingConversationId !== null && viewConversationId === streamingConversationId;
896
+ const [messages, setMessages] = useState(conversationMessages);
897
+ const sendMessage = (message) => {
898
+ if (!message.toString().trim()) return;
899
+ wasStoppedByUserRef.current = false;
900
+ if (viewConversationId !== TEMP_CONVERSATION_ID) {
901
+ setNewChatCreated(false);
902
+ }
903
+ setAnnouncement(
904
+ t("conversation.announcement.userMessage", {
905
+ prompt: message.toString()
906
+ })
907
+ );
908
+ handleInputPrompt(message.toString(), getAttachments(fileContents));
909
+ setIsSendButtonDisabled(true);
910
+ setFileContents([]);
911
+ setDraftMessage("");
912
+ };
913
+ const onNewChat = useCallback(() => {
914
+ (async () => {
915
+ if (!isFullscreenMode) {
916
+ setIsMcpSettingsOpen(false);
917
+ }
918
+ if (conversationId !== TEMP_CONVERSATION_ID) {
919
+ setMessages([]);
920
+ setFileContents([]);
921
+ setUploadError({ message: null });
922
+ setDraftMessage("");
923
+ setConversationId(TEMP_CONVERSATION_ID);
924
+ setNewChatCreated(true);
925
+ setCurrentConversationId(void 0);
926
+ if (!isFullscreenMode) {
927
+ setIsChatHistoryDrawerOpen(false);
928
+ }
929
+ } else {
930
+ setMessages([]);
931
+ setNewChatCreated(true);
932
+ }
933
+ })();
934
+ }, [
935
+ conversationId,
936
+ setFileContents,
937
+ setUploadError,
938
+ setDraftMessage,
939
+ setCurrentConversationId,
940
+ isFullscreenMode
941
+ ]);
942
+ const openDeleteModal = (conversation_id) => {
943
+ setTargetConversationId(conversation_id);
944
+ setIsDeleteModalOpen(true);
945
+ };
946
+ const openChatRenameModal = (conversation_id) => {
947
+ setTargetConversationId(conversation_id);
948
+ setIsRenameModalOpen(true);
949
+ };
950
+ const handleDeleteConversation = useCallback(() => {
951
+ if (targetConversationId === lastOpenedId) {
952
+ onNewChat();
953
+ clearLastOpenedId();
954
+ }
955
+ setIsDeleteModalOpen(false);
956
+ }, [clearLastOpenedId, lastOpenedId, onNewChat, targetConversationId]);
957
+ const additionalMessageProps = useCallback(
958
+ (conversationSummary) => {
959
+ const isChatFavorite = pinnedChats?.find(
960
+ (c) => c === conversationSummary.conversation_id
961
+ );
962
+ return {
963
+ menuItems: /* @__PURE__ */ jsxs(Fragment, { children: [
964
+ /* @__PURE__ */ jsx(
965
+ DropdownItem,
966
+ {
967
+ isDisabled: !hasUpdateAccess,
968
+ icon: /* @__PURE__ */ jsx(PenIcon, {}),
969
+ onClick: () => openChatRenameModal(conversationSummary.conversation_id),
970
+ children: t("conversation.rename")
971
+ }
972
+ ),
973
+ isPinningChatsEnabled && /* @__PURE__ */ jsx(Fragment, { children: isChatFavorite ? /* @__PURE__ */ jsx(
974
+ DropdownItem,
975
+ {
976
+ icon: /* @__PURE__ */ jsx(ThumbtackIcon, {}),
977
+ onClick: () => unpinChat(conversationSummary.conversation_id),
978
+ children: t("conversation.removeFromPinnedChats")
979
+ }
980
+ ) : /* @__PURE__ */ jsx(
981
+ DropdownItem,
982
+ {
983
+ icon: /* @__PURE__ */ jsx(ThumbtackIcon, {}),
984
+ onClick: () => pinChat(conversationSummary.conversation_id),
985
+ children: t("conversation.addToPinnedChats")
986
+ }
987
+ ) }),
988
+ /* @__PURE__ */ jsx(
989
+ DropdownItem,
990
+ {
991
+ isDisabled: !hasDeleteAccess,
992
+ icon: /* @__PURE__ */ jsx(TrashIcon, {}),
993
+ onClick: () => openDeleteModal(conversationSummary.conversation_id),
994
+ children: t("conversation.delete")
995
+ }
996
+ )
997
+ ] })
998
+ };
999
+ },
1000
+ [
1001
+ pinnedChats,
1002
+ hasDeleteAccess,
1003
+ isPinningChatsEnabled,
1004
+ hasUpdateAccess,
1005
+ t,
1006
+ pinChat,
1007
+ unpinChat
1008
+ ]
1009
+ );
1010
+ const notebookConversationIds = useMemo(
1011
+ () => new Set(notebookConversationIdsArray),
1012
+ [notebookConversationIdsArray]
1013
+ );
1014
+ const chatOnlyConversations = useMemo(
1015
+ () => conversations.filter(
1016
+ (c) => !notebookConversationIds.has(c.conversation_id)
1017
+ ),
1018
+ [conversations, notebookConversationIds]
1019
+ );
1020
+ const deleteChatName = useMemo(
1021
+ () => conversations.find((c) => c.conversation_id === targetConversationId)?.topic_summary ?? "",
1022
+ [conversations, targetConversationId]
1023
+ );
1024
+ const categorizedMessages = useMemo(
1025
+ () => getCategorizeMessages(
1026
+ chatOnlyConversations,
1027
+ pinnedChats,
1028
+ additionalMessageProps,
1029
+ t,
1030
+ selectedSort
1031
+ ),
1032
+ [
1033
+ additionalMessageProps,
1034
+ chatOnlyConversations,
1035
+ pinnedChats,
1036
+ t,
1037
+ selectedSort
1038
+ ]
1039
+ );
1040
+ const filterConversations = useCallback(
1041
+ (targetValue) => {
1042
+ const pinnedChatsKey = t("conversation.category.pinnedChats") || "Pinned chats";
1043
+ let isNoPinnedChatsSearchResults = false;
1044
+ let isNoRecentChatsSearchResults = false;
1045
+ const filteredConversations = Object.entries(categorizedMessages).reduce(
1046
+ (acc, [key, items]) => {
1047
+ const filteredItems = items.filter(
1048
+ (item) => (item.text ?? "").toLocaleLowerCase("en-US").includes(targetValue.toLocaleLowerCase("en-US"))
1049
+ );
1050
+ const isPinnedCategory = key === pinnedChatsKey;
1051
+ if (isPinnedCategory && isPinningChatsEnabled) {
1052
+ if (filteredItems.length > 0) {
1053
+ acc[pinnedChatsKey] = filteredItems;
1054
+ } else {
1055
+ isNoPinnedChatsSearchResults = categorizedMessages[pinnedChatsKey].length > 0;
1056
+ acc[pinnedChatsKey] = [
1057
+ {
1058
+ id: isNoPinnedChatsSearchResults ? "no-pinned-chats-search-results" : "no-pinned-chats",
1059
+ text: isNoPinnedChatsSearchResults ? t("common.noSearchResults") : t("chatbox.emptyState.noPinnedChats"),
1060
+ noIcon: true,
1061
+ additionalProps: {
1062
+ isDisabled: true,
1063
+ style: {
1064
+ fontStyle: "italic",
1065
+ opacity: 0.6
1066
+ }
1067
+ }
1068
+ }
1069
+ ];
1070
+ }
1071
+ } else if (!isPinnedCategory) {
1072
+ if (filteredItems.length > 0) {
1073
+ acc[key] = filteredItems;
1074
+ } else {
1075
+ isNoRecentChatsSearchResults = categorizedMessages[key].length > 0;
1076
+ acc[key] = [
1077
+ {
1078
+ id: isNoRecentChatsSearchResults ? "no-recent-chats-search-results" : "no-recent-chats",
1079
+ text: isNoRecentChatsSearchResults ? t("common.noSearchResults") : t("chatbox.emptyState.noRecentChats"),
1080
+ noIcon: true,
1081
+ additionalProps: {
1082
+ isDisabled: true,
1083
+ style: {
1084
+ fontStyle: "italic",
1085
+ opacity: 0.6
1086
+ }
1087
+ }
1088
+ }
1089
+ ];
1090
+ }
1091
+ }
1092
+ return acc;
1093
+ },
1094
+ {}
1095
+ );
1096
+ if (isNoPinnedChatsSearchResults && isNoRecentChatsSearchResults) {
1097
+ return {};
1098
+ }
1099
+ return filteredConversations;
1100
+ },
1101
+ [categorizedMessages, isPinningChatsEnabled, t]
1102
+ );
1103
+ useEffect(() => {
1104
+ setMessages(conversationMessages);
1105
+ }, [conversationMessages]);
1106
+ const onSelectActiveItem = useCallback(
1107
+ (_, selectedItem) => {
1108
+ if (!isFullscreenMode) {
1109
+ setIsMcpSettingsOpen(false);
1110
+ }
1111
+ setNewChatCreated(false);
1112
+ const newConvId = String(selectedItem);
1113
+ setConversationId((c_id) => {
1114
+ if (c_id !== selectedItem) {
1115
+ return newConvId;
1116
+ }
1117
+ return c_id;
1118
+ });
1119
+ setCurrentConversationId(newConvId);
1120
+ setFileContents([]);
1121
+ setUploadError({ message: null });
1122
+ setDraftMessage("");
1123
+ scrollToBottomRef.current?.scrollToBottom();
1124
+ },
1125
+ [
1126
+ setConversationId,
1127
+ setUploadError,
1128
+ setFileContents,
1129
+ setDraftMessage,
1130
+ scrollToBottomRef,
1131
+ setCurrentConversationId,
1132
+ setIsMcpSettingsOpen,
1133
+ isFullscreenMode
1134
+ ]
1135
+ );
1136
+ const conversationFound = !!conversations.find(
1137
+ (c) => c.conversation_id === viewConversationId
1138
+ );
1139
+ const getMaxPrompts = () => {
1140
+ if (isFullscreenMode) {
1141
+ return samplePrompts?.length;
1142
+ }
1143
+ if (displayMode === ChatbotDisplayMode.docked) {
1144
+ return 2;
1145
+ }
1146
+ return 1;
1147
+ };
1148
+ const maxPrompts = getMaxPrompts();
1149
+ const welcomePrompts = newChatCreated && conversationMessages.length === 0 || !conversationFound && conversationMessages.length === 0 ? samplePrompts?.slice(0, maxPrompts).map((prompt) => {
1150
+ const p = prompt;
1151
+ return {
1152
+ title: p.title,
1153
+ message: p.message,
1154
+ onClick: () => {
1155
+ sendMessage(p.message);
1156
+ }
1157
+ };
1158
+ }) : [];
1159
+ useLayoutEffect(() => {
1160
+ if (welcomePrompts.length === 0) return void 0;
1161
+ const el = contentScrollRef.current;
1162
+ const sentinel = bottomSentinelRef.current;
1163
+ if (!el) return void 0;
1164
+ const scrollToBottom = () => {
1165
+ if (sentinel && typeof sentinel.scrollIntoView === "function") {
1166
+ sentinel.scrollIntoView({ block: "end", behavior: "auto" });
1167
+ } else {
1168
+ el.scrollTop = el.scrollHeight;
1169
+ }
1170
+ };
1171
+ const rafId = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(() => scrollToBottom()) : null;
1172
+ if (rafId === null) scrollToBottom();
1173
+ const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => scrollToBottom()) : void 0;
1174
+ resizeObserver?.observe(el);
1175
+ return () => {
1176
+ if (rafId !== null && typeof cancelAnimationFrame !== "undefined") {
1177
+ cancelAnimationFrame(rafId);
1178
+ }
1179
+ resizeObserver?.disconnect();
1180
+ };
1181
+ }, [welcomePrompts.length]);
1182
+ useEffect(() => {
1183
+ const scrollContainer = contentScrollRef.current;
1184
+ if (!scrollContainer) {
1185
+ setHasChatContentOverflow(false);
1186
+ return void 0;
1187
+ }
1188
+ const getMessageBox = () => scrollContainer.querySelector(
1189
+ ".pf-chatbot__messagebox"
1190
+ );
1191
+ const messageBoxOwnsScroll = (messageBox) => {
1192
+ if (!messageBox || typeof window === "undefined") {
1193
+ return false;
1194
+ }
1195
+ const overflowY = window.getComputedStyle(messageBox).overflowY;
1196
+ return overflowY === "auto" || overflowY === "scroll" || overflowY === "overlay";
1197
+ };
1198
+ const getScrollTarget = () => {
1199
+ const messageBox = getMessageBox();
1200
+ return messageBoxOwnsScroll(messageBox) ? messageBox : scrollContainer;
1201
+ };
1202
+ let observedScrollTarget = getScrollTarget();
1203
+ let rafId = null;
1204
+ let updateScheduled = false;
1205
+ const updateOverflow = () => {
1206
+ const scrollTarget = observedScrollTarget ?? scrollContainer;
1207
+ setHasChatContentOverflow(
1208
+ scrollTarget.scrollHeight > scrollTarget.clientHeight + 1
1209
+ );
1210
+ };
1211
+ const scheduleOverflowUpdate = () => {
1212
+ if (updateScheduled) {
1213
+ return;
1214
+ }
1215
+ updateScheduled = true;
1216
+ if (typeof requestAnimationFrame !== "undefined") {
1217
+ rafId = requestAnimationFrame(() => {
1218
+ updateScheduled = false;
1219
+ updateOverflow();
1220
+ });
1221
+ } else {
1222
+ updateScheduled = false;
1223
+ updateOverflow();
1224
+ }
1225
+ };
1226
+ scheduleOverflowUpdate();
1227
+ scrollContainer.addEventListener("scroll", scheduleOverflowUpdate, {
1228
+ passive: true,
1229
+ capture: true
1230
+ });
1231
+ const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => scheduleOverflowUpdate()) : void 0;
1232
+ resizeObserver?.observe(scrollContainer);
1233
+ if (observedScrollTarget !== scrollContainer) {
1234
+ resizeObserver?.observe(observedScrollTarget);
1235
+ }
1236
+ const syncObservedScrollTarget = () => {
1237
+ const nextScrollTarget = getScrollTarget();
1238
+ if (nextScrollTarget === observedScrollTarget) {
1239
+ return;
1240
+ }
1241
+ if (observedScrollTarget && observedScrollTarget !== scrollContainer) {
1242
+ resizeObserver?.unobserve(observedScrollTarget);
1243
+ }
1244
+ if (nextScrollTarget !== scrollContainer) {
1245
+ resizeObserver?.observe(nextScrollTarget);
1246
+ }
1247
+ observedScrollTarget = nextScrollTarget;
1248
+ };
1249
+ const mutationObserver = typeof MutationObserver !== "undefined" ? new MutationObserver(() => {
1250
+ syncObservedScrollTarget();
1251
+ scheduleOverflowUpdate();
1252
+ }) : void 0;
1253
+ mutationObserver?.observe(scrollContainer, {
1254
+ childList: true,
1255
+ subtree: true,
1256
+ characterData: true
1257
+ });
1258
+ if (typeof window !== "undefined") {
1259
+ window.addEventListener("resize", updateOverflow);
1260
+ }
1261
+ return () => {
1262
+ if (rafId !== null && typeof cancelAnimationFrame !== "undefined") {
1263
+ cancelAnimationFrame(rafId);
1264
+ }
1265
+ scrollContainer.removeEventListener(
1266
+ "scroll",
1267
+ scheduleOverflowUpdate,
1268
+ true
1269
+ );
1270
+ if (observedScrollTarget && observedScrollTarget !== scrollContainer) {
1271
+ resizeObserver?.unobserve(observedScrollTarget);
1272
+ }
1273
+ resizeObserver?.disconnect();
1274
+ mutationObserver?.disconnect();
1275
+ if (typeof window !== "undefined") {
1276
+ window.removeEventListener("resize", updateOverflow);
1277
+ }
1278
+ };
1279
+ }, [
1280
+ conversationId,
1281
+ displayMode,
1282
+ isMcpSettingsOpen,
1283
+ messages.length,
1284
+ welcomePrompts.length
1285
+ ]);
1286
+ const handleFilter = useCallback((value) => {
1287
+ setFilterValue(value);
1288
+ }, []);
1289
+ const onChatHistoryDrawerToggle = useCallback(() => {
1290
+ setIsChatHistoryDrawerOpen((isOpen) => !isOpen);
1291
+ }, []);
1292
+ const onSortToggle = useCallback(() => {
1293
+ setIsSortSelectOpen((prev) => !prev);
1294
+ }, []);
1295
+ const onSortSelect = useCallback(
1296
+ (_event, value) => {
1297
+ handleSortChange(value);
1298
+ setIsSortSelectOpen(false);
1299
+ },
1300
+ [handleSortChange]
1301
+ );
1302
+ const getSortLabel = useCallback(
1303
+ (option) => {
1304
+ const labels = {
1305
+ newest: t("sort.newest"),
1306
+ oldest: t("sort.oldest"),
1307
+ alphabeticalAsc: t("sort.alphabeticalAsc"),
1308
+ alphabeticalDesc: t("sort.alphabeticalDesc")
1309
+ };
1310
+ return labels[option];
1311
+ },
1312
+ [t]
1313
+ );
1314
+ const sortToggle = useCallback(
1315
+ (toggleRef) => /* @__PURE__ */ jsx(Tooltip, { content: `${t("sort.label")} - ${getSortLabel(selectedSort)}`, children: /* @__PURE__ */ jsx(
1316
+ MenuToggle,
1317
+ {
1318
+ ref: toggleRef,
1319
+ "aria-label": t("sort.label"),
1320
+ variant: "plain",
1321
+ onClick: onSortToggle,
1322
+ isExpanded: isSortSelectOpen,
1323
+ children: selectedSort === "oldest" || selectedSort === "alphabeticalDesc" ? /* @__PURE__ */ jsx(SortAmountDownAltIcon, {}) : /* @__PURE__ */ jsx(SortAmountDownIcon, {})
1324
+ }
1325
+ ) }),
1326
+ [t, getSortLabel, selectedSort, onSortToggle, isSortSelectOpen]
1327
+ );
1328
+ const sortDropdown = useMemo(
1329
+ () => /* @__PURE__ */ jsx(
1330
+ Select,
1331
+ {
1332
+ id: "sort-select",
1333
+ isOpen: isSortSelectOpen,
1334
+ selected: selectedSort,
1335
+ onSelect: onSortSelect,
1336
+ onOpenChange: (isOpen) => setIsSortSelectOpen(isOpen),
1337
+ popperProps: { position: "end" },
1338
+ toggle: sortToggle,
1339
+ shouldFocusToggleOnSelect: true,
1340
+ children: /* @__PURE__ */ jsxs(SelectList, { className: classes.sortDropdown, children: [
1341
+ /* @__PURE__ */ jsx(SelectOption, { value: "newest", children: t("sort.newest") }),
1342
+ /* @__PURE__ */ jsx(SelectOption, { value: "oldest", children: t("sort.oldest") }),
1343
+ /* @__PURE__ */ jsx(SelectOption, { value: "alphabeticalAsc", children: t("sort.alphabeticalAsc") }),
1344
+ /* @__PURE__ */ jsx(SelectOption, { value: "alphabeticalDesc", children: t("sort.alphabeticalDesc") })
1345
+ ] })
1346
+ }
1347
+ ),
1348
+ [
1349
+ isSortSelectOpen,
1350
+ selectedSort,
1351
+ onSortSelect,
1352
+ sortToggle,
1353
+ t,
1354
+ classes.sortDropdown
1355
+ ]
1356
+ );
1357
+ const handleAttach = (data, event) => {
1358
+ if ("preventDefault" in event && typeof event.preventDefault === "function") {
1359
+ event.preventDefault();
1360
+ }
1361
+ handleFileUpload(data);
1362
+ };
1363
+ const { mutate: stopConversation } = useStopConversation();
1364
+ const handleStopButton = () => {
1365
+ wasStoppedByUserRef.current = true;
1366
+ if (requestId) {
1367
+ stopConversation(requestId);
1368
+ setRequestId("");
1369
+ }
1370
+ setIsSendButtonDisabled(false);
1371
+ setAnnouncement(t("conversation.announcement.responseStopped"));
1372
+ const lastUserMessage = [...conversationMessages].reverse().find((m) => m.role === "user");
1373
+ const restoredPrompt = lastUserMessage?.content ?? "";
1374
+ setDraftMessage(restoredPrompt.trim());
1375
+ if (restoredPrompt) setMessageBarKey((k) => k + 1);
1376
+ setFileContents([]);
1377
+ setUploadError({ message: null });
1378
+ };
1379
+ const handleDraftMessage = (_e, value) => setDraftMessage(value);
1380
+ const onAttachRejected = (data) => {
1381
+ data.forEach((attachment) => {
1382
+ const hasInvalidTypeError = attachment.errors.some(
1383
+ (e) => e.code === "file-invalid-type"
1384
+ );
1385
+ if (hasInvalidTypeError) {
1386
+ setShowAlert(true);
1387
+ setUploadError({
1388
+ message: t("file.upload.error.unsupportedType")
1389
+ });
1390
+ }
1391
+ });
1392
+ };
1393
+ const chatMainContent = /* @__PURE__ */ jsxs(Fragment, { children: [
1394
+ /* @__PURE__ */ jsx(
1395
+ ChatbotContent,
1396
+ {
1397
+ className: `${classes.chatbotContent} ${hasChatContentOverflow ? classes.chatbotContentHasOverflow : ""}`,
1398
+ children: /* @__PURE__ */ jsxs(
1399
+ "div",
1400
+ {
1401
+ ref: contentScrollRef,
1402
+ className: `${classes.chatbotContentScroll}${welcomePrompts.length > 0 ? ` ${classes.chatbotContentScrollNewChat}` : ""}`,
1403
+ children: [
1404
+ welcomePrompts.length > 0 && /* @__PURE__ */ jsx("div", { className: classes.chatbotContentSpacer, "aria-hidden": true }),
1405
+ /* @__PURE__ */ jsx(
1406
+ LightspeedChatBox,
1407
+ {
1408
+ userName,
1409
+ messages,
1410
+ profileLoading,
1411
+ announcement,
1412
+ ref: scrollToBottomRef,
1413
+ welcomePrompts,
1414
+ conversationId,
1415
+ isStreaming: streamingUiMatchesView,
1416
+ topicRestrictionEnabled,
1417
+ displayMode
1418
+ }
1419
+ ),
1420
+ welcomePrompts.length > 0 && /* @__PURE__ */ jsx(
1421
+ "div",
1422
+ {
1423
+ ref: bottomSentinelRef,
1424
+ "aria-hidden": true,
1425
+ style: { height: 0, flexShrink: 0 }
1426
+ }
1427
+ )
1428
+ ]
1429
+ }
1430
+ )
1431
+ }
1432
+ ),
1433
+ /* @__PURE__ */ jsxs(
1434
+ ChatbotFooter,
1435
+ {
1436
+ className: `${classes.footer} ${classes.fullscreenFooter}`,
1437
+ children: [
1438
+ /* @__PURE__ */ jsx(FilePreview, {}),
1439
+ /* @__PURE__ */ jsx(
1440
+ MessageBar,
1441
+ {
1442
+ className: classes.messageBar,
1443
+ onSendMessage: sendMessage,
1444
+ isSendButtonDisabled,
1445
+ hasAttachButton: true,
1446
+ handleAttach,
1447
+ hasMicrophoneButton: true,
1448
+ value: draftMessage,
1449
+ onChange: handleDraftMessage,
1450
+ hasStopButton: streamingUiMatchesView,
1451
+ handleStopButton: streamingUiMatchesView ? handleStopButton : void 0,
1452
+ buttonProps: {
1453
+ attach: {
1454
+ inputTestId: "attachment-input",
1455
+ tooltipContent: t("tooltip.attach"),
1456
+ "aria-label": t("tooltip.attach"),
1457
+ icon: /* @__PURE__ */ jsx(PlusIcon, {})
1458
+ },
1459
+ microphone: {
1460
+ tooltipContent: {
1461
+ active: t("tooltip.microphone.active"),
1462
+ inactive: t("tooltip.microphone.inactive")
1463
+ }
1464
+ },
1465
+ send: {
1466
+ tooltipContent: t("tooltip.send")
1467
+ }
1468
+ },
1469
+ additionalActions: /* @__PURE__ */ jsx(
1470
+ MessageBarModelSelector,
1471
+ {
1472
+ selectedModel,
1473
+ models,
1474
+ onSelect: (item) => {
1475
+ if (!isFullscreenMode) {
1476
+ setIsMcpSettingsOpen(false);
1477
+ }
1478
+ onNewChat();
1479
+ handleSelectedModel(item);
1480
+ },
1481
+ disabled: isSendButtonDisabled
1482
+ }
1483
+ ),
1484
+ forceMultilineLayout: true,
1485
+ allowedFileTypes: supportedFileTypes,
1486
+ onAttachRejected,
1487
+ placeholder: t("chatbox.message.placeholder")
1488
+ },
1489
+ messageBarKey
1490
+ ),
1491
+ /* @__PURE__ */ jsx(ChatbotFootnoteWithIcon, { ...getFootnoteProps(t) })
1492
+ ]
1493
+ }
1494
+ )
1495
+ ] });
1496
+ const mcpSettingsPanel = /* @__PURE__ */ jsx(
1497
+ McpServersSettings,
1498
+ {
1499
+ onClose: () => setIsMcpSettingsOpen(false),
1500
+ backgroundColor: chatHeaderBgColor
1501
+ }
1502
+ );
1503
+ const mainPanelContent = (() => {
1504
+ if (!isMcpSettingsOpen) {
1505
+ return /* @__PURE__ */ jsx(Fragment, { children: chatMainContent });
1506
+ }
1507
+ if (isFullscreenMode) {
1508
+ return /* @__PURE__ */ jsxs("div", { className: classes.mcpFullscreenLayout, children: [
1509
+ /* @__PURE__ */ jsx("div", { className: classes.mcpChatPane, children: chatMainContent }),
1510
+ /* @__PURE__ */ jsx("div", { className: classes.mcpSettingsPane, children: mcpSettingsPanel })
1511
+ ] });
1512
+ }
1513
+ return /* @__PURE__ */ jsx(
1514
+ Settings,
1515
+ {
1516
+ className: classes.settingsFlat,
1517
+ fields: [
1518
+ {
1519
+ id: "mcp-servers-settings",
1520
+ label: "",
1521
+ field: mcpSettingsPanel
1522
+ }
1523
+ ]
1524
+ }
1525
+ );
1526
+ })();
1527
+ let drawerPanelStyle;
1528
+ if (!isFullscreenMode) {
1529
+ drawerPanelStyle = { zIndex: 1300 };
1530
+ } else if (isMcpSettingsOpen) {
1531
+ drawerPanelStyle = { width: 320, minWidth: 320, maxWidth: 320 };
1532
+ } else {
1533
+ drawerPanelStyle = { minWidth: 232, maxWidth: 400 };
1534
+ }
1535
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1536
+ notebookAlerts.length > 0 && /* @__PURE__ */ jsx(
1537
+ AlertGroup,
1538
+ {
1539
+ hasAnimations: true,
1540
+ isToast: true,
1541
+ isLiveRegion: true,
1542
+ className: classes.toastAlertGroup,
1543
+ children: notebookAlerts.map(({ key, title, variant }) => /* @__PURE__ */ jsx(
1544
+ Alert,
1545
+ {
1546
+ variant: AlertVariant[variant ?? "success"],
1547
+ title,
1548
+ className: classes.toastAlert,
1549
+ timeout: 2e3,
1550
+ onTimeout: () => handleRemoveNotebookAlert(key),
1551
+ actionClose: /* @__PURE__ */ jsx(
1552
+ AlertActionCloseButton,
1553
+ {
1554
+ title,
1555
+ variantLabel: `${variant ?? "success"} alert`,
1556
+ onClose: () => handleRemoveNotebookAlert(key)
1557
+ }
1558
+ )
1559
+ },
1560
+ key
1561
+ ))
1562
+ }
1563
+ ),
1564
+ isDeleteModalOpen && /* @__PURE__ */ jsx(
1565
+ DeleteModal,
1566
+ {
1567
+ isOpen: isDeleteModalOpen,
1568
+ conversationId: targetConversationId,
1569
+ chatName: deleteChatName,
1570
+ onClose: () => setIsDeleteModalOpen(false),
1571
+ onConfirm: handleDeleteConversation
1572
+ }
1573
+ ),
1574
+ isRenameModalOpen && /* @__PURE__ */ jsx(
1575
+ RenameConversationModal,
1576
+ {
1577
+ isOpen: isRenameModalOpen,
1578
+ onClose: () => setIsRenameModalOpen(false),
1579
+ conversationId: targetConversationId
1580
+ }
1581
+ ),
1582
+ renameNotebookId && /* @__PURE__ */ jsx(
1583
+ RenameNotebookModal,
1584
+ {
1585
+ isOpen: Boolean(renameNotebookId),
1586
+ onClose: () => setRenameNotebookId(null),
1587
+ sessionId: renameNotebookId,
1588
+ currentName: notebooks.find((n) => n.session_id === renameNotebookId)?.name ?? ""
1589
+ }
1590
+ ),
1591
+ deleteNotebookId && /* @__PURE__ */ jsx(
1592
+ DeleteNotebookModal,
1593
+ {
1594
+ isOpen: Boolean(deleteNotebookId),
1595
+ onClose: () => setDeleteNotebookId(null),
1596
+ onDeleted: handleNotebookDeleted,
1597
+ sessionId: deleteNotebookId,
1598
+ name: notebooks.find((n) => n.session_id === deleteNotebookId)?.name ?? ""
1599
+ }
1600
+ ),
1601
+ /* @__PURE__ */ jsxs(
1602
+ Chatbot,
1603
+ {
1604
+ displayMode: ChatbotDisplayMode.embedded,
1605
+ className: `${classes.body} ${isMcpSettingsOpen && !isChatHistoryDrawerOpen ? classes.mcpCollapsedDrawerOrderFix : ""}`,
1606
+ children: [
1607
+ /* @__PURE__ */ jsxs(ChatbotHeader, { className: classes.header, children: [
1608
+ /* @__PURE__ */ jsxs(ChatbotHeaderMain, { children: [
1609
+ showChatPanel && !isFullscreenMode && /* @__PURE__ */ jsx(
1610
+ ChatbotHeaderMenu,
1611
+ {
1612
+ "aria-expanded": isChatHistoryDrawerOpen,
1613
+ onMenuToggle: onChatHistoryDrawerToggle,
1614
+ className: classes.headerMenu,
1615
+ tooltipContent: t("tooltip.chatHistoryMenu"),
1616
+ "aria-label": t("aria.chatHistoryMenu")
1617
+ }
1618
+ ),
1619
+ isFullscreenMode && /* @__PURE__ */ jsxs(Fragment, { children: [
1620
+ /* @__PURE__ */ jsx(
1621
+ RhUiAiExperienceIcon,
1622
+ {
1623
+ style: { width: "24px", height: "24px" },
1624
+ "aria-label": t("icon.lightspeed.alt"),
1625
+ className: classes.headerLogo
1626
+ }
1627
+ ),
1628
+ /* @__PURE__ */ jsx(ChatbotHeaderTitle, { className: classes.headerTitle, children: /* @__PURE__ */ jsx(
1629
+ Title,
1630
+ {
1631
+ headingLevel: "h1",
1632
+ size: "2xl",
1633
+ style: { fontWeight: 700 },
1634
+ children: t("chatbox.header.title")
1635
+ }
1636
+ ) })
1637
+ ] })
1638
+ ] }),
1639
+ /* @__PURE__ */ jsx(
1640
+ LightspeedChatBoxHeader,
1641
+ {
1642
+ selectedModel,
1643
+ handleSelectedModel: (item) => {
1644
+ if (!isFullscreenMode) {
1645
+ setIsMcpSettingsOpen(false);
1646
+ }
1647
+ onNewChat();
1648
+ handleSelectedModel(item);
1649
+ },
1650
+ models,
1651
+ isPinningChatsEnabled,
1652
+ isModelSelectorDisabled: isSendButtonDisabled,
1653
+ hideModelSelector: true,
1654
+ showChatTabOptions: !showNotebooksPanel,
1655
+ setDisplayMode: setDisplayModeFromHeader,
1656
+ displayMode,
1657
+ onPinnedChatsToggle: handlePinningChatsToggle,
1658
+ onMcpSettingsClick: () => setIsMcpSettingsOpen(true)
1659
+ }
1660
+ )
1661
+ ] }),
1662
+ isFullscreenMode && /* @__PURE__ */ jsx("div", { className: classes.headerDivider }),
1663
+ isFullscreenMode && shouldShowTabs && /* @__PURE__ */ jsxs(
1664
+ Tabs,
1665
+ {
1666
+ value: activeTab,
1667
+ onChange: handleNotebookTabSelect,
1668
+ "aria-label": t("tabs.ariaLabel"),
1669
+ variant: "standard",
1670
+ textColor: "primary",
1671
+ sx: (theme) => ({
1672
+ backgroundColor: "var(--pf-t--global--background--color--floating--default)",
1673
+ borderBottom: "1px solid var(--pf-t--global--border--color--default)",
1674
+ minHeight: theme.spacing(6),
1675
+ paddingLeft: theme.spacing(2),
1676
+ paddingRight: theme.spacing(2),
1677
+ "& .MuiTabs-flexContainer": {
1678
+ gap: theme.spacing(2)
1679
+ },
1680
+ '& [role="tab"]': {
1681
+ fontWeight: 700,
1682
+ textTransform: "none",
1683
+ opacity: 1,
1684
+ padding: `${theme.spacing(1)} ${theme.spacing(2)}`,
1685
+ borderRadius: theme.spacing(0.5),
1686
+ '&:not([aria-selected="true"])': {
1687
+ color: `${theme.palette.text.primary} !important`
1688
+ },
1689
+ "&:hover": {
1690
+ background: "none !important",
1691
+ backgroundColor: "transparent !important",
1692
+ backgroundImage: "none !important"
1693
+ },
1694
+ '&:not([aria-selected="true"]):hover': {
1695
+ color: "var(--pf-t--global--text--color--brand--default)"
1696
+ },
1697
+ '&[aria-selected="true"]:hover': {
1698
+ color: `${theme.palette.primary.main} !important`
1699
+ }
1700
+ },
1701
+ '& [class*="Tabs-indicator"]': {
1702
+ height: 3
1703
+ }
1704
+ }),
1705
+ children: [
1706
+ /* @__PURE__ */ jsx(
1707
+ Tab,
1708
+ {
1709
+ disableRipple: true,
1710
+ label: t("tabs.chat"),
1711
+ "aria-label": t("tabs.chat")
1712
+ }
1713
+ ),
1714
+ /* @__PURE__ */ jsx(
1715
+ Tab,
1716
+ {
1717
+ disableRipple: true,
1718
+ label: /* @__PURE__ */ jsxs(
1719
+ "span",
1720
+ {
1721
+ style: {
1722
+ display: "inline-flex",
1723
+ alignItems: "center",
1724
+ gap: 8
1725
+ },
1726
+ children: [
1727
+ t("tabs.notebooks"),
1728
+ /* @__PURE__ */ jsx(
1729
+ Label,
1730
+ {
1731
+ color: "purple",
1732
+ style: {
1733
+ alignSelf: "center",
1734
+ margin: 0,
1735
+ lineHeight: 1
1736
+ },
1737
+ children: t("tabs.notebooks.devPreview")
1738
+ }
1739
+ )
1740
+ ]
1741
+ }
1742
+ ),
1743
+ "aria-label": t("tabs.notebooks")
1744
+ }
1745
+ )
1746
+ ]
1747
+ }
1748
+ ),
1749
+ showChatPanel && /* @__PURE__ */ jsx(
1750
+ ConditionalWrapper,
1751
+ {
1752
+ condition: isFullscreenMode,
1753
+ wrapper: (children) => /* @__PURE__ */ jsxs("div", { className: classes.fullscreenChatLayout, children: [
1754
+ !isChatHistoryDrawerOpen && /* @__PURE__ */ jsx(
1755
+ CollapsedHistoryStrip,
1756
+ {
1757
+ onExpand: () => setIsChatHistoryDrawerOpen(true),
1758
+ onNewChat,
1759
+ newChatDisabled: newChatCreated
1760
+ }
1761
+ ),
1762
+ children
1763
+ ] }),
1764
+ children: /* @__PURE__ */ jsx(
1765
+ ChatbotConversationHistoryNav,
1766
+ {
1767
+ drawerPanelContentProps: {
1768
+ isResizable: isFullscreenMode,
1769
+ hasNoBorder: !isFullscreenMode,
1770
+ style: drawerPanelStyle
1771
+ },
1772
+ reverseButtonOrder: true,
1773
+ displayMode: ChatbotDisplayMode.embedded,
1774
+ onDrawerToggle: onChatHistoryDrawerToggle,
1775
+ title: "",
1776
+ navTitleIcon: null,
1777
+ isDrawerOpen: isChatHistoryDrawerOpen,
1778
+ drawerCloseButtonProps: {
1779
+ "aria-label": t("aria.closeDrawerPanel")
1780
+ },
1781
+ setIsDrawerOpen: setIsChatHistoryDrawerOpen,
1782
+ activeItemId: viewConversationId,
1783
+ onSelectActiveItem,
1784
+ conversations: filterConversations(filterValue),
1785
+ onNewChat,
1786
+ newChatButtonText: t("button.newChat"),
1787
+ newChatButtonProps: {
1788
+ icon: /* @__PURE__ */ jsx(PenIcon, {}),
1789
+ isDisabled: newChatCreated
1790
+ },
1791
+ handleTextInputChange: handleFilter,
1792
+ searchInputPlaceholder: t("chatbox.search.placeholder"),
1793
+ searchInputAriaLabel: t("aria.search.placeholder"),
1794
+ searchInputProps: {
1795
+ value: filterValue,
1796
+ onClear: () => {
1797
+ setFilterValue("");
1798
+ }
1799
+ },
1800
+ searchActionEnd: sortDropdown,
1801
+ noResultsState: filterValue && Object.keys(filterConversations(filterValue)).length === 0 ? {
1802
+ bodyText: t("chatbox.emptyState.noResults.body"),
1803
+ titleText: t("chatbox.emptyState.noResults.title"),
1804
+ icon: SearchIcon
1805
+ } : void 0,
1806
+ drawerContent: /* @__PURE__ */ jsxs(
1807
+ FileDropZone,
1808
+ {
1809
+ className: classes.drawerFileDropZone,
1810
+ onFileDrop: (e, data) => handleAttach(data, e),
1811
+ displayMode: ChatbotDisplayMode.embedded,
1812
+ infoText: t("chatbox.fileUpload.infoText"),
1813
+ allowedFileTypes: supportedFileTypes,
1814
+ onAttachRejected,
1815
+ children: [
1816
+ showAlert && uploadError.message && /* @__PURE__ */ jsx("div", { className: classes.errorContainer, children: /* @__PURE__ */ jsx(
1817
+ ChatbotAlert,
1818
+ {
1819
+ component: "h4",
1820
+ title: t("chatbox.fileUpload.failed"),
1821
+ variant: uploadError.type ?? "danger",
1822
+ isInline: true,
1823
+ onClose: () => setUploadError({ message: null }),
1824
+ children: uploadError.message
1825
+ }
1826
+ ) }),
1827
+ mainPanelContent
1828
+ ]
1829
+ }
1830
+ )
1831
+ }
1832
+ )
1833
+ }
1834
+ ),
1835
+ showNotebooksPanel && !notebooksPermissionLoading && hasNotebooksAccess && activeNotebook && /* @__PURE__ */ jsx(
1836
+ NotebookView,
1837
+ {
1838
+ sessionId: activeNotebook.session_id,
1839
+ notebookName: activeNotebook.name,
1840
+ documents: notebookDocuments,
1841
+ isDocumentsFetching,
1842
+ metadata: activeNotebook.metadata,
1843
+ topicSummary: conversations.find(
1844
+ (c) => c.conversation_id === activeNotebook.metadata?.conversation_id
1845
+ )?.topic_summary ?? void 0,
1846
+ userName,
1847
+ avatar,
1848
+ profileLoading,
1849
+ topicRestrictionEnabled,
1850
+ onClose: handleCloseNotebook
1851
+ }
1852
+ ),
1853
+ showNotebooksPanel && !notebooksPermissionLoading && hasNotebooksAccess && !activeNotebook && /* @__PURE__ */ jsx(
1854
+ NotebooksTab,
1855
+ {
1856
+ notebooks,
1857
+ hasNotebooks,
1858
+ classes,
1859
+ openNotebookMenuId,
1860
+ setOpenNotebookMenuId,
1861
+ onSelectNotebook: (notebook) => {
1862
+ navigate(`${LIGHTSPEED_PATH}/notebooks/${notebook.session_id}`);
1863
+ },
1864
+ onRename: setRenameNotebookId,
1865
+ onDelete: setDeleteNotebookId,
1866
+ onCreateNotebook: handleCreateNotebook,
1867
+ t
1868
+ }
1869
+ ),
1870
+ showNotebooksPanel && !notebooksPermissionLoading && !hasNotebooksAccess && /* @__PURE__ */ jsx(
1871
+ PermissionRequiredState,
1872
+ {
1873
+ subject: t("permission.subject.notebooks"),
1874
+ permissions: ["intelligent-assistant.notebooks.use"],
1875
+ action: /* @__PURE__ */ jsx(
1876
+ Button,
1877
+ {
1878
+ variant: "outlined",
1879
+ color: "primary",
1880
+ style: { borderRadius: "20px" },
1881
+ onClick: () => {
1882
+ setActiveTab(0);
1883
+ setShellViewTab(0);
1884
+ },
1885
+ children: t("permission.notebooks.goBack")
1886
+ }
1887
+ )
1888
+ }
1889
+ )
1890
+ ]
1891
+ }
1892
+ ),
1893
+ /* @__PURE__ */ jsx(Attachment, {})
1894
+ ] });
1895
+ };
1896
+
1897
+ export { LightspeedChat };
1898
+ //# sourceMappingURL=LightSpeedChat.esm.js.map