@red-hat-developer-hub/backstage-plugin-lightspeed 1.3.0 → 2.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 (95) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +63 -4
  3. package/dist/alpha/LightspeedFAB.esm.js +69 -0
  4. package/dist/alpha/LightspeedFAB.esm.js.map +1 -0
  5. package/dist/alpha/LightspeedProvider.esm.js +6 -0
  6. package/dist/alpha/LightspeedProvider.esm.js.map +1 -0
  7. package/dist/alpha.d.ts +170 -1
  8. package/dist/alpha.esm.js +97 -1
  9. package/dist/alpha.esm.js.map +1 -1
  10. package/dist/api/LightspeedApiClient.esm.js +19 -0
  11. package/dist/api/LightspeedApiClient.esm.js.map +1 -1
  12. package/dist/api/NotebooksApiClient.esm.js +72 -0
  13. package/dist/api/NotebooksApiClient.esm.js.map +1 -0
  14. package/dist/api/api.esm.js.map +1 -1
  15. package/dist/api/notebooksApi.esm.js +10 -0
  16. package/dist/api/notebooksApi.esm.js.map +1 -0
  17. package/dist/components/DeleteModal.esm.js +2 -0
  18. package/dist/components/DeleteModal.esm.js.map +1 -1
  19. package/dist/components/LightSpeedChat.esm.js +714 -66
  20. package/dist/components/LightSpeedChat.esm.js.map +1 -1
  21. package/dist/components/LightspeedChatBox.esm.js +18 -4
  22. package/dist/components/LightspeedChatBox.esm.js.map +1 -1
  23. package/dist/components/LightspeedChatBoxHeader.esm.js +59 -50
  24. package/dist/components/LightspeedChatBoxHeader.esm.js.map +1 -1
  25. package/dist/components/LightspeedChatContainer.esm.js +26 -2
  26. package/dist/components/LightspeedChatContainer.esm.js.map +1 -1
  27. package/dist/components/LightspeedDrawerProvider.esm.js +12 -157
  28. package/dist/components/LightspeedDrawerProvider.esm.js.map +1 -1
  29. package/dist/components/LightspeedFAB.esm.js +5 -4
  30. package/dist/components/LightspeedFAB.esm.js.map +1 -1
  31. package/dist/components/McpServersSettings.esm.js +932 -0
  32. package/dist/components/McpServersSettings.esm.js.map +1 -0
  33. package/dist/components/McpSettingsIcon.esm.js +26 -0
  34. package/dist/components/McpSettingsIcon.esm.js.map +1 -0
  35. package/dist/components/PermissionRequiredState.esm.js +18 -22
  36. package/dist/components/PermissionRequiredState.esm.js.map +1 -1
  37. package/dist/components/RenameConversationModal.esm.js +2 -2
  38. package/dist/components/RenameConversationModal.esm.js.map +1 -1
  39. package/dist/components/ToolCallContent.esm.js +14 -4
  40. package/dist/components/ToolCallContent.esm.js.map +1 -1
  41. package/dist/components/notebooks/DeleteNotebookModal.esm.js +143 -0
  42. package/dist/components/notebooks/DeleteNotebookModal.esm.js.map +1 -0
  43. package/dist/components/notebooks/NotebookCard.esm.js +96 -0
  44. package/dist/components/notebooks/NotebookCard.esm.js.map +1 -0
  45. package/dist/components/notebooks/NotebooksTab.esm.js +61 -0
  46. package/dist/components/notebooks/NotebooksTab.esm.js.map +1 -0
  47. package/dist/components/notebooks/RenameNotebookModal.esm.js +187 -0
  48. package/dist/components/notebooks/RenameNotebookModal.esm.js.map +1 -0
  49. package/dist/const.esm.js +3 -1
  50. package/dist/const.esm.js.map +1 -1
  51. package/dist/dev.d.ts +2 -0
  52. package/dist/dev.esm.js +48 -0
  53. package/dist/dev.esm.js.map +1 -0
  54. package/dist/hooks/notebooks/useDeleteNotebook.esm.js +19 -0
  55. package/dist/hooks/notebooks/useDeleteNotebook.esm.js.map +1 -0
  56. package/dist/hooks/notebooks/useLightspeedNotebooksPermission.esm.js +15 -0
  57. package/dist/hooks/notebooks/useLightspeedNotebooksPermission.esm.js.map +1 -0
  58. package/dist/hooks/notebooks/useNotebookSessions.esm.js +18 -0
  59. package/dist/hooks/notebooks/useNotebookSessions.esm.js.map +1 -0
  60. package/dist/hooks/notebooks/useRenameNotebook.esm.js +19 -0
  61. package/dist/hooks/notebooks/useRenameNotebook.esm.js.map +1 -0
  62. package/dist/hooks/useConversationMessages.esm.js +136 -36
  63. package/dist/hooks/useConversationMessages.esm.js.map +1 -1
  64. package/dist/hooks/useConversations.esm.js +6 -0
  65. package/dist/hooks/useConversations.esm.js.map +1 -1
  66. package/dist/hooks/useCreateCoversationMessage.esm.js.map +1 -1
  67. package/dist/hooks/useLightspeedProviderState.esm.js +205 -0
  68. package/dist/hooks/useLightspeedProviderState.esm.js.map +1 -0
  69. package/dist/hooks/useStopConversation.esm.js +18 -0
  70. package/dist/hooks/useStopConversation.esm.js.map +1 -0
  71. package/dist/hooks/useWelcomePrompts.esm.js +2 -2
  72. package/dist/hooks/useWelcomePrompts.esm.js.map +1 -1
  73. package/dist/index.d.ts +31 -31
  74. package/dist/plugin.esm.js +10 -0
  75. package/dist/plugin.esm.js.map +1 -1
  76. package/dist/translations/de.esm.js +136 -100
  77. package/dist/translations/de.esm.js.map +1 -1
  78. package/dist/translations/es.esm.js +134 -98
  79. package/dist/translations/es.esm.js.map +1 -1
  80. package/dist/translations/fr.esm.js +64 -1
  81. package/dist/translations/fr.esm.js.map +1 -1
  82. package/dist/translations/it.esm.js +66 -1
  83. package/dist/translations/it.esm.js.map +1 -1
  84. package/dist/translations/ja.esm.js +66 -1
  85. package/dist/translations/ja.esm.js.map +1 -1
  86. package/dist/translations/ref.esm.js +65 -1
  87. package/dist/translations/ref.esm.js.map +1 -1
  88. package/dist/types.esm.js.map +1 -1
  89. package/dist/utils/formatToolResponseForMarkdown.esm.js +46 -0
  90. package/dist/utils/formatToolResponseForMarkdown.esm.js.map +1 -0
  91. package/dist/utils/lightspeed-chatbox-utils.esm.js +7 -3
  92. package/dist/utils/lightspeed-chatbox-utils.esm.js.map +1 -1
  93. package/dist/utils/notebooks-utils.esm.js +25 -0
  94. package/dist/utils/notebooks-utils.esm.js.map +1 -0
  95. package/package.json +28 -12
@@ -1,10 +1,9 @@
1
1
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
- import { useState, useEffect, useCallback, useMemo } from 'react';
3
- import { makeStyles } from '@material-ui/core';
4
- import Divider from '@mui/material/Divider';
5
- import { ChatbotDisplayMode, Chatbot, ChatbotHeader, ChatbotHeaderMain, ChatbotHeaderMenu, ChatbotHeaderTitle, FileDropZone, ChatbotAlert, ChatbotContent, ChatbotFooter, MessageBar, ChatbotFootnote } from '@patternfly/chatbot';
2
+ import { useState, useRef, useEffect, useCallback, useMemo, useLayoutEffect } from 'react';
3
+ import { makeStyles, Button } from '@material-ui/core';
4
+ import { ChatbotDisplayMode, ChatbotContent, ChatbotFooter, MessageBar, ChatbotFootnote, Settings, Chatbot, ChatbotHeader, ChatbotHeaderMain, ChatbotHeaderMenu, ChatbotHeaderTitle, FileDropZone, ChatbotAlert } from '@patternfly/chatbot';
6
5
  import ChatbotConversationHistoryNav from '@patternfly/chatbot/dist/dynamic/ChatbotConversationHistoryNav';
7
- import { DropdownItem, Tooltip, MenuToggle, Select, SelectList, SelectOption, Title } from '@patternfly/react-core';
6
+ import { DropdownItem, Tooltip, MenuToggle, Select, SelectList, SelectOption, AlertGroup, Alert, AlertVariant, AlertActionCloseButton, Title, Tabs, Tab } from '@patternfly/react-core';
8
7
  import { SortAmountDownAltIcon, SortAmountDownIcon, PlusIcon, SearchIcon } from '@patternfly/react-icons';
9
8
  import { useQueryClient } from '@tanstack/react-query';
10
9
  import { TEMP_CONVERSATION_ID, supportedFileTypes } from '../const.esm.js';
@@ -13,13 +12,17 @@ import '../api/api.esm.js';
13
12
  import { useBackstageUserIdentity } from '../hooks/useBackstageUserIdentity.esm.js';
14
13
  import { useConversationMessages } from '../hooks/useConversationMessages.esm.js';
15
14
  import { useConversations } from '../hooks/useConversations.esm.js';
15
+ import '../api/notebooksApi.esm.js';
16
16
  import { useIsMobile } from '../hooks/useIsMobile.esm.js';
17
17
  import { useLastOpenedConversation } from '../hooks/useLastOpenedConversation.esm.js';
18
18
  import { useLightspeedDeletePermission } from '../hooks/useLightspeedDeletePermission.esm.js';
19
+ import { useLightspeedNotebooksPermission } from '../hooks/notebooks/useLightspeedNotebooksPermission.esm.js';
19
20
  import '@backstage/plugin-permission-react';
20
21
  import '@red-hat-developer-hub/backstage-plugin-lightspeed-common';
22
+ import { useNotebookSessions } from '../hooks/notebooks/useNotebookSessions.esm.js';
21
23
  import { usePinnedChatsSettings } from '../hooks/usePinnedChatsSettings.esm.js';
22
24
  import { useSortSettings } from '../hooks/useSortSettings.esm.js';
25
+ import { useStopConversation } from '../hooks/useStopConversation.esm.js';
23
26
  import { useTranslation } from '../hooks/useTranslation.esm.js';
24
27
  import { useLightspeedDrawerContext } from '../hooks/useLightspeedDrawerContext.esm.js';
25
28
  import { useLightspeedUpdatePermission } from '../hooks/useLightspeedUpdatePermission.esm.js';
@@ -32,6 +35,11 @@ import { DeleteModal } from './DeleteModal.esm.js';
32
35
  import FilePreview from './FilePreview.esm.js';
33
36
  import { LightspeedChatBox } from './LightspeedChatBox.esm.js';
34
37
  import { LightspeedChatBoxHeader } from './LightspeedChatBoxHeader.esm.js';
38
+ import { McpServersSettings } from './McpServersSettings.esm.js';
39
+ import { DeleteNotebookModal } from './notebooks/DeleteNotebookModal.esm.js';
40
+ import { NotebooksTab } from './notebooks/NotebooksTab.esm.js';
41
+ import { RenameNotebookModal } from './notebooks/RenameNotebookModal.esm.js';
42
+ import PermissionRequiredState from './PermissionRequiredState.esm.js';
35
43
  import { RenameConversationModal } from './RenameConversationModal.esm.js';
36
44
 
37
45
  const useStyles = makeStyles((theme) => ({
@@ -43,7 +51,9 @@ const useStyles = makeStyles((theme) => ({
43
51
  }
44
52
  },
45
53
  header: {
46
- padding: `${theme.spacing(3)}px !important`
54
+ padding: `${theme.spacing(3)}px ${theme.spacing(3)}px 0 ${theme.spacing(
55
+ 3
56
+ )}px !important`
47
57
  },
48
58
  errorContainer: {
49
59
  padding: theme.spacing(3)
@@ -58,6 +68,157 @@ const useStyles = makeStyles((theme) => ({
58
68
  headerTitle: {
59
69
  justifyContent: "left !important"
60
70
  },
71
+ tabs: {
72
+ padding: `${theme.spacing(2)}px ${theme.spacing(3)}px 0`,
73
+ backgroundColor: "var(--pf-t--global--background--color--floating--default)",
74
+ "& .pf-v6-c-tabs__item, & .pf-v5-c-tabs__item": {
75
+ backgroundColor: "transparent"
76
+ },
77
+ "& .pf-v6-c-tabs__item:not(:last-child), & .pf-v5-c-tabs__item:not(:last-child)": {
78
+ marginRight: theme.spacing(5)
79
+ },
80
+ "& .pf-v6-c-tabs__link, & .pf-v5-c-tabs__link": {
81
+ backgroundColor: "transparent",
82
+ paddingBottom: theme.spacing(2),
83
+ fontWeight: 700,
84
+ cursor: "pointer"
85
+ },
86
+ "& .pf-v6-c-tabs__item.pf-m-current .pf-v6-c-tabs__link, & .pf-v5-c-tabs__item.pf-m-current .pf-v5-c-tabs__link": {
87
+ color: "var(--pf-t--global--text--color--brand--default)"
88
+ }
89
+ },
90
+ tabsDivider: {
91
+ borderTop: "1px solid var(--pf-t--global--border--color--default)"
92
+ },
93
+ notebooksContainer: {
94
+ padding: theme.spacing(3),
95
+ height: "100%",
96
+ display: "flex",
97
+ flexDirection: "column",
98
+ flex: 1,
99
+ minHeight: 0,
100
+ overflowY: "auto"
101
+ },
102
+ notebooksHeader: {
103
+ display: "flex",
104
+ alignItems: "center",
105
+ justifyContent: "space-between",
106
+ marginBottom: theme.spacing(4)
107
+ },
108
+ notebooksHeading: {
109
+ marginBottom: 0
110
+ },
111
+ notebooksHeadingEmpty: {
112
+ "&&": {
113
+ marginBottom: theme.spacing(1),
114
+ paddingBottom: theme.spacing(1)
115
+ }
116
+ },
117
+ notebooksEmptyState: {
118
+ flex: 1,
119
+ display: "flex",
120
+ flexDirection: "column",
121
+ alignItems: "center",
122
+ justifyContent: "center",
123
+ textAlign: "center"
124
+ },
125
+ notebooksIcon: {
126
+ fontSize: 48,
127
+ color: "var(--pf-t--global--icon--color--subtle)",
128
+ marginBottom: theme.spacing(1.5)
129
+ },
130
+ notebooksDescription: {
131
+ marginTop: theme.spacing(1),
132
+ marginBottom: theme.spacing(3),
133
+ maxWidth: 420
134
+ },
135
+ notebooksAction: {
136
+ textTransform: "none",
137
+ borderRadius: 999,
138
+ paddingLeft: theme.spacing(3),
139
+ paddingRight: theme.spacing(3)
140
+ },
141
+ notebooksActionEmpty: {
142
+ textTransform: "none",
143
+ borderRadius: 999,
144
+ paddingLeft: theme.spacing(3),
145
+ paddingRight: theme.spacing(3),
146
+ marginTop: theme.spacing(3)
147
+ },
148
+ notebooksGrid: {
149
+ display: "grid",
150
+ gridTemplateColumns: "repeat(3, minmax(0, 1fr))",
151
+ gap: theme.spacing(2),
152
+ width: "100%",
153
+ maxWidth: "100%",
154
+ paddingBottom: theme.spacing(3),
155
+ [theme.breakpoints.down("md")]: {
156
+ gridTemplateColumns: "repeat(2, minmax(0, 1fr))"
157
+ },
158
+ [theme.breakpoints.down("sm")]: {
159
+ gridTemplateColumns: "repeat(1, minmax(0, 1fr))"
160
+ }
161
+ },
162
+ notebookCard: {
163
+ borderRadius: theme.spacing(1.5),
164
+ display: "flex",
165
+ flexDirection: "column"
166
+ },
167
+ notebookCardHeader: {
168
+ padding: theme.spacing(2),
169
+ paddingBottom: 0,
170
+ alignItems: "center"
171
+ },
172
+ notebookCardDivider: {
173
+ borderTop: "1px solid var(--pf-t--global--border--color--default)",
174
+ marginTop: theme.spacing(1)
175
+ },
176
+ notebookCardBody: {
177
+ padding: theme.spacing(2),
178
+ paddingTop: theme.spacing(1.5)
179
+ },
180
+ notebookDocuments: {
181
+ paddingTop: theme.spacing(1),
182
+ paddingLeft: theme.spacing(2)
183
+ },
184
+ notebookUpdated: {
185
+ paddingBottom: theme.spacing(5),
186
+ paddingLeft: theme.spacing(2),
187
+ paddingTop: theme.spacing(2)
188
+ },
189
+ notebookTitle: {
190
+ display: "flex",
191
+ alignItems: "center",
192
+ gap: theme.spacing(1),
193
+ minWidth: 0,
194
+ flex: 1
195
+ },
196
+ notebookCardHeaderActions: {
197
+ marginLeft: theme.spacing(1)
198
+ },
199
+ notebookTitleText: {
200
+ overflow: "hidden",
201
+ textOverflow: "ellipsis",
202
+ whiteSpace: "nowrap"
203
+ },
204
+ notebookMenuButton: {
205
+ color: theme.palette.text.secondary
206
+ },
207
+ notebookDropdownList: {
208
+ paddingTop: 0,
209
+ paddingBottom: 0,
210
+ paddingInlineStart: 0
211
+ },
212
+ notebookDropdownMenu: {
213
+ "--pf-v6-c-menu--PaddingBlockStart": "0",
214
+ "--pf-v6-c-menu--PaddingBlockEnd": "0"
215
+ },
216
+ notebookDropdownItem: {
217
+ justifyContent: "flex-start",
218
+ textAlign: "left",
219
+ paddingLeft: theme.spacing(1.5),
220
+ paddingRight: theme.spacing(1.5)
221
+ },
61
222
  footer: {
62
223
  "&>.pf-chatbot__footer-container": {
63
224
  width: "95% !important",
@@ -67,6 +228,125 @@ const useStyles = makeStyles((theme) => ({
67
228
  sortDropdown: {
68
229
  padding: 0,
69
230
  margin: 0
231
+ },
232
+ // Outer content wrapper (library may override overflow; we rely on inner scroll wrapper).
233
+ chatbotContent: {
234
+ minHeight: 0,
235
+ display: "flex",
236
+ flexDirection: "column",
237
+ flex: 1,
238
+ "& .pf-chatbot__jump": {
239
+ left: "50% !important",
240
+ right: "auto !important",
241
+ transform: "translateX(-50%)",
242
+ visibility: "hidden",
243
+ pointerEvents: "none"
244
+ }
245
+ },
246
+ chatbotContentHasOverflow: {
247
+ "& .pf-chatbot__jump": {
248
+ visibility: "visible",
249
+ pointerEvents: "auto"
250
+ }
251
+ },
252
+ // Inner scroll container we control: always scrollable so zoomed-in users see full content.
253
+ chatbotContentScroll: {
254
+ minHeight: 0,
255
+ flex: 1,
256
+ display: "flex",
257
+ flexDirection: "column",
258
+ overflowY: "auto",
259
+ WebkitOverflowScrolling: "touch"
260
+ },
261
+ toastAlertGroup: {
262
+ "--pf-v6-c-alert-group--m-toast--InsetInlineEnd": `${theme.spacing(2.5)}px`,
263
+ "--pf-v6-c-alert-group--m-toast--InsetBlockStart": `${theme.spacing(2.5)}px`,
264
+ "--pf-v6-c-alert-group--m-toast--MaxWidth": "350px"
265
+ },
266
+ toastAlert: {
267
+ maxWidth: "350px",
268
+ "& .pf-v6-c-alert__title": {
269
+ margin: 0
270
+ }
271
+ },
272
+ // When present, pushes welcome content to bottom (zoom out). Scroll up to see important box (zoom in).
273
+ chatbotContentSpacer: {
274
+ flex: 1,
275
+ minHeight: 0
276
+ },
277
+ settingsFlat: {
278
+ height: "100%",
279
+ width: "100%",
280
+ "&.pf-chatbot__settings-form-container": {
281
+ background: "var(--pf-v6-c-table--BackgroundColor, var(--pf-t--global--background--color--primary--default))",
282
+ padding: 0,
283
+ margin: 0,
284
+ minHeight: "100%",
285
+ display: "flex",
286
+ flexDirection: "column",
287
+ width: "100%",
288
+ maxWidth: "none"
289
+ },
290
+ "& .pf-chatbot__settings-form": {
291
+ margin: 0,
292
+ padding: 0,
293
+ background: "var(--pf-v6-c-table--BackgroundColor, var(--pf-t--global--background--color--primary--default))",
294
+ minHeight: "100%",
295
+ display: "flex",
296
+ flexDirection: "column",
297
+ width: "100%",
298
+ maxWidth: "none"
299
+ },
300
+ "& .pf-chatbot__settings-form-row": {
301
+ background: "var(--pf-v6-c-table--BackgroundColor, var(--pf-t--global--background--color--primary--default))",
302
+ border: 0,
303
+ margin: 0,
304
+ padding: 0,
305
+ minHeight: "100%",
306
+ display: "flex",
307
+ flexDirection: "column",
308
+ width: "100%",
309
+ maxWidth: "none"
310
+ },
311
+ "& .pf-chatbot__settings-label": {
312
+ display: "none"
313
+ }
314
+ },
315
+ mcpFullscreenLayout: {
316
+ display: "grid",
317
+ gridTemplateColumns: "minmax(0, 1fr) minmax(0, 1fr)",
318
+ minHeight: 0,
319
+ height: "100%",
320
+ flex: 1,
321
+ width: "100%",
322
+ minWidth: 0,
323
+ overflow: "hidden"
324
+ },
325
+ mcpChatPane: {
326
+ display: "flex",
327
+ flexDirection: "column",
328
+ minHeight: 0,
329
+ width: "100%",
330
+ minWidth: 0
331
+ },
332
+ mcpSettingsPane: {
333
+ width: "100%",
334
+ minWidth: 0,
335
+ borderLeft: `1px solid ${theme.palette.divider}`,
336
+ backgroundColor: "var(--pf-v6-c-table--BackgroundColor, var(--pf-t--global--background--color--primary--default))",
337
+ display: "flex",
338
+ flexDirection: "column",
339
+ minHeight: 0
340
+ },
341
+ mcpCollapsedDrawerOrderFix: {
342
+ "& .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": {
343
+ order: "unset"
344
+ },
345
+ "& .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": {
346
+ visibility: "hidden",
347
+ opacity: 0,
348
+ transition: "none !important"
349
+ }
70
350
  }
71
351
  }));
72
352
  const LightspeedChat = ({
@@ -85,13 +365,34 @@ const LightspeedChat = ({
85
365
  const user = useBackstageUserIdentity();
86
366
  const [filterValue, setFilterValue] = useState("");
87
367
  const [announcement, setAnnouncement] = useState("");
368
+ const [activeTab, setActiveTab] = useState(0);
369
+ const { allowed: hasNotebooksAccess, loading: notebooksPermissionLoading } = useLightspeedNotebooksPermission();
370
+ const notebooksPermissionResolved = !notebooksPermissionLoading && hasNotebooksAccess;
371
+ const { data: notebooks = [], refetch: refetchNotebooks } = useNotebookSessions(activeTab === 1 && notebooksPermissionResolved);
372
+ const hasNotebooks = notebooks.length > 0;
373
+ const [openNotebookMenuId, setOpenNotebookMenuId] = useState(
374
+ null
375
+ );
376
+ const [renameNotebookId, setRenameNotebookId] = useState(null);
377
+ const [deleteNotebookId, setDeleteNotebookId] = useState(null);
378
+ const [notebookAlerts, setNotebookAlerts] = useState(
379
+ []
380
+ );
88
381
  const [conversationId, setConversationId] = useState("");
382
+ const [requestId, setRequestId] = useState("");
89
383
  const [newChatCreated, setNewChatCreated] = useState(false);
90
384
  const [isSendButtonDisabled, setIsSendButtonDisabled] = useState(false);
91
385
  const [targetConversationId, setTargetConversationId] = useState("");
92
386
  const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
93
387
  const [isRenameModalOpen, setIsRenameModalOpen] = useState(false);
94
388
  const [isSortSelectOpen, setIsSortSelectOpen] = useState(false);
389
+ const [isMcpSettingsOpen, setIsMcpSettingsOpen] = useState(false);
390
+ const [chatHeaderBgColor, setChatHeaderBgColor] = useState();
391
+ const contentScrollRef = useRef(null);
392
+ const bottomSentinelRef = useRef(null);
393
+ const [messageBarKey, setMessageBarKey] = useState(0);
394
+ const [hasChatContentOverflow, setHasChatContentOverflow] = useState(false);
395
+ const wasStoppedByUserRef = useRef(false);
95
396
  const { isReady, lastOpenedId, setLastOpenedId, clearLastOpenedId } = useLastOpenedConversation(user);
96
397
  const {
97
398
  displayMode,
@@ -102,12 +403,42 @@ const LightspeedChat = ({
102
403
  setDraftMessage
103
404
  } = useLightspeedDrawerContext();
104
405
  const isFullscreenMode = displayMode === ChatbotDisplayMode.embedded;
406
+ const showChatPanel = !isFullscreenMode || activeTab === 0;
407
+ const showNotebooksPanel = isFullscreenMode && activeTab !== 0;
105
408
  const [isChatHistoryDrawerOpen, setIsChatHistoryDrawerOpen] = useState(!isMobile && isFullscreenMode);
409
+ const handleNotebookTabSelect = (_event, tabIndex) => {
410
+ const nextTab = Number(tabIndex);
411
+ setActiveTab(nextTab);
412
+ if (nextTab === 1 && notebooksPermissionResolved) {
413
+ refetchNotebooks();
414
+ }
415
+ };
416
+ const handleNotebookDeleted = () => {
417
+ const key = Date.now();
418
+ setNotebookAlerts((prevAlerts) => [
419
+ { title: t("notebooks.delete.toast"), variant: "success", key },
420
+ ...prevAlerts
421
+ ]);
422
+ };
423
+ const handleRemoveNotebookAlert = (key) => {
424
+ setNotebookAlerts(
425
+ (prevAlerts) => prevAlerts.filter((alert) => alert.key !== key)
426
+ );
427
+ };
106
428
  useEffect(() => {
107
429
  if (!isMobile && isFullscreenMode) {
108
430
  setIsChatHistoryDrawerOpen(true);
109
431
  }
110
432
  }, [isMobile, isFullscreenMode]);
433
+ useEffect(() => {
434
+ if (typeof window === "undefined") return;
435
+ const headerElement = document.querySelector(".pf-chatbot__header");
436
+ if (!headerElement) return;
437
+ const computedBg = window.getComputedStyle(headerElement).backgroundColor;
438
+ if (computedBg) {
439
+ setChatHeaderBgColor(computedBg);
440
+ }
441
+ }, [displayMode, isMcpSettingsOpen]);
111
442
  const {
112
443
  isPinningChatsEnabled,
113
444
  pinnedChats,
@@ -140,8 +471,11 @@ const LightspeedChat = ({
140
471
  const { allowed: hasUpdateAccess } = useLightspeedUpdatePermission();
141
472
  const samplePrompts = useWelcomePrompts();
142
473
  useEffect(() => {
143
- if (user && lastOpenedId === null && isReady) {
474
+ if (!user || !isReady) return;
475
+ if (lastOpenedId === null) {
144
476
  setConversationId(TEMP_CONVERSATION_ID);
477
+ }
478
+ if (lastOpenedId === TEMP_CONVERSATION_ID || lastOpenedId === null) {
145
479
  setNewChatCreated(true);
146
480
  }
147
481
  }, [user, isReady, lastOpenedId, setConversationId]);
@@ -182,9 +516,15 @@ const LightspeedChat = ({
182
516
  setConversationId(conv_id);
183
517
  setCurrentConversationId(conv_id);
184
518
  };
519
+ const onRequestIdReady = (request_id) => {
520
+ setRequestId(request_id);
521
+ };
185
522
  const onComplete = (message) => {
186
523
  setIsSendButtonDisabled(false);
187
- setAnnouncement(`Message from Bot: ${message}`);
524
+ if (!wasStoppedByUserRef.current) {
525
+ setAnnouncement(`Message from Bot: ${message}`);
526
+ }
527
+ wasStoppedByUserRef.current = false;
188
528
  queryClient.invalidateQueries({
189
529
  queryKey: ["conversations"]
190
530
  });
@@ -200,10 +540,13 @@ const LightspeedChat = ({
200
540
  selectedProvider,
201
541
  avatar,
202
542
  onComplete,
203
- onStart
543
+ onStart,
544
+ onRequestIdReady
204
545
  );
205
546
  const [messages, setMessages] = useState(conversationMessages);
206
547
  const sendMessage = (message) => {
548
+ if (!message.toString().trim()) return;
549
+ wasStoppedByUserRef.current = false;
207
550
  if (conversationId !== TEMP_CONVERSATION_ID) {
208
551
  setNewChatCreated(false);
209
552
  }
@@ -219,6 +562,7 @@ const LightspeedChat = ({
219
562
  };
220
563
  const onNewChat = useCallback(() => {
221
564
  (async () => {
565
+ setIsMcpSettingsOpen(false);
222
566
  if (conversationId !== TEMP_CONVERSATION_ID) {
223
567
  setMessages([]);
224
568
  setFileContents([]);
@@ -230,6 +574,9 @@ const LightspeedChat = ({
230
574
  if (!isFullscreenMode) {
231
575
  setIsChatHistoryDrawerOpen(false);
232
576
  }
577
+ } else {
578
+ setMessages([]);
579
+ setNewChatCreated(true);
233
580
  }
234
581
  })();
235
582
  }, [
@@ -322,7 +669,7 @@ const LightspeedChat = ({
322
669
  const filteredConversations = Object.entries(categorizedMessages).reduce(
323
670
  (acc, [key, items]) => {
324
671
  const filteredItems = items.filter(
325
- (item) => item.text.toLocaleLowerCase("en-US").includes(targetValue.toLocaleLowerCase("en-US"))
672
+ (item) => (item.text ?? "").toLocaleLowerCase("en-US").includes(targetValue.toLocaleLowerCase("en-US"))
326
673
  );
327
674
  const isPinnedCategory = key === pinnedChatsKey;
328
675
  if (isPinnedCategory && isPinningChatsEnabled) {
@@ -374,6 +721,7 @@ const LightspeedChat = ({
374
721
  }, [conversationMessages]);
375
722
  const onSelectActiveItem = useCallback(
376
723
  (_, selectedItem) => {
724
+ setIsMcpSettingsOpen(false);
377
725
  setNewChatCreated(false);
378
726
  const newConvId = String(selectedItem);
379
727
  setConversationId((c_id) => {
@@ -394,7 +742,8 @@ const LightspeedChat = ({
394
742
  setFileContents,
395
743
  setDraftMessage,
396
744
  scrollToBottomRef,
397
- setCurrentConversationId
745
+ setCurrentConversationId,
746
+ setIsMcpSettingsOpen
398
747
  ]
399
748
  );
400
749
  const conversationFound = !!conversations.find(
@@ -420,6 +769,133 @@ const LightspeedChat = ({
420
769
  }
421
770
  };
422
771
  }) : [];
772
+ useLayoutEffect(() => {
773
+ if (welcomePrompts.length === 0) return undefined;
774
+ const el = contentScrollRef.current;
775
+ const sentinel = bottomSentinelRef.current;
776
+ if (!el) return undefined;
777
+ const scrollToBottom = () => {
778
+ if (sentinel && typeof sentinel.scrollIntoView === "function") {
779
+ sentinel.scrollIntoView({ block: "end", behavior: "auto" });
780
+ } else {
781
+ el.scrollTop = el.scrollHeight;
782
+ }
783
+ };
784
+ const rafId = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(() => scrollToBottom()) : null;
785
+ if (rafId === null) scrollToBottom();
786
+ const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => scrollToBottom()) : undefined;
787
+ resizeObserver?.observe(el);
788
+ return () => {
789
+ if (rafId !== null && typeof cancelAnimationFrame !== "undefined") {
790
+ cancelAnimationFrame(rafId);
791
+ }
792
+ resizeObserver?.disconnect();
793
+ };
794
+ }, [welcomePrompts.length]);
795
+ useEffect(() => {
796
+ const scrollContainer = contentScrollRef.current;
797
+ if (!scrollContainer) {
798
+ setHasChatContentOverflow(false);
799
+ return undefined;
800
+ }
801
+ const getMessageBox = () => scrollContainer.querySelector(
802
+ ".pf-chatbot__messagebox"
803
+ );
804
+ const messageBoxOwnsScroll = (messageBox) => {
805
+ if (!messageBox || typeof window === "undefined") {
806
+ return false;
807
+ }
808
+ const overflowY = window.getComputedStyle(messageBox).overflowY;
809
+ return overflowY === "auto" || overflowY === "scroll" || overflowY === "overlay";
810
+ };
811
+ const getScrollTarget = () => {
812
+ const messageBox = getMessageBox();
813
+ return messageBoxOwnsScroll(messageBox) ? messageBox : scrollContainer;
814
+ };
815
+ let observedScrollTarget = getScrollTarget();
816
+ let rafId = null;
817
+ let updateScheduled = false;
818
+ const updateOverflow = () => {
819
+ const scrollTarget = observedScrollTarget ?? scrollContainer;
820
+ setHasChatContentOverflow(
821
+ scrollTarget.scrollHeight > scrollTarget.clientHeight + 1
822
+ );
823
+ };
824
+ const scheduleOverflowUpdate = () => {
825
+ if (updateScheduled) {
826
+ return;
827
+ }
828
+ updateScheduled = true;
829
+ if (typeof requestAnimationFrame !== "undefined") {
830
+ rafId = requestAnimationFrame(() => {
831
+ updateScheduled = false;
832
+ updateOverflow();
833
+ });
834
+ } else {
835
+ updateScheduled = false;
836
+ updateOverflow();
837
+ }
838
+ };
839
+ scheduleOverflowUpdate();
840
+ scrollContainer.addEventListener("scroll", scheduleOverflowUpdate, {
841
+ passive: true,
842
+ capture: true
843
+ });
844
+ const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => scheduleOverflowUpdate()) : undefined;
845
+ resizeObserver?.observe(scrollContainer);
846
+ if (observedScrollTarget !== scrollContainer) {
847
+ resizeObserver?.observe(observedScrollTarget);
848
+ }
849
+ const syncObservedScrollTarget = () => {
850
+ const nextScrollTarget = getScrollTarget();
851
+ if (nextScrollTarget === observedScrollTarget) {
852
+ return;
853
+ }
854
+ if (observedScrollTarget && observedScrollTarget !== scrollContainer) {
855
+ resizeObserver?.unobserve(observedScrollTarget);
856
+ }
857
+ if (nextScrollTarget !== scrollContainer) {
858
+ resizeObserver?.observe(nextScrollTarget);
859
+ }
860
+ observedScrollTarget = nextScrollTarget;
861
+ };
862
+ const mutationObserver = typeof MutationObserver !== "undefined" ? new MutationObserver(() => {
863
+ syncObservedScrollTarget();
864
+ scheduleOverflowUpdate();
865
+ }) : undefined;
866
+ mutationObserver?.observe(scrollContainer, {
867
+ childList: true,
868
+ subtree: true,
869
+ characterData: true
870
+ });
871
+ if (typeof window !== "undefined") {
872
+ window.addEventListener("resize", updateOverflow);
873
+ }
874
+ return () => {
875
+ if (rafId !== null && typeof cancelAnimationFrame !== "undefined") {
876
+ cancelAnimationFrame(rafId);
877
+ }
878
+ scrollContainer.removeEventListener(
879
+ "scroll",
880
+ scheduleOverflowUpdate,
881
+ true
882
+ );
883
+ if (observedScrollTarget && observedScrollTarget !== scrollContainer) {
884
+ resizeObserver?.unobserve(observedScrollTarget);
885
+ }
886
+ resizeObserver?.disconnect();
887
+ mutationObserver?.disconnect();
888
+ if (typeof window !== "undefined") {
889
+ window.removeEventListener("resize", updateOverflow);
890
+ }
891
+ };
892
+ }, [
893
+ conversationId,
894
+ displayMode,
895
+ isMcpSettingsOpen,
896
+ messages.length,
897
+ welcomePrompts.length
898
+ ]);
423
899
  const handleFilter = useCallback((value) => {
424
900
  setFilterValue(value);
425
901
  }, []);
@@ -491,12 +967,31 @@ const LightspeedChat = ({
491
967
  classes.sortDropdown
492
968
  ]
493
969
  );
970
+ const getDocumentsCount = (documentIds) => {
971
+ return Array.isArray(documentIds) ? documentIds.length : 0;
972
+ };
494
973
  const handleAttach = (data, event) => {
495
974
  if ("preventDefault" in event && typeof event.preventDefault === "function") {
496
975
  event.preventDefault();
497
976
  }
498
977
  handleFileUpload(data);
499
978
  };
979
+ const { mutate: stopConversation } = useStopConversation();
980
+ const handleStopButton = () => {
981
+ wasStoppedByUserRef.current = true;
982
+ if (requestId) {
983
+ stopConversation(requestId);
984
+ setRequestId("");
985
+ }
986
+ setIsSendButtonDisabled(false);
987
+ setAnnouncement(t("conversation.announcement.responseStopped"));
988
+ const lastUserMessage = [...conversationMessages].reverse().find((m) => m.role === "user");
989
+ const restoredPrompt = lastUserMessage?.content ?? "";
990
+ setDraftMessage(restoredPrompt.trim());
991
+ if (restoredPrompt) setMessageBarKey((k) => k + 1);
992
+ setFileContents([]);
993
+ setUploadError({ message: null });
994
+ };
500
995
  const handleDraftMessage = (_e, value) => setDraftMessage(value);
501
996
  const onAttachRejected = (data) => {
502
997
  data.forEach((attachment) => {
@@ -511,7 +1006,141 @@ const LightspeedChat = ({
511
1006
  }
512
1007
  });
513
1008
  };
1009
+ const chatMainContent = /* @__PURE__ */ jsxs(Fragment, { children: [
1010
+ /* @__PURE__ */ jsx(
1011
+ ChatbotContent,
1012
+ {
1013
+ className: `${classes.chatbotContent} ${hasChatContentOverflow ? classes.chatbotContentHasOverflow : ""}`,
1014
+ children: /* @__PURE__ */ jsxs("div", { ref: contentScrollRef, className: classes.chatbotContentScroll, children: [
1015
+ welcomePrompts.length > 0 && /* @__PURE__ */ jsx("div", { className: classes.chatbotContentSpacer, "aria-hidden": true }),
1016
+ /* @__PURE__ */ jsx(
1017
+ LightspeedChatBox,
1018
+ {
1019
+ userName,
1020
+ messages,
1021
+ profileLoading,
1022
+ announcement,
1023
+ ref: scrollToBottomRef,
1024
+ welcomePrompts,
1025
+ conversationId,
1026
+ isStreaming: isSendButtonDisabled,
1027
+ topicRestrictionEnabled,
1028
+ displayMode
1029
+ }
1030
+ ),
1031
+ welcomePrompts.length > 0 && /* @__PURE__ */ jsx(
1032
+ "div",
1033
+ {
1034
+ ref: bottomSentinelRef,
1035
+ "aria-hidden": true,
1036
+ style: { height: 0, flexShrink: 0 }
1037
+ }
1038
+ )
1039
+ ] })
1040
+ }
1041
+ ),
1042
+ /* @__PURE__ */ jsxs(ChatbotFooter, { className: classes.footer, children: [
1043
+ /* @__PURE__ */ jsx(FilePreview, {}),
1044
+ /* @__PURE__ */ jsx(
1045
+ MessageBar,
1046
+ {
1047
+ onSendMessage: sendMessage,
1048
+ isSendButtonDisabled,
1049
+ hasAttachButton: true,
1050
+ handleAttach,
1051
+ hasMicrophoneButton: true,
1052
+ value: draftMessage,
1053
+ onChange: handleDraftMessage,
1054
+ hasStopButton: isSendButtonDisabled,
1055
+ handleStopButton: isSendButtonDisabled ? handleStopButton : undefined,
1056
+ buttonProps: {
1057
+ attach: {
1058
+ inputTestId: "attachment-input",
1059
+ tooltipContent: t("tooltip.attach")
1060
+ },
1061
+ microphone: {
1062
+ tooltipContent: {
1063
+ active: t("tooltip.microphone.active"),
1064
+ inactive: t("tooltip.microphone.inactive")
1065
+ }
1066
+ },
1067
+ send: {
1068
+ tooltipContent: t("tooltip.send")
1069
+ }
1070
+ },
1071
+ allowedFileTypes: supportedFileTypes,
1072
+ onAttachRejected,
1073
+ placeholder: t("chatbox.message.placeholder")
1074
+ },
1075
+ messageBarKey
1076
+ ),
1077
+ /* @__PURE__ */ jsx(ChatbotFootnote, { ...getFootnoteProps(t) })
1078
+ ] })
1079
+ ] });
1080
+ const mcpSettingsPanel = /* @__PURE__ */ jsx(
1081
+ McpServersSettings,
1082
+ {
1083
+ onClose: () => setIsMcpSettingsOpen(false),
1084
+ backgroundColor: chatHeaderBgColor
1085
+ }
1086
+ );
1087
+ const mainPanelContent = (() => {
1088
+ if (!isMcpSettingsOpen) {
1089
+ return /* @__PURE__ */ jsx(Fragment, { children: chatMainContent });
1090
+ }
1091
+ if (isFullscreenMode) {
1092
+ return /* @__PURE__ */ jsxs("div", { className: classes.mcpFullscreenLayout, children: [
1093
+ /* @__PURE__ */ jsx("div", { className: classes.mcpChatPane, children: chatMainContent }),
1094
+ /* @__PURE__ */ jsx("div", { className: classes.mcpSettingsPane, children: mcpSettingsPanel })
1095
+ ] });
1096
+ }
1097
+ return /* @__PURE__ */ jsx(
1098
+ Settings,
1099
+ {
1100
+ className: classes.settingsFlat,
1101
+ fields: [
1102
+ {
1103
+ id: "mcp-servers-settings",
1104
+ label: "",
1105
+ field: mcpSettingsPanel
1106
+ }
1107
+ ]
1108
+ }
1109
+ );
1110
+ })();
1111
+ let drawerPanelStyle;
1112
+ if (!isFullscreenMode) {
1113
+ drawerPanelStyle = { zIndex: 1300 };
1114
+ } else if (isMcpSettingsOpen) {
1115
+ drawerPanelStyle = { width: 320, minWidth: 320, maxWidth: 320 };
1116
+ }
514
1117
  return /* @__PURE__ */ jsxs(Fragment, { children: [
1118
+ notebookAlerts.length > 0 && /* @__PURE__ */ jsx(
1119
+ AlertGroup,
1120
+ {
1121
+ hasAnimations: true,
1122
+ isToast: true,
1123
+ isLiveRegion: true,
1124
+ className: classes.toastAlertGroup,
1125
+ children: notebookAlerts.map(({ key, title, variant }) => /* @__PURE__ */ jsx(
1126
+ Alert,
1127
+ {
1128
+ variant: AlertVariant[variant ?? "success"],
1129
+ title,
1130
+ className: classes.toastAlert,
1131
+ actionClose: /* @__PURE__ */ jsx(
1132
+ AlertActionCloseButton,
1133
+ {
1134
+ title,
1135
+ variantLabel: `${variant ?? "success"} alert`,
1136
+ onClose: () => handleRemoveNotebookAlert(key)
1137
+ }
1138
+ )
1139
+ },
1140
+ key
1141
+ ))
1142
+ }
1143
+ ),
515
1144
  isDeleteModalOpen && /* @__PURE__ */ jsx(
516
1145
  DeleteModal,
517
1146
  {
@@ -529,11 +1158,30 @@ const LightspeedChat = ({
529
1158
  conversationId: targetConversationId
530
1159
  }
531
1160
  ),
1161
+ renameNotebookId && /* @__PURE__ */ jsx(
1162
+ RenameNotebookModal,
1163
+ {
1164
+ isOpen: Boolean(renameNotebookId),
1165
+ onClose: () => setRenameNotebookId(null),
1166
+ sessionId: renameNotebookId,
1167
+ currentName: notebooks.find((n) => n.session_id === renameNotebookId)?.name ?? ""
1168
+ }
1169
+ ),
1170
+ deleteNotebookId && /* @__PURE__ */ jsx(
1171
+ DeleteNotebookModal,
1172
+ {
1173
+ isOpen: Boolean(deleteNotebookId),
1174
+ onClose: () => setDeleteNotebookId(null),
1175
+ onDeleted: handleNotebookDeleted,
1176
+ sessionId: deleteNotebookId,
1177
+ name: notebooks.find((n) => n.session_id === deleteNotebookId)?.name ?? ""
1178
+ }
1179
+ ),
532
1180
  /* @__PURE__ */ jsxs(
533
1181
  Chatbot,
534
1182
  {
535
1183
  displayMode: ChatbotDisplayMode.embedded,
536
- className: classes.body,
1184
+ className: `${classes.body} ${isMcpSettingsOpen && !isChatHistoryDrawerOpen ? classes.mcpCollapsedDrawerOrderFix : ""}`,
537
1185
  children: [
538
1186
  /* @__PURE__ */ jsxs(ChatbotHeader, { className: classes.header, children: [
539
1187
  /* @__PURE__ */ jsxs(ChatbotHeaderMain, { children: [
@@ -541,7 +1189,7 @@ const LightspeedChat = ({
541
1189
  ChatbotHeaderMenu,
542
1190
  {
543
1191
  "aria-expanded": isChatHistoryDrawerOpen,
544
- onMenuToggle: () => setIsChatHistoryDrawerOpen(!isChatHistoryDrawerOpen),
1192
+ onMenuToggle: onChatHistoryDrawerToggle,
545
1193
  className: classes.headerMenu,
546
1194
  tooltipContent: t("tooltip.chatHistoryMenu"),
547
1195
  "aria-label": t("aria.chatHistoryMenu")
@@ -554,6 +1202,7 @@ const LightspeedChat = ({
554
1202
  {
555
1203
  selectedModel,
556
1204
  handleSelectedModel: (item) => {
1205
+ setIsMcpSettingsOpen(false);
557
1206
  onNewChat();
558
1207
  handleSelectedModel(item);
559
1208
  },
@@ -562,18 +1211,34 @@ const LightspeedChat = ({
562
1211
  isModelSelectorDisabled: isSendButtonDisabled,
563
1212
  setDisplayMode,
564
1213
  displayMode,
565
- onPinnedChatsToggle: handlePinningChatsToggle
1214
+ onPinnedChatsToggle: handlePinningChatsToggle,
1215
+ onMcpSettingsClick: () => setIsMcpSettingsOpen(true)
566
1216
  }
567
1217
  )
568
1218
  ] }),
569
- /* @__PURE__ */ jsx(Divider, {}),
570
- /* @__PURE__ */ jsx(
1219
+ isFullscreenMode && /* @__PURE__ */ jsxs(Fragment, { children: [
1220
+ /* @__PURE__ */ jsxs(
1221
+ Tabs,
1222
+ {
1223
+ activeKey: activeTab,
1224
+ onSelect: handleNotebookTabSelect,
1225
+ "aria-label": t("tabs.ariaLabel"),
1226
+ className: classes.tabs,
1227
+ children: [
1228
+ /* @__PURE__ */ jsx(Tab, { eventKey: 0, title: t("tabs.chat") }),
1229
+ /* @__PURE__ */ jsx(Tab, { eventKey: 1, title: t("tabs.notebooks") })
1230
+ ]
1231
+ }
1232
+ ),
1233
+ /* @__PURE__ */ jsx("div", { className: classes.tabsDivider })
1234
+ ] }),
1235
+ showChatPanel && /* @__PURE__ */ jsx(
571
1236
  ChatbotConversationHistoryNav,
572
1237
  {
573
1238
  drawerPanelContentProps: {
574
1239
  isResizable: isFullscreenMode,
575
1240
  hasNoBorder: !isFullscreenMode,
576
- style: isFullscreenMode ? undefined : { zIndex: 1300 }
1241
+ style: drawerPanelStyle
577
1242
  },
578
1243
  reverseButtonOrder: true,
579
1244
  displayMode: ChatbotDisplayMode.embedded,
@@ -628,59 +1293,42 @@ const LightspeedChat = ({
628
1293
  children: uploadError.message
629
1294
  }
630
1295
  ) }),
631
- /* @__PURE__ */ jsx(ChatbotContent, { children: /* @__PURE__ */ jsx(
632
- LightspeedChatBox,
633
- {
634
- userName,
635
- messages,
636
- profileLoading,
637
- announcement,
638
- ref: scrollToBottomRef,
639
- welcomePrompts,
640
- conversationId,
641
- isStreaming: isSendButtonDisabled,
642
- topicRestrictionEnabled,
643
- displayMode
644
- }
645
- ) }),
646
- /* @__PURE__ */ jsxs(ChatbotFooter, { className: classes.footer, children: [
647
- /* @__PURE__ */ jsx(FilePreview, {}),
648
- /* @__PURE__ */ jsx(
649
- MessageBar,
650
- {
651
- onSendMessage: sendMessage,
652
- isSendButtonDisabled,
653
- hasAttachButton: true,
654
- handleAttach,
655
- hasMicrophoneButton: true,
656
- value: draftMessage,
657
- onChange: handleDraftMessage,
658
- buttonProps: {
659
- attach: {
660
- inputTestId: "attachment-input",
661
- tooltipContent: t("tooltip.attach")
662
- },
663
- microphone: {
664
- tooltipContent: {
665
- active: t("tooltip.microphone.active"),
666
- inactive: t("tooltip.microphone.inactive")
667
- }
668
- },
669
- send: {
670
- tooltipContent: t("tooltip.send")
671
- }
672
- },
673
- allowedFileTypes: supportedFileTypes,
674
- onAttachRejected,
675
- placeholder: t("chatbox.message.placeholder")
676
- }
677
- ),
678
- /* @__PURE__ */ jsx(ChatbotFootnote, { ...getFootnoteProps(t) })
679
- ] })
1296
+ mainPanelContent
680
1297
  ]
681
1298
  }
682
1299
  )
683
1300
  }
1301
+ ),
1302
+ showNotebooksPanel && !notebooksPermissionLoading && hasNotebooksAccess && /* @__PURE__ */ jsx(
1303
+ NotebooksTab,
1304
+ {
1305
+ notebooks,
1306
+ hasNotebooks,
1307
+ classes,
1308
+ openNotebookMenuId,
1309
+ setOpenNotebookMenuId,
1310
+ onRename: setRenameNotebookId,
1311
+ onDelete: setDeleteNotebookId,
1312
+ t,
1313
+ getDocumentsCount
1314
+ }
1315
+ ),
1316
+ showNotebooksPanel && !notebooksPermissionLoading && !hasNotebooksAccess && /* @__PURE__ */ jsx(
1317
+ PermissionRequiredState,
1318
+ {
1319
+ subject: t("permission.subject.notebooks"),
1320
+ permissions: ["lightspeed.notebooks.use"],
1321
+ action: /* @__PURE__ */ jsx(
1322
+ Button,
1323
+ {
1324
+ variant: "outlined",
1325
+ color: "primary",
1326
+ style: { borderRadius: "20px" },
1327
+ onClick: () => setActiveTab(0),
1328
+ children: t("permission.notebooks.goBack")
1329
+ }
1330
+ )
1331
+ }
684
1332
  )
685
1333
  ]
686
1334
  }