@red-hat-developer-hub/backstage-plugin-intelligent-assistant 5.2.0 → 5.3.1

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 (106) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +14 -2
  3. package/dist/alpha.d.ts +24 -0
  4. package/dist/components/AttachmentContext.esm.js +1 -1
  5. package/dist/components/ChatLoadingFallback.esm.js +37 -0
  6. package/dist/components/ChatLoadingFallback.esm.js.map +1 -0
  7. package/dist/components/CollapsedHistoryStrip.esm.js +1 -1
  8. package/dist/components/LightSpeedChat.esm.js +76 -29
  9. package/dist/components/LightSpeedChat.esm.js.map +1 -1
  10. package/dist/components/LightspeedChatBox.esm.js +2 -2
  11. package/dist/components/LightspeedChatBoxHeader.esm.js +30 -2
  12. package/dist/components/LightspeedChatBoxHeader.esm.js.map +1 -1
  13. package/dist/components/LightspeedChatContainer.esm.js +20 -4
  14. package/dist/components/LightspeedChatContainer.esm.js.map +1 -1
  15. package/dist/components/LightspeedDrawerContext.esm.js.map +1 -1
  16. package/dist/components/LightspeedDrawerProvider.esm.js +11 -25
  17. package/dist/components/LightspeedDrawerProvider.esm.js.map +1 -1
  18. package/dist/components/LightspeedFABContent.esm.js +14 -2
  19. package/dist/components/LightspeedFABContent.esm.js.map +1 -1
  20. package/dist/components/LightspeedOverlayChat.esm.js +39 -0
  21. package/dist/components/LightspeedOverlayChat.esm.js.map +1 -0
  22. package/dist/components/McpConfigureServerModal.esm.js +2 -2
  23. package/dist/components/MessageBarModelSelector.esm.js +105 -13
  24. package/dist/components/MessageBarModelSelector.esm.js.map +1 -1
  25. package/dist/components/ScreenContextChip.esm.js +172 -0
  26. package/dist/components/ScreenContextChip.esm.js.map +1 -0
  27. package/dist/components/ToastAlertGroup.esm.js +1 -1
  28. package/dist/components/criticalFabBundle.esm.js +3 -0
  29. package/dist/components/criticalFabBundle.esm.js.map +1 -0
  30. package/dist/components/loaders.esm.js +11 -0
  31. package/dist/components/loaders.esm.js.map +1 -0
  32. package/dist/components/notebooks/AddDocumentModal.esm.js +2 -2
  33. package/dist/components/notebooks/DocumentSidebar.esm.js +1 -1
  34. package/dist/components/notebooks/NotebookCard.esm.js +1 -1
  35. package/dist/components/notebooks/NotebookStreamProvider.esm.js +1 -1
  36. package/dist/components/notebooks/NotebookView.esm.js +3 -3
  37. package/dist/components/notebooks/OverwriteConfirmModal.esm.js +1 -1
  38. package/dist/components/notebooks/UploadResourceScreen.esm.js +1 -1
  39. package/dist/components/notebooks/notebookStreamStore.esm.js +1 -1
  40. package/dist/components/notebooks/notebookStreamStore.esm.js.map +1 -1
  41. package/dist/const.esm.js +9 -1
  42. package/dist/const.esm.js.map +1 -1
  43. package/dist/fabModule.esm.js +51 -0
  44. package/dist/fabModule.esm.js.map +1 -0
  45. package/dist/hooks/screenContextLabelSubscription.esm.js +113 -0
  46. package/dist/hooks/screenContextLabelSubscription.esm.js.map +1 -0
  47. package/dist/hooks/useConversationMessages.esm.js +2 -1
  48. package/dist/hooks/useConversationMessages.esm.js.map +1 -1
  49. package/dist/hooks/useDisplayModeSettings.esm.js +1 -1
  50. package/dist/hooks/useDisplayModeSettings.esm.js.map +1 -1
  51. package/dist/hooks/useLightspeedProviderState.esm.js +1 -2
  52. package/dist/hooks/useLightspeedProviderState.esm.js.map +1 -1
  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/useWindowLocation.esm.js +28 -0
  58. package/dist/hooks/useWindowLocation.esm.js.map +1 -0
  59. package/dist/index.d.ts +1 -15
  60. package/dist/index.esm.js +7 -69
  61. package/dist/index.esm.js.map +1 -1
  62. package/dist/intelligent-assistant-fab-module.d.ts +12 -4
  63. package/dist/intelligent-assistant-fab-module.esm.js +1 -1
  64. package/dist/intelligent-assistant-translations-module.d.ts +10 -4
  65. package/dist/intelligent-assistant-translations-module.esm.js +1 -1
  66. package/dist/lazy/LazyLightspeedChatDrawerContent.esm.js +13 -0
  67. package/dist/lazy/LazyLightspeedChatDrawerContent.esm.js.map +1 -0
  68. package/dist/lazy/LazyLightspeedFabRootWrapper.esm.js +17 -0
  69. package/dist/lazy/LazyLightspeedFabRootWrapper.esm.js.map +1 -0
  70. package/dist/legacy.d.ts +14 -16
  71. package/dist/legacy.esm.js +2 -9
  72. package/dist/legacy.esm.js.map +1 -1
  73. package/dist/loadChatPatternflyStyles.esm.js +14 -0
  74. package/dist/loadChatPatternflyStyles.esm.js.map +1 -0
  75. package/dist/muiClassNameConfig.esm.js +6 -0
  76. package/dist/muiClassNameConfig.esm.js.map +1 -0
  77. package/dist/plugin.esm.js +4 -4
  78. package/dist/plugin.esm.js.map +1 -1
  79. package/dist/translations/de.esm.js +24 -0
  80. package/dist/translations/de.esm.js.map +1 -1
  81. package/dist/translations/es.esm.js +24 -0
  82. package/dist/translations/es.esm.js.map +1 -1
  83. package/dist/translations/fr.esm.js +24 -0
  84. package/dist/translations/fr.esm.js.map +1 -1
  85. package/dist/translations/it.esm.js +24 -0
  86. package/dist/translations/it.esm.js.map +1 -1
  87. package/dist/translations/ja.esm.js +24 -0
  88. package/dist/translations/ja.esm.js.map +1 -1
  89. package/dist/translations/ref.esm.js +24 -0
  90. package/dist/translations/ref.esm.js.map +1 -1
  91. package/dist/translationsModule.esm.js +18 -0
  92. package/dist/translationsModule.esm.js.map +1 -0
  93. package/dist/types.esm.js.map +1 -1
  94. package/dist/utils/dom-selectors.esm.js +22 -2
  95. package/dist/utils/dom-selectors.esm.js.map +1 -1
  96. package/dist/utils/lightspeed-chatbox-message-utils.esm.js +145 -0
  97. package/dist/utils/lightspeed-chatbox-message-utils.esm.js.map +1 -0
  98. package/dist/utils/lightspeed-chatbox-utils.esm.js +20 -144
  99. package/dist/utils/lightspeed-chatbox-utils.esm.js.map +1 -1
  100. package/dist/utils/screen-capture.esm.js +116 -0
  101. package/dist/utils/screen-capture.esm.js.map +1 -0
  102. package/dist/utils/screen-context-utils.esm.js +343 -0
  103. package/dist/utils/screen-context-utils.esm.js.map +1 -0
  104. package/dist/utils/sensitive-data-redactor.esm.js +39 -1
  105. package/dist/utils/sensitive-data-redactor.esm.js.map +1 -1
  106. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"notebookStreamStore.esm.js","sources":["../../../src/components/notebooks/notebookStreamStore.ts"],"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 { MessageProps } from '@patternfly/chatbot';\n\nimport { TEMP_CONVERSATION_ID } from '../../const';\nimport {\n clearSharedToolCallsCacheSessionPrefix,\n migrateSharedToolCallsCacheSessionPrefixToConversation,\n setSharedToolCallsCache,\n} from '../../hooks/toolCallsCacheStore';\nimport { NotebookSession, ToolCall } from '../../types';\nimport {\n createBotMessage,\n createUserMessage,\n getTimestamp,\n normalizeChatUserInput,\n transformDocumentsToSources,\n} from '../../utils/lightspeed-chatbox-utils';\nimport queryClient from '../../utils/queryClient';\nimport {\n applyToolResultToToolCalls,\n createTempToolCallsCacheSessionPrefix,\n normalizeToolCalls,\n parseSSEBuffer,\n parseToolCallFromEvent,\n parseToolResultFromEvent,\n toolCallIdKey,\n} from '../../utils/stream-event-helpers';\n\n/**\n * External store that owns notebook message streaming, keyed by notebook\n * `sessionId`. The store lives above the display-mode remount boundary\n * (mounted by {@link NotebookStreamProvider}) so a stream started in one mode\n * (overlay/docked/fullscreen) keeps running when the notebook view unmounts and\n * remounts in another mode. The view is a pure subscriber: it never owns the\n * stream lifecycle, and the stream is aborted only on explicit intent\n * (stop/close/delete/provider-unmount), never on unmount.\n */\n\nexport type ExtendedMessageProps = MessageProps & { toolCalls?: ToolCall[] };\n\nexport type NotebookStreamStatus =\n 'idle' | 'streaming' | 'complete' | 'stopped' | 'error';\n\nexport interface NotebookStreamSnapshot {\n messages: ExtendedMessageProps[];\n conversationId: string;\n requestId: string;\n status: NotebookStreamStatus;\n}\n\nexport interface NotebookSendParams {\n prompt: string;\n /** Current on-screen messages the new turn is appended to. */\n seedMessages: ExtendedMessageProps[];\n /** Current conversation id (may be the provisional temp id). */\n conversationId: string;\n userName?: string;\n avatar: string;\n botAvatar: string;\n selectedModel: string;\n /** Bound to the notebook session; returns the SSE reader. */\n createMessage: (\n prompt: string,\n options?: { signal?: AbortSignal },\n ) => Promise<ReadableStreamDefaultReader<Uint8Array>>;\n}\n\nexport interface NotebookStreamStore {\n subscribe(sessionId: string, listener: () => void): () => void;\n getSnapshot(sessionId: string): NotebookStreamSnapshot;\n send(sessionId: string, params: NotebookSendParams): void;\n stop(sessionId: string): void;\n clear(sessionId: string): void;\n clearAll(): void;\n}\n\nconst IDLE_SNAPSHOT: NotebookStreamSnapshot = Object.freeze({\n messages: [],\n conversationId: '',\n requestId: '',\n status: 'idle',\n});\n\ninterface Entry {\n snapshot: NotebookStreamSnapshot;\n listeners: Set<() => void>;\n abort?: AbortController;\n generation: number;\n pendingToolCalls: Record<string, ToolCall>;\n}\n\nexport function createNotebookStreamStore(): NotebookStreamStore {\n const entries = new Map<string, Entry>();\n\n const ensureEntry = (sessionId: string): Entry => {\n let entry = entries.get(sessionId);\n if (!entry) {\n entry = {\n snapshot: IDLE_SNAPSHOT,\n listeners: new Set(),\n generation: 0,\n pendingToolCalls: {},\n };\n entries.set(sessionId, entry);\n }\n return entry;\n };\n\n const emit = (\n sessionId: string,\n next: Partial<NotebookStreamSnapshot> & {\n messages?: ExtendedMessageProps[];\n },\n ) => {\n const entry = ensureEntry(sessionId);\n entry.snapshot = { ...entry.snapshot, ...next };\n entry.listeners.forEach(l => l());\n };\n\n const updateSessionConversationId = (\n sessionId: string,\n conversationId: string,\n ) => {\n queryClient.setQueryData<NotebookSession>(\n ['notebooks', 'session', sessionId],\n old =>\n old\n ? {\n ...old,\n metadata: { ...old.metadata, conversation_id: conversationId },\n }\n : old,\n );\n };\n\n async function runStream(sessionId: string, params: NotebookSendParams) {\n const {\n prompt,\n seedMessages,\n userName,\n avatar,\n botAvatar,\n selectedModel,\n createMessage,\n } = params;\n\n const entry = ensureEntry(sessionId);\n const signal = entry.abort!.signal;\n const runGeneration = entry.generation;\n entry.pendingToolCalls = {};\n\n const isStale = () => signal.aborted || entry.generation !== runGeneration;\n\n let convId = params.conversationId;\n let requestId = '';\n let newConversationId = '';\n const startedOnTemp = convId === TEMP_CONVERSATION_ID;\n const toolCallsCacheKeyPrefix = startedOnTemp\n ? createTempToolCallsCacheSessionPrefix()\n : convId;\n\n let working: ExtendedMessageProps[] = [\n ...seedMessages,\n createUserMessage({\n avatar,\n name: userName,\n content: prompt,\n timestamp: getTimestamp(Date.now()) ?? '',\n }),\n createBotMessage({\n avatar: botAvatar,\n isLoading: true,\n name: selectedModel,\n content: '',\n timestamp: '',\n }),\n ];\n\n const commit = (status: NotebookStreamStatus = 'streaming') =>\n emit(sessionId, {\n messages: [...working],\n conversationId: convId,\n requestId,\n status,\n });\n\n const updateLast = (\n fn: (msg: ExtendedMessageProps) => ExtendedMessageProps,\n ) => {\n if (working.length === 0) return;\n const lastIndex = working.length - 1;\n working = [...working.slice(0, lastIndex), fn({ ...working[lastIndex] })];\n };\n\n commit('streaming');\n\n const finalMessages: string[] = [];\n let buffer = '';\n\n try {\n const reader = await createMessage(prompt, { signal });\n if (isStale()) return;\n\n const decoder = new TextDecoder('utf-8');\n let streamEnded = false;\n\n while (!streamEnded) {\n if (isStale()) return;\n\n const { value, done } = await reader.read();\n if (isStale()) return;\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const { events: parsedEvents, remainder } = parseSSEBuffer(buffer);\n buffer = remainder;\n\n for (const { event, data } of parsedEvents) {\n if (event === 'start') {\n requestId = data?.request_id;\n if (startedOnTemp) {\n newConversationId = data?.conversation_id;\n if (newConversationId) {\n updateSessionConversationId(sessionId, newConversationId);\n }\n }\n commit('streaming');\n }\n\n if (event === 'tool_call') {\n const toolCall = parseToolCallFromEvent(data);\n\n if (toolCall && data.id !== null) {\n entry.pendingToolCalls[toolCallIdKey(data.id)] = toolCall;\n const lastIndex = working.length - 1;\n const messageIndex = Math.floor(lastIndex / 2);\n updateLast(last => {\n const nextToolCalls = [\n ...normalizeToolCalls(last.toolCalls),\n toolCall,\n ];\n setSharedToolCallsCache(\n `${toolCallsCacheKeyPrefix}-${messageIndex}`,\n nextToolCalls,\n );\n return { ...last, toolCalls: nextToolCalls };\n });\n commit('streaming');\n }\n }\n\n if (event === 'tool_result') {\n const result = parseToolResultFromEvent(\n data,\n entry.pendingToolCalls,\n );\n\n if (result) {\n const lastIndex = working.length - 1;\n const messageIndex = Math.floor(lastIndex / 2);\n updateLast(last => {\n const updatedToolCalls = applyToolResultToToolCalls(\n last.toolCalls || [],\n result,\n );\n setSharedToolCallsCache(\n `${toolCallsCacheKeyPrefix}-${messageIndex}`,\n updatedToolCalls,\n );\n return { ...last, toolCalls: updatedToolCalls };\n });\n delete entry.pendingToolCalls[result.toolIdKey];\n commit('streaming');\n }\n }\n\n if (event === 'token') {\n const content = data?.token || '';\n finalMessages.push(content);\n updateLast(last => {\n const next = { ...last };\n if ((next.content ?? '').trim().length > 0) {\n next.isLoading = false;\n }\n next.content = (next.content ?? '') + content;\n next.name = data?.response_metadata?.model || selectedModel;\n next.timestamp = getTimestamp(\n data?.response_metadata?.created_at || Date.now(),\n );\n return next;\n });\n commit('streaming');\n }\n\n if (event === 'interrupted') {\n if (startedOnTemp && data?.conversation_id) {\n newConversationId = data.conversation_id;\n }\n updateLast(last => ({ ...last, isLoading: false }));\n commit('streaming');\n streamEnded = true;\n break;\n }\n\n if (event === 'end') {\n const documents = data?.referenced_documents || [];\n const sources = transformDocumentsToSources(documents);\n updateLast(last => ({\n ...last,\n isLoading: false,\n ...(sources ? { sources } : {}),\n }));\n commit('streaming');\n }\n }\n if (streamEnded) break;\n }\n } catch (e: any) {\n if (isStale()) return;\n updateLast(last => ({\n ...last,\n isLoading: false,\n content: `${last.content ?? ''}${e}`,\n error: { title: e?.message },\n timestamp: getTimestamp(Date.now()),\n }));\n finalMessages.push(`${e}`);\n emit(sessionId, {\n messages: [...working],\n conversationId: newConversationId || convId,\n requestId,\n status: 'error',\n });\n return;\n }\n\n if (isStale()) return;\n\n // Migrate temp conversation to its real id (tool-call cache + session cache).\n if (startedOnTemp && newConversationId) {\n migrateSharedToolCallsCacheSessionPrefixToConversation(\n toolCallsCacheKeyPrefix,\n newConversationId,\n );\n convId = newConversationId;\n updateSessionConversationId(sessionId, newConversationId);\n } else if (startedOnTemp) {\n clearSharedToolCallsCacheSessionPrefix(toolCallsCacheKeyPrefix);\n }\n\n // Status stays 'complete' (never reverts to 'idle') so the in-memory\n // transcript is preserved across remounts. The view layer merges this with\n // react-query's refetch which fires after invalidation below. If the\n // notebook is later closed/deleted, clear() drops the entry entirely and\n // getSnapshot falls back to IDLE_SNAPSHOT; the next open re-fetches from\n // the server via useConversationMessages.\n commit('complete');\n\n queryClient.invalidateQueries({\n queryKey: ['conversationMessages', convId],\n });\n queryClient.invalidateQueries({ queryKey: ['notebooks', 'sessions'] });\n }\n\n return {\n subscribe(sessionId, listener) {\n const entry = ensureEntry(sessionId);\n entry.listeners.add(listener);\n return () => {\n entry.listeners.delete(listener);\n };\n },\n\n getSnapshot(sessionId) {\n return entries.get(sessionId)?.snapshot ?? IDLE_SNAPSHOT;\n },\n\n send(sessionId, params) {\n if (!normalizeChatUserInput(params.prompt)) return;\n const entry = ensureEntry(sessionId);\n entry.abort?.abort();\n entry.abort = new AbortController();\n entry.generation++;\n void runStream(sessionId, params);\n },\n\n stop(sessionId) {\n const entry = entries.get(sessionId);\n if (!entry) return;\n entry.abort?.abort();\n const messages = entry.snapshot.messages;\n const lastIndex = messages.length - 1;\n const nextMessages =\n lastIndex >= 0\n ? [\n ...messages.slice(0, lastIndex),\n { ...messages[lastIndex], isLoading: false },\n ]\n : messages;\n emit(sessionId, {\n messages: nextMessages,\n requestId: '',\n status: 'stopped',\n });\n },\n\n clear(sessionId) {\n const entry = entries.get(sessionId);\n if (!entry) return;\n entry.abort?.abort();\n entries.delete(sessionId);\n },\n\n clearAll() {\n entries.forEach(entry => entry.abort?.abort());\n entries.clear();\n },\n };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"notebookStreamStore.esm.js","sources":["../../../src/components/notebooks/notebookStreamStore.ts"],"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 type { MessageProps } from '@patternfly/chatbot';\n\nimport { TEMP_CONVERSATION_ID } from '../../const';\nimport {\n clearSharedToolCallsCacheSessionPrefix,\n migrateSharedToolCallsCacheSessionPrefixToConversation,\n setSharedToolCallsCache,\n} from '../../hooks/toolCallsCacheStore';\nimport { NotebookSession, ToolCall } from '../../types';\nimport {\n createBotMessage,\n createUserMessage,\n getTimestamp,\n normalizeChatUserInput,\n transformDocumentsToSources,\n} from '../../utils/lightspeed-chatbox-message-utils';\nimport queryClient from '../../utils/queryClient';\nimport {\n applyToolResultToToolCalls,\n createTempToolCallsCacheSessionPrefix,\n normalizeToolCalls,\n parseSSEBuffer,\n parseToolCallFromEvent,\n parseToolResultFromEvent,\n toolCallIdKey,\n} from '../../utils/stream-event-helpers';\n\n/**\n * External store that owns notebook message streaming, keyed by notebook\n * `sessionId`. The store lives above the display-mode remount boundary\n * (mounted by {@link NotebookStreamProvider}) so a stream started in one mode\n * (overlay/docked/fullscreen) keeps running when the notebook view unmounts and\n * remounts in another mode. The view is a pure subscriber: it never owns the\n * stream lifecycle, and the stream is aborted only on explicit intent\n * (stop/close/delete/provider-unmount), never on unmount.\n */\n\nexport type ExtendedMessageProps = MessageProps & { toolCalls?: ToolCall[] };\n\nexport type NotebookStreamStatus =\n 'idle' | 'streaming' | 'complete' | 'stopped' | 'error';\n\nexport interface NotebookStreamSnapshot {\n messages: ExtendedMessageProps[];\n conversationId: string;\n requestId: string;\n status: NotebookStreamStatus;\n}\n\nexport interface NotebookSendParams {\n prompt: string;\n /** Current on-screen messages the new turn is appended to. */\n seedMessages: ExtendedMessageProps[];\n /** Current conversation id (may be the provisional temp id). */\n conversationId: string;\n userName?: string;\n avatar: string;\n botAvatar: string;\n selectedModel: string;\n /** Bound to the notebook session; returns the SSE reader. */\n createMessage: (\n prompt: string,\n options?: { signal?: AbortSignal },\n ) => Promise<ReadableStreamDefaultReader<Uint8Array>>;\n}\n\nexport interface NotebookStreamStore {\n subscribe(sessionId: string, listener: () => void): () => void;\n getSnapshot(sessionId: string): NotebookStreamSnapshot;\n send(sessionId: string, params: NotebookSendParams): void;\n stop(sessionId: string): void;\n clear(sessionId: string): void;\n clearAll(): void;\n}\n\nconst IDLE_SNAPSHOT: NotebookStreamSnapshot = Object.freeze({\n messages: [],\n conversationId: '',\n requestId: '',\n status: 'idle',\n});\n\ninterface Entry {\n snapshot: NotebookStreamSnapshot;\n listeners: Set<() => void>;\n abort?: AbortController;\n generation: number;\n pendingToolCalls: Record<string, ToolCall>;\n}\n\nexport function createNotebookStreamStore(): NotebookStreamStore {\n const entries = new Map<string, Entry>();\n\n const ensureEntry = (sessionId: string): Entry => {\n let entry = entries.get(sessionId);\n if (!entry) {\n entry = {\n snapshot: IDLE_SNAPSHOT,\n listeners: new Set(),\n generation: 0,\n pendingToolCalls: {},\n };\n entries.set(sessionId, entry);\n }\n return entry;\n };\n\n const emit = (\n sessionId: string,\n next: Partial<NotebookStreamSnapshot> & {\n messages?: ExtendedMessageProps[];\n },\n ) => {\n const entry = ensureEntry(sessionId);\n entry.snapshot = { ...entry.snapshot, ...next };\n entry.listeners.forEach(l => l());\n };\n\n const updateSessionConversationId = (\n sessionId: string,\n conversationId: string,\n ) => {\n queryClient.setQueryData<NotebookSession>(\n ['notebooks', 'session', sessionId],\n old =>\n old\n ? {\n ...old,\n metadata: { ...old.metadata, conversation_id: conversationId },\n }\n : old,\n );\n };\n\n async function runStream(sessionId: string, params: NotebookSendParams) {\n const {\n prompt,\n seedMessages,\n userName,\n avatar,\n botAvatar,\n selectedModel,\n createMessage,\n } = params;\n\n const entry = ensureEntry(sessionId);\n const signal = entry.abort!.signal;\n const runGeneration = entry.generation;\n entry.pendingToolCalls = {};\n\n const isStale = () => signal.aborted || entry.generation !== runGeneration;\n\n let convId = params.conversationId;\n let requestId = '';\n let newConversationId = '';\n const startedOnTemp = convId === TEMP_CONVERSATION_ID;\n const toolCallsCacheKeyPrefix = startedOnTemp\n ? createTempToolCallsCacheSessionPrefix()\n : convId;\n\n let working: ExtendedMessageProps[] = [\n ...seedMessages,\n createUserMessage({\n avatar,\n name: userName,\n content: prompt,\n timestamp: getTimestamp(Date.now()) ?? '',\n }),\n createBotMessage({\n avatar: botAvatar,\n isLoading: true,\n name: selectedModel,\n content: '',\n timestamp: '',\n }),\n ];\n\n const commit = (status: NotebookStreamStatus = 'streaming') =>\n emit(sessionId, {\n messages: [...working],\n conversationId: convId,\n requestId,\n status,\n });\n\n const updateLast = (\n fn: (msg: ExtendedMessageProps) => ExtendedMessageProps,\n ) => {\n if (working.length === 0) return;\n const lastIndex = working.length - 1;\n working = [...working.slice(0, lastIndex), fn({ ...working[lastIndex] })];\n };\n\n commit('streaming');\n\n const finalMessages: string[] = [];\n let buffer = '';\n\n try {\n const reader = await createMessage(prompt, { signal });\n if (isStale()) return;\n\n const decoder = new TextDecoder('utf-8');\n let streamEnded = false;\n\n while (!streamEnded) {\n if (isStale()) return;\n\n const { value, done } = await reader.read();\n if (isStale()) return;\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const { events: parsedEvents, remainder } = parseSSEBuffer(buffer);\n buffer = remainder;\n\n for (const { event, data } of parsedEvents) {\n if (event === 'start') {\n requestId = data?.request_id;\n if (startedOnTemp) {\n newConversationId = data?.conversation_id;\n if (newConversationId) {\n updateSessionConversationId(sessionId, newConversationId);\n }\n }\n commit('streaming');\n }\n\n if (event === 'tool_call') {\n const toolCall = parseToolCallFromEvent(data);\n\n if (toolCall && data.id !== null) {\n entry.pendingToolCalls[toolCallIdKey(data.id)] = toolCall;\n const lastIndex = working.length - 1;\n const messageIndex = Math.floor(lastIndex / 2);\n updateLast(last => {\n const nextToolCalls = [\n ...normalizeToolCalls(last.toolCalls),\n toolCall,\n ];\n setSharedToolCallsCache(\n `${toolCallsCacheKeyPrefix}-${messageIndex}`,\n nextToolCalls,\n );\n return { ...last, toolCalls: nextToolCalls };\n });\n commit('streaming');\n }\n }\n\n if (event === 'tool_result') {\n const result = parseToolResultFromEvent(\n data,\n entry.pendingToolCalls,\n );\n\n if (result) {\n const lastIndex = working.length - 1;\n const messageIndex = Math.floor(lastIndex / 2);\n updateLast(last => {\n const updatedToolCalls = applyToolResultToToolCalls(\n last.toolCalls || [],\n result,\n );\n setSharedToolCallsCache(\n `${toolCallsCacheKeyPrefix}-${messageIndex}`,\n updatedToolCalls,\n );\n return { ...last, toolCalls: updatedToolCalls };\n });\n delete entry.pendingToolCalls[result.toolIdKey];\n commit('streaming');\n }\n }\n\n if (event === 'token') {\n const content = data?.token || '';\n finalMessages.push(content);\n updateLast(last => {\n const next = { ...last };\n if ((next.content ?? '').trim().length > 0) {\n next.isLoading = false;\n }\n next.content = (next.content ?? '') + content;\n next.name = data?.response_metadata?.model || selectedModel;\n next.timestamp = getTimestamp(\n data?.response_metadata?.created_at || Date.now(),\n );\n return next;\n });\n commit('streaming');\n }\n\n if (event === 'interrupted') {\n if (startedOnTemp && data?.conversation_id) {\n newConversationId = data.conversation_id;\n }\n updateLast(last => ({ ...last, isLoading: false }));\n commit('streaming');\n streamEnded = true;\n break;\n }\n\n if (event === 'end') {\n const documents = data?.referenced_documents || [];\n const sources = transformDocumentsToSources(documents);\n updateLast(last => ({\n ...last,\n isLoading: false,\n ...(sources ? { sources } : {}),\n }));\n commit('streaming');\n }\n }\n if (streamEnded) break;\n }\n } catch (e: any) {\n if (isStale()) return;\n updateLast(last => ({\n ...last,\n isLoading: false,\n content: `${last.content ?? ''}${e}`,\n error: { title: e?.message },\n timestamp: getTimestamp(Date.now()),\n }));\n finalMessages.push(`${e}`);\n emit(sessionId, {\n messages: [...working],\n conversationId: newConversationId || convId,\n requestId,\n status: 'error',\n });\n return;\n }\n\n if (isStale()) return;\n\n // Migrate temp conversation to its real id (tool-call cache + session cache).\n if (startedOnTemp && newConversationId) {\n migrateSharedToolCallsCacheSessionPrefixToConversation(\n toolCallsCacheKeyPrefix,\n newConversationId,\n );\n convId = newConversationId;\n updateSessionConversationId(sessionId, newConversationId);\n } else if (startedOnTemp) {\n clearSharedToolCallsCacheSessionPrefix(toolCallsCacheKeyPrefix);\n }\n\n // Status stays 'complete' (never reverts to 'idle') so the in-memory\n // transcript is preserved across remounts. The view layer merges this with\n // react-query's refetch which fires after invalidation below. If the\n // notebook is later closed/deleted, clear() drops the entry entirely and\n // getSnapshot falls back to IDLE_SNAPSHOT; the next open re-fetches from\n // the server via useConversationMessages.\n commit('complete');\n\n queryClient.invalidateQueries({\n queryKey: ['conversationMessages', convId],\n });\n queryClient.invalidateQueries({ queryKey: ['notebooks', 'sessions'] });\n }\n\n return {\n subscribe(sessionId, listener) {\n const entry = ensureEntry(sessionId);\n entry.listeners.add(listener);\n return () => {\n entry.listeners.delete(listener);\n };\n },\n\n getSnapshot(sessionId) {\n return entries.get(sessionId)?.snapshot ?? IDLE_SNAPSHOT;\n },\n\n send(sessionId, params) {\n if (!normalizeChatUserInput(params.prompt)) return;\n const entry = ensureEntry(sessionId);\n entry.abort?.abort();\n entry.abort = new AbortController();\n entry.generation++;\n void runStream(sessionId, params);\n },\n\n stop(sessionId) {\n const entry = entries.get(sessionId);\n if (!entry) return;\n entry.abort?.abort();\n const messages = entry.snapshot.messages;\n const lastIndex = messages.length - 1;\n const nextMessages =\n lastIndex >= 0\n ? [\n ...messages.slice(0, lastIndex),\n { ...messages[lastIndex], isLoading: false },\n ]\n : messages;\n emit(sessionId, {\n messages: nextMessages,\n requestId: '',\n status: 'stopped',\n });\n },\n\n clear(sessionId) {\n const entry = entries.get(sessionId);\n if (!entry) return;\n entry.abort?.abort();\n entries.delete(sessionId);\n },\n\n clearAll() {\n entries.forEach(entry => entry.abort?.abort());\n entries.clear();\n },\n };\n}\n"],"names":[],"mappings":"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"}
package/dist/const.esm.js CHANGED
@@ -1,3 +1,11 @@
1
+ var ChatbotDisplayMode = /* @__PURE__ */ ((ChatbotDisplayMode2) => {
2
+ ChatbotDisplayMode2["default"] = "default";
3
+ ChatbotDisplayMode2["embedded"] = "embedded";
4
+ ChatbotDisplayMode2["docked"] = "docked";
5
+ ChatbotDisplayMode2["fullscreen"] = "fullscreen";
6
+ ChatbotDisplayMode2["drawer"] = "drawer";
7
+ return ChatbotDisplayMode2;
8
+ })(ChatbotDisplayMode || {});
1
9
  const TEMP_CONVERSATION_ID = "temp-conversation-id";
2
10
  const LIGHTSPEED_APP_DRAWER_ID = "intelligent-assistant";
3
11
  const createPrompt = (titleKey, messageKey) => {
@@ -84,5 +92,5 @@ const LIGHTSPEED_OVERLAY_MAX_WIDTH = `min(30rem, calc(100vw - 2 * var(${LIGHTSPE
84
92
  const LIGHTSPEED_PATH = "/intelligent-assistant";
85
93
  const LIGHTSPEED_LEGACY_PATH = "/lightspeed";
86
94
 
87
- export { DEFAULT_SAMPLE_PROMPTS, DOCKED_CONTENT_OFFSET, LIGHTSPEED_APP_DRAWER_ID, LIGHTSPEED_FAB_ANCHOR_VARS, LIGHTSPEED_FAB_ELEMENT_ID, LIGHTSPEED_LEGACY_PATH, LIGHTSPEED_OVERLAY_BOTTOM, LIGHTSPEED_OVERLAY_CHATBOT_MODAL_CLASS, LIGHTSPEED_OVERLAY_MAX_WIDTH, LIGHTSPEED_OVERLAY_RIGHT, LIGHTSPEED_PATH, NOTEBOOK_ALLOWED_EXTENSIONS, NOTEBOOK_EXTENSION_TO_FILE_TYPE, NOTEBOOK_MAX_FILES, NOTEBOOK_MAX_FILE_SIZE_BYTES, NOTEBOOK_MAX_TITLE_LENGTH, NOTEBOOK_PROMPT_KEYS, RHDH_SAMPLE_PROMPTS, TEMP_CONVERSATION_ID, UNTITLED_NOTEBOOK_NAME, VALID_TOPIC_RESTRICTION_PROVIDER_IDS, supportedFileTypes };
95
+ export { ChatbotDisplayMode, DEFAULT_SAMPLE_PROMPTS, DOCKED_CONTENT_OFFSET, LIGHTSPEED_APP_DRAWER_ID, LIGHTSPEED_FAB_ANCHOR_VARS, LIGHTSPEED_FAB_ELEMENT_ID, LIGHTSPEED_LEGACY_PATH, LIGHTSPEED_OVERLAY_BOTTOM, LIGHTSPEED_OVERLAY_CHATBOT_MODAL_CLASS, LIGHTSPEED_OVERLAY_MAX_WIDTH, LIGHTSPEED_OVERLAY_RIGHT, LIGHTSPEED_PATH, NOTEBOOK_ALLOWED_EXTENSIONS, NOTEBOOK_EXTENSION_TO_FILE_TYPE, NOTEBOOK_MAX_FILES, NOTEBOOK_MAX_FILE_SIZE_BYTES, NOTEBOOK_MAX_TITLE_LENGTH, NOTEBOOK_PROMPT_KEYS, RHDH_SAMPLE_PROMPTS, TEMP_CONVERSATION_ID, UNTITLED_NOTEBOOK_NAME, VALID_TOPIC_RESTRICTION_PROVIDER_IDS, supportedFileTypes };
88
96
  //# sourceMappingURL=const.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"const.esm.js","sources":["../src/const.ts"],"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 { SamplePrompts } from './types';\n\nexport const TEMP_CONVERSATION_ID = 'temp-conversation-id';\n\nexport const LIGHTSPEED_APP_DRAWER_ID = 'intelligent-assistant';\n\n// Translation keys for disclaimers\nexport const FUNCTION_DISCLAIMER_WITHOUT_QUESTION_VALIDATION_KEY =\n 'disclaimer.withoutValidation';\nexport const FUNCTION_DISCLAIMER_KEY = 'disclaimer';\n\nconst createPrompt = (titleKey: string, messageKey: string) => {\n return { titleKey, messageKey };\n};\n\nexport const supportedFileTypes = {\n 'text/plain': ['.txt'],\n 'application/json': ['.json'],\n 'application/yaml': ['.yaml', '.yml'],\n};\n\nexport const NOTEBOOK_MAX_FILES = 10;\nexport const NOTEBOOK_MAX_FILE_SIZE_BYTES = 25 * 1024 * 1024; // 25 MB\nexport const NOTEBOOK_MAX_TITLE_LENGTH = 255;\nexport const UNTITLED_NOTEBOOK_NAME = 'Untitled Notebook';\n\nexport const NOTEBOOK_ALLOWED_EXTENSIONS: Record<string, string[]> = {\n 'text/plain': ['.txt', '.log'],\n 'text/markdown': ['.md'],\n 'application/pdf': ['.pdf'],\n 'application/json': ['.json'],\n 'application/x-yaml': ['.yaml', '.yml'],\n};\n\nexport const NOTEBOOK_EXTENSION_TO_FILE_TYPE: Record<string, string> = {\n '.txt': 'txt',\n '.md': 'md',\n '.pdf': 'pdf',\n '.json': 'json',\n '.yaml': 'yaml',\n '.yml': 'yaml',\n '.log': 'log',\n};\n\nexport const DEFAULT_SAMPLE_PROMPTS: SamplePrompts = [\n createPrompt(\n 'prompts.codeReadability.title',\n 'prompts.codeReadability.message',\n ),\n createPrompt('prompts.debugging.title', 'prompts.debugging.message'),\n createPrompt(\n 'prompts.developmentConcept.title',\n 'prompts.developmentConcept.message',\n ),\n createPrompt(\n 'prompts.codeOptimization.title',\n 'prompts.codeOptimization.message',\n ),\n createPrompt('prompts.documentation.title', 'prompts.documentation.message'),\n createPrompt('prompts.gitWorkflows.title', 'prompts.gitWorkflows.message'),\n createPrompt(\n 'prompts.testingStrategies.title',\n 'prompts.testingStrategies.message',\n ),\n createPrompt(\n 'prompts.sortingAlgorithms.title',\n 'prompts.sortingAlgorithms.message',\n ),\n createPrompt('prompts.eventDriven.title', 'prompts.eventDriven.message'),\n];\n\nexport const RHDH_SAMPLE_PROMPTS: SamplePrompts = [\n createPrompt('prompts.tekton.title', 'prompts.tekton.message'),\n createPrompt('prompts.openshift.title', 'prompts.openshift.message'),\n createPrompt('prompts.rhdh.title', 'prompts.rhdh.message'),\n];\n\nexport const NOTEBOOK_PROMPT_KEYS: string[] = [\n 'notebooks.prompts.coreConcepts.title',\n 'notebooks.prompts.vulnerabilities.title',\n 'notebooks.prompts.accessIssue.title',\n];\n\n// Topic restriction valid provider IDs\nexport const VALID_TOPIC_RESTRICTION_PROVIDER_IDS = [\n 'lightspeed_question_validity-shield',\n];\n\nexport const LIGHTSPEED_FAB_ELEMENT_ID = 'lightspeed-fab';\nexport const LIGHTSPEED_OVERLAY_CHATBOT_MODAL_CLASS =\n 'ia-overlay-chatbot-modal';\n\n/** CSS variables published by LightspeedFABContent — single source for overlay layout. */\nexport const LIGHTSPEED_FAB_ANCHOR_VARS = {\n insetBlockEnd: '--ia-fab-inset-block-end',\n insetInlineEnd: '--ia-fab-inset-inline-end',\n height: '--ia-fab-height',\n overlayGap: '--ia-overlay-gap',\n dockedDrawerGutter: '--ia-docked-drawer-gutter',\n} as const;\n\nconst zero = '0px';\n\n/** Shift FAB/overlay left when the app drawer is docked (drawer width + theme gutter). */\nexport const DOCKED_CONTENT_OFFSET = `calc(var(--docked-drawer-width, ${zero}) + var(${LIGHTSPEED_FAB_ANCHOR_VARS.dockedDrawerGutter}, ${zero}))`;\n\n/** Overlay bottom: measured FAB bottom inset + FAB height + theme gap. */\nexport const LIGHTSPEED_OVERLAY_BOTTOM = `calc(var(${LIGHTSPEED_FAB_ANCHOR_VARS.insetBlockEnd}, ${zero}) + var(${LIGHTSPEED_FAB_ANCHOR_VARS.height}, ${zero}) + var(${LIGHTSPEED_FAB_ANCHOR_VARS.overlayGap}, ${zero}))`;\n\n/** Overlay right: measured FAB right inset (tracks docked margin via getBoundingClientRect). */\nexport const LIGHTSPEED_OVERLAY_RIGHT = `var(${LIGHTSPEED_FAB_ANCHOR_VARS.insetInlineEnd}, ${zero})`;\n\n/** Overlay max width: PatternFly default capped by viewport minus theme gutters. */\nexport const LIGHTSPEED_OVERLAY_MAX_WIDTH = `min(30rem, calc(100vw - 2 * var(${LIGHTSPEED_FAB_ANCHOR_VARS.overlayGap}, ${zero})))`;\n\nexport const LIGHTSPEED_PATH = '/intelligent-assistant';\nexport const LIGHTSPEED_LEGACY_PATH = '/lightspeed';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"const.esm.js","sources":["../src/const.ts"],"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 { SamplePrompts } from './types';\n\n/**\n * Local mirror of PatternFly ChatbotDisplayMode string values.\n * Keeps the always-loaded FAB / drawer-provider graph free of\n * `@patternfly/chatbot` for these constants alone.\n */\nexport enum ChatbotDisplayMode {\n default = 'default',\n embedded = 'embedded',\n docked = 'docked',\n fullscreen = 'fullscreen',\n drawer = 'drawer',\n}\n\nexport const TEMP_CONVERSATION_ID = 'temp-conversation-id';\n\nexport const LIGHTSPEED_APP_DRAWER_ID = 'intelligent-assistant';\n\n// Translation keys for disclaimers\nexport const FUNCTION_DISCLAIMER_WITHOUT_QUESTION_VALIDATION_KEY =\n 'disclaimer.withoutValidation';\nexport const FUNCTION_DISCLAIMER_KEY = 'disclaimer';\n\nconst createPrompt = (titleKey: string, messageKey: string) => {\n return { titleKey, messageKey };\n};\n\nexport const supportedFileTypes = {\n 'text/plain': ['.txt'],\n 'application/json': ['.json'],\n 'application/yaml': ['.yaml', '.yml'],\n};\n\nexport const NOTEBOOK_MAX_FILES = 10;\nexport const NOTEBOOK_MAX_FILE_SIZE_BYTES = 25 * 1024 * 1024; // 25 MB\nexport const NOTEBOOK_MAX_TITLE_LENGTH = 255;\nexport const UNTITLED_NOTEBOOK_NAME = 'Untitled Notebook';\n\nexport const NOTEBOOK_ALLOWED_EXTENSIONS: Record<string, string[]> = {\n 'text/plain': ['.txt', '.log'],\n 'text/markdown': ['.md'],\n 'application/pdf': ['.pdf'],\n 'application/json': ['.json'],\n 'application/x-yaml': ['.yaml', '.yml'],\n};\n\nexport const NOTEBOOK_EXTENSION_TO_FILE_TYPE: Record<string, string> = {\n '.txt': 'txt',\n '.md': 'md',\n '.pdf': 'pdf',\n '.json': 'json',\n '.yaml': 'yaml',\n '.yml': 'yaml',\n '.log': 'log',\n};\n\nexport const DEFAULT_SAMPLE_PROMPTS: SamplePrompts = [\n createPrompt(\n 'prompts.codeReadability.title',\n 'prompts.codeReadability.message',\n ),\n createPrompt('prompts.debugging.title', 'prompts.debugging.message'),\n createPrompt(\n 'prompts.developmentConcept.title',\n 'prompts.developmentConcept.message',\n ),\n createPrompt(\n 'prompts.codeOptimization.title',\n 'prompts.codeOptimization.message',\n ),\n createPrompt('prompts.documentation.title', 'prompts.documentation.message'),\n createPrompt('prompts.gitWorkflows.title', 'prompts.gitWorkflows.message'),\n createPrompt(\n 'prompts.testingStrategies.title',\n 'prompts.testingStrategies.message',\n ),\n createPrompt(\n 'prompts.sortingAlgorithms.title',\n 'prompts.sortingAlgorithms.message',\n ),\n createPrompt('prompts.eventDriven.title', 'prompts.eventDriven.message'),\n];\n\nexport const RHDH_SAMPLE_PROMPTS: SamplePrompts = [\n createPrompt('prompts.tekton.title', 'prompts.tekton.message'),\n createPrompt('prompts.openshift.title', 'prompts.openshift.message'),\n createPrompt('prompts.rhdh.title', 'prompts.rhdh.message'),\n];\n\nexport const NOTEBOOK_PROMPT_KEYS: string[] = [\n 'notebooks.prompts.coreConcepts.title',\n 'notebooks.prompts.vulnerabilities.title',\n 'notebooks.prompts.accessIssue.title',\n];\n\n// Topic restriction valid provider IDs\nexport const VALID_TOPIC_RESTRICTION_PROVIDER_IDS = [\n 'lightspeed_question_validity-shield',\n];\n\nexport const LIGHTSPEED_FAB_ELEMENT_ID = 'lightspeed-fab';\nexport const LIGHTSPEED_OVERLAY_CHATBOT_MODAL_CLASS =\n 'ia-overlay-chatbot-modal';\n\n/** CSS variables published by LightspeedFABContent — single source for overlay layout. */\nexport const LIGHTSPEED_FAB_ANCHOR_VARS = {\n insetBlockEnd: '--ia-fab-inset-block-end',\n insetInlineEnd: '--ia-fab-inset-inline-end',\n height: '--ia-fab-height',\n overlayGap: '--ia-overlay-gap',\n dockedDrawerGutter: '--ia-docked-drawer-gutter',\n} as const;\n\nconst zero = '0px';\n\n/** Shift FAB/overlay left when the app drawer is docked (drawer width + theme gutter). */\nexport const DOCKED_CONTENT_OFFSET = `calc(var(--docked-drawer-width, ${zero}) + var(${LIGHTSPEED_FAB_ANCHOR_VARS.dockedDrawerGutter}, ${zero}))`;\n\n/** Overlay bottom: measured FAB bottom inset + FAB height + theme gap. */\nexport const LIGHTSPEED_OVERLAY_BOTTOM = `calc(var(${LIGHTSPEED_FAB_ANCHOR_VARS.insetBlockEnd}, ${zero}) + var(${LIGHTSPEED_FAB_ANCHOR_VARS.height}, ${zero}) + var(${LIGHTSPEED_FAB_ANCHOR_VARS.overlayGap}, ${zero}))`;\n\n/** Overlay right: measured FAB right inset (tracks docked margin via getBoundingClientRect). */\nexport const LIGHTSPEED_OVERLAY_RIGHT = `var(${LIGHTSPEED_FAB_ANCHOR_VARS.insetInlineEnd}, ${zero})`;\n\n/** Overlay max width: PatternFly default capped by viewport minus theme gutters. */\nexport const LIGHTSPEED_OVERLAY_MAX_WIDTH = `min(30rem, calc(100vw - 2 * var(${LIGHTSPEED_FAB_ANCHOR_VARS.overlayGap}, ${zero})))`;\n\nexport const LIGHTSPEED_PATH = '/intelligent-assistant';\nexport const LIGHTSPEED_LEGACY_PATH = '/lightspeed';\n"],"names":["ChatbotDisplayMode"],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import { jsx, Fragment } from 'react/jsx-runtime';
2
+ import { useEffect, useLayoutEffect } from 'react';
3
+ import { useLocation, useNavigate } from 'react-router-dom';
4
+ import { createFrontendModule } from '@backstage/frontend-plugin-api';
5
+ import { AppRootWrapperBlueprint } from '@backstage/plugin-app-react';
6
+ import './muiClassNameConfig.esm.js';
7
+ import { LIGHTSPEED_LEGACY_PATH, LIGHTSPEED_PATH } from './const.esm.js';
8
+ import { LazyLightspeedFabRootWrapper } from './lazy/LazyLightspeedFabRootWrapper.esm.js';
9
+
10
+ const LightspeedLegacyRedirect = ({ children }) => {
11
+ const location = useLocation();
12
+ const navigate = useNavigate();
13
+ useEffect(() => {
14
+ if (location.pathname.startsWith(LIGHTSPEED_LEGACY_PATH)) {
15
+ const newPath = location.pathname.replace(
16
+ LIGHTSPEED_LEGACY_PATH,
17
+ LIGHTSPEED_PATH
18
+ );
19
+ navigate(newPath + location.search + location.hash, {
20
+ replace: true
21
+ });
22
+ }
23
+ }, [location, navigate]);
24
+ useLayoutEffect(() => {
25
+ document.documentElement.style.containerType = "normal";
26
+ }, []);
27
+ return /* @__PURE__ */ jsx(Fragment, { children });
28
+ };
29
+ const intelligentAssistantRedirect = AppRootWrapperBlueprint.make({
30
+ name: "intelligent-assistant-redirect",
31
+ params: {
32
+ component: LightspeedLegacyRedirect
33
+ }
34
+ });
35
+ const intelligentAssistantRedirectModule = createFrontendModule({
36
+ pluginId: "app",
37
+ extensions: [intelligentAssistantRedirect]
38
+ });
39
+ const intelligentAssistantFABExtension = AppRootWrapperBlueprint.make({
40
+ name: "intelligent-assistant-fab",
41
+ params: {
42
+ component: LazyLightspeedFabRootWrapper
43
+ }
44
+ });
45
+ const intelligentAssistantFABModule = createFrontendModule({
46
+ pluginId: "app",
47
+ extensions: [intelligentAssistantFABExtension, intelligentAssistantRedirect]
48
+ });
49
+
50
+ export { intelligentAssistantFABModule, intelligentAssistantRedirectModule };
51
+ //# sourceMappingURL=fabModule.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fabModule.esm.js","sources":["../src/fabModule.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, useLayoutEffect, type ReactNode } from 'react';\nimport { useLocation, useNavigate } from 'react-router-dom';\n\nimport { createFrontendModule } from '@backstage/frontend-plugin-api';\nimport { AppRootWrapperBlueprint } from '@backstage/plugin-app-react';\n\nimport './muiClassNameConfig';\n\nimport { LIGHTSPEED_LEGACY_PATH, LIGHTSPEED_PATH } from './const';\nimport { LazyLightspeedFabRootWrapper } from './lazy/LazyLightspeedFabRootWrapper';\n\nconst LightspeedLegacyRedirect = ({ children }: { children: ReactNode }) => {\n const location = useLocation();\n const navigate = useNavigate();\n useEffect(() => {\n if (location.pathname.startsWith(LIGHTSPEED_LEGACY_PATH)) {\n const newPath = location.pathname.replace(\n LIGHTSPEED_LEGACY_PATH,\n LIGHTSPEED_PATH,\n );\n navigate(newPath + location.search + location.hash, {\n replace: true,\n });\n }\n }, [location, navigate]);\n\n // Workaround: PF 6.6.0 base-no-reset.css sets container-type: inline-size on :root,\n // breaking body height. Remove after https://github.com/patternfly/patternfly-react/issues/12568\n useLayoutEffect(() => {\n document.documentElement.style.containerType = 'normal';\n }, []);\n\n return <>{children}</>;\n};\n\nconst intelligentAssistantRedirect = AppRootWrapperBlueprint.make({\n name: 'intelligent-assistant-redirect',\n params: {\n component: LightspeedLegacyRedirect,\n },\n});\n\n/**\n * @public\n */\nexport const intelligentAssistantRedirectModule = createFrontendModule({\n pluginId: 'app',\n extensions: [intelligentAssistantRedirect],\n});\n\nconst intelligentAssistantFABExtension = AppRootWrapperBlueprint.make({\n name: 'intelligent-assistant-fab',\n params: {\n component: LazyLightspeedFabRootWrapper,\n },\n});\n\n/**\n * @public\n */\nexport const intelligentAssistantFABModule = createFrontendModule({\n pluginId: 'app',\n extensions: [intelligentAssistantFABExtension, intelligentAssistantRedirect],\n});\n"],"names":[],"mappings":";;;;;;;;;AA2BA,MAAM,wBAAA,GAA2B,CAAC,EAAE,QAAA,EAAS,KAA+B;AAC1E,EAAA,MAAM,WAAW,WAAA,EAAY;AAC7B,EAAA,MAAM,WAAW,WAAA,EAAY;AAC7B,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,QAAA,CAAS,QAAA,CAAS,UAAA,CAAW,sBAAsB,CAAA,EAAG;AACxD,MAAA,MAAM,OAAA,GAAU,SAAS,QAAA,CAAS,OAAA;AAAA,QAChC,sBAAA;AAAA,QACA;AAAA,OACF;AACA,MAAA,QAAA,CAAS,OAAA,GAAU,QAAA,CAAS,MAAA,GAAS,QAAA,CAAS,IAAA,EAAM;AAAA,QAClD,OAAA,EAAS;AAAA,OACV,CAAA;AAAA,IACH;AAAA,EACF,CAAA,EAAG,CAAC,QAAA,EAAU,QAAQ,CAAC,CAAA;AAIvB,EAAA,eAAA,CAAgB,MAAM;AACpB,IAAA,QAAA,CAAS,eAAA,CAAgB,MAAM,aAAA,GAAgB,QAAA;AAAA,EACjD,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,uCAAU,QAAA,EAAS,CAAA;AACrB,CAAA;AAEA,MAAM,4BAAA,GAA+B,wBAAwB,IAAA,CAAK;AAAA,EAChE,IAAA,EAAM,gCAAA;AAAA,EACN,MAAA,EAAQ;AAAA,IACN,SAAA,EAAW;AAAA;AAEf,CAAC,CAAA;AAKM,MAAM,qCAAqC,oBAAA,CAAqB;AAAA,EACrE,QAAA,EAAU,KAAA;AAAA,EACV,UAAA,EAAY,CAAC,4BAA4B;AAC3C,CAAC;AAED,MAAM,gCAAA,GAAmC,wBAAwB,IAAA,CAAK;AAAA,EACpE,IAAA,EAAM,2BAAA;AAAA,EACN,MAAA,EAAQ;AAAA,IACN,SAAA,EAAW;AAAA;AAEf,CAAC,CAAA;AAKM,MAAM,gCAAgC,oBAAA,CAAqB;AAAA,EAChE,QAAA,EAAU,KAAA;AAAA,EACV,UAAA,EAAY,CAAC,gCAAA,EAAkC,4BAA4B;AAC7E,CAAC;;;;"}
@@ -0,0 +1,113 @@
1
+ import { PAGE_CHROME_ROOT_SELECTORS } from '../utils/dom-selectors.esm.js';
2
+ import { resolveScreenContextChipLabel } from '../utils/screen-context-utils.esm.js';
3
+
4
+ const listeners = /* @__PURE__ */ new Set();
5
+ let historyPatched = false;
6
+ let pageChromeObserver;
7
+ let notifyScheduled = false;
8
+ function notifyScreenContextLabelListeners() {
9
+ listeners.forEach((listener) => listener());
10
+ }
11
+ function scheduleNotifyScreenContextLabelListeners() {
12
+ if (notifyScheduled || typeof window === "undefined") {
13
+ return;
14
+ }
15
+ notifyScheduled = true;
16
+ window.requestAnimationFrame(() => {
17
+ notifyScheduled = false;
18
+ notifyScreenContextLabelListeners();
19
+ });
20
+ }
21
+ function isInsideScreenCaptureExclude(node) {
22
+ const el = node instanceof Element ? node : node.parentElement;
23
+ return Boolean(el?.closest("[data-screen-capture-exclude]"));
24
+ }
25
+ function shouldReactToMutation(mutations) {
26
+ for (const mutation of mutations) {
27
+ if (mutation.target instanceof Node && isInsideScreenCaptureExclude(mutation.target)) {
28
+ continue;
29
+ }
30
+ return true;
31
+ }
32
+ return false;
33
+ }
34
+ const observedChromeNodes = /* @__PURE__ */ new WeakSet();
35
+ function collectPageChromeObserveTargets() {
36
+ const observeTargets = [];
37
+ const titleEl = document.querySelector("title");
38
+ if (titleEl) {
39
+ observeTargets.push(titleEl);
40
+ }
41
+ for (const selector of PAGE_CHROME_ROOT_SELECTORS) {
42
+ const node = document.querySelector(selector);
43
+ if (node && !observeTargets.includes(node)) {
44
+ observeTargets.push(node);
45
+ }
46
+ }
47
+ if (observeTargets.length === 0 && document.body) {
48
+ observeTargets.push(document.body);
49
+ }
50
+ return observeTargets;
51
+ }
52
+ function ensurePageChromeObserver() {
53
+ if (typeof window === "undefined") {
54
+ return;
55
+ }
56
+ if (!pageChromeObserver) {
57
+ pageChromeObserver = new MutationObserver((mutations) => {
58
+ if (shouldReactToMutation(mutations)) {
59
+ scheduleNotifyScreenContextLabelListeners();
60
+ }
61
+ });
62
+ }
63
+ for (const target of collectPageChromeObserveTargets()) {
64
+ if (observedChromeNodes.has(target)) {
65
+ continue;
66
+ }
67
+ observedChromeNodes.add(target);
68
+ pageChromeObserver.observe(target, {
69
+ subtree: true,
70
+ childList: true,
71
+ characterData: true
72
+ });
73
+ }
74
+ }
75
+ function patchBrowserHistoryForScreenContext() {
76
+ if (historyPatched || typeof window === "undefined") {
77
+ return;
78
+ }
79
+ historyPatched = true;
80
+ window.addEventListener("popstate", notifyScreenContextLabelListeners);
81
+ window.addEventListener("hashchange", notifyScreenContextLabelListeners);
82
+ const { pushState, replaceState } = window.history;
83
+ window.history.pushState = function pushStatePatched(...args) {
84
+ pushState.apply(this, args);
85
+ notifyScreenContextLabelListeners();
86
+ };
87
+ window.history.replaceState = function replaceStatePatched(...args) {
88
+ replaceState.apply(this, args);
89
+ notifyScreenContextLabelListeners();
90
+ };
91
+ }
92
+ let cachedSnapshot = "";
93
+ function getScreenContextLabelSnapshot() {
94
+ const pathname = window.location.pathname;
95
+ const search = window.location.search;
96
+ const { label } = resolveScreenContextChipLabel({ pathname, search });
97
+ const next = `${pathname}\0${search}\0${label}`;
98
+ if (next !== cachedSnapshot) {
99
+ cachedSnapshot = next;
100
+ }
101
+ return cachedSnapshot;
102
+ }
103
+ function subscribeToScreenContextLabel(onStoreChange) {
104
+ patchBrowserHistoryForScreenContext();
105
+ ensurePageChromeObserver();
106
+ listeners.add(onStoreChange);
107
+ return () => {
108
+ listeners.delete(onStoreChange);
109
+ };
110
+ }
111
+
112
+ export { getScreenContextLabelSnapshot, isInsideScreenCaptureExclude, patchBrowserHistoryForScreenContext, subscribeToScreenContextLabel };
113
+ //# sourceMappingURL=screenContextLabelSubscription.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screenContextLabelSubscription.esm.js","sources":["../../src/hooks/screenContextLabelSubscription.ts"],"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 { PAGE_CHROME_ROOT_SELECTORS } from '../utils/dom-selectors';\nimport { resolveScreenContextChipLabel } from '../utils/screen-context-utils';\n\nconst listeners = new Set<() => void>();\nlet historyPatched = false;\nlet pageChromeObserver: MutationObserver | undefined;\nlet notifyScheduled = false;\n\nfunction notifyScreenContextLabelListeners() {\n listeners.forEach(listener => listener());\n}\n\nfunction scheduleNotifyScreenContextLabelListeners() {\n if (notifyScheduled || typeof window === 'undefined') {\n return;\n }\n notifyScheduled = true;\n window.requestAnimationFrame(() => {\n notifyScheduled = false;\n notifyScreenContextLabelListeners();\n });\n}\n\n/** @internal Exported for unit tests. */\nexport function isInsideScreenCaptureExclude(node: Node): boolean {\n const el = node instanceof Element ? node : node.parentElement;\n return Boolean(el?.closest('[data-screen-capture-exclude]'));\n}\n\nfunction shouldReactToMutation(mutations: MutationRecord[]): boolean {\n for (const mutation of mutations) {\n if (\n mutation.target instanceof Node &&\n isInsideScreenCaptureExclude(mutation.target)\n ) {\n continue;\n }\n return true;\n }\n return false;\n}\n\nconst observedChromeNodes = new WeakSet<Node>();\n\nfunction collectPageChromeObserveTargets(): Node[] {\n const observeTargets: Node[] = [];\n const titleEl = document.querySelector('title');\n if (titleEl) {\n observeTargets.push(titleEl);\n }\n for (const selector of PAGE_CHROME_ROOT_SELECTORS) {\n const node = document.querySelector(selector);\n if (node && !observeTargets.includes(node)) {\n observeTargets.push(node);\n }\n }\n if (observeTargets.length === 0 && document.body) {\n observeTargets.push(document.body);\n }\n return observeTargets;\n}\n\nfunction ensurePageChromeObserver() {\n if (typeof window === 'undefined') {\n return;\n }\n\n if (!pageChromeObserver) {\n pageChromeObserver = new MutationObserver(mutations => {\n if (shouldReactToMutation(mutations)) {\n scheduleNotifyScreenContextLabelListeners();\n }\n });\n }\n\n for (const target of collectPageChromeObserveTargets()) {\n if (observedChromeNodes.has(target)) {\n continue;\n }\n observedChromeNodes.add(target);\n pageChromeObserver.observe(target, {\n subtree: true,\n childList: true,\n characterData: true,\n });\n }\n}\n\n/**\n * Patch browser history so SPA pushState/replaceState notify label listeners.\n * Idempotent; called on first subscribe rather than at module load.\n */\nexport function patchBrowserHistoryForScreenContext() {\n if (historyPatched || typeof window === 'undefined') {\n return;\n }\n historyPatched = true;\n\n window.addEventListener('popstate', notifyScreenContextLabelListeners);\n window.addEventListener('hashchange', notifyScreenContextLabelListeners);\n\n const { pushState, replaceState } = window.history;\n window.history.pushState = function pushStatePatched(...args) {\n pushState.apply(this, args);\n notifyScreenContextLabelListeners();\n };\n window.history.replaceState = function replaceStatePatched(...args) {\n replaceState.apply(this, args);\n notifyScreenContextLabelListeners();\n };\n}\n\nlet cachedSnapshot = '';\n\nexport function getScreenContextLabelSnapshot(): string {\n const pathname = window.location.pathname;\n const search = window.location.search;\n const { label } = resolveScreenContextChipLabel({ pathname, search });\n const next = `${pathname}\\0${search}\\0${label}`;\n if (next !== cachedSnapshot) {\n cachedSnapshot = next;\n }\n return cachedSnapshot;\n}\n\nexport function subscribeToScreenContextLabel(\n onStoreChange: () => void,\n): () => void {\n patchBrowserHistoryForScreenContext();\n ensurePageChromeObserver();\n listeners.add(onStoreChange);\n return () => {\n listeners.delete(onStoreChange);\n };\n}\n\n/** @internal For unit tests only. */\nexport function resetScreenContextLabelSnapshotCache(): void {\n cachedSnapshot = '';\n}\n"],"names":[],"mappings":"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"}
@@ -7,10 +7,11 @@ import { TEMP_CONVERSATION_ID } from '../const.esm.js';
7
7
  import botAvatarDark from '../images/bot-avatar-dark.svg';
8
8
  import botAvatarLight from '../images/bot-avatar.svg';
9
9
  import userAvatar from '../images/user-avatar.svg';
10
- import { getConversationsData, createUserMessage, createBotMessage, transformDocumentsToSources, normalizeChatUserInput, getTimestamp } from '../utils/lightspeed-chatbox-utils.esm.js';
10
+ import { transformDocumentsToSources } from '../utils/lightspeed-chatbox-utils.esm.js';
11
11
  import { createTempToolCallsCacheSessionPrefix, parseSSEBuffer, parseToolCallFromEvent, toolCallIdKey, normalizeToolCalls, parseToolResultFromEvent, applyToolResultToToolCalls } from '../utils/stream-event-helpers.esm.js';
12
12
  import { getSharedToolCallsCache, setSharedToolCallsCache, migrateSharedToolCallsCacheSessionPrefixToConversation, clearSharedToolCallsCacheSessionPrefix } from './toolCallsCacheStore.esm.js';
13
13
  import { useCreateConversationMessage } from './useCreateCoversationMessage.esm.js';
14
+ import { getConversationsData, createUserMessage, createBotMessage, normalizeChatUserInput, getTimestamp } from '../utils/lightspeed-chatbox-message-utils.esm.js';
14
15
 
15
16
  const useFetchConversationMessages = (currentConversation) => {
16
17
  const lightspeedApi = useApi(lightspeedApiRef);
@@ -1 +1 @@
1
- {"version":3,"file":"useConversationMessages.esm.js","sources":["../../src/hooks/useConversationMessages.ts"],"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 { RefObject, useCallback, useEffect, useRef, useState } from 'react';\n\nimport { useApi } from '@backstage/core-plugin-api';\n\nimport { useTheme } from '@mui/material/styles';\nimport { MessageProps } from '@patternfly/chatbot';\nimport { useQuery, type UseQueryResult } from '@tanstack/react-query';\n\nimport { lightspeedApiRef } from '../api/api';\nimport { ScrollContainerHandle } from '../components/LightspeedChatBox';\nimport { TEMP_CONVERSATION_ID } from '../const';\nimport botAvatarDark from '../images/bot-avatar-dark.svg';\nimport botAvatarLight from '../images/bot-avatar.svg';\nimport userAvatar from '../images/user-avatar.svg';\nimport { Attachment, BaseMessage, LCSConversation, ToolCall } from '../types';\nimport {\n createBotMessage,\n createUserMessage,\n getConversationsData,\n getTimestamp,\n normalizeChatUserInput,\n transformDocumentsToSources,\n} from '../utils/lightspeed-chatbox-utils';\nimport {\n applyToolResultToToolCalls,\n createTempToolCallsCacheSessionPrefix,\n normalizeToolCalls,\n parseSSEBuffer,\n parseToolCallFromEvent,\n parseToolResultFromEvent,\n toolCallIdKey,\n} from '../utils/stream-event-helpers';\nimport {\n clearSharedToolCallsCacheSessionPrefix,\n getSharedToolCallsCache,\n migrateSharedToolCallsCacheSessionPrefixToConversation,\n setSharedToolCallsCache,\n} from './toolCallsCacheStore';\nimport {\n CreateMessageVariables,\n useCreateConversationMessage,\n} from './useCreateCoversationMessage';\n\n// Fetch all conversation messages\nexport const useFetchConversationMessages = (\n currentConversation: string,\n): UseQueryResult<BaseMessage[] | undefined, Error> => {\n const lightspeedApi = useApi(lightspeedApiRef);\n return useQuery({\n queryKey: ['conversationMessages', currentConversation],\n queryFn: currentConversation\n ? async () => {\n const response =\n await lightspeedApi.getConversationMessages(currentConversation);\n\n return response;\n }\n : undefined,\n retry: false,\n });\n};\n\n// Extended message type to include tool calls\ninterface ExtendedMessageProps extends MessageProps {\n toolCalls?: ToolCall[];\n}\n\ntype Conversations = { [_key: string]: ExtendedMessageProps[] };\n\nexport type UseConversationMessagesReturn = {\n conversationMessages: ExtendedMessageProps[];\n handleInputPrompt: (\n prompt: string,\n attachments?: Attachment[],\n ) => Promise<void>;\n conversations: Conversations;\n scrollToBottomRef: RefObject<ScrollContainerHandle | null>;\n streamingConversationId: string | null;\n data?: BaseMessage[] | undefined;\n error: Error | null;\n isPending: boolean;\n isFetching: boolean;\n isSuccess: boolean;\n isError: boolean;\n status: 'pending' | 'error' | 'success';\n refetch: () => void;\n};\n\n/**\n * Fetches all the messages for given conversation_id\n * @param conversationId\n * @param userName\n * @param selectedModel\n * @param selectedProvider\n * @param avatar\n *\n */\nexport const useConversationMessages = (\n conversationId: string,\n userName: string | undefined,\n selectedModel: string,\n selectedProvider: string,\n avatar: string = userAvatar,\n onComplete?: (message: string) => void,\n onStart?: (conversation_id: string) => void,\n createMessageOverride?: (\n vars: CreateMessageVariables,\n ) => Promise<ReadableStreamDefaultReader<Uint8Array>>,\n onRequestIdReady?: (request_id: string, conversation_id?: string) => void,\n): UseConversationMessagesReturn => {\n const theme = useTheme();\n const botAvatar =\n theme.palette.mode === 'dark' ? botAvatarDark : botAvatarLight;\n const { mutateAsync: defaultCreateMessage } = useCreateConversationMessage();\n const createMessage = createMessageOverride ?? defaultCreateMessage;\n const scrollToBottomRef = useRef<ScrollContainerHandle>(null);\n\n const [currentConversation, setCurrentConversation] =\n useState(conversationId);\n const [conversations, setConversations] = useState<Conversations>({\n [currentConversation]: [],\n });\n const streamingConversations = useRef<Conversations>({\n [currentConversation]: [],\n });\n\n /** True while a send on the provisional thread is still running (even if UI switched to another conv). */\n const isTempStreamInProgressRef = useRef(false);\n\n const [streamingConversationId, setStreamingConversationId] = useState<\n string | null\n >(null);\n\n // Track pending tool calls during streaming\n const pendingToolCalls = useRef<Record<string, ToolCall>>({});\n\n useEffect(() => {\n if (currentConversation !== conversationId) {\n setCurrentConversation(conversationId);\n setConversations(prev => {\n // New chat from the nav resets TEMP to []. When returning to a still-streaming temp thread,\n // keep existing messages so the user sees the full inflight exchange (RHDHBUGS-3040).\n if (conversationId === TEMP_CONVERSATION_ID) {\n if (\n isTempStreamInProgressRef.current &&\n (prev[TEMP_CONVERSATION_ID]?.length ?? 0) > 0\n ) {\n return prev;\n }\n return { ...prev, [TEMP_CONVERSATION_ID]: [] };\n }\n if (prev[conversationId]) return prev;\n return {\n ...prev,\n [conversationId]: [],\n };\n });\n }\n }, [currentConversation, conversationId]);\n\n const { data: conversationsData = [], ...queryProps } =\n useFetchConversationMessages(currentConversation);\n\n useEffect(() => {\n if (!Array.isArray(conversationsData) || conversationsData.length === 0)\n return;\n\n const newConvoIndex: number[] = [];\n\n if (conversations) {\n const _conversations: { [key: string]: any[] } = {\n [currentConversation]: [],\n };\n\n let index = 0;\n for (let i = 0; i < conversationsData.length; i++) {\n const [userMessage, aiMessage] = getConversationsData(\n conversationsData[i] as unknown as LCSConversation,\n );\n\n // Create user message\n const userMsg = createUserMessage({\n avatar,\n name: userName,\n content: userMessage.content,\n timestamp: userMessage.timestamp,\n });\n\n // Create bot message\n const botMsg = createBotMessage({\n avatar: botAvatar,\n isLoading: false,\n name: conversationsData[i].model ?? selectedModel,\n content: aiMessage.content,\n timestamp: aiMessage.timestamp,\n sources: transformDocumentsToSources(\n aiMessage?.referenced_documents ?? [],\n ),\n });\n\n // Merge cached tool calls if available\n const cacheKey = `${currentConversation}-${i}`;\n const cachedToolCalls = getSharedToolCallsCache(cacheKey);\n if (cachedToolCalls && cachedToolCalls.length > 0) {\n botMsg.toolCalls = cachedToolCalls;\n }\n\n _conversations[currentConversation].push(userMsg, botMsg);\n\n newConvoIndex.push(index);\n index++;\n }\n\n if (streamingConversations.current[currentConversation]) {\n _conversations[currentConversation].push(\n ...streamingConversations.current[currentConversation],\n );\n }\n\n setConversations(prev => ({\n ...prev,\n ..._conversations,\n }));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n conversationsData,\n userName,\n avatar,\n currentConversation,\n selectedModel,\n streamingConversations,\n ]);\n\n const handleInputPrompt = useCallback(\n async (prompt: string, attachments: Attachment[] = []) => {\n const normalizedPrompt = normalizeChatUserInput(prompt);\n if (!normalizedPrompt) {\n return;\n }\n\n const streamStartedOnTemp = currentConversation === TEMP_CONVERSATION_ID;\n if (streamStartedOnTemp) {\n isTempStreamInProgressRef.current = true;\n }\n\n try {\n let newConversationId = '';\n let requestId = '';\n setStreamingConversationId(currentConversation);\n\n const toolCallsCacheKeyPrefix =\n currentConversation === TEMP_CONVERSATION_ID\n ? createTempToolCallsCacheSessionPrefix()\n : currentConversation;\n\n const conversationTuple = [\n createUserMessage({\n avatar,\n name: userName,\n content: normalizedPrompt,\n timestamp: getTimestamp(Date.now()) ?? '',\n }),\n createBotMessage({\n avatar: botAvatar,\n isLoading: true,\n name: selectedModel,\n content: '',\n timestamp: '',\n }),\n ];\n\n streamingConversations.current = {\n ...streamingConversations.current,\n [currentConversation]: conversationTuple,\n };\n\n setConversations((prevConv: Conversations) => {\n return {\n ...prevConv,\n [currentConversation]: [\n ...(prevConv?.[currentConversation] ?? []),\n ...conversationTuple,\n ],\n };\n });\n\n setTimeout(() => {\n scrollToBottomRef.current?.scrollToBottom();\n }, 0);\n const finalMessages: string[] = [];\n let buffer = '';\n\n try {\n const reader = await createMessage({\n prompt: normalizedPrompt,\n selectedModel,\n selectedProvider,\n currentConversation,\n attachments,\n });\n\n const decoder = new TextDecoder('utf-8');\n let streamEnded = false;\n\n while (!streamEnded) {\n const { value, done } = await reader.read();\n if (done) {\n streamEnded = true;\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n\n const {\n events: parsedEvents,\n parseErrors,\n remainder,\n } = parseSSEBuffer(buffer);\n buffer = remainder;\n\n if (parseErrors.length > 0) {\n // eslint-disable-next-line no-console\n console.warn('Error parsing JSON:', parseErrors[0]);\n if (typeof onComplete === 'function') {\n onComplete('Invalid JSON received');\n }\n }\n\n for (const { event, data } of parsedEvents) {\n try {\n if (event === 'start') {\n requestId = data?.request_id;\n\n if (currentConversation === TEMP_CONVERSATION_ID) {\n newConversationId = data?.conversation_id;\n }\n\n onRequestIdReady?.(requestId, newConversationId || undefined);\n }\n\n if (event === 'tool_call') {\n const toolCall = parseToolCallFromEvent(data);\n\n if (toolCall && data.id !== null) {\n const newToolCall: ToolCall = toolCall;\n pendingToolCalls.current[toolCallIdKey(data.id)] =\n newToolCall;\n\n setConversations(prevConversations => {\n const conversation =\n prevConversations[currentConversation] ?? [];\n const lastMessageIndex = conversation.length - 1;\n\n if (lastMessageIndex < 0) return prevConversations;\n\n const lastMessage = { ...conversation[lastMessageIndex] };\n const existingToolCalls = normalizeToolCalls(\n lastMessage.toolCalls,\n );\n const nextToolCalls: ToolCall[] = [\n ...existingToolCalls,\n newToolCall,\n ];\n lastMessage.toolCalls = nextToolCalls;\n\n const messageIndex = Math.floor(lastMessageIndex / 2);\n const cacheKey = `${toolCallsCacheKeyPrefix}-${messageIndex}`;\n setSharedToolCallsCache(cacheKey, nextToolCalls);\n\n const updatedConversation = [\n ...conversation.slice(0, lastMessageIndex),\n lastMessage,\n ];\n\n return {\n ...prevConversations,\n [currentConversation]: updatedConversation,\n };\n });\n\n const [humanMessage, aiMessage] =\n streamingConversations.current[currentConversation] || [];\n if (aiMessage) {\n const existingStreamingToolCalls = normalizeToolCalls(\n aiMessage.toolCalls,\n );\n streamingConversations.current[currentConversation] = [\n humanMessage,\n {\n ...aiMessage,\n toolCalls: [\n ...existingStreamingToolCalls,\n newToolCall,\n ],\n },\n ];\n }\n }\n }\n\n if (event === 'tool_result') {\n const result = parseToolResultFromEvent(\n data,\n pendingToolCalls.current,\n );\n\n if (result) {\n setConversations(prevConversations => {\n const conversation =\n prevConversations[currentConversation] ?? [];\n const lastMessageIndex = conversation.length - 1;\n\n if (lastMessageIndex < 0) return prevConversations;\n\n const lastMessage = { ...conversation[lastMessageIndex] };\n const updatedToolCalls = applyToolResultToToolCalls(\n lastMessage.toolCalls || [],\n result,\n );\n\n lastMessage.toolCalls = updatedToolCalls;\n\n const messageIndex = Math.floor(lastMessageIndex / 2);\n const cacheKey = `${toolCallsCacheKeyPrefix}-${messageIndex}`;\n setSharedToolCallsCache(cacheKey, updatedToolCalls);\n\n const updatedConversation = [\n ...conversation.slice(0, lastMessageIndex),\n lastMessage,\n ];\n\n return {\n ...prevConversations,\n [currentConversation]: updatedConversation,\n };\n });\n\n const [humanMessage, aiMessage] =\n streamingConversations.current[currentConversation] || [];\n if (aiMessage) {\n const updatedToolCalls = applyToolResultToToolCalls(\n aiMessage.toolCalls || [],\n result,\n );\n streamingConversations.current[currentConversation] = [\n humanMessage,\n { ...aiMessage, toolCalls: updatedToolCalls },\n ];\n }\n\n delete pendingToolCalls.current[result.toolIdKey];\n }\n }\n\n if (event === 'token') {\n const content = data?.token || '';\n\n finalMessages.push(content);\n\n // Store streaming message\n const [humanMessage, aiMessage] =\n streamingConversations.current[currentConversation];\n streamingConversations.current[currentConversation] = [\n humanMessage,\n { ...aiMessage, content: aiMessage.content + content },\n ];\n\n setConversations(prevConversations => {\n const conversation =\n prevConversations[currentConversation] ?? [];\n\n const lastMessageIndex = conversation.length - 1;\n const lastMessage =\n conversation.length === 0\n ? createBotMessage({\n content: '',\n timestamp: getTimestamp(Date.now()),\n })\n : { ...conversation[lastMessageIndex] };\n\n if ((lastMessage?.content ?? '').trim().length > 0) {\n lastMessage.isLoading = false;\n }\n lastMessage.content += content;\n lastMessage.name =\n data?.response_metadata?.model || selectedModel;\n lastMessage.timestamp = getTimestamp(\n // TODO: To be fixed in the query response\n data?.response_metadata?.created_at || Date.now(),\n );\n\n const updatedConversation = [\n ...conversation.slice(0, lastMessageIndex),\n lastMessage,\n ];\n\n return {\n ...prevConversations,\n [currentConversation]: updatedConversation,\n };\n });\n }\n\n if (event === 'interrupted') {\n if (\n currentConversation === TEMP_CONVERSATION_ID &&\n data?.conversation_id\n ) {\n newConversationId = data.conversation_id;\n }\n setConversations(prevConversations => {\n const conversation =\n prevConversations[currentConversation] ?? [];\n const lastMessageIndex = conversation.length - 1;\n const lastMessage =\n conversation.length === 0\n ? createBotMessage({\n content: '',\n isLoading: false,\n timestamp: getTimestamp(Date.now()),\n })\n : {\n ...conversation[lastMessageIndex],\n isLoading: false,\n };\n const updatedConversation = [\n ...conversation.slice(0, lastMessageIndex),\n lastMessage,\n ];\n return {\n ...prevConversations,\n [currentConversation]: updatedConversation,\n };\n });\n streamEnded = true;\n break;\n }\n\n if (event === 'end') {\n const documents = data?.referenced_documents || [];\n\n setConversations(prevConversations => {\n const conversation =\n prevConversations[currentConversation] ?? [];\n\n const lastMessageIndex = conversation.length - 1;\n const lastMessage =\n conversation.length === 0\n ? createBotMessage({\n content: '',\n isLoading: false,\n timestamp: getTimestamp(Date.now()),\n })\n : {\n ...conversation[lastMessageIndex],\n isLoading: false,\n };\n\n const sourcesFromDocs =\n transformDocumentsToSources(documents);\n if (sourcesFromDocs) {\n lastMessage.sources = sourcesFromDocs;\n }\n\n const updatedConversation = [\n ...conversation.slice(0, lastMessageIndex),\n lastMessage,\n ];\n\n return {\n ...prevConversations,\n [currentConversation]: updatedConversation,\n };\n });\n }\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('Error parsing JSON:', error);\n if (typeof onComplete === 'function') {\n onComplete('Invalid JSON received');\n }\n }\n }\n if (streamEnded) break;\n }\n } catch (e) {\n setConversations(prevConversations => {\n const conversation = prevConversations[currentConversation] ?? [];\n\n const lastMessageIndex = conversation.length - 1;\n const lastMessage =\n conversation.length === 0\n ? createBotMessage({\n content: '',\n timestamp: getTimestamp(Date.now()),\n })\n : { ...conversation[lastMessageIndex] };\n\n lastMessage.isLoading = false;\n lastMessage.content += e;\n lastMessage.error = {\n title: e.message,\n };\n lastMessage.timestamp = getTimestamp(Date.now());\n\n const updatedConversation = [\n ...conversation.slice(0, lastMessageIndex),\n lastMessage,\n ];\n\n finalMessages.push(`${e}`);\n\n return {\n ...prevConversations,\n [newConversationId.length > 0\n ? newConversationId\n : currentConversation]: updatedConversation,\n };\n });\n }\n // reset current streaming\n streamingConversations.current[currentConversation] = [];\n if (typeof onComplete === 'function') {\n onComplete(finalMessages.join(''));\n }\n // Swap temp conversation messages with new conversation\n\n if (currentConversation === TEMP_CONVERSATION_ID && newConversationId) {\n migrateSharedToolCallsCacheSessionPrefixToConversation(\n toolCallsCacheKeyPrefix,\n newConversationId,\n );\n\n setConversations(prevConversations => {\n return {\n ...prevConversations,\n [newConversationId]: prevConversations[TEMP_CONVERSATION_ID],\n };\n });\n\n onStart?.(newConversationId);\n\n // Defer removal so it runs after the sync useEffect updates currentConversation.\n setTimeout(() => {\n setConversations(prev => {\n const { [TEMP_CONVERSATION_ID]: _, ...rest } = prev;\n return rest;\n });\n }, 0);\n } else if (currentConversation === TEMP_CONVERSATION_ID) {\n clearSharedToolCallsCacheSessionPrefix(toolCallsCacheKeyPrefix);\n }\n } finally {\n if (streamStartedOnTemp) {\n isTempStreamInProgressRef.current = false;\n }\n setStreamingConversationId(null);\n }\n },\n\n [\n avatar,\n botAvatar,\n userName,\n onComplete,\n onStart,\n onRequestIdReady,\n selectedModel,\n selectedProvider,\n createMessage,\n currentConversation,\n ],\n );\n\n return {\n conversationMessages: conversations[currentConversation] ?? [],\n handleInputPrompt,\n conversations,\n scrollToBottomRef,\n streamingConversationId,\n ...queryProps,\n };\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useConversationMessages.esm.js","sources":["../../src/hooks/useConversationMessages.ts"],"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 { RefObject, useCallback, useEffect, useRef, useState } from 'react';\n\nimport { useApi } from '@backstage/core-plugin-api';\n\nimport { useTheme } from '@mui/material/styles';\nimport { MessageProps } from '@patternfly/chatbot';\nimport { useQuery, type UseQueryResult } from '@tanstack/react-query';\n\nimport { lightspeedApiRef } from '../api/api';\nimport { ScrollContainerHandle } from '../components/LightspeedChatBox';\nimport { TEMP_CONVERSATION_ID } from '../const';\nimport botAvatarDark from '../images/bot-avatar-dark.svg';\nimport botAvatarLight from '../images/bot-avatar.svg';\nimport userAvatar from '../images/user-avatar.svg';\nimport { Attachment, BaseMessage, LCSConversation, ToolCall } from '../types';\nimport {\n createBotMessage,\n createUserMessage,\n getConversationsData,\n getTimestamp,\n normalizeChatUserInput,\n transformDocumentsToSources,\n} from '../utils/lightspeed-chatbox-utils';\nimport {\n applyToolResultToToolCalls,\n createTempToolCallsCacheSessionPrefix,\n normalizeToolCalls,\n parseSSEBuffer,\n parseToolCallFromEvent,\n parseToolResultFromEvent,\n toolCallIdKey,\n} from '../utils/stream-event-helpers';\nimport {\n clearSharedToolCallsCacheSessionPrefix,\n getSharedToolCallsCache,\n migrateSharedToolCallsCacheSessionPrefixToConversation,\n setSharedToolCallsCache,\n} from './toolCallsCacheStore';\nimport {\n CreateMessageVariables,\n useCreateConversationMessage,\n} from './useCreateCoversationMessage';\n\n// Fetch all conversation messages\nexport const useFetchConversationMessages = (\n currentConversation: string,\n): UseQueryResult<BaseMessage[] | undefined, Error> => {\n const lightspeedApi = useApi(lightspeedApiRef);\n return useQuery({\n queryKey: ['conversationMessages', currentConversation],\n queryFn: currentConversation\n ? async () => {\n const response =\n await lightspeedApi.getConversationMessages(currentConversation);\n\n return response;\n }\n : undefined,\n retry: false,\n });\n};\n\n// Extended message type to include tool calls\ninterface ExtendedMessageProps extends MessageProps {\n toolCalls?: ToolCall[];\n}\n\ntype Conversations = { [_key: string]: ExtendedMessageProps[] };\n\nexport type UseConversationMessagesReturn = {\n conversationMessages: ExtendedMessageProps[];\n handleInputPrompt: (\n prompt: string,\n attachments?: Attachment[],\n ) => Promise<void>;\n conversations: Conversations;\n scrollToBottomRef: RefObject<ScrollContainerHandle | null>;\n streamingConversationId: string | null;\n data?: BaseMessage[] | undefined;\n error: Error | null;\n isPending: boolean;\n isFetching: boolean;\n isSuccess: boolean;\n isError: boolean;\n status: 'pending' | 'error' | 'success';\n refetch: () => void;\n};\n\n/**\n * Fetches all the messages for given conversation_id\n * @param conversationId\n * @param userName\n * @param selectedModel\n * @param selectedProvider\n * @param avatar\n *\n */\nexport const useConversationMessages = (\n conversationId: string,\n userName: string | undefined,\n selectedModel: string,\n selectedProvider: string,\n avatar: string = userAvatar,\n onComplete?: (message: string) => void,\n onStart?: (conversation_id: string) => void,\n createMessageOverride?: (\n vars: CreateMessageVariables,\n ) => Promise<ReadableStreamDefaultReader<Uint8Array>>,\n onRequestIdReady?: (request_id: string, conversation_id?: string) => void,\n): UseConversationMessagesReturn => {\n const theme = useTheme();\n const botAvatar =\n theme.palette.mode === 'dark' ? botAvatarDark : botAvatarLight;\n const { mutateAsync: defaultCreateMessage } = useCreateConversationMessage();\n const createMessage = createMessageOverride ?? defaultCreateMessage;\n const scrollToBottomRef = useRef<ScrollContainerHandle>(null);\n\n const [currentConversation, setCurrentConversation] =\n useState(conversationId);\n const [conversations, setConversations] = useState<Conversations>({\n [currentConversation]: [],\n });\n const streamingConversations = useRef<Conversations>({\n [currentConversation]: [],\n });\n\n /** True while a send on the provisional thread is still running (even if UI switched to another conv). */\n const isTempStreamInProgressRef = useRef(false);\n\n const [streamingConversationId, setStreamingConversationId] = useState<\n string | null\n >(null);\n\n // Track pending tool calls during streaming\n const pendingToolCalls = useRef<Record<string, ToolCall>>({});\n\n useEffect(() => {\n if (currentConversation !== conversationId) {\n setCurrentConversation(conversationId);\n setConversations(prev => {\n // New chat from the nav resets TEMP to []. When returning to a still-streaming temp thread,\n // keep existing messages so the user sees the full inflight exchange (RHDHBUGS-3040).\n if (conversationId === TEMP_CONVERSATION_ID) {\n if (\n isTempStreamInProgressRef.current &&\n (prev[TEMP_CONVERSATION_ID]?.length ?? 0) > 0\n ) {\n return prev;\n }\n return { ...prev, [TEMP_CONVERSATION_ID]: [] };\n }\n if (prev[conversationId]) return prev;\n return {\n ...prev,\n [conversationId]: [],\n };\n });\n }\n }, [currentConversation, conversationId]);\n\n const { data: conversationsData = [], ...queryProps } =\n useFetchConversationMessages(currentConversation);\n\n useEffect(() => {\n if (!Array.isArray(conversationsData) || conversationsData.length === 0)\n return;\n\n const newConvoIndex: number[] = [];\n\n if (conversations) {\n const _conversations: { [key: string]: any[] } = {\n [currentConversation]: [],\n };\n\n let index = 0;\n for (let i = 0; i < conversationsData.length; i++) {\n const [userMessage, aiMessage] = getConversationsData(\n conversationsData[i] as unknown as LCSConversation,\n );\n\n // Create user message\n const userMsg = createUserMessage({\n avatar,\n name: userName,\n content: userMessage.content,\n timestamp: userMessage.timestamp,\n });\n\n // Create bot message\n const botMsg = createBotMessage({\n avatar: botAvatar,\n isLoading: false,\n name: conversationsData[i].model ?? selectedModel,\n content: aiMessage.content,\n timestamp: aiMessage.timestamp,\n sources: transformDocumentsToSources(\n aiMessage?.referenced_documents ?? [],\n ),\n });\n\n // Merge cached tool calls if available\n const cacheKey = `${currentConversation}-${i}`;\n const cachedToolCalls = getSharedToolCallsCache(cacheKey);\n if (cachedToolCalls && cachedToolCalls.length > 0) {\n botMsg.toolCalls = cachedToolCalls;\n }\n\n _conversations[currentConversation].push(userMsg, botMsg);\n\n newConvoIndex.push(index);\n index++;\n }\n\n if (streamingConversations.current[currentConversation]) {\n _conversations[currentConversation].push(\n ...streamingConversations.current[currentConversation],\n );\n }\n\n setConversations(prev => ({\n ...prev,\n ..._conversations,\n }));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n conversationsData,\n userName,\n avatar,\n currentConversation,\n selectedModel,\n streamingConversations,\n ]);\n\n const handleInputPrompt = useCallback(\n async (prompt: string, attachments: Attachment[] = []) => {\n const normalizedPrompt = normalizeChatUserInput(prompt);\n if (!normalizedPrompt) {\n return;\n }\n\n const streamStartedOnTemp = currentConversation === TEMP_CONVERSATION_ID;\n if (streamStartedOnTemp) {\n isTempStreamInProgressRef.current = true;\n }\n\n try {\n let newConversationId = '';\n let requestId = '';\n setStreamingConversationId(currentConversation);\n\n const toolCallsCacheKeyPrefix =\n currentConversation === TEMP_CONVERSATION_ID\n ? createTempToolCallsCacheSessionPrefix()\n : currentConversation;\n\n const conversationTuple = [\n createUserMessage({\n avatar,\n name: userName,\n content: normalizedPrompt,\n timestamp: getTimestamp(Date.now()) ?? '',\n }),\n createBotMessage({\n avatar: botAvatar,\n isLoading: true,\n name: selectedModel,\n content: '',\n timestamp: '',\n }),\n ];\n\n streamingConversations.current = {\n ...streamingConversations.current,\n [currentConversation]: conversationTuple,\n };\n\n setConversations((prevConv: Conversations) => {\n return {\n ...prevConv,\n [currentConversation]: [\n ...(prevConv?.[currentConversation] ?? []),\n ...conversationTuple,\n ],\n };\n });\n\n setTimeout(() => {\n scrollToBottomRef.current?.scrollToBottom();\n }, 0);\n const finalMessages: string[] = [];\n let buffer = '';\n\n try {\n const reader = await createMessage({\n prompt: normalizedPrompt,\n selectedModel,\n selectedProvider,\n currentConversation,\n attachments,\n });\n\n const decoder = new TextDecoder('utf-8');\n let streamEnded = false;\n\n while (!streamEnded) {\n const { value, done } = await reader.read();\n if (done) {\n streamEnded = true;\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n\n const {\n events: parsedEvents,\n parseErrors,\n remainder,\n } = parseSSEBuffer(buffer);\n buffer = remainder;\n\n if (parseErrors.length > 0) {\n // eslint-disable-next-line no-console\n console.warn('Error parsing JSON:', parseErrors[0]);\n if (typeof onComplete === 'function') {\n onComplete('Invalid JSON received');\n }\n }\n\n for (const { event, data } of parsedEvents) {\n try {\n if (event === 'start') {\n requestId = data?.request_id;\n\n if (currentConversation === TEMP_CONVERSATION_ID) {\n newConversationId = data?.conversation_id;\n }\n\n onRequestIdReady?.(requestId, newConversationId || undefined);\n }\n\n if (event === 'tool_call') {\n const toolCall = parseToolCallFromEvent(data);\n\n if (toolCall && data.id !== null) {\n const newToolCall: ToolCall = toolCall;\n pendingToolCalls.current[toolCallIdKey(data.id)] =\n newToolCall;\n\n setConversations(prevConversations => {\n const conversation =\n prevConversations[currentConversation] ?? [];\n const lastMessageIndex = conversation.length - 1;\n\n if (lastMessageIndex < 0) return prevConversations;\n\n const lastMessage = { ...conversation[lastMessageIndex] };\n const existingToolCalls = normalizeToolCalls(\n lastMessage.toolCalls,\n );\n const nextToolCalls: ToolCall[] = [\n ...existingToolCalls,\n newToolCall,\n ];\n lastMessage.toolCalls = nextToolCalls;\n\n const messageIndex = Math.floor(lastMessageIndex / 2);\n const cacheKey = `${toolCallsCacheKeyPrefix}-${messageIndex}`;\n setSharedToolCallsCache(cacheKey, nextToolCalls);\n\n const updatedConversation = [\n ...conversation.slice(0, lastMessageIndex),\n lastMessage,\n ];\n\n return {\n ...prevConversations,\n [currentConversation]: updatedConversation,\n };\n });\n\n const [humanMessage, aiMessage] =\n streamingConversations.current[currentConversation] || [];\n if (aiMessage) {\n const existingStreamingToolCalls = normalizeToolCalls(\n aiMessage.toolCalls,\n );\n streamingConversations.current[currentConversation] = [\n humanMessage,\n {\n ...aiMessage,\n toolCalls: [\n ...existingStreamingToolCalls,\n newToolCall,\n ],\n },\n ];\n }\n }\n }\n\n if (event === 'tool_result') {\n const result = parseToolResultFromEvent(\n data,\n pendingToolCalls.current,\n );\n\n if (result) {\n setConversations(prevConversations => {\n const conversation =\n prevConversations[currentConversation] ?? [];\n const lastMessageIndex = conversation.length - 1;\n\n if (lastMessageIndex < 0) return prevConversations;\n\n const lastMessage = { ...conversation[lastMessageIndex] };\n const updatedToolCalls = applyToolResultToToolCalls(\n lastMessage.toolCalls || [],\n result,\n );\n\n lastMessage.toolCalls = updatedToolCalls;\n\n const messageIndex = Math.floor(lastMessageIndex / 2);\n const cacheKey = `${toolCallsCacheKeyPrefix}-${messageIndex}`;\n setSharedToolCallsCache(cacheKey, updatedToolCalls);\n\n const updatedConversation = [\n ...conversation.slice(0, lastMessageIndex),\n lastMessage,\n ];\n\n return {\n ...prevConversations,\n [currentConversation]: updatedConversation,\n };\n });\n\n const [humanMessage, aiMessage] =\n streamingConversations.current[currentConversation] || [];\n if (aiMessage) {\n const updatedToolCalls = applyToolResultToToolCalls(\n aiMessage.toolCalls || [],\n result,\n );\n streamingConversations.current[currentConversation] = [\n humanMessage,\n { ...aiMessage, toolCalls: updatedToolCalls },\n ];\n }\n\n delete pendingToolCalls.current[result.toolIdKey];\n }\n }\n\n if (event === 'token') {\n const content = data?.token || '';\n\n finalMessages.push(content);\n\n // Store streaming message\n const [humanMessage, aiMessage] =\n streamingConversations.current[currentConversation];\n streamingConversations.current[currentConversation] = [\n humanMessage,\n { ...aiMessage, content: aiMessage.content + content },\n ];\n\n setConversations(prevConversations => {\n const conversation =\n prevConversations[currentConversation] ?? [];\n\n const lastMessageIndex = conversation.length - 1;\n const lastMessage =\n conversation.length === 0\n ? createBotMessage({\n content: '',\n timestamp: getTimestamp(Date.now()),\n })\n : { ...conversation[lastMessageIndex] };\n\n if ((lastMessage?.content ?? '').trim().length > 0) {\n lastMessage.isLoading = false;\n }\n lastMessage.content += content;\n lastMessage.name =\n data?.response_metadata?.model || selectedModel;\n lastMessage.timestamp = getTimestamp(\n // TODO: To be fixed in the query response\n data?.response_metadata?.created_at || Date.now(),\n );\n\n const updatedConversation = [\n ...conversation.slice(0, lastMessageIndex),\n lastMessage,\n ];\n\n return {\n ...prevConversations,\n [currentConversation]: updatedConversation,\n };\n });\n }\n\n if (event === 'interrupted') {\n if (\n currentConversation === TEMP_CONVERSATION_ID &&\n data?.conversation_id\n ) {\n newConversationId = data.conversation_id;\n }\n setConversations(prevConversations => {\n const conversation =\n prevConversations[currentConversation] ?? [];\n const lastMessageIndex = conversation.length - 1;\n const lastMessage =\n conversation.length === 0\n ? createBotMessage({\n content: '',\n isLoading: false,\n timestamp: getTimestamp(Date.now()),\n })\n : {\n ...conversation[lastMessageIndex],\n isLoading: false,\n };\n const updatedConversation = [\n ...conversation.slice(0, lastMessageIndex),\n lastMessage,\n ];\n return {\n ...prevConversations,\n [currentConversation]: updatedConversation,\n };\n });\n streamEnded = true;\n break;\n }\n\n if (event === 'end') {\n const documents = data?.referenced_documents || [];\n\n setConversations(prevConversations => {\n const conversation =\n prevConversations[currentConversation] ?? [];\n\n const lastMessageIndex = conversation.length - 1;\n const lastMessage =\n conversation.length === 0\n ? createBotMessage({\n content: '',\n isLoading: false,\n timestamp: getTimestamp(Date.now()),\n })\n : {\n ...conversation[lastMessageIndex],\n isLoading: false,\n };\n\n const sourcesFromDocs =\n transformDocumentsToSources(documents);\n if (sourcesFromDocs) {\n lastMessage.sources = sourcesFromDocs;\n }\n\n const updatedConversation = [\n ...conversation.slice(0, lastMessageIndex),\n lastMessage,\n ];\n\n return {\n ...prevConversations,\n [currentConversation]: updatedConversation,\n };\n });\n }\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('Error parsing JSON:', error);\n if (typeof onComplete === 'function') {\n onComplete('Invalid JSON received');\n }\n }\n }\n if (streamEnded) break;\n }\n } catch (e) {\n setConversations(prevConversations => {\n const conversation = prevConversations[currentConversation] ?? [];\n\n const lastMessageIndex = conversation.length - 1;\n const lastMessage =\n conversation.length === 0\n ? createBotMessage({\n content: '',\n timestamp: getTimestamp(Date.now()),\n })\n : { ...conversation[lastMessageIndex] };\n\n lastMessage.isLoading = false;\n lastMessage.content += e;\n lastMessage.error = {\n title: e.message,\n };\n lastMessage.timestamp = getTimestamp(Date.now());\n\n const updatedConversation = [\n ...conversation.slice(0, lastMessageIndex),\n lastMessage,\n ];\n\n finalMessages.push(`${e}`);\n\n return {\n ...prevConversations,\n [newConversationId.length > 0\n ? newConversationId\n : currentConversation]: updatedConversation,\n };\n });\n }\n // reset current streaming\n streamingConversations.current[currentConversation] = [];\n if (typeof onComplete === 'function') {\n onComplete(finalMessages.join(''));\n }\n // Swap temp conversation messages with new conversation\n\n if (currentConversation === TEMP_CONVERSATION_ID && newConversationId) {\n migrateSharedToolCallsCacheSessionPrefixToConversation(\n toolCallsCacheKeyPrefix,\n newConversationId,\n );\n\n setConversations(prevConversations => {\n return {\n ...prevConversations,\n [newConversationId]: prevConversations[TEMP_CONVERSATION_ID],\n };\n });\n\n onStart?.(newConversationId);\n\n // Defer removal so it runs after the sync useEffect updates currentConversation.\n setTimeout(() => {\n setConversations(prev => {\n const { [TEMP_CONVERSATION_ID]: _, ...rest } = prev;\n return rest;\n });\n }, 0);\n } else if (currentConversation === TEMP_CONVERSATION_ID) {\n clearSharedToolCallsCacheSessionPrefix(toolCallsCacheKeyPrefix);\n }\n } finally {\n if (streamStartedOnTemp) {\n isTempStreamInProgressRef.current = false;\n }\n setStreamingConversationId(null);\n }\n },\n\n [\n avatar,\n botAvatar,\n userName,\n onComplete,\n onStart,\n onRequestIdReady,\n selectedModel,\n selectedProvider,\n createMessage,\n currentConversation,\n ],\n );\n\n return {\n conversationMessages: conversations[currentConversation] ?? [],\n handleInputPrompt,\n conversations,\n scrollToBottomRef,\n streamingConversationId,\n ...queryProps,\n };\n};\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { useState, useEffect, useCallback } from 'react';
2
2
  import { useApi, storageApiRef } from '@backstage/core-plugin-api';
3
- import { ChatbotDisplayMode } from '@patternfly/chatbot';
3
+ import { ChatbotDisplayMode } from '../const.esm.js';
4
4
  import { isGuestUser } from '../utils/user-utils.esm.js';
5
5
 
6
6
  const BUCKET_NAME = "lightspeed";
@@ -1 +1 @@
1
- {"version":3,"file":"useDisplayModeSettings.esm.js","sources":["../../src/hooks/useDisplayModeSettings.ts"],"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 */\nimport { useCallback, useEffect, useState } from 'react';\n\nimport { storageApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport { ChatbotDisplayMode } from '@patternfly/chatbot';\n\nimport { isGuestUser } from '../utils/user-utils';\n\nconst BUCKET_NAME = 'lightspeed';\nconst DISPLAY_MODE_KEY = 'displayMode';\n\ntype UseDisplayModeSettingsReturn = {\n displayMode: ChatbotDisplayMode;\n setDisplayMode: (mode: ChatbotDisplayMode) => void;\n};\n\n/**\n * Hook to manage display mode settings with persistence using Backstage StorageApi.\n *\n * @param user - The user entity ref (e.g., \"user:default/john\")\n * @param defaultMode - The default display mode to use if no preference is stored\n * @returns Object containing display mode state and management function\n */\nexport const useDisplayModeSettings = (\n user: string | undefined,\n defaultMode: ChatbotDisplayMode = ChatbotDisplayMode.default,\n): UseDisplayModeSettingsReturn => {\n const storageApi = useApi(storageApiRef);\n const bucket = storageApi.forBucket(BUCKET_NAME);\n\n const [displayModeState, setDisplayModeState] =\n useState<ChatbotDisplayMode>(defaultMode);\n\n const shouldPersist = !isGuestUser(user);\n\n useEffect(() => {\n if (!user || isGuestUser(user)) {\n setDisplayModeState(defaultMode);\n return undefined;\n }\n\n try {\n const modeSnapshot =\n bucket.snapshot<ChatbotDisplayMode>(DISPLAY_MODE_KEY);\n setDisplayModeState(modeSnapshot.value ?? defaultMode);\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('Error reading display mode from storage:', error);\n }\n\n const modeSubscription = bucket\n .observe$<ChatbotDisplayMode>(DISPLAY_MODE_KEY)\n .subscribe({\n next: snapshot => {\n setDisplayModeState(snapshot.value ?? defaultMode);\n },\n error: error => {\n // eslint-disable-next-line no-console\n console.error('Error observing displayMode:', error);\n },\n });\n\n return () => {\n modeSubscription.unsubscribe();\n };\n }, [bucket, user, defaultMode]);\n\n const setDisplayMode = useCallback(\n (mode: ChatbotDisplayMode) => {\n if (!user) return;\n\n setDisplayModeState(mode);\n\n if (shouldPersist) {\n try {\n bucket.set(DISPLAY_MODE_KEY, mode);\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('Error saving display mode:', error);\n }\n }\n },\n [bucket, user, shouldPersist],\n );\n\n return {\n displayMode: displayModeState,\n setDisplayMode,\n };\n};\n"],"names":[],"mappings":";;;;;AAuBA,MAAM,WAAA,GAAc,YAAA;AACpB,MAAM,gBAAA,GAAmB,aAAA;AAclB,MAAM,sBAAA,GAAyB,CACpC,IAAA,EACA,WAAA,GAAkC,mBAAmB,OAAA,KACpB;AACjC,EAAA,MAAM,UAAA,GAAa,OAAO,aAAa,CAAA;AACvC,EAAA,MAAM,MAAA,GAAS,UAAA,CAAW,SAAA,CAAU,WAAW,CAAA;AAE/C,EAAA,MAAM,CAAC,gBAAA,EAAkB,mBAAmB,CAAA,GAC1C,SAA6B,WAAW,CAAA;AAE1C,EAAA,MAAM,aAAA,GAAgB,CAAC,WAAA,CAAY,IAAI,CAAA;AAEvC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,IAAA,IAAQ,WAAA,CAAY,IAAI,CAAA,EAAG;AAC9B,MAAA,mBAAA,CAAoB,WAAW,CAAA;AAC/B,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,YAAA,GACJ,MAAA,CAAO,QAAA,CAA6B,gBAAgB,CAAA;AACtD,MAAA,mBAAA,CAAoB,YAAA,CAAa,SAAS,WAAW,CAAA;AAAA,IACvD,SAAS,KAAA,EAAO;AAEd,MAAA,OAAA,CAAQ,KAAA,CAAM,4CAA4C,KAAK,CAAA;AAAA,IACjE;AAEA,IAAA,MAAM,gBAAA,GAAmB,MAAA,CACtB,QAAA,CAA6B,gBAAgB,EAC7C,SAAA,CAAU;AAAA,MACT,MAAM,CAAA,QAAA,KAAY;AAChB,QAAA,mBAAA,CAAoB,QAAA,CAAS,SAAS,WAAW,CAAA;AAAA,MACnD,CAAA;AAAA,MACA,OAAO,CAAA,KAAA,KAAS;AAEd,QAAA,OAAA,CAAQ,KAAA,CAAM,gCAAgC,KAAK,CAAA;AAAA,MACrD;AAAA,KACD,CAAA;AAEH,IAAA,OAAO,MAAM;AACX,MAAA,gBAAA,CAAiB,WAAA,EAAY;AAAA,IAC/B,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,IAAA,EAAM,WAAW,CAAC,CAAA;AAE9B,EAAA,MAAM,cAAA,GAAiB,WAAA;AAAA,IACrB,CAAC,IAAA,KAA6B;AAC5B,MAAA,IAAI,CAAC,IAAA,EAAM;AAEX,MAAA,mBAAA,CAAoB,IAAI,CAAA;AAExB,MAAA,IAAI,aAAA,EAAe;AACjB,QAAA,IAAI;AACF,UAAA,MAAA,CAAO,GAAA,CAAI,kBAAkB,IAAI,CAAA;AAAA,QACnC,SAAS,KAAA,EAAO;AAEd,UAAA,OAAA,CAAQ,KAAA,CAAM,8BAA8B,KAAK,CAAA;AAAA,QACnD;AAAA,MACF;AAAA,IACF,CAAA;AAAA,IACA,CAAC,MAAA,EAAQ,IAAA,EAAM,aAAa;AAAA,GAC9B;AAEA,EAAA,OAAO;AAAA,IACL,WAAA,EAAa,gBAAA;AAAA,IACb;AAAA,GACF;AACF;;;;"}
1
+ {"version":3,"file":"useDisplayModeSettings.esm.js","sources":["../../src/hooks/useDisplayModeSettings.ts"],"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 */\nimport { useCallback, useEffect, useState } from 'react';\n\nimport { storageApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport { ChatbotDisplayMode } from '../const';\nimport { isGuestUser } from '../utils/user-utils';\n\nconst BUCKET_NAME = 'lightspeed';\nconst DISPLAY_MODE_KEY = 'displayMode';\n\ntype UseDisplayModeSettingsReturn = {\n displayMode: ChatbotDisplayMode;\n setDisplayMode: (mode: ChatbotDisplayMode) => void;\n};\n\n/**\n * Hook to manage display mode settings with persistence using Backstage StorageApi.\n *\n * @param user - The user entity ref (e.g., \"user:default/john\")\n * @param defaultMode - The default display mode to use if no preference is stored\n * @returns Object containing display mode state and management function\n */\nexport const useDisplayModeSettings = (\n user: string | undefined,\n defaultMode: ChatbotDisplayMode = ChatbotDisplayMode.default,\n): UseDisplayModeSettingsReturn => {\n const storageApi = useApi(storageApiRef);\n const bucket = storageApi.forBucket(BUCKET_NAME);\n\n const [displayModeState, setDisplayModeState] =\n useState<ChatbotDisplayMode>(defaultMode);\n\n const shouldPersist = !isGuestUser(user);\n\n useEffect(() => {\n if (!user || isGuestUser(user)) {\n setDisplayModeState(defaultMode);\n return undefined;\n }\n\n try {\n const modeSnapshot =\n bucket.snapshot<ChatbotDisplayMode>(DISPLAY_MODE_KEY);\n setDisplayModeState(modeSnapshot.value ?? defaultMode);\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('Error reading display mode from storage:', error);\n }\n\n const modeSubscription = bucket\n .observe$<ChatbotDisplayMode>(DISPLAY_MODE_KEY)\n .subscribe({\n next: snapshot => {\n setDisplayModeState(snapshot.value ?? defaultMode);\n },\n error: error => {\n // eslint-disable-next-line no-console\n console.error('Error observing displayMode:', error);\n },\n });\n\n return () => {\n modeSubscription.unsubscribe();\n };\n }, [bucket, user, defaultMode]);\n\n const setDisplayMode = useCallback(\n (mode: ChatbotDisplayMode) => {\n if (!user) return;\n\n setDisplayModeState(mode);\n\n if (shouldPersist) {\n try {\n bucket.set(DISPLAY_MODE_KEY, mode);\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('Error saving display mode:', error);\n }\n }\n },\n [bucket, user, shouldPersist],\n );\n\n return {\n displayMode: displayModeState,\n setDisplayMode,\n };\n};\n"],"names":[],"mappings":";;;;;AAsBA,MAAM,WAAA,GAAc,YAAA;AACpB,MAAM,gBAAA,GAAmB,aAAA;AAclB,MAAM,sBAAA,GAAyB,CACpC,IAAA,EACA,WAAA,GAAkC,mBAAmB,OAAA,KACpB;AACjC,EAAA,MAAM,UAAA,GAAa,OAAO,aAAa,CAAA;AACvC,EAAA,MAAM,MAAA,GAAS,UAAA,CAAW,SAAA,CAAU,WAAW,CAAA;AAE/C,EAAA,MAAM,CAAC,gBAAA,EAAkB,mBAAmB,CAAA,GAC1C,SAA6B,WAAW,CAAA;AAE1C,EAAA,MAAM,aAAA,GAAgB,CAAC,WAAA,CAAY,IAAI,CAAA;AAEvC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,IAAA,IAAQ,WAAA,CAAY,IAAI,CAAA,EAAG;AAC9B,MAAA,mBAAA,CAAoB,WAAW,CAAA;AAC/B,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,YAAA,GACJ,MAAA,CAAO,QAAA,CAA6B,gBAAgB,CAAA;AACtD,MAAA,mBAAA,CAAoB,YAAA,CAAa,SAAS,WAAW,CAAA;AAAA,IACvD,SAAS,KAAA,EAAO;AAEd,MAAA,OAAA,CAAQ,KAAA,CAAM,4CAA4C,KAAK,CAAA;AAAA,IACjE;AAEA,IAAA,MAAM,gBAAA,GAAmB,MAAA,CACtB,QAAA,CAA6B,gBAAgB,EAC7C,SAAA,CAAU;AAAA,MACT,MAAM,CAAA,QAAA,KAAY;AAChB,QAAA,mBAAA,CAAoB,QAAA,CAAS,SAAS,WAAW,CAAA;AAAA,MACnD,CAAA;AAAA,MACA,OAAO,CAAA,KAAA,KAAS;AAEd,QAAA,OAAA,CAAQ,KAAA,CAAM,gCAAgC,KAAK,CAAA;AAAA,MACrD;AAAA,KACD,CAAA;AAEH,IAAA,OAAO,MAAM;AACX,MAAA,gBAAA,CAAiB,WAAA,EAAY;AAAA,IAC/B,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,IAAA,EAAM,WAAW,CAAC,CAAA;AAE9B,EAAA,MAAM,cAAA,GAAiB,WAAA;AAAA,IACrB,CAAC,IAAA,KAA6B;AAC5B,MAAA,IAAI,CAAC,IAAA,EAAM;AAEX,MAAA,mBAAA,CAAoB,IAAI,CAAA;AAExB,MAAA,IAAI,aAAA,EAAe;AACjB,QAAA,IAAI;AACF,UAAA,MAAA,CAAO,GAAA,CAAI,kBAAkB,IAAI,CAAA;AAAA,QACnC,SAAS,KAAA,EAAO;AAEd,UAAA,OAAA,CAAQ,KAAA,CAAM,8BAA8B,KAAK,CAAA;AAAA,QACnD;AAAA,MACF;AAAA,IACF,CAAA;AAAA,IACA,CAAC,MAAA,EAAQ,IAAA,EAAM,aAAa;AAAA,GAC9B;AAEA,EAAA,OAAO;AAAA,IACL,WAAA,EAAa,gBAAA;AAAA,IACb;AAAA,GACF;AACF;;;;"}