@red-hat-developer-hub/backstage-plugin-intelligent-assistant 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/CHANGELOG.md +681 -0
  2. package/README.md +378 -0
  3. package/config.d.ts +70 -0
  4. package/dist/alpha.d.ts +285 -0
  5. package/dist/alpha.esm.js +3 -0
  6. package/dist/alpha.esm.js.map +1 -0
  7. package/dist/api/LightspeedApiClient.esm.js +234 -0
  8. package/dist/api/LightspeedApiClient.esm.js.map +1 -0
  9. package/dist/api/NotebooksApiClient.esm.js +179 -0
  10. package/dist/api/NotebooksApiClient.esm.js.map +1 -0
  11. package/dist/api/api.esm.js +8 -0
  12. package/dist/api/api.esm.js.map +1 -0
  13. package/dist/api/notebooksApi.esm.js +10 -0
  14. package/dist/api/notebooksApi.esm.js.map +1 -0
  15. package/dist/components/Attachment.esm.js +108 -0
  16. package/dist/components/Attachment.esm.js.map +1 -0
  17. package/dist/components/AttachmentContext.esm.js +125 -0
  18. package/dist/components/AttachmentContext.esm.js.map +1 -0
  19. package/dist/components/CollapsedHistoryStrip.esm.js +87 -0
  20. package/dist/components/CollapsedHistoryStrip.esm.js.map +1 -0
  21. package/dist/components/DeleteModal.esm.js +92 -0
  22. package/dist/components/DeleteModal.esm.js.map +1 -0
  23. package/dist/components/FilePreview.esm.js +49 -0
  24. package/dist/components/FilePreview.esm.js.map +1 -0
  25. package/dist/components/LightSpeedChat.esm.js +1898 -0
  26. package/dist/components/LightSpeedChat.esm.js.map +1 -0
  27. package/dist/components/LightspeedChatBox.esm.js +252 -0
  28. package/dist/components/LightspeedChatBox.esm.js.map +1 -0
  29. package/dist/components/LightspeedChatBoxHeader.esm.js +210 -0
  30. package/dist/components/LightspeedChatBoxHeader.esm.js.map +1 -0
  31. package/dist/components/LightspeedChatContainer.esm.js +162 -0
  32. package/dist/components/LightspeedChatContainer.esm.js.map +1 -0
  33. package/dist/components/LightspeedChatModelsState.esm.js +198 -0
  34. package/dist/components/LightspeedChatModelsState.esm.js.map +1 -0
  35. package/dist/components/LightspeedDrawerContext.esm.js +15 -0
  36. package/dist/components/LightspeedDrawerContext.esm.js.map +1 -0
  37. package/dist/components/LightspeedDrawerProvider.esm.js +44 -0
  38. package/dist/components/LightspeedDrawerProvider.esm.js.map +1 -0
  39. package/dist/components/LightspeedDrawerStateExposer.esm.js +34 -0
  40. package/dist/components/LightspeedDrawerStateExposer.esm.js.map +1 -0
  41. package/dist/components/LightspeedFAB.esm.js +6 -0
  42. package/dist/components/LightspeedFAB.esm.js.map +1 -0
  43. package/dist/components/LightspeedFABContent.esm.js +65 -0
  44. package/dist/components/LightspeedFABContent.esm.js.map +1 -0
  45. package/dist/components/LightspeedIcon.esm.js +46 -0
  46. package/dist/components/LightspeedIcon.esm.js.map +1 -0
  47. package/dist/components/LightspeedPage.esm.js +31 -0
  48. package/dist/components/LightspeedPage.esm.js.map +1 -0
  49. package/dist/components/McpServersSettings.esm.js +953 -0
  50. package/dist/components/McpServersSettings.esm.js.map +1 -0
  51. package/dist/components/McpSettingsIcon.esm.js +18 -0
  52. package/dist/components/McpSettingsIcon.esm.js.map +1 -0
  53. package/dist/components/MessageBarModelSelector.esm.js +92 -0
  54. package/dist/components/MessageBarModelSelector.esm.js.map +1 -0
  55. package/dist/components/PermissionRequiredIcon.esm.js +18 -0
  56. package/dist/components/PermissionRequiredIcon.esm.js.map +1 -0
  57. package/dist/components/PermissionRequiredState.esm.js +88 -0
  58. package/dist/components/PermissionRequiredState.esm.js.map +1 -0
  59. package/dist/components/RenameConversationModal.esm.js +157 -0
  60. package/dist/components/RenameConversationModal.esm.js.map +1 -0
  61. package/dist/components/Router.esm.js +35 -0
  62. package/dist/components/Router.esm.js.map +1 -0
  63. package/dist/components/SourcesChipModal.esm.js +124 -0
  64. package/dist/components/SourcesChipModal.esm.js.map +1 -0
  65. package/dist/components/ToolCallContent.esm.js +208 -0
  66. package/dist/components/ToolCallContent.esm.js.map +1 -0
  67. package/dist/components/Trans.esm.js +33 -0
  68. package/dist/components/Trans.esm.js.map +1 -0
  69. package/dist/components/notebooks/AddDocumentModal.esm.js +271 -0
  70. package/dist/components/notebooks/AddDocumentModal.esm.js.map +1 -0
  71. package/dist/components/notebooks/DeleteDocumentModal.esm.js +131 -0
  72. package/dist/components/notebooks/DeleteDocumentModal.esm.js.map +1 -0
  73. package/dist/components/notebooks/DeleteNotebookModal.esm.js +143 -0
  74. package/dist/components/notebooks/DeleteNotebookModal.esm.js.map +1 -0
  75. package/dist/components/notebooks/DocumentSidebar.esm.js +235 -0
  76. package/dist/components/notebooks/DocumentSidebar.esm.js.map +1 -0
  77. package/dist/components/notebooks/FileListItem.esm.js +94 -0
  78. package/dist/components/notebooks/FileListItem.esm.js.map +1 -0
  79. package/dist/components/notebooks/FileTypeIcon.esm.js +59 -0
  80. package/dist/components/notebooks/FileTypeIcon.esm.js.map +1 -0
  81. package/dist/components/notebooks/NotebookCard.esm.js +118 -0
  82. package/dist/components/notebooks/NotebookCard.esm.js.map +1 -0
  83. package/dist/components/notebooks/NotebookView.esm.js +681 -0
  84. package/dist/components/notebooks/NotebookView.esm.js.map +1 -0
  85. package/dist/components/notebooks/NotebooksTab.esm.js +71 -0
  86. package/dist/components/notebooks/NotebooksTab.esm.js.map +1 -0
  87. package/dist/components/notebooks/OverwriteConfirmModal.esm.js +142 -0
  88. package/dist/components/notebooks/OverwriteConfirmModal.esm.js.map +1 -0
  89. package/dist/components/notebooks/RenameNotebookModal.esm.js +187 -0
  90. package/dist/components/notebooks/RenameNotebookModal.esm.js.map +1 -0
  91. package/dist/components/notebooks/SidebarCollapseIcon.esm.js +50 -0
  92. package/dist/components/notebooks/SidebarCollapseIcon.esm.js.map +1 -0
  93. package/dist/components/notebooks/UploadResourceScreen.esm.js +79 -0
  94. package/dist/components/notebooks/UploadResourceScreen.esm.js.map +1 -0
  95. package/dist/const.esm.js +74 -0
  96. package/dist/const.esm.js.map +1 -0
  97. package/dist/dev.d.ts +2 -0
  98. package/dist/dev.esm.js +48 -0
  99. package/dist/dev.esm.js.map +1 -0
  100. package/dist/hooks/notebooks/useCreateNotebook.esm.js +19 -0
  101. package/dist/hooks/notebooks/useCreateNotebook.esm.js.map +1 -0
  102. package/dist/hooks/notebooks/useCreateNotebookMessage.esm.js +24 -0
  103. package/dist/hooks/notebooks/useCreateNotebookMessage.esm.js.map +1 -0
  104. package/dist/hooks/notebooks/useDeleteNotebook.esm.js +19 -0
  105. package/dist/hooks/notebooks/useDeleteNotebook.esm.js.map +1 -0
  106. package/dist/hooks/notebooks/useDocumentStatusPolling.esm.js +40 -0
  107. package/dist/hooks/notebooks/useDocumentStatusPolling.esm.js.map +1 -0
  108. package/dist/hooks/notebooks/useLightspeedNotebooksPermission.esm.js +15 -0
  109. package/dist/hooks/notebooks/useLightspeedNotebooksPermission.esm.js.map +1 -0
  110. package/dist/hooks/notebooks/useNotebookDocuments.esm.js +18 -0
  111. package/dist/hooks/notebooks/useNotebookDocuments.esm.js.map +1 -0
  112. package/dist/hooks/notebooks/useNotebookSession.esm.js +18 -0
  113. package/dist/hooks/notebooks/useNotebookSession.esm.js.map +1 -0
  114. package/dist/hooks/notebooks/useNotebookSessions.esm.js +18 -0
  115. package/dist/hooks/notebooks/useNotebookSessions.esm.js.map +1 -0
  116. package/dist/hooks/notebooks/useRenameNotebook.esm.js +19 -0
  117. package/dist/hooks/notebooks/useRenameNotebook.esm.js.map +1 -0
  118. package/dist/hooks/notebooks/useUploadDocument.esm.js +28 -0
  119. package/dist/hooks/notebooks/useUploadDocument.esm.js.map +1 -0
  120. package/dist/hooks/toolCallsCacheStore.esm.js +61 -0
  121. package/dist/hooks/toolCallsCacheStore.esm.js.map +1 -0
  122. package/dist/hooks/useAllModels.esm.js +20 -0
  123. package/dist/hooks/useAllModels.esm.js.map +1 -0
  124. package/dist/hooks/useAutoScroll.esm.js +78 -0
  125. package/dist/hooks/useAutoScroll.esm.js.map +1 -0
  126. package/dist/hooks/useBackstageUserIdentity.esm.js +14 -0
  127. package/dist/hooks/useBackstageUserIdentity.esm.js.map +1 -0
  128. package/dist/hooks/useBufferedMessages.esm.js +27 -0
  129. package/dist/hooks/useBufferedMessages.esm.js.map +1 -0
  130. package/dist/hooks/useCaptureFeedback.esm.js +21 -0
  131. package/dist/hooks/useCaptureFeedback.esm.js.map +1 -0
  132. package/dist/hooks/useConversationMessages.esm.js +544 -0
  133. package/dist/hooks/useConversationMessages.esm.js.map +1 -0
  134. package/dist/hooks/useConversations.esm.js +25 -0
  135. package/dist/hooks/useConversations.esm.js.map +1 -0
  136. package/dist/hooks/useCreateCoversationMessage.esm.js +33 -0
  137. package/dist/hooks/useCreateCoversationMessage.esm.js.map +1 -0
  138. package/dist/hooks/useDeleteConversation.esm.js +39 -0
  139. package/dist/hooks/useDeleteConversation.esm.js.map +1 -0
  140. package/dist/hooks/useDisplayModeSettings.esm.js +57 -0
  141. package/dist/hooks/useDisplayModeSettings.esm.js.map +1 -0
  142. package/dist/hooks/useFeedbackActions.esm.js +275 -0
  143. package/dist/hooks/useFeedbackActions.esm.js.map +1 -0
  144. package/dist/hooks/useFeedbackState.esm.js +93 -0
  145. package/dist/hooks/useFeedbackState.esm.js.map +1 -0
  146. package/dist/hooks/useFeedbackStatus.esm.js +14 -0
  147. package/dist/hooks/useFeedbackStatus.esm.js.map +1 -0
  148. package/dist/hooks/useIsMobile.esm.js +14 -0
  149. package/dist/hooks/useIsMobile.esm.js.map +1 -0
  150. package/dist/hooks/useLastOpenedConversation.esm.js +51 -0
  151. package/dist/hooks/useLastOpenedConversation.esm.js.map +1 -0
  152. package/dist/hooks/useLightspeedDeletePermission.esm.js +12 -0
  153. package/dist/hooks/useLightspeedDeletePermission.esm.js.map +1 -0
  154. package/dist/hooks/useLightspeedDrawerContext.esm.js +15 -0
  155. package/dist/hooks/useLightspeedDrawerContext.esm.js.map +1 -0
  156. package/dist/hooks/useLightspeedProviderState.esm.js +277 -0
  157. package/dist/hooks/useLightspeedProviderState.esm.js.map +1 -0
  158. package/dist/hooks/useLightspeedUpdatePermission.esm.js +12 -0
  159. package/dist/hooks/useLightspeedUpdatePermission.esm.js.map +1 -0
  160. package/dist/hooks/useLightspeedViewPermission.esm.js +18 -0
  161. package/dist/hooks/useLightspeedViewPermission.esm.js.map +1 -0
  162. package/dist/hooks/useNotebookConversationIds.esm.js +19 -0
  163. package/dist/hooks/useNotebookConversationIds.esm.js.map +1 -0
  164. package/dist/hooks/useNotebookWelcomePrompts.esm.js +14 -0
  165. package/dist/hooks/useNotebookWelcomePrompts.esm.js.map +1 -0
  166. package/dist/hooks/usePinnedChatsSettings.esm.js +118 -0
  167. package/dist/hooks/usePinnedChatsSettings.esm.js.map +1 -0
  168. package/dist/hooks/useQuestionValidation.esm.js +16 -0
  169. package/dist/hooks/useQuestionValidation.esm.js.map +1 -0
  170. package/dist/hooks/useRenameConversation.esm.js +44 -0
  171. package/dist/hooks/useRenameConversation.esm.js.map +1 -0
  172. package/dist/hooks/useSortSettings.esm.js +60 -0
  173. package/dist/hooks/useSortSettings.esm.js.map +1 -0
  174. package/dist/hooks/useStopConversation.esm.js +18 -0
  175. package/dist/hooks/useStopConversation.esm.js.map +1 -0
  176. package/dist/hooks/useTranslation.esm.js +7 -0
  177. package/dist/hooks/useTranslation.esm.js.map +1 -0
  178. package/dist/hooks/useWelcomePrompts.esm.js +36 -0
  179. package/dist/hooks/useWelcomePrompts.esm.js.map +1 -0
  180. package/dist/images/bot-avatar-dark.svg +4 -0
  181. package/dist/images/bot-avatar.svg +4 -0
  182. package/dist/images/permission-required.svg +319 -0
  183. package/dist/images/user-avatar.svg +4 -0
  184. package/dist/index.d.ts +113 -0
  185. package/dist/index.esm.js +137 -0
  186. package/dist/index.esm.js.map +1 -0
  187. package/dist/intelligent-assistant-fab-module.d.ts +4 -0
  188. package/dist/intelligent-assistant-fab-module.esm.js +2 -0
  189. package/dist/intelligent-assistant-fab-module.esm.js.map +1 -0
  190. package/dist/intelligent-assistant-translations-module.d.ts +4 -0
  191. package/dist/intelligent-assistant-translations-module.esm.js +2 -0
  192. package/dist/intelligent-assistant-translations-module.esm.js.map +1 -0
  193. package/dist/legacy.d.ts +75 -0
  194. package/dist/legacy.esm.js +13 -0
  195. package/dist/legacy.esm.js.map +1 -0
  196. package/dist/plugin.esm.js +84 -0
  197. package/dist/plugin.esm.js.map +1 -0
  198. package/dist/routes.esm.js +23 -0
  199. package/dist/routes.esm.js.map +1 -0
  200. package/dist/translations/de.esm.js +278 -0
  201. package/dist/translations/de.esm.js.map +1 -0
  202. package/dist/translations/es.esm.js +278 -0
  203. package/dist/translations/es.esm.js.map +1 -0
  204. package/dist/translations/fr.esm.js +278 -0
  205. package/dist/translations/fr.esm.js.map +1 -0
  206. package/dist/translations/index.esm.js +16 -0
  207. package/dist/translations/index.esm.js.map +1 -0
  208. package/dist/translations/it.esm.js +278 -0
  209. package/dist/translations/it.esm.js.map +1 -0
  210. package/dist/translations/ja.esm.js +278 -0
  211. package/dist/translations/ja.esm.js.map +1 -0
  212. package/dist/translations/ref.esm.js +315 -0
  213. package/dist/translations/ref.esm.js.map +1 -0
  214. package/dist/types.esm.js +9 -0
  215. package/dist/types.esm.js.map +1 -0
  216. package/dist/utils/attachment-utils.esm.js +30 -0
  217. package/dist/utils/attachment-utils.esm.js.map +1 -0
  218. package/dist/utils/formatToolResponseForMarkdown.esm.js +98 -0
  219. package/dist/utils/formatToolResponseForMarkdown.esm.js.map +1 -0
  220. package/dist/utils/generateClassName.esm.js +12 -0
  221. package/dist/utils/generateClassName.esm.js.map +1 -0
  222. package/dist/utils/lightspeed-chatbox-utils.esm.js +232 -0
  223. package/dist/utils/lightspeed-chatbox-utils.esm.js.map +1 -0
  224. package/dist/utils/notebook-upload-utils.esm.js +48 -0
  225. package/dist/utils/notebook-upload-utils.esm.js.map +1 -0
  226. package/dist/utils/notebooks-utils.esm.js +25 -0
  227. package/dist/utils/notebooks-utils.esm.js.map +1 -0
  228. package/dist/utils/prompt-utils.esm.js +17 -0
  229. package/dist/utils/prompt-utils.esm.js.map +1 -0
  230. package/dist/utils/queryClient.esm.js +6 -0
  231. package/dist/utils/queryClient.esm.js.map +1 -0
  232. package/dist/utils/reasoningParser.esm.js +33 -0
  233. package/dist/utils/reasoningParser.esm.js.map +1 -0
  234. package/dist/utils/toolCallMapper.esm.js +15 -0
  235. package/dist/utils/toolCallMapper.esm.js.map +1 -0
  236. package/dist/utils/user-utils.esm.js +7 -0
  237. package/dist/utils/user-utils.esm.js.map +1 -0
  238. package/package.json +182 -0
@@ -0,0 +1,232 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { ChatbotFootnote } from '@patternfly/chatbot';
3
+ import { Spinner } from '@patternfly/react-core';
4
+ import { ThumbtackIcon } from '@patternfly/react-icons';
5
+ import { RhUiAiInfoIcon } from '@patternfly/react-icons/dist/esm/icons/rh-ui-ai-info-icon';
6
+
7
+ const getFootnoteProps = (t) => ({
8
+ label: t?.("footer.accuracy.label") || "Always review AI generated content prior to use."
9
+ });
10
+ const ChatbotFootnoteWithIcon = ({ label }) => /* @__PURE__ */ jsxs(
11
+ "div",
12
+ {
13
+ style: {
14
+ display: "flex",
15
+ alignItems: "center",
16
+ justifyContent: "center",
17
+ gap: "4px"
18
+ },
19
+ children: [
20
+ /* @__PURE__ */ jsx(RhUiAiInfoIcon, { style: { width: "14px", height: "14px", flexShrink: 0 } }),
21
+ /* @__PURE__ */ jsx(ChatbotFootnote, { label })
22
+ ]
23
+ }
24
+ );
25
+ const getTimestampVariablesString = (v) => {
26
+ if (v < 10) {
27
+ return `0${v}`;
28
+ }
29
+ return `${v}`;
30
+ };
31
+ const isBlankLine = (line) => !line.trim();
32
+ const isOrderedListLine = (line) => /^\s*\d+\.\s/.test(line);
33
+ const isBulletListLine = (line) => /^\s*[-*+]\s/.test(line) || /^\s*\u2022(?:\s+|\S|$)/u.test(line);
34
+ const escapeBulletListMarker = (line) => {
35
+ if (/^\s*\u2022/u.test(line)) {
36
+ return line;
37
+ }
38
+ return line.replace(/^(\s*)([*+-])(\s)/, "$1\\$2$3");
39
+ };
40
+ const escapeOrderedListMarker = (line) => line.replace(/^(\s*)(\d+)\.(\s)/, "$1$2\\.$3");
41
+ const foldListWithIntro = (s, isListItemLine, escapeListLine) => {
42
+ const lines = s.split("\n");
43
+ let firstListIdx = -1;
44
+ for (let i = 0; i < lines.length; i++) {
45
+ const line = lines[i];
46
+ if (line !== void 0 && isListItemLine(line)) {
47
+ firstListIdx = i;
48
+ break;
49
+ }
50
+ }
51
+ if (firstListIdx < 0) {
52
+ return s;
53
+ }
54
+ const intro = lines.slice(0, firstListIdx);
55
+ if (intro.some(isBlankLine)) {
56
+ return s;
57
+ }
58
+ const rest = lines.slice(firstListIdx);
59
+ const restItems = rest.filter((l) => !isBlankLine(l));
60
+ if (restItems.length === 0 || !restItems.every(isListItemLine)) {
61
+ return s;
62
+ }
63
+ const escaped = restItems.map(escapeListLine);
64
+ if (intro.length === 0) {
65
+ return escaped.join(" \n");
66
+ }
67
+ return `${intro.join(" \n")}
68
+ ${escaped.join(" \n")}`;
69
+ };
70
+ const foldOrderedListWithIntro = (s) => foldListWithIntro(s, isOrderedListLine, escapeOrderedListMarker);
71
+ const foldBulletListWithIntro = (s) => foldListWithIntro(s, isBulletListLine, escapeBulletListMarker);
72
+ const normalizeChatUserInput = (input) => {
73
+ let s = input.replace(/\r\n/g, "\n").trim();
74
+ if (!s) {
75
+ return s;
76
+ }
77
+ s = s.replace(/\n{3,}/g, "\n\n");
78
+ s = s.replace(/\n\n(?=\s*\d+\.\s)/gm, "\n");
79
+ s = s.replace(/\n\n(?=\s*[-*+]\s)/gm, "\n");
80
+ s = s.replace(/\n\n(?=\s*\u2022)/gm, "\n");
81
+ s = foldOrderedListWithIntro(s);
82
+ s = foldBulletListWithIntro(s);
83
+ return s.trim();
84
+ };
85
+ const getTimestamp = (unix_timestamp) => {
86
+ if (typeof unix_timestamp !== "number" || Number.isNaN(unix_timestamp)) {
87
+ console.error("Invalid Unix timestamp provided");
88
+ return "";
89
+ }
90
+ const a = new Date(unix_timestamp);
91
+ const month = getTimestampVariablesString(a.getMonth() + 1);
92
+ const year = a.getFullYear();
93
+ const date = getTimestampVariablesString(a.getDate());
94
+ const hour = getTimestampVariablesString(a.getHours());
95
+ const min = getTimestampVariablesString(a.getMinutes());
96
+ const sec = getTimestampVariablesString(a.getSeconds());
97
+ const time = `${date}/${month}/${year}, ${hour}:${min}:${sec}`;
98
+ return time;
99
+ };
100
+ const createMessage = ({
101
+ role,
102
+ name,
103
+ avatar,
104
+ isLoading = false,
105
+ content,
106
+ timestamp,
107
+ error,
108
+ sources,
109
+ toolCalls,
110
+ defaultUserName = "Guest"
111
+ }) => ({
112
+ role,
113
+ name: name || defaultUserName,
114
+ avatar,
115
+ isLoading,
116
+ content,
117
+ timestamp,
118
+ error,
119
+ sources,
120
+ toolCalls
121
+ });
122
+ const createUserMessage = (props) => createMessage({
123
+ ...props,
124
+ role: "user",
125
+ defaultUserName: props.defaultUserName
126
+ });
127
+ const createBotMessage = (props) => createMessage({
128
+ ...props,
129
+ role: "bot"
130
+ });
131
+ const getConversationsData = (conversation) => {
132
+ const [userMessage, botMessage] = conversation.messages || [];
133
+ return [
134
+ {
135
+ ...userMessage,
136
+ timestamp: getTimestamp(
137
+ conversation.started_at ? new Date(conversation.started_at).getTime() : Date.now()
138
+ )
139
+ },
140
+ {
141
+ ...botMessage,
142
+ timestamp: getTimestamp(
143
+ conversation.completed_at ? new Date(conversation.completed_at).getTime() : Date.now()
144
+ ),
145
+ referenced_documents: botMessage?.referenced_documents ?? []
146
+ }
147
+ ];
148
+ };
149
+ const transformDocumentsToSources = (referenced_documents) => {
150
+ if (!referenced_documents || referenced_documents?.length === 0) {
151
+ return void 0;
152
+ }
153
+ return {
154
+ sources: referenced_documents.map((doc) => ({
155
+ body: doc.doc_description,
156
+ title: doc.doc_title,
157
+ link: doc?.doc_url,
158
+ isExternal: !!doc?.doc_url
159
+ }))
160
+ };
161
+ };
162
+ const sortConversations = (messages, sortOption) => {
163
+ return [...messages].sort((a, b) => {
164
+ const aTopicSummary = a.topic_summary || "";
165
+ const bTopicSummary = b.topic_summary || "";
166
+ switch (sortOption) {
167
+ case "oldest":
168
+ return a.last_message_timestamp - b.last_message_timestamp;
169
+ case "alphabeticalAsc":
170
+ return aTopicSummary.localeCompare(bTopicSummary, void 0, {
171
+ sensitivity: "base"
172
+ });
173
+ case "alphabeticalDesc":
174
+ return bTopicSummary.localeCompare(aTopicSummary, void 0, {
175
+ sensitivity: "base"
176
+ });
177
+ case "newest":
178
+ default:
179
+ return b.last_message_timestamp - a.last_message_timestamp;
180
+ }
181
+ });
182
+ };
183
+ const getCategorizeMessages = (messages, pinnedChats, addProps, t, sortOption = "newest") => {
184
+ const pinnedChatsKey = t?.("conversation.category.pinnedChats") || "Pinned chats";
185
+ const recentKey = t?.("conversation.category.recent") || "Chats";
186
+ const categorizedMessages = {
187
+ [pinnedChatsKey]: [],
188
+ [recentKey]: []
189
+ };
190
+ const sortedMessages = sortConversations(messages, sortOption);
191
+ sortedMessages.forEach((c) => {
192
+ const message = {
193
+ id: c.conversation_id,
194
+ text: c.topic_summary ?? "",
195
+ icon: c.topic_summary ? void 0 : /* @__PURE__ */ jsx(Spinner, { size: "sm" }),
196
+ label: t?.("message.options.label") || "Options",
197
+ additionalProps: {
198
+ "aria-label": t?.("aria.options.label") || "Options"
199
+ },
200
+ ...addProps(c)
201
+ };
202
+ if (pinnedChats.includes(c.conversation_id)) {
203
+ categorizedMessages[pinnedChatsKey].push({
204
+ ...message,
205
+ icon: /* @__PURE__ */ jsx(
206
+ ThumbtackIcon,
207
+ {
208
+ style: {
209
+ width: "1rem",
210
+ height: "1rem",
211
+ display: "flex",
212
+ alignItems: "center"
213
+ }
214
+ }
215
+ )
216
+ });
217
+ } else {
218
+ categorizedMessages[recentKey].push(message);
219
+ }
220
+ });
221
+ const filteredCategories = Object.keys(categorizedMessages).reduce(
222
+ (result, category) => {
223
+ result[category] = categorizedMessages[category];
224
+ return result;
225
+ },
226
+ {}
227
+ );
228
+ return filteredCategories;
229
+ };
230
+
231
+ export { ChatbotFootnoteWithIcon, createBotMessage, createMessage, createUserMessage, getCategorizeMessages, getConversationsData, getFootnoteProps, getTimestamp, getTimestampVariablesString, normalizeChatUserInput, transformDocumentsToSources };
232
+ //# sourceMappingURL=lightspeed-chatbox-utils.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lightspeed-chatbox-utils.esm.js","sources":["../../src/utils/lightspeed-chatbox-utils.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 */\nimport {\n ChatbotFootnote,\n Conversation,\n SourcesCardProps,\n} from '@patternfly/chatbot';\nimport { Spinner } from '@patternfly/react-core';\nimport { ThumbtackIcon } from '@patternfly/react-icons';\nimport { RhUiAiInfoIcon } from '@patternfly/react-icons/dist/esm/icons/rh-ui-ai-info-icon';\n\nimport {\n BaseMessage,\n ConversationList,\n ConversationSummary,\n LCSConversation,\n ReferencedDocument,\n ReferencedDocuments,\n ToolCall,\n} from '../types';\n\nexport const getFootnoteProps = (\n t?: (key: string, params?: any) => string,\n) => ({\n label:\n t?.('footer.accuracy.label') ||\n 'Always review AI generated content prior to use.',\n});\n\nexport const ChatbotFootnoteWithIcon = ({ label }: { label: string }) => (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '4px',\n }}\n >\n <RhUiAiInfoIcon style={{ width: '14px', height: '14px', flexShrink: 0 }} />\n <ChatbotFootnote label={label} />\n </div>\n);\n\nexport const getTimestampVariablesString = (v: number) => {\n if (v < 10) {\n return `0${v}`;\n }\n return `${v}`;\n};\n\nconst isBlankLine = (line: string) => !line.trim();\n\n/** Ordered list item at line start (CommonMark), ignoring leading spaces. */\nconst isOrderedListLine = (line: string) => /^\\s*\\d+\\.\\s/.test(line);\n\n/** ASCII bullets; also U+2022 (•) — not a CommonMark marker, but users paste it as a list. */\nconst isBulletListLine = (line: string) =>\n /^\\s*[-*+]\\s/.test(line) || /^\\s*\\u2022(?:\\s+|\\S|$)/u.test(line);\n\nconst escapeBulletListMarker = (line: string) => {\n if (/^\\s*\\u2022/u.test(line)) {\n return line;\n }\n return line.replace(/^(\\s*)([*+-])(\\s)/, '$1\\\\$2$3');\n};\n\nconst escapeOrderedListMarker = (line: string) =>\n line.replace(/^(\\s*)(\\d+)\\.(\\s)/, '$1$2\\\\.$3');\n\n/**\n * When intro lines (no blank lines among them) are followed by a contiguous run of\n * list lines, join intro + list into one Markdown paragraph using hard breaks and\n * per-line escaping so the block does not split awkwardly in the chat UI.\n */\nconst foldListWithIntro = (\n s: string,\n isListItemLine: (line: string) => boolean,\n escapeListLine: (line: string) => string,\n): string => {\n const lines = s.split('\\n');\n let firstListIdx = -1;\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (line !== undefined && isListItemLine(line)) {\n firstListIdx = i;\n break;\n }\n }\n if (firstListIdx < 0) {\n return s;\n }\n\n const intro = lines.slice(0, firstListIdx);\n if (intro.some(isBlankLine)) {\n return s;\n }\n\n const rest = lines.slice(firstListIdx);\n const restItems = rest.filter(l => !isBlankLine(l));\n if (restItems.length === 0 || !restItems.every(isListItemLine)) {\n return s;\n }\n\n const escaped = restItems.map(escapeListLine);\n if (intro.length === 0) {\n return escaped.join(' \\n');\n }\n return `${intro.join(' \\n')} \\n${escaped.join(' \\n')}`;\n};\n\n/**\n * Paragraph + ordered list (even with a single newline) parses as two blocks; merge\n * intro + contiguous numbered lines into one paragraph using hard breaks (two spaces\n * + newline) and escaped `1.` markers so Markdown stays a single block.\n */\nconst foldOrderedListWithIntro = (s: string) =>\n foldListWithIntro(s, isOrderedListLine, escapeOrderedListMarker);\n\n/** Same idea as ordered lists for intro + bullet lines. */\nconst foldBulletListWithIntro = (s: string) =>\n foldListWithIntro(s, isBulletListLine, escapeBulletListMarker);\n\n/**\n * Trims user chat input and reduces blank lines that split Markdown blocks\n * (e.g. paragraph + blank line + ordered list) so PatternFly renders one user bubble.\n */\nexport const normalizeChatUserInput = (input: string): string => {\n let s = input.replace(/\\r\\n/g, '\\n').trim();\n if (!s) {\n return s;\n }\n s = s.replace(/\\n{3,}/g, '\\n\\n');\n s = s.replace(/\\n\\n(?=\\s*\\d+\\.\\s)/gm, '\\n');\n s = s.replace(/\\n\\n(?=\\s*[-*+]\\s)/gm, '\\n');\n s = s.replace(/\\n\\n(?=\\s*\\u2022)/gm, '\\n');\n s = foldOrderedListWithIntro(s);\n s = foldBulletListWithIntro(s);\n return s.trim();\n};\n\nexport const getTimestamp = (unix_timestamp: number) => {\n if (typeof unix_timestamp !== 'number' || Number.isNaN(unix_timestamp)) {\n // eslint-disable-next-line no-console\n console.error('Invalid Unix timestamp provided');\n return '';\n }\n\n const a = new Date(unix_timestamp);\n const month = getTimestampVariablesString(a.getMonth() + 1);\n const year = a.getFullYear();\n const date = getTimestampVariablesString(a.getDate());\n const hour = getTimestampVariablesString(a.getHours());\n const min = getTimestampVariablesString(a.getMinutes());\n const sec = getTimestampVariablesString(a.getSeconds());\n const time = `${date}/${month}/${year}, ${hour}:${min}:${sec}`;\n return time;\n};\n\nexport const splitJsonStrings = (jsonString: string): string[] => {\n const chunks = jsonString.split('}{');\n\n if (chunks.length <= 1) {\n return [jsonString];\n }\n\n return chunks.map((chunk, index, arr) => {\n if (index === 0) {\n return `${chunk}}`;\n } else if (index === arr.length - 1) {\n return `{${chunk}`;\n }\n return `{${chunk}}`;\n });\n};\n\ntype MessageProps = {\n content: string;\n timestamp: string;\n name?: string;\n avatar?: string | any;\n isLoading?: boolean;\n error?: {\n title: string;\n };\n sources?: SourcesCardProps;\n toolCalls?: ToolCall[];\n};\n\nexport const createMessage = ({\n role,\n name,\n avatar,\n isLoading = false,\n content,\n timestamp,\n error,\n sources,\n toolCalls,\n defaultUserName = 'Guest',\n}: MessageProps & { role: 'user' | 'bot'; defaultUserName?: string }) => ({\n role,\n name: name || defaultUserName,\n avatar,\n isLoading,\n content,\n timestamp,\n error,\n sources,\n toolCalls,\n});\n\nexport const createUserMessage = (\n props: MessageProps & { defaultUserName?: string },\n) =>\n createMessage({\n ...props,\n role: 'user',\n defaultUserName: props.defaultUserName,\n });\n\nexport const createBotMessage = (props: MessageProps) =>\n createMessage({\n ...props,\n role: 'bot',\n });\n\nexport const getConversationsData = (\n conversation: LCSConversation,\n): [BaseMessage, BaseMessage] => {\n const [userMessage, botMessage] = conversation.messages || [];\n return [\n {\n ...userMessage,\n timestamp: getTimestamp(\n conversation.started_at\n ? new Date(conversation.started_at).getTime()\n : Date.now(),\n ),\n },\n {\n ...botMessage,\n timestamp: getTimestamp(\n conversation.completed_at\n ? new Date(conversation.completed_at).getTime()\n : Date.now(),\n ),\n referenced_documents: botMessage?.referenced_documents ?? [],\n },\n ];\n};\n\nexport const transformDocumentsToSources = (\n referenced_documents: ReferencedDocuments,\n): SourcesCardProps | undefined => {\n if (!referenced_documents || referenced_documents?.length === 0) {\n return undefined;\n }\n return {\n sources: referenced_documents.map((doc: ReferencedDocument) => ({\n body: doc.doc_description,\n title: doc.doc_title,\n link: doc?.doc_url,\n isExternal: !!doc?.doc_url,\n })),\n };\n};\n\nexport type SortOption =\n | 'newest'\n | 'oldest'\n | 'alphabeticalAsc'\n | 'alphabeticalDesc';\n\nconst sortConversations = (\n messages: ConversationList,\n sortOption: SortOption,\n): ConversationList => {\n return [...messages].sort((a, b) => {\n const aTopicSummary = a.topic_summary || '';\n const bTopicSummary = b.topic_summary || '';\n switch (sortOption) {\n case 'oldest':\n return a.last_message_timestamp - b.last_message_timestamp;\n case 'alphabeticalAsc':\n return aTopicSummary.localeCompare(bTopicSummary, undefined, {\n sensitivity: 'base',\n });\n case 'alphabeticalDesc':\n return bTopicSummary.localeCompare(aTopicSummary, undefined, {\n sensitivity: 'base',\n });\n case 'newest':\n default:\n return b.last_message_timestamp - a.last_message_timestamp;\n }\n });\n};\n\nexport const getCategorizeMessages = (\n messages: ConversationList,\n pinnedChats: string[],\n addProps: (c: ConversationSummary) => { [k: string]: any },\n t?: (key: string, params?: any) => string,\n sortOption: SortOption = 'newest',\n): { [k: string]: Conversation[] } => {\n const pinnedChatsKey =\n t?.('conversation.category.pinnedChats') || 'Pinned chats';\n const recentKey = t?.('conversation.category.recent') || 'Chats';\n const categorizedMessages: { [k: string]: Conversation[] } = {\n [pinnedChatsKey]: [],\n [recentKey]: [],\n };\n const sortedMessages = sortConversations(messages, sortOption);\n sortedMessages.forEach(c => {\n const message: Conversation = {\n id: c.conversation_id,\n text: c.topic_summary ?? '',\n icon: c.topic_summary ? undefined : <Spinner size=\"sm\" />,\n label: t?.('message.options.label') || 'Options',\n additionalProps: {\n 'aria-label': t?.('aria.options.label') || 'Options',\n },\n ...addProps(c),\n };\n\n if (pinnedChats.includes(c.conversation_id)) {\n categorizedMessages[pinnedChatsKey].push({\n ...message,\n icon: (\n <ThumbtackIcon\n style={{\n width: '1rem',\n height: '1rem',\n display: 'flex',\n alignItems: 'center',\n }}\n />\n ),\n });\n } else {\n categorizedMessages[recentKey].push(message);\n }\n });\n\n const filteredCategories = Object.keys(categorizedMessages).reduce(\n (result, category) => {\n result[category] = categorizedMessages[category];\n return result;\n },\n {} as any,\n );\n\n return filteredCategories;\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import { NOTEBOOK_ALLOWED_EXTENSIONS, NOTEBOOK_MAX_FILES, NOTEBOOK_MAX_FILE_SIZE_BYTES } from '../const.esm.js';
2
+
3
+ const getAllowedExtensions = () => Object.values(NOTEBOOK_ALLOWED_EXTENSIONS).flat();
4
+ const getFileExtension = (fileName) => {
5
+ const lastDot = fileName.lastIndexOf(".");
6
+ return lastDot >= 0 ? fileName.slice(lastDot).toLowerCase() : "";
7
+ };
8
+ const validateFileType = (file) => {
9
+ const ext = getFileExtension(file.name);
10
+ return getAllowedExtensions().includes(ext);
11
+ };
12
+ const validateFileSize = (file) => file.size <= NOTEBOOK_MAX_FILE_SIZE_BYTES;
13
+ const validateFileCount = (existingCount, newCount) => existingCount + newCount <= NOTEBOOK_MAX_FILES;
14
+ const validateFiles = (files, existingCount = 0) => {
15
+ const errors = [];
16
+ const valid = [];
17
+ if (!validateFileCount(existingCount, files.length)) {
18
+ errors.push("notebook.upload.error.tooManyFiles");
19
+ return { valid: [], errors };
20
+ }
21
+ const oversizedFiles = [];
22
+ const unsupportedFiles = [];
23
+ for (const file of files) {
24
+ let isValid = true;
25
+ if (!validateFileType(file)) {
26
+ unsupportedFiles.push(file.name);
27
+ isValid = false;
28
+ }
29
+ if (!validateFileSize(file)) {
30
+ oversizedFiles.push(file.name);
31
+ isValid = false;
32
+ }
33
+ if (isValid) {
34
+ valid.push(file);
35
+ }
36
+ }
37
+ if (unsupportedFiles.length > 0) {
38
+ errors.push("notebook.upload.error.unsupportedType");
39
+ }
40
+ if (oversizedFiles.length > 0) {
41
+ errors.push("notebook.upload.error.fileTooLarge");
42
+ }
43
+ return { valid, errors };
44
+ };
45
+ const getNotebookAcceptedFileTypes = () => NOTEBOOK_ALLOWED_EXTENSIONS;
46
+
47
+ export { getNotebookAcceptedFileTypes, validateFileCount, validateFileSize, validateFileType, validateFiles };
48
+ //# sourceMappingURL=notebook-upload-utils.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notebook-upload-utils.esm.js","sources":["../../src/utils/notebook-upload-utils.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 {\n NOTEBOOK_ALLOWED_EXTENSIONS,\n NOTEBOOK_MAX_FILE_SIZE_BYTES,\n NOTEBOOK_MAX_FILES,\n} from '../const';\n\nconst getAllowedExtensions = (): string[] =>\n Object.values(NOTEBOOK_ALLOWED_EXTENSIONS).flat();\n\nconst getFileExtension = (fileName: string): string => {\n const lastDot = fileName.lastIndexOf('.');\n return lastDot >= 0 ? fileName.slice(lastDot).toLowerCase() : '';\n};\n\nexport type FileValidationResult = {\n valid: File[];\n errors: string[];\n};\n\nexport const validateFileType = (file: File): boolean => {\n const ext = getFileExtension(file.name);\n return getAllowedExtensions().includes(ext);\n};\n\nexport const validateFileSize = (file: File): boolean =>\n file.size <= NOTEBOOK_MAX_FILE_SIZE_BYTES;\n\nexport const validateFileCount = (\n existingCount: number,\n newCount: number,\n): boolean => existingCount + newCount <= NOTEBOOK_MAX_FILES;\n\nexport const validateFiles = (\n files: File[],\n existingCount: number = 0,\n): FileValidationResult => {\n const errors: string[] = [];\n const valid: File[] = [];\n\n if (!validateFileCount(existingCount, files.length)) {\n errors.push('notebook.upload.error.tooManyFiles');\n return { valid: [], errors };\n }\n\n const oversizedFiles: string[] = [];\n const unsupportedFiles: string[] = [];\n\n for (const file of files) {\n let isValid = true;\n\n if (!validateFileType(file)) {\n unsupportedFiles.push(file.name);\n isValid = false;\n }\n\n if (!validateFileSize(file)) {\n oversizedFiles.push(file.name);\n isValid = false;\n }\n\n if (isValid) {\n valid.push(file);\n }\n }\n\n if (unsupportedFiles.length > 0) {\n errors.push('notebook.upload.error.unsupportedType');\n }\n\n if (oversizedFiles.length > 0) {\n errors.push('notebook.upload.error.fileTooLarge');\n }\n\n return { valid, errors };\n};\n\nexport const getNotebookAcceptedFileTypes = (): Record<string, string[]> =>\n NOTEBOOK_ALLOWED_EXTENSIONS;\n"],"names":[],"mappings":";;AAsBA,MAAM,uBAAuB,MAC3B,MAAA,CAAO,MAAA,CAAO,2BAA2B,EAAE,IAAA,EAAK;AAElD,MAAM,gBAAA,GAAmB,CAAC,QAAA,KAA6B;AACrD,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,WAAA,CAAY,GAAG,CAAA;AACxC,EAAA,OAAO,WAAW,CAAA,GAAI,QAAA,CAAS,MAAM,OAAO,CAAA,CAAE,aAAY,GAAI,EAAA;AAChE,CAAA;AAOO,MAAM,gBAAA,GAAmB,CAAC,IAAA,KAAwB;AACvD,EAAA,MAAM,GAAA,GAAM,gBAAA,CAAiB,IAAA,CAAK,IAAI,CAAA;AACtC,EAAA,OAAO,oBAAA,EAAqB,CAAE,QAAA,CAAS,GAAG,CAAA;AAC5C;AAEO,MAAM,gBAAA,GAAmB,CAAC,IAAA,KAC/B,IAAA,CAAK,IAAA,IAAQ;AAER,MAAM,iBAAA,GAAoB,CAC/B,aAAA,EACA,QAAA,KACY,gBAAgB,QAAA,IAAY;AAEnC,MAAM,aAAA,GAAgB,CAC3B,KAAA,EACA,aAAA,GAAwB,CAAA,KACC;AACzB,EAAA,MAAM,SAAmB,EAAC;AAC1B,EAAA,MAAM,QAAgB,EAAC;AAEvB,EAAA,IAAI,CAAC,iBAAA,CAAkB,aAAA,EAAe,KAAA,CAAM,MAAM,CAAA,EAAG;AACnD,IAAA,MAAA,CAAO,KAAK,oCAAoC,CAAA;AAChD,IAAA,OAAO,EAAE,KAAA,EAAO,EAAC,EAAG,MAAA,EAAO;AAAA,EAC7B;AAEA,EAAA,MAAM,iBAA2B,EAAC;AAClC,EAAA,MAAM,mBAA6B,EAAC;AAEpC,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,IAAI,OAAA,GAAU,IAAA;AAEd,IAAA,IAAI,CAAC,gBAAA,CAAiB,IAAI,CAAA,EAAG;AAC3B,MAAA,gBAAA,CAAiB,IAAA,CAAK,KAAK,IAAI,CAAA;AAC/B,MAAA,OAAA,GAAU,KAAA;AAAA,IACZ;AAEA,IAAA,IAAI,CAAC,gBAAA,CAAiB,IAAI,CAAA,EAAG;AAC3B,MAAA,cAAA,CAAe,IAAA,CAAK,KAAK,IAAI,CAAA;AAC7B,MAAA,OAAA,GAAU,KAAA;AAAA,IACZ;AAEA,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,IACjB;AAAA,EACF;AAEA,EAAA,IAAI,gBAAA,CAAiB,SAAS,CAAA,EAAG;AAC/B,IAAA,MAAA,CAAO,KAAK,uCAAuC,CAAA;AAAA,EACrD;AAEA,EAAA,IAAI,cAAA,CAAe,SAAS,CAAA,EAAG;AAC7B,IAAA,MAAA,CAAO,KAAK,oCAAoC,CAAA;AAAA,EAClD;AAEA,EAAA,OAAO,EAAE,OAAO,MAAA,EAAO;AACzB;AAEO,MAAM,+BAA+B,MAC1C;;;;"}
@@ -0,0 +1,25 @@
1
+ const formatUpdatedLabel = (updatedAt, t) => {
2
+ const updatedDate = new Date(updatedAt);
3
+ if (Number.isNaN(updatedDate.getTime())) {
4
+ return updatedAt;
5
+ }
6
+ const now = /* @__PURE__ */ new Date();
7
+ const diffMs = now.getTime() - updatedDate.getTime();
8
+ const diffDays = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
9
+ if (diffDays <= 0) {
10
+ return t("notebooks.updated.today");
11
+ }
12
+ if (diffDays === 1) {
13
+ return t("notebooks.updated.yesterday");
14
+ }
15
+ if (diffDays < 7) {
16
+ return t("notebooks.updated.days", { days: diffDays });
17
+ }
18
+ return `${t("notebooks.updated.on")} ${updatedDate.toLocaleDateString(
19
+ void 0,
20
+ { month: "short", day: "numeric" }
21
+ )}`;
22
+ };
23
+
24
+ export { formatUpdatedLabel };
25
+ //# sourceMappingURL=notebooks-utils.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notebooks-utils.esm.js","sources":["../../src/utils/notebooks-utils.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 { TranslationFunction } from '@backstage/core-plugin-api/alpha';\n\nimport { intelligentAssistantTranslationRef } from '../translations/ref';\n\ntype TranslateFn = TranslationFunction<\n typeof intelligentAssistantTranslationRef.T\n>;\n\nexport const formatUpdatedLabel = (updatedAt: string, t: TranslateFn) => {\n const updatedDate = new Date(updatedAt);\n if (Number.isNaN(updatedDate.getTime())) {\n return updatedAt;\n }\n const now = new Date();\n const diffMs = now.getTime() - updatedDate.getTime();\n const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));\n if (diffDays <= 0) {\n return t('notebooks.updated.today');\n }\n if (diffDays === 1) {\n return t('notebooks.updated.yesterday');\n }\n if (diffDays < 7) {\n return t('notebooks.updated.days', { days: diffDays } as any);\n }\n return `${t('notebooks.updated.on')} ${updatedDate.toLocaleDateString(\n undefined,\n { month: 'short', day: 'numeric' },\n )}`;\n};\n"],"names":[],"mappings":"AAwBO,MAAM,kBAAA,GAAqB,CAAC,SAAA,EAAmB,CAAA,KAAmB;AACvE,EAAA,MAAM,WAAA,GAAc,IAAI,IAAA,CAAK,SAAS,CAAA;AACtC,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,WAAA,CAAY,OAAA,EAAS,CAAA,EAAG;AACvC,IAAA,OAAO,SAAA;AAAA,EACT;AACA,EAAA,MAAM,GAAA,uBAAU,IAAA,EAAK;AACrB,EAAA,MAAM,MAAA,GAAS,GAAA,CAAI,OAAA,EAAQ,GAAI,YAAY,OAAA,EAAQ;AACnD,EAAA,MAAM,WAAW,IAAA,CAAK,KAAA,CAAM,UAAU,GAAA,GAAO,EAAA,GAAK,KAAK,EAAA,CAAG,CAAA;AAC1D,EAAA,IAAI,YAAY,CAAA,EAAG;AACjB,IAAA,OAAO,EAAE,yBAAyB,CAAA;AAAA,EACpC;AACA,EAAA,IAAI,aAAa,CAAA,EAAG;AAClB,IAAA,OAAO,EAAE,6BAA6B,CAAA;AAAA,EACxC;AACA,EAAA,IAAI,WAAW,CAAA,EAAG;AAChB,IAAA,OAAO,CAAA,CAAE,wBAAA,EAA0B,EAAE,IAAA,EAAM,UAAiB,CAAA;AAAA,EAC9D;AACA,EAAA,OAAO,CAAA,EAAG,CAAA,CAAE,sBAAsB,CAAC,IAAI,WAAA,CAAY,kBAAA;AAAA,IACjD,MAAA;AAAA,IACA,EAAE,KAAA,EAAO,OAAA,EAAS,GAAA,EAAK,SAAA;AAAU,GAClC,CAAA,CAAA;AACH;;;;"}
@@ -0,0 +1,17 @@
1
+ const getRandomPrompts = (prompts, n) => {
2
+ const shuffled = prompts.slice().sort(() => 0.5 - Math.random());
3
+ return shuffled.slice(0, Math.min(n, prompts.length));
4
+ };
5
+ const getRandomSamplePrompts = (userPrompts = [], defaultPrompts = [], numberOfPrompts = 3) => {
6
+ const userCount = userPrompts.length;
7
+ if (userCount >= numberOfPrompts) {
8
+ return getRandomPrompts(userPrompts, numberOfPrompts);
9
+ }
10
+ const userSelected = getRandomPrompts(userPrompts, userCount);
11
+ const remaining = numberOfPrompts - userSelected.length;
12
+ const defaultSelected = getRandomPrompts(defaultPrompts, remaining);
13
+ return [...userSelected, ...defaultSelected];
14
+ };
15
+
16
+ export { getRandomSamplePrompts };
17
+ //# sourceMappingURL=prompt-utils.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-utils.esm.js","sources":["../../src/utils/prompt-utils.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 { SamplePrompts } from '../types';\n\nconst getRandomPrompts = (prompts: SamplePrompts, n: number) => {\n const shuffled = prompts.slice().sort(() => 0.5 - Math.random()); // NOSONAR\n return shuffled.slice(0, Math.min(n, prompts.length));\n};\n\nexport const getRandomSamplePrompts = (\n userPrompts: SamplePrompts = [],\n defaultPrompts: SamplePrompts = [],\n numberOfPrompts: number = 3,\n) => {\n const userCount = userPrompts.length;\n\n if (userCount >= numberOfPrompts) {\n return getRandomPrompts(userPrompts, numberOfPrompts);\n }\n const userSelected = getRandomPrompts(userPrompts, userCount);\n const remaining = numberOfPrompts - userSelected.length;\n const defaultSelected = getRandomPrompts(defaultPrompts, remaining);\n return [...userSelected, ...defaultSelected];\n};\n"],"names":[],"mappings":"AAiBA,MAAM,gBAAA,GAAmB,CAAC,OAAA,EAAwB,CAAA,KAAc;AAC9D,EAAA,MAAM,QAAA,GAAW,QAAQ,KAAA,EAAM,CAAE,KAAK,MAAM,GAAA,GAAM,IAAA,CAAK,MAAA,EAAQ,CAAA;AAC/D,EAAA,OAAO,QAAA,CAAS,MAAM,CAAA,EAAG,IAAA,CAAK,IAAI,CAAA,EAAG,OAAA,CAAQ,MAAM,CAAC,CAAA;AACtD,CAAA;AAEO,MAAM,sBAAA,GAAyB,CACpC,WAAA,GAA6B,IAC7B,cAAA,GAAgC,EAAC,EACjC,eAAA,GAA0B,CAAA,KACvB;AACH,EAAA,MAAM,YAAY,WAAA,CAAY,MAAA;AAE9B,EAAA,IAAI,aAAa,eAAA,EAAiB;AAChC,IAAA,OAAO,gBAAA,CAAiB,aAAa,eAAe,CAAA;AAAA,EACtD;AACA,EAAA,MAAM,YAAA,GAAe,gBAAA,CAAiB,WAAA,EAAa,SAAS,CAAA;AAC5D,EAAA,MAAM,SAAA,GAAY,kBAAkB,YAAA,CAAa,MAAA;AACjD,EAAA,MAAM,eAAA,GAAkB,gBAAA,CAAiB,cAAA,EAAgB,SAAS,CAAA;AAClE,EAAA,OAAO,CAAC,GAAG,YAAA,EAAc,GAAG,eAAe,CAAA;AAC7C;;;;"}
@@ -0,0 +1,6 @@
1
+ import { QueryClient } from '@tanstack/react-query';
2
+
3
+ const queryClient = new QueryClient();
4
+
5
+ export { queryClient as default };
6
+ //# sourceMappingURL=queryClient.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queryClient.esm.js","sources":["../../src/utils/queryClient.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 { QueryClient } from '@tanstack/react-query';\n\nconst queryClient = new QueryClient();\nexport default queryClient;\n"],"names":[],"mappings":";;AAkBA,MAAM,WAAA,GAAc,IAAI,WAAA;;;;"}
@@ -0,0 +1,33 @@
1
+ const parseReasoning = (content) => {
2
+ if (!content) {
3
+ return {
4
+ reasoning: null,
5
+ mainContent: content,
6
+ hasReasoning: false,
7
+ isReasoningInProgress: false
8
+ };
9
+ }
10
+ const lastOpenIndex = content.lastIndexOf("<think>");
11
+ const lastCloseIndex = content.lastIndexOf("</think>");
12
+ const isReasoningInProgress = lastOpenIndex !== -1 && lastOpenIndex > lastCloseIndex;
13
+ const reasoningPattern = /<think>(.*?)<\/think>/gs;
14
+ const matches = Array.from(content.matchAll(reasoningPattern));
15
+ const extractedReasoning = matches.map((m) => (m[1] || "").trim()).filter((reasoning) => reasoning.length > 0);
16
+ if (isReasoningInProgress && lastOpenIndex !== -1) {
17
+ const partial = content.substring(lastOpenIndex + "<think>".length).trim();
18
+ if (partial.length > 0) {
19
+ extractedReasoning.push(partial);
20
+ }
21
+ }
22
+ const mainContent = content.replaceAll(reasoningPattern, "").trim();
23
+ const hasValidReasoning = extractedReasoning.length > 0;
24
+ return {
25
+ reasoning: hasValidReasoning ? extractedReasoning.join("\n\n") : null,
26
+ mainContent: isReasoningInProgress ? "" : mainContent,
27
+ hasReasoning: hasValidReasoning,
28
+ isReasoningInProgress
29
+ };
30
+ };
31
+
32
+ export { parseReasoning };
33
+ //# sourceMappingURL=reasoningParser.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reasoningParser.esm.js","sources":["../../src/utils/reasoningParser.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\n/**\n * Parses a message content to extract redacted reasoning and main content.\n * Messages from models with deep thinking support may contain:\n * <think>Some reasoning...</think>Main response\n *\n * @param content - The message content that may contain reasoning tags\n * @returns An object with the extracted reasoning and cleaned main content\n */\nexport interface ParsedReasoning {\n reasoning: string | null;\n mainContent: string;\n hasReasoning: boolean;\n isReasoningInProgress: boolean;\n}\n\nexport const parseReasoning = (content: string): ParsedReasoning => {\n if (!content) {\n return {\n reasoning: null,\n mainContent: content,\n hasReasoning: false,\n isReasoningInProgress: false,\n };\n }\n\n const lastOpenIndex = content.lastIndexOf('<think>');\n const lastCloseIndex = content.lastIndexOf('</think>');\n\n const isReasoningInProgress =\n lastOpenIndex !== -1 && lastOpenIndex > lastCloseIndex;\n\n const reasoningPattern = /<think>(.*?)<\\/think>/gs;\n const matches = Array.from(content.matchAll(reasoningPattern));\n\n const extractedReasoning = matches\n .map(m => (m[1] || '').trim())\n .filter(reasoning => reasoning.length > 0);\n\n if (isReasoningInProgress && lastOpenIndex !== -1) {\n const partial = content.substring(lastOpenIndex + '<think>'.length).trim();\n if (partial.length > 0) {\n extractedReasoning.push(partial);\n }\n }\n\n const mainContent = content.replaceAll(reasoningPattern, '').trim();\n\n const hasValidReasoning = extractedReasoning.length > 0;\n\n return {\n reasoning: hasValidReasoning ? extractedReasoning.join('\\n\\n') : null,\n mainContent: isReasoningInProgress ? '' : mainContent,\n hasReasoning: hasValidReasoning,\n isReasoningInProgress: isReasoningInProgress,\n };\n};\n"],"names":[],"mappings":"AA+BO,MAAM,cAAA,GAAiB,CAAC,OAAA,KAAqC;AAClE,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAO;AAAA,MACL,SAAA,EAAW,IAAA;AAAA,MACX,WAAA,EAAa,OAAA;AAAA,MACb,YAAA,EAAc,KAAA;AAAA,MACd,qBAAA,EAAuB;AAAA,KACzB;AAAA,EACF;AAEA,EAAA,MAAM,aAAA,GAAgB,OAAA,CAAQ,WAAA,CAAY,SAAS,CAAA;AACnD,EAAA,MAAM,cAAA,GAAiB,OAAA,CAAQ,WAAA,CAAY,UAAU,CAAA;AAErD,EAAA,MAAM,qBAAA,GACJ,aAAA,KAAkB,EAAA,IAAM,aAAA,GAAgB,cAAA;AAE1C,EAAA,MAAM,gBAAA,GAAmB,yBAAA;AACzB,EAAA,MAAM,UAAU,KAAA,CAAM,IAAA,CAAK,OAAA,CAAQ,QAAA,CAAS,gBAAgB,CAAC,CAAA;AAE7D,EAAA,MAAM,kBAAA,GAAqB,OAAA,CACxB,GAAA,CAAI,CAAA,CAAA,KAAA,CAAM,EAAE,CAAC,CAAA,IAAK,EAAA,EAAI,IAAA,EAAM,CAAA,CAC5B,MAAA,CAAO,CAAA,SAAA,KAAa,SAAA,CAAU,SAAS,CAAC,CAAA;AAE3C,EAAA,IAAI,qBAAA,IAAyB,kBAAkB,EAAA,EAAI;AACjD,IAAA,MAAM,UAAU,OAAA,CAAQ,SAAA,CAAU,gBAAgB,SAAA,CAAU,MAAM,EAAE,IAAA,EAAK;AACzE,IAAA,IAAI,OAAA,CAAQ,SAAS,CAAA,EAAG;AACtB,MAAA,kBAAA,CAAmB,KAAK,OAAO,CAAA;AAAA,IACjC;AAAA,EACF;AAEA,EAAA,MAAM,cAAc,OAAA,CAAQ,UAAA,CAAW,gBAAA,EAAkB,EAAE,EAAE,IAAA,EAAK;AAElE,EAAA,MAAM,iBAAA,GAAoB,mBAAmB,MAAA,GAAS,CAAA;AAEtD,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,iBAAA,GAAoB,kBAAA,CAAmB,IAAA,CAAK,MAAM,CAAA,GAAI,IAAA;AAAA,IACjE,WAAA,EAAa,wBAAwB,EAAA,GAAK,WAAA;AAAA,IAC1C,YAAA,EAAc,iBAAA;AAAA,IACd;AAAA,GACF;AACF;;;;"}
@@ -0,0 +1,15 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { ToolCallContent } from '../components/ToolCallContent.esm.js';
3
+
4
+ const mapToPatternFlyToolCall = (toolCall, t, role) => {
5
+ return {
6
+ titleText: t("toolCall.header", { toolName: toolCall.toolName }),
7
+ isLoading: toolCall.isLoading,
8
+ loadingText: t("toolCall.executing"),
9
+ expandableContent: !toolCall.isLoading ? /* @__PURE__ */ jsx(ToolCallContent, { toolCall, role }) : void 0,
10
+ actions: []
11
+ };
12
+ };
13
+
14
+ export { mapToPatternFlyToolCall };
15
+ //# sourceMappingURL=toolCallMapper.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolCallMapper.esm.js","sources":["../../src/utils/toolCallMapper.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 { ToolCallProps } from '@patternfly/chatbot';\n\nimport { ToolCallContent } from '../components/ToolCallContent';\nimport { ToolCall } from '../types';\n\n/**\n * Maps our internal ToolCall type to PatternFly's ToolCallProps\n */\nexport const mapToPatternFlyToolCall = (\n toolCall: ToolCall,\n t: (key: any, options?: any) => string,\n role?: 'user' | 'bot',\n): ToolCallProps => {\n return {\n titleText: t('toolCall.header' as any, { toolName: toolCall.toolName }),\n isLoading: toolCall.isLoading,\n loadingText: t('toolCall.executing'),\n expandableContent: !toolCall.isLoading ? (\n <ToolCallContent toolCall={toolCall} role={role} />\n ) : undefined,\n actions: [],\n };\n};\n\nexport default mapToPatternFlyToolCall;\n"],"names":[],"mappings":";;;AAwBO,MAAM,uBAAA,GAA0B,CACrC,QAAA,EACA,CAAA,EACA,IAAA,KACkB;AAClB,EAAA,OAAO;AAAA,IACL,WAAW,CAAA,CAAE,iBAAA,EAA0B,EAAE,QAAA,EAAU,QAAA,CAAS,UAAU,CAAA;AAAA,IACtE,WAAW,QAAA,CAAS,SAAA;AAAA,IACpB,WAAA,EAAa,EAAE,oBAAoB,CAAA;AAAA,IACnC,iBAAA,EAAmB,CAAC,QAAA,CAAS,SAAA,uBAC1B,eAAA,EAAA,EAAgB,QAAA,EAAoB,MAAY,CAAA,GAC/C,MAAA;AAAA,IACJ,SAAS;AAAC,GACZ;AACF;;;;"}
@@ -0,0 +1,7 @@
1
+ const isGuestUser = (user) => {
2
+ if (!user) return true;
3
+ return user.endsWith("/guest");
4
+ };
5
+
6
+ export { isGuestUser };
7
+ //# sourceMappingURL=user-utils.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-utils.esm.js","sources":["../../src/utils/user-utils.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\n/**\n * Check if the user is a guest user.\n * Guest users have userEntityRef like \"user:default/guest\" or \"user:development/guest\"\n *\n * @param user - The user entity ref (e.g., \"user:default/john\")\n * @returns true if the user is a guest user, false otherwise\n */\nexport const isGuestUser = (user: string | undefined): boolean => {\n if (!user) return true;\n return user.endsWith('/guest');\n};\n"],"names":[],"mappings":"AAuBO,MAAM,WAAA,GAAc,CAAC,IAAA,KAAsC;AAChE,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,EAAA,OAAO,IAAA,CAAK,SAAS,QAAQ,CAAA;AAC/B;;;;"}