@red-hat-developer-hub/backstage-plugin-intelligent-assistant 5.1.0 → 5.3.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 (87) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +40 -5
  3. package/dist/alpha.d.ts +61 -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 +276 -134
  12. package/dist/components/LightSpeedChat.esm.js.map +1 -1
  13. package/dist/components/LightspeedChatBoxHeader.esm.js +57 -2
  14. package/dist/components/LightspeedChatBoxHeader.esm.js.map +1 -1
  15. package/dist/components/LightspeedChatContainer.esm.js +2 -1
  16. package/dist/components/LightspeedChatContainer.esm.js.map +1 -1
  17. package/dist/components/LightspeedDrawerContext.esm.js.map +1 -1
  18. package/dist/components/LightspeedDrawerProvider.esm.js +1 -0
  19. package/dist/components/LightspeedDrawerProvider.esm.js.map +1 -1
  20. package/dist/components/McpServersSettings.esm.js +9 -22
  21. package/dist/components/McpServersSettings.esm.js.map +1 -1
  22. package/dist/components/MessageBarModelSelector.esm.js +104 -12
  23. package/dist/components/MessageBarModelSelector.esm.js.map +1 -1
  24. package/dist/components/SavedPromptCard.esm.js +100 -0
  25. package/dist/components/SavedPromptCard.esm.js.map +1 -0
  26. package/dist/components/SavedPromptKebabMenu.esm.js +87 -0
  27. package/dist/components/SavedPromptKebabMenu.esm.js.map +1 -0
  28. package/dist/components/SavedPromptMenuItems.esm.js +52 -0
  29. package/dist/components/SavedPromptMenuItems.esm.js.map +1 -0
  30. package/dist/components/SavedPromptsEmptyState.esm.js +63 -0
  31. package/dist/components/SavedPromptsEmptyState.esm.js.map +1 -0
  32. package/dist/components/SavedPromptsList.esm.js +63 -0
  33. package/dist/components/SavedPromptsList.esm.js.map +1 -0
  34. package/dist/components/SavedPromptsSettings.esm.js +285 -0
  35. package/dist/components/SavedPromptsSettings.esm.js.map +1 -0
  36. package/dist/components/ScreenContextChip.esm.js +172 -0
  37. package/dist/components/ScreenContextChip.esm.js.map +1 -0
  38. package/dist/components/SettingsPanel.esm.js +135 -0
  39. package/dist/components/SettingsPanel.esm.js.map +1 -0
  40. package/dist/hooks/screenContextLabelSubscription.esm.js +113 -0
  41. package/dist/hooks/screenContextLabelSubscription.esm.js.map +1 -0
  42. package/dist/hooks/useConversationHistoryGroups.esm.js +71 -0
  43. package/dist/hooks/useConversationHistoryGroups.esm.js.map +1 -0
  44. package/dist/hooks/useFeedbackActions.esm.js.map +1 -1
  45. package/dist/hooks/useLightspeedProviderState.esm.js +19 -5
  46. package/dist/hooks/useLightspeedProviderState.esm.js.map +1 -1
  47. package/dist/hooks/useSavedPromptActions.esm.js +64 -0
  48. package/dist/hooks/useSavedPromptActions.esm.js.map +1 -0
  49. package/dist/hooks/useSavedPrompts.esm.js +75 -0
  50. package/dist/hooks/useSavedPrompts.esm.js.map +1 -0
  51. package/dist/hooks/useSavedPromptsSettings.esm.js +65 -0
  52. package/dist/hooks/useSavedPromptsSettings.esm.js.map +1 -0
  53. package/dist/hooks/useScreenContextLabelRevision.esm.js +13 -0
  54. package/dist/hooks/useScreenContextLabelRevision.esm.js.map +1 -0
  55. package/dist/hooks/useScreenContextSettings.esm.js +110 -0
  56. package/dist/hooks/useScreenContextSettings.esm.js.map +1 -0
  57. package/dist/hooks/useSettingsPanelUrlState.esm.js +95 -0
  58. package/dist/hooks/useSettingsPanelUrlState.esm.js.map +1 -0
  59. package/dist/hooks/useWelcomePrompts.esm.js +16 -5
  60. package/dist/hooks/useWelcomePrompts.esm.js.map +1 -1
  61. package/dist/hooks/useWindowLocation.esm.js +28 -0
  62. package/dist/hooks/useWindowLocation.esm.js.map +1 -0
  63. package/dist/translations/de.esm.js +64 -1
  64. package/dist/translations/de.esm.js.map +1 -1
  65. package/dist/translations/es.esm.js +64 -1
  66. package/dist/translations/es.esm.js.map +1 -1
  67. package/dist/translations/fr.esm.js +64 -1
  68. package/dist/translations/fr.esm.js.map +1 -1
  69. package/dist/translations/it.esm.js +64 -1
  70. package/dist/translations/it.esm.js.map +1 -1
  71. package/dist/translations/ja.esm.js +64 -1
  72. package/dist/translations/ja.esm.js.map +1 -1
  73. package/dist/translations/ref.esm.js +64 -2
  74. package/dist/translations/ref.esm.js.map +1 -1
  75. package/dist/utils/buildConversationHistoryGroups.esm.js +241 -0
  76. package/dist/utils/buildConversationHistoryGroups.esm.js.map +1 -0
  77. package/dist/utils/dom-selectors.esm.js +22 -2
  78. package/dist/utils/dom-selectors.esm.js.map +1 -1
  79. package/dist/utils/prompt-utils.esm.js +18 -1
  80. package/dist/utils/prompt-utils.esm.js.map +1 -1
  81. package/dist/utils/screen-capture.esm.js +116 -0
  82. package/dist/utils/screen-capture.esm.js.map +1 -0
  83. package/dist/utils/screen-context-utils.esm.js +343 -0
  84. package/dist/utils/screen-context-utils.esm.js.map +1 -0
  85. package/dist/utils/sensitive-data-redactor.esm.js +39 -1
  86. package/dist/utils/sensitive-data-redactor.esm.js.map +1 -1
  87. package/package.json +5 -15
@@ -39,6 +39,11 @@ const LightspeedChatBoxHeader = ({
39
39
  models,
40
40
  isPinningChatsEnabled,
41
41
  onPinnedChatsToggle,
42
+ isSavedPromptsEnabled,
43
+ onSavedPromptsToggle,
44
+ screenContextAdminEnabled = false,
45
+ isScreenContextSharingEnabled = false,
46
+ onScreenContextSharingToggle,
42
47
  onMcpSettingsClick,
43
48
  isModelSelectorDisabled = false,
44
49
  hideModelSelector = false,
@@ -190,14 +195,64 @@ const LightspeedChatBoxHeader = ({
190
195
  },
191
196
  "enablePinningChats"
192
197
  ),
193
- showMcpSettings && /* @__PURE__ */ jsxs(
198
+ isSavedPromptsEnabled ? /* @__PURE__ */ jsx(
199
+ DropdownItem,
200
+ {
201
+ value: "disableSavedPrompts",
202
+ icon: /* @__PURE__ */ jsx(ToggleOnOutlinedIcon, { sx: { marginTop: "8px" } }),
203
+ description: t("settings.savedPrompts.enabled.description"),
204
+ onClick: () => onSavedPromptsToggle(false),
205
+ children: t("settings.savedPrompts.disable")
206
+ },
207
+ "disableSavedPrompts"
208
+ ) : /* @__PURE__ */ jsx(
209
+ DropdownItem,
210
+ {
211
+ value: "enableSavedPrompts",
212
+ icon: /* @__PURE__ */ jsx(ToggleOffOutlinedIcon, { sx: { marginTop: "8px" } }),
213
+ description: t(
214
+ "settings.savedPrompts.disabled.description"
215
+ ),
216
+ onClick: () => onSavedPromptsToggle(true),
217
+ children: t("settings.savedPrompts.enable")
218
+ },
219
+ "enableSavedPrompts"
220
+ ),
221
+ screenContextAdminEnabled && (isScreenContextSharingEnabled ? /* @__PURE__ */ jsx(
222
+ DropdownItem,
223
+ {
224
+ value: "disableScreenContext",
225
+ icon: /* @__PURE__ */ jsx(ToggleOnOutlinedIcon, { sx: { marginTop: "8px" } }),
226
+ description: t(
227
+ "settings.screenContext.enabled.description"
228
+ ),
229
+ onClick: () => onScreenContextSharingToggle?.(false),
230
+ children: t("settings.screenContext.disable")
231
+ },
232
+ "disableScreenContext"
233
+ ) : /* @__PURE__ */ jsx(
234
+ DropdownItem,
235
+ {
236
+ value: "enableScreenContext",
237
+ icon: /* @__PURE__ */ jsx(ToggleOffOutlinedIcon, { sx: { marginTop: "8px" } }),
238
+ description: t(
239
+ "settings.screenContext.disabled.description"
240
+ ),
241
+ onClick: () => onScreenContextSharingToggle?.(true),
242
+ children: t("settings.screenContext.enable")
243
+ },
244
+ "enableScreenContext"
245
+ )),
246
+ /* @__PURE__ */ jsxs(
194
247
  DropdownItem,
195
248
  {
196
249
  value: "mcpSettings",
197
250
  icon: /* @__PURE__ */ jsx(McpSettingsIcon, {}),
198
251
  onClick: onMcpSettingsClick,
199
252
  children: [
200
- t("settings.mcp.label"),
253
+ t(
254
+ showMcpSettings ? "settings.mcp.label" : "settings.prompt.label"
255
+ ),
201
256
  /* @__PURE__ */ jsx(Label, { color: "purple", isCompact: true, style: { marginLeft: 8 }, children: t("settings.mcp.badge") })
202
257
  ]
203
258
  },
@@ -1 +1 @@
1
- {"version":3,"file":"LightspeedChatBoxHeader.esm.js","sources":["../../src/components/LightspeedChatBoxHeader.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Ref, useState } from 'react';\n\nimport ToggleOffOutlinedIcon from '@mui/icons-material/ToggleOffOutlined';\nimport ToggleOnOutlinedIcon from '@mui/icons-material/ToggleOnOutlined';\nimport Divider from '@mui/material/Divider';\nimport { styled } from '@mui/material/styles';\nimport {\n ChatbotDisplayMode,\n ChatbotHeaderActions,\n ChatbotHeaderOptionsDropdown,\n} from '@patternfly/chatbot';\nimport {\n Dropdown,\n DropdownGroup,\n DropdownItem,\n DropdownList,\n Icon,\n Label,\n MenuToggle,\n MenuToggleElement,\n} from '@patternfly/react-core';\nimport {\n ExpandIcon,\n OpenDrawerRightIcon,\n OutlinedWindowRestoreIcon,\n RhUiEllipsisVerticalFillIcon,\n} from '@patternfly/react-icons';\n\nimport { useTranslation } from '../hooks/useTranslation';\nimport { McpSettingsIcon } from './McpSettingsIcon';\n\ntype LightspeedChatBoxHeaderProps = {\n displayMode: ChatbotDisplayMode;\n selectedModel: string;\n handleSelectedModel: (item: string) => void;\n models: { label: string; value: string; provider: string }[];\n isPinningChatsEnabled: boolean;\n onPinnedChatsToggle: (state: boolean) => void;\n onMcpSettingsClick: () => void;\n isModelSelectorDisabled?: boolean;\n hideModelSelector?: boolean;\n /** When false, omits pinned-chats and MCP entries (Chat tab only). */\n showChatTabOptions?: boolean;\n /** When false, hides MCP settings from the header menu. */\n showMcpSettings?: boolean;\n setDisplayMode: (mode: ChatbotDisplayMode) => void;\n};\n\nconst StyledDropdown = styled(Dropdown)({\n '& ul, & li': {\n padding: 0,\n margin: 0,\n },\n});\n\nconst StyledOptionsDropdown = styled(ChatbotHeaderOptionsDropdown)({\n '& ul, & li': {\n padding: 0,\n margin: 0,\n },\n});\n\nconst SelectorToggle = styled(MenuToggle, {\n shouldForwardProp: prop => prop !== 'dimmed',\n})<{ dimmed?: boolean }>(({ theme, dimmed }) => ({\n ...(dimmed && {\n backgroundColor: theme.palette.action.disabled,\n }),\n}));\n\nconst StyledDropdownGroup = styled(DropdownGroup)({\n fontWeight: 'bold',\n});\n\nexport const LightspeedChatBoxHeader = ({\n selectedModel,\n displayMode,\n handleSelectedModel,\n models,\n isPinningChatsEnabled,\n onPinnedChatsToggle,\n onMcpSettingsClick,\n isModelSelectorDisabled = false,\n hideModelSelector = false,\n showChatTabOptions = true,\n showMcpSettings = false,\n setDisplayMode,\n}: LightspeedChatBoxHeaderProps) => {\n const [isOptionsMenuOpen, setIsOptionsMenuOpen] = useState(false);\n const { t } = useTranslation();\n\n const maxLabelLength = Math.max(\n ...models.map(m => m.label.length),\n selectedModel.length,\n 1,\n );\n const toggleMinWidth = `${maxLabelLength + 4}ch`;\n\n const toggle = (toggleRef: Ref<MenuToggleElement>) => (\n <SelectorToggle\n dimmed={isModelSelectorDisabled}\n variant=\"secondary\"\n aria-label={t('aria.chatbotSelector')}\n ref={toggleRef}\n isExpanded={isOptionsMenuOpen}\n isDisabled={isModelSelectorDisabled}\n onClick={() => setIsOptionsMenuOpen(!isOptionsMenuOpen)}\n style={{ minWidth: toggleMinWidth }}\n >\n {selectedModel}\n </SelectorToggle>\n );\n\n const handlePinningChatsToggle = (state: boolean) => {\n onPinnedChatsToggle(state);\n };\n\n const handleDockedToWindow = () => {\n setDisplayMode(ChatbotDisplayMode.docked);\n };\n\n const handleFullscreen = () => {\n setDisplayMode(ChatbotDisplayMode.embedded);\n };\n\n const handleOverlay = () => {\n setDisplayMode(ChatbotDisplayMode.default);\n };\n\n const isOverlayMode = displayMode === ChatbotDisplayMode.default;\n const scrollThreshold = isOverlayMode ? 8 : 10;\n const isModelDropdownScrollable = models.length > scrollThreshold;\n\n return (\n <ChatbotHeaderActions>\n {!hideModelSelector && (\n <StyledDropdown\n isOpen={isOptionsMenuOpen}\n onSelect={(_e, value) => {\n handleSelectedModel(value as string);\n setIsOptionsMenuOpen(false);\n }}\n onOpenChange={isOpen => setIsOptionsMenuOpen(isOpen)}\n popperProps={{ position: 'right' }}\n shouldFocusToggleOnSelect\n shouldFocusFirstItemOnOpen={false}\n toggle={toggle}\n isScrollable={isModelDropdownScrollable}\n maxMenuHeight={isModelDropdownScrollable ? '240px' : undefined}\n >\n <DropdownList>\n {models.map(model => (\n <StyledDropdownGroup key={model.label}>\n <DropdownItem\n value={model.value}\n key={model.value}\n isSelected={selectedModel === model.value}\n >\n {model.label}\n </DropdownItem>\n </StyledDropdownGroup>\n ))}\n </DropdownList>\n </StyledDropdown>\n )}\n <StyledOptionsDropdown\n isCompact\n shouldFocusFirstItemOnOpen={false}\n popperProps={{\n position: 'right',\n preventOverflow: true,\n appendTo: () => document.body,\n }}\n toggleProps={{\n 'aria-label': t('aria.options.label'),\n className: 'pf-chatbot__button--toggle-options pf-m-compact',\n icon: (\n <Icon size=\"lg\" isInline>\n <RhUiEllipsisVerticalFillIcon />\n </Icon>\n ),\n }}\n tooltipProps={{\n trigger: 'manual',\n content: '',\n }}\n >\n <DropdownGroup>\n <DropdownList>\n <DropdownItem key=\"displayModeLabel\" isDisabled>\n {t('settings.displayMode.label')}\n </DropdownItem>\n <DropdownItem\n value={ChatbotDisplayMode.default}\n key=\"switchDisplayOverlay\"\n icon={<OutlinedWindowRestoreIcon />}\n onClick={handleOverlay}\n isSelected={displayMode === ChatbotDisplayMode.default}\n >\n {t('settings.displayMode.overlay')}\n </DropdownItem>\n <DropdownItem\n value={ChatbotDisplayMode.docked}\n key=\"switchDisplayDock\"\n icon={<OpenDrawerRightIcon />}\n onClick={handleDockedToWindow}\n isSelected={displayMode === ChatbotDisplayMode.docked}\n >\n {t('settings.displayMode.docked')}\n </DropdownItem>\n <DropdownItem\n value={ChatbotDisplayMode.embedded}\n key=\"switchDisplayFullscreen\"\n icon={<ExpandIcon />}\n onClick={handleFullscreen}\n isSelected={displayMode === ChatbotDisplayMode.embedded}\n >\n {t('settings.displayMode.fullscreen')}\n </DropdownItem>\n </DropdownList>\n </DropdownGroup>\n {showChatTabOptions && (\n <>\n <Divider />\n <DropdownGroup>\n <DropdownList>\n {isPinningChatsEnabled ? (\n <DropdownItem\n value=\"disablePinningChats\"\n key=\"disablePinningChat\"\n icon={<ToggleOnOutlinedIcon sx={{ marginTop: '8px' }} />}\n description={t('settings.pinned.enabled.description')}\n onClick={() => handlePinningChatsToggle(false)}\n >\n {t('settings.pinned.disable')}\n </DropdownItem>\n ) : (\n <DropdownItem\n value=\"enablePinningChats\"\n key=\"enablePinningChats\"\n icon={<ToggleOffOutlinedIcon sx={{ marginTop: '8px' }} />}\n description={t('settings.pinned.disabled.description')}\n onClick={() => handlePinningChatsToggle(true)}\n >\n {t('settings.pinned.enable')}\n </DropdownItem>\n )}\n {showMcpSettings && (\n <DropdownItem\n value=\"mcpSettings\"\n key=\"mcpSettings\"\n icon={<McpSettingsIcon />}\n onClick={onMcpSettingsClick}\n >\n {t('settings.mcp.label')}\n <Label color=\"purple\" isCompact style={{ marginLeft: 8 }}>\n {t('settings.mcp.badge')}\n </Label>\n </DropdownItem>\n )}\n </DropdownList>\n </DropdownGroup>\n </>\n )}\n </StyledOptionsDropdown>\n </ChatbotHeaderActions>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"LightspeedChatBoxHeader.esm.js","sources":["../../src/components/LightspeedChatBoxHeader.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Ref, useState } from 'react';\n\nimport ToggleOffOutlinedIcon from '@mui/icons-material/ToggleOffOutlined';\nimport ToggleOnOutlinedIcon from '@mui/icons-material/ToggleOnOutlined';\nimport Divider from '@mui/material/Divider';\nimport { styled } from '@mui/material/styles';\nimport {\n ChatbotDisplayMode,\n ChatbotHeaderActions,\n ChatbotHeaderOptionsDropdown,\n} from '@patternfly/chatbot';\nimport {\n Dropdown,\n DropdownGroup,\n DropdownItem,\n DropdownList,\n Icon,\n Label,\n MenuToggle,\n MenuToggleElement,\n} from '@patternfly/react-core';\nimport {\n ExpandIcon,\n OpenDrawerRightIcon,\n OutlinedWindowRestoreIcon,\n RhUiEllipsisVerticalFillIcon,\n} from '@patternfly/react-icons';\n\nimport { useTranslation } from '../hooks/useTranslation';\nimport { McpSettingsIcon } from './McpSettingsIcon';\n\ntype LightspeedChatBoxHeaderProps = {\n displayMode: ChatbotDisplayMode;\n selectedModel: string;\n handleSelectedModel: (item: string) => void;\n models: { label: string; value: string; provider: string }[];\n isPinningChatsEnabled: boolean;\n onPinnedChatsToggle: (state: boolean) => void;\n isSavedPromptsEnabled: boolean;\n onSavedPromptsToggle: (state: boolean) => void;\n screenContextAdminEnabled?: boolean;\n isScreenContextSharingEnabled?: boolean;\n onScreenContextSharingToggle?: (state: boolean) => void;\n onMcpSettingsClick: () => void;\n isModelSelectorDisabled?: boolean;\n hideModelSelector?: boolean;\n /** When false, omits pinned-chats and MCP entries (Chat tab only). */\n showChatTabOptions?: boolean;\n /** When false, shows prompt-only settings label and opens saved-prompts tab. */\n showMcpSettings?: boolean;\n setDisplayMode: (mode: ChatbotDisplayMode) => void;\n};\n\nconst StyledDropdown = styled(Dropdown)({\n '& ul, & li': {\n padding: 0,\n margin: 0,\n },\n});\n\nconst StyledOptionsDropdown = styled(ChatbotHeaderOptionsDropdown)({\n '& ul, & li': {\n padding: 0,\n margin: 0,\n },\n});\n\nconst SelectorToggle = styled(MenuToggle, {\n shouldForwardProp: prop => prop !== 'dimmed',\n})<{ dimmed?: boolean }>(({ theme, dimmed }) => ({\n ...(dimmed && {\n backgroundColor: theme.palette.action.disabled,\n }),\n}));\n\nconst StyledDropdownGroup = styled(DropdownGroup)({\n fontWeight: 'bold',\n});\n\nexport const LightspeedChatBoxHeader = ({\n selectedModel,\n displayMode,\n handleSelectedModel,\n models,\n isPinningChatsEnabled,\n onPinnedChatsToggle,\n isSavedPromptsEnabled,\n onSavedPromptsToggle,\n screenContextAdminEnabled = false,\n isScreenContextSharingEnabled = false,\n onScreenContextSharingToggle,\n onMcpSettingsClick,\n isModelSelectorDisabled = false,\n hideModelSelector = false,\n showChatTabOptions = true,\n showMcpSettings = false,\n setDisplayMode,\n}: LightspeedChatBoxHeaderProps) => {\n const [isOptionsMenuOpen, setIsOptionsMenuOpen] = useState(false);\n const { t } = useTranslation();\n\n const maxLabelLength = Math.max(\n ...models.map(m => m.label.length),\n selectedModel.length,\n 1,\n );\n const toggleMinWidth = `${maxLabelLength + 4}ch`;\n\n const toggle = (toggleRef: Ref<MenuToggleElement>) => (\n <SelectorToggle\n dimmed={isModelSelectorDisabled}\n variant=\"secondary\"\n aria-label={t('aria.chatbotSelector')}\n ref={toggleRef}\n isExpanded={isOptionsMenuOpen}\n isDisabled={isModelSelectorDisabled}\n onClick={() => setIsOptionsMenuOpen(!isOptionsMenuOpen)}\n style={{ minWidth: toggleMinWidth }}\n >\n {selectedModel}\n </SelectorToggle>\n );\n\n const handlePinningChatsToggle = (state: boolean) => {\n onPinnedChatsToggle(state);\n };\n\n const handleDockedToWindow = () => {\n setDisplayMode(ChatbotDisplayMode.docked);\n };\n\n const handleFullscreen = () => {\n setDisplayMode(ChatbotDisplayMode.embedded);\n };\n\n const handleOverlay = () => {\n setDisplayMode(ChatbotDisplayMode.default);\n };\n\n const isOverlayMode = displayMode === ChatbotDisplayMode.default;\n const scrollThreshold = isOverlayMode ? 8 : 10;\n const isModelDropdownScrollable = models.length > scrollThreshold;\n\n return (\n <ChatbotHeaderActions>\n {!hideModelSelector && (\n <StyledDropdown\n isOpen={isOptionsMenuOpen}\n onSelect={(_e, value) => {\n handleSelectedModel(value as string);\n setIsOptionsMenuOpen(false);\n }}\n onOpenChange={isOpen => setIsOptionsMenuOpen(isOpen)}\n popperProps={{ position: 'right' }}\n shouldFocusToggleOnSelect\n shouldFocusFirstItemOnOpen={false}\n toggle={toggle}\n isScrollable={isModelDropdownScrollable}\n maxMenuHeight={isModelDropdownScrollable ? '240px' : undefined}\n >\n <DropdownList>\n {models.map(model => (\n <StyledDropdownGroup key={model.label}>\n <DropdownItem\n value={model.value}\n key={model.value}\n isSelected={selectedModel === model.value}\n >\n {model.label}\n </DropdownItem>\n </StyledDropdownGroup>\n ))}\n </DropdownList>\n </StyledDropdown>\n )}\n <StyledOptionsDropdown\n isCompact\n shouldFocusFirstItemOnOpen={false}\n popperProps={{\n position: 'right',\n preventOverflow: true,\n appendTo: () => document.body,\n }}\n toggleProps={{\n 'aria-label': t('aria.options.label'),\n className: 'pf-chatbot__button--toggle-options pf-m-compact',\n icon: (\n <Icon size=\"lg\" isInline>\n <RhUiEllipsisVerticalFillIcon />\n </Icon>\n ),\n }}\n tooltipProps={{\n trigger: 'manual',\n content: '',\n }}\n >\n <DropdownGroup>\n <DropdownList>\n <DropdownItem key=\"displayModeLabel\" isDisabled>\n {t('settings.displayMode.label')}\n </DropdownItem>\n <DropdownItem\n value={ChatbotDisplayMode.default}\n key=\"switchDisplayOverlay\"\n icon={<OutlinedWindowRestoreIcon />}\n onClick={handleOverlay}\n isSelected={displayMode === ChatbotDisplayMode.default}\n >\n {t('settings.displayMode.overlay')}\n </DropdownItem>\n <DropdownItem\n value={ChatbotDisplayMode.docked}\n key=\"switchDisplayDock\"\n icon={<OpenDrawerRightIcon />}\n onClick={handleDockedToWindow}\n isSelected={displayMode === ChatbotDisplayMode.docked}\n >\n {t('settings.displayMode.docked')}\n </DropdownItem>\n <DropdownItem\n value={ChatbotDisplayMode.embedded}\n key=\"switchDisplayFullscreen\"\n icon={<ExpandIcon />}\n onClick={handleFullscreen}\n isSelected={displayMode === ChatbotDisplayMode.embedded}\n >\n {t('settings.displayMode.fullscreen')}\n </DropdownItem>\n </DropdownList>\n </DropdownGroup>\n {showChatTabOptions && (\n <>\n <Divider />\n <DropdownGroup>\n <DropdownList>\n {isPinningChatsEnabled ? (\n <DropdownItem\n value=\"disablePinningChats\"\n key=\"disablePinningChat\"\n icon={<ToggleOnOutlinedIcon sx={{ marginTop: '8px' }} />}\n description={t('settings.pinned.enabled.description')}\n onClick={() => handlePinningChatsToggle(false)}\n >\n {t('settings.pinned.disable')}\n </DropdownItem>\n ) : (\n <DropdownItem\n value=\"enablePinningChats\"\n key=\"enablePinningChats\"\n icon={<ToggleOffOutlinedIcon sx={{ marginTop: '8px' }} />}\n description={t('settings.pinned.disabled.description')}\n onClick={() => handlePinningChatsToggle(true)}\n >\n {t('settings.pinned.enable')}\n </DropdownItem>\n )}\n {isSavedPromptsEnabled ? (\n <DropdownItem\n value=\"disableSavedPrompts\"\n key=\"disableSavedPrompts\"\n icon={<ToggleOnOutlinedIcon sx={{ marginTop: '8px' }} />}\n description={t('settings.savedPrompts.enabled.description')}\n onClick={() => onSavedPromptsToggle(false)}\n >\n {t('settings.savedPrompts.disable')}\n </DropdownItem>\n ) : (\n <DropdownItem\n value=\"enableSavedPrompts\"\n key=\"enableSavedPrompts\"\n icon={<ToggleOffOutlinedIcon sx={{ marginTop: '8px' }} />}\n description={t(\n 'settings.savedPrompts.disabled.description',\n )}\n onClick={() => onSavedPromptsToggle(true)}\n >\n {t('settings.savedPrompts.enable')}\n </DropdownItem>\n )}\n {screenContextAdminEnabled &&\n (isScreenContextSharingEnabled ? (\n <DropdownItem\n value=\"disableScreenContext\"\n key=\"disableScreenContext\"\n icon={<ToggleOnOutlinedIcon sx={{ marginTop: '8px' }} />}\n description={t(\n 'settings.screenContext.enabled.description',\n )}\n onClick={() => onScreenContextSharingToggle?.(false)}\n >\n {t('settings.screenContext.disable')}\n </DropdownItem>\n ) : (\n <DropdownItem\n value=\"enableScreenContext\"\n key=\"enableScreenContext\"\n icon={<ToggleOffOutlinedIcon sx={{ marginTop: '8px' }} />}\n description={t(\n 'settings.screenContext.disabled.description',\n )}\n onClick={() => onScreenContextSharingToggle?.(true)}\n >\n {t('settings.screenContext.enable')}\n </DropdownItem>\n ))}\n <DropdownItem\n value=\"mcpSettings\"\n key=\"mcpSettings\"\n icon={<McpSettingsIcon />}\n onClick={onMcpSettingsClick}\n >\n {t(\n showMcpSettings\n ? 'settings.mcp.label'\n : 'settings.prompt.label',\n )}\n <Label color=\"purple\" isCompact style={{ marginLeft: 8 }}>\n {t('settings.mcp.badge')}\n </Label>\n </DropdownItem>\n </DropdownList>\n </DropdownGroup>\n </>\n )}\n </StyledOptionsDropdown>\n </ChatbotHeaderActions>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -43,7 +43,8 @@ const LightspeedChatContainerInner = () => {
43
43
  () => models ? models.filter((model) => model.model_type === "llm").map((m) => ({
44
44
  label: m.provider_resource_id,
45
45
  value: m.provider_resource_id,
46
- provider: m.provider_id
46
+ provider: m.provider_id,
47
+ supportsVision: m.supportsVision
47
48
  })) : [],
48
49
  [models]
49
50
  );
@@ -1 +1 @@
1
- {"version":3,"file":"LightspeedChatContainer.esm.js","sources":["../../src/components/LightspeedChatContainer.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport '@patternfly/react-core/dist/styles/base-no-reset.css';\nimport '@patternfly/chatbot/dist/css/main.css';\n\nimport { useEffect, useLayoutEffect, useMemo, useState } from 'react';\nimport { useAsync } from 'react-use';\n\nimport { identityApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport { useTheme } from '@mui/material/styles';\nimport { QueryClientProvider } from '@tanstack/react-query';\n\nimport { useAllModels } from '../hooks/useAllModels';\nimport { useIaChatPermission } from '../hooks/useIaChatPermission';\nimport { useIaNotebooksPermission } from '../hooks/useIaNotebooksPermission';\nimport { useTopicRestrictionStatus } from '../hooks/useQuestionValidation';\nimport queryClient from '../utils/queryClient';\nimport FileAttachmentContextProvider from './AttachmentContext';\nimport { LightspeedChat } from './LightSpeedChat';\nimport {\n LcoreNotConfiguredEmptyState,\n LightspeedChatModelsLoading,\n ModelsLoadErrorEmptyState,\n} from './LightspeedChatModelsState';\n\nconst THEME_DARK = 'dark';\nconst THEME_DARK_CLASS = 'pf-v6-theme-dark';\nconst LAST_SELECTED_MODEL_KEY = 'lastSelectedModel';\n\n/**\n * Inner component that contains all the Lightspeed chat rendering logic\n */\nconst LightspeedChatContainerInner = () => {\n const {\n palette: { mode },\n } = useTheme();\n\n const identityApi = useApi(identityApiRef);\n\n const { allowed: hasChatAccess, loading: chatPermissionLoading } =\n useIaChatPermission();\n\n const { allowed: hasNotebooksAccess, loading: notebooksPermissionLoading } =\n useIaNotebooksPermission();\n\n const permissionsLoading =\n chatPermissionLoading || notebooksPermissionLoading;\n const hasPluginAccess = hasChatAccess || hasNotebooksAccess;\n\n const {\n data: models,\n isLoading: modelsLoading,\n isError: modelsError,\n refetch: refetchModels,\n } = useAllModels(hasChatAccess);\n\n const { value: profile, loading: profileLoading } = useAsync(\n async () => await identityApi.getProfileInfo(),\n );\n\n const [selectedModel, setSelectedModel] = useState('');\n const [selectedProvider, setSelectedProvider] = useState('');\n\n const { data: topicRestrictionEnabled } =\n useTopicRestrictionStatus(hasChatAccess);\n\n const modelsItems = useMemo(\n () =>\n models\n ? models\n .filter(model => model.model_type === 'llm')\n .map(m => ({\n label: m.provider_resource_id,\n value: m.provider_resource_id,\n provider: m.provider_id,\n }))\n : [],\n [models],\n );\n\n useLayoutEffect(() => {\n const htmlTagElement = document.documentElement;\n if (mode === THEME_DARK) {\n htmlTagElement.classList.add(THEME_DARK_CLASS);\n } else {\n htmlTagElement.classList.remove(THEME_DARK_CLASS);\n }\n }, [mode]);\n\n // Load last selected model from localStorage\n useEffect(() => {\n if (!hasChatAccess || modelsItems.length === 0) {\n return;\n }\n\n try {\n const storedData = localStorage.getItem(LAST_SELECTED_MODEL_KEY);\n const parsedData = storedData ? JSON.parse(storedData) : null;\n\n const storedModel = parsedData?.model\n ? modelsItems.find(m => m.value === parsedData.model)\n : null;\n\n if (storedModel) {\n setSelectedModel(storedModel.value);\n setSelectedProvider(storedModel.provider);\n } else {\n setSelectedModel(modelsItems[0].value);\n setSelectedProvider(modelsItems[0].provider);\n }\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(\n 'Error loading last selected model from localStorage:',\n error,\n );\n setSelectedModel(modelsItems[0].value);\n setSelectedProvider(modelsItems[0].provider);\n }\n }, [hasChatAccess, modelsItems]);\n\n // Save selected model to localStorage\n useEffect(() => {\n if (selectedModel && selectedProvider) {\n try {\n localStorage.setItem(\n LAST_SELECTED_MODEL_KEY,\n JSON.stringify({\n model: selectedModel,\n provider: selectedProvider,\n }),\n );\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(\n 'Error saving last selected model to localStorage:',\n error,\n );\n }\n }\n }, [selectedModel, selectedProvider]);\n\n if (permissionsLoading) {\n // Never return null inside the overlay modal: PatternFly's focus-trap requires at least\n // one tabbable node (e.g. after removing the modal close button). Locale switches can\n // briefly re-enter this loading state.\n return <LightspeedChatModelsLoading />;\n }\n\n if (!hasPluginAccess) {\n return null;\n }\n\n if (hasChatAccess && modelsLoading) {\n return <LightspeedChatModelsLoading />;\n }\n\n // TanStack Query can keep the last successful `data` while `isError` is true after a\n // failed refetch. Prefer showing chat when we still have LLM rows; only use the full-page\n // error state when there is nothing usable to render.\n if (hasChatAccess && modelsError && modelsItems.length === 0) {\n return <ModelsLoadErrorEmptyState onRetry={() => refetchModels()} />;\n }\n\n if (hasChatAccess && modelsItems.length === 0) {\n return <LcoreNotConfiguredEmptyState />;\n }\n\n const resolvedSelectedModel = selectedModel || modelsItems[0]?.value || '';\n const resolvedSelectedProvider =\n selectedProvider || modelsItems[0]?.provider || '';\n\n return (\n <FileAttachmentContextProvider>\n <LightspeedChat\n selectedModel={resolvedSelectedModel}\n selectedProvider={resolvedSelectedProvider}\n topicRestrictionEnabled={topicRestrictionEnabled ?? false}\n handleSelectedModel={item => {\n setSelectedModel(item);\n setSelectedProvider(\n modelsItems.find((m: any) => m.value === item)?.provider || '',\n );\n }}\n models={modelsItems}\n userName={profile?.displayName}\n avatar={profile?.picture}\n profileLoading={profileLoading}\n />\n </FileAttachmentContextProvider>\n );\n};\n\n/**\n * @public\n */\nexport const LightspeedChatContainer = () => {\n return (\n <QueryClientProvider client={queryClient}>\n <LightspeedChatContainerInner />\n </QueryClientProvider>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"LightspeedChatContainer.esm.js","sources":["../../src/components/LightspeedChatContainer.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport '@patternfly/react-core/dist/styles/base-no-reset.css';\nimport '@patternfly/chatbot/dist/css/main.css';\n\nimport { useEffect, useLayoutEffect, useMemo, useState } from 'react';\nimport { useAsync } from 'react-use';\n\nimport { identityApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport { useTheme } from '@mui/material/styles';\nimport { QueryClientProvider } from '@tanstack/react-query';\n\nimport { useAllModels } from '../hooks/useAllModels';\nimport { useIaChatPermission } from '../hooks/useIaChatPermission';\nimport { useIaNotebooksPermission } from '../hooks/useIaNotebooksPermission';\nimport { useTopicRestrictionStatus } from '../hooks/useQuestionValidation';\nimport queryClient from '../utils/queryClient';\nimport FileAttachmentContextProvider from './AttachmentContext';\nimport { LightspeedChat } from './LightSpeedChat';\nimport {\n LcoreNotConfiguredEmptyState,\n LightspeedChatModelsLoading,\n ModelsLoadErrorEmptyState,\n} from './LightspeedChatModelsState';\n\nconst THEME_DARK = 'dark';\nconst THEME_DARK_CLASS = 'pf-v6-theme-dark';\nconst LAST_SELECTED_MODEL_KEY = 'lastSelectedModel';\n\n/**\n * Inner component that contains all the Lightspeed chat rendering logic\n */\nconst LightspeedChatContainerInner = () => {\n const {\n palette: { mode },\n } = useTheme();\n\n const identityApi = useApi(identityApiRef);\n\n const { allowed: hasChatAccess, loading: chatPermissionLoading } =\n useIaChatPermission();\n\n const { allowed: hasNotebooksAccess, loading: notebooksPermissionLoading } =\n useIaNotebooksPermission();\n\n const permissionsLoading =\n chatPermissionLoading || notebooksPermissionLoading;\n const hasPluginAccess = hasChatAccess || hasNotebooksAccess;\n\n const {\n data: models,\n isLoading: modelsLoading,\n isError: modelsError,\n refetch: refetchModels,\n } = useAllModels(hasChatAccess);\n\n const { value: profile, loading: profileLoading } = useAsync(\n async () => await identityApi.getProfileInfo(),\n );\n\n const [selectedModel, setSelectedModel] = useState('');\n const [selectedProvider, setSelectedProvider] = useState('');\n\n const { data: topicRestrictionEnabled } =\n useTopicRestrictionStatus(hasChatAccess);\n\n const modelsItems = useMemo(\n () =>\n models\n ? models\n .filter(model => model.model_type === 'llm')\n .map(m => ({\n label: m.provider_resource_id,\n value: m.provider_resource_id,\n provider: m.provider_id,\n supportsVision: m.supportsVision,\n }))\n : [],\n [models],\n );\n\n useLayoutEffect(() => {\n const htmlTagElement = document.documentElement;\n if (mode === THEME_DARK) {\n htmlTagElement.classList.add(THEME_DARK_CLASS);\n } else {\n htmlTagElement.classList.remove(THEME_DARK_CLASS);\n }\n }, [mode]);\n\n // Load last selected model from localStorage\n useEffect(() => {\n if (!hasChatAccess || modelsItems.length === 0) {\n return;\n }\n\n try {\n const storedData = localStorage.getItem(LAST_SELECTED_MODEL_KEY);\n const parsedData = storedData ? JSON.parse(storedData) : null;\n\n const storedModel = parsedData?.model\n ? modelsItems.find(m => m.value === parsedData.model)\n : null;\n\n if (storedModel) {\n setSelectedModel(storedModel.value);\n setSelectedProvider(storedModel.provider);\n } else {\n setSelectedModel(modelsItems[0].value);\n setSelectedProvider(modelsItems[0].provider);\n }\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(\n 'Error loading last selected model from localStorage:',\n error,\n );\n setSelectedModel(modelsItems[0].value);\n setSelectedProvider(modelsItems[0].provider);\n }\n }, [hasChatAccess, modelsItems]);\n\n // Save selected model to localStorage\n useEffect(() => {\n if (selectedModel && selectedProvider) {\n try {\n localStorage.setItem(\n LAST_SELECTED_MODEL_KEY,\n JSON.stringify({\n model: selectedModel,\n provider: selectedProvider,\n }),\n );\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(\n 'Error saving last selected model to localStorage:',\n error,\n );\n }\n }\n }, [selectedModel, selectedProvider]);\n\n if (permissionsLoading) {\n // Never return null inside the overlay modal: PatternFly's focus-trap requires at least\n // one tabbable node (e.g. after removing the modal close button). Locale switches can\n // briefly re-enter this loading state.\n return <LightspeedChatModelsLoading />;\n }\n\n if (!hasPluginAccess) {\n return null;\n }\n\n if (hasChatAccess && modelsLoading) {\n return <LightspeedChatModelsLoading />;\n }\n\n // TanStack Query can keep the last successful `data` while `isError` is true after a\n // failed refetch. Prefer showing chat when we still have LLM rows; only use the full-page\n // error state when there is nothing usable to render.\n if (hasChatAccess && modelsError && modelsItems.length === 0) {\n return <ModelsLoadErrorEmptyState onRetry={() => refetchModels()} />;\n }\n\n if (hasChatAccess && modelsItems.length === 0) {\n return <LcoreNotConfiguredEmptyState />;\n }\n\n const resolvedSelectedModel = selectedModel || modelsItems[0]?.value || '';\n const resolvedSelectedProvider =\n selectedProvider || modelsItems[0]?.provider || '';\n\n return (\n <FileAttachmentContextProvider>\n <LightspeedChat\n selectedModel={resolvedSelectedModel}\n selectedProvider={resolvedSelectedProvider}\n topicRestrictionEnabled={topicRestrictionEnabled ?? false}\n handleSelectedModel={item => {\n setSelectedModel(item);\n setSelectedProvider(\n modelsItems.find((m: any) => m.value === item)?.provider || '',\n );\n }}\n models={modelsItems}\n userName={profile?.displayName}\n avatar={profile?.picture}\n profileLoading={profileLoading}\n />\n </FileAttachmentContextProvider>\n );\n};\n\n/**\n * @public\n */\nexport const LightspeedChatContainer = () => {\n return (\n <QueryClientProvider client={queryClient}>\n <LightspeedChatContainerInner />\n </QueryClientProvider>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"LightspeedDrawerContext.esm.js","sources":["../../src/components/LightspeedDrawerContext.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { createContext } from 'react';\n\nimport { ChatbotDisplayMode } from '@patternfly/chatbot';\n\nimport { FileContent } from '../types';\n\n/**\n * When switching to fullscreen (embedded), open the notebooks list or a specific session.\n *\n * @public\n */\nexport type LightspeedEmbeddedNotebooksTarget =\n 'notebooks' | { notebookSessionId: string };\n\n/**\n * Type for LightspeedDrawerContext\n *\n * @public\n */\nexport interface LightspeedDrawerContextType {\n /**\n * Whether the chatbot is active\n */\n isChatbotActive: boolean;\n /**\n * Toggle the chatbot open/closed\n */\n toggleChatbot: () => void;\n /**\n * The current display mode\n */\n displayMode: ChatbotDisplayMode;\n /**\n * Set the display mode (overlay, docked, or fullscreen/embedded).\n * When entering embedded mode, optional `embeddedNotebooks` navigates to\n * `/lightspeed/notebooks` (or a session URL) instead of the chat route.\n * Notebooks are available in all display modes; the shell tab and active\n * notebook are preserved across mode switches.\n */\n setDisplayMode: (\n mode: ChatbotDisplayMode,\n conversationIdParam?: string,\n embeddedNotebooks?: LightspeedEmbeddedNotebooksTarget,\n ) => void;\n /**\n * The drawer width (for docked mode)\n */\n drawerWidth: number;\n /**\n * The function for setting the drawer width\n */\n setDrawerWidth: React.Dispatch<React.SetStateAction<number>>;\n /**\n * The current conversation ID\n */\n currentConversationId?: string;\n /**\n * Set the current conversation ID and update the route if in embedded mode\n * Pass undefined to clear the conversation (example: for new chat)\n */\n setCurrentConversationId: (id: string | undefined) => void;\n /**\n * The message in the chat input box\n * Used to preserve input content when switching between display modes\n */\n draftMessage: string;\n /**\n * To save the input message as a draft when switching modes\n */\n setDraftMessage: (message: string) => void;\n /**\n * The file attachments in the chat input\n * Used to preserve file attachments when switching between display modes\n */\n draftFileContents: FileContent[];\n /**\n * To save file attachments as a draft when switching modes\n */\n setDraftFileContents: (files: FileContent[]) => void;\n /**\n * @internal After leaving fullscreen for overlay/docked, the next overlay/docked chat\n * mount should seed the thread from currentConversationId (or TEMP) instead of storage\n * lastOpened. Returns true at most once per handoff.\n */\n consumePendingOverlayThreadHandoff?: () => boolean;\n /**\n * Chat tab is 0, Notebooks tab is 1. Persisted across overlay/docked/fullscreen remounts\n * (each display mode mounts its own `LightspeedChat` tree).\n */\n shellViewTab: number;\n setShellViewTab: (tab: number) => void;\n /**\n * ID of the currently active notebook session, persisted across\n * overlay/docked/fullscreen remounts so display-mode switches preserve\n * the open notebook.\n */\n activeNotebookId: string | undefined;\n setActiveNotebookId: (id: string | undefined) => void;\n}\n\nconst CONTEXT_KEY = '__lightspeed_drawer_context__' as keyof typeof globalThis;\n\nfunction getOrCreateContext() {\n const existing = (globalThis as any)[CONTEXT_KEY];\n if (existing)\n return existing as React.Context<LightspeedDrawerContextType | undefined>;\n const ctx = createContext<LightspeedDrawerContextType | undefined>(undefined);\n (globalThis as any)[CONTEXT_KEY] = ctx;\n return ctx;\n}\n\n/**\n * @public\n */\nexport const LightspeedDrawerContext = getOrCreateContext();\n"],"names":[],"mappings":";;AAoHA,MAAM,WAAA,GAAc,+BAAA;AAEpB,SAAS,kBAAA,GAAqB;AAC5B,EAAA,MAAM,QAAA,GAAY,WAAmB,WAAW,CAAA;AAChD,EAAA,IAAI,QAAA;AACF,IAAA,OAAO,QAAA;AACT,EAAA,MAAM,GAAA,GAAM,cAAuD,MAAS,CAAA;AAC5E,EAAC,UAAA,CAAmB,WAAW,CAAA,GAAI,GAAA;AACnC,EAAA,OAAO,GAAA;AACT;AAKO,MAAM,0BAA0B,kBAAA;;;;"}
1
+ {"version":3,"file":"LightspeedDrawerContext.esm.js","sources":["../../src/components/LightspeedDrawerContext.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { createContext } from 'react';\n\nimport { ChatbotDisplayMode } from '@patternfly/chatbot';\n\nimport type { SettingsTab } from '../hooks/useSettingsPanelUrlState';\nimport { FileContent } from '../types';\n\n/**\n * When switching to fullscreen (embedded), open the notebooks list or a specific session.\n *\n * @public\n */\nexport type LightspeedEmbeddedNotebooksTarget =\n 'notebooks' | { notebookSessionId: string };\n\n/**\n * Type for LightspeedDrawerContext\n *\n * @public\n */\nexport interface LightspeedDrawerContextType {\n /**\n * Whether the chatbot is active\n */\n isChatbotActive: boolean;\n /**\n * Toggle the chatbot open/closed\n */\n toggleChatbot: () => void;\n /**\n * The current display mode\n */\n displayMode: ChatbotDisplayMode;\n /**\n * Set the display mode (overlay, docked, or fullscreen/embedded).\n * When entering embedded mode, optional `embeddedNotebooks` navigates to\n * `/lightspeed/notebooks` (or a session URL) instead of the chat route.\n * Notebooks are available in all display modes; the shell tab and active\n * notebook are preserved across mode switches.\n */\n setDisplayMode: (\n mode: ChatbotDisplayMode,\n conversationIdParam?: string,\n embeddedNotebooks?: LightspeedEmbeddedNotebooksTarget,\n ) => void;\n /**\n * The drawer width (for docked mode)\n */\n drawerWidth: number;\n /**\n * The function for setting the drawer width\n */\n setDrawerWidth: React.Dispatch<React.SetStateAction<number>>;\n /**\n * The current conversation ID\n */\n currentConversationId?: string;\n /**\n * Set the current conversation ID and update the route if in embedded mode\n * Pass undefined to clear the conversation (example: for new chat)\n */\n setCurrentConversationId: (id: string | undefined) => void;\n /**\n * The message in the chat input box\n * Used to preserve input content when switching between display modes\n */\n draftMessage: string;\n /**\n * To save the input message as a draft when switching modes\n */\n setDraftMessage: (message: string) => void;\n /**\n * The file attachments in the chat input\n * Used to preserve file attachments when switching between display modes\n */\n draftFileContents: FileContent[];\n /**\n * To save file attachments as a draft when switching modes\n */\n setDraftFileContents: (files: FileContent[]) => void;\n /**\n * @internal After leaving fullscreen for overlay/docked, the next overlay/docked chat\n * mount should seed the thread from currentConversationId (or TEMP) instead of storage\n * lastOpened. Returns true at most once per handoff.\n */\n consumePendingOverlayThreadHandoff?: () => boolean;\n /**\n * Chat tab is 0, Notebooks tab is 1. Persisted across overlay/docked/fullscreen remounts\n * (each display mode mounts its own `LightspeedChat` tree).\n */\n shellViewTab: number;\n setShellViewTab: (tab: number) => void;\n /**\n * ID of the currently active notebook session, persisted across\n * overlay/docked/fullscreen remounts so display-mode switches preserve\n * the open notebook.\n */\n activeNotebookId: string | undefined;\n setActiveNotebookId: (id: string | undefined) => void;\n /**\n * Active settings tab when the settings panel is open; null when closed.\n * Persisted across overlay/docked/fullscreen remounts.\n */\n settingsTab: SettingsTab | null;\n setSettingsTab: (tab: SettingsTab | null) => void;\n}\n\nconst CONTEXT_KEY = '__lightspeed_drawer_context__' as keyof typeof globalThis;\n\nfunction getOrCreateContext() {\n const existing = (globalThis as any)[CONTEXT_KEY];\n if (existing)\n return existing as React.Context<LightspeedDrawerContextType | undefined>;\n const ctx = createContext<LightspeedDrawerContextType | undefined>(undefined);\n (globalThis as any)[CONTEXT_KEY] = ctx;\n return ctx;\n}\n\n/**\n * @public\n */\nexport const LightspeedDrawerContext = getOrCreateContext();\n"],"names":[],"mappings":";;AA2HA,MAAM,WAAA,GAAc,+BAAA;AAEpB,SAAS,kBAAA,GAAqB;AAC5B,EAAA,MAAM,QAAA,GAAY,WAAmB,WAAW,CAAA;AAChD,EAAA,IAAI,QAAA;AACF,IAAA,OAAO,QAAA;AACT,EAAA,MAAM,GAAA,GAAM,cAAuD,MAAS,CAAA;AAC5E,EAAC,UAAA,CAAmB,WAAW,CAAA,GAAI,GAAA;AACnC,EAAA,OAAO,GAAA;AACT;AAKO,MAAM,0BAA0B,kBAAA;;;;"}
@@ -32,6 +32,7 @@ const LightspeedDrawerProvider = ({ children }) => {
32
32
  onEscapePress: () => closeChatbot(),
33
33
  ouiaId: "LightspeedChatbotModal",
34
34
  "aria-labelledby": "lightspeed-chatpopup-modal",
35
+ "data-screen-capture-exclude": true,
35
36
  children: /* @__PURE__ */ jsx(LightspeedChatContainer, {})
36
37
  }
37
38
  )
@@ -1 +1 @@
1
- {"version":3,"file":"LightspeedDrawerProvider.esm.js","sources":["../../src/components/LightspeedDrawerProvider.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { PropsWithChildren } from 'react';\n\nimport { styled } from '@mui/material/styles';\nimport { ChatbotModal } from '@patternfly/chatbot';\n\nimport {\n DOCKED_CONTENT_OFFSET,\n LIGHTSPEED_OVERLAY_BOTTOM,\n LIGHTSPEED_OVERLAY_CHATBOT_MODAL_CLASS,\n LIGHTSPEED_OVERLAY_MAX_WIDTH,\n LIGHTSPEED_OVERLAY_RIGHT,\n} from '../const';\nimport { useLightspeedProviderState } from '../hooks/useLightspeedProviderState';\nimport { LightspeedChatContainer } from './LightspeedChatContainer';\nimport { LightspeedDrawerContext } from './LightspeedDrawerContext';\nimport { NotebookStreamProvider } from './notebooks/NotebookStreamProvider';\n\nconst StyledChatbotModal = styled(ChatbotModal)(() => ({\n boxShadow:\n '0 14px 20px -7px rgba(0, 0, 0, 0.22), 0 32px 50px 6px rgba(0, 0, 0, 0.16), 0 12px 60px 12px rgba(0, 0, 0, 0.14) !important',\n bottom: `${LIGHTSPEED_OVERLAY_BOTTOM} !important`,\n right: `${LIGHTSPEED_OVERLAY_RIGHT} !important`,\n maxWidth: `${LIGHTSPEED_OVERLAY_MAX_WIDTH} !important`,\n overflow: 'hidden',\n transition:\n 'margin-right 0.3s ease, bottom 0.3s ease, right 0.3s ease, inset-block-end 0.3s ease, inset-inline-end 0.3s ease',\n 'body.docked-drawer-open &': {\n marginRight: DOCKED_CONTENT_OFFSET,\n },\n}));\n\n/**\n * @public\n */\nexport const LightspeedDrawerProvider = ({ children }: PropsWithChildren) => {\n const { contextValue, shouldRenderOverlayModal, closeChatbot } =\n useLightspeedProviderState();\n\n return (\n <LightspeedDrawerContext.Provider value={contextValue}>\n <NotebookStreamProvider>\n {children}\n {shouldRenderOverlayModal && (\n <StyledChatbotModal\n isOpen\n className={LIGHTSPEED_OVERLAY_CHATBOT_MODAL_CLASS}\n displayMode={contextValue.displayMode}\n disableFocusTrap\n onEscapePress={() => closeChatbot()}\n ouiaId=\"LightspeedChatbotModal\"\n aria-labelledby=\"lightspeed-chatpopup-modal\"\n >\n <LightspeedChatContainer />\n </StyledChatbotModal>\n )}\n </NotebookStreamProvider>\n </LightspeedDrawerContext.Provider>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AAiCA,MAAM,kBAAA,GAAqB,MAAA,CAAO,YAAY,CAAA,CAAE,OAAO;AAAA,EACrD,SAAA,EACE,4HAAA;AAAA,EACF,MAAA,EAAQ,GAAG,yBAAyB,CAAA,WAAA,CAAA;AAAA,EACpC,KAAA,EAAO,GAAG,wBAAwB,CAAA,WAAA,CAAA;AAAA,EAClC,QAAA,EAAU,GAAG,4BAA4B,CAAA,WAAA,CAAA;AAAA,EACzC,QAAA,EAAU,QAAA;AAAA,EACV,UAAA,EACE,kHAAA;AAAA,EACF,2BAAA,EAA6B;AAAA,IAC3B,WAAA,EAAa;AAAA;AAEjB,CAAA,CAAE,CAAA;AAKK,MAAM,wBAAA,GAA2B,CAAC,EAAE,QAAA,EAAS,KAAyB;AAC3E,EAAA,MAAM,EAAE,YAAA,EAAc,wBAAA,EAA0B,YAAA,KAC9C,0BAAA,EAA2B;AAE7B,EAAA,2BACG,uBAAA,CAAwB,QAAA,EAAxB,EAAiC,KAAA,EAAO,YAAA,EACvC,+BAAC,sBAAA,EAAA,EACE,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,IACA,wBAAA,oBACC,GAAA;AAAA,MAAC,kBAAA;AAAA,MAAA;AAAA,QACC,MAAA,EAAM,IAAA;AAAA,QACN,SAAA,EAAW,sCAAA;AAAA,QACX,aAAa,YAAA,CAAa,WAAA;AAAA,QAC1B,gBAAA,EAAgB,IAAA;AAAA,QAChB,aAAA,EAAe,MAAM,YAAA,EAAa;AAAA,QAClC,MAAA,EAAO,wBAAA;AAAA,QACP,iBAAA,EAAgB,4BAAA;AAAA,QAEhB,8BAAC,uBAAA,EAAA,EAAwB;AAAA;AAAA;AAC3B,GAAA,EAEJ,CAAA,EACF,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"LightspeedDrawerProvider.esm.js","sources":["../../src/components/LightspeedDrawerProvider.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { PropsWithChildren } from 'react';\n\nimport { styled } from '@mui/material/styles';\nimport { ChatbotModal } from '@patternfly/chatbot';\n\nimport {\n DOCKED_CONTENT_OFFSET,\n LIGHTSPEED_OVERLAY_BOTTOM,\n LIGHTSPEED_OVERLAY_CHATBOT_MODAL_CLASS,\n LIGHTSPEED_OVERLAY_MAX_WIDTH,\n LIGHTSPEED_OVERLAY_RIGHT,\n} from '../const';\nimport { useLightspeedProviderState } from '../hooks/useLightspeedProviderState';\nimport { LightspeedChatContainer } from './LightspeedChatContainer';\nimport { LightspeedDrawerContext } from './LightspeedDrawerContext';\nimport { NotebookStreamProvider } from './notebooks/NotebookStreamProvider';\n\nconst StyledChatbotModal = styled(ChatbotModal)(() => ({\n boxShadow:\n '0 14px 20px -7px rgba(0, 0, 0, 0.22), 0 32px 50px 6px rgba(0, 0, 0, 0.16), 0 12px 60px 12px rgba(0, 0, 0, 0.14) !important',\n bottom: `${LIGHTSPEED_OVERLAY_BOTTOM} !important`,\n right: `${LIGHTSPEED_OVERLAY_RIGHT} !important`,\n maxWidth: `${LIGHTSPEED_OVERLAY_MAX_WIDTH} !important`,\n overflow: 'hidden',\n transition:\n 'margin-right 0.3s ease, bottom 0.3s ease, right 0.3s ease, inset-block-end 0.3s ease, inset-inline-end 0.3s ease',\n 'body.docked-drawer-open &': {\n marginRight: DOCKED_CONTENT_OFFSET,\n },\n}));\n\n/**\n * @public\n */\nexport const LightspeedDrawerProvider = ({ children }: PropsWithChildren) => {\n const { contextValue, shouldRenderOverlayModal, closeChatbot } =\n useLightspeedProviderState();\n\n return (\n <LightspeedDrawerContext.Provider value={contextValue}>\n <NotebookStreamProvider>\n {children}\n {shouldRenderOverlayModal && (\n <StyledChatbotModal\n isOpen\n className={LIGHTSPEED_OVERLAY_CHATBOT_MODAL_CLASS}\n displayMode={contextValue.displayMode}\n disableFocusTrap\n onEscapePress={() => closeChatbot()}\n ouiaId=\"LightspeedChatbotModal\"\n aria-labelledby=\"lightspeed-chatpopup-modal\"\n data-screen-capture-exclude\n >\n <LightspeedChatContainer />\n </StyledChatbotModal>\n )}\n </NotebookStreamProvider>\n </LightspeedDrawerContext.Provider>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AAiCA,MAAM,kBAAA,GAAqB,MAAA,CAAO,YAAY,CAAA,CAAE,OAAO;AAAA,EACrD,SAAA,EACE,4HAAA;AAAA,EACF,MAAA,EAAQ,GAAG,yBAAyB,CAAA,WAAA,CAAA;AAAA,EACpC,KAAA,EAAO,GAAG,wBAAwB,CAAA,WAAA,CAAA;AAAA,EAClC,QAAA,EAAU,GAAG,4BAA4B,CAAA,WAAA,CAAA;AAAA,EACzC,QAAA,EAAU,QAAA;AAAA,EACV,UAAA,EACE,kHAAA;AAAA,EACF,2BAAA,EAA6B;AAAA,IAC3B,WAAA,EAAa;AAAA;AAEjB,CAAA,CAAE,CAAA;AAKK,MAAM,wBAAA,GAA2B,CAAC,EAAE,QAAA,EAAS,KAAyB;AAC3E,EAAA,MAAM,EAAE,YAAA,EAAc,wBAAA,EAA0B,YAAA,KAC9C,0BAAA,EAA2B;AAE7B,EAAA,2BACG,uBAAA,CAAwB,QAAA,EAAxB,EAAiC,KAAA,EAAO,YAAA,EACvC,+BAAC,sBAAA,EAAA,EACE,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,IACA,wBAAA,oBACC,GAAA;AAAA,MAAC,kBAAA;AAAA,MAAA;AAAA,QACC,MAAA,EAAM,IAAA;AAAA,QACN,SAAA,EAAW,sCAAA;AAAA,QACX,aAAa,YAAA,CAAa,WAAA;AAAA,QAC1B,gBAAA,EAAgB,IAAA;AAAA,QAChB,aAAA,EAAe,MAAM,YAAA,EAAa;AAAA,QAClC,MAAA,EAAO,wBAAA;AAAA,QACP,iBAAA,EAAgB,4BAAA;AAAA,QAChB,6BAAA,EAA2B,IAAA;AAAA,QAE3B,8BAAC,uBAAA,EAAA,EAAwB;AAAA;AAAA;AAC3B,GAAA,EAEJ,CAAA,EACF,CAAA;AAEJ;;;;"}
@@ -4,8 +4,8 @@ import { useApi, configApiRef, fetchApiRef } from '@backstage/core-plugin-api';
4
4
  import GlobalStyles from '@mui/material/GlobalStyles';
5
5
  import { styled } from '@mui/material/styles';
6
6
  import Typography from '@mui/material/Typography';
7
- import { Title, Button, Alert, Switch, Tooltip } from '@patternfly/react-core';
8
- import { TimesIcon, PencilAltIcon, SortAmountDownIcon, KeyIcon, InfoCircleIcon, ExclamationCircleIcon, CheckCircleIcon, SortAmountUpIcon } from '@patternfly/react-icons';
7
+ import { Title, Alert, Button, Switch, Tooltip } from '@patternfly/react-core';
8
+ import { PencilAltIcon, SortAmountDownIcon, KeyIcon, InfoCircleIcon, ExclamationCircleIcon, CheckCircleIcon, SortAmountUpIcon } from '@patternfly/react-icons';
9
9
  import { Table, Thead, Tr, Th, Tbody, Td } from '@patternfly/react-table';
10
10
  import { useIaMcpToolsPermission } from '../hooks/useIaMcpToolsPermission.esm.js';
11
11
  import { useMcpConfigureModal } from '../hooks/useMcpConfigureModal.esm.js';
@@ -204,7 +204,6 @@ const toUiServer = (server, validationError) => ({
204
204
  auth: server.auth
205
205
  });
206
206
  const McpServersSettings = ({
207
- onClose,
208
207
  backgroundColor
209
208
  }) => {
210
209
  const { t } = useTranslation();
@@ -412,25 +411,13 @@ const McpServersSettings = ({
412
411
  }
413
412
  }
414
413
  ),
415
- /* @__PURE__ */ jsxs("div", { className: mcpClasses.headerRow, children: [
416
- /* @__PURE__ */ jsxs("div", { children: [
417
- /* @__PURE__ */ jsx(Title, { headingLevel: "h2", size: "xl", className: mcpClasses.title, children: t("mcp.settings.title") }),
418
- /* @__PURE__ */ jsx("div", { className: mcpClasses.selectedCount, children: t("mcp.settings.selectedCount", {
419
- selectedCount: String(selectedCount),
420
- totalCount: String(servers.length)
421
- }) })
422
- ] }),
423
- /* @__PURE__ */ jsx(
424
- Button,
425
- {
426
- "aria-label": t("mcp.settings.closeAriaLabel"),
427
- icon: /* @__PURE__ */ jsx(TimesIcon, {}),
428
- variant: "plain",
429
- className: mcpClasses.closeButton,
430
- onClick: onClose
431
- }
432
- )
433
- ] }),
414
+ /* @__PURE__ */ jsx("div", { className: mcpClasses.headerRow, children: /* @__PURE__ */ jsxs("div", { children: [
415
+ /* @__PURE__ */ jsx(Title, { headingLevel: "h2", size: "xl", className: mcpClasses.title, children: t("mcp.settings.title") }),
416
+ /* @__PURE__ */ jsx("div", { className: mcpClasses.selectedCount, children: t("mcp.settings.selectedCount", {
417
+ selectedCount: String(selectedCount),
418
+ totalCount: String(servers.length)
419
+ }) })
420
+ ] }) }),
434
421
  error && /* @__PURE__ */ jsx(
435
422
  Alert,
436
423
  {
@@ -1 +1 @@
1
- {"version":3,"file":"McpServersSettings.esm.js","sources":["../../src/components/McpServersSettings.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useCallback, useEffect, useState } from 'react';\n\nimport { configApiRef, fetchApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport GlobalStyles from '@mui/material/GlobalStyles';\nimport { styled } from '@mui/material/styles';\nimport Typography from '@mui/material/Typography';\nimport { Alert, Button, Switch, Title, Tooltip } from '@patternfly/react-core';\nimport {\n CheckCircleIcon,\n ExclamationCircleIcon,\n InfoCircleIcon,\n KeyIcon,\n PencilAltIcon,\n SortAmountDownIcon,\n SortAmountUpIcon,\n TimesIcon,\n} from '@patternfly/react-icons';\nimport { Table, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table';\n\nimport { useIaMcpToolsPermission } from '../hooks/useIaMcpToolsPermission';\nimport { useMcpConfigureModal } from '../hooks/useMcpConfigureModal';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { McpConfigureServerModal } from './McpConfigureServerModal';\nimport {\n compareMcpServers,\n formatApiError,\n getDisplayDetail,\n getDisplayStatus,\n getEnabledToggleChecked,\n isEnabledToggleUnavailable,\n type McpConfigureServer,\n type McpServerSortColumn,\n type ServerStatus,\n} from './mcpServersDisplayUtils';\n\ntype McpServer = McpConfigureServer;\n\ntype McpServersSettingsProps = {\n onClose: () => void;\n backgroundColor?: string;\n};\n\nconst mcpClasses = {\n headerRow: 'ia-mcp-headerRow',\n selectedCount: 'ia-mcp-selectedCount',\n title: 'ia-mcp-title',\n closeButton: 'ia-mcp-closeButton',\n nameHeaderButton: 'ia-mcp-nameHeaderButton',\n statusHeaderButton: 'ia-mcp-statusHeaderButton',\n sortHeaderIconActive: 'ia-mcp-sortHeaderIconActive',\n sortHeaderIconInactive: 'ia-mcp-sortHeaderIconInactive',\n nameHeaderText: 'ia-mcp-nameHeaderText',\n nameCell: 'ia-mcp-nameCell',\n statusHeader: 'ia-mcp-statusHeader',\n statusColumnCell: 'ia-mcp-statusColumnCell',\n rowName: 'ia-mcp-rowName',\n nameValue: 'ia-mcp-nameValue',\n statusCell: 'ia-mcp-statusCell',\n statusValue: 'ia-mcp-statusValue',\n statusOk: 'ia-mcp-statusOk',\n statusWarn: 'ia-mcp-statusWarn',\n statusDisabled: 'ia-mcp-statusDisabled',\n actionButton: 'ia-mcp-actionButton',\n tableRow: 'ia-mcp-tableRow',\n toggleCell: 'ia-mcp-toggleCell',\n table: 'ia-mcp-table',\n alert: 'ia-mcp-alert',\n} as const;\n\nconst StyledMcpRoot = styled('div')(({ theme }) => ({\n padding: 0,\n height: '100%',\n minHeight: 0,\n flex: 1,\n width: '100%',\n overflow: 'auto',\n [`& .${mcpClasses.headerRow}`]: {\n display: 'flex',\n alignItems: 'flex-start',\n justifyContent: 'space-between',\n marginBottom: theme.spacing(2),\n marginTop: theme.spacing(2),\n marginLeft: theme.spacing(3),\n marginRight: theme.spacing(2),\n },\n [`& .${mcpClasses.selectedCount}`]: {\n color: theme.palette.text.secondary,\n marginTop: theme.spacing(0.5),\n fontSize: '0.75rem',\n },\n [`& .${mcpClasses.title}`]: {\n fontSize: '1.125rem',\n },\n [`& .${mcpClasses.closeButton}`]: {\n marginTop: theme.spacing(-1),\n marginRight: theme.spacing(-1),\n color: theme.palette.text.primary,\n },\n [`& .${mcpClasses.nameHeaderButton}`]: {\n paddingLeft: 0,\n paddingTop: 0,\n paddingBottom: 0,\n marginLeft: '-0.85rem',\n fontWeight: 600,\n fontSize: '0.75rem',\n lineHeight: '1.25rem',\n minHeight: 'auto',\n color: theme.palette.text.primary,\n textDecoration: 'none !important',\n display: 'inline-flex',\n alignItems: 'center',\n },\n [`& .${mcpClasses.statusHeaderButton}`]: {\n paddingLeft: 0,\n paddingTop: 0,\n paddingBottom: 0,\n fontWeight: 600,\n fontSize: '0.75rem',\n lineHeight: '1.25rem',\n minHeight: 'auto',\n color: theme.palette.text.primary,\n textDecoration: 'none !important',\n display: 'inline-flex',\n alignItems: 'center',\n },\n [`& .${mcpClasses.sortHeaderIconActive}`]: {\n color: 'var(--pf-t--global--icon--color--brand--default)',\n },\n [`& .${mcpClasses.sortHeaderIconInactive}`]: {\n color: 'var(--pf-t--global--icon--color--subtle)',\n },\n [`& .${mcpClasses.nameHeaderText}`]: {\n paddingLeft: '7px',\n fontSize: '0.75rem',\n lineHeight: '1.25rem',\n fontWeight: 600,\n },\n [`& .${mcpClasses.nameCell}`]: {\n paddingLeft: '8px !important',\n },\n [`& .${mcpClasses.statusHeader}`]: {\n paddingLeft: '0 !important',\n },\n [`& .${mcpClasses.statusColumnCell}`]: {\n paddingLeft: '0 !important',\n },\n [`& .${mcpClasses.rowName}`]: {\n fontSize: '1rem',\n fontWeight: 500,\n whiteSpace: 'nowrap',\n },\n [`& .${mcpClasses.nameValue}`]: {\n fontSize: '0.875rem',\n fontWeight: 500,\n },\n [`& .${mcpClasses.statusCell}`]: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n whiteSpace: 'nowrap',\n },\n [`& .${mcpClasses.statusValue}`]: {\n fontSize: '0.875rem',\n },\n [`& .${mcpClasses.statusOk}`]: {\n color: 'var(--pf-t--global--icon--color--status--custom--default)',\n },\n [`& .${mcpClasses.statusWarn}`]: {\n color: 'var(--pf-t--global--icon--color--status--danger--default)',\n },\n [`& .${mcpClasses.statusDisabled}`]: {\n color: 'var(--pf-t--global--icon--color--subtle)',\n },\n [`& .${mcpClasses.actionButton}`]: {\n color: theme.palette.text.secondary,\n opacity: 0,\n transition: 'opacity 0.15s ease-in-out',\n },\n [`& .${mcpClasses.tableRow}:hover .${mcpClasses.actionButton}, & .${mcpClasses.tableRow}:focus-within .${mcpClasses.actionButton}`]:\n {\n opacity: 1,\n },\n [`& .${mcpClasses.toggleCell}`]: {\n paddingRight: '0 !important',\n },\n [`& .${mcpClasses.table}`]: {\n width: '100%',\n backgroundColor: 'transparent',\n '--pf-v6-c-table--BackgroundColor': 'transparent',\n '--pf-v5-c-table--BackgroundColor': 'transparent',\n '& table, & thead, & tbody, & tr, & th, & td': {\n backgroundColor: 'transparent !important',\n },\n '& th': {\n borderBottom: 0,\n fontSize: '0.75rem',\n fontWeight: 600,\n color: theme.palette.text.primary,\n whiteSpace: 'nowrap',\n textAlign: 'left',\n },\n '& td': {\n borderBottom: 0,\n paddingTop: theme.spacing(1.5),\n paddingBottom: theme.spacing(1.5),\n verticalAlign: 'middle',\n },\n },\n [`& .${mcpClasses.alert}`]: {\n marginLeft: theme.spacing(3),\n marginRight: theme.spacing(3),\n marginBottom: theme.spacing(2),\n },\n}));\n\ntype McpServerResponse = {\n name: string;\n url?: string;\n enabled: boolean;\n status: 'connected' | 'error' | 'unknown';\n toolCount: number;\n hasToken: boolean;\n hasUserToken: boolean;\n hasOrgToken: boolean;\n auth?: string;\n};\n\ntype McpServersListResponse = {\n servers?: McpServerResponse[];\n};\n\ntype McpServersPatchResponse = {\n server?: McpServerResponse;\n validation?: {\n error?: string;\n };\n};\n\ntype McpToolInfo = {\n name: string;\n description?: string;\n};\n\ntype McpServersValidateResponse = {\n name: string;\n status: 'connected' | 'error' | 'unknown';\n toolCount: number;\n validation?: {\n error?: unknown;\n tools?: McpToolInfo[];\n };\n};\n\ntype McpCredentialsValidateResponse = {\n valid: boolean;\n error?: unknown;\n toolCount: number;\n tools?: McpToolInfo[];\n};\n\nconst getStatusIcon = (status: ServerStatus, className: string) => {\n if (status === 'tokenRequired') return <KeyIcon className={className} />;\n if (status === 'disabled') return <InfoCircleIcon className={className} />;\n if (status === 'failed')\n return <ExclamationCircleIcon className={className} />;\n return <CheckCircleIcon className={className} />;\n};\n\nconst toUiServer = (\n server: McpServerResponse,\n validationError?: string,\n): McpServer => ({\n id: server.name,\n name: server.name,\n url: server.url,\n enabled: server.enabled,\n status: server.status,\n toolCount: server.toolCount,\n hasToken: server.hasToken,\n hasUserToken: server.hasUserToken,\n hasOrgToken: server.hasOrgToken,\n validationError: server.status === 'error' ? validationError : undefined,\n auth: server.auth,\n});\nexport const McpServersSettings = ({\n onClose,\n backgroundColor,\n}: McpServersSettingsProps) => {\n const { t } = useTranslation();\n const configApi = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const { allowed: hasMcpToolsAccess, loading: mcpToolsPermissionLoading } =\n useIaMcpToolsPermission();\n\n const [servers, setServers] = useState<McpServer[]>([]);\n const [sortColumn, setSortColumn] = useState<McpServerSortColumn>('name');\n const [sortAsc, setSortAsc] = useState(true);\n const [isLoading, setIsLoading] = useState(true);\n const [isSaving, setIsSaving] = useState<Record<string, boolean>>({});\n const [error, setError] = useState<string | null>(null);\n\n const getBaseUrl = useCallback(() => {\n return `${configApi.getString('backend.baseUrl')}/api/intelligent-assistant`;\n }, [configApi]);\n\n const fetchJson = useCallback(\n async <T,>(url: string, init?: RequestInit): Promise<T> => {\n const response = await fetchApi.fetch(url, {\n headers: {\n 'Content-Type': 'application/json',\n },\n ...init,\n });\n if (!response.ok) {\n let message = `${response.status} ${response.statusText}`;\n try {\n const bodyText = await response.text();\n if (bodyText) {\n const parsed = JSON.parse(bodyText);\n if (parsed?.error) {\n message = parsed.error;\n }\n }\n } catch {\n // Keep default message when parsing fails.\n }\n throw new Error(message);\n }\n\n const text = await response.text();\n return (text ? JSON.parse(text) : {}) as T;\n },\n [fetchApi],\n );\n\n const fetchServerValidation = useCallback(\n async (serverName: string) => {\n const baseUrl = getBaseUrl();\n return fetchJson<McpServersValidateResponse>(\n `${baseUrl}/mcp-servers/${encodeURIComponent(serverName)}/validate`,\n {\n method: 'POST',\n },\n );\n },\n [fetchJson, getBaseUrl],\n );\n\n const validateServer = useCallback(\n async (serverName: string) => {\n const data = await fetchServerValidation(serverName);\n\n setServers(prev =>\n prev.map(server =>\n server.name === serverName\n ? {\n ...server,\n status: data.status,\n toolCount: data.toolCount,\n validationError:\n data.status === 'error'\n ? formatApiError(data.validation?.error) ||\n 'Validation failed'\n : undefined,\n }\n : server,\n ),\n );\n return data;\n },\n [fetchServerValidation],\n );\n\n const validateCredentials = useCallback(\n async (url: string, token: string) => {\n const baseUrl = getBaseUrl();\n return await fetchJson<McpCredentialsValidateResponse>(\n `${baseUrl}/mcp-servers/validate`,\n {\n method: 'POST',\n body: JSON.stringify({ url, token }),\n },\n );\n },\n [fetchJson, getBaseUrl],\n );\n const loadServers = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n try {\n const baseUrl = getBaseUrl();\n const data = await fetchJson<McpServersListResponse>(\n `${baseUrl}/mcp-servers`,\n );\n const uiServers = (data.servers ?? []).map(server => toUiServer(server));\n setServers(uiServers);\n\n const serversToValidate = uiServers.filter(server => server.hasToken);\n void Promise.allSettled(\n serversToValidate.map(async server => {\n try {\n await validateServer(server.name);\n } catch (validationError) {\n setError(\n prev =>\n prev ??\n (validationError instanceof Error\n ? validationError.message\n : `Failed to validate ${server.name}`),\n );\n }\n }),\n );\n } catch (e) {\n setError(\n e instanceof Error ? e.message : 'Failed to load MCP server settings',\n );\n } finally {\n setIsLoading(false);\n }\n }, [fetchJson, getBaseUrl, validateServer]);\n\n useEffect(() => {\n if (mcpToolsPermissionLoading || !hasMcpToolsAccess) {\n return;\n }\n loadServers();\n }, [loadServers, mcpToolsPermissionLoading, hasMcpToolsAccess]);\n\n const patchServer = useCallback(\n async (\n serverName: string,\n body: { enabled?: boolean; token?: string | null },\n ) => {\n setError(null);\n setIsSaving(prev => ({ ...prev, [serverName]: true }));\n try {\n const baseUrl = getBaseUrl();\n const data = await fetchJson<McpServersPatchResponse>(\n `${baseUrl}/mcp-servers/${encodeURIComponent(serverName)}`,\n {\n method: 'PATCH',\n body: JSON.stringify(body),\n },\n );\n\n if (data.server) {\n setServers(prev =>\n prev.map(server =>\n server.name === serverName\n ? toUiServer(data.server!, data.validation?.error)\n : server,\n ),\n );\n } else {\n await loadServers();\n }\n } catch (e) {\n setError(\n e instanceof Error\n ? e.message\n : `Failed to update ${serverName} settings`,\n );\n throw e;\n } finally {\n setIsSaving(prev => ({ ...prev, [serverName]: false }));\n }\n },\n [fetchJson, getBaseUrl, loadServers],\n );\n\n const configureModal = useMcpConfigureModal({\n servers,\n isSaving,\n patchServer,\n validateServer,\n validateCredentials,\n fetchServerValidation,\n });\n\n const selectedCount = servers.filter(server => {\n const displayStatus = getDisplayStatus(server);\n const isUnavailable =\n displayStatus === 'failed' || displayStatus === 'tokenRequired';\n return server.enabled && !isUnavailable;\n }).length;\n\n const sortedServers = [...servers].sort((a, b) =>\n compareMcpServers(a, b, sortColumn, sortAsc),\n );\n\n const onSortColumnClick = (column: McpServerSortColumn) => {\n if (sortColumn === column) {\n setSortAsc(prev => !prev);\n return;\n }\n setSortColumn(column);\n setSortAsc(true);\n };\n\n const renderSortIcon = (column: McpServerSortColumn) => {\n const isActive = sortColumn === column;\n let Icon = SortAmountDownIcon;\n if (isActive && !sortAsc) {\n Icon = SortAmountUpIcon;\n }\n\n return (\n <Icon\n className={\n isActive\n ? mcpClasses.sortHeaderIconActive\n : mcpClasses.sortHeaderIconInactive\n }\n />\n );\n };\n\n if (mcpToolsPermissionLoading || !hasMcpToolsAccess) {\n return null;\n }\n\n return (\n <StyledMcpRoot style={backgroundColor ? { backgroundColor } : undefined}>\n <GlobalStyles\n styles={{\n '.pf-v6-c-backdrop': {\n zIndex: '1400 !important',\n },\n '.pf-v5-c-backdrop': {\n zIndex: '1400 !important',\n },\n }}\n />\n <div className={mcpClasses.headerRow}>\n <div>\n <Title headingLevel=\"h2\" size=\"xl\" className={mcpClasses.title}>\n {t('mcp.settings.title')}\n </Title>\n <div className={mcpClasses.selectedCount}>\n {t('mcp.settings.selectedCount' as any, {\n selectedCount: String(selectedCount),\n totalCount: String(servers.length),\n })}\n </div>\n </div>\n <Button\n aria-label={t('mcp.settings.closeAriaLabel')}\n icon={<TimesIcon />}\n variant=\"plain\"\n className={mcpClasses.closeButton}\n onClick={onClose}\n />\n </div>\n {error && (\n <Alert\n variant=\"danger\"\n isInline\n title={error}\n className={mcpClasses.alert}\n />\n )}\n <Table\n variant=\"compact\"\n aria-label={t('mcp.settings.tableAriaLabel')}\n className={mcpClasses.table}\n >\n <Thead>\n <Tr>\n <Th width={10} screenReaderText={t('mcp.settings.enabled')} />\n <Th>\n <Button\n variant=\"link\"\n className={mcpClasses.nameHeaderButton}\n icon={renderSortIcon('name')}\n iconPosition=\"right\"\n onClick={() => onSortColumnClick('name')}\n >\n <Typography\n component=\"span\"\n className={mcpClasses.nameHeaderText}\n >\n {t('mcp.settings.name')}\n </Typography>\n </Button>\n </Th>\n <Th className={mcpClasses.statusHeader}>\n <Button\n variant=\"link\"\n className={mcpClasses.statusHeaderButton}\n icon={renderSortIcon('status')}\n iconPosition=\"right\"\n onClick={() => onSortColumnClick('status')}\n >\n <Typography\n component=\"span\"\n className={mcpClasses.nameHeaderText}\n >\n {t('mcp.settings.status')}\n </Typography>\n </Button>\n </Th>\n <Th screenReaderText={t('mcp.settings.edit')} />\n </Tr>\n </Thead>\n <Tbody>\n {isLoading && (\n <Tr>\n <Td colSpan={4}>{t('mcp.settings.loading')}</Td>\n </Tr>\n )}\n {!isLoading && sortedServers.length === 0 && (\n <Tr>\n <Td colSpan={4}>{t('mcp.settings.noneAvailable')}</Td>\n </Tr>\n )}\n {sortedServers.map(server => {\n const displayStatus = getDisplayStatus(server);\n const displayDetail = getDisplayDetail(server, displayStatus, t);\n let statusClass:\n | typeof mcpClasses.statusOk\n | typeof mcpClasses.statusWarn\n | typeof mcpClasses.statusDisabled = mcpClasses.statusWarn;\n if (displayStatus === 'ok') {\n statusClass = mcpClasses.statusOk;\n } else if (displayStatus === 'disabled') {\n statusClass = mcpClasses.statusDisabled;\n }\n\n return (\n <Tr key={server.id} className={mcpClasses.tableRow}>\n <Td width={10} className={mcpClasses.toggleCell}>\n {(() => {\n const isUnavailable =\n isEnabledToggleUnavailable(displayStatus);\n const isChecked = getEnabledToggleChecked(\n server,\n displayStatus,\n );\n const isRowSaving = Boolean(isSaving[server.name]);\n const isToggleDisabled = isUnavailable || isRowSaving;\n const switchControl = (\n <Switch\n id={`mcp-switch-${server.id}`}\n aria-label={t(\n 'mcp.settings.toggleServerAriaLabel' as any,\n {\n serverName: server.name,\n },\n )}\n isChecked={isChecked}\n isDisabled={isToggleDisabled}\n onChange={(_event, checked) => {\n void patchServer(server.name, {\n enabled: checked,\n }).catch(() => {\n // patchServer already updates component error state.\n // Swallow here to avoid unhandled promise rejections\n // from event-handler fire-and-forget usage.\n });\n }}\n />\n );\n\n if (!isToggleDisabled) {\n return switchControl;\n }\n\n return (\n <Tooltip content={displayDetail}>\n <Typography component=\"span\">\n {switchControl}\n </Typography>\n </Tooltip>\n );\n })()}\n </Td>\n <Td\n width={35}\n className={`${mcpClasses.rowName} ${mcpClasses.nameCell}`}\n >\n <Typography component=\"span\" className={mcpClasses.nameValue}>\n {server.name}\n </Typography>\n </Td>\n <Td width={40} className={mcpClasses.statusColumnCell}>\n <div className={mcpClasses.statusCell}>\n {getStatusIcon(displayStatus, statusClass)}\n {displayStatus === 'failed' ? (\n <Tooltip\n content={\n server.validationError ??\n t('mcp.settings.token.validationFailed')\n }\n >\n <Typography\n component=\"span\"\n className={mcpClasses.statusValue}\n >\n {displayDetail}\n </Typography>\n </Tooltip>\n ) : (\n <Typography\n component=\"span\"\n className={mcpClasses.statusValue}\n >\n {displayDetail}\n </Typography>\n )}\n </div>\n </Td>\n <Td width={15} isActionCell style={{ textAlign: 'right' }}>\n <Button\n aria-label={t('mcp.settings.editServerAriaLabel' as any, {\n serverName: server.name,\n })}\n icon={<PencilAltIcon />}\n variant=\"plain\"\n className={mcpClasses.actionButton}\n onClick={() => configureModal.open(server)}\n />\n </Td>\n </Tr>\n );\n })}\n </Tbody>\n </Table>\n <McpConfigureServerModal {...configureModal} />\n </StyledMcpRoot>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"McpServersSettings.esm.js","sources":["../../src/components/McpServersSettings.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useCallback, useEffect, useState } from 'react';\n\nimport { configApiRef, fetchApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport GlobalStyles from '@mui/material/GlobalStyles';\nimport { styled } from '@mui/material/styles';\nimport Typography from '@mui/material/Typography';\nimport { Alert, Button, Switch, Title, Tooltip } from '@patternfly/react-core';\nimport {\n CheckCircleIcon,\n ExclamationCircleIcon,\n InfoCircleIcon,\n KeyIcon,\n PencilAltIcon,\n SortAmountDownIcon,\n SortAmountUpIcon,\n} from '@patternfly/react-icons';\nimport { Table, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table';\n\nimport { useIaMcpToolsPermission } from '../hooks/useIaMcpToolsPermission';\nimport { useMcpConfigureModal } from '../hooks/useMcpConfigureModal';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { McpConfigureServerModal } from './McpConfigureServerModal';\nimport {\n compareMcpServers,\n formatApiError,\n getDisplayDetail,\n getDisplayStatus,\n getEnabledToggleChecked,\n isEnabledToggleUnavailable,\n type McpConfigureServer,\n type McpServerSortColumn,\n type ServerStatus,\n} from './mcpServersDisplayUtils';\n\ntype McpServer = McpConfigureServer;\n\ntype McpServersSettingsProps = {\n backgroundColor?: string;\n};\n\nconst mcpClasses = {\n headerRow: 'ia-mcp-headerRow',\n selectedCount: 'ia-mcp-selectedCount',\n title: 'ia-mcp-title',\n closeButton: 'ia-mcp-closeButton',\n nameHeaderButton: 'ia-mcp-nameHeaderButton',\n statusHeaderButton: 'ia-mcp-statusHeaderButton',\n sortHeaderIconActive: 'ia-mcp-sortHeaderIconActive',\n sortHeaderIconInactive: 'ia-mcp-sortHeaderIconInactive',\n nameHeaderText: 'ia-mcp-nameHeaderText',\n nameCell: 'ia-mcp-nameCell',\n statusHeader: 'ia-mcp-statusHeader',\n statusColumnCell: 'ia-mcp-statusColumnCell',\n rowName: 'ia-mcp-rowName',\n nameValue: 'ia-mcp-nameValue',\n statusCell: 'ia-mcp-statusCell',\n statusValue: 'ia-mcp-statusValue',\n statusOk: 'ia-mcp-statusOk',\n statusWarn: 'ia-mcp-statusWarn',\n statusDisabled: 'ia-mcp-statusDisabled',\n actionButton: 'ia-mcp-actionButton',\n tableRow: 'ia-mcp-tableRow',\n toggleCell: 'ia-mcp-toggleCell',\n table: 'ia-mcp-table',\n alert: 'ia-mcp-alert',\n} as const;\n\nconst StyledMcpRoot = styled('div')(({ theme }) => ({\n padding: 0,\n height: '100%',\n minHeight: 0,\n flex: 1,\n width: '100%',\n overflow: 'auto',\n [`& .${mcpClasses.headerRow}`]: {\n display: 'flex',\n alignItems: 'flex-start',\n justifyContent: 'space-between',\n marginBottom: theme.spacing(2),\n marginTop: theme.spacing(2),\n marginLeft: theme.spacing(3),\n marginRight: theme.spacing(2),\n },\n [`& .${mcpClasses.selectedCount}`]: {\n color: theme.palette.text.secondary,\n marginTop: theme.spacing(0.5),\n fontSize: '0.75rem',\n },\n [`& .${mcpClasses.title}`]: {\n fontSize: '1.125rem',\n },\n [`& .${mcpClasses.closeButton}`]: {\n marginTop: theme.spacing(-1),\n marginRight: theme.spacing(-1),\n color: theme.palette.text.primary,\n },\n [`& .${mcpClasses.nameHeaderButton}`]: {\n paddingLeft: 0,\n paddingTop: 0,\n paddingBottom: 0,\n marginLeft: '-0.85rem',\n fontWeight: 600,\n fontSize: '0.75rem',\n lineHeight: '1.25rem',\n minHeight: 'auto',\n color: theme.palette.text.primary,\n textDecoration: 'none !important',\n display: 'inline-flex',\n alignItems: 'center',\n },\n [`& .${mcpClasses.statusHeaderButton}`]: {\n paddingLeft: 0,\n paddingTop: 0,\n paddingBottom: 0,\n fontWeight: 600,\n fontSize: '0.75rem',\n lineHeight: '1.25rem',\n minHeight: 'auto',\n color: theme.palette.text.primary,\n textDecoration: 'none !important',\n display: 'inline-flex',\n alignItems: 'center',\n },\n [`& .${mcpClasses.sortHeaderIconActive}`]: {\n color: 'var(--pf-t--global--icon--color--brand--default)',\n },\n [`& .${mcpClasses.sortHeaderIconInactive}`]: {\n color: 'var(--pf-t--global--icon--color--subtle)',\n },\n [`& .${mcpClasses.nameHeaderText}`]: {\n paddingLeft: '7px',\n fontSize: '0.75rem',\n lineHeight: '1.25rem',\n fontWeight: 600,\n },\n [`& .${mcpClasses.nameCell}`]: {\n paddingLeft: '8px !important',\n },\n [`& .${mcpClasses.statusHeader}`]: {\n paddingLeft: '0 !important',\n },\n [`& .${mcpClasses.statusColumnCell}`]: {\n paddingLeft: '0 !important',\n },\n [`& .${mcpClasses.rowName}`]: {\n fontSize: '1rem',\n fontWeight: 500,\n whiteSpace: 'nowrap',\n },\n [`& .${mcpClasses.nameValue}`]: {\n fontSize: '0.875rem',\n fontWeight: 500,\n },\n [`& .${mcpClasses.statusCell}`]: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n whiteSpace: 'nowrap',\n },\n [`& .${mcpClasses.statusValue}`]: {\n fontSize: '0.875rem',\n },\n [`& .${mcpClasses.statusOk}`]: {\n color: 'var(--pf-t--global--icon--color--status--custom--default)',\n },\n [`& .${mcpClasses.statusWarn}`]: {\n color: 'var(--pf-t--global--icon--color--status--danger--default)',\n },\n [`& .${mcpClasses.statusDisabled}`]: {\n color: 'var(--pf-t--global--icon--color--subtle)',\n },\n [`& .${mcpClasses.actionButton}`]: {\n color: theme.palette.text.secondary,\n opacity: 0,\n transition: 'opacity 0.15s ease-in-out',\n },\n [`& .${mcpClasses.tableRow}:hover .${mcpClasses.actionButton}, & .${mcpClasses.tableRow}:focus-within .${mcpClasses.actionButton}`]:\n {\n opacity: 1,\n },\n [`& .${mcpClasses.toggleCell}`]: {\n paddingRight: '0 !important',\n },\n [`& .${mcpClasses.table}`]: {\n width: '100%',\n backgroundColor: 'transparent',\n '--pf-v6-c-table--BackgroundColor': 'transparent',\n '--pf-v5-c-table--BackgroundColor': 'transparent',\n '& table, & thead, & tbody, & tr, & th, & td': {\n backgroundColor: 'transparent !important',\n },\n '& th': {\n borderBottom: 0,\n fontSize: '0.75rem',\n fontWeight: 600,\n color: theme.palette.text.primary,\n whiteSpace: 'nowrap',\n textAlign: 'left',\n },\n '& td': {\n borderBottom: 0,\n paddingTop: theme.spacing(1.5),\n paddingBottom: theme.spacing(1.5),\n verticalAlign: 'middle',\n },\n },\n [`& .${mcpClasses.alert}`]: {\n marginLeft: theme.spacing(3),\n marginRight: theme.spacing(3),\n marginBottom: theme.spacing(2),\n },\n}));\n\ntype McpServerResponse = {\n name: string;\n url?: string;\n enabled: boolean;\n status: 'connected' | 'error' | 'unknown';\n toolCount: number;\n hasToken: boolean;\n hasUserToken: boolean;\n hasOrgToken: boolean;\n auth?: string;\n};\n\ntype McpServersListResponse = {\n servers?: McpServerResponse[];\n};\n\ntype McpServersPatchResponse = {\n server?: McpServerResponse;\n validation?: {\n error?: string;\n };\n};\n\ntype McpToolInfo = {\n name: string;\n description?: string;\n};\n\ntype McpServersValidateResponse = {\n name: string;\n status: 'connected' | 'error' | 'unknown';\n toolCount: number;\n validation?: {\n error?: unknown;\n tools?: McpToolInfo[];\n };\n};\n\ntype McpCredentialsValidateResponse = {\n valid: boolean;\n error?: unknown;\n toolCount: number;\n tools?: McpToolInfo[];\n};\n\nconst getStatusIcon = (status: ServerStatus, className: string) => {\n if (status === 'tokenRequired') return <KeyIcon className={className} />;\n if (status === 'disabled') return <InfoCircleIcon className={className} />;\n if (status === 'failed')\n return <ExclamationCircleIcon className={className} />;\n return <CheckCircleIcon className={className} />;\n};\n\nconst toUiServer = (\n server: McpServerResponse,\n validationError?: string,\n): McpServer => ({\n id: server.name,\n name: server.name,\n url: server.url,\n enabled: server.enabled,\n status: server.status,\n toolCount: server.toolCount,\n hasToken: server.hasToken,\n hasUserToken: server.hasUserToken,\n hasOrgToken: server.hasOrgToken,\n validationError: server.status === 'error' ? validationError : undefined,\n auth: server.auth,\n});\nexport const McpServersSettings = ({\n backgroundColor,\n}: McpServersSettingsProps) => {\n const { t } = useTranslation();\n const configApi = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const { allowed: hasMcpToolsAccess, loading: mcpToolsPermissionLoading } =\n useIaMcpToolsPermission();\n\n const [servers, setServers] = useState<McpServer[]>([]);\n const [sortColumn, setSortColumn] = useState<McpServerSortColumn>('name');\n const [sortAsc, setSortAsc] = useState(true);\n const [isLoading, setIsLoading] = useState(true);\n const [isSaving, setIsSaving] = useState<Record<string, boolean>>({});\n const [error, setError] = useState<string | null>(null);\n\n const getBaseUrl = useCallback(() => {\n return `${configApi.getString('backend.baseUrl')}/api/intelligent-assistant`;\n }, [configApi]);\n\n const fetchJson = useCallback(\n async <T,>(url: string, init?: RequestInit): Promise<T> => {\n const response = await fetchApi.fetch(url, {\n headers: {\n 'Content-Type': 'application/json',\n },\n ...init,\n });\n if (!response.ok) {\n let message = `${response.status} ${response.statusText}`;\n try {\n const bodyText = await response.text();\n if (bodyText) {\n const parsed = JSON.parse(bodyText);\n if (parsed?.error) {\n message = parsed.error;\n }\n }\n } catch {\n // Keep default message when parsing fails.\n }\n throw new Error(message);\n }\n\n const text = await response.text();\n return (text ? JSON.parse(text) : {}) as T;\n },\n [fetchApi],\n );\n\n const fetchServerValidation = useCallback(\n async (serverName: string) => {\n const baseUrl = getBaseUrl();\n return fetchJson<McpServersValidateResponse>(\n `${baseUrl}/mcp-servers/${encodeURIComponent(serverName)}/validate`,\n {\n method: 'POST',\n },\n );\n },\n [fetchJson, getBaseUrl],\n );\n\n const validateServer = useCallback(\n async (serverName: string) => {\n const data = await fetchServerValidation(serverName);\n\n setServers(prev =>\n prev.map(server =>\n server.name === serverName\n ? {\n ...server,\n status: data.status,\n toolCount: data.toolCount,\n validationError:\n data.status === 'error'\n ? formatApiError(data.validation?.error) ||\n 'Validation failed'\n : undefined,\n }\n : server,\n ),\n );\n return data;\n },\n [fetchServerValidation],\n );\n\n const validateCredentials = useCallback(\n async (url: string, token: string) => {\n const baseUrl = getBaseUrl();\n return await fetchJson<McpCredentialsValidateResponse>(\n `${baseUrl}/mcp-servers/validate`,\n {\n method: 'POST',\n body: JSON.stringify({ url, token }),\n },\n );\n },\n [fetchJson, getBaseUrl],\n );\n const loadServers = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n try {\n const baseUrl = getBaseUrl();\n const data = await fetchJson<McpServersListResponse>(\n `${baseUrl}/mcp-servers`,\n );\n const uiServers = (data.servers ?? []).map(server => toUiServer(server));\n setServers(uiServers);\n\n const serversToValidate = uiServers.filter(server => server.hasToken);\n void Promise.allSettled(\n serversToValidate.map(async server => {\n try {\n await validateServer(server.name);\n } catch (validationError) {\n setError(\n prev =>\n prev ??\n (validationError instanceof Error\n ? validationError.message\n : `Failed to validate ${server.name}`),\n );\n }\n }),\n );\n } catch (e) {\n setError(\n e instanceof Error ? e.message : 'Failed to load MCP server settings',\n );\n } finally {\n setIsLoading(false);\n }\n }, [fetchJson, getBaseUrl, validateServer]);\n\n useEffect(() => {\n if (mcpToolsPermissionLoading || !hasMcpToolsAccess) {\n return;\n }\n loadServers();\n }, [loadServers, mcpToolsPermissionLoading, hasMcpToolsAccess]);\n\n const patchServer = useCallback(\n async (\n serverName: string,\n body: { enabled?: boolean; token?: string | null },\n ) => {\n setError(null);\n setIsSaving(prev => ({ ...prev, [serverName]: true }));\n try {\n const baseUrl = getBaseUrl();\n const data = await fetchJson<McpServersPatchResponse>(\n `${baseUrl}/mcp-servers/${encodeURIComponent(serverName)}`,\n {\n method: 'PATCH',\n body: JSON.stringify(body),\n },\n );\n\n if (data.server) {\n setServers(prev =>\n prev.map(server =>\n server.name === serverName\n ? toUiServer(data.server!, data.validation?.error)\n : server,\n ),\n );\n } else {\n await loadServers();\n }\n } catch (e) {\n setError(\n e instanceof Error\n ? e.message\n : `Failed to update ${serverName} settings`,\n );\n throw e;\n } finally {\n setIsSaving(prev => ({ ...prev, [serverName]: false }));\n }\n },\n [fetchJson, getBaseUrl, loadServers],\n );\n\n const configureModal = useMcpConfigureModal({\n servers,\n isSaving,\n patchServer,\n validateServer,\n validateCredentials,\n fetchServerValidation,\n });\n\n const selectedCount = servers.filter(server => {\n const displayStatus = getDisplayStatus(server);\n const isUnavailable =\n displayStatus === 'failed' || displayStatus === 'tokenRequired';\n return server.enabled && !isUnavailable;\n }).length;\n\n const sortedServers = [...servers].sort((a, b) =>\n compareMcpServers(a, b, sortColumn, sortAsc),\n );\n\n const onSortColumnClick = (column: McpServerSortColumn) => {\n if (sortColumn === column) {\n setSortAsc(prev => !prev);\n return;\n }\n setSortColumn(column);\n setSortAsc(true);\n };\n\n const renderSortIcon = (column: McpServerSortColumn) => {\n const isActive = sortColumn === column;\n let Icon = SortAmountDownIcon;\n if (isActive && !sortAsc) {\n Icon = SortAmountUpIcon;\n }\n\n return (\n <Icon\n className={\n isActive\n ? mcpClasses.sortHeaderIconActive\n : mcpClasses.sortHeaderIconInactive\n }\n />\n );\n };\n\n if (mcpToolsPermissionLoading || !hasMcpToolsAccess) {\n return null;\n }\n\n return (\n <StyledMcpRoot style={backgroundColor ? { backgroundColor } : undefined}>\n <GlobalStyles\n styles={{\n '.pf-v6-c-backdrop': {\n zIndex: '1400 !important',\n },\n '.pf-v5-c-backdrop': {\n zIndex: '1400 !important',\n },\n }}\n />\n <div className={mcpClasses.headerRow}>\n <div>\n <Title headingLevel=\"h2\" size=\"xl\" className={mcpClasses.title}>\n {t('mcp.settings.title')}\n </Title>\n <div className={mcpClasses.selectedCount}>\n {t('mcp.settings.selectedCount' as any, {\n selectedCount: String(selectedCount),\n totalCount: String(servers.length),\n })}\n </div>\n </div>\n </div>\n {error && (\n <Alert\n variant=\"danger\"\n isInline\n title={error}\n className={mcpClasses.alert}\n />\n )}\n <Table\n variant=\"compact\"\n aria-label={t('mcp.settings.tableAriaLabel')}\n className={mcpClasses.table}\n >\n <Thead>\n <Tr>\n <Th width={10} screenReaderText={t('mcp.settings.enabled')} />\n <Th>\n <Button\n variant=\"link\"\n className={mcpClasses.nameHeaderButton}\n icon={renderSortIcon('name')}\n iconPosition=\"right\"\n onClick={() => onSortColumnClick('name')}\n >\n <Typography\n component=\"span\"\n className={mcpClasses.nameHeaderText}\n >\n {t('mcp.settings.name')}\n </Typography>\n </Button>\n </Th>\n <Th className={mcpClasses.statusHeader}>\n <Button\n variant=\"link\"\n className={mcpClasses.statusHeaderButton}\n icon={renderSortIcon('status')}\n iconPosition=\"right\"\n onClick={() => onSortColumnClick('status')}\n >\n <Typography\n component=\"span\"\n className={mcpClasses.nameHeaderText}\n >\n {t('mcp.settings.status')}\n </Typography>\n </Button>\n </Th>\n <Th screenReaderText={t('mcp.settings.edit')} />\n </Tr>\n </Thead>\n <Tbody>\n {isLoading && (\n <Tr>\n <Td colSpan={4}>{t('mcp.settings.loading')}</Td>\n </Tr>\n )}\n {!isLoading && sortedServers.length === 0 && (\n <Tr>\n <Td colSpan={4}>{t('mcp.settings.noneAvailable')}</Td>\n </Tr>\n )}\n {sortedServers.map(server => {\n const displayStatus = getDisplayStatus(server);\n const displayDetail = getDisplayDetail(server, displayStatus, t);\n let statusClass:\n | typeof mcpClasses.statusOk\n | typeof mcpClasses.statusWarn\n | typeof mcpClasses.statusDisabled = mcpClasses.statusWarn;\n if (displayStatus === 'ok') {\n statusClass = mcpClasses.statusOk;\n } else if (displayStatus === 'disabled') {\n statusClass = mcpClasses.statusDisabled;\n }\n\n return (\n <Tr key={server.id} className={mcpClasses.tableRow}>\n <Td width={10} className={mcpClasses.toggleCell}>\n {(() => {\n const isUnavailable =\n isEnabledToggleUnavailable(displayStatus);\n const isChecked = getEnabledToggleChecked(\n server,\n displayStatus,\n );\n const isRowSaving = Boolean(isSaving[server.name]);\n const isToggleDisabled = isUnavailable || isRowSaving;\n const switchControl = (\n <Switch\n id={`mcp-switch-${server.id}`}\n aria-label={t(\n 'mcp.settings.toggleServerAriaLabel' as any,\n {\n serverName: server.name,\n },\n )}\n isChecked={isChecked}\n isDisabled={isToggleDisabled}\n onChange={(_event, checked) => {\n void patchServer(server.name, {\n enabled: checked,\n }).catch(() => {\n // patchServer already updates component error state.\n // Swallow here to avoid unhandled promise rejections\n // from event-handler fire-and-forget usage.\n });\n }}\n />\n );\n\n if (!isToggleDisabled) {\n return switchControl;\n }\n\n return (\n <Tooltip content={displayDetail}>\n <Typography component=\"span\">\n {switchControl}\n </Typography>\n </Tooltip>\n );\n })()}\n </Td>\n <Td\n width={35}\n className={`${mcpClasses.rowName} ${mcpClasses.nameCell}`}\n >\n <Typography component=\"span\" className={mcpClasses.nameValue}>\n {server.name}\n </Typography>\n </Td>\n <Td width={40} className={mcpClasses.statusColumnCell}>\n <div className={mcpClasses.statusCell}>\n {getStatusIcon(displayStatus, statusClass)}\n {displayStatus === 'failed' ? (\n <Tooltip\n content={\n server.validationError ??\n t('mcp.settings.token.validationFailed')\n }\n >\n <Typography\n component=\"span\"\n className={mcpClasses.statusValue}\n >\n {displayDetail}\n </Typography>\n </Tooltip>\n ) : (\n <Typography\n component=\"span\"\n className={mcpClasses.statusValue}\n >\n {displayDetail}\n </Typography>\n )}\n </div>\n </Td>\n <Td width={15} isActionCell style={{ textAlign: 'right' }}>\n <Button\n aria-label={t('mcp.settings.editServerAriaLabel' as any, {\n serverName: server.name,\n })}\n icon={<PencilAltIcon />}\n variant=\"plain\"\n className={mcpClasses.actionButton}\n onClick={() => configureModal.open(server)}\n />\n </Td>\n </Tr>\n );\n })}\n </Tbody>\n </Table>\n <McpConfigureServerModal {...configureModal} />\n </StyledMcpRoot>\n );\n};\n"],"names":[],"mappings":"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"}