@red-hat-developer-hub/backstage-plugin-lightspeed 1.2.2 → 1.2.3
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.
- package/CHANGELOG.md +7 -0
- package/dist/alpha.d.ts +0 -6
- package/dist/api/LightspeedApiClient.esm.js +20 -6
- package/dist/api/LightspeedApiClient.esm.js.map +1 -1
- package/dist/components/DeleteModal.esm.js +2 -3
- package/dist/components/DeleteModal.esm.js.map +1 -1
- package/dist/components/LightSpeedChat.esm.js +1 -11
- package/dist/components/LightSpeedChat.esm.js.map +1 -1
- package/dist/components/LightspeedChatBox.esm.js +48 -17
- package/dist/components/LightspeedChatBox.esm.js.map +1 -1
- package/dist/components/LightspeedDrawerProvider.esm.js +39 -26
- package/dist/components/LightspeedDrawerProvider.esm.js.map +1 -1
- package/dist/components/LightspeedDrawerStateExposer.esm.js +8 -2
- package/dist/components/LightspeedDrawerStateExposer.esm.js.map +1 -1
- package/dist/components/RenameConversationModal.esm.js +26 -8
- package/dist/components/RenameConversationModal.esm.js.map +1 -1
- package/dist/components/ToolCallContent.esm.js +25 -54
- package/dist/components/ToolCallContent.esm.js.map +1 -1
- package/dist/hooks/useDisplayModeSettings.esm.js +57 -0
- package/dist/hooks/useDisplayModeSettings.esm.js.map +1 -0
- package/dist/translations/de.esm.js +1 -7
- package/dist/translations/de.esm.js.map +1 -1
- package/dist/translations/es.esm.js +1 -7
- package/dist/translations/es.esm.js.map +1 -1
- package/dist/translations/fr.esm.js +1 -7
- package/dist/translations/fr.esm.js.map +1 -1
- package/dist/translations/it.esm.js +1 -7
- package/dist/translations/it.esm.js.map +1 -1
- package/dist/translations/ja.esm.js +1 -7
- package/dist/translations/ja.esm.js.map +1 -1
- package/dist/translations/ref.esm.js +1 -7
- package/dist/translations/ref.esm.js.map +1 -1
- package/dist/utils/lightspeed-chatbox-utils.esm.js +13 -23
- package/dist/utils/lightspeed-chatbox-utils.esm.js.map +1 -1
- package/dist/utils/reasoningParser.esm.js +18 -31
- package/dist/utils/reasoningParser.esm.js.map +1 -1
- package/dist/utils/toolCallMapper.esm.js +2 -2
- package/dist/utils/toolCallMapper.esm.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LightspeedChatBox.esm.js","sources":["../../src/components/LightspeedChatBox.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 {\n ForwardedRef,\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n} from 'react';\n\nimport { makeStyles } from '@material-ui/core';\nimport {\n ChatbotDisplayMode,\n ChatbotWelcomePrompt,\n DeepThinking,\n DeepThinkingProps,\n Message,\n MessageBox,\n MessageBoxHandle,\n MessageProps,\n ToolCall as PatternFlyToolCall,\n WelcomePrompt,\n} from '@patternfly/chatbot';\nimport { Alert } from '@patternfly/react-core';\n\nimport { useAutoScroll } from '../hooks/useAutoScroll';\nimport { useBufferedMessages } from '../hooks/useBufferedMessages';\nimport { useFeedbackActions } from '../hooks/useFeedbackActions';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { ToolCall } from '../types';\nimport { parseReasoning } from '../utils/reasoningParser';\nimport { mapToPatternFlyToolCall } from '../utils/toolCallMapper';\n\nconst useStyles = makeStyles(theme => ({\n prompt: {\n 'justify-content': 'flex-end',\n },\n container: {\n maxWidth: 'unset !important',\n },\n alert: {\n background: 'unset !important',\n },\n promptSuggestions: {\n '& div.pf-chatbot__prompt-suggestions': {\n 'flex-direction': 'column !important',\n },\n },\n\n userMessageText: {\n '& div.pf-chatbot__message--user': {\n '& div.pf-chatbot__message-text': {\n '& p': {\n color: theme.palette.common.white,\n },\n },\n },\n },\n}));\n\n// Extended message type that includes tool calls\ninterface ExtendedMessageProps extends MessageProps {\n toolCalls?: ToolCall[];\n}\n\ntype LightspeedChatBoxProps = {\n userName?: string;\n messages: ExtendedMessageProps[];\n profileLoading: boolean;\n announcement: string | undefined;\n topicRestrictionEnabled: boolean;\n welcomePrompts: WelcomePrompt[];\n conversationId: string;\n isStreaming: boolean;\n displayMode?: ChatbotDisplayMode;\n};\n\nexport interface ScrollContainerHandle {\n scrollToBottom: () => void;\n}\n\nexport const LightspeedChatBox = forwardRef(\n (\n {\n userName,\n messages,\n announcement,\n conversationId,\n profileLoading,\n welcomePrompts,\n isStreaming,\n topicRestrictionEnabled,\n displayMode,\n }: LightspeedChatBoxProps,\n ref: ForwardedRef<ScrollContainerHandle>,\n ) => {\n const classes = useStyles();\n const scrollQueued = useRef(false);\n const containerRef = useRef<MessageBoxHandle>(null);\n const { t } = useTranslation();\n\n const cmessages = useBufferedMessages(messages, 30);\n const { autoScroll, scrollToBottom, scrollToTop } =\n useAutoScroll(containerRef);\n const conversationMessages = useFeedbackActions(\n cmessages,\n conversationId,\n isStreaming,\n );\n\n useImperativeHandle(ref, () => ({\n scrollToBottom: () => {\n if (scrollQueued.current) return;\n scrollQueued.current = true;\n\n requestAnimationFrame(() => {\n scrollToBottom();\n scrollQueued.current = false;\n });\n },\n }));\n\n // Auto-scrolls to the latest message\n useEffect(() => {\n if (!autoScroll || scrollQueued.current) return undefined;\n\n scrollQueued.current = true;\n\n const rafId = requestAnimationFrame(() => {\n const container = containerRef.current;\n if (!container) return;\n\n setTimeout(() => {\n container.scrollTo({\n top: container.scrollHeight,\n behavior: 'auto',\n });\n }, 0);\n\n scrollQueued.current = false;\n });\n\n return () => {\n cancelAnimationFrame(rafId);\n scrollQueued.current = false;\n };\n\n // eslint-disable-next-line\n }, [autoScroll, cmessages, containerRef]);\n\n const messageBoxClasses = `${classes.container} ${classes.userMessageText}`;\n const isEmbeddedMode = displayMode === ChatbotDisplayMode.embedded;\n\n const getMessageBoxClassName = () => {\n if (!welcomePrompts.length) {\n return messageBoxClasses;\n }\n const baseClasses = `${messageBoxClasses} ${classes.prompt}`;\n if (isEmbeddedMode) {\n return baseClasses;\n }\n return `${baseClasses} ${classes.promptSuggestions}`;\n };\n\n return (\n <MessageBox\n className={getMessageBoxClassName()}\n announcement={announcement}\n ref={containerRef}\n onScrollToTopClick={scrollToTop}\n onScrollToBottomClick={scrollToBottom}\n jumpButtonBottomProps={{ 'aria-label': t('aria.scroll.down') }}\n jumpButtonTopProps={{ 'aria-label': t('aria.scroll.up') }}\n jumpButtonBottomTooltipProps={{ content: t('tooltip.backToBottom') }}\n jumpButtonTopTooltipProps={{ content: t('tooltip.backToTop') }}\n >\n <div>\n <Alert\n title={t('aria.important')}\n variant=\"info\"\n isInline\n className={classes.alert}\n >\n {topicRestrictionEnabled\n ? t('disclaimer.withValidation')\n : t('disclaimer.withoutValidation')}\n </Alert>\n <br />\n </div>\n {welcomePrompts.length ? (\n <ChatbotWelcomePrompt\n title={t('chatbox.welcome.greeting' as any, {\n userName: profileLoading\n ? t('user.loading')\n : (userName ?? t('user.guest')),\n })}\n description={t('chatbox.welcome.description')}\n prompts={welcomePrompts}\n style={{ paddingBottom: '0' }}\n />\n ) : (\n <br />\n )}\n {conversationMessages.map((message, index) => {\n const messageContent = message.content as string;\n const parsedReasoning = parseReasoning(messageContent || '');\n\n // Map first tool call to PatternFly's toolCall prop\n const firstToolCall = message.toolCalls?.[0];\n const toolCallProp = firstToolCall\n ? mapToPatternFlyToolCall(firstToolCall, t)\n : undefined;\n\n // Handle additional tool calls (if any) via extraContent\n const additionalToolCalls = message.toolCalls?.slice(1);\n\n const extraContentParts: {\n beforeMainContent?: React.ReactNode;\n afterMainContent?: React.ReactNode;\n } = {};\n\n let deepThinking: DeepThinkingProps | undefined = undefined;\n\n if (\n parsedReasoning.isReasoningInProgress ||\n parsedReasoning.hasReasoning\n ) {\n const reasoningContent =\n parsedReasoning.reasoning ||\n (() => {\n const reasoningMatch = messageContent.match(/<think>(.*?)$/s);\n return reasoningMatch ? reasoningMatch[1].trim() : '';\n })();\n\n if (reasoningContent) {\n deepThinking = {\n cardBodyProps: {\n id: `deep-thinking-${index}`,\n style: { whiteSpace: 'pre-line' },\n },\n toggleContent: t('reasoning.thinking'),\n body: reasoningContent,\n expandableSectionProps: {},\n };\n extraContentParts.beforeMainContent = (\n <DeepThinking {...deepThinking} />\n );\n }\n }\n\n if (additionalToolCalls && additionalToolCalls.length > 0) {\n extraContentParts.afterMainContent = (\n <>\n {additionalToolCalls.map(tc => {\n const tcProps = mapToPatternFlyToolCall(tc, t);\n return (\n <div\n key={`tool-${tc.id}-${tc.toolName}`}\n style={{ marginTop: '8px' }}\n >\n <PatternFlyToolCall {...tcProps} />\n </div>\n );\n })}\n </>\n );\n }\n\n const extraContent =\n extraContentParts.beforeMainContent ||\n extraContentParts.afterMainContent\n ? extraContentParts\n : undefined;\n\n const finalMessage =\n parsedReasoning.hasReasoning ||\n parsedReasoning.isReasoningInProgress\n ? { ...message, content: parsedReasoning.mainContent }\n : message;\n\n return (\n <Message\n key={`${message.role}-${index}`}\n toolCall={toolCallProp}\n extraContent={extraContent}\n {...finalMessage}\n />\n );\n })}\n </MessageBox>\n );\n },\n);\n"],"names":["PatternFlyToolCall"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"LightspeedChatBox.esm.js","sources":["../../src/components/LightspeedChatBox.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 {\n ForwardedRef,\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n} from 'react';\n\nimport { makeStyles } from '@material-ui/core';\nimport {\n ChatbotDisplayMode,\n ChatbotWelcomePrompt,\n DeepThinking,\n DeepThinkingProps,\n Message,\n MessageBox,\n MessageBoxHandle,\n MessageProps,\n ToolCall as PatternFlyToolCall,\n WelcomePrompt,\n} from '@patternfly/chatbot';\nimport { Alert } from '@patternfly/react-core';\n\nimport { useAutoScroll } from '../hooks/useAutoScroll';\nimport { useBufferedMessages } from '../hooks/useBufferedMessages';\nimport { useFeedbackActions } from '../hooks/useFeedbackActions';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { ToolCall } from '../types';\nimport { parseReasoning } from '../utils/reasoningParser';\nimport { mapToPatternFlyToolCall } from '../utils/toolCallMapper';\n\nconst useStyles = makeStyles(theme => ({\n prompt: {\n 'justify-content': 'flex-end',\n },\n container: {\n maxWidth: 'unset !important',\n },\n alert: {\n background: 'unset !important',\n },\n promptSuggestions: {\n '& div.pf-chatbot__prompt-suggestions': {\n 'flex-direction': 'column !important',\n },\n },\n\n userMessageText: {\n '& div.pf-chatbot__message--user': {\n '& div.pf-chatbot__message-text': {\n '& p': {\n color: theme.palette.common.white,\n },\n },\n },\n },\n deepThinking: {\n animation: '$deepThinking 1.6s ease-in-out infinite',\n },\n\n '@keyframes deepThinking': {\n '0%': {\n opacity: 0.65,\n },\n '50%': {\n opacity: 1,\n },\n '100%': {\n opacity: 0.65,\n },\n },\n}));\n\n// Extended message type that includes tool calls\ninterface ExtendedMessageProps extends MessageProps {\n toolCalls?: ToolCall[];\n}\n\ntype LightspeedChatBoxProps = {\n userName?: string;\n messages: ExtendedMessageProps[];\n profileLoading: boolean;\n announcement: string | undefined;\n topicRestrictionEnabled: boolean;\n welcomePrompts: WelcomePrompt[];\n conversationId: string;\n isStreaming: boolean;\n displayMode?: ChatbotDisplayMode;\n};\n\nexport interface ScrollContainerHandle {\n scrollToBottom: () => void;\n}\n\nexport const LightspeedChatBox = forwardRef(\n (\n {\n userName,\n messages,\n announcement,\n conversationId,\n profileLoading,\n welcomePrompts,\n isStreaming,\n topicRestrictionEnabled,\n displayMode,\n }: LightspeedChatBoxProps,\n ref: ForwardedRef<ScrollContainerHandle>,\n ) => {\n const classes = useStyles();\n const scrollQueued = useRef(false);\n const containerRef = useRef<MessageBoxHandle>(null);\n const { t } = useTranslation();\n\n const cmessages = useBufferedMessages(messages, 30);\n const { autoScroll, scrollToBottom, scrollToTop } =\n useAutoScroll(containerRef);\n const conversationMessages = useFeedbackActions(\n cmessages,\n conversationId,\n isStreaming,\n );\n\n useImperativeHandle(ref, () => ({\n scrollToBottom: () => {\n if (scrollQueued.current) return;\n scrollQueued.current = true;\n\n requestAnimationFrame(() => {\n scrollToBottom();\n scrollQueued.current = false;\n });\n },\n }));\n\n // Auto-scrolls to the latest message\n useEffect(() => {\n if (!autoScroll || scrollQueued.current) return undefined;\n\n scrollQueued.current = true;\n\n const rafId = requestAnimationFrame(() => {\n const container = containerRef.current;\n if (!container) return;\n\n setTimeout(() => {\n container.scrollTo({\n top: container.scrollHeight,\n behavior: 'auto',\n });\n }, 0);\n\n scrollQueued.current = false;\n });\n\n return () => {\n cancelAnimationFrame(rafId);\n scrollQueued.current = false;\n };\n\n // eslint-disable-next-line\n }, [autoScroll, cmessages, containerRef]);\n\n const messageBoxClasses = `${classes.container} ${classes.userMessageText}`;\n const isEmbeddedMode = displayMode === ChatbotDisplayMode.embedded;\n\n const getMessageBoxClassName = () => {\n if (!welcomePrompts.length) {\n return messageBoxClasses;\n }\n const baseClasses = `${messageBoxClasses} ${classes.prompt}`;\n if (isEmbeddedMode) {\n return baseClasses;\n }\n return `${baseClasses} ${classes.promptSuggestions}`;\n };\n\n return (\n <MessageBox\n className={getMessageBoxClassName()}\n announcement={announcement}\n ref={containerRef}\n onScrollToTopClick={scrollToTop}\n onScrollToBottomClick={scrollToBottom}\n jumpButtonBottomProps={{ 'aria-label': t('aria.scroll.down') }}\n jumpButtonTopProps={{ 'aria-label': t('aria.scroll.up') }}\n jumpButtonBottomTooltipProps={{ content: t('tooltip.backToBottom') }}\n jumpButtonTopTooltipProps={{ content: t('tooltip.backToTop') }}\n >\n <div>\n <Alert\n title={t('aria.important')}\n variant=\"info\"\n isInline\n className={classes.alert}\n >\n {topicRestrictionEnabled\n ? t('disclaimer.withValidation')\n : t('disclaimer.withoutValidation')}\n </Alert>\n <br />\n </div>\n {welcomePrompts.length ? (\n <ChatbotWelcomePrompt\n title={t('chatbox.welcome.greeting' as any, {\n userName: profileLoading\n ? t('user.loading')\n : (userName ?? t('user.guest')),\n })}\n description={t('chatbox.welcome.description')}\n prompts={welcomePrompts}\n style={{ paddingBottom: '0' }}\n />\n ) : (\n <br />\n )}\n {conversationMessages.map((message, index) => {\n const messageContent = message.content as string;\n const parsedReasoning = parseReasoning(messageContent || '');\n\n // Map first tool call to PatternFly's toolCall prop\n const firstToolCall = message.toolCalls?.[0];\n const toolCallProp = firstToolCall\n ? mapToPatternFlyToolCall(firstToolCall, t, message.role)\n : undefined;\n\n // Handle additional tool calls (if any) via extraContent\n const additionalToolCalls = message.toolCalls?.slice(1);\n\n const extraContentParts: {\n beforeMainContent?: React.ReactNode;\n afterMainContent?: React.ReactNode;\n } = {};\n\n let deepThinking: DeepThinkingProps | undefined = undefined;\n\n if (\n parsedReasoning.isReasoningInProgress ||\n parsedReasoning.hasReasoning\n ) {\n const reasoningContent = parsedReasoning.reasoning;\n\n if (reasoningContent) {\n deepThinking = {\n cardBodyProps: {\n id: `deep-thinking-${index}`,\n style: { whiteSpace: 'pre-line' },\n className: parsedReasoning.isReasoningInProgress\n ? classes.deepThinking\n : undefined,\n },\n toggleContent: t('reasoning.thinking'),\n body: reasoningContent,\n isDefaultExpanded: false,\n };\n }\n }\n\n const allToolCalls: React.ReactNode[] = [];\n\n // Add first tool call if it exists\n if (toolCallProp && firstToolCall) {\n allToolCalls.push(\n <div\n key={`tool-${firstToolCall.id}-${firstToolCall.toolName}`}\n style={{ marginTop: '8px' }}\n >\n <PatternFlyToolCall {...toolCallProp} />\n </div>,\n );\n }\n\n // Add additional tool calls\n if (additionalToolCalls && additionalToolCalls.length > 0) {\n additionalToolCalls.forEach(tc => {\n const tcProps = mapToPatternFlyToolCall(tc, t, message.role);\n allToolCalls.push(\n <div\n key={`tool-${tc.id}-${tc.toolName}`}\n style={{ marginTop: '8px' }}\n >\n <PatternFlyToolCall {...tcProps} />\n </div>,\n );\n });\n }\n\n // Show Thinking first, then tool calls\n if (deepThinking || allToolCalls.length > 0) {\n extraContentParts.beforeMainContent = (\n <>\n {deepThinking && <DeepThinking {...deepThinking} />}\n {allToolCalls.length > 0 && (\n <div style={{ marginTop: deepThinking ? '8px' : '0' }}>\n {allToolCalls}\n </div>\n )}\n </>\n );\n }\n\n const extraContent =\n extraContentParts.beforeMainContent ||\n extraContentParts.afterMainContent\n ? extraContentParts\n : undefined;\n\n const finalMessage =\n parsedReasoning.hasReasoning ||\n parsedReasoning.isReasoningInProgress\n ? { ...message, content: parsedReasoning.mainContent }\n : message;\n\n return (\n <Message\n key={`${message.role}-${index}`}\n extraContent={extraContent}\n {...finalMessage}\n />\n );\n })}\n </MessageBox>\n );\n },\n);\n"],"names":["PatternFlyToolCall"],"mappings":"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"}
|
|
@@ -3,6 +3,16 @@ import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
|
|
|
3
3
|
import { useNavigate, useLocation, useMatch } from 'react-router-dom';
|
|
4
4
|
import { makeStyles } from '@mui/styles';
|
|
5
5
|
import { ChatbotDisplayMode, ChatbotModal } from '@patternfly/chatbot';
|
|
6
|
+
import '@backstage/core-plugin-api';
|
|
7
|
+
import '@tanstack/react-query';
|
|
8
|
+
import '../api/api.esm.js';
|
|
9
|
+
import { useBackstageUserIdentity } from '../hooks/useBackstageUserIdentity.esm.js';
|
|
10
|
+
import '@mui/icons-material/PushPin';
|
|
11
|
+
import '@backstage/plugin-permission-react';
|
|
12
|
+
import '@red-hat-developer-hub/backstage-plugin-lightspeed-common';
|
|
13
|
+
import { useDisplayModeSettings } from '../hooks/useDisplayModeSettings.esm.js';
|
|
14
|
+
import '@backstage/core-plugin-api/alpha';
|
|
15
|
+
import '../translations/ref.esm.js';
|
|
6
16
|
import { LightspeedChatContainer } from './LightspeedChatContainer.esm.js';
|
|
7
17
|
import { LightspeedDrawerContext } from './LightspeedDrawerContext.esm.js';
|
|
8
18
|
|
|
@@ -17,9 +27,12 @@ const LightspeedDrawerProvider = ({ children }) => {
|
|
|
17
27
|
const classes = useStyles();
|
|
18
28
|
const navigate = useNavigate();
|
|
19
29
|
const location = useLocation();
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
30
|
+
const user = useBackstageUserIdentity();
|
|
31
|
+
const {
|
|
32
|
+
displayMode: persistedDisplayMode,
|
|
33
|
+
setDisplayMode: setPersistedDisplayMode
|
|
34
|
+
} = useDisplayModeSettings(user, ChatbotDisplayMode.default);
|
|
35
|
+
const [displayModeState, setDisplayModeState] = useState(persistedDisplayMode);
|
|
23
36
|
const [isOpen, setIsOpen] = useState(false);
|
|
24
37
|
const [drawerWidth, setDrawerWidth] = useState(400);
|
|
25
38
|
const [currentConversationIdState, setCurrentConversationIdState] = useState(undefined);
|
|
@@ -40,39 +53,38 @@ const LightspeedDrawerProvider = ({ children }) => {
|
|
|
40
53
|
navigate(-1);
|
|
41
54
|
}, [navigate]);
|
|
42
55
|
useEffect(() => {
|
|
56
|
+
if (conversationId) {
|
|
57
|
+
setCurrentConversationIdState(conversationId);
|
|
58
|
+
} else {
|
|
59
|
+
setCurrentConversationIdState(undefined);
|
|
60
|
+
}
|
|
43
61
|
if (isLightspeedRoute) {
|
|
44
|
-
|
|
45
|
-
setCurrentConversationIdState(conversationId);
|
|
46
|
-
} else {
|
|
47
|
-
setCurrentConversationIdState(undefined);
|
|
48
|
-
}
|
|
49
|
-
setDisplayModeState((prev) => {
|
|
50
|
-
if (prev === ChatbotDisplayMode.docked) {
|
|
51
|
-
return prev;
|
|
52
|
-
}
|
|
53
|
-
return ChatbotDisplayMode.embedded;
|
|
54
|
-
});
|
|
62
|
+
setDisplayModeState(ChatbotDisplayMode.embedded);
|
|
55
63
|
setIsOpen(true);
|
|
56
64
|
} else {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
});
|
|
65
|
+
if (persistedDisplayMode === ChatbotDisplayMode.embedded) {
|
|
66
|
+
setDisplayModeState(ChatbotDisplayMode.default);
|
|
67
|
+
} else {
|
|
68
|
+
setDisplayModeState(persistedDisplayMode);
|
|
69
|
+
}
|
|
63
70
|
}
|
|
64
|
-
}, [conversationId, isLightspeedRoute]);
|
|
71
|
+
}, [conversationId, isLightspeedRoute, persistedDisplayMode]);
|
|
65
72
|
const openChatbot = useCallback(() => {
|
|
66
73
|
openedViaFABRef.current = true;
|
|
67
|
-
|
|
74
|
+
const modeToUse = persistedDisplayMode || ChatbotDisplayMode.default;
|
|
75
|
+
setDisplayModeState(modeToUse);
|
|
76
|
+
if (modeToUse === ChatbotDisplayMode.embedded) {
|
|
77
|
+
const convId = currentConversationIdState;
|
|
78
|
+
const path = convId ? `/lightspeed/conversation/${convId}` : "/lightspeed";
|
|
79
|
+
navigate(path);
|
|
80
|
+
}
|
|
68
81
|
setIsOpen(true);
|
|
69
|
-
}, []);
|
|
82
|
+
}, [persistedDisplayMode, currentConversationIdState, navigate]);
|
|
70
83
|
const closeChatbot = useCallback(() => {
|
|
71
84
|
if (displayModeState === ChatbotDisplayMode.embedded && isLightspeedRoute) {
|
|
72
85
|
navigateBackOrGoToCatalog();
|
|
73
86
|
}
|
|
74
87
|
setIsOpen(false);
|
|
75
|
-
setDisplayModeState(ChatbotDisplayMode.default);
|
|
76
88
|
}, [displayModeState, isLightspeedRoute, navigateBackOrGoToCatalog]);
|
|
77
89
|
const toggleChatbot = useCallback(() => {
|
|
78
90
|
if (isOpen) {
|
|
@@ -102,7 +114,7 @@ const LightspeedDrawerProvider = ({ children }) => {
|
|
|
102
114
|
if (mode === displayModeState) {
|
|
103
115
|
return;
|
|
104
116
|
}
|
|
105
|
-
|
|
117
|
+
setPersistedDisplayMode(mode);
|
|
106
118
|
if (mode === ChatbotDisplayMode.embedded) {
|
|
107
119
|
const convId = conversationIdParam ?? currentConversationIdState;
|
|
108
120
|
const path = convId ? `/lightspeed/conversation/${convId}` : "/lightspeed";
|
|
@@ -120,7 +132,8 @@ const LightspeedDrawerProvider = ({ children }) => {
|
|
|
120
132
|
isLightspeedRoute,
|
|
121
133
|
currentConversationIdState,
|
|
122
134
|
displayModeState,
|
|
123
|
-
navigateBackOrGoToCatalog
|
|
135
|
+
navigateBackOrGoToCatalog,
|
|
136
|
+
setPersistedDisplayMode
|
|
124
137
|
]
|
|
125
138
|
);
|
|
126
139
|
const shouldRenderOverlayModal = isOpen && displayModeState === ChatbotDisplayMode.default && !isLightspeedRoute;
|
|
@@ -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 {\n PropsWithChildren,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { useLocation, useMatch, useNavigate } from 'react-router-dom';\n\nimport { makeStyles } from '@mui/styles';\nimport { ChatbotDisplayMode, ChatbotModal } from '@patternfly/chatbot';\n\nimport { FileContent } from '../types';\nimport { LightspeedChatContainer } from './LightspeedChatContainer';\nimport { LightspeedDrawerContext } from './LightspeedDrawerContext';\n\nconst useStyles = makeStyles(theme => ({\n 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: `calc(${theme?.spacing?.(2) ?? '16px'} + 5em)`,\n right: `calc(${theme?.spacing?.(2) ?? '16px'} + 1.5em)`,\n },\n}));\n\n/**\n * @public\n */\nexport const LightspeedDrawerProvider = ({ children }: PropsWithChildren) => {\n const classes = useStyles();\n const navigate = useNavigate();\n const location = useLocation();\n\n const [displayModeState, setDisplayModeState] = useState<ChatbotDisplayMode>(\n ChatbotDisplayMode.default,\n );\n const [isOpen, setIsOpen] = useState<boolean>(false);\n const [drawerWidth, setDrawerWidth] = useState<number>(400);\n const [currentConversationIdState, setCurrentConversationIdState] = useState<\n string | undefined\n >(undefined);\n const [draftMessage, setDraftMessageState] = useState<string>('');\n const [draftFileContents, setDraftFileContentsState] = useState<\n FileContent[]\n >([]);\n const openedViaFABRef = useRef<boolean>(false);\n\n const isLightspeedRoute = location.pathname.startsWith('/lightspeed');\n\n const conversationMatch = useMatch(\n '/lightspeed/conversation/:conversationId',\n );\n\n const conversationId = conversationMatch?.params?.conversationId;\n\n const navigateBackOrGoToCatalog = useCallback(() => {\n // go to catalog page, if the user opens the lightspeed route via a new tab\n if (!openedViaFABRef.current) {\n navigate('/catalog');\n openedViaFABRef.current = true;\n return;\n }\n navigate(-1);\n }, [navigate]);\n\n useEffect(() => {\n if (isLightspeedRoute) {\n if (conversationId) {\n setCurrentConversationIdState(conversationId);\n } else {\n setCurrentConversationIdState(undefined);\n }\n // Update this to fullscreen only when it is not already in the docked mode\n setDisplayModeState(prev => {\n if (prev === ChatbotDisplayMode.docked) {\n return prev; // Don't override docked mode\n }\n return ChatbotDisplayMode.embedded;\n });\n setIsOpen(true);\n } else {\n // When leaving lightspeed route, update this only when the current mode is fullscreen\n setDisplayModeState(prev => {\n if (prev === ChatbotDisplayMode.embedded) {\n return ChatbotDisplayMode.default;\n }\n return prev;\n });\n }\n }, [conversationId, isLightspeedRoute]);\n\n // Open chatbot in overlay mode\n const openChatbot = useCallback(() => {\n openedViaFABRef.current = true;\n setDisplayModeState(ChatbotDisplayMode.default);\n setIsOpen(true);\n }, []);\n\n // Close chatbot\n const closeChatbot = useCallback(() => {\n // If in embedded mode on the lightspeed route, navigate back\n if (displayModeState === ChatbotDisplayMode.embedded && isLightspeedRoute) {\n navigateBackOrGoToCatalog();\n }\n setIsOpen(false);\n setDisplayModeState(ChatbotDisplayMode.default);\n }, [displayModeState, isLightspeedRoute, navigateBackOrGoToCatalog]);\n\n const toggleChatbot = useCallback(() => {\n if (isOpen) {\n closeChatbot();\n } else {\n openChatbot();\n }\n }, [isOpen, openChatbot, closeChatbot]);\n\n const setCurrentConversationId = useCallback(\n (id: string | undefined) => {\n setCurrentConversationIdState(id);\n\n // Update route if in embedded mode\n if (\n displayModeState === ChatbotDisplayMode.embedded &&\n isLightspeedRoute\n ) {\n const path = id ? `/lightspeed/conversation/${id}` : '/lightspeed';\n navigate(path, { replace: true });\n }\n },\n [displayModeState, isLightspeedRoute, navigate],\n );\n\n const setDraftMessage = useCallback((message: string) => {\n setDraftMessageState(message);\n }, []);\n\n const setDraftFileContents = useCallback((files: FileContent[]) => {\n setDraftFileContentsState(files);\n }, []);\n\n // Set display mode with route handling for embedded/fullscreen\n const setDisplayMode = useCallback(\n (mode: ChatbotDisplayMode, conversationIdParam?: string) => {\n if (mode === displayModeState) {\n return;\n }\n\n setDisplayModeState(mode);\n\n // Navigate to fullscreen route with conversation ID if available\n if (mode === ChatbotDisplayMode.embedded) {\n const convId = conversationIdParam ?? currentConversationIdState;\n const path = convId\n ? `/lightspeed/conversation/${convId}`\n : '/lightspeed';\n navigate(path);\n setIsOpen(true);\n } else {\n if (isLightspeedRoute) {\n navigateBackOrGoToCatalog();\n }\n setIsOpen(true);\n }\n },\n [\n navigate,\n isLightspeedRoute,\n currentConversationIdState,\n displayModeState,\n navigateBackOrGoToCatalog,\n ],\n );\n\n // Only render ChatbotModal for overlay mode\n // Docked mode is handled by ApplicationDrawer in Root\n // Embedded mode is handled by LightspeedPage route\n const shouldRenderOverlayModal =\n isOpen &&\n displayModeState === ChatbotDisplayMode.default &&\n !isLightspeedRoute;\n\n const contextValue = useMemo(\n () => ({\n isChatbotActive: isOpen,\n toggleChatbot,\n displayMode: displayModeState,\n setDisplayMode,\n drawerWidth,\n setDrawerWidth,\n currentConversationId: currentConversationIdState,\n setCurrentConversationId,\n draftMessage,\n setDraftMessage,\n draftFileContents,\n setDraftFileContents,\n }),\n [\n isOpen,\n toggleChatbot,\n displayModeState,\n setDisplayMode,\n drawerWidth,\n setDrawerWidth,\n currentConversationIdState,\n setCurrentConversationId,\n draftMessage,\n setDraftMessage,\n draftFileContents,\n setDraftFileContents,\n ],\n );\n\n return (\n <LightspeedDrawerContext.Provider value={contextValue}>\n {children}\n {shouldRenderOverlayModal && (\n <ChatbotModal\n isOpen\n displayMode={displayModeState}\n onClose={closeChatbot}\n ouiaId=\"LightspeedChatbotModal\"\n aria-labelledby=\"lightspeed-chatpopup-modal\"\n className={classes.chatbotModal}\n >\n <LightspeedChatContainer />\n </ChatbotModal>\n )}\n </LightspeedDrawerContext.Provider>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
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 {\n PropsWithChildren,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { useLocation, useMatch, useNavigate } from 'react-router-dom';\n\nimport { makeStyles } from '@mui/styles';\nimport { ChatbotDisplayMode, ChatbotModal } from '@patternfly/chatbot';\n\nimport { useBackstageUserIdentity, useDisplayModeSettings } from '../hooks';\nimport { FileContent } from '../types';\nimport { LightspeedChatContainer } from './LightspeedChatContainer';\nimport { LightspeedDrawerContext } from './LightspeedDrawerContext';\n\nconst useStyles = makeStyles(theme => ({\n 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: `calc(${theme?.spacing?.(2) ?? '16px'} + 5em)`,\n right: `calc(${theme?.spacing?.(2) ?? '16px'} + 1.5em)`,\n },\n}));\n\n/**\n * @public\n */\nexport const LightspeedDrawerProvider = ({ children }: PropsWithChildren) => {\n const classes = useStyles();\n const navigate = useNavigate();\n const location = useLocation();\n const user = useBackstageUserIdentity();\n const {\n displayMode: persistedDisplayMode,\n setDisplayMode: setPersistedDisplayMode,\n } = useDisplayModeSettings(user, ChatbotDisplayMode.default);\n\n const [displayModeState, setDisplayModeState] =\n useState<ChatbotDisplayMode>(persistedDisplayMode);\n const [isOpen, setIsOpen] = useState<boolean>(false);\n const [drawerWidth, setDrawerWidth] = useState<number>(400);\n const [currentConversationIdState, setCurrentConversationIdState] = useState<\n string | undefined\n >(undefined);\n const [draftMessage, setDraftMessageState] = useState<string>('');\n const [draftFileContents, setDraftFileContentsState] = useState<\n FileContent[]\n >([]);\n const openedViaFABRef = useRef<boolean>(false);\n\n const isLightspeedRoute = location.pathname.startsWith('/lightspeed');\n\n const conversationMatch = useMatch(\n '/lightspeed/conversation/:conversationId',\n );\n\n const conversationId = conversationMatch?.params?.conversationId;\n\n const navigateBackOrGoToCatalog = useCallback(() => {\n // go to catalog page, if the user opens the lightspeed route via a new tab\n if (!openedViaFABRef.current) {\n navigate('/catalog');\n openedViaFABRef.current = true;\n return;\n }\n navigate(-1);\n }, [navigate]);\n\n useEffect(() => {\n if (conversationId) {\n setCurrentConversationIdState(conversationId);\n } else {\n setCurrentConversationIdState(undefined);\n }\n\n if (isLightspeedRoute) {\n setDisplayModeState(ChatbotDisplayMode.embedded);\n setIsOpen(true);\n } else {\n // When leaving lightspeed route, restore the persisted display mode\n // If persisted mode is embedded, reset to default\n if (persistedDisplayMode === ChatbotDisplayMode.embedded) {\n setDisplayModeState(ChatbotDisplayMode.default);\n } else {\n setDisplayModeState(persistedDisplayMode);\n }\n }\n }, [conversationId, isLightspeedRoute, persistedDisplayMode]);\n\n // Open chatbot using the persisted display mode preference\n const openChatbot = useCallback(() => {\n openedViaFABRef.current = true;\n\n const modeToUse = persistedDisplayMode || ChatbotDisplayMode.default;\n setDisplayModeState(modeToUse);\n\n if (modeToUse === ChatbotDisplayMode.embedded) {\n const convId = currentConversationIdState;\n const path = convId\n ? `/lightspeed/conversation/${convId}`\n : '/lightspeed';\n navigate(path);\n }\n\n setIsOpen(true);\n }, [persistedDisplayMode, currentConversationIdState, navigate]);\n\n const closeChatbot = useCallback(() => {\n // If in embedded mode on the lightspeed route, navigate back\n if (displayModeState === ChatbotDisplayMode.embedded && isLightspeedRoute) {\n navigateBackOrGoToCatalog();\n }\n setIsOpen(false);\n }, [displayModeState, isLightspeedRoute, navigateBackOrGoToCatalog]);\n\n const toggleChatbot = useCallback(() => {\n if (isOpen) {\n closeChatbot();\n } else {\n openChatbot();\n }\n }, [isOpen, openChatbot, closeChatbot]);\n\n const setCurrentConversationId = useCallback(\n (id: string | undefined) => {\n setCurrentConversationIdState(id);\n\n if (\n displayModeState === ChatbotDisplayMode.embedded &&\n isLightspeedRoute\n ) {\n const path = id ? `/lightspeed/conversation/${id}` : '/lightspeed';\n navigate(path, { replace: true });\n }\n },\n [displayModeState, isLightspeedRoute, navigate],\n );\n\n const setDraftMessage = useCallback((message: string) => {\n setDraftMessageState(message);\n }, []);\n\n const setDraftFileContents = useCallback((files: FileContent[]) => {\n setDraftFileContentsState(files);\n }, []);\n\n // Set display mode with route handling for embedded/fullscreen\n const setDisplayMode = useCallback(\n (mode: ChatbotDisplayMode, conversationIdParam?: string) => {\n if (mode === displayModeState) {\n return;\n }\n\n setPersistedDisplayMode(mode);\n\n // Navigate to fullscreen route with conversation ID if available\n if (mode === ChatbotDisplayMode.embedded) {\n const convId = conversationIdParam ?? currentConversationIdState;\n const path = convId\n ? `/lightspeed/conversation/${convId}`\n : '/lightspeed';\n navigate(path);\n setIsOpen(true);\n } else {\n if (isLightspeedRoute) {\n navigateBackOrGoToCatalog();\n }\n setIsOpen(true);\n }\n },\n [\n navigate,\n isLightspeedRoute,\n currentConversationIdState,\n displayModeState,\n navigateBackOrGoToCatalog,\n setPersistedDisplayMode,\n ],\n );\n\n // Only render ChatbotModal for overlay mode\n // Docked mode is handled by ApplicationDrawer in Root\n // Embedded mode is handled by LightspeedPage route\n const shouldRenderOverlayModal =\n isOpen &&\n displayModeState === ChatbotDisplayMode.default &&\n !isLightspeedRoute;\n\n const contextValue = useMemo(\n () => ({\n isChatbotActive: isOpen,\n toggleChatbot,\n displayMode: displayModeState,\n setDisplayMode,\n drawerWidth,\n setDrawerWidth,\n currentConversationId: currentConversationIdState,\n setCurrentConversationId,\n draftMessage,\n setDraftMessage,\n draftFileContents,\n setDraftFileContents,\n }),\n [\n isOpen,\n toggleChatbot,\n displayModeState,\n setDisplayMode,\n drawerWidth,\n setDrawerWidth,\n currentConversationIdState,\n setCurrentConversationId,\n draftMessage,\n setDraftMessage,\n draftFileContents,\n setDraftFileContents,\n ],\n );\n\n return (\n <LightspeedDrawerContext.Provider value={contextValue}>\n {children}\n {shouldRenderOverlayModal && (\n <ChatbotModal\n isOpen\n displayMode={displayModeState}\n onClose={closeChatbot}\n ouiaId=\"LightspeedChatbotModal\"\n aria-labelledby=\"lightspeed-chatpopup-modal\"\n className={classes.chatbotModal}\n >\n <LightspeedChatContainer />\n </ChatbotModal>\n )}\n </LightspeedDrawerContext.Provider>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -5,8 +5,14 @@ import { useLightspeedDrawerContext } from '../hooks/useLightspeedDrawerContext.
|
|
|
5
5
|
const LightspeedDrawerStateExposer = ({
|
|
6
6
|
onStateChange
|
|
7
7
|
}) => {
|
|
8
|
-
const {
|
|
9
|
-
|
|
8
|
+
const {
|
|
9
|
+
displayMode,
|
|
10
|
+
drawerWidth,
|
|
11
|
+
setDrawerWidth,
|
|
12
|
+
toggleChatbot,
|
|
13
|
+
isChatbotActive
|
|
14
|
+
} = useLightspeedDrawerContext();
|
|
15
|
+
const isDrawerOpen = displayMode === ChatbotDisplayMode.docked && isChatbotActive;
|
|
10
16
|
const toggleChatbotRef = useRef(toggleChatbot);
|
|
11
17
|
toggleChatbotRef.current = toggleChatbot;
|
|
12
18
|
const closeDrawer = useCallback(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LightspeedDrawerStateExposer.esm.js","sources":["../../src/components/LightspeedDrawerStateExposer.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, useRef } from 'react';\n\nimport { ChatbotDisplayMode } from '@patternfly/chatbot';\n\nimport { useLightspeedDrawerContext } from '../hooks/useLightspeedDrawerContext';\n\n/**\n * @public\n * Partial Lightspeed drawer state exposed to the ApplicationDrawer\n */\nexport type DrawerState = {\n id: string;\n isDrawerOpen: boolean;\n drawerWidth: number;\n setDrawerWidth: (width: number) => void;\n closeDrawer: () => void;\n};\n\n/**\n * @public\n * Props for drawer state exposer components\n */\nexport type DrawerStateExposerProps = {\n /**\n * Callback called whenever the drawer state changes\n */\n onStateChange: (state: DrawerState) => void;\n};\n\n/**\n * @public\n * This exposes LightspeedDrawer's partial context to the ApplicationDrawer\n *\n * It reads the LightspeedDrawerContext and calls the onStateChange callback with the\n * partial state (id, isDrawerOpen, drawerWidth, setDrawerWidth).\n \n */\nexport const LightspeedDrawerStateExposer = ({\n onStateChange,\n}: DrawerStateExposerProps) => {\n const {
|
|
1
|
+
{"version":3,"file":"LightspeedDrawerStateExposer.esm.js","sources":["../../src/components/LightspeedDrawerStateExposer.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, useRef } from 'react';\n\nimport { ChatbotDisplayMode } from '@patternfly/chatbot';\n\nimport { useLightspeedDrawerContext } from '../hooks/useLightspeedDrawerContext';\n\n/**\n * @public\n * Partial Lightspeed drawer state exposed to the ApplicationDrawer\n */\nexport type DrawerState = {\n id: string;\n isDrawerOpen: boolean;\n drawerWidth: number;\n setDrawerWidth: (width: number) => void;\n closeDrawer: () => void;\n};\n\n/**\n * @public\n * Props for drawer state exposer components\n */\nexport type DrawerStateExposerProps = {\n /**\n * Callback called whenever the drawer state changes\n */\n onStateChange: (state: DrawerState) => void;\n};\n\n/**\n * @public\n * This exposes LightspeedDrawer's partial context to the ApplicationDrawer\n *\n * It reads the LightspeedDrawerContext and calls the onStateChange callback with the\n * partial state (id, isDrawerOpen, drawerWidth, setDrawerWidth).\n \n */\nexport const LightspeedDrawerStateExposer = ({\n onStateChange,\n}: DrawerStateExposerProps) => {\n const {\n displayMode,\n drawerWidth,\n setDrawerWidth,\n toggleChatbot,\n isChatbotActive,\n } = useLightspeedDrawerContext();\n\n const isDrawerOpen =\n displayMode === ChatbotDisplayMode.docked && isChatbotActive;\n\n const toggleChatbotRef = useRef(toggleChatbot);\n toggleChatbotRef.current = toggleChatbot;\n\n const closeDrawer = useCallback(() => {\n toggleChatbotRef.current();\n }, []);\n\n useEffect(() => {\n onStateChange({\n id: 'lightspeed',\n isDrawerOpen,\n drawerWidth,\n setDrawerWidth,\n closeDrawer,\n });\n }, [isDrawerOpen, drawerWidth, setDrawerWidth, closeDrawer, onStateChange]);\n\n return null;\n};\n"],"names":[],"mappings":";;;;AAqDO,MAAM,+BAA+B,CAAC;AAAA,EAC3C;AACF,CAA+B,KAAA;AAC7B,EAAM,MAAA;AAAA,IACJ,WAAA;AAAA,IACA,WAAA;AAAA,IACA,cAAA;AAAA,IACA,aAAA;AAAA,IACA;AAAA,MACE,0BAA2B,EAAA;AAE/B,EAAM,MAAA,YAAA,GACJ,WAAgB,KAAA,kBAAA,CAAmB,MAAU,IAAA,eAAA;AAE/C,EAAM,MAAA,gBAAA,GAAmB,OAAO,aAAa,CAAA;AAC7C,EAAA,gBAAA,CAAiB,OAAU,GAAA,aAAA;AAE3B,EAAM,MAAA,WAAA,GAAc,YAAY,MAAM;AACpC,IAAA,gBAAA,CAAiB,OAAQ,EAAA;AAAA,GAC3B,EAAG,EAAE,CAAA;AAEL,EAAA,SAAA,CAAU,MAAM;AACd,IAAc,aAAA,CAAA;AAAA,MACZ,EAAI,EAAA,YAAA;AAAA,MACJ,YAAA;AAAA,MACA,WAAA;AAAA,MACA,cAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,KACA,CAAC,YAAA,EAAc,aAAa,cAAgB,EAAA,WAAA,EAAa,aAAa,CAAC,CAAA;AAE1E,EAAO,OAAA,IAAA;AACT;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { useState } from 'react';
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
3
3
|
import { TextField } from '@material-ui/core';
|
|
4
4
|
import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined';
|
|
5
5
|
import CloseIcon from '@mui/icons-material/Close';
|
|
@@ -12,6 +12,7 @@ import DialogContent from '@mui/material/DialogContent';
|
|
|
12
12
|
import DialogTitle from '@mui/material/DialogTitle';
|
|
13
13
|
import IconButton from '@mui/material/IconButton';
|
|
14
14
|
import Typography from '@mui/material/Typography';
|
|
15
|
+
import { useConversations } from '../hooks/useConversations.esm.js';
|
|
15
16
|
import { useRenameConversation } from '../hooks/useRenameConversation.esm.js';
|
|
16
17
|
import { useTranslation } from '../hooks/useTranslation.esm.js';
|
|
17
18
|
|
|
@@ -26,19 +27,37 @@ const RenameConversationModal = ({
|
|
|
26
27
|
isError,
|
|
27
28
|
error
|
|
28
29
|
} = useRenameConversation();
|
|
30
|
+
const { data: conversations } = useConversations();
|
|
29
31
|
const [chatName, setChatName] = useState("");
|
|
32
|
+
const [originalChatName, setOriginalChatName] = useState("");
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (isOpen && conversations) {
|
|
35
|
+
const conversation = conversations.find(
|
|
36
|
+
(c) => c.conversation_id === conversationId
|
|
37
|
+
);
|
|
38
|
+
if (conversation) {
|
|
39
|
+
setChatName(conversation.topic_summary);
|
|
40
|
+
setOriginalChatName(conversation.topic_summary);
|
|
41
|
+
} else {
|
|
42
|
+
setChatName("");
|
|
43
|
+
setOriginalChatName("");
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}, [isOpen, conversationId, conversations]);
|
|
30
47
|
const handleChatNameChange = (event) => {
|
|
31
48
|
setChatName(event.target.value);
|
|
32
49
|
};
|
|
33
|
-
const handleRename = () => {
|
|
34
|
-
|
|
50
|
+
const handleRename = async () => {
|
|
51
|
+
try {
|
|
35
52
|
await renameConversation({
|
|
36
53
|
conversation_id: conversationId,
|
|
37
54
|
newName: chatName,
|
|
38
55
|
invalidateCache: false
|
|
39
56
|
});
|
|
40
57
|
onClose();
|
|
41
|
-
}
|
|
58
|
+
} catch (e) {
|
|
59
|
+
console.warn(e);
|
|
60
|
+
}
|
|
42
61
|
};
|
|
43
62
|
return /* @__PURE__ */ jsxs(
|
|
44
63
|
Dialog,
|
|
@@ -89,6 +108,7 @@ const RenameConversationModal = ({
|
|
|
89
108
|
style: { marginTop: "10px" },
|
|
90
109
|
variant: "outlined",
|
|
91
110
|
InputProps: {
|
|
111
|
+
autoFocus: true,
|
|
92
112
|
endAdornment: /* @__PURE__ */ jsx(
|
|
93
113
|
IconButton,
|
|
94
114
|
{
|
|
@@ -101,9 +121,7 @@ const RenameConversationModal = ({
|
|
|
101
121
|
}
|
|
102
122
|
}
|
|
103
123
|
) }),
|
|
104
|
-
isError && /* @__PURE__ */ jsx(Box, { maxWidth: "650px", marginLeft: "20px", children: /* @__PURE__ */ jsx(Alert, { severity: "error", children:
|
|
105
|
-
error: String(error)
|
|
106
|
-
}) }) }),
|
|
124
|
+
isError && /* @__PURE__ */ jsx(Box, { maxWidth: "650px", marginLeft: "20px", marginRight: "20px", children: /* @__PURE__ */ jsx(Alert, { severity: "error", children: String(error) }) }),
|
|
107
125
|
/* @__PURE__ */ jsxs(DialogActions, { style: { justifyContent: "left", padding: "20px" }, children: [
|
|
108
126
|
/* @__PURE__ */ jsx(
|
|
109
127
|
Button,
|
|
@@ -112,7 +130,7 @@ const RenameConversationModal = ({
|
|
|
112
130
|
sx: {
|
|
113
131
|
textTransform: "none"
|
|
114
132
|
},
|
|
115
|
-
disabled: chatName.trim() === "",
|
|
133
|
+
disabled: chatName.trim() === "" || chatName.trim() === originalChatName.trim(),
|
|
116
134
|
onClick: handleRename,
|
|
117
135
|
children: t("conversation.rename.confirm.action")
|
|
118
136
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RenameConversationModal.esm.js","sources":["../../src/components/RenameConversationModal.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 { useState } from 'react';\n\nimport { TextField } from '@material-ui/core';\nimport CancelOutlinedIcon from '@mui/icons-material/CancelOutlined';\nimport CloseIcon from '@mui/icons-material/Close';\nimport Alert from '@mui/material/Alert';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Dialog from '@mui/material/Dialog';\nimport DialogActions from '@mui/material/DialogActions';\nimport DialogContent from '@mui/material/DialogContent';\nimport DialogTitle from '@mui/material/DialogTitle';\nimport IconButton from '@mui/material/IconButton';\nimport Typography from '@mui/material/Typography';\n\nimport { useRenameConversation } from '../hooks/useRenameConversation';\nimport { useTranslation } from '../hooks/useTranslation';\n\nexport const RenameConversationModal = ({\n isOpen,\n onClose,\n conversationId,\n}: {\n isOpen: boolean;\n onClose: () => void;\n conversationId: string;\n}) => {\n const { t } = useTranslation();\n const {\n mutateAsync: renameConversation,\n isError,\n error,\n } = useRenameConversation();\n const [chatName, setChatName] = useState<string>('');\n\n const handleChatNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setChatName(event.target.value);\n };\n\n const handleRename = () => {\n
|
|
1
|
+
{"version":3,"file":"RenameConversationModal.esm.js","sources":["../../src/components/RenameConversationModal.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 { useEffect, useState } from 'react';\n\nimport { TextField } from '@material-ui/core';\nimport CancelOutlinedIcon from '@mui/icons-material/CancelOutlined';\nimport CloseIcon from '@mui/icons-material/Close';\nimport Alert from '@mui/material/Alert';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Dialog from '@mui/material/Dialog';\nimport DialogActions from '@mui/material/DialogActions';\nimport DialogContent from '@mui/material/DialogContent';\nimport DialogTitle from '@mui/material/DialogTitle';\nimport IconButton from '@mui/material/IconButton';\nimport Typography from '@mui/material/Typography';\n\nimport { useConversations } from '../hooks/useConversations';\nimport { useRenameConversation } from '../hooks/useRenameConversation';\nimport { useTranslation } from '../hooks/useTranslation';\n\nexport const RenameConversationModal = ({\n isOpen,\n onClose,\n conversationId,\n}: {\n isOpen: boolean;\n onClose: () => void;\n conversationId: string;\n}) => {\n const { t } = useTranslation();\n const {\n mutateAsync: renameConversation,\n isError,\n error,\n } = useRenameConversation();\n const { data: conversations } = useConversations();\n const [chatName, setChatName] = useState<string>('');\n const [originalChatName, setOriginalChatName] = useState<string>('');\n\n useEffect(() => {\n if (isOpen && conversations) {\n const conversation = conversations.find(\n c => c.conversation_id === conversationId,\n );\n if (conversation) {\n setChatName(conversation.topic_summary);\n setOriginalChatName(conversation.topic_summary);\n } else {\n setChatName('');\n setOriginalChatName('');\n }\n }\n }, [isOpen, conversationId, conversations]);\n\n const handleChatNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setChatName(event.target.value);\n };\n\n const handleRename = async () => {\n try {\n await renameConversation({\n conversation_id: conversationId,\n newName: chatName,\n invalidateCache: false,\n });\n onClose();\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn(e);\n }\n };\n\n return (\n <Dialog\n open={isOpen}\n onClose={onClose}\n aria-labelledby=\"rename-modal\"\n aria-describedby=\"rename-modal-confirmation\"\n fullWidth\n >\n <DialogTitle sx={{ p: '16px 20px', fontStyle: 'inherit' }}>\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n gap: 1,\n }}\n >\n <Typography component=\"span\" sx={{ fontWeight: 'bold' }}>\n {t('conversation.rename.confirm.title')}\n </Typography>\n\n <IconButton\n aria-label=\"close\"\n onClick={onClose}\n title={t('common.close')}\n size=\"large\"\n sx={{\n position: 'absolute',\n right: 1,\n top: 1,\n color: 'grey.700',\n }}\n >\n <CloseIcon />\n </IconButton>\n </Box>\n </DialogTitle>\n <DialogContent id=\"rename-modal-body-input\">\n <TextField\n id=\"outlined-chat-name-input\"\n label={t('conversation.rename.placeholder')}\n onChange={handleChatNameChange}\n fullWidth\n value={chatName}\n style={{ marginTop: '10px' }}\n variant=\"outlined\"\n InputProps={{\n autoFocus: true,\n endAdornment: (\n <IconButton\n aria-label=\"clear-input\"\n onClick={() => setChatName('')}\n edge=\"end\"\n >\n <CancelOutlinedIcon />\n </IconButton>\n ),\n }}\n />\n </DialogContent>\n {isError && (\n <Box maxWidth=\"650px\" marginLeft=\"20px\" marginRight=\"20px\">\n <Alert severity=\"error\">{String(error)}</Alert>\n </Box>\n )}\n <DialogActions style={{ justifyContent: 'left', padding: '20px' }}>\n <Button\n variant=\"contained\"\n sx={{\n textTransform: 'none',\n }}\n disabled={\n chatName.trim() === '' ||\n chatName.trim() === originalChatName.trim()\n }\n onClick={handleRename}\n >\n {t('conversation.rename.confirm.action')}\n </Button>\n <Button\n key=\"cancel\"\n variant=\"outlined\"\n sx={{\n textTransform: 'none',\n }}\n onClick={onClose}\n >\n {t('common.cancel')}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import {
|
|
3
|
-
import { Flex, FlexItem, Content, ContentVariants, DescriptionList, DescriptionListGroup, DescriptionListTerm, DescriptionListDescription, Label
|
|
4
|
-
import { WrenchIcon
|
|
2
|
+
import { Message } from '@patternfly/chatbot';
|
|
3
|
+
import { Flex, FlexItem, Content, ContentVariants, DescriptionList, DescriptionListGroup, DescriptionListTerm, DescriptionListDescription, Label } from '@patternfly/react-core';
|
|
4
|
+
import { WrenchIcon } from '@patternfly/react-icons';
|
|
5
5
|
import { useTranslation } from '../hooks/useTranslation.esm.js';
|
|
6
6
|
|
|
7
|
-
const ToolCallContent = ({
|
|
7
|
+
const ToolCallContent = ({
|
|
8
|
+
toolCall,
|
|
9
|
+
role = "bot"
|
|
10
|
+
}) => {
|
|
8
11
|
const { t } = useTranslation();
|
|
9
|
-
const [isExpanded, setIsExpanded] = useState(false);
|
|
10
|
-
const handleCopy = async () => {
|
|
11
|
-
if (toolCall.response) {
|
|
12
|
-
await globalThis.navigator.clipboard.writeText(toolCall.response);
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
12
|
const formatExecutionTime = (seconds) => {
|
|
16
13
|
if (seconds === undefined) return "";
|
|
17
14
|
if (seconds < 1) return `${Math.round(seconds * 1e3)}ms`;
|
|
@@ -134,65 +131,39 @@ const ToolCallContent = ({ toolCall }) => {
|
|
|
134
131
|
"--pf-v6-c-description-list__group--RowGap": "var(--pf-t--global--spacer--xs)"
|
|
135
132
|
},
|
|
136
133
|
children: [
|
|
137
|
-
/* @__PURE__ */
|
|
134
|
+
/* @__PURE__ */ jsx(
|
|
138
135
|
Flex,
|
|
139
136
|
{
|
|
140
137
|
alignItems: { default: "alignItemsCenter" },
|
|
141
138
|
justifyContent: { default: "justifyContentSpaceBetween" },
|
|
142
|
-
children: [
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
] }) }),
|
|
147
|
-
/* @__PURE__ */ jsx(FlexItem, { children: /* @__PURE__ */ jsx(Tooltip, { content: t("toolCall.copyResponse"), children: /* @__PURE__ */ jsx(
|
|
148
|
-
Button,
|
|
149
|
-
{
|
|
150
|
-
variant: "plain",
|
|
151
|
-
"aria-label": t("toolCall.copyResponse"),
|
|
152
|
-
onClick: handleCopy,
|
|
153
|
-
icon: /* @__PURE__ */ jsx(CopyIcon, {})
|
|
154
|
-
}
|
|
155
|
-
) }) })
|
|
156
|
-
]
|
|
139
|
+
children: /* @__PURE__ */ jsx(FlexItem, { flex: { default: "flex_1" }, children: /* @__PURE__ */ jsxs("strong", { children: [
|
|
140
|
+
" ",
|
|
141
|
+
t("toolCall.response")
|
|
142
|
+
] }) })
|
|
157
143
|
}
|
|
158
144
|
),
|
|
159
145
|
/* @__PURE__ */ jsx(
|
|
160
146
|
DescriptionListDescription,
|
|
161
147
|
{
|
|
162
148
|
style: { marginInlineStart: 0 },
|
|
163
|
-
children: /* @__PURE__ */
|
|
149
|
+
children: /* @__PURE__ */ jsx(
|
|
164
150
|
Flex,
|
|
165
151
|
{
|
|
166
152
|
direction: { default: "column" },
|
|
167
153
|
spaceItems: { default: "spaceItemsXs" },
|
|
168
|
-
children:
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
borderRadius: "var(--pf-t--global--border--radius--small)",
|
|
179
|
-
maxHeight: isExpanded ? "300px" : "105px",
|
|
180
|
-
overflowY: "auto",
|
|
181
|
-
transition: "max-height 0.3s ease"
|
|
182
|
-
},
|
|
183
|
-
children: toolCall.response
|
|
184
|
-
}
|
|
185
|
-
) }),
|
|
186
|
-
toolCall.response.length > 300 && /* @__PURE__ */ jsx(FlexItem, { children: /* @__PURE__ */ jsx(
|
|
187
|
-
Button,
|
|
188
|
-
{
|
|
189
|
-
variant: "link",
|
|
190
|
-
isInline: true,
|
|
191
|
-
onClick: () => setIsExpanded(!isExpanded),
|
|
192
|
-
children: isExpanded ? t("toolCall.showLess") : t("toolCall.showMore")
|
|
154
|
+
children: /* @__PURE__ */ jsx(FlexItem, { children: /* @__PURE__ */ jsx(
|
|
155
|
+
Message,
|
|
156
|
+
{
|
|
157
|
+
content: toolCall.response,
|
|
158
|
+
role,
|
|
159
|
+
codeBlockProps: {
|
|
160
|
+
isExpandable: true,
|
|
161
|
+
expandableSectionProps: {
|
|
162
|
+
truncateMaxLines: 1
|
|
163
|
+
}
|
|
193
164
|
}
|
|
194
|
-
|
|
195
|
-
|
|
165
|
+
}
|
|
166
|
+
) })
|
|
196
167
|
}
|
|
197
168
|
)
|
|
198
169
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolCallContent.esm.js","sources":["../../src/components/ToolCallContent.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 { useState } from 'react';\n\nimport {\n Button,\n Content,\n ContentVariants,\n DescriptionList,\n DescriptionListDescription,\n DescriptionListGroup,\n DescriptionListTerm,\n Flex,\n FlexItem,\n Label,\n Tooltip,\n} from '@patternfly/react-core';\nimport { CopyIcon, WrenchIcon } from '@patternfly/react-icons';\n\nimport { useTranslation } from '../hooks/useTranslation';\nimport { ToolCall } from '../types';\n\ninterface ToolCallContentProps {\n toolCall: ToolCall;\n}\n\n/**\n * Lightweight component for rendering tool call expandable content.\n * Used inside PatternFly's ToolCall component's expandableContent prop.\n */\nexport const ToolCallContent = ({ toolCall }: ToolCallContentProps) => {\n const { t } = useTranslation();\n const [isExpanded, setIsExpanded] = useState(false);\n\n const handleCopy = async () => {\n if (toolCall.response) {\n await globalThis.navigator.clipboard.writeText(toolCall.response);\n }\n };\n\n const formatExecutionTime = (seconds?: number): string => {\n if (seconds === undefined) return '';\n if (seconds < 1) return `${Math.round(seconds * 1000)}ms`;\n return `${seconds.toFixed(2)}s`;\n };\n\n const getParameterKeys = (): string[] => {\n if (!toolCall.arguments) return [];\n return Object.keys(toolCall.arguments).filter(\n key => toolCall.arguments[key] !== '' && toolCall.arguments[key] !== null,\n );\n };\n\n const getThinkingTime = (): number => {\n if (toolCall.startTime && toolCall.endTime) {\n return Math.round((toolCall.endTime - toolCall.startTime) / 1000);\n }\n return 0;\n };\n\n const thinkingTime = getThinkingTime();\n const parameterKeys = getParameterKeys();\n\n return (\n <Flex\n direction={{ default: 'column' }}\n spaceItems={{ default: 'spaceItemsSm' }}\n >\n {/* Thinking Time */}\n {thinkingTime > 0 && (\n <FlexItem>\n <Content component={ContentVariants.small}>\n {t('toolCall.thinking' as any, {\n seconds: String(thinkingTime),\n })}\n </Content>\n </FlexItem>\n )}\n\n {/* Summary */}\n <FlexItem>\n <Content component={ContentVariants.p}>{t('toolCall.summary')}</Content>\n </FlexItem>\n\n {/* Tool Header with MCP Server */}\n <FlexItem>\n <div\n style={{\n border: '1px solid var(--pf-t--global--border--color--default)',\n borderRadius: 'var(--pf-t--global--border--radius--small)',\n padding: 'var(--pf-t--global--spacer--md)',\n }}\n >\n <Flex\n direction={{ default: 'column' }}\n spaceItems={{ default: 'spaceItemsSm' }}\n >\n <FlexItem\n style={{\n borderBottom:\n '1px solid var(--pf-t--global--border--color--default)',\n paddingBottom: 'var(--pf-t--global--spacer--sm)',\n }}\n >\n <Content\n component={ContentVariants.p}\n style={{ marginBlockEnd: 0 }}\n >\n <WrenchIcon\n style={{\n color: 'var(--pf-t--global--icon--color--brand--default)',\n marginRight: '0.5em',\n }}\n />\n <strong>{t('toolCall.mcpServer')}</strong>\n </Content>\n {toolCall.executionTime !== undefined && (\n <Content component={ContentVariants.small}>\n {t('toolCall.executionTime')}\n {formatExecutionTime(toolCall.executionTime)}\n </Content>\n )}\n </FlexItem>\n\n {/* Description List for Parameters and Response */}\n <FlexItem>\n <DescriptionList\n style={\n {\n '--pf-v6-c-description-list--RowGap':\n 'var(--pf-t--global--spacer--md)',\n } as any\n }\n aria-label=\"Tool response\"\n >\n {/* Parameters Section */}\n {parameterKeys.length > 0 && (\n <DescriptionListGroup\n style={\n {\n '--pf-v6-c-description-list__group--RowGap':\n 'var(--pf-t--global--spacer--xs)',\n } as any\n }\n >\n <DescriptionListTerm>\n {t('toolCall.parameters' as any, {\n defaultValue: 'Parameters',\n }) || 'Parameters'}\n </DescriptionListTerm>\n <DescriptionListDescription\n style={{ marginInlineStart: 0 }}\n >\n <Flex direction={{ default: 'column' }}>\n {toolCall.description && (\n <FlexItem>\n <Content component={ContentVariants.small}>\n {toolCall.description}\n </Content>\n </FlexItem>\n )}\n <FlexItem>\n <Flex\n gap={{ default: 'gapSm' }}\n flexWrap={{ default: 'wrap' }}\n >\n {parameterKeys.map(key => (\n <FlexItem key={key}>\n <Label variant=\"outline\" color=\"blue\">\n {key}\n </Label>\n </FlexItem>\n ))}\n </Flex>\n </FlexItem>\n </Flex>\n </DescriptionListDescription>\n </DescriptionListGroup>\n )}\n\n {/* Response Section */}\n {toolCall.response && (\n <DescriptionListGroup\n style={\n {\n '--pf-v6-c-description-list__group--RowGap':\n 'var(--pf-t--global--spacer--xs)',\n } as any\n }\n >\n {/* <DescriptionListTerm> */}\n <Flex\n alignItems={{ default: 'alignItemsCenter' }}\n justifyContent={{ default: 'justifyContentSpaceBetween' }}\n >\n <FlexItem flex={{ default: 'flex_1' }}>\n <strong> {t('toolCall.response')}</strong>\n </FlexItem>\n <FlexItem>\n <Tooltip content={t('toolCall.copyResponse')}>\n <Button\n variant=\"plain\"\n aria-label={t('toolCall.copyResponse')}\n onClick={handleCopy}\n icon={<CopyIcon />}\n />\n </Tooltip>\n </FlexItem>\n </Flex>\n {/* </DescriptionListTerm> */}\n <DescriptionListDescription\n style={{ marginInlineStart: 0 }}\n >\n <Flex\n direction={{ default: 'column' }}\n spaceItems={{ default: 'spaceItemsXs' }}\n >\n <FlexItem>\n <div\n style={{\n fontFamily:\n 'Red Hat Mono, Monaco, Consolas, monospace',\n fontSize: '0.875rem',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n padding: 'var(--pf-t--global--spacer--sm)',\n borderRadius:\n 'var(--pf-t--global--border--radius--small)',\n maxHeight: isExpanded ? '300px' : '105px',\n overflowY: 'auto',\n transition: 'max-height 0.3s ease',\n }}\n >\n {toolCall.response}\n </div>\n </FlexItem>\n {toolCall.response.length > 300 && (\n <FlexItem>\n <Button\n variant=\"link\"\n isInline\n onClick={() => setIsExpanded(!isExpanded)}\n >\n {isExpanded\n ? t('toolCall.showLess')\n : t('toolCall.showMore')}\n </Button>\n </FlexItem>\n )}\n </Flex>\n </DescriptionListDescription>\n </DescriptionListGroup>\n )}\n </DescriptionList>\n </FlexItem>\n </Flex>\n </div>\n </FlexItem>\n </Flex>\n );\n};\n\nexport default ToolCallContent;\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ToolCallContent.esm.js","sources":["../../src/components/ToolCallContent.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 { Message } from '@patternfly/chatbot';\nimport {\n Content,\n ContentVariants,\n DescriptionList,\n DescriptionListDescription,\n DescriptionListGroup,\n DescriptionListTerm,\n Flex,\n FlexItem,\n Label,\n} from '@patternfly/react-core';\nimport { WrenchIcon } from '@patternfly/react-icons';\n\nimport { useTranslation } from '../hooks/useTranslation';\nimport { ToolCall } from '../types';\n\ninterface ToolCallContentProps {\n toolCall: ToolCall;\n role?: 'user' | 'bot';\n}\n\n/**\n * Lightweight component for rendering tool call expandable content.\n * Used inside PatternFly's ToolCall component's expandableContent prop.\n */\nexport const ToolCallContent = ({\n toolCall,\n role = 'bot',\n}: ToolCallContentProps) => {\n const { t } = useTranslation();\n\n const formatExecutionTime = (seconds?: number): string => {\n if (seconds === undefined) return '';\n if (seconds < 1) return `${Math.round(seconds * 1000)}ms`;\n return `${seconds.toFixed(2)}s`;\n };\n\n const getParameterKeys = (): string[] => {\n if (!toolCall.arguments) return [];\n return Object.keys(toolCall.arguments).filter(\n key => toolCall.arguments[key] !== '' && toolCall.arguments[key] !== null,\n );\n };\n\n const getThinkingTime = (): number => {\n if (toolCall.startTime && toolCall.endTime) {\n return Math.round((toolCall.endTime - toolCall.startTime) / 1000);\n }\n return 0;\n };\n\n const thinkingTime = getThinkingTime();\n const parameterKeys = getParameterKeys();\n\n return (\n <Flex\n direction={{ default: 'column' }}\n spaceItems={{ default: 'spaceItemsSm' }}\n >\n {/* Thinking Time */}\n {thinkingTime > 0 && (\n <FlexItem>\n <Content component={ContentVariants.small}>\n {t('toolCall.thinking' as any, {\n seconds: String(thinkingTime),\n })}\n </Content>\n </FlexItem>\n )}\n\n {/* Summary */}\n <FlexItem>\n <Content component={ContentVariants.p}>{t('toolCall.summary')}</Content>\n </FlexItem>\n\n {/* Tool Header with MCP Server */}\n <FlexItem>\n <div\n style={{\n border: '1px solid var(--pf-t--global--border--color--default)',\n borderRadius: 'var(--pf-t--global--border--radius--small)',\n padding: 'var(--pf-t--global--spacer--md)',\n }}\n >\n <Flex\n direction={{ default: 'column' }}\n spaceItems={{ default: 'spaceItemsSm' }}\n >\n <FlexItem\n style={{\n borderBottom:\n '1px solid var(--pf-t--global--border--color--default)',\n paddingBottom: 'var(--pf-t--global--spacer--sm)',\n }}\n >\n <Content\n component={ContentVariants.p}\n style={{ marginBlockEnd: 0 }}\n >\n <WrenchIcon\n style={{\n color: 'var(--pf-t--global--icon--color--brand--default)',\n marginRight: '0.5em',\n }}\n />\n <strong>{t('toolCall.mcpServer')}</strong>\n </Content>\n {toolCall.executionTime !== undefined && (\n <Content component={ContentVariants.small}>\n {t('toolCall.executionTime')}\n {formatExecutionTime(toolCall.executionTime)}\n </Content>\n )}\n </FlexItem>\n\n {/* Description List for Parameters and Response */}\n <FlexItem>\n <DescriptionList\n style={\n {\n '--pf-v6-c-description-list--RowGap':\n 'var(--pf-t--global--spacer--md)',\n } as any\n }\n aria-label=\"Tool response\"\n >\n {/* Parameters Section */}\n {parameterKeys.length > 0 && (\n <DescriptionListGroup\n style={\n {\n '--pf-v6-c-description-list__group--RowGap':\n 'var(--pf-t--global--spacer--xs)',\n } as any\n }\n >\n <DescriptionListTerm>\n {t('toolCall.parameters' as any, {\n defaultValue: 'Parameters',\n }) || 'Parameters'}\n </DescriptionListTerm>\n <DescriptionListDescription\n style={{ marginInlineStart: 0 }}\n >\n <Flex direction={{ default: 'column' }}>\n {toolCall.description && (\n <FlexItem>\n <Content component={ContentVariants.small}>\n {toolCall.description}\n </Content>\n </FlexItem>\n )}\n <FlexItem>\n <Flex\n gap={{ default: 'gapSm' }}\n flexWrap={{ default: 'wrap' }}\n >\n {parameterKeys.map(key => (\n <FlexItem key={key}>\n <Label variant=\"outline\" color=\"blue\">\n {key}\n </Label>\n </FlexItem>\n ))}\n </Flex>\n </FlexItem>\n </Flex>\n </DescriptionListDescription>\n </DescriptionListGroup>\n )}\n\n {/* Response Section */}\n {toolCall.response && (\n <DescriptionListGroup\n style={\n {\n '--pf-v6-c-description-list__group--RowGap':\n 'var(--pf-t--global--spacer--xs)',\n } as any\n }\n >\n {/* <DescriptionListTerm> */}\n <Flex\n alignItems={{ default: 'alignItemsCenter' }}\n justifyContent={{ default: 'justifyContentSpaceBetween' }}\n >\n <FlexItem flex={{ default: 'flex_1' }}>\n <strong> {t('toolCall.response')}</strong>\n </FlexItem>\n </Flex>\n {/* </DescriptionListTerm> */}\n <DescriptionListDescription\n style={{ marginInlineStart: 0 }}\n >\n <Flex\n direction={{ default: 'column' }}\n spaceItems={{ default: 'spaceItemsXs' }}\n >\n <FlexItem>\n <Message\n content={toolCall.response}\n role={role}\n codeBlockProps={{\n isExpandable: true,\n expandableSectionProps: {\n truncateMaxLines: 1,\n },\n }}\n />\n </FlexItem>\n </Flex>\n </DescriptionListDescription>\n </DescriptionListGroup>\n )}\n </DescriptionList>\n </FlexItem>\n </Flex>\n </div>\n </FlexItem>\n </Flex>\n );\n};\n\nexport default ToolCallContent;\n"],"names":[],"mappings":"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"}
|