@red-hat-developer-hub/backstage-plugin-intelligent-assistant 5.1.0 → 5.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 (63) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +26 -3
  3. package/dist/alpha.d.ts +37 -0
  4. package/dist/api/LightspeedApiClient.esm.js +57 -0
  5. package/dist/api/LightspeedApiClient.esm.js.map +1 -1
  6. package/dist/api/api.esm.js.map +1 -1
  7. package/dist/components/DeleteModal.esm.js +2 -0
  8. package/dist/components/DeleteModal.esm.js.map +1 -1
  9. package/dist/components/DeleteSavedPromptModal.esm.js +75 -0
  10. package/dist/components/DeleteSavedPromptModal.esm.js.map +1 -0
  11. package/dist/components/LightSpeedChat.esm.js +202 -107
  12. package/dist/components/LightSpeedChat.esm.js.map +1 -1
  13. package/dist/components/LightspeedChatBoxHeader.esm.js +29 -2
  14. package/dist/components/LightspeedChatBoxHeader.esm.js.map +1 -1
  15. package/dist/components/LightspeedDrawerContext.esm.js.map +1 -1
  16. package/dist/components/McpServersSettings.esm.js +9 -22
  17. package/dist/components/McpServersSettings.esm.js.map +1 -1
  18. package/dist/components/SavedPromptCard.esm.js +100 -0
  19. package/dist/components/SavedPromptCard.esm.js.map +1 -0
  20. package/dist/components/SavedPromptKebabMenu.esm.js +87 -0
  21. package/dist/components/SavedPromptKebabMenu.esm.js.map +1 -0
  22. package/dist/components/SavedPromptMenuItems.esm.js +52 -0
  23. package/dist/components/SavedPromptMenuItems.esm.js.map +1 -0
  24. package/dist/components/SavedPromptsEmptyState.esm.js +63 -0
  25. package/dist/components/SavedPromptsEmptyState.esm.js.map +1 -0
  26. package/dist/components/SavedPromptsList.esm.js +63 -0
  27. package/dist/components/SavedPromptsList.esm.js.map +1 -0
  28. package/dist/components/SavedPromptsSettings.esm.js +285 -0
  29. package/dist/components/SavedPromptsSettings.esm.js.map +1 -0
  30. package/dist/components/SettingsPanel.esm.js +135 -0
  31. package/dist/components/SettingsPanel.esm.js.map +1 -0
  32. package/dist/hooks/useConversationHistoryGroups.esm.js +71 -0
  33. package/dist/hooks/useConversationHistoryGroups.esm.js.map +1 -0
  34. package/dist/hooks/useFeedbackActions.esm.js.map +1 -1
  35. package/dist/hooks/useLightspeedProviderState.esm.js +19 -5
  36. package/dist/hooks/useLightspeedProviderState.esm.js.map +1 -1
  37. package/dist/hooks/useSavedPromptActions.esm.js +64 -0
  38. package/dist/hooks/useSavedPromptActions.esm.js.map +1 -0
  39. package/dist/hooks/useSavedPrompts.esm.js +75 -0
  40. package/dist/hooks/useSavedPrompts.esm.js.map +1 -0
  41. package/dist/hooks/useSavedPromptsSettings.esm.js +65 -0
  42. package/dist/hooks/useSavedPromptsSettings.esm.js.map +1 -0
  43. package/dist/hooks/useSettingsPanelUrlState.esm.js +95 -0
  44. package/dist/hooks/useSettingsPanelUrlState.esm.js.map +1 -0
  45. package/dist/hooks/useWelcomePrompts.esm.js +16 -5
  46. package/dist/hooks/useWelcomePrompts.esm.js.map +1 -1
  47. package/dist/translations/de.esm.js +40 -1
  48. package/dist/translations/de.esm.js.map +1 -1
  49. package/dist/translations/es.esm.js +40 -1
  50. package/dist/translations/es.esm.js.map +1 -1
  51. package/dist/translations/fr.esm.js +40 -1
  52. package/dist/translations/fr.esm.js.map +1 -1
  53. package/dist/translations/it.esm.js +40 -1
  54. package/dist/translations/it.esm.js.map +1 -1
  55. package/dist/translations/ja.esm.js +40 -1
  56. package/dist/translations/ja.esm.js.map +1 -1
  57. package/dist/translations/ref.esm.js +40 -2
  58. package/dist/translations/ref.esm.js.map +1 -1
  59. package/dist/utils/buildConversationHistoryGroups.esm.js +241 -0
  60. package/dist/utils/buildConversationHistoryGroups.esm.js.map +1 -0
  61. package/dist/utils/prompt-utils.esm.js +18 -1
  62. package/dist/utils/prompt-utils.esm.js.map +1 -1
  63. package/package.json +4 -14
@@ -8,7 +8,7 @@ import Tabs from '@mui/material/Tabs';
8
8
  import { Chatbot, ChatbotHeader, ChatbotHeaderTitle, ChatbotFooter, MessageBar, ChatbotContent, Settings, ChatbotDisplayMode, ChatbotHeaderMain, ChatbotAlert, FileDropZone } from '@patternfly/chatbot';
9
9
  import ChatbotConversationHistoryNav from '@patternfly/chatbot/dist/dynamic/ChatbotConversationHistoryNav';
10
10
  import { SelectList, DropdownItem, Tooltip, MenuToggle, Select, SelectOption, Button, Title, Label } from '@patternfly/react-core';
11
- import { PenIcon, ThumbtackIcon, TrashIcon, SearchIcon, SortAmountDownAltIcon, SortAmountDownIcon, PlusIcon } from '@patternfly/react-icons';
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';
14
14
  import { LIGHTSPEED_PATH, UNTITLED_NOTEBOOK_NAME, TEMP_CONVERSATION_ID, supportedFileTypes } from '../const.esm.js';
@@ -29,6 +29,11 @@ import { useNotebookConversationIds } from '../hooks/useNotebookConversationIds.
29
29
  import { useNotebookSession } from '../hooks/notebooks/useNotebookSession.esm.js';
30
30
  import { useNotebookSessions } from '../hooks/notebooks/useNotebookSessions.esm.js';
31
31
  import { usePinnedChatsSettings } from '../hooks/usePinnedChatsSettings.esm.js';
32
+ import { useSavedPromptsSettings } from '../hooks/useSavedPromptsSettings.esm.js';
33
+ import { useSavedPrompts } from '../hooks/useSavedPrompts.esm.js';
34
+ import { useSavedPromptActions } from '../hooks/useSavedPromptActions.esm.js';
35
+ import { useConversationHistoryGroups } from '../hooks/useConversationHistoryGroups.esm.js';
36
+ import { useSettingsPanelUrlState } from '../hooks/useSettingsPanelUrlState.esm.js';
32
37
  import '../api/notebooksApi.esm.js';
33
38
  import { useRenameNotebookWithAlert } from '../hooks/notebooks/useRenameNotebookWithAlert.esm.js';
34
39
  import { useSortSettings } from '../hooks/useSortSettings.esm.js';
@@ -38,16 +43,17 @@ import { useNotebookDocuments } from '../hooks/notebooks/useNotebookDocuments.es
38
43
  import { useLightspeedDrawerContext } from '../hooks/useLightspeedDrawerContext.esm.js';
39
44
  import { useWelcomePrompts } from '../hooks/useWelcomePrompts.esm.js';
40
45
  import { getAttachments } from '../utils/attachment-utils.esm.js';
46
+ import { isSavedPromptConversationId, SAVED_PROMPT_CONVERSATION_ID_PREFIX } from '../utils/buildConversationHistoryGroups.esm.js';
41
47
  import { extractPageContext } from '../utils/dom-extractor.esm.js';
42
48
  import { getCategorizeMessages, ChatbotFootnoteWithIcon, getFootnoteProps } from '../utils/lightspeed-chatbox-utils.esm.js';
43
49
  import Attachment from './Attachment.esm.js';
44
50
  import { useFileAttachmentContext } from './AttachmentContext.esm.js';
45
51
  import { CollapsedHistoryStrip } from './CollapsedHistoryStrip.esm.js';
46
52
  import { DeleteModal } from './DeleteModal.esm.js';
53
+ import { DeleteSavedPromptModal } from './DeleteSavedPromptModal.esm.js';
47
54
  import FilePreview from './FilePreview.esm.js';
48
55
  import { LightspeedChatBox } from './LightspeedChatBox.esm.js';
49
56
  import { LightspeedChatBoxHeader } from './LightspeedChatBoxHeader.esm.js';
50
- import { McpServersSettings } from './McpServersSettings.esm.js';
51
57
  import { MessageBarModelSelector } from './MessageBarModelSelector.esm.js';
52
58
  import { DeleteNotebookModal } from './notebooks/DeleteNotebookModal.esm.js';
53
59
  import { NotebookHeaderActions } from './notebooks/NotebookHeaderActions.esm.js';
@@ -56,6 +62,8 @@ import { useNotebookStreamStore } from './notebooks/NotebookStreamProvider.esm.j
56
62
  import { NotebookView } from './notebooks/NotebookView.esm.js';
57
63
  import { SidebarCollapseIcon, SidebarExpandIcon } from './notebooks/SidebarCollapseIcon.esm.js';
58
64
  import { RenameConversationModal } from './RenameConversationModal.esm.js';
65
+ import { SavedPromptMenuItems } from './SavedPromptMenuItems.esm.js';
66
+ import { SettingsPanel } from './SettingsPanel.esm.js';
59
67
  import { ToastAlertGroup } from './ToastAlertGroup.esm.js';
60
68
 
61
69
  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`;
@@ -81,6 +89,24 @@ const StyledChatbot = styled(Chatbot, {
81
89
  height: 0,
82
90
  overflow: "hidden"
83
91
  },
92
+ // Remove once @patternfly/chatbot supports ConversationGroup header actions:
93
+ // https://github.com/patternfly/chatbot/issues/904
94
+ "& .pf-chatbot__history-menu .pf-v6-c-menu__list": {
95
+ paddingInlineStart: 0
96
+ },
97
+ "& .pf-chatbot__menu-show-all-toggle": {
98
+ cursor: "pointer"
99
+ },
100
+ "& .pf-chatbot__menu-item-header--expandable.lightspeed-saved-prompts-group .pf-v6-c-button__text": {
101
+ width: "100%"
102
+ },
103
+ "& .lightspeed-saved-prompts-section-gear": {
104
+ opacity: 0,
105
+ transition: "opacity 0.15s ease-in-out"
106
+ },
107
+ "& .pf-chatbot__menu-item-header--expandable.lightspeed-saved-prompts-group:hover .lightspeed-saved-prompts-section-gear, & .pf-chatbot__menu-item-header--expandable.lightspeed-saved-prompts-group .lightspeed-saved-prompts-section-gear:focus-visible": {
108
+ opacity: 1
109
+ },
84
110
  "& .pf-chatbot-container": {
85
111
  minHeight: 0
86
112
  },
@@ -233,6 +259,19 @@ const StyledChatbotContent = styled(ChatbotContent, {
233
259
  overflowX: "hidden",
234
260
  overflowWrap: "break-word",
235
261
  wordBreak: "break-word"
262
+ },
263
+ // Remove once @patternfly/chatbot adds a responsive grid layout for prompt suggestions:
264
+ // https://github.com/patternfly/chatbot/issues/905
265
+ "& .pf-chatbot__prompt-suggestions": {
266
+ display: "grid !important",
267
+ flexDirection: "unset !important",
268
+ alignItems: "stretch",
269
+ gap: "var(--pf-t--global--spacer--lg)",
270
+ gridTemplateColumns: "repeat(auto-fit, minmax(min(100%, 12.5rem), 1fr))"
271
+ },
272
+ "& .pf-chatbot__prompt-suggestions > .pf-chatbot__prompt-suggestion": {
273
+ height: "100%",
274
+ minWidth: 0
236
275
  }
237
276
  }));
238
277
  const ContentScroll = styled("div", {
@@ -383,6 +422,15 @@ const FullscreenChatLayout = styled("div")({
383
422
  "--pf-v6-c-menu__item--PaddingInlineStart": "var(--pf-t--global--spacer--md)",
384
423
  "--pf-v6-c-menu__item--PaddingInlineEnd": "var(--pf-t--global--spacer--md)"
385
424
  },
425
+ "& .pf-chatbot__menu-item .pf-v6-c-menu__item-main, & .pf-chatbot__menu-item .pf-v5-c-menu__item-main": {
426
+ minWidth: 0,
427
+ overflow: "hidden"
428
+ },
429
+ "& .pf-chatbot__menu-item-text, & .pf-v6-c-menu__item-text, & .pf-v5-c-menu__item-text": {
430
+ overflow: "hidden",
431
+ textOverflow: "ellipsis",
432
+ whiteSpace: "nowrap"
433
+ },
386
434
  "& .pf-chatbot__menu-item .pf-v6-c-menu-toggle, & .pf-chatbot__menu-item .pf-v5-c-menu-toggle": {
387
435
  opacity: 0,
388
436
  transition: "opacity 0.15s ease-in-out"
@@ -434,9 +482,23 @@ const LightspeedChat = ({
434
482
  shellViewTab,
435
483
  setShellViewTab,
436
484
  activeNotebookId,
437
- setActiveNotebookId
485
+ setActiveNotebookId,
486
+ settingsTab: persistedSettingsTab,
487
+ setSettingsTab: setPersistedSettingsTab
438
488
  } = useLightspeedDrawerContext();
439
489
  const isFullscreenMode = displayMode === ChatbotDisplayMode.embedded;
490
+ const {
491
+ isOpen: isSettingsOpen,
492
+ activeTab: activeSettingsTab,
493
+ openSettings,
494
+ closeSettings,
495
+ setActiveTab: setSettingsTab
496
+ } = useSettingsPanelUrlState(
497
+ isFullscreenMode,
498
+ persistedSettingsTab,
499
+ setPersistedSettingsTab
500
+ );
501
+ const showCompactSettings = !isFullscreenMode && isSettingsOpen;
440
502
  const location = useLocation();
441
503
  const isNotebooksFullscreenPath = location.pathname === `${LIGHTSPEED_PATH}/notebooks` || location.pathname.startsWith(`${LIGHTSPEED_PATH}/notebooks/`);
442
504
  const user = useBackstageUserIdentity();
@@ -515,7 +577,6 @@ const LightspeedChat = ({
515
577
  const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
516
578
  const [isRenameModalOpen, setIsRenameModalOpen] = useState(false);
517
579
  const [isSortSelectOpen, setIsSortSelectOpen] = useState(false);
518
- const [isMcpSettingsOpen, setIsMcpSettingsOpen] = useState(false);
519
580
  const [chatHeaderBgColor, setChatHeaderBgColor] = useState();
520
581
  const contentScrollRef = useRef(null);
521
582
  const bottomSentinelRef = useRef(null);
@@ -736,12 +797,17 @@ const LightspeedChat = ({
736
797
  if (computedBg) {
737
798
  setChatHeaderBgColor(computedBg);
738
799
  }
739
- }, [displayMode, isMcpSettingsOpen]);
800
+ }, [displayMode, isSettingsOpen]);
740
801
  useEffect(() => {
741
- if (!mcpToolsPermissionResolved && isMcpSettingsOpen) {
742
- setIsMcpSettingsOpen(false);
802
+ if (!mcpToolsPermissionResolved && isSettingsOpen && activeSettingsTab === "mcp-servers") {
803
+ setSettingsTab("saved-prompts");
743
804
  }
744
- }, [mcpToolsPermissionResolved, isMcpSettingsOpen]);
805
+ }, [
806
+ mcpToolsPermissionResolved,
807
+ isSettingsOpen,
808
+ activeSettingsTab,
809
+ setSettingsTab
810
+ ]);
745
811
  const {
746
812
  isPinningChatsEnabled,
747
813
  pinnedChats,
@@ -749,6 +815,7 @@ const LightspeedChat = ({
749
815
  pinChat,
750
816
  unpinChat
751
817
  } = usePinnedChatsSettings(user);
818
+ const { isSavedPromptsEnabled, handleSavedPromptsToggle } = useSavedPromptsSettings(user);
752
819
  const { selectedSort, handleSortChange } = useSortSettings(user);
753
820
  const {
754
821
  uploadError,
@@ -803,7 +870,18 @@ const LightspeedChat = ({
803
870
  isLoading,
804
871
  isRefetching
805
872
  } = useConversations(chatPermissionResolved);
806
- const samplePrompts = useWelcomePrompts(chatPermissionResolved);
873
+ const {
874
+ savedPrompts,
875
+ config: savedPromptsConfig,
876
+ loading: savedPromptsLoading,
877
+ error: savedPromptsError,
878
+ createPrompt,
879
+ deletePrompt
880
+ } = useSavedPrompts();
881
+ const samplePrompts = useWelcomePrompts(
882
+ chatPermissionResolved,
883
+ isSavedPromptsEnabled ? savedPrompts : void 0
884
+ );
807
885
  useEffect(() => {
808
886
  if (!user || !isReady) return;
809
887
  const onOverlayLikeSurface = isFullscreenMode || !routeConversationId;
@@ -947,10 +1025,31 @@ const LightspeedChat = ({
947
1025
  setFileContents([]);
948
1026
  setDraftMessage("");
949
1027
  };
1028
+ const handleApplySavedPrompt = useCallback(
1029
+ (content) => {
1030
+ setDraftMessage(content);
1031
+ setMessageBarKey((k) => k + 1);
1032
+ },
1033
+ [setDraftMessage]
1034
+ );
1035
+ const {
1036
+ sendDirectly: sendSavedPromptDirectly,
1037
+ requestDelete: requestSavedPromptDelete,
1038
+ promptToDelete,
1039
+ closeDeleteModal: closeSavedPromptDeleteModal,
1040
+ confirmDelete: confirmSavedPromptDelete,
1041
+ isDeleting: isSavedPromptDeleting,
1042
+ deleteError: savedPromptDeleteError,
1043
+ isDeleteModalOpen: isSavedPromptDeleteModalOpen
1044
+ } = useSavedPromptActions({
1045
+ onApplyToInput: handleApplySavedPrompt,
1046
+ onSendDirectly: sendMessage,
1047
+ onDelete: deletePrompt
1048
+ });
950
1049
  const onNewChat = useCallback(() => {
951
1050
  (async () => {
952
1051
  if (!isFullscreenMode) {
953
- setIsMcpSettingsOpen(false);
1052
+ closeSettings();
954
1053
  }
955
1054
  if (conversationId !== TEMP_CONVERSATION_ID) {
956
1055
  setMessages([]);
@@ -974,7 +1073,8 @@ const LightspeedChat = ({
974
1073
  setUploadError,
975
1074
  setDraftMessage,
976
1075
  setCurrentConversationId,
977
- isFullscreenMode
1076
+ isFullscreenMode,
1077
+ closeSettings
978
1078
  ]);
979
1079
  const openDeleteModal = (conversation_id) => {
980
1080
  setTargetConversationId(conversation_id);
@@ -1064,76 +1164,47 @@ const LightspeedChat = ({
1064
1164
  selectedSort
1065
1165
  ]
1066
1166
  );
1067
- const filterConversations = useCallback(
1068
- (targetValue) => {
1069
- const pinnedChatsKey = t("conversation.category.pinnedChats") || "Pinned chats";
1070
- let isNoPinnedChatsSearchResults = false;
1071
- let isNoRecentChatsSearchResults = false;
1072
- const filteredConversations2 = Object.entries(categorizedMessages).reduce(
1073
- (acc, [key, items]) => {
1074
- const filteredItems = items.filter(
1075
- (item) => (item.text ?? "").toLocaleLowerCase("en-US").includes(targetValue.toLocaleLowerCase("en-US"))
1076
- );
1077
- const isPinnedCategory = key === pinnedChatsKey;
1078
- if (isPinnedCategory && isPinningChatsEnabled) {
1079
- if (filteredItems.length > 0) {
1080
- acc[pinnedChatsKey] = filteredItems;
1081
- } else {
1082
- isNoPinnedChatsSearchResults = categorizedMessages[pinnedChatsKey].length > 0;
1083
- acc[pinnedChatsKey] = [
1084
- {
1085
- id: isNoPinnedChatsSearchResults ? "no-pinned-chats-search-results" : "no-pinned-chats",
1086
- text: isNoPinnedChatsSearchResults ? t("common.noSearchResults") : t("chatbox.emptyState.noPinnedChats"),
1087
- noIcon: true,
1088
- additionalProps: {
1089
- isDisabled: true,
1090
- style: {
1091
- fontStyle: "italic",
1092
- opacity: 0.6
1093
- }
1094
- }
1095
- }
1096
- ];
1097
- }
1098
- } else if (!isPinnedCategory) {
1099
- if (filteredItems.length > 0) {
1100
- acc[key] = filteredItems;
1101
- } else {
1102
- isNoRecentChatsSearchResults = categorizedMessages[key].length > 0;
1103
- acc[key] = [
1104
- {
1105
- id: isNoRecentChatsSearchResults ? "no-recent-chats-search-results" : "no-recent-chats",
1106
- text: isNoRecentChatsSearchResults ? t("common.noSearchResults") : t("chatbox.emptyState.noRecentChats"),
1107
- noIcon: true,
1108
- additionalProps: {
1109
- isDisabled: true,
1110
- style: {
1111
- fontStyle: "italic",
1112
- opacity: 0.6
1113
- }
1114
- }
1115
- }
1116
- ];
1117
- }
1118
- }
1119
- return acc;
1120
- },
1121
- {}
1122
- );
1123
- if (isNoPinnedChatsSearchResults && isNoRecentChatsSearchResults) {
1124
- return {};
1167
+ const getSavedPromptMenuItems = useCallback(
1168
+ (prompt) => /* @__PURE__ */ jsx(
1169
+ SavedPromptMenuItems,
1170
+ {
1171
+ prompt,
1172
+ variant: "sidebar",
1173
+ onSendDirectly: sendSavedPromptDirectly,
1174
+ onDelete: requestSavedPromptDelete,
1175
+ isSendDirectlyDisabled: streamingUiMatchesView
1125
1176
  }
1126
- return filteredConversations2;
1127
- },
1128
- [categorizedMessages, isPinningChatsEnabled, t]
1177
+ ),
1178
+ [sendSavedPromptDirectly, requestSavedPromptDelete, streamingUiMatchesView]
1129
1179
  );
1180
+ const { conversationGroups, hasNoSearchResults } = useConversationHistoryGroups({
1181
+ savedPrompts,
1182
+ categorizedMessages,
1183
+ filterValue,
1184
+ isSavedPromptsEnabled,
1185
+ isPinningChatsEnabled,
1186
+ isSettingsOpen,
1187
+ activeSettingsTab,
1188
+ openSettings,
1189
+ getSavedPromptMenuItems
1190
+ });
1130
1191
  useEffect(() => {
1131
1192
  setMessages(conversationMessages);
1132
1193
  }, [conversationMessages]);
1133
1194
  const onSelectActiveItem = useCallback(
1134
1195
  (_, selectedItem) => {
1196
+ if (selectedItem !== void 0 && isSavedPromptConversationId(selectedItem)) {
1197
+ const promptId = String(selectedItem).slice(
1198
+ SAVED_PROMPT_CONVERSATION_ID_PREFIX.length
1199
+ );
1200
+ const prompt = savedPrompts.find(({ id }) => id === promptId);
1201
+ if (prompt) {
1202
+ handleApplySavedPrompt(prompt.content);
1203
+ }
1204
+ return;
1205
+ }
1135
1206
  if (!isFullscreenMode) {
1136
- setIsMcpSettingsOpen(false);
1207
+ closeSettings();
1137
1208
  setIsChatHistoryDrawerOpen(false);
1138
1209
  }
1139
1210
  setNewChatCreated(false);
@@ -1157,7 +1228,9 @@ const LightspeedChat = ({
1157
1228
  setDraftMessage,
1158
1229
  scrollToBottomRef,
1159
1230
  setCurrentConversationId,
1160
- setIsMcpSettingsOpen,
1231
+ closeSettings,
1232
+ savedPrompts,
1233
+ handleApplySavedPrompt,
1161
1234
  isFullscreenMode
1162
1235
  ]
1163
1236
  );
@@ -1165,8 +1238,9 @@ const LightspeedChat = ({
1165
1238
  (c) => c.conversation_id === viewConversationId
1166
1239
  );
1167
1240
  const getMaxPrompts = () => {
1241
+ const count = samplePrompts?.length ?? 0;
1168
1242
  if (isFullscreenMode) {
1169
- return samplePrompts?.length;
1243
+ return count;
1170
1244
  }
1171
1245
  if (displayMode === ChatbotDisplayMode.docked) {
1172
1246
  return 2;
@@ -1307,7 +1381,7 @@ const LightspeedChat = ({
1307
1381
  }, [
1308
1382
  conversationId,
1309
1383
  displayMode,
1310
- isMcpSettingsOpen,
1384
+ isSettingsOpen,
1311
1385
  messages.length,
1312
1386
  welcomePrompts.length
1313
1387
  ]);
@@ -1324,20 +1398,6 @@ const LightspeedChat = ({
1324
1398
  }),
1325
1399
  [filterValue, onClearFilter]
1326
1400
  );
1327
- const filteredConversations = useMemo(
1328
- () => filterConversations(filterValue),
1329
- [filterConversations, filterValue]
1330
- );
1331
- const noResultsState = useMemo(() => {
1332
- if (!filterValue || Object.keys(filteredConversations).length > 0) {
1333
- return void 0;
1334
- }
1335
- return {
1336
- bodyText: t("chatbox.emptyState.noResults.body"),
1337
- titleText: t("chatbox.emptyState.noResults.title"),
1338
- icon: SearchIcon
1339
- };
1340
- }, [filterValue, filteredConversations, t]);
1341
1401
  const onChatHistoryDrawerToggle = useCallback(() => {
1342
1402
  setIsChatHistoryDrawerOpen((isOpen) => !isOpen);
1343
1403
  }, []);
@@ -1521,21 +1581,35 @@ const LightspeedChat = ({
1521
1581
  /* @__PURE__ */ jsx(ChatbotFootnoteWithIcon, { ...getFootnoteProps(t) })
1522
1582
  ] })
1523
1583
  ] });
1524
- const mcpSettingsPanel = /* @__PURE__ */ jsx(
1525
- McpServersSettings,
1584
+ const settingsPanel = /* @__PURE__ */ jsx(
1585
+ SettingsPanel,
1526
1586
  {
1527
- onClose: () => setIsMcpSettingsOpen(false),
1528
- backgroundColor: chatHeaderBgColor
1587
+ activeTab: activeSettingsTab,
1588
+ onTabChange: setSettingsTab,
1589
+ onClose: closeSettings,
1590
+ backgroundColor: chatHeaderBgColor,
1591
+ isSavedPromptsEnabled,
1592
+ onEnableSavedPrompts: () => handleSavedPromptsToggle(true),
1593
+ onApplySavedPromptToInput: handleApplySavedPrompt,
1594
+ onSendSavedPromptDirectly: sendMessage,
1595
+ isChatStreaming: streamingUiMatchesView,
1596
+ savedPrompts,
1597
+ savedPromptsConfig,
1598
+ savedPromptsLoading,
1599
+ savedPromptsError,
1600
+ onCreateSavedPrompt: createPrompt,
1601
+ onRequestSavedPromptDelete: requestSavedPromptDelete,
1602
+ showMcpSettings: mcpToolsPermissionResolved
1529
1603
  }
1530
1604
  );
1531
1605
  const mainPanelContent = (() => {
1532
- if (!isMcpSettingsOpen || !mcpToolsPermissionResolved) {
1606
+ if (!isSettingsOpen) {
1533
1607
  return /* @__PURE__ */ jsx(Fragment, { children: chatMainContent });
1534
1608
  }
1535
1609
  if (isFullscreenMode) {
1536
1610
  return /* @__PURE__ */ jsxs(McpFullscreenLayout, { children: [
1537
1611
  /* @__PURE__ */ jsx(McpChatPane, { children: chatMainContent }),
1538
- /* @__PURE__ */ jsx(McpSettingsPane, { children: mcpSettingsPanel })
1612
+ /* @__PURE__ */ jsx(McpSettingsPane, { children: settingsPanel })
1539
1613
  ] });
1540
1614
  }
1541
1615
  return /* @__PURE__ */ jsx(
@@ -1543,9 +1617,9 @@ const LightspeedChat = ({
1543
1617
  {
1544
1618
  fields: [
1545
1619
  {
1546
- id: "mcp-servers-settings",
1620
+ id: "settings-panel",
1547
1621
  label: "",
1548
- field: mcpSettingsPanel
1622
+ field: settingsPanel
1549
1623
  }
1550
1624
  ]
1551
1625
  }
@@ -1554,7 +1628,7 @@ const LightspeedChat = ({
1554
1628
  let drawerPanelStyle;
1555
1629
  if (!isFullscreenMode) {
1556
1630
  drawerPanelStyle = { zIndex: 1300 };
1557
- } else if (isMcpSettingsOpen) {
1631
+ } else if (isSettingsOpen) {
1558
1632
  drawerPanelStyle = { width: 320, minWidth: 320, maxWidth: 320 };
1559
1633
  } else {
1560
1634
  drawerPanelStyle = { minWidth: 232, maxWidth: 400 };
@@ -1596,14 +1670,14 @@ const LightspeedChat = ({
1596
1670
  isCompact: !isFullscreenMode
1597
1671
  }
1598
1672
  ),
1599
- /* @__PURE__ */ jsxs(
1673
+ /* @__PURE__ */ jsx(
1600
1674
  StyledChatbot,
1601
1675
  {
1602
1676
  displayMode: ChatbotDisplayMode.embedded,
1603
1677
  isCompact: !isFullscreenMode,
1604
1678
  compactDrawerOpen: !isFullscreenMode && isChatHistoryDrawerOpen,
1605
- mcpDrawerFix: isMcpSettingsOpen && !isChatHistoryDrawerOpen,
1606
- children: [
1679
+ mcpDrawerFix: isSettingsOpen && !isChatHistoryDrawerOpen,
1680
+ children: showCompactSettings ? settingsPanel : /* @__PURE__ */ jsxs(Fragment, { children: [
1607
1681
  /* @__PURE__ */ jsxs(StyledChatbotHeader, { children: [
1608
1682
  /* @__PURE__ */ jsxs(ChatbotHeaderMain, { children: [
1609
1683
  showChatPanel && !isFullscreenMode && /* @__PURE__ */ jsxs(HeaderActions, { children: [
@@ -1690,17 +1764,23 @@ const LightspeedChat = ({
1690
1764
  handleSelectedModel,
1691
1765
  models,
1692
1766
  isPinningChatsEnabled,
1767
+ isSavedPromptsEnabled,
1768
+ onSavedPromptsToggle: handleSavedPromptsToggle,
1693
1769
  hideModelSelector: true,
1694
1770
  showChatTabOptions: !showNotebooksPanel,
1695
1771
  showMcpSettings: mcpToolsPermissionResolved,
1696
1772
  setDisplayMode: setDisplayModeFromHeader,
1697
1773
  displayMode,
1698
1774
  onPinnedChatsToggle: handlePinningChatsToggle,
1699
- onMcpSettingsClick: () => setIsMcpSettingsOpen(true)
1775
+ onMcpSettingsClick: () => {
1776
+ openSettings(
1777
+ mcpToolsPermissionResolved ? "mcp-servers" : "saved-prompts"
1778
+ );
1779
+ }
1700
1780
  }
1701
1781
  )
1702
1782
  ] }),
1703
- /* @__PURE__ */ jsx(HeaderDivider, { "data-testid": "lightspeed-header-divider" }),
1783
+ (isFullscreenMode || shouldShowTabs) && /* @__PURE__ */ jsx(HeaderDivider, { "data-testid": "lightspeed-header-divider" }),
1704
1784
  shouldShowTabs && /* @__PURE__ */ jsxs(
1705
1785
  Tabs,
1706
1786
  {
@@ -1817,7 +1897,7 @@ const LightspeedChat = ({
1817
1897
  setIsDrawerOpen: setIsChatHistoryDrawerOpen,
1818
1898
  activeItemId: viewConversationId,
1819
1899
  onSelectActiveItem,
1820
- conversations: filteredConversations,
1900
+ conversations: conversationGroups,
1821
1901
  onNewChat,
1822
1902
  newChatButtonText: t("button.newChat"),
1823
1903
  newChatButtonProps: {
@@ -1829,7 +1909,11 @@ const LightspeedChat = ({
1829
1909
  searchInputAriaLabel: t("aria.search.placeholder"),
1830
1910
  searchInputProps,
1831
1911
  searchActionEnd: sortDropdown,
1832
- noResultsState,
1912
+ noResultsState: filterValue && hasNoSearchResults ? {
1913
+ bodyText: t("chatbox.emptyState.noResults.body"),
1914
+ titleText: t("chatbox.emptyState.noResults.title"),
1915
+ icon: SearchIcon
1916
+ } : void 0,
1833
1917
  drawerContent: /* @__PURE__ */ jsxs(
1834
1918
  ChatFileDropZone,
1835
1919
  {
@@ -1919,7 +2003,18 @@ const LightspeedChat = ({
1919
2003
  }
1920
2004
  )
1921
2005
  ] })
1922
- ]
2006
+ ] })
2007
+ }
2008
+ ),
2009
+ /* @__PURE__ */ jsx(
2010
+ DeleteSavedPromptModal,
2011
+ {
2012
+ isOpen: isSavedPromptDeleteModalOpen,
2013
+ promptName: promptToDelete?.name,
2014
+ isDeleting: isSavedPromptDeleting,
2015
+ error: savedPromptDeleteError,
2016
+ onClose: closeSavedPromptDeleteModal,
2017
+ onConfirm: confirmSavedPromptDelete
1923
2018
  }
1924
2019
  ),
1925
2020
  /* @__PURE__ */ jsx(Attachment, {})