@red-hat-developer-hub/backstage-plugin-intelligent-assistant 4.0.0 → 4.2.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 (57) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +23 -3
  3. package/config.schema.json +117 -0
  4. package/dist/api/NotebooksApiClient.esm.js +3 -2
  5. package/dist/api/NotebooksApiClient.esm.js.map +1 -1
  6. package/dist/api/notebooksApi.esm.js.map +1 -1
  7. package/dist/components/LightSpeedChat.esm.js +280 -118
  8. package/dist/components/LightSpeedChat.esm.js.map +1 -1
  9. package/dist/components/LightspeedDrawerContext.esm.js.map +1 -1
  10. package/dist/components/LightspeedDrawerProvider.esm.js +5 -4
  11. package/dist/components/LightspeedDrawerProvider.esm.js.map +1 -1
  12. package/dist/components/ToastAlertGroup.esm.js +56 -0
  13. package/dist/components/ToastAlertGroup.esm.js.map +1 -0
  14. package/dist/components/notebooks/AddDocumentModal.esm.js +165 -144
  15. package/dist/components/notebooks/AddDocumentModal.esm.js.map +1 -1
  16. package/dist/components/notebooks/DeleteDocumentModal.esm.js +73 -38
  17. package/dist/components/notebooks/DeleteDocumentModal.esm.js.map +1 -1
  18. package/dist/components/notebooks/DeleteNotebookModal.esm.js +80 -40
  19. package/dist/components/notebooks/DeleteNotebookModal.esm.js.map +1 -1
  20. package/dist/components/notebooks/NotebookHeaderActions.esm.js +78 -0
  21. package/dist/components/notebooks/NotebookHeaderActions.esm.js.map +1 -0
  22. package/dist/components/notebooks/NotebookStreamProvider.esm.js +47 -0
  23. package/dist/components/notebooks/NotebookStreamProvider.esm.js.map +1 -0
  24. package/dist/components/notebooks/NotebookView.esm.js +284 -349
  25. package/dist/components/notebooks/NotebookView.esm.js.map +1 -1
  26. package/dist/components/notebooks/NotebooksTab.esm.js +2 -2
  27. package/dist/components/notebooks/NotebooksTab.esm.js.map +1 -1
  28. package/dist/components/notebooks/OverwriteConfirmModal.esm.js +126 -82
  29. package/dist/components/notebooks/OverwriteConfirmModal.esm.js.map +1 -1
  30. package/dist/components/notebooks/SidebarCollapseIcon.esm.js +8 -6
  31. package/dist/components/notebooks/SidebarCollapseIcon.esm.js.map +1 -1
  32. package/dist/components/notebooks/UploadResourceScreen.esm.js +1 -0
  33. package/dist/components/notebooks/UploadResourceScreen.esm.js.map +1 -1
  34. package/dist/components/notebooks/notebookDialogStyles.esm.js +40 -0
  35. package/dist/components/notebooks/notebookDialogStyles.esm.js.map +1 -0
  36. package/dist/components/notebooks/notebookStreamStore.esm.js +282 -0
  37. package/dist/components/notebooks/notebookStreamStore.esm.js.map +1 -0
  38. package/dist/hooks/notebooks/useCreateNotebookMessage.esm.js +3 -2
  39. package/dist/hooks/notebooks/useCreateNotebookMessage.esm.js.map +1 -1
  40. package/dist/hooks/useConversationMessages.esm.js +31 -108
  41. package/dist/hooks/useConversationMessages.esm.js.map +1 -1
  42. package/dist/hooks/useLightspeedProviderState.esm.js +14 -5
  43. package/dist/hooks/useLightspeedProviderState.esm.js.map +1 -1
  44. package/dist/index.esm.js +2 -2
  45. package/dist/index.esm.js.map +1 -1
  46. package/dist/utils/dom-extractor.esm.js +816 -0
  47. package/dist/utils/dom-extractor.esm.js.map +1 -0
  48. package/dist/utils/dom-selectors.esm.js +91 -0
  49. package/dist/utils/dom-selectors.esm.js.map +1 -0
  50. package/dist/utils/scoped-dialog-utils.esm.js +35 -0
  51. package/dist/utils/scoped-dialog-utils.esm.js.map +1 -0
  52. package/dist/utils/sensitive-data-redactor.esm.js +66 -0
  53. package/dist/utils/sensitive-data-redactor.esm.js.map +1 -0
  54. package/dist/utils/stream-event-helpers.esm.js +105 -0
  55. package/dist/utils/stream-event-helpers.esm.js.map +1 -0
  56. package/package.json +14 -14
  57. package/config.d.ts +0 -99
@@ -2,12 +2,12 @@ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
2
  import { useState, useEffect, useRef, useLayoutEffect, useCallback, useMemo } from 'react';
3
3
  import { useNavigate, useMatch, useLocation } from 'react-router-dom';
4
4
  import { useApi, configApiRef } from '@backstage/core-plugin-api';
5
- import { makeStyles, Button } from '@material-ui/core';
5
+ import { makeStyles, Button as Button$1 } from '@material-ui/core';
6
6
  import Tab from '@mui/material/Tab';
7
7
  import Tabs from '@mui/material/Tabs';
8
- import { ChatbotDisplayMode, ChatbotContent, ChatbotFooter, MessageBar, Settings, Chatbot, ChatbotHeader, ChatbotHeaderMain, ChatbotHeaderMenu, ChatbotHeaderTitle, FileDropZone, ChatbotAlert } from '@patternfly/chatbot';
8
+ import { ChatbotDisplayMode, ChatbotContent, ChatbotFooter, MessageBar, Settings, Chatbot, ChatbotHeader, ChatbotHeaderMain, ChatbotHeaderTitle, FileDropZone, ChatbotAlert } from '@patternfly/chatbot';
9
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';
10
+ import { DropdownItem, Tooltip, MenuToggle, Select, SelectList, SelectOption, Button, Title, Label } from '@patternfly/react-core';
11
11
  import { PenIcon, ThumbtackIcon, TrashIcon, SortAmountDownAltIcon, SortAmountDownIcon, PlusIcon, SearchIcon } from '@patternfly/react-icons';
12
12
  import { RhUiAiExperienceIcon } from '@patternfly/react-icons/dist/esm/icons/rh-ui-ai-experience-icon';
13
13
  import { useQueryClient } from '@tanstack/react-query';
@@ -16,7 +16,7 @@ import '../api/api.esm.js';
16
16
  import { useBackstageUserIdentity } from '../hooks/useBackstageUserIdentity.esm.js';
17
17
  import { useConversationMessages } from '../hooks/useConversationMessages.esm.js';
18
18
  import { useConversations } from '../hooks/useConversations.esm.js';
19
- import '../api/notebooksApi.esm.js';
19
+ import { useDeleteNotebook } from '../hooks/notebooks/useDeleteNotebook.esm.js';
20
20
  import { useIsMobile } from '../hooks/useIsMobile.esm.js';
21
21
  import { useLastOpenedConversation } from '../hooks/useLastOpenedConversation.esm.js';
22
22
  import { useLightspeedDeletePermission } from '../hooks/useLightspeedDeletePermission.esm.js';
@@ -28,6 +28,7 @@ import { useNotebookConversationIds } from '../hooks/useNotebookConversationIds.
28
28
  import { useNotebookSession } from '../hooks/notebooks/useNotebookSession.esm.js';
29
29
  import { useNotebookSessions } from '../hooks/notebooks/useNotebookSessions.esm.js';
30
30
  import { usePinnedChatsSettings } from '../hooks/usePinnedChatsSettings.esm.js';
31
+ import '../api/notebooksApi.esm.js';
31
32
  import { useRenameNotebookWithAlert } from '../hooks/notebooks/useRenameNotebookWithAlert.esm.js';
32
33
  import { useSortSettings } from '../hooks/useSortSettings.esm.js';
33
34
  import { useStopConversation } from '../hooks/useStopConversation.esm.js';
@@ -37,6 +38,7 @@ import { useLightspeedDrawerContext } from '../hooks/useLightspeedDrawerContext.
37
38
  import { useLightspeedUpdatePermission } from '../hooks/useLightspeedUpdatePermission.esm.js';
38
39
  import { useWelcomePrompts } from '../hooks/useWelcomePrompts.esm.js';
39
40
  import { getAttachments } from '../utils/attachment-utils.esm.js';
41
+ import { extractPageContext } from '../utils/dom-extractor.esm.js';
40
42
  import { getCategorizeMessages, ChatbotFootnoteWithIcon, getFootnoteProps } from '../utils/lightspeed-chatbox-utils.esm.js';
41
43
  import Attachment from './Attachment.esm.js';
42
44
  import { useFileAttachmentContext } from './AttachmentContext.esm.js';
@@ -48,10 +50,14 @@ import { LightspeedChatBoxHeader } from './LightspeedChatBoxHeader.esm.js';
48
50
  import { McpServersSettings } from './McpServersSettings.esm.js';
49
51
  import { MessageBarModelSelector } from './MessageBarModelSelector.esm.js';
50
52
  import { DeleteNotebookModal } from './notebooks/DeleteNotebookModal.esm.js';
53
+ import { NotebookHeaderActions } from './notebooks/NotebookHeaderActions.esm.js';
51
54
  import { NotebooksTab } from './notebooks/NotebooksTab.esm.js';
55
+ import { useNotebookStreamStore } from './notebooks/NotebookStreamProvider.esm.js';
52
56
  import { NotebookView } from './notebooks/NotebookView.esm.js';
57
+ import { SidebarCollapseIcon, SidebarExpandIcon } from './notebooks/SidebarCollapseIcon.esm.js';
53
58
  import PermissionRequiredState from './PermissionRequiredState.esm.js';
54
59
  import { RenameConversationModal } from './RenameConversationModal.esm.js';
60
+ import { ToastAlertGroup } from './ToastAlertGroup.esm.js';
55
61
 
56
62
  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
63
  const ConditionalWrapper = ({
@@ -61,8 +67,6 @@ const ConditionalWrapper = ({
61
67
  }) => condition ? wrapper(children) : children;
62
68
  const useStyles = makeStyles((theme) => ({
63
69
  body: {
64
- // remove default margin and padding from common elements
65
- // lists excluded for proper formatting
66
70
  "& h1, & h2, & h3, & h4, & h5, & h6, & p, & li": {
67
71
  margin: 0,
68
72
  padding: 0
@@ -77,6 +81,11 @@ const useStyles = makeStyles((theme) => ({
77
81
  overflow: "hidden"
78
82
  }
79
83
  },
84
+ bodyCompact: {
85
+ height: "100% !important",
86
+ minHeight: "0 !important",
87
+ overflow: "hidden"
88
+ },
80
89
  header: {
81
90
  padding: `${theme.spacing(3)}px ${theme.spacing(3)}px 0 ${theme.spacing(
82
91
  3
@@ -96,13 +105,24 @@ const useStyles = makeStyles((theme) => ({
96
105
  minWidth: 0,
97
106
  backgroundColor: "var(--pf-t--global--background--color--floating--default) !important"
98
107
  },
99
- headerMenu: {
100
- // align hamburger icon with title
101
- "& .pf-v6-c-button": {
102
- display: "flex",
103
- alignItems: "center"
108
+ chatHeaderActions: {
109
+ display: "flex",
110
+ alignItems: "center",
111
+ gap: theme.spacing(0.5)
112
+ },
113
+ compactDrawerPanel: {
114
+ "&.pf-v6-c-drawer__panel": {
115
+ width: "100%",
116
+ minWidth: "100%",
117
+ maxWidth: "100%",
118
+ flexBasis: "100%"
104
119
  }
105
120
  },
121
+ notebookHeaderActions: {
122
+ display: "flex",
123
+ alignItems: "center",
124
+ gap: theme.spacing(0.5)
125
+ },
106
126
  headerLogo: {
107
127
  width: 48,
108
128
  height: 48,
@@ -131,10 +151,14 @@ const useStyles = makeStyles((theme) => ({
131
151
  display: "flex",
132
152
  alignItems: "center",
133
153
  justifyContent: "space-between",
154
+ flexWrap: "wrap",
155
+ gap: theme.spacing(1),
134
156
  marginBottom: theme.spacing(4)
135
157
  },
136
158
  notebooksHeading: {
137
- marginBottom: 0
159
+ marginBottom: 0,
160
+ whiteSpace: "nowrap",
161
+ fontSize: "1.25rem"
138
162
  },
139
163
  notebooksHeadingEmpty: {
140
164
  "&&": {
@@ -190,6 +214,14 @@ const useStyles = makeStyles((theme) => ({
190
214
  gridTemplateColumns: "repeat(1, minmax(0, 1fr))"
191
215
  }
192
216
  },
217
+ notebooksGridCompact: {
218
+ display: "grid",
219
+ gridTemplateColumns: "repeat(auto-fill, minmax(280px, 1fr))",
220
+ gap: theme.spacing(2),
221
+ width: "100%",
222
+ maxWidth: "100%",
223
+ paddingBottom: theme.spacing(6)
224
+ },
193
225
  notebookCard: {
194
226
  borderRadius: theme.spacing(1.5),
195
227
  display: "flex",
@@ -333,18 +365,6 @@ const useStyles = makeStyles((theme) => ({
333
365
  chatbotContentScrollNewChat: {
334
366
  backgroundColor: "var(--pf-t--global--background--color--floating--default) !important"
335
367
  },
336
- toastAlertGroup: {
337
- "--pf-v6-c-alert-group--m-toast--InsetInlineEnd": `${theme.spacing(2.5)}px`,
338
- "--pf-v6-c-alert-group--m-toast--InsetBlockStart": `${theme.spacing(2.5)}px`,
339
- "--pf-v6-c-alert-group--m-toast--MaxWidth": "350px",
340
- "--pf-v6-c-alert-group--m-toast--ZIndex": "9999"
341
- },
342
- toastAlert: {
343
- maxWidth: "350px",
344
- "& .pf-v6-c-alert__title": {
345
- margin: 0
346
- }
347
- },
348
368
  // When present, pushes welcome content to bottom (zoom out). Scroll up to see important box (zoom in).
349
369
  chatbotContentSpacer: {
350
370
  flex: 1,
@@ -536,6 +556,15 @@ const LightspeedChat = ({
536
556
  const navigate = useNavigate();
537
557
  const configApi = useApi(configApiRef);
538
558
  const notebooksEnabled = configApi.getOptionalBoolean("intelligent-assistant.notebooks.enabled") ?? false;
559
+ const screenContextEnabled = configApi.getOptionalBoolean(
560
+ "intelligent-assistant.screen-context.enabled"
561
+ ) ?? false;
562
+ const domExtractionEnabled = configApi.getOptionalBoolean(
563
+ "intelligent-assistant.screen-context.dom-extraction.enabled"
564
+ ) ?? true;
565
+ const domExtractionMaxChars = configApi.getOptionalNumber(
566
+ "intelligent-assistant.screen-context.dom-extraction.maxChars"
567
+ ) ?? 8e3;
539
568
  const notebooksRouteMatch = useMatch(`${LIGHTSPEED_PATH}/notebooks`);
540
569
  const notebookViewRouteMatch = useMatch(
541
570
  `${LIGHTSPEED_PATH}/notebooks/:notebookId`
@@ -554,7 +583,9 @@ const LightspeedChat = ({
554
583
  setDraftMessage,
555
584
  consumePendingOverlayThreadHandoff,
556
585
  shellViewTab,
557
- setShellViewTab
586
+ setShellViewTab,
587
+ activeNotebookId,
588
+ setActiveNotebookId
558
589
  } = useLightspeedDrawerContext();
559
590
  const isFullscreenMode = displayMode === ChatbotDisplayMode.embedded;
560
591
  const location = useLocation();
@@ -563,9 +594,6 @@ const LightspeedChat = ({
563
594
  const [filterValue, setFilterValue] = useState("");
564
595
  const [announcement, setAnnouncement] = useState("");
565
596
  const [activeTab, setActiveTab] = useState(() => {
566
- if (!isFullscreenMode) {
567
- return 0;
568
- }
569
597
  if (notebooksRouteMatch || notebookViewRouteMatch) {
570
598
  return 1;
571
599
  }
@@ -591,29 +619,22 @@ const LightspeedChat = ({
591
619
  null
592
620
  );
593
621
  const [deleteNotebookId, setDeleteNotebookId] = useState(null);
594
- const [activeNotebook, setActiveNotebook] = useState(
595
- null
596
- );
597
- const {
598
- data: routeNotebook,
599
- isLoading: routeNotebookLoading,
600
- isError: routeNotebookError
601
- } = useNotebookSession(routeNotebookId);
622
+ const effectiveNotebookId = routeNotebookId ?? (!isFullscreenMode ? activeNotebookId : void 0);
623
+ const { data: activeNotebook, isError: activeNotebookError } = useNotebookSession(effectiveNotebookId);
602
624
  useEffect(() => {
603
- if (routeNotebookId && routeNotebook && !routeNotebookLoading) {
604
- setActiveNotebook(routeNotebook);
605
- } else if (routeNotebookId && routeNotebookError) {
606
- navigate(`${LIGHTSPEED_PATH}/notebooks`, { replace: true });
607
- } else if (!routeNotebookId && notebooksRouteMatch) {
608
- setActiveNotebook(null);
625
+ if (effectiveNotebookId && activeNotebookError) {
626
+ if (isFullscreenMode) {
627
+ navigate(`${LIGHTSPEED_PATH}/notebooks`, { replace: true });
628
+ } else {
629
+ setActiveNotebookId(void 0);
630
+ }
609
631
  }
610
632
  }, [
611
- routeNotebookId,
612
- routeNotebook,
613
- routeNotebookLoading,
614
- routeNotebookError,
615
- notebooksRouteMatch,
616
- navigate
633
+ effectiveNotebookId,
634
+ activeNotebookError,
635
+ isFullscreenMode,
636
+ navigate,
637
+ setActiveNotebookId
617
638
  ]);
618
639
  const [notebookAlerts, setNotebookAlerts] = useState(
619
640
  []
@@ -624,6 +645,11 @@ const LightspeedChat = ({
624
645
  getNotebookName: (sid) => notebooks.find((n) => n.session_id === sid)?.name ?? "notebook"
625
646
  });
626
647
  const { data: notebookDocuments = [], isFetching: isDocumentsFetching } = useNotebookDocuments(activeNotebook?.session_id);
648
+ const [notebookUploadsInProgress, setNotebookUploadsInProgress] = useState(false);
649
+ const { mutate: deleteNotebook } = useDeleteNotebook();
650
+ const notebookStreamStore = useNotebookStreamStore();
651
+ const [notebookSidebarCollapsed, setNotebookSidebarCollapsed] = useState(!isFullscreenMode);
652
+ const [notebookUploadModalOpen, setNotebookUploadModalOpen] = useState(false);
627
653
  const [conversationId, setConversationId] = useState("");
628
654
  const [requestId, setRequestId] = useState("");
629
655
  const [newChatCreated, setNewChatCreated] = useState(false);
@@ -640,7 +666,7 @@ const LightspeedChat = ({
640
666
  const [hasChatContentOverflow, setHasChatContentOverflow] = useState(false);
641
667
  const wasStoppedByUserRef = useRef(false);
642
668
  const { isReady, lastOpenedId, setLastOpenedId, clearLastOpenedId } = useLastOpenedConversation(user);
643
- const showChatPanel = !isFullscreenMode || activeTab === 0;
669
+ const showChatPanel = activeTab === 0;
644
670
  const showNotebooksPanel = (notebooksEnabled || isOnNotebookRoute) && activeTab !== 0;
645
671
  const [isChatHistoryDrawerOpen, setIsChatHistoryDrawerOpen] = useState(!isMobile && isFullscreenMode);
646
672
  useLayoutEffect(() => {
@@ -667,60 +693,119 @@ const LightspeedChat = ({
667
693
  navigate,
668
694
  setShellViewTab
669
695
  ]);
696
+ const maybeAutoDeleteScratchNotebook = useCallback(() => {
697
+ const nb = activeNotebook;
698
+ if (!nb) return;
699
+ const isUntitled = nb.name === UNTITLED_NOTEBOOK_NAME;
700
+ const isEmpty = notebookDocuments.length === 0;
701
+ const noUploads = !notebookUploadsInProgress;
702
+ const convId = nb.metadata?.conversation_id;
703
+ const noChat = !convId || convId === TEMP_CONVERSATION_ID;
704
+ if (isUntitled && isEmpty && noUploads && noChat) {
705
+ notebookStreamStore.clear(nb.session_id);
706
+ deleteNotebook(nb.session_id);
707
+ }
708
+ }, [
709
+ activeNotebook,
710
+ notebookDocuments,
711
+ notebookUploadsInProgress,
712
+ notebookStreamStore,
713
+ deleteNotebook
714
+ ]);
670
715
  const handleNotebookTabSelect = (_event, nextTab) => {
716
+ if (nextTab === 0) {
717
+ maybeAutoDeleteScratchNotebook();
718
+ }
671
719
  setActiveTab(nextTab);
672
720
  setShellViewTab(nextTab);
673
- if (nextTab === 1) {
674
- navigate(`${LIGHTSPEED_PATH}/notebooks`);
675
- if (notebooksPermissionResolved) {
676
- refetchNotebooks();
721
+ if (isFullscreenMode) {
722
+ if (nextTab === 1) {
723
+ navigate(
724
+ activeNotebookId ? `${LIGHTSPEED_PATH}/notebooks/${activeNotebookId}` : `${LIGHTSPEED_PATH}/notebooks`
725
+ );
726
+ } else {
727
+ navigate(
728
+ routeConversationId ? `${LIGHTSPEED_PATH}/conversation/${routeConversationId}` : LIGHTSPEED_PATH
729
+ );
677
730
  }
678
- } else {
679
- setActiveNotebook(null);
680
- navigate(
681
- routeConversationId ? `${LIGHTSPEED_PATH}/conversation/${routeConversationId}` : LIGHTSPEED_PATH
682
- );
731
+ }
732
+ if (nextTab === 1 && notebooksPermissionResolved) {
733
+ refetchNotebooks();
683
734
  }
684
735
  };
685
736
  const setDisplayModeFromHeader = useCallback(
686
737
  (mode) => {
687
738
  if (mode !== ChatbotDisplayMode.embedded) {
739
+ if (activeTab === 1) {
740
+ const notebookId = routeNotebookId || activeNotebookId;
741
+ if (notebookId) {
742
+ setActiveNotebookId(notebookId);
743
+ }
744
+ }
688
745
  setDisplayMode(mode);
689
746
  return;
690
747
  }
691
748
  if (activeTab === 1) {
692
- const sid = activeNotebook?.session_id;
693
749
  setDisplayMode(
694
750
  mode,
695
751
  void 0,
696
- sid ? { notebookSessionId: sid } : "notebooks"
752
+ activeNotebookId ? { notebookSessionId: activeNotebookId } : "notebooks"
697
753
  );
698
754
  } else {
699
755
  setDisplayMode(mode);
700
756
  }
701
757
  },
702
- [setDisplayMode, activeTab, activeNotebook?.session_id]
758
+ [
759
+ setDisplayMode,
760
+ activeTab,
761
+ routeNotebookId,
762
+ activeNotebookId,
763
+ setActiveNotebookId
764
+ ]
703
765
  );
704
766
  const handleCreateNotebook = useCallback(() => {
767
+ maybeAutoDeleteScratchNotebook();
705
768
  createNotebookMutation.mutate(
706
769
  { name: UNTITLED_NOTEBOOK_NAME },
707
770
  {
708
771
  onSuccess: (session) => {
709
- navigate(`${LIGHTSPEED_PATH}/notebooks/${session.session_id}`);
772
+ setActiveNotebookId(session.session_id);
773
+ if (isFullscreenMode) {
774
+ navigate(`${LIGHTSPEED_PATH}/notebooks/${session.session_id}`);
775
+ }
710
776
  }
711
777
  }
712
778
  );
713
- }, [createNotebookMutation, navigate]);
779
+ }, [
780
+ maybeAutoDeleteScratchNotebook,
781
+ createNotebookMutation,
782
+ isFullscreenMode,
783
+ navigate,
784
+ setActiveNotebookId
785
+ ]);
714
786
  const handleCloseNotebook = useCallback(() => {
715
- setActiveNotebook(null);
716
- navigate(`${LIGHTSPEED_PATH}/notebooks`);
717
- }, [navigate]);
787
+ maybeAutoDeleteScratchNotebook();
788
+ setActiveNotebookId(void 0);
789
+ if (isFullscreenMode) {
790
+ navigate(`${LIGHTSPEED_PATH}/notebooks`);
791
+ }
792
+ refetchNotebooks();
793
+ }, [
794
+ maybeAutoDeleteScratchNotebook,
795
+ isFullscreenMode,
796
+ navigate,
797
+ refetchNotebooks,
798
+ setActiveNotebookId
799
+ ]);
718
800
  const handleRemoveNotebookAlert = (key) => {
719
801
  setNotebookAlerts(
720
802
  (prevAlerts) => prevAlerts.filter((alert) => alert.key !== key)
721
803
  );
722
804
  };
723
805
  const handleNotebookDeleted = () => {
806
+ if (deleteNotebookId) {
807
+ notebookStreamStore.clear(deleteNotebookId);
808
+ }
724
809
  const key = Date.now();
725
810
  setNotebookAlerts((prevAlerts) => [
726
811
  { title: t("notebooks.delete.toast"), variant: "success", key },
@@ -927,7 +1012,23 @@ const LightspeedChat = ({
927
1012
  prompt: message.toString()
928
1013
  })
929
1014
  );
930
- handleInputPrompt(message.toString(), getAttachments(fileContents));
1015
+ const allAttachments = getAttachments(fileContents);
1016
+ if (screenContextEnabled && domExtractionEnabled) {
1017
+ try {
1018
+ const domContext = extractPageContext({
1019
+ maxChars: domExtractionMaxChars
1020
+ });
1021
+ if (domContext) {
1022
+ allAttachments.push({
1023
+ attachment_type: "configuration",
1024
+ content_type: "text/plain",
1025
+ content: domContext
1026
+ });
1027
+ }
1028
+ } catch {
1029
+ }
1030
+ }
1031
+ handleInputPrompt(message.toString(), allAttachments);
931
1032
  setIsSendButtonDisabled(true);
932
1033
  setFileContents([]);
933
1034
  setDraftMessage("");
@@ -1129,6 +1230,7 @@ const LightspeedChat = ({
1129
1230
  (_, selectedItem) => {
1130
1231
  if (!isFullscreenMode) {
1131
1232
  setIsMcpSettingsOpen(false);
1233
+ setIsChatHistoryDrawerOpen(false);
1132
1234
  }
1133
1235
  setNewChatCreated(false);
1134
1236
  const newConvId = String(selectedItem);
@@ -1551,32 +1653,11 @@ const LightspeedChat = ({
1551
1653
  drawerPanelStyle = { minWidth: 232, maxWidth: 400 };
1552
1654
  }
1553
1655
  return /* @__PURE__ */ jsxs(Fragment, { children: [
1554
- notebookAlerts.length > 0 && /* @__PURE__ */ jsx(
1555
- AlertGroup,
1656
+ /* @__PURE__ */ jsx(
1657
+ ToastAlertGroup,
1556
1658
  {
1557
- hasAnimations: true,
1558
- isToast: true,
1559
- isLiveRegion: true,
1560
- className: classes.toastAlertGroup,
1561
- children: notebookAlerts.map(({ key, title, variant }) => /* @__PURE__ */ jsx(
1562
- Alert,
1563
- {
1564
- variant: AlertVariant[variant ?? "success"],
1565
- title,
1566
- className: classes.toastAlert,
1567
- timeout: 2e3,
1568
- onTimeout: () => handleRemoveNotebookAlert(key),
1569
- actionClose: /* @__PURE__ */ jsx(
1570
- AlertActionCloseButton,
1571
- {
1572
- title,
1573
- variantLabel: `${variant ?? "success"} alert`,
1574
- onClose: () => handleRemoveNotebookAlert(key)
1575
- }
1576
- )
1577
- },
1578
- key
1579
- ))
1659
+ alerts: notebookAlerts,
1660
+ onRemoveAlert: handleRemoveNotebookAlert
1580
1661
  }
1581
1662
  ),
1582
1663
  isDeleteModalOpen && /* @__PURE__ */ jsx(
@@ -1604,25 +1685,75 @@ const LightspeedChat = ({
1604
1685
  onClose: () => setDeleteNotebookId(null),
1605
1686
  onDeleted: handleNotebookDeleted,
1606
1687
  sessionId: deleteNotebookId,
1607
- name: notebooks.find((n) => n.session_id === deleteNotebookId)?.name ?? ""
1688
+ name: notebooks.find((n) => n.session_id === deleteNotebookId)?.name ?? "",
1689
+ isCompact: !isFullscreenMode
1608
1690
  }
1609
1691
  ),
1610
1692
  /* @__PURE__ */ jsxs(
1611
1693
  Chatbot,
1612
1694
  {
1613
1695
  displayMode: ChatbotDisplayMode.embedded,
1614
- className: `${classes.body} ${isMcpSettingsOpen && !isChatHistoryDrawerOpen ? classes.mcpCollapsedDrawerOrderFix : ""}`,
1696
+ className: `${classes.body} ${!isFullscreenMode ? classes.bodyCompact : ""} ${isMcpSettingsOpen && !isChatHistoryDrawerOpen ? classes.mcpCollapsedDrawerOrderFix : ""}`,
1615
1697
  children: [
1616
1698
  /* @__PURE__ */ jsxs(ChatbotHeader, { className: classes.header, children: [
1617
1699
  /* @__PURE__ */ jsxs(ChatbotHeaderMain, { children: [
1618
- showChatPanel && !isFullscreenMode && /* @__PURE__ */ jsx(
1619
- ChatbotHeaderMenu,
1700
+ showChatPanel && !isFullscreenMode && /* @__PURE__ */ jsxs("div", { className: classes.chatHeaderActions, children: [
1701
+ /* @__PURE__ */ jsx(
1702
+ Tooltip,
1703
+ {
1704
+ content: isChatHistoryDrawerOpen ? t("tooltip.collapseHistoryPanel") : t("tooltip.expandHistoryPanel"),
1705
+ position: "bottom",
1706
+ children: /* @__PURE__ */ jsx(
1707
+ Button,
1708
+ {
1709
+ variant: "plain",
1710
+ onClick: onChatHistoryDrawerToggle,
1711
+ "aria-expanded": isChatHistoryDrawerOpen,
1712
+ "aria-label": t("aria.chatHistoryMenu"),
1713
+ size: "sm",
1714
+ children: isChatHistoryDrawerOpen ? /* @__PURE__ */ jsx(SidebarCollapseIcon, { size: 18 }) : /* @__PURE__ */ jsx(SidebarExpandIcon, { size: 18 })
1715
+ }
1716
+ )
1717
+ }
1718
+ ),
1719
+ !isChatHistoryDrawerOpen && /* @__PURE__ */ jsx(
1720
+ Tooltip,
1721
+ {
1722
+ content: t("tooltip.quickNewChat"),
1723
+ position: "bottom",
1724
+ children: /* @__PURE__ */ jsx(
1725
+ Button,
1726
+ {
1727
+ variant: "plain",
1728
+ onClick: onNewChat,
1729
+ isDisabled: newChatCreated,
1730
+ "aria-label": t("tooltip.quickNewChat"),
1731
+ size: "sm",
1732
+ children: /* @__PURE__ */ jsx(
1733
+ PenIcon,
1734
+ {
1735
+ style: {
1736
+ width: 18,
1737
+ height: 18,
1738
+ color: newChatCreated ? void 0 : "var(--pf-t--global--color--brand--default)"
1739
+ }
1740
+ }
1741
+ )
1742
+ }
1743
+ )
1744
+ }
1745
+ )
1746
+ ] }),
1747
+ !isFullscreenMode && showNotebooksPanel && activeNotebook && /* @__PURE__ */ jsx(
1748
+ NotebookHeaderActions,
1620
1749
  {
1621
- "aria-expanded": isChatHistoryDrawerOpen,
1622
- onMenuToggle: onChatHistoryDrawerToggle,
1623
- className: classes.headerMenu,
1624
- tooltipContent: t("tooltip.chatHistoryMenu"),
1625
- "aria-label": t("aria.chatHistoryMenu")
1750
+ className: classes.notebookHeaderActions,
1751
+ onClose: handleCloseNotebook,
1752
+ onOpenUploadModal: () => setNotebookUploadModalOpen(true),
1753
+ uploadsInProgress: notebookUploadsInProgress,
1754
+ uploadModalOpen: notebookUploadModalOpen,
1755
+ sidebarCollapsed: notebookSidebarCollapsed,
1756
+ onSidebarCollapsedChange: setNotebookSidebarCollapsed
1626
1757
  }
1627
1758
  ),
1628
1759
  isFullscreenMode && /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -1661,8 +1792,8 @@ const LightspeedChat = ({
1661
1792
  }
1662
1793
  )
1663
1794
  ] }),
1664
- isFullscreenMode && /* @__PURE__ */ jsx("div", { className: classes.headerDivider }),
1665
- isFullscreenMode && shouldShowTabs && /* @__PURE__ */ jsxs(
1795
+ (isFullscreenMode || shouldShowTabs) && /* @__PURE__ */ jsx("div", { className: classes.headerDivider }),
1796
+ shouldShowTabs && /* @__PURE__ */ jsxs(
1666
1797
  Tabs,
1667
1798
  {
1668
1799
  value: activeTab,
@@ -1769,7 +1900,10 @@ const LightspeedChat = ({
1769
1900
  drawerPanelContentProps: {
1770
1901
  isResizable: isFullscreenMode,
1771
1902
  hasNoBorder: !isFullscreenMode,
1772
- style: drawerPanelStyle
1903
+ style: drawerPanelStyle,
1904
+ ...!isFullscreenMode && isChatHistoryDrawerOpen && {
1905
+ className: classes.compactDrawerPanel
1906
+ }
1773
1907
  },
1774
1908
  reverseButtonOrder: true,
1775
1909
  displayMode: ChatbotDisplayMode.embedded,
@@ -1849,24 +1983,52 @@ const LightspeedChat = ({
1849
1983
  avatar,
1850
1984
  profileLoading,
1851
1985
  topicRestrictionEnabled,
1852
- onClose: handleCloseNotebook
1986
+ onClose: handleCloseNotebook,
1987
+ isCompact: !isFullscreenMode,
1988
+ sidebarCollapsed: notebookSidebarCollapsed,
1989
+ onSidebarCollapsedChange: setNotebookSidebarCollapsed,
1990
+ isUploadModalOpen: notebookUploadModalOpen,
1991
+ onUploadModalOpenChange: setNotebookUploadModalOpen,
1992
+ onUploadsInProgressChange: setNotebookUploadsInProgress
1853
1993
  }
1854
1994
  ),
1855
1995
  showNotebooksPanel && !notebooksPermissionLoading && hasNotebooksAccess && !activeNotebook && /* @__PURE__ */ jsx(
1856
- NotebooksTab,
1996
+ "div",
1857
1997
  {
1858
- notebooks,
1859
- hasNotebooks,
1860
- classes,
1861
- openNotebookMenuId,
1862
- setOpenNotebookMenuId,
1863
- onSelectNotebook: (notebook) => {
1864
- navigate(`${LIGHTSPEED_PATH}/notebooks/${notebook.session_id}`);
1998
+ style: {
1999
+ position: "relative",
2000
+ display: "flex",
2001
+ flexDirection: "column",
2002
+ flex: 1,
2003
+ minHeight: 0,
2004
+ overflow: "hidden"
1865
2005
  },
1866
- onRename: handleRenameNotebook,
1867
- onDelete: setDeleteNotebookId,
1868
- onCreateNotebook: handleCreateNotebook,
1869
- t
2006
+ children: /* @__PURE__ */ jsx(
2007
+ NotebooksTab,
2008
+ {
2009
+ notebooks,
2010
+ hasNotebooks,
2011
+ classes: isFullscreenMode ? classes : {
2012
+ ...classes,
2013
+ notebooksGrid: classes.notebooksGridCompact
2014
+ },
2015
+ openNotebookMenuId,
2016
+ setOpenNotebookMenuId,
2017
+ onSelectNotebook: (notebook) => {
2018
+ maybeAutoDeleteScratchNotebook();
2019
+ setActiveNotebookId(notebook.session_id);
2020
+ if (isFullscreenMode) {
2021
+ navigate(
2022
+ `${LIGHTSPEED_PATH}/notebooks/${notebook.session_id}`
2023
+ );
2024
+ }
2025
+ },
2026
+ onRename: handleRenameNotebook,
2027
+ onDelete: setDeleteNotebookId,
2028
+ onCreateNotebook: handleCreateNotebook,
2029
+ t
2030
+ }
2031
+ )
1870
2032
  }
1871
2033
  ),
1872
2034
  showNotebooksPanel && !notebooksPermissionLoading && !hasNotebooksAccess && /* @__PURE__ */ jsx(
@@ -1875,7 +2037,7 @@ const LightspeedChat = ({
1875
2037
  subject: t("permission.subject.notebooks"),
1876
2038
  permissions: [iaNotebooksUsePermissionName],
1877
2039
  action: /* @__PURE__ */ jsx(
1878
- Button,
2040
+ Button$1,
1879
2041
  {
1880
2042
  variant: "outlined",
1881
2043
  color: "primary",