@red-hat-developer-hub/backstage-plugin-lightspeed 2.5.1 → 2.6.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.
- package/CHANGELOG.md +7 -0
- package/README.md +1 -1
- package/dist/components/LightSpeedChat.esm.js +10 -4
- package/dist/components/LightSpeedChat.esm.js.map +1 -1
- package/dist/hooks/useConversationMessages.esm.js +352 -322
- package/dist/hooks/useConversationMessages.esm.js.map +1 -1
- package/package.json +2 -2
|
@@ -55,12 +55,17 @@ const useConversationMessages = (conversationId, userName, selectedModel, select
|
|
|
55
55
|
const streamingConversations = useRef({
|
|
56
56
|
[currentConversation]: []
|
|
57
57
|
});
|
|
58
|
+
const isTempStreamInProgressRef = useRef(false);
|
|
59
|
+
const [streamingConversationId, setStreamingConversationId] = useState(null);
|
|
58
60
|
const pendingToolCalls = useRef({});
|
|
59
61
|
useEffect(() => {
|
|
60
62
|
if (currentConversation !== conversationId) {
|
|
61
63
|
setCurrentConversation(conversationId);
|
|
62
64
|
setConversations((prev) => {
|
|
63
65
|
if (conversationId === TEMP_CONVERSATION_ID) {
|
|
66
|
+
if (isTempStreamInProgressRef.current && (prev[TEMP_CONVERSATION_ID]?.length ?? 0) > 0) {
|
|
67
|
+
return prev;
|
|
68
|
+
}
|
|
64
69
|
return { ...prev, [TEMP_CONVERSATION_ID]: [] };
|
|
65
70
|
}
|
|
66
71
|
if (prev[conversationId]) return prev;
|
|
@@ -111,7 +116,10 @@ const useConversationMessages = (conversationId, userName, selectedModel, select
|
|
|
111
116
|
...streamingConversations.current[currentConversation]
|
|
112
117
|
);
|
|
113
118
|
}
|
|
114
|
-
setConversations(
|
|
119
|
+
setConversations((prev) => ({
|
|
120
|
+
...prev,
|
|
121
|
+
..._conversations
|
|
122
|
+
}));
|
|
115
123
|
}
|
|
116
124
|
}, [
|
|
117
125
|
conversationsData,
|
|
@@ -123,117 +131,254 @@ const useConversationMessages = (conversationId, userName, selectedModel, select
|
|
|
123
131
|
]);
|
|
124
132
|
const handleInputPrompt = useCallback(
|
|
125
133
|
async (prompt, attachments = []) => {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
createUserMessage({
|
|
131
|
-
avatar,
|
|
132
|
-
name: userName,
|
|
133
|
-
content: prompt,
|
|
134
|
-
timestamp: getTimestamp(Date.now()) ?? ""
|
|
135
|
-
}),
|
|
136
|
-
createBotMessage({
|
|
137
|
-
avatar: botAvatar,
|
|
138
|
-
isLoading: true,
|
|
139
|
-
name: selectedModel,
|
|
140
|
-
content: "",
|
|
141
|
-
timestamp: ""
|
|
142
|
-
})
|
|
143
|
-
];
|
|
144
|
-
streamingConversations.current = {
|
|
145
|
-
...streamingConversations.current,
|
|
146
|
-
[currentConversation]: conversationTuple
|
|
147
|
-
};
|
|
148
|
-
setConversations((prevConv) => {
|
|
149
|
-
return {
|
|
150
|
-
...prevConv,
|
|
151
|
-
[currentConversation]: [
|
|
152
|
-
...prevConv?.[currentConversation] ?? [],
|
|
153
|
-
...conversationTuple
|
|
154
|
-
]
|
|
155
|
-
};
|
|
156
|
-
});
|
|
157
|
-
setTimeout(() => {
|
|
158
|
-
scrollToBottomRef.current?.scrollToBottom();
|
|
159
|
-
}, 0);
|
|
160
|
-
const finalMessages = [];
|
|
161
|
-
let buffer = "";
|
|
134
|
+
const streamStartedOnTemp = currentConversation === TEMP_CONVERSATION_ID;
|
|
135
|
+
if (streamStartedOnTemp) {
|
|
136
|
+
isTempStreamInProgressRef.current = true;
|
|
137
|
+
}
|
|
162
138
|
try {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
139
|
+
let newConversationId = "";
|
|
140
|
+
let requestId = "";
|
|
141
|
+
setStreamingConversationId(currentConversation);
|
|
142
|
+
const toolCallsCacheKeyPrefix = currentConversation === TEMP_CONVERSATION_ID ? createTempToolCallsCacheSessionPrefix() : currentConversation;
|
|
143
|
+
const conversationTuple = [
|
|
144
|
+
createUserMessage({
|
|
145
|
+
avatar,
|
|
146
|
+
name: userName,
|
|
147
|
+
content: prompt,
|
|
148
|
+
timestamp: getTimestamp(Date.now()) ?? ""
|
|
149
|
+
}),
|
|
150
|
+
createBotMessage({
|
|
151
|
+
avatar: botAvatar,
|
|
152
|
+
isLoading: true,
|
|
153
|
+
name: selectedModel,
|
|
154
|
+
content: "",
|
|
155
|
+
timestamp: ""
|
|
156
|
+
})
|
|
157
|
+
];
|
|
158
|
+
streamingConversations.current = {
|
|
159
|
+
...streamingConversations.current,
|
|
160
|
+
[currentConversation]: conversationTuple
|
|
161
|
+
};
|
|
162
|
+
setConversations((prevConv) => {
|
|
163
|
+
return {
|
|
164
|
+
...prevConv,
|
|
165
|
+
[currentConversation]: [
|
|
166
|
+
...prevConv?.[currentConversation] ?? [],
|
|
167
|
+
...conversationTuple
|
|
168
|
+
]
|
|
169
|
+
};
|
|
169
170
|
});
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
171
|
+
setTimeout(() => {
|
|
172
|
+
scrollToBottomRef.current?.scrollToBottom();
|
|
173
|
+
}, 0);
|
|
174
|
+
const finalMessages = [];
|
|
175
|
+
let buffer = "";
|
|
176
|
+
try {
|
|
177
|
+
const reader = await createMessage({
|
|
178
|
+
prompt,
|
|
179
|
+
selectedModel,
|
|
180
|
+
selectedProvider,
|
|
181
|
+
currentConversation,
|
|
182
|
+
attachments
|
|
183
|
+
});
|
|
184
|
+
const decoder = new TextDecoder("utf-8");
|
|
185
|
+
let streamEnded = false;
|
|
186
|
+
while (!streamEnded) {
|
|
187
|
+
const { value, done } = await reader.read();
|
|
188
|
+
if (done) {
|
|
189
|
+
streamEnded = true;
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
buffer += decoder.decode(value, { stream: true });
|
|
193
|
+
const parts = buffer.split("\n\n");
|
|
194
|
+
buffer = parts.pop();
|
|
195
|
+
for (const part of parts) {
|
|
196
|
+
const lines = part.split("\n").filter((line) => line.startsWith("data:"));
|
|
197
|
+
const jsonString = lines.map((line) => line.trim().slice(5).trim()).join("");
|
|
198
|
+
try {
|
|
199
|
+
const { event, data } = JSON.parse(jsonString);
|
|
200
|
+
if (event === "start") {
|
|
201
|
+
requestId = data?.request_id;
|
|
202
|
+
onRequestIdReady?.(requestId);
|
|
203
|
+
if (currentConversation === TEMP_CONVERSATION_ID) {
|
|
204
|
+
newConversationId = data?.conversation_id;
|
|
205
|
+
}
|
|
191
206
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
}
|
|
207
|
+
if (event === "tool_call") {
|
|
208
|
+
const toolCallData = data?.token;
|
|
209
|
+
const legacyObjectCall = typeof toolCallData === "object" && toolCallData !== null && !Array.isArray(toolCallData) && toolCallData.tool_name;
|
|
210
|
+
const mcpStyle = isMcpStyleToolCallPayload(data);
|
|
211
|
+
const rawArgs = data?.args ?? data?.arguments;
|
|
212
|
+
const mcpArgs = rawArgs && typeof rawArgs === "object" && !Array.isArray(rawArgs) ? rawArgs : {};
|
|
213
|
+
let toolCall;
|
|
214
|
+
if (legacyObjectCall && data.id !== null) {
|
|
215
|
+
toolCall = {
|
|
216
|
+
id: data.id,
|
|
217
|
+
toolName: toolCallData.tool_name,
|
|
218
|
+
arguments: toolCallData.arguments || {},
|
|
219
|
+
startTime: Date.now(),
|
|
220
|
+
isLoading: true
|
|
221
|
+
};
|
|
222
|
+
} else if (mcpStyle) {
|
|
223
|
+
toolCall = {
|
|
224
|
+
id: data.id,
|
|
225
|
+
toolName: data.name.trim(),
|
|
226
|
+
description: typeof data.type === "string" && data.type !== data.name ? data.type : void 0,
|
|
227
|
+
arguments: mcpArgs,
|
|
228
|
+
startTime: Date.now(),
|
|
229
|
+
isLoading: true
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
if (toolCall && data.id !== null) {
|
|
233
|
+
const newToolCall = toolCall;
|
|
234
|
+
pendingToolCalls.current[toolCallIdKey(data.id)] = newToolCall;
|
|
235
|
+
setConversations((prevConversations) => {
|
|
236
|
+
const conversation = prevConversations[currentConversation] ?? [];
|
|
237
|
+
const lastMessageIndex = conversation.length - 1;
|
|
238
|
+
if (lastMessageIndex < 0) return prevConversations;
|
|
239
|
+
const lastMessage = { ...conversation[lastMessageIndex] };
|
|
240
|
+
const existingToolCalls = normalizeToolCalls(
|
|
241
|
+
lastMessage.toolCalls
|
|
242
|
+
);
|
|
243
|
+
const nextToolCalls = [
|
|
244
|
+
...existingToolCalls,
|
|
245
|
+
newToolCall
|
|
246
|
+
];
|
|
247
|
+
lastMessage.toolCalls = nextToolCalls;
|
|
248
|
+
const messageIndex = Math.floor(lastMessageIndex / 2);
|
|
249
|
+
const cacheKey = `${toolCallsCacheKeyPrefix}-${messageIndex}`;
|
|
250
|
+
setSharedToolCallsCache(cacheKey, nextToolCalls);
|
|
251
|
+
const updatedConversation = [
|
|
252
|
+
...conversation.slice(0, lastMessageIndex),
|
|
253
|
+
lastMessage
|
|
254
|
+
];
|
|
255
|
+
return {
|
|
256
|
+
...prevConversations,
|
|
257
|
+
[currentConversation]: updatedConversation
|
|
258
|
+
};
|
|
259
|
+
});
|
|
260
|
+
const [humanMessage, aiMessage] = streamingConversations.current[currentConversation] || [];
|
|
261
|
+
if (aiMessage) {
|
|
262
|
+
const existingStreamingToolCalls = normalizeToolCalls(
|
|
263
|
+
aiMessage.toolCalls
|
|
264
|
+
);
|
|
265
|
+
streamingConversations.current[currentConversation] = [
|
|
266
|
+
humanMessage,
|
|
267
|
+
{
|
|
268
|
+
...aiMessage,
|
|
269
|
+
toolCalls: [
|
|
270
|
+
...existingStreamingToolCalls,
|
|
271
|
+
newToolCall
|
|
272
|
+
]
|
|
273
|
+
}
|
|
274
|
+
];
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (event === "tool_result") {
|
|
279
|
+
const tokenResult = data?.token;
|
|
280
|
+
const legacyResult = isLegacyToolResultToken(tokenResult);
|
|
281
|
+
const mcpHasContent = data?.id !== null && data.content !== void 0 && !legacyResult;
|
|
282
|
+
let responsePayload;
|
|
283
|
+
let matchToolName;
|
|
284
|
+
let toolIdKey;
|
|
285
|
+
if (legacyResult) {
|
|
286
|
+
responsePayload = legacyToolResultToString(
|
|
287
|
+
tokenResult.response
|
|
288
|
+
);
|
|
289
|
+
matchToolName = tokenResult.tool_name;
|
|
290
|
+
toolIdKey = data?.id !== null ? toolCallIdKey(data.id) : void 0;
|
|
291
|
+
} else if (mcpHasContent) {
|
|
292
|
+
toolIdKey = toolCallIdKey(data.id);
|
|
293
|
+
responsePayload = typeof data.content === "string" ? data.content : JSON.stringify(data.content);
|
|
294
|
+
if (typeof data.status === "string" && data.status !== "success") {
|
|
295
|
+
responsePayload = `[${data.status}] ${responsePayload}`;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
if (responsePayload !== void 0 && toolIdKey !== void 0) {
|
|
299
|
+
const pendingCall = pendingToolCalls.current[toolIdKey];
|
|
300
|
+
const endTime = Date.now();
|
|
301
|
+
const executionTime = pendingCall ? (endTime - pendingCall.startTime) / 1e3 : 0;
|
|
302
|
+
setConversations((prevConversations) => {
|
|
303
|
+
const conversation = prevConversations[currentConversation] ?? [];
|
|
304
|
+
const lastMessageIndex = conversation.length - 1;
|
|
305
|
+
if (lastMessageIndex < 0) return prevConversations;
|
|
306
|
+
const lastMessage = { ...conversation[lastMessageIndex] };
|
|
307
|
+
const toolCalls = lastMessage.toolCalls || [];
|
|
308
|
+
const updatedToolCalls = toolCalls.map((tc) => {
|
|
309
|
+
const idMatches = toolCallIdKey(tc.id) === toolIdKey || matchToolName !== void 0 && tc.toolName === matchToolName;
|
|
310
|
+
if (idMatches) {
|
|
311
|
+
return {
|
|
312
|
+
...tc,
|
|
313
|
+
response: responsePayload,
|
|
314
|
+
endTime,
|
|
315
|
+
executionTime,
|
|
316
|
+
isLoading: false
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
return tc;
|
|
320
|
+
});
|
|
321
|
+
lastMessage.toolCalls = updatedToolCalls;
|
|
322
|
+
const messageIndex = Math.floor(lastMessageIndex / 2);
|
|
323
|
+
const cacheKey = `${toolCallsCacheKeyPrefix}-${messageIndex}`;
|
|
324
|
+
setSharedToolCallsCache(cacheKey, updatedToolCalls);
|
|
325
|
+
const updatedConversation = [
|
|
326
|
+
...conversation.slice(0, lastMessageIndex),
|
|
327
|
+
lastMessage
|
|
328
|
+
];
|
|
329
|
+
return {
|
|
330
|
+
...prevConversations,
|
|
331
|
+
[currentConversation]: updatedConversation
|
|
332
|
+
};
|
|
333
|
+
});
|
|
334
|
+
const [humanMessage, aiMessage] = streamingConversations.current[currentConversation] || [];
|
|
335
|
+
if (aiMessage) {
|
|
336
|
+
const toolCalls = aiMessage.toolCalls || [];
|
|
337
|
+
const updatedToolCalls = toolCalls.map((tc) => {
|
|
338
|
+
const idMatches = toolCallIdKey(tc.id) === toolIdKey || matchToolName !== void 0 && tc.toolName === matchToolName;
|
|
339
|
+
if (idMatches) {
|
|
340
|
+
return {
|
|
341
|
+
...tc,
|
|
342
|
+
response: responsePayload,
|
|
343
|
+
endTime,
|
|
344
|
+
executionTime,
|
|
345
|
+
isLoading: false
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
return tc;
|
|
349
|
+
});
|
|
350
|
+
streamingConversations.current[currentConversation] = [
|
|
351
|
+
humanMessage,
|
|
352
|
+
{ ...aiMessage, toolCalls: updatedToolCalls }
|
|
353
|
+
];
|
|
354
|
+
}
|
|
355
|
+
delete pendingToolCalls.current[toolIdKey];
|
|
356
|
+
}
|
|
217
357
|
}
|
|
218
|
-
if (
|
|
219
|
-
const
|
|
220
|
-
|
|
358
|
+
if (event === "token") {
|
|
359
|
+
const content = data?.token || "";
|
|
360
|
+
finalMessages.push(content);
|
|
361
|
+
const [humanMessage, aiMessage] = streamingConversations.current[currentConversation];
|
|
362
|
+
streamingConversations.current[currentConversation] = [
|
|
363
|
+
humanMessage,
|
|
364
|
+
{ ...aiMessage, content: aiMessage.content + content }
|
|
365
|
+
];
|
|
221
366
|
setConversations((prevConversations) => {
|
|
222
367
|
const conversation = prevConversations[currentConversation] ?? [];
|
|
223
368
|
const lastMessageIndex = conversation.length - 1;
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
369
|
+
const lastMessage = conversation.length === 0 ? createBotMessage({
|
|
370
|
+
content: "",
|
|
371
|
+
timestamp: getTimestamp(Date.now())
|
|
372
|
+
}) : { ...conversation[lastMessageIndex] };
|
|
373
|
+
if ((lastMessage?.content ?? "").trim().length > 0) {
|
|
374
|
+
lastMessage.isLoading = false;
|
|
375
|
+
}
|
|
376
|
+
lastMessage.content += content;
|
|
377
|
+
lastMessage.name = data?.response_metadata?.model || selectedModel;
|
|
378
|
+
lastMessage.timestamp = getTimestamp(
|
|
379
|
+
// TODO: To be fixed in the query response
|
|
380
|
+
data?.response_metadata?.created_at || Date.now()
|
|
228
381
|
);
|
|
229
|
-
const nextToolCalls = [
|
|
230
|
-
...existingToolCalls,
|
|
231
|
-
newToolCall
|
|
232
|
-
];
|
|
233
|
-
lastMessage.toolCalls = nextToolCalls;
|
|
234
|
-
const messageIndex = Math.floor(lastMessageIndex / 2);
|
|
235
|
-
const cacheKey = `${toolCallsCacheKeyPrefix}-${messageIndex}`;
|
|
236
|
-
setSharedToolCallsCache(cacheKey, nextToolCalls);
|
|
237
382
|
const updatedConversation = [
|
|
238
383
|
...conversation.slice(0, lastMessageIndex),
|
|
239
384
|
lastMessage
|
|
@@ -243,68 +388,22 @@ const useConversationMessages = (conversationId, userName, selectedModel, select
|
|
|
243
388
|
[currentConversation]: updatedConversation
|
|
244
389
|
};
|
|
245
390
|
});
|
|
246
|
-
const [humanMessage, aiMessage] = streamingConversations.current[currentConversation] || [];
|
|
247
|
-
if (aiMessage) {
|
|
248
|
-
const existingStreamingToolCalls = normalizeToolCalls(
|
|
249
|
-
aiMessage.toolCalls
|
|
250
|
-
);
|
|
251
|
-
streamingConversations.current[currentConversation] = [
|
|
252
|
-
humanMessage,
|
|
253
|
-
{
|
|
254
|
-
...aiMessage,
|
|
255
|
-
toolCalls: [...existingStreamingToolCalls, newToolCall]
|
|
256
|
-
}
|
|
257
|
-
];
|
|
258
|
-
}
|
|
259
391
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
const legacyResult = isLegacyToolResultToken(tokenResult);
|
|
264
|
-
const mcpHasContent = data?.id !== null && data.content !== void 0 && !legacyResult;
|
|
265
|
-
let responsePayload;
|
|
266
|
-
let matchToolName;
|
|
267
|
-
let toolIdKey;
|
|
268
|
-
if (legacyResult) {
|
|
269
|
-
responsePayload = legacyToolResultToString(
|
|
270
|
-
tokenResult.response
|
|
271
|
-
);
|
|
272
|
-
matchToolName = tokenResult.tool_name;
|
|
273
|
-
toolIdKey = data?.id !== null ? toolCallIdKey(data.id) : void 0;
|
|
274
|
-
} else if (mcpHasContent) {
|
|
275
|
-
toolIdKey = toolCallIdKey(data.id);
|
|
276
|
-
responsePayload = typeof data.content === "string" ? data.content : JSON.stringify(data.content);
|
|
277
|
-
if (typeof data.status === "string" && data.status !== "success") {
|
|
278
|
-
responsePayload = `[${data.status}] ${responsePayload}`;
|
|
392
|
+
if (event === "interrupted") {
|
|
393
|
+
if (currentConversation === TEMP_CONVERSATION_ID && data?.conversation_id) {
|
|
394
|
+
newConversationId = data.conversation_id;
|
|
279
395
|
}
|
|
280
|
-
}
|
|
281
|
-
if (responsePayload !== void 0 && toolIdKey !== void 0) {
|
|
282
|
-
const pendingCall = pendingToolCalls.current[toolIdKey];
|
|
283
|
-
const endTime = Date.now();
|
|
284
|
-
const executionTime = pendingCall ? (endTime - pendingCall.startTime) / 1e3 : 0;
|
|
285
396
|
setConversations((prevConversations) => {
|
|
286
397
|
const conversation = prevConversations[currentConversation] ?? [];
|
|
287
398
|
const lastMessageIndex = conversation.length - 1;
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
response: responsePayload,
|
|
297
|
-
endTime,
|
|
298
|
-
executionTime,
|
|
299
|
-
isLoading: false
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
return tc;
|
|
303
|
-
});
|
|
304
|
-
lastMessage.toolCalls = updatedToolCalls;
|
|
305
|
-
const messageIndex = Math.floor(lastMessageIndex / 2);
|
|
306
|
-
const cacheKey = `${toolCallsCacheKeyPrefix}-${messageIndex}`;
|
|
307
|
-
setSharedToolCallsCache(cacheKey, updatedToolCalls);
|
|
399
|
+
const lastMessage = conversation.length === 0 ? createBotMessage({
|
|
400
|
+
content: "",
|
|
401
|
+
isLoading: false,
|
|
402
|
+
timestamp: getTimestamp(Date.now())
|
|
403
|
+
}) : {
|
|
404
|
+
...conversation[lastMessageIndex],
|
|
405
|
+
isLoading: false
|
|
406
|
+
};
|
|
308
407
|
const updatedConversation = [
|
|
309
408
|
...conversation.slice(0, lastMessageIndex),
|
|
310
409
|
lastMessage
|
|
@@ -314,175 +413,105 @@ const useConversationMessages = (conversationId, userName, selectedModel, select
|
|
|
314
413
|
[currentConversation]: updatedConversation
|
|
315
414
|
};
|
|
316
415
|
});
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
416
|
+
streamEnded = true;
|
|
417
|
+
break;
|
|
418
|
+
}
|
|
419
|
+
if (event === "end") {
|
|
420
|
+
const documents = data?.referenced_documents || [];
|
|
421
|
+
setConversations((prevConversations) => {
|
|
422
|
+
const conversation = prevConversations[currentConversation] ?? [];
|
|
423
|
+
const lastMessageIndex = conversation.length - 1;
|
|
424
|
+
const lastMessage = conversation.length === 0 ? createBotMessage({
|
|
425
|
+
content: "",
|
|
426
|
+
isLoading: false,
|
|
427
|
+
timestamp: getTimestamp(Date.now())
|
|
428
|
+
}) : {
|
|
429
|
+
...conversation[lastMessageIndex],
|
|
430
|
+
isLoading: false
|
|
431
|
+
};
|
|
432
|
+
if (documents.length) {
|
|
433
|
+
lastMessage.sources = {
|
|
434
|
+
sources: documents.map((doc) => ({
|
|
435
|
+
title: doc.doc_title,
|
|
436
|
+
link: doc.doc_url,
|
|
437
|
+
body: doc.doc_description
|
|
438
|
+
}))
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
const updatedConversation = [
|
|
442
|
+
...conversation.slice(0, lastMessageIndex),
|
|
443
|
+
lastMessage
|
|
336
444
|
];
|
|
337
|
-
|
|
338
|
-
|
|
445
|
+
return {
|
|
446
|
+
...prevConversations,
|
|
447
|
+
[currentConversation]: updatedConversation
|
|
448
|
+
};
|
|
449
|
+
});
|
|
339
450
|
}
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
const [humanMessage, aiMessage] = streamingConversations.current[currentConversation];
|
|
345
|
-
streamingConversations.current[currentConversation] = [
|
|
346
|
-
humanMessage,
|
|
347
|
-
{ ...aiMessage, content: aiMessage.content + content }
|
|
348
|
-
];
|
|
349
|
-
setConversations((prevConversations) => {
|
|
350
|
-
const conversation = prevConversations[currentConversation] ?? [];
|
|
351
|
-
const lastMessageIndex = conversation.length - 1;
|
|
352
|
-
const lastMessage = conversation.length === 0 ? createBotMessage({
|
|
353
|
-
content: "",
|
|
354
|
-
timestamp: getTimestamp(Date.now())
|
|
355
|
-
}) : { ...conversation[lastMessageIndex] };
|
|
356
|
-
if ((lastMessage?.content ?? "").trim().length > 0) {
|
|
357
|
-
lastMessage.isLoading = false;
|
|
358
|
-
}
|
|
359
|
-
lastMessage.content += content;
|
|
360
|
-
lastMessage.name = data?.response_metadata?.model || selectedModel;
|
|
361
|
-
lastMessage.timestamp = getTimestamp(
|
|
362
|
-
// TODO: To be fixed in the query response
|
|
363
|
-
data?.response_metadata?.created_at || Date.now()
|
|
364
|
-
);
|
|
365
|
-
const updatedConversation = [
|
|
366
|
-
...conversation.slice(0, lastMessageIndex),
|
|
367
|
-
lastMessage
|
|
368
|
-
];
|
|
369
|
-
return {
|
|
370
|
-
...prevConversations,
|
|
371
|
-
[currentConversation]: updatedConversation
|
|
372
|
-
};
|
|
373
|
-
});
|
|
374
|
-
}
|
|
375
|
-
if (event === "interrupted") {
|
|
376
|
-
if (currentConversation === TEMP_CONVERSATION_ID && data?.conversation_id) {
|
|
377
|
-
newConversationId = data.conversation_id;
|
|
451
|
+
} catch (error) {
|
|
452
|
+
console.warn("Error parsing JSON:", error);
|
|
453
|
+
if (typeof onComplete === "function") {
|
|
454
|
+
onComplete("Invalid JSON received");
|
|
378
455
|
}
|
|
379
|
-
setConversations((prevConversations) => {
|
|
380
|
-
const conversation = prevConversations[currentConversation] ?? [];
|
|
381
|
-
const lastMessageIndex = conversation.length - 1;
|
|
382
|
-
const lastMessage = conversation.length === 0 ? createBotMessage({
|
|
383
|
-
content: "",
|
|
384
|
-
isLoading: false,
|
|
385
|
-
timestamp: getTimestamp(Date.now())
|
|
386
|
-
}) : { ...conversation[lastMessageIndex], isLoading: false };
|
|
387
|
-
const updatedConversation = [
|
|
388
|
-
...conversation.slice(0, lastMessageIndex),
|
|
389
|
-
lastMessage
|
|
390
|
-
];
|
|
391
|
-
return {
|
|
392
|
-
...prevConversations,
|
|
393
|
-
[currentConversation]: updatedConversation
|
|
394
|
-
};
|
|
395
|
-
});
|
|
396
|
-
streamEnded = true;
|
|
397
|
-
break;
|
|
398
|
-
}
|
|
399
|
-
if (event === "end") {
|
|
400
|
-
const documents = data?.referenced_documents || [];
|
|
401
|
-
setConversations((prevConversations) => {
|
|
402
|
-
const conversation = prevConversations[currentConversation] ?? [];
|
|
403
|
-
const lastMessageIndex = conversation.length - 1;
|
|
404
|
-
const lastMessage = conversation.length === 0 ? createBotMessage({
|
|
405
|
-
content: "",
|
|
406
|
-
isLoading: false,
|
|
407
|
-
timestamp: getTimestamp(Date.now())
|
|
408
|
-
}) : { ...conversation[lastMessageIndex], isLoading: false };
|
|
409
|
-
if (documents.length) {
|
|
410
|
-
lastMessage.sources = {
|
|
411
|
-
sources: documents.map((doc) => ({
|
|
412
|
-
title: doc.doc_title,
|
|
413
|
-
link: doc.doc_url,
|
|
414
|
-
body: doc.doc_description
|
|
415
|
-
}))
|
|
416
|
-
};
|
|
417
|
-
}
|
|
418
|
-
const updatedConversation = [
|
|
419
|
-
...conversation.slice(0, lastMessageIndex),
|
|
420
|
-
lastMessage
|
|
421
|
-
];
|
|
422
|
-
return {
|
|
423
|
-
...prevConversations,
|
|
424
|
-
[currentConversation]: updatedConversation
|
|
425
|
-
};
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
} catch (error) {
|
|
429
|
-
console.warn("Error parsing JSON:", error);
|
|
430
|
-
if (typeof onComplete === "function") {
|
|
431
|
-
onComplete("Invalid JSON received");
|
|
432
456
|
}
|
|
433
457
|
}
|
|
458
|
+
if (streamEnded) break;
|
|
434
459
|
}
|
|
435
|
-
|
|
460
|
+
} catch (e) {
|
|
461
|
+
setConversations((prevConversations) => {
|
|
462
|
+
const conversation = prevConversations[currentConversation] ?? [];
|
|
463
|
+
const lastMessageIndex = conversation.length - 1;
|
|
464
|
+
const lastMessage = conversation.length === 0 ? createBotMessage({
|
|
465
|
+
content: "",
|
|
466
|
+
timestamp: getTimestamp(Date.now())
|
|
467
|
+
}) : { ...conversation[lastMessageIndex] };
|
|
468
|
+
lastMessage.isLoading = false;
|
|
469
|
+
lastMessage.content += e;
|
|
470
|
+
lastMessage.error = {
|
|
471
|
+
title: e.message
|
|
472
|
+
};
|
|
473
|
+
lastMessage.timestamp = getTimestamp(Date.now());
|
|
474
|
+
const updatedConversation = [
|
|
475
|
+
...conversation.slice(0, lastMessageIndex),
|
|
476
|
+
lastMessage
|
|
477
|
+
];
|
|
478
|
+
finalMessages.push(`${e}`);
|
|
479
|
+
return {
|
|
480
|
+
...prevConversations,
|
|
481
|
+
[newConversationId.length > 0 ? newConversationId : currentConversation]: updatedConversation
|
|
482
|
+
};
|
|
483
|
+
});
|
|
436
484
|
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
const updatedConversation = [
|
|
452
|
-
...conversation.slice(0, lastMessageIndex),
|
|
453
|
-
lastMessage
|
|
454
|
-
];
|
|
455
|
-
finalMessages.push(`${e}`);
|
|
456
|
-
return {
|
|
457
|
-
...prevConversations,
|
|
458
|
-
[newConversationId.length > 0 ? newConversationId : currentConversation]: updatedConversation
|
|
459
|
-
};
|
|
460
|
-
});
|
|
461
|
-
}
|
|
462
|
-
streamingConversations.current[currentConversation] = [];
|
|
463
|
-
if (typeof onComplete === "function") {
|
|
464
|
-
onComplete(finalMessages.join(""));
|
|
465
|
-
}
|
|
466
|
-
if (currentConversation === TEMP_CONVERSATION_ID && newConversationId) {
|
|
467
|
-
migrateSharedToolCallsCacheSessionPrefixToConversation(
|
|
468
|
-
toolCallsCacheKeyPrefix,
|
|
469
|
-
newConversationId
|
|
470
|
-
);
|
|
471
|
-
setConversations((prevConversations) => {
|
|
472
|
-
return {
|
|
473
|
-
...prevConversations,
|
|
474
|
-
[newConversationId]: prevConversations[TEMP_CONVERSATION_ID]
|
|
475
|
-
};
|
|
476
|
-
});
|
|
477
|
-
onStart?.(newConversationId);
|
|
478
|
-
setTimeout(() => {
|
|
479
|
-
setConversations((prev) => {
|
|
480
|
-
const { [TEMP_CONVERSATION_ID]: _, ...rest } = prev;
|
|
481
|
-
return rest;
|
|
485
|
+
streamingConversations.current[currentConversation] = [];
|
|
486
|
+
if (typeof onComplete === "function") {
|
|
487
|
+
onComplete(finalMessages.join(""));
|
|
488
|
+
}
|
|
489
|
+
if (currentConversation === TEMP_CONVERSATION_ID && newConversationId) {
|
|
490
|
+
migrateSharedToolCallsCacheSessionPrefixToConversation(
|
|
491
|
+
toolCallsCacheKeyPrefix,
|
|
492
|
+
newConversationId
|
|
493
|
+
);
|
|
494
|
+
setConversations((prevConversations) => {
|
|
495
|
+
return {
|
|
496
|
+
...prevConversations,
|
|
497
|
+
[newConversationId]: prevConversations[TEMP_CONVERSATION_ID]
|
|
498
|
+
};
|
|
482
499
|
});
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
500
|
+
onStart?.(newConversationId);
|
|
501
|
+
setTimeout(() => {
|
|
502
|
+
setConversations((prev) => {
|
|
503
|
+
const { [TEMP_CONVERSATION_ID]: _, ...rest } = prev;
|
|
504
|
+
return rest;
|
|
505
|
+
});
|
|
506
|
+
}, 0);
|
|
507
|
+
} else if (currentConversation === TEMP_CONVERSATION_ID) {
|
|
508
|
+
clearSharedToolCallsCacheSessionPrefix(toolCallsCacheKeyPrefix);
|
|
509
|
+
}
|
|
510
|
+
} finally {
|
|
511
|
+
if (streamStartedOnTemp) {
|
|
512
|
+
isTempStreamInProgressRef.current = false;
|
|
513
|
+
}
|
|
514
|
+
setStreamingConversationId(null);
|
|
486
515
|
}
|
|
487
516
|
},
|
|
488
517
|
[
|
|
@@ -502,6 +531,7 @@ const useConversationMessages = (conversationId, userName, selectedModel, select
|
|
|
502
531
|
handleInputPrompt,
|
|
503
532
|
conversations,
|
|
504
533
|
scrollToBottomRef,
|
|
534
|
+
streamingConversationId,
|
|
505
535
|
...queryProps
|
|
506
536
|
};
|
|
507
537
|
};
|