@gooddata/sdk-ui-gen-ai 11.57.0 → 11.58.0-alpha.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 (150) hide show
  1. package/NOTICE +2321 -1760
  2. package/esm/components/GenAIChatDialogConnected.d.ts +1 -2
  3. package/esm/components/GenAIChatDialogConnected.d.ts.map +1 -1
  4. package/esm/components/GenAIChatDialogConnected.js +3 -9
  5. package/esm/components/Input.d.ts.map +1 -1
  6. package/esm/components/Input.js +8 -18
  7. package/esm/components/Messages.d.ts.map +1 -1
  8. package/esm/components/Messages.js +4 -20
  9. package/esm/components/customized/LandingQuestion.d.ts.map +1 -1
  10. package/esm/components/customized/LandingQuestion.js +1 -5
  11. package/esm/components/hooks/useEndpointCheck.d.ts.map +1 -1
  12. package/esm/components/hooks/useEndpointCheck.js +2 -2
  13. package/esm/components/messages/MessageScroller.d.ts +2 -2
  14. package/esm/components/messages/MessageScroller.d.ts.map +1 -1
  15. package/esm/components/messages/components/SemanticSearchTreeView.d.ts +4 -3
  16. package/esm/components/messages/components/SemanticSearchTreeView.d.ts.map +1 -1
  17. package/esm/components/messages/components/SemanticSearchTreeView.js +4 -4
  18. package/esm/components/messages/contents/drill/DrillSelectDropdownMenu.js +1 -1
  19. package/esm/components/messages/conversationContents/ConversationMultipartContent.js +1 -1
  20. package/esm/components/messages/conversationContents/ConversationSearchContent.d.ts.map +1 -1
  21. package/esm/components/messages/conversationContents/ConversationSearchContent.js +2 -8
  22. package/esm/components/messages/conversationContents/ConversationVisualisation.d.ts.map +1 -1
  23. package/esm/components/messages/conversationContents/ConversationVisualisation.js +63 -3
  24. package/esm/components/messages/conversationContents/ConversationVisualizationContent.js +2 -2
  25. package/esm/components/messages/conversationContents/SaveVisualizationDialog.js +1 -1
  26. package/esm/components/messages/useUserFeedback.d.ts +2 -2
  27. package/esm/components/messages/useUserFeedback.d.ts.map +1 -1
  28. package/esm/components/messages/useUserFeedback.js +17 -47
  29. package/esm/components/utils/modelCheckUtility.d.ts +1 -1
  30. package/esm/components/utils/modelCheckUtility.d.ts.map +1 -1
  31. package/esm/components/utils/modelCheckUtility.js +2 -2
  32. package/esm/index.d.ts +1 -1
  33. package/esm/index.d.ts.map +1 -1
  34. package/esm/index.js +1 -1
  35. package/esm/internal.d.ts +1 -2
  36. package/esm/internal.d.ts.map +1 -1
  37. package/esm/internal.js +1 -2
  38. package/esm/localization/bundles/en-US.localization-bundle.d.ts +0 -12
  39. package/esm/localization/bundles/en-US.localization-bundle.d.ts.map +1 -1
  40. package/esm/localization/bundles/en-US.localization-bundle.js +0 -12
  41. package/esm/model.d.ts +0 -209
  42. package/esm/model.d.ts.map +1 -1
  43. package/esm/model.js +0 -131
  44. package/esm/sdk-ui-gen-ai.d.ts +1 -159
  45. package/esm/store/localStorage.d.ts +0 -4
  46. package/esm/store/localStorage.d.ts.map +1 -1
  47. package/esm/store/localStorage.js +0 -41
  48. package/esm/store/messages/messagesSelectors.d.ts +1 -12
  49. package/esm/store/messages/messagesSelectors.d.ts.map +1 -1
  50. package/esm/store/messages/messagesSelectors.js +1 -6
  51. package/esm/store/messages/messagesSlice.d.ts +7 -34
  52. package/esm/store/messages/messagesSlice.d.ts.map +1 -1
  53. package/esm/store/messages/messagesSlice.js +159 -408
  54. package/esm/store/queues/queue.newMessage.js +2 -4
  55. package/esm/store/sideEffects/conversationSession.js +1 -1
  56. package/esm/store/sideEffects/onChatOpenSync.d.ts +0 -1
  57. package/esm/store/sideEffects/onChatOpenSync.d.ts.map +1 -1
  58. package/esm/store/sideEffects/onChatOpenSync.js +0 -6
  59. package/esm/store/sideEffects/onDefinitionReceivedTrigger.d.ts +2 -2
  60. package/esm/store/sideEffects/onDefinitionReceivedTrigger.d.ts.map +1 -1
  61. package/esm/store/sideEffects/onDefinitionReceivedTrigger.js +2 -8
  62. package/esm/store/sideEffects/onEvent.d.ts.map +1 -1
  63. package/esm/store/sideEffects/onEvent.js +26 -71
  64. package/esm/store/sideEffects/onThreadClear.d.ts +1 -7
  65. package/esm/store/sideEffects/onThreadClear.d.ts.map +1 -1
  66. package/esm/store/sideEffects/onThreadClear.js +4 -26
  67. package/esm/store/sideEffects/onThreadLoad.d.ts +3 -26
  68. package/esm/store/sideEffects/onThreadLoad.d.ts.map +1 -1
  69. package/esm/store/sideEffects/onThreadLoad.js +3 -86
  70. package/esm/store/sideEffects/onUserFeedback.d.ts +4 -4
  71. package/esm/store/sideEffects/onUserFeedback.d.ts.map +1 -1
  72. package/esm/store/sideEffects/onUserFeedback.js +21 -44
  73. package/esm/store/sideEffects/onUserMessage.d.ts +3 -25
  74. package/esm/store/sideEffects/onUserMessage.d.ts.map +1 -1
  75. package/esm/store/sideEffects/onUserMessage.js +7 -161
  76. package/esm/store/sideEffects/onVisualisationRender.d.ts +2 -8
  77. package/esm/store/sideEffects/onVisualisationRender.d.ts.map +1 -1
  78. package/esm/store/sideEffects/onVisualisationRender.js +1 -28
  79. package/esm/store/sideEffects/onVisualizationSave.d.ts +5 -6
  80. package/esm/store/sideEffects/onVisualizationSave.d.ts.map +1 -1
  81. package/esm/store/sideEffects/onVisualizationSave.js +32 -240
  82. package/esm/store/sideEffects/onVisualizationSuccessSave.d.ts +3 -4
  83. package/esm/store/sideEffects/onVisualizationSuccessSave.d.ts.map +1 -1
  84. package/esm/store/sideEffects/onVisualizationSuccessSave.js +16 -49
  85. package/esm/store/sideEffects/utils.d.ts +0 -2
  86. package/esm/store/sideEffects/utils.d.ts.map +1 -1
  87. package/esm/store/sideEffects/utils.js +0 -14
  88. package/package.json +20 -19
  89. package/styles/css/main.css +12 -496
  90. package/styles/css/main.css.map +1 -1
  91. package/styles/css/messages.css +12 -496
  92. package/styles/css/messages.css.map +1 -1
  93. package/styles/scss/messages.scss +14 -375
  94. package/esm/components/messages/AssistantMessage.d.ts +0 -8
  95. package/esm/components/messages/AssistantMessage.d.ts.map +0 -1
  96. package/esm/components/messages/AssistantMessage.js +0 -35
  97. package/esm/components/messages/MessageContents.d.ts +0 -12
  98. package/esm/components/messages/MessageContents.d.ts.map +0 -1
  99. package/esm/components/messages/MessageContents.js +0 -49
  100. package/esm/components/messages/ReasoningDropdown.d.ts +0 -14
  101. package/esm/components/messages/ReasoningDropdown.d.ts.map +0 -1
  102. package/esm/components/messages/ReasoningDropdown.js +0 -42
  103. package/esm/components/messages/ReasoningMessage.d.ts +0 -9
  104. package/esm/components/messages/ReasoningMessage.d.ts.map +0 -1
  105. package/esm/components/messages/ReasoningMessage.js +0 -45
  106. package/esm/components/messages/UserMessage.d.ts +0 -8
  107. package/esm/components/messages/UserMessage.d.ts.map +0 -1
  108. package/esm/components/messages/UserMessage.js +0 -10
  109. package/esm/components/messages/contents/ChangeAnalysisContentsComponent.d.ts +0 -12
  110. package/esm/components/messages/contents/ChangeAnalysisContentsComponent.d.ts.map +0 -1
  111. package/esm/components/messages/contents/ChangeAnalysisContentsComponent.js +0 -36
  112. package/esm/components/messages/contents/ErrorContents.d.ts +0 -7
  113. package/esm/components/messages/contents/ErrorContents.d.ts.map +0 -1
  114. package/esm/components/messages/contents/ErrorContents.js +0 -8
  115. package/esm/components/messages/contents/ReasoningContents.d.ts +0 -6
  116. package/esm/components/messages/contents/ReasoningContents.d.ts.map +0 -1
  117. package/esm/components/messages/contents/ReasoningContents.js +0 -43
  118. package/esm/components/messages/contents/RoutingContents.d.ts +0 -8
  119. package/esm/components/messages/contents/RoutingContents.d.ts.map +0 -1
  120. package/esm/components/messages/contents/RoutingContents.js +0 -8
  121. package/esm/components/messages/contents/SearchContents.d.ts +0 -7
  122. package/esm/components/messages/contents/SearchContents.d.ts.map +0 -1
  123. package/esm/components/messages/contents/SearchContents.js +0 -15
  124. package/esm/components/messages/contents/SemanticSearchContents.d.ts +0 -8
  125. package/esm/components/messages/contents/SemanticSearchContents.d.ts.map +0 -1
  126. package/esm/components/messages/contents/SemanticSearchContents.js +0 -27
  127. package/esm/components/messages/contents/TextContents.d.ts +0 -7
  128. package/esm/components/messages/contents/TextContents.d.ts.map +0 -1
  129. package/esm/components/messages/contents/TextContents.js +0 -8
  130. package/esm/components/messages/contents/VisualizationContents.d.ts +0 -24
  131. package/esm/components/messages/contents/VisualizationContents.d.ts.map +0 -1
  132. package/esm/components/messages/contents/VisualizationContents.js +0 -532
  133. package/esm/components/messages/contents/VisualizationSaveDialog.d.ts +0 -13
  134. package/esm/components/messages/contents/VisualizationSaveDialog.d.ts.map +0 -1
  135. package/esm/components/messages/contents/VisualizationSaveDialog.js +0 -33
  136. package/esm/components/messages/contents/hooks/useVisualisationSaving.d.ts +0 -6
  137. package/esm/components/messages/contents/hooks/useVisualisationSaving.d.ts.map +0 -1
  138. package/esm/components/messages/contents/hooks/useVisualisationSaving.js +0 -17
  139. package/esm/components/messages/contents/useExecution.d.ts +0 -14
  140. package/esm/components/messages/contents/useExecution.d.ts.map +0 -1
  141. package/esm/components/messages/contents/useExecution.js +0 -131
  142. package/esm/components/messages/contents/useKdaDefinition.d.ts +0 -13
  143. package/esm/components/messages/contents/useKdaDefinition.d.ts.map +0 -1
  144. package/esm/components/messages/contents/useKdaDefinition.js +0 -140
  145. package/esm/components/messages/messageState.d.ts +0 -12
  146. package/esm/components/messages/messageState.d.ts.map +0 -1
  147. package/esm/components/messages/messageState.js +0 -21
  148. package/esm/store/sideEffects/converters/interactionsToMessages.d.ts +0 -19
  149. package/esm/store/sideEffects/converters/interactionsToMessages.d.ts.map +0 -1
  150. package/esm/store/sideEffects/converters/interactionsToMessages.js +0 -82
@@ -2,8 +2,7 @@
2
2
  import { createSlice } from "@reduxjs/toolkit";
3
3
  import { selectDefaultAgentId } from "../../components/utils/agentSelection.js";
4
4
  import { DEFAULT_EFFORT, deriveConversationEffort } from "../../components/utils/effortSelection.js";
5
- import { isAssistantMessage, isChatConversationLocalItem, isUserMessage, isVisualizationContents, makeAgentChangeItem, makeErrorContent, makeErrorContents, } from "../../model.js";
6
- import { convertMessageToChatConversation } from "../sideEffects/utils.js";
5
+ import { makeAgentChangeItem, makeErrorContent, } from "../../model.js";
7
6
  import { createEmptyConversation, getConversationData, getConversationLocalId, isConversationWithLocalId, } from "../utils.js";
8
7
  export const LS_VERBOSE_KEY = "gd-gen-ai-verbose";
9
8
  export const messagesSliceName = "messages";
@@ -21,10 +20,6 @@ const initialState = {
21
20
  // Start with loading state to avoid re-render from empty state on startup
22
21
  loaded: false,
23
22
  verbose: getInitialVerboseState(),
24
- //old messages
25
- messageAsyncProcess: "loading",
26
- messageOrder: [],
27
- messages: {},
28
23
  //conversations
29
24
  conversations: undefined,
30
25
  currentConversation: undefined,
@@ -35,14 +30,6 @@ const initialState = {
35
30
  conversationsData: {},
36
31
  refocus: 0,
37
32
  };
38
- const setNormalizedMessages = (state, messages) => {
39
- state.messages = messages.reduce((acc, message) => {
40
- acc[message.localId] = message;
41
- return acc;
42
- }, {});
43
- state.messageOrder = messages.map((message) => message.localId);
44
- state.loaded = true;
45
- };
46
33
  const setNormalizedConversations = (state, conversations) => {
47
34
  const originalConversations = state.conversations ?? [];
48
35
  // Iterate new conversations and try to find existing conversation by id
@@ -102,131 +89,64 @@ const getResponseTrace = (state, conversationId, responseId) => {
102
89
  return (trace[responseId] ??= { steps: [], detailsByStepId: {}, responseDetails: [] });
103
90
  };
104
91
  const getAssistantMessageStrict = (state, assistantMessageId, conversationId) => {
105
- if (state.currentConversation) {
106
- const data = getConversationData(state.conversationsData, conversationId);
107
- if (!data) {
108
- throw new Error(`Unexpected error during message evaluation.`);
109
- }
110
- const message = data.items[assistantMessageId];
111
- if (message.role !== "assistant") {
112
- throw new Error(`Unexpected error during message evaluation.`);
113
- }
114
- return message;
92
+ const data = getConversationData(state.conversationsData, conversationId);
93
+ if (!data) {
94
+ throw new Error(`Unexpected error during message evaluation.`);
115
95
  }
116
- else {
117
- const message = state.messages[assistantMessageId];
118
- if (!isAssistantMessage(message)) {
119
- throw new Error(`Unexpected error during message evaluation.`);
120
- }
121
- return message;
96
+ const message = data.items[assistantMessageId];
97
+ if (message.role !== "assistant") {
98
+ throw new Error(`Unexpected error during message evaluation.`);
122
99
  }
100
+ return message;
123
101
  };
124
102
  const getUserMessageStrict = (state, assistantMessageId, conversationId) => {
125
- if (state.currentConversation) {
126
- const data = getConversationData(state.conversationsData, conversationId);
127
- if (!data) {
128
- throw new Error(`Unexpected error during message evaluation.`);
129
- }
130
- const message = data.items[assistantMessageId];
131
- if (message.role !== "user") {
132
- throw new Error(`Unexpected error during message evaluation.`);
133
- }
134
- return message;
103
+ const data = getConversationData(state.conversationsData, conversationId);
104
+ if (!data) {
105
+ throw new Error(`Unexpected error during message evaluation.`);
135
106
  }
136
- else {
137
- const message = state.messages[assistantMessageId];
138
- if (!isUserMessage(message)) {
139
- throw new Error(`Unexpected error during message evaluation.`);
140
- }
141
- return message;
107
+ const message = data.items[assistantMessageId];
108
+ if (message.role !== "user") {
109
+ throw new Error(`Unexpected error during message evaluation.`);
142
110
  }
111
+ return message;
143
112
  };
144
113
  const getMessageExists = (state, assistantMessageId, conversationId) => {
145
- if (state.currentConversation) {
146
- if (!conversationId) {
147
- return false;
148
- }
149
- const data = getConversationData(state.conversationsData, conversationId);
150
- return !!data?.items[assistantMessageId];
114
+ if (!conversationId) {
115
+ return false;
151
116
  }
152
- return !!state.messages[assistantMessageId];
117
+ const data = getConversationData(state.conversationsData, conversationId);
118
+ return !!data?.items[assistantMessageId];
153
119
  };
154
120
  /**
155
121
  * Get the user message before the assistant message, or undefined if there isn't one.
156
122
  * This is useful for dynamically created assistant messages that don't have a preceding user message.
157
123
  */
158
124
  const getUserMessageBeforeSafe = (state, assistantMessageId, conversationId) => {
159
- if (state.currentConversation) {
160
- const data = getConversationData(state.conversationsData, conversationId);
161
- if (!data) {
162
- return undefined;
163
- }
164
- const messageIndex = data.order.indexOf(assistantMessageId);
165
- if (messageIndex <= 0) {
166
- return undefined;
167
- }
168
- const message = data.items[data.order[messageIndex - 1]];
169
- return message.role === "user" ? message : undefined;
125
+ const data = getConversationData(state.conversationsData, conversationId);
126
+ if (!data) {
127
+ return undefined;
170
128
  }
171
- const messageIndex = state.messageOrder.indexOf(assistantMessageId);
129
+ const messageIndex = data.order.indexOf(assistantMessageId);
172
130
  if (messageIndex <= 0) {
173
131
  return undefined;
174
132
  }
175
- const message = state.messages[state.messageOrder[messageIndex - 1]];
176
- return isUserMessage(message) ? message : undefined;
133
+ const message = data.items[data.order[messageIndex - 1]];
134
+ return message.role === "user" ? message : undefined;
177
135
  };
178
136
  const messagesSlice = createSlice({
179
137
  name: messagesSliceName,
180
138
  initialState,
181
139
  reducers: {
182
140
  loadThreadAction: (state) => {
183
- if (state.currentConversation) {
184
- const data = getConversationData(state.conversationsData, state.currentConversation.localId);
185
- if (data) {
186
- data.asyncProcess = "loading";
187
- }
188
- }
189
- else {
190
- state.messageAsyncProcess = "loading";
141
+ const data = getConversationData(state.conversationsData, state.currentConversation?.localId);
142
+ if (data) {
143
+ data.asyncProcess = "loading";
191
144
  }
192
145
  },
193
146
  loadThreadErrorAction: (state, { payload: { error } }) => {
194
147
  state.globalError = errorToObject(error);
195
- if (state.currentConversation) {
196
- const data = getConversationData(state.conversationsData, state.currentConversation.localId);
197
- delete data?.asyncProcess;
198
- }
199
- else {
200
- delete state.messageAsyncProcess;
201
- }
202
- },
203
- loadThreadSuccessAction: (state, { payload: { messages, threadId } }) => {
204
- setNormalizedMessages(state, messages);
205
- state.threadId = threadId;
206
- if (state.currentConversation) {
207
- const data = getConversationData(state.conversationsData, state.currentConversation.localId);
208
- delete data?.asyncProcess;
209
- }
210
- else {
211
- delete state.messageAsyncProcess;
212
- state.conversationsLoaded = true;
213
- }
214
- },
215
- /**
216
- * Restore previously cached messages immediately while the backend is still loading.
217
- * Unlike loadThreadSuccessAction, this does not mark the thread as fully loaded,
218
- * so the backend fetch continues and will replace these messages when complete.
219
- * Sets asyncProcess to "restoring" so that:
220
- * - The skeleton spinner is hidden and cached messages are rendered (Messages checks for "loading"/"clearing" only).
221
- * - The input remains disabled (Input checks !!asyncProcess, and "restoring" is truthy).
222
- */
223
- restoreCachedMessagesAction: (state, { payload: { messages } }) => {
224
- state.messages = messages.reduce((acc, message) => {
225
- acc[message.localId] = message;
226
- return acc;
227
- }, {});
228
- state.messageOrder = messages.map((message) => message.localId);
229
- state.messageAsyncProcess = "restoring";
148
+ const data = getConversationData(state.conversationsData, state.currentConversation?.localId);
149
+ delete data?.asyncProcess;
230
150
  },
231
151
  loadConversationsSuccessAction: (state, { payload: { conversations }, }) => {
232
152
  setNormalizedConversations(state, conversations);
@@ -236,50 +156,28 @@ const messagesSlice = createSlice({
236
156
  state.selectedAgentId = currentConversation.agentId ?? state.selectedAgentId;
237
157
  seedConversationEffort(state, currentConversation.localId);
238
158
  state.threadId = threadId;
239
- if (state.currentConversation) {
240
- const data = getConversationData(state.conversationsData, state.currentConversation.localId);
241
- delete data?.asyncProcess;
242
- }
243
- else {
244
- delete state.messageAsyncProcess;
245
- }
159
+ const data = getConversationData(state.conversationsData, state.currentConversation?.localId);
160
+ delete data?.asyncProcess;
246
161
  },
247
162
  clearThreadAction: (state) => {
248
163
  // Don't clobber an in-flight reply's "evaluating" marker: in multi-conversation mode this
249
164
  // "clear" navigates to a fresh draft and leaves the outgoing conversation intact, so it must
250
165
  // stay busy until its reply resolves (LX-2644).
251
- if (state.currentConversation) {
252
- const data = getConversationData(state.conversationsData, state.currentConversation.localId);
253
- if (data && data.asyncProcess !== "evaluating") {
254
- data.asyncProcess = "clearing";
255
- }
256
- }
257
- else if (state.messageAsyncProcess !== "evaluating") {
258
- state.messageAsyncProcess = "clearing";
166
+ const data = getConversationData(state.conversationsData, state.currentConversation?.localId);
167
+ if (data && data.asyncProcess !== "evaluating") {
168
+ data.asyncProcess = "clearing";
259
169
  }
260
170
  },
261
171
  clearThreadErrorAction: (state, { payload: { error } }) => {
262
172
  state.globalError = errorToObject(error);
263
- if (state.currentConversation) {
264
- const data = getConversationData(state.conversationsData, state.currentConversation.localId);
265
- delete data?.asyncProcess;
266
- }
267
- else {
268
- delete state.messageAsyncProcess;
269
- }
173
+ const data = getConversationData(state.conversationsData, state.currentConversation?.localId);
174
+ delete data?.asyncProcess;
270
175
  },
271
176
  clearThreadSuccessAction: (state) => {
272
- state.messages = {};
273
- state.messageOrder = [];
274
177
  state.loaded = false;
275
178
  delete state.globalError;
276
- if (state.currentConversation) {
277
- const data = getConversationData(state.conversationsData, state.currentConversation.localId);
278
- delete data?.asyncProcess;
279
- }
280
- else {
281
- delete state.messageAsyncProcess;
282
- }
179
+ const data = getConversationData(state.conversationsData, state.currentConversation?.localId);
180
+ delete data?.asyncProcess;
283
181
  },
284
182
  clearConversationSuccessAction: (state, { payload: { conversation, threadId }, }) => {
285
183
  state.conversations = [conversation, ...(state.conversations ?? [])];
@@ -290,108 +188,60 @@ const messagesSlice = createSlice({
290
188
  const data = getConversationData(state.conversationsData, state.currentConversation.localId);
291
189
  delete data?.asyncProcess;
292
190
  },
293
- /**
294
- * Add message to the stack
295
- */
296
191
  newMessageAction: (state, action) => {
297
- let message = action.payload;
298
- if (state.currentConversation && !isChatConversationLocalItem(message)) {
299
- message = convertMessageToChatConversation(message);
192
+ const message = action.payload;
193
+ // keep list of conversations, but clear current conversation data in the view
194
+ if (!state.currentConversation) {
195
+ state.currentConversation = createEmptyConversation();
300
196
  }
301
- if (isChatConversationLocalItem(message)) {
302
- // keep list of conversations, but clear current conversation data in the view
303
- if (!state.currentConversation) {
304
- state.currentConversation = createEmptyConversation();
197
+ const currentConversation = state.currentConversation;
198
+ currentConversation.updatedAt = new Date().toISOString();
199
+ state.conversations = state.conversations?.map((conversation) => {
200
+ if (conversation.localId === currentConversation.localId) {
201
+ return {
202
+ ...conversation,
203
+ updatedAt: currentConversation.updatedAt,
204
+ };
305
205
  }
306
- const currentConversation = state.currentConversation;
307
- currentConversation.updatedAt = new Date().toISOString();
308
- state.conversations = state.conversations?.map((conversation) => {
309
- if (conversation.localId === currentConversation.localId) {
310
- return {
311
- ...conversation,
312
- updatedAt: currentConversation.updatedAt,
313
- };
314
- }
315
- return conversation;
206
+ return conversation;
207
+ });
208
+ const data = getConversationData(state.conversationsData, currentConversation.localId);
209
+ if (data) {
210
+ // We need to mark all messages as filled
211
+ Object.values(data.items).forEach((item) => {
212
+ item.filled = true;
316
213
  });
317
- const data = getConversationData(state.conversationsData, currentConversation.localId);
318
- if (data) {
319
- // We need to mark all messages as filled
320
- Object.values(data.items).forEach((item) => {
321
- item.filled = true;
322
- });
323
- data.items[message.localId] = message;
324
- data.order.push(message.localId);
325
- }
326
- }
327
- else {
328
- if (state.currentConversation) {
329
- throw new Error("Working with thread message but conversation mode is active.");
330
- }
331
- state.messages[message.localId] = message;
332
- state.messageOrder.push(action.payload.localId);
214
+ data.items[message.localId] = message;
215
+ data.order.push(message.localId);
333
216
  }
334
217
  state.loaded = true;
335
218
  },
336
- /**
337
- * Start the message evaluation, adding new assistant message as an incomplete placeholder
338
- */
339
219
  evaluateMessageAction: (state, { payload: { message, conversationId }, }) => {
340
- if (isChatConversationLocalItem(message)) {
341
- if (!conversationId) {
342
- throw new Error("Working with conversation message but thread mode is active.");
343
- }
344
- const data = getConversationData(state.conversationsData, conversationId);
345
- if (data) {
346
- data.items[message.localId] = message;
347
- data.order.push(message.localId);
348
- }
349
- setConversationInProgress(state, true, conversationId);
350
- }
351
- else {
352
- if (state.currentConversation) {
353
- throw new Error("Working with thread message but conversation mode is active.");
354
- }
355
- state.messages[message.localId] = message;
356
- state.messageOrder.push(message.localId);
220
+ if (!conversationId) {
221
+ throw new Error("Working with conversation message but thread mode is active.");
357
222
  }
358
- if (state.currentConversation) {
359
- const data = getConversationData(state.conversationsData, conversationId);
360
- if (data) {
361
- data.asyncProcess = "evaluating";
362
- }
363
- }
364
- else {
365
- state.messageAsyncProcess = "evaluating";
223
+ const data = getConversationData(state.conversationsData, conversationId);
224
+ if (data) {
225
+ data.items[message.localId] = message;
226
+ data.order.push(message.localId);
227
+ data.asyncProcess = "evaluating";
366
228
  }
229
+ setConversationInProgress(state, true, conversationId);
367
230
  },
368
- /**
369
- * The evaluation failed, need to update the assistant message.
370
- */
371
231
  evaluateMessageErrorAction: (state, { payload, }) => {
372
232
  // Always clear the async process first to avoid stranding the UI
373
233
  const data = getConversationData(state.conversationsData, payload.conversationId);
374
234
  if (data) {
375
235
  delete data.asyncProcess;
376
236
  }
377
- delete state.messageAsyncProcess;
378
237
  if (!getMessageExists(state, payload.assistantMessageId, payload.conversationId)) {
379
238
  return;
380
239
  }
381
240
  const assistantMessage = getAssistantMessageStrict(state, payload.assistantMessageId, payload.conversationId);
382
- if (isChatConversationLocalItem(assistantMessage)) {
383
- assistantMessage.complete = true;
384
- assistantMessage.streaming = false;
385
- assistantMessage.content = makeErrorContent(payload.error);
386
- }
387
- else {
388
- assistantMessage.complete = true;
389
- assistantMessage.content.push(makeErrorContents(payload.error));
390
- }
241
+ assistantMessage.complete = true;
242
+ assistantMessage.streaming = false;
243
+ assistantMessage.content = makeErrorContent(payload.error);
391
244
  },
392
- /**
393
- * Received new chunk from server over SSE.
394
- */
395
245
  evaluateMessageStreamingAction: (state, { payload, }) => {
396
246
  //NOTE: During streaming a message, user can choose to close or reset a chat
397
247
  // and without this check, we would get an unwanted error
@@ -402,20 +252,14 @@ const messagesSlice = createSlice({
402
252
  // Update assistant message
403
253
  const assistantMessage = getAssistantMessageStrict(state, payload.assistantMessageId, payload.conversationId);
404
254
  assistantMessage.id = payload.interactionId ?? assistantMessage.id;
405
- if (isChatConversationLocalItem(assistantMessage)) {
406
- assistantMessage.content = payload.content ?? {
407
- type: "text",
408
- text: "",
409
- };
410
- assistantMessage.streaming = true;
411
- assistantMessage.cancelled = false;
412
- assistantMessage.responseId = payload.item?.responseId ?? "";
413
- assistantMessage.replyTo = payload.item?.replyTo;
414
- }
415
- else {
416
- assistantMessage.content.push(...(payload.contents ?? []));
417
- assistantMessage.cancelled = false;
418
- }
255
+ assistantMessage.content = payload.content ?? {
256
+ type: "text",
257
+ text: "",
258
+ };
259
+ assistantMessage.streaming = true;
260
+ assistantMessage.cancelled = false;
261
+ assistantMessage.responseId = payload.item?.responseId ?? "";
262
+ assistantMessage.replyTo = payload.item?.replyTo;
419
263
  // Also update the interaction id in the relevant user message (if one exists)
420
264
  // Note: dynamically created assistant messages (for multi-interaction streams)
421
265
  // may not have a preceding user message
@@ -447,16 +291,10 @@ const messagesSlice = createSlice({
447
291
  // Update assistant message
448
292
  const userMessage = getUserMessageStrict(state, payload.userMessageId, payload.conversationId);
449
293
  userMessage.id = payload.interactionId ?? userMessage.id;
450
- if (isChatConversationLocalItem(userMessage)) {
451
- const message = payload.message;
452
- userMessage.responseId = message.responseId;
453
- userMessage.replyTo = message.replyTo;
454
- userMessage.createdAt = message.createdAt;
455
- }
456
- else {
457
- const message = payload.message;
458
- userMessage.created = message.created;
459
- }
294
+ const message = payload.message;
295
+ userMessage.responseId = message.responseId;
296
+ userMessage.replyTo = message.replyTo;
297
+ userMessage.createdAt = message.createdAt;
460
298
  },
461
299
  evaluateMessageCompleteAction: (state, { payload, }) => {
462
300
  // Always clear the async process first to avoid stranding the UI
@@ -465,25 +303,19 @@ const messagesSlice = createSlice({
465
303
  if (data) {
466
304
  delete data.asyncProcess;
467
305
  }
468
- delete state.messageAsyncProcess;
469
306
  if (!getMessageExists(state, payload.assistantMessageId, payload.conversationId)) {
470
307
  return;
471
308
  }
472
309
  const assistantMessage = getAssistantMessageStrict(state, payload.assistantMessageId, payload.conversationId);
473
310
  assistantMessage.complete = true;
474
311
  assistantMessage.cancelled = payload.cancelled ?? assistantMessage.cancelled;
475
- if (isChatConversationLocalItem(assistantMessage)) {
476
- assistantMessage.streaming = false;
477
- }
312
+ assistantMessage.streaming = false;
478
313
  },
479
- setMessagesAction: (state, { payload: { messages, items }, }) => {
314
+ setMessagesAction: (state, { payload: { items } }) => {
480
315
  const conversation = state.currentConversation;
481
316
  if (conversation) {
482
317
  setNormalizedConversation(state, conversation, items ?? []);
483
318
  }
484
- else {
485
- setNormalizedMessages(state, messages ?? []);
486
- }
487
319
  },
488
320
  setVerboseAction: (state, { payload: { verbose } }) => {
489
321
  state.verbose = verbose;
@@ -668,9 +500,6 @@ const messagesSlice = createSlice({
668
500
  // orphan the "loading" flag on the conversation that was actually loading -
669
501
  // its skeleton then spins forever when it is reopened (LX-2577). Clear the
670
502
  // load flag wherever it sits; there is only ever one load in flight.
671
- if (state.messageAsyncProcess === "loading" || state.messageAsyncProcess === "restoring") {
672
- delete state.messageAsyncProcess;
673
- }
674
503
  for (const data of Object.values(state.conversationsData)) {
675
504
  if (data.asyncProcess === "loading" || data.asyncProcess === "restoring") {
676
505
  delete data.asyncProcess;
@@ -678,13 +507,8 @@ const messagesSlice = createSlice({
678
507
  }
679
508
  // Preserve the original behaviour for the current conversation's non-load
680
509
  // async states (e.g. "evaluating"/"clearing").
681
- if (state.currentConversation) {
682
- const data = getConversationData(state.conversationsData, state.currentConversation.localId);
683
- delete data?.asyncProcess;
684
- }
685
- else {
686
- delete state.messageAsyncProcess;
687
- }
510
+ const data = getConversationData(state.conversationsData, state.currentConversation?.localId);
511
+ delete data?.asyncProcess;
688
512
  },
689
513
  /**
690
514
  * Clear the "loading"/"restoring" flag for a specific conversation.
@@ -701,16 +525,11 @@ const messagesSlice = createSlice({
701
525
  delete data.asyncProcess;
702
526
  }
703
527
  }
704
- else if (state.messageAsyncProcess === "loading" || state.messageAsyncProcess === "restoring") {
705
- delete state.messageAsyncProcess;
706
- }
707
528
  },
708
529
  filledFormAction: (state, { payload, }) => {
709
530
  const conversationId = getConversationLocalId(state.currentConversation);
710
531
  const assistantMessage = getAssistantMessageStrict(state, payload.assistantMessageId, conversationId);
711
- if (isChatConversationLocalItem(assistantMessage)) {
712
- assistantMessage.filled = true;
713
- }
532
+ assistantMessage.filled = true;
714
533
  },
715
534
  refocusInput: (state) => {
716
535
  state.refocus++;
@@ -718,172 +537,104 @@ const messagesSlice = createSlice({
718
537
  setUserFeedback: (state, { payload, }) => {
719
538
  const conversationId = getConversationLocalId(state.currentConversation);
720
539
  const assistantMessage = getAssistantMessageStrict(state, payload.assistantMessageId, conversationId);
721
- if (isChatConversationLocalItem(assistantMessage)) {
722
- const original = assistantMessage.feedback ?? {
723
- type: "feedback",
724
- createdAt: new Date().getTime(),
725
- updatedAt: new Date().getTime(),
726
- };
727
- assistantMessage.feedback = {
728
- ...original,
729
- feedback: payload.feedback,
730
- };
731
- }
732
- else {
733
- assistantMessage.feedback = payload.feedback;
734
- }
540
+ const original = assistantMessage.feedback ?? {
541
+ type: "feedback",
542
+ createdAt: new Date().getTime(),
543
+ updatedAt: new Date().getTime(),
544
+ };
545
+ assistantMessage.feedback = {
546
+ ...original,
547
+ feedback: payload.feedback,
548
+ };
735
549
  },
736
550
  setUserFeedbackError: (state, { payload, }) => {
737
551
  // Reset feedback to NONE and set error when submission fails
738
552
  const assistantMessage = getAssistantMessageStrict(state, payload.assistantMessageId, payload.conversationId);
739
- if (isChatConversationLocalItem(assistantMessage)) {
740
- const original = assistantMessage.feedback ?? {
741
- type: "feedback",
742
- createdAt: new Date().getTime(),
743
- updatedAt: new Date().getTime(),
744
- };
745
- assistantMessage.feedback = {
746
- ...original,
747
- feedback: "NONE",
748
- error: payload.error,
749
- };
750
- }
751
- else {
752
- assistantMessage.feedback = "NONE";
753
- assistantMessage.feedbackError = payload.error;
754
- }
755
- },
756
- clearUserFeedbackError: (state, { payload, }) => {
757
- // Clear feedback error after showing toast
758
- const assistantMessage = getAssistantMessageStrict(state, payload.assistantMessageId, payload.conversationId);
759
- if (isChatConversationLocalItem(assistantMessage)) {
760
- delete assistantMessage.feedback?.error;
761
- }
762
- else {
763
- delete assistantMessage.feedbackError;
764
- }
553
+ const original = assistantMessage.feedback ?? {
554
+ type: "feedback",
555
+ createdAt: new Date().getTime(),
556
+ updatedAt: new Date().getTime(),
557
+ };
558
+ assistantMessage.feedback = {
559
+ ...original,
560
+ feedback: "NONE",
561
+ error: payload.error,
562
+ };
765
563
  },
766
564
  saveVisualizationAction: (state, { payload, }) => {
767
565
  const conversationId = getConversationLocalId(state.currentConversation);
768
566
  const assistantMessage = getAssistantMessageStrict(state, payload.assistantMessageId, conversationId);
769
- if (isChatConversationLocalItem(assistantMessage)) {
770
- if (assistantMessage.content.type !== "multipart") {
771
- throw new Error("Unexpected message type");
772
- }
773
- const visualization = assistantMessage.content.parts
774
- .filter((filter) => filter.type === "visualization")
775
- .find((content) => content.visualization?.insight.identifier === payload.visualizationId);
776
- if (visualization?.visualization) {
777
- visualization.visualization.insight.title = payload.visualizationTitle;
778
- visualization.saving = {
779
- started: true,
780
- completed: false,
781
- };
782
- }
783
- }
784
- else {
785
- const visualization = assistantMessage.content
786
- .filter(isVisualizationContents)
787
- .flatMap((content) => content.createdVisualizations)
788
- .find((content) => content.id === payload.visualizationId);
789
- if (visualization) {
790
- visualization.saving = true;
791
- }
567
+ if (assistantMessage.content.type !== "multipart") {
568
+ throw new Error("Unexpected message type");
569
+ }
570
+ const visualization = assistantMessage.content.parts
571
+ .filter((filter) => filter.type === "visualization")
572
+ .find((content) => content.visualization?.insight.identifier === payload.visualizationId);
573
+ if (visualization?.visualization) {
574
+ visualization.visualization.insight.title = payload.visualizationTitle;
575
+ visualization.saving = {
576
+ started: true,
577
+ completed: false,
578
+ };
792
579
  }
793
580
  },
794
581
  savedVisualizationAction: (state, { payload, }) => {
795
582
  const conversationId = getConversationLocalId(state.currentConversation);
796
583
  const assistantMessage = getAssistantMessageStrict(state, payload.assistantMessageId, conversationId);
797
- if (isChatConversationLocalItem(assistantMessage)) {
798
- if (assistantMessage.content.type !== "multipart") {
799
- throw new Error("Unexpected message type");
800
- }
801
- const visualization = assistantMessage.content.parts
802
- .filter((filter) => filter.type === "visualization")
803
- .find((content) => content.visualization?.insight.identifier === payload.visualizationId);
804
- if (visualization) {
805
- delete visualization.saving;
806
- }
584
+ if (assistantMessage.content.type !== "multipart") {
585
+ throw new Error("Unexpected message type");
586
+ }
587
+ const visualization = assistantMessage.content.parts
588
+ .filter((filter) => filter.type === "visualization")
589
+ .find((content) => content.visualization?.insight.identifier === payload.visualizationId);
590
+ if (visualization) {
591
+ delete visualization.saving;
807
592
  }
808
593
  },
809
594
  saveVisualizationErrorAction: (state, { payload, }) => {
810
595
  const assistantMessage = getAssistantMessageStrict(state, payload.assistantMessageId, payload.conversationId);
811
- if (isChatConversationLocalItem(assistantMessage)) {
812
- if (assistantMessage.content.type !== "multipart") {
813
- throw new Error("Unexpected message type");
814
- }
815
- const visualization = assistantMessage.content.parts
816
- .filter((filter) => filter.type === "visualization")
817
- .find((content) => content.visualization?.insight.identifier === payload.visualizationId);
818
- if (visualization) {
819
- visualization.saving = {
820
- started: false,
821
- completed: false,
822
- };
823
- visualization.error = payload.error;
824
- }
825
- }
826
- else {
827
- const visualization = assistantMessage.content
828
- .filter(isVisualizationContents)
829
- .flatMap((content) => content.createdVisualizations)
830
- .find((content) => content.id === payload.visualizationId);
831
- if (visualization) {
832
- visualization.saving = false;
833
- }
596
+ if (assistantMessage.content.type !== "multipart") {
597
+ throw new Error("Unexpected message type");
598
+ }
599
+ const visualization = assistantMessage.content.parts
600
+ .filter((filter) => filter.type === "visualization")
601
+ .find((content) => content.visualization?.insight.identifier === payload.visualizationId);
602
+ if (visualization) {
603
+ visualization.saving = {
604
+ started: false,
605
+ completed: false,
606
+ };
607
+ visualization.error = payload.error;
834
608
  }
835
609
  },
836
610
  saveVisualizationSuccessAction: (state, { payload, }) => {
837
611
  const assistantMessage = getAssistantMessageStrict(state, payload.assistantMessageId, payload.conversationId);
838
- if (isChatConversationLocalItem(assistantMessage)) {
839
- if (assistantMessage.content.type !== "multipart") {
840
- throw new Error("Unexpected message type");
841
- }
842
- const visualization = assistantMessage.content.parts
843
- .filter((filter) => filter.type === "visualization")
844
- .find((content) => content.visualization?.insight.identifier === payload.visualizationId);
845
- if (visualization?.visualization) {
846
- visualization.saving = {
847
- started: true,
848
- completed: true,
849
- };
850
- visualization.visualization.insight.identifier = payload.savedVisualizationId;
851
- }
852
- }
853
- else {
854
- const visualization = assistantMessage.content
855
- .filter(isVisualizationContents)
856
- .flatMap((content) => content.createdVisualizations)
857
- .find((content) => content.id === payload.visualizationId);
858
- if (visualization) {
859
- visualization.saving = false;
860
- visualization.savedVisualizationId = payload.savedVisualizationId;
861
- }
612
+ if (assistantMessage.content.type !== "multipart") {
613
+ throw new Error("Unexpected message type");
614
+ }
615
+ const visualization = assistantMessage.content.parts
616
+ .filter((filter) => filter.type === "visualization")
617
+ .find((content) => content.visualization?.insight.identifier === payload.visualizationId);
618
+ if (visualization?.visualization) {
619
+ visualization.saving = {
620
+ started: true,
621
+ completed: true,
622
+ };
623
+ visualization.visualization.insight.identifier = payload.savedVisualizationId;
862
624
  }
863
625
  },
864
626
  saveVisualisationRenderStatusAction: (state, _action) => state,
865
627
  saveVisualisationRenderStatusSuccessAction: (state, { payload, }) => {
866
628
  const conversationId = getConversationLocalId(state.currentConversation);
867
629
  const assistantMessage = getAssistantMessageStrict(state, payload.assistantMessageId, conversationId);
868
- if (isChatConversationLocalItem(assistantMessage)) {
869
- if (assistantMessage.content.type !== "multipart") {
870
- throw new Error("Unexpected message type");
871
- }
872
- const visualization = assistantMessage.content.parts
873
- .filter((filter) => filter.type === "visualization")
874
- .find((content) => content.visualization?.insight.identifier === payload.visualizationId);
875
- if (visualization) {
876
- delete visualization.reporting;
877
- }
630
+ if (assistantMessage.content.type !== "multipart") {
631
+ throw new Error("Unexpected message type");
878
632
  }
879
- else {
880
- const visualization = assistantMessage.content
881
- .filter(isVisualizationContents)
882
- .flatMap((content) => content.createdVisualizations)
883
- .find((content) => content.id === payload.visualizationId);
884
- if (visualization) {
885
- delete visualization.statusReportPending;
886
- }
633
+ const visualization = assistantMessage.content.parts
634
+ .filter((filter) => filter.type === "visualization")
635
+ .find((content) => content.visualization?.insight.identifier === payload.visualizationId);
636
+ if (visualization) {
637
+ delete visualization.reporting;
887
638
  }
888
639
  },
889
640
  visualizationErrorAction: (state, _action) => state,
@@ -962,7 +713,7 @@ const messagesSlice = createSlice({
962
713
  });
963
714
  const errorToObject = (error) => Object.fromEntries(Object.getOwnPropertyNames(error).map((key) => [key, error[key]]));
964
715
  export const messagesSliceReducer = messagesSlice.reducer;
965
- export const { loadThreadAction, loadThreadErrorAction, loadThreadSuccessAction, loadConversationsSuccessAction, loadConversationSuccessAction, restoreCachedMessagesAction, clearThreadErrorAction, clearThreadSuccessAction, clearConversationSuccessAction, evaluateConversationTitleAction, evaluateMessageAction, evaluateMessageErrorAction, evaluateMessageStreamingAction, evaluateMessageUpdateAction, evaluateMessageCompleteAction, setMessagesAction, setVerboseAction, setGlobalErrorAction, cancelAsyncAction, clearConversationLoadingAction, setUserFeedback, setUserFeedbackError, clearUserFeedbackError, saveVisualizationAction, savedVisualizationAction, saveVisualizationErrorAction, saveVisualizationSuccessAction, saveVisualisationRenderStatusAction, saveVisualisationRenderStatusSuccessAction, visualizationErrorAction, appendInteractionStepAction, appendTracedActionAction, appendResponseDetailAction, applyPendingAgentSwitchAction, revertAgentSwitchAction, setAgentsAction, pinConversationAction, pinConversationSuccessAction, pinConversationFailureAction, renameConversationAction, renameConversationSuccessAction, renameConversationFailureAction, deleteConversationAction, deleteConversationStartAction, deleteConversationSuccessAction, deleteConversationFailureAction, filledFormAction, refocusInput,
716
+ export const { loadThreadAction, loadThreadErrorAction, loadConversationsSuccessAction, loadConversationSuccessAction, clearThreadErrorAction, clearThreadSuccessAction, clearConversationSuccessAction, evaluateConversationTitleAction, evaluateMessageAction, evaluateMessageErrorAction, evaluateMessageStreamingAction, evaluateMessageUpdateAction, evaluateMessageCompleteAction, setMessagesAction, setVerboseAction, setGlobalErrorAction, cancelAsyncAction, clearConversationLoadingAction, setUserFeedback, setUserFeedbackError, saveVisualizationAction, savedVisualizationAction, saveVisualizationErrorAction, saveVisualizationSuccessAction, saveVisualisationRenderStatusAction, saveVisualisationRenderStatusSuccessAction, visualizationErrorAction, appendInteractionStepAction, appendTracedActionAction, appendResponseDetailAction, applyPendingAgentSwitchAction, revertAgentSwitchAction, setAgentsAction, pinConversationAction, pinConversationSuccessAction, pinConversationFailureAction, renameConversationAction, renameConversationSuccessAction, renameConversationFailureAction, deleteConversationAction, deleteConversationStartAction, deleteConversationSuccessAction, deleteConversationFailureAction, filledFormAction, refocusInput,
966
717
  /**
967
718
  * @public
968
719
  */