@ai-group/chat-sdk 3.6.7 → 3.6.8
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/dist/cjs/components/XAdkChatbot/components/FunctionCallRender/index.js.map +2 -2
- package/dist/cjs/hooks/useADKChat.d.ts +2 -2
- package/dist/cjs/hooks/useADKChat.js +141 -176
- package/dist/cjs/hooks/useADKChat.js.map +3 -3
- package/dist/esm/components/XAdkChatbot/components/FunctionCallRender/index.js +2 -0
- package/dist/esm/components/XAdkChatbot/components/FunctionCallRender/index.js.map +1 -1
- package/dist/esm/hooks/useADKChat.d.ts +2 -2
- package/dist/esm/hooks/useADKChat.js +204 -196
- package/dist/esm/hooks/useADKChat.js.map +1 -1
- package/dist/umd/chat-sdk.min.js +1 -1
- package/package.json +1 -1
|
@@ -45,6 +45,47 @@ var combineTextParts = function combineTextParts(parts) {
|
|
|
45
45
|
return result;
|
|
46
46
|
};
|
|
47
47
|
var DEFAULT_SESSION_EVENTS_POLLING_INTERVAL = 10000;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 从 event + part 构建非文本 IMessage(functionCall / functionResponse / executableCode 等)。
|
|
51
|
+
*/
|
|
52
|
+
var buildNonTextMessage = function buildNonTextMessage(event, part) {
|
|
53
|
+
var role = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "bot";
|
|
54
|
+
var msg = {
|
|
55
|
+
id: v4(),
|
|
56
|
+
author: event.author,
|
|
57
|
+
invocationId: event.invocationId,
|
|
58
|
+
eventId: event.id,
|
|
59
|
+
timestamp: event.timestamp,
|
|
60
|
+
isLike: event.isLike || 0,
|
|
61
|
+
role: role,
|
|
62
|
+
modelCode: event.modelCode,
|
|
63
|
+
usageMetadata: event.usageMetadata,
|
|
64
|
+
finishReason: event.finishReason,
|
|
65
|
+
raw: event
|
|
66
|
+
};
|
|
67
|
+
if (part.inlineData) {
|
|
68
|
+
msg.inlineData = {
|
|
69
|
+
displayName: part.inlineData.displayName,
|
|
70
|
+
data: part.inlineData.data,
|
|
71
|
+
mimeType: part.inlineData.mimeType
|
|
72
|
+
};
|
|
73
|
+
} else if (part.fileData) {
|
|
74
|
+
msg.fileData = [part.fileData];
|
|
75
|
+
} else if (part.functionCall) {
|
|
76
|
+
msg.functionCall = part.functionCall;
|
|
77
|
+
} else if (part.functionResponse) {
|
|
78
|
+
msg.functionResponse = part.functionResponse;
|
|
79
|
+
} else if (part.executableCode) {
|
|
80
|
+
msg.executableCode = part.executableCode;
|
|
81
|
+
} else if (part.codeExecutionResult) {
|
|
82
|
+
msg.codeExecutionResult = part.codeExecutionResult;
|
|
83
|
+
} else if (part.text) {
|
|
84
|
+
msg.text = part.text;
|
|
85
|
+
msg.thought = part.thought;
|
|
86
|
+
}
|
|
87
|
+
return msg;
|
|
88
|
+
};
|
|
48
89
|
var getMessageEventId = function getMessageEventId(messageItem) {
|
|
49
90
|
var _messageItem$raw;
|
|
50
91
|
return messageItem.eventId || ((_messageItem$raw = messageItem.raw) === null || _messageItem$raw === void 0 ? void 0 : _messageItem$raw.id);
|
|
@@ -60,6 +101,8 @@ var deduplicateMessages = function deduplicateMessages(messageItems) {
|
|
|
60
101
|
seenMessageIds.add(messageItem.id);
|
|
61
102
|
return true;
|
|
62
103
|
});
|
|
104
|
+
|
|
105
|
+
// 机器人文本消息去重:同一事件、同一思考类型、同一文件列表的文本消息,如果文本内容包含关系,则保留最长的文本消息,去掉被包含的短文本消息。
|
|
63
106
|
var botTextGroups = new Map();
|
|
64
107
|
uniqueIdMessages.forEach(function (messageItem) {
|
|
65
108
|
var eventId = getMessageEventId(messageItem);
|
|
@@ -107,6 +150,10 @@ var mapSessionMessages = function mapSessionMessages(sessionEvents) {
|
|
|
107
150
|
if (item.author === "user" && item.content.parts.some(function (part) {
|
|
108
151
|
return part.task;
|
|
109
152
|
})) return;
|
|
153
|
+
// functionResponse 的 user 事件仅用于配对 functionCall,不作为独立消息展示
|
|
154
|
+
if (item.content.role === "user" && item.content.parts.every(function (part) {
|
|
155
|
+
return !part || part.functionResponse;
|
|
156
|
+
})) return;
|
|
110
157
|
var role = (item.content.role || "").toLowerCase() === "user" ? "user" : "bot";
|
|
111
158
|
var parts = item.content.parts.filter(function (part) {
|
|
112
159
|
if (!part) return false;
|
|
@@ -122,9 +169,13 @@ var mapSessionMessages = function mapSessionMessages(sessionEvents) {
|
|
|
122
169
|
var otherParts = parts.filter(function (part) {
|
|
123
170
|
return !part.text && !part.errorMessage && !part.inlineData && !part.fileData;
|
|
124
171
|
});
|
|
172
|
+
|
|
173
|
+
// 使用确定性 ID:同一服务端事件 + 同一 part 类型始终生成相同 ID,
|
|
174
|
+
// 确保多次 mapSessionMessages 调用产生的消息可以被 id 去重正确识别。
|
|
175
|
+
var partCounter = 0;
|
|
125
176
|
if (textParts.length > 0 || fileDataParts.length > 0) {
|
|
126
177
|
var messageItem = {
|
|
127
|
-
id:
|
|
178
|
+
id: "session-event:".concat(item.id, ":").concat(partCounter++),
|
|
128
179
|
author: item.author,
|
|
129
180
|
invocationId: item.invocationId,
|
|
130
181
|
eventId: item.id,
|
|
@@ -165,7 +216,7 @@ var mapSessionMessages = function mapSessionMessages(sessionEvents) {
|
|
|
165
216
|
}
|
|
166
217
|
otherParts.forEach(function (part) {
|
|
167
218
|
var messageItem = {
|
|
168
|
-
id:
|
|
219
|
+
id: "session-event:".concat(item.id, ":").concat(partCounter++),
|
|
169
220
|
author: item.author,
|
|
170
221
|
invocationId: item.invocationId,
|
|
171
222
|
eventId: item.id,
|
|
@@ -195,62 +246,54 @@ var mapSessionMessages = function mapSessionMessages(sessionEvents) {
|
|
|
195
246
|
});
|
|
196
247
|
return mapped;
|
|
197
248
|
};
|
|
198
|
-
var
|
|
199
|
-
var _messageItem$text;
|
|
200
|
-
return JSON.stringify({
|
|
201
|
-
role: messageItem.role,
|
|
202
|
-
text: ((_messageItem$text = messageItem.text) === null || _messageItem$text === void 0 ? void 0 : _messageItem$text.replace(/\r\n/g, "\n").trim()) || "",
|
|
203
|
-
thought: Boolean(messageItem.thought),
|
|
204
|
-
inlineData: messageItem.inlineData || null,
|
|
205
|
-
fileData: messageItem.fileData || null,
|
|
206
|
-
functionCall: messageItem.functionCall || null,
|
|
207
|
-
functionResponse: messageItem.functionResponse || null,
|
|
208
|
-
executableCode: messageItem.executableCode || null,
|
|
209
|
-
codeExecutionResult: messageItem.codeExecutionResult || null
|
|
210
|
-
});
|
|
211
|
-
};
|
|
212
|
-
var isStreamMessageWithoutServerEventId = function isStreamMessageWithoutServerEventId(messageItem) {
|
|
213
|
-
var eventId = getMessageEventId(messageItem);
|
|
214
|
-
return Boolean(messageItem.invocationId) && (!eventId || eventId === messageItem.invocationId);
|
|
215
|
-
};
|
|
216
|
-
var insertMissingSessionEvents = function insertMissingSessionEvents(currentMessages, sessionEvents) {
|
|
249
|
+
var insertMissingSessionEvents = function insertMissingSessionEvents(currentMessages, sessionEvents, removedInvocationIds) {
|
|
217
250
|
var renderedEventIds = new Set(currentMessages.map(getMessageEventId).filter(Boolean));
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
251
|
+
|
|
252
|
+
// 从所有 sessionEvents 中提取 functionResponse,配对到 currentMessages 中缺少响应的 functionCall
|
|
253
|
+
// (functionResponse 事件的 role 为 user,不应作为独立消息展示,仅用于补齐工具调用状态)
|
|
254
|
+
var nextMessages = _toConsumableArray(currentMessages);
|
|
255
|
+
var fnResMap = new Map();
|
|
256
|
+
sessionEvents.forEach(function (event) {
|
|
224
257
|
var _event$content, _event$content2;
|
|
225
|
-
|
|
226
|
-
|
|
258
|
+
if (((_event$content = event.content) === null || _event$content === void 0 ? void 0 : _event$content.role) !== "user" || !Array.isArray((_event$content2 = event.content) === null || _event$content2 === void 0 ? void 0 : _event$content2.parts)) return;
|
|
259
|
+
event.content.parts.forEach(function (p) {
|
|
260
|
+
var _p$functionResponse;
|
|
261
|
+
if ((_p$functionResponse = p.functionResponse) !== null && _p$functionResponse !== void 0 && _p$functionResponse.id) {
|
|
262
|
+
fnResMap.set(p.functionResponse.id, p.functionResponse);
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
if (fnResMap.size > 0) {
|
|
267
|
+
var paired = false;
|
|
268
|
+
nextMessages = nextMessages.map(function (msg) {
|
|
269
|
+
if (msg.functionCall && !msg.functionResponse) {
|
|
270
|
+
var callId = msg.functionCall.id;
|
|
271
|
+
if (callId && fnResMap.has(callId)) {
|
|
272
|
+
paired = true;
|
|
273
|
+
return _objectSpread(_objectSpread({}, msg), {}, {
|
|
274
|
+
functionResponse: fnResMap.get(callId)
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return msg;
|
|
279
|
+
});
|
|
280
|
+
if (!paired) nextMessages = currentMessages;
|
|
281
|
+
}
|
|
282
|
+
var missingEvents = sessionEvents.filter(function (event) {
|
|
283
|
+
var _event$content3, _event$content4;
|
|
284
|
+
var parts = (_event$content3 = event.content) === null || _event$content3 === void 0 ? void 0 : _event$content3.parts;
|
|
285
|
+
var canRender = Boolean(event.id) && ((_event$content4 = event.content) === null || _event$content4 === void 0 ? void 0 : _event$content4.role) === "model" && Array.isArray(parts) && parts.length > 0;
|
|
227
286
|
if (!canRender || renderedEventIds.has(event.id)) return false;
|
|
228
287
|
|
|
229
|
-
//
|
|
230
|
-
|
|
231
|
-
// 同 invocation 下内容不同或后续出现的事件,仍然按独立 event.id 补入。
|
|
232
|
-
var eventMessages = mapSessionMessages([event]);
|
|
233
|
-
var matchedIndexes = [];
|
|
234
|
-
var isRenderedByStream = eventMessages.length > 0 && eventMessages.every(function (eventMessage) {
|
|
235
|
-
var comparableContent = getComparableMessageContent(eventMessage);
|
|
236
|
-
var matchedIndex = currentMessages.findIndex(function (currentMessage, index) {
|
|
237
|
-
return unmatchedStreamMessageIndexes.has(index) && !matchedIndexes.includes(index) && currentMessage.invocationId === eventMessage.invocationId && getComparableMessageContent(currentMessage) === comparableContent;
|
|
238
|
-
});
|
|
239
|
-
if (matchedIndex < 0) return false;
|
|
240
|
-
matchedIndexes.push(matchedIndex);
|
|
241
|
-
return true;
|
|
242
|
-
});
|
|
243
|
-
if (isRenderedByStream) {
|
|
244
|
-
matchedIndexes.forEach(function (index) {
|
|
245
|
-
return unmatchedStreamMessageIndexes.delete(index);
|
|
246
|
-
});
|
|
288
|
+
// reChat 截断后,忽略被删除的 invocationId 对应的旧 bot 消息
|
|
289
|
+
if (removedInvocationIds && removedInvocationIds.size > 0 && event.invocationId && removedInvocationIds.has(event.invocationId)) {
|
|
247
290
|
return false;
|
|
248
291
|
}
|
|
249
292
|
return true;
|
|
250
293
|
});
|
|
251
|
-
if (missingEvents.length === 0) return
|
|
294
|
+
if (missingEvents.length === 0) return nextMessages;
|
|
252
295
|
var missingMessages = mapSessionMessages(missingEvents);
|
|
253
|
-
if (missingMessages.length === 0) return
|
|
296
|
+
if (missingMessages.length === 0) return nextMessages;
|
|
254
297
|
var eventOrder = new Map(sessionEvents.map(function (event, index) {
|
|
255
298
|
return [event.id, index];
|
|
256
299
|
}));
|
|
@@ -267,7 +310,8 @@ var insertMissingSessionEvents = function insertMissingSessionEvents(currentMess
|
|
|
267
310
|
}
|
|
268
311
|
return Number.POSITIVE_INFINITY;
|
|
269
312
|
};
|
|
270
|
-
|
|
313
|
+
|
|
314
|
+
// nextMessages 已在上方 functionResponse 配对阶段创建,此处直接复用
|
|
271
315
|
missingMessages.forEach(function (messageItem) {
|
|
272
316
|
var targetOrder = getMessageOrder(messageItem);
|
|
273
317
|
var insertIndex = nextMessages.findIndex(function (currentMessage) {
|
|
@@ -290,7 +334,7 @@ function useADKChat(_ref2) {
|
|
|
290
334
|
_ref2$config = _ref2.config,
|
|
291
335
|
config = _ref2$config === void 0 ? {} : _ref2$config,
|
|
292
336
|
_ref2$type = _ref2.type,
|
|
293
|
-
|
|
337
|
+
_type = _ref2$type === void 0 ? "agentDebug" : _ref2$type,
|
|
294
338
|
_ref2$enabled = _ref2.enabled,
|
|
295
339
|
enabled = _ref2$enabled === void 0 ? true : _ref2$enabled,
|
|
296
340
|
strategies = _ref2.strategies,
|
|
@@ -366,11 +410,11 @@ function useADKChat(_ref2) {
|
|
|
366
410
|
messages = _useState20[0],
|
|
367
411
|
setMessages = _useState20[1];
|
|
368
412
|
var pendingSessionEventsRef = useRef(null);
|
|
369
|
-
var sessionEventsFlushTimerRef = useRef(null);
|
|
370
|
-
var sessionEventsSyncingRef = useRef(false);
|
|
371
413
|
var sessionDetailLoadingRef = useRef(false);
|
|
372
414
|
// 用户自定义业务参数 (stateDelta),每次发送请求时携带
|
|
373
415
|
var stateDeltaRef = useRef(undefined);
|
|
416
|
+
// reChat 截断消息时记录被删除的 invocationId,防止轮询把旧 bot 回复补回
|
|
417
|
+
var reChatRemovedInvocationIdsRef = useRef(new Set());
|
|
374
418
|
|
|
375
419
|
// ===== 多会话后台连接管理 =====
|
|
376
420
|
var backgroundRef = useRef(new Map());
|
|
@@ -378,6 +422,7 @@ function useADKChat(_ref2) {
|
|
|
378
422
|
messagesRef.current = messages;
|
|
379
423
|
var currentSessionIdRef = useRef(currentSessionId);
|
|
380
424
|
currentSessionIdRef.current = currentSessionId;
|
|
425
|
+
// 合并消息
|
|
381
426
|
var mergedMessages = useMemo(function () {
|
|
382
427
|
var fnResMap = {};
|
|
383
428
|
var uniqueMessages = deduplicateMessages(messages);
|
|
@@ -399,33 +444,23 @@ function useADKChat(_ref2) {
|
|
|
399
444
|
}, [messages]);
|
|
400
445
|
var textMsgRef = useRef(null);
|
|
401
446
|
var eventDataRef = useRef(new Map());
|
|
402
|
-
var cancelSessionEventsFlush = useCallback(function () {
|
|
403
|
-
if (sessionEventsFlushTimerRef.current === null) return;
|
|
404
|
-
clearTimeout(sessionEventsFlushTimerRef.current);
|
|
405
|
-
sessionEventsFlushTimerRef.current = null;
|
|
406
|
-
}, []);
|
|
407
447
|
var flushPendingSessionEvents = useCallback(function () {
|
|
408
448
|
var pending = pendingSessionEventsRef.current;
|
|
409
|
-
|
|
449
|
+
// 仅在用户正在发送或流式文本拼接时跳过 flush,
|
|
450
|
+
// loading 状态不应阻塞轮询补入(异步任务完成的消息需要在 loading 期间也能补入)
|
|
451
|
+
var replyInProgress = sendingRef.current || textMsgRef.current !== null;
|
|
410
452
|
if (!pending || replyInProgress || pending.sessionId !== currentSessionIdRef.current) return;
|
|
411
|
-
var previewMessages = insertMissingSessionEvents(messagesRef.current, pending.events);
|
|
412
453
|
pendingSessionEventsRef.current = null;
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
if (
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
|
-
sessionEventsSyncingRef.current = false;
|
|
426
|
-
setLoading(false);
|
|
427
|
-
}, 0);
|
|
428
|
-
}, [setLoading]);
|
|
454
|
+
|
|
455
|
+
// 使用 functional update 在同一个 setMessages 回调中完成 diff + 写入,
|
|
456
|
+
// 避免双重调用和 loading 闪烁。仅在有实际新消息时才触发 loading 状态。
|
|
457
|
+
setMessages(function (prev) {
|
|
458
|
+
var nextMessages = insertMissingSessionEvents(prev, pending.events, reChatRemovedInvocationIdsRef.current);
|
|
459
|
+
if (nextMessages === prev) return prev; // 无变化,不触发 re-render
|
|
460
|
+
messagesRef.current = nextMessages;
|
|
461
|
+
return nextMessages;
|
|
462
|
+
});
|
|
463
|
+
}, []);
|
|
429
464
|
var syncSessionEvents = useCallback(function (events, targetSessionId) {
|
|
430
465
|
if (targetSessionId !== currentSessionIdRef.current) return;
|
|
431
466
|
pendingSessionEventsRef.current = {
|
|
@@ -436,12 +471,7 @@ function useADKChat(_ref2) {
|
|
|
436
471
|
}, [flushPendingSessionEvents]);
|
|
437
472
|
useEffect(function () {
|
|
438
473
|
pendingSessionEventsRef.current = null;
|
|
439
|
-
|
|
440
|
-
if (sessionEventsSyncingRef.current) {
|
|
441
|
-
sessionEventsSyncingRef.current = false;
|
|
442
|
-
setLoading(false);
|
|
443
|
-
}
|
|
444
|
-
}, [cancelSessionEventsFlush, currentSessionId, setLoading]);
|
|
474
|
+
}, [currentSessionId]);
|
|
445
475
|
useEffect(function () {
|
|
446
476
|
if (!loading) flushPendingSessionEvents();
|
|
447
477
|
}, [flushPendingSessionEvents, loading]);
|
|
@@ -458,21 +488,21 @@ function useADKChat(_ref2) {
|
|
|
458
488
|
}, []);
|
|
459
489
|
|
|
460
490
|
// 初始化开场白预设置问题
|
|
461
|
-
var insertSuggestedQuestions = function
|
|
491
|
+
var insertSuggestedQuestions = useCallback(function () {
|
|
462
492
|
var suggested_questions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
463
493
|
if (!(suggested_questions !== null && suggested_questions !== void 0 && suggested_questions.length)) return;
|
|
464
494
|
// 无消息内容 且 有建议问题时
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
}
|
|
468
|
-
};
|
|
495
|
+
setSuggestedQuestions(function (prev) {
|
|
496
|
+
return messages.length === 0 ? suggested_questions : prev;
|
|
497
|
+
});
|
|
498
|
+
}, [messages.length]);
|
|
469
499
|
|
|
470
500
|
// 初始化开场白
|
|
471
|
-
var insertPrologue = function
|
|
472
|
-
if (
|
|
473
|
-
setPrologue(
|
|
501
|
+
var insertPrologue = useCallback(function (prologueText) {
|
|
502
|
+
if (prologueText) {
|
|
503
|
+
setPrologue(prologueText);
|
|
474
504
|
}
|
|
475
|
-
};
|
|
505
|
+
}, []);
|
|
476
506
|
|
|
477
507
|
// 更新消息
|
|
478
508
|
var updateMessage = useCallback(function (msg) {
|
|
@@ -539,48 +569,15 @@ function useADKChat(_ref2) {
|
|
|
539
569
|
|
|
540
570
|
// 存储消息
|
|
541
571
|
var storeMessage = useCallback(function (part, event, role) {
|
|
542
|
-
var
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
role: role,
|
|
550
|
-
modelCode: event.modelCode,
|
|
551
|
-
usageMetadata: event.usageMetadata,
|
|
552
|
-
finishReason: event.finishReason,
|
|
553
|
-
raw: event
|
|
554
|
-
};
|
|
555
|
-
if (part) {
|
|
556
|
-
if (part.inlineData) {
|
|
557
|
-
msg.inlineData = {
|
|
558
|
-
displayName: part.inlineData.displayName,
|
|
559
|
-
data: part.inlineData.data,
|
|
560
|
-
mimeType: part.inlineData.mimeType
|
|
561
|
-
};
|
|
562
|
-
} else if (part.text) {
|
|
563
|
-
var _event$groundingMetad;
|
|
564
|
-
msg.text = part.text;
|
|
565
|
-
msg.thought = part.thought;
|
|
566
|
-
if (event !== null && event !== void 0 && (_event$groundingMetad = event.groundingMetadata) !== null && _event$groundingMetad !== void 0 && (_event$groundingMetad = _event$groundingMetad.searchEntryPoint) !== null && _event$groundingMetad !== void 0 && _event$groundingMetad.renderedContent) {
|
|
567
|
-
msg.renderedContent = event.groundingMetadata.searchEntryPoint.renderedContent;
|
|
568
|
-
}
|
|
569
|
-
} else if (part.fileData) {
|
|
570
|
-
msg.fileData = [part.fileData];
|
|
571
|
-
} else if (part.functionCall) {
|
|
572
|
-
msg.functionCall = part.functionCall;
|
|
573
|
-
} else if (part.functionResponse) {
|
|
574
|
-
msg.functionResponse = part.functionResponse;
|
|
575
|
-
} else if (part.executableCode) {
|
|
576
|
-
msg.executableCode = part.executableCode;
|
|
577
|
-
} else if (part.codeExecutionResult) {
|
|
578
|
-
msg.codeExecutionResult = part.codeExecutionResult;
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
if (part && Object.keys(part).length > 0) {
|
|
582
|
-
insertMessage(msg);
|
|
572
|
+
var _event$groundingMetad;
|
|
573
|
+
if (!part || Object.keys(part).length === 0) return;
|
|
574
|
+
var msg = buildNonTextMessage(event, part, role);
|
|
575
|
+
|
|
576
|
+
// groundingMetadata 仅在前台 SSE 场景需要
|
|
577
|
+
if (part.text && event !== null && event !== void 0 && (_event$groundingMetad = event.groundingMetadata) !== null && _event$groundingMetad !== void 0 && (_event$groundingMetad = _event$groundingMetad.searchEntryPoint) !== null && _event$groundingMetad !== void 0 && _event$groundingMetad.renderedContent) {
|
|
578
|
+
msg.renderedContent = event.groundingMetadata.searchEntryPoint.renderedContent;
|
|
583
579
|
}
|
|
580
|
+
insertMessage(msg);
|
|
584
581
|
}, [insertMessage]);
|
|
585
582
|
|
|
586
583
|
// 处理消息部分(关键更新)
|
|
@@ -639,9 +636,9 @@ function useADKChat(_ref2) {
|
|
|
639
636
|
|
|
640
637
|
// 处理建议类消息
|
|
641
638
|
var processFollowupPart = useCallback(function (event) {
|
|
642
|
-
var _event$
|
|
639
|
+
var _event$content5;
|
|
643
640
|
// 获取建议类消息的文本内容
|
|
644
|
-
var part = (event === null || event === void 0 || (_event$
|
|
641
|
+
var part = (event === null || event === void 0 || (_event$content5 = event.content) === null || _event$content5 === void 0 || (_event$content5 = _event$content5.parts) === null || _event$content5 === void 0 ? void 0 : _event$content5[0]) || null;
|
|
645
642
|
var text = (part === null || part === void 0 ? void 0 : part.text) || "";
|
|
646
643
|
storeEvents(part, event);
|
|
647
644
|
if (text) {
|
|
@@ -649,7 +646,7 @@ function useADKChat(_ref2) {
|
|
|
649
646
|
return [].concat(_toConsumableArray(prev), [text]);
|
|
650
647
|
});
|
|
651
648
|
}
|
|
652
|
-
}, [storeEvents
|
|
649
|
+
}, [storeEvents]);
|
|
653
650
|
|
|
654
651
|
// 处理错误消息
|
|
655
652
|
var processErrorMessage = useCallback(function (chunkJson) {
|
|
@@ -795,20 +792,7 @@ function useADKChat(_ref2) {
|
|
|
795
792
|
}
|
|
796
793
|
} else {
|
|
797
794
|
bgTextMsg = null;
|
|
798
|
-
|
|
799
|
-
id: v4(),
|
|
800
|
-
author: chunkJson.author,
|
|
801
|
-
invocationId: chunkJson.invocationId,
|
|
802
|
-
eventId: chunkJson.id,
|
|
803
|
-
timestamp: chunkJson.timestamp,
|
|
804
|
-
role: "bot"
|
|
805
|
-
};
|
|
806
|
-
if (part.functionCall) msg.functionCall = part.functionCall;else if (part.functionResponse) msg.functionResponse = part.functionResponse;else if (part.executableCode) msg.executableCode = part.executableCode;else if (part.codeExecutionResult) msg.codeExecutionResult = part.codeExecutionResult;else {
|
|
807
|
-
msg.text = part.text;
|
|
808
|
-
msg.thought = part.thought;
|
|
809
|
-
if (part.fileData) msg.fileData = [part.fileData];
|
|
810
|
-
}
|
|
811
|
-
bg.messages = [].concat(_toConsumableArray(bg.messages), [msg]);
|
|
795
|
+
bg.messages = [].concat(_toConsumableArray(bg.messages), [buildNonTextMessage(chunkJson, part)]);
|
|
812
796
|
}
|
|
813
797
|
}
|
|
814
798
|
} catch (err) {
|
|
@@ -843,7 +827,7 @@ function useADKChat(_ref2) {
|
|
|
843
827
|
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
844
828
|
var _chunkJson2;
|
|
845
829
|
var _part = _step3.value;
|
|
846
|
-
// partial为
|
|
830
|
+
// partial为 false 时忽略该条消息文本
|
|
847
831
|
processPart(chunkJson, _part, ((_chunkJson2 = chunkJson) === null || _chunkJson2 === void 0 ? void 0 : _chunkJson2.partial) === false);
|
|
848
832
|
}
|
|
849
833
|
} catch (err) {
|
|
@@ -865,6 +849,12 @@ function useADKChat(_ref2) {
|
|
|
865
849
|
bg.loading = false;
|
|
866
850
|
bg.textMsgRef = null;
|
|
867
851
|
}
|
|
852
|
+
// 如果该后台会话已被恢复到前台(backgroundRef 中已删除),
|
|
853
|
+
// 需要更新前台 loading 状态
|
|
854
|
+
if (!backgroundRef.current.has(targetSessionId) && currentSessionIdRef.current === targetSessionId) {
|
|
855
|
+
setLoading(false);
|
|
856
|
+
textMsgRef.current = null;
|
|
857
|
+
}
|
|
868
858
|
} else {
|
|
869
859
|
setLoading(false);
|
|
870
860
|
if (textMsgRef.current) {
|
|
@@ -872,6 +862,7 @@ function useADKChat(_ref2) {
|
|
|
872
862
|
onMessage === null || onMessage === void 0 || onMessage(((_textMsgRef$current = textMsgRef.current) === null || _textMsgRef$current === void 0 ? void 0 : _textMsgRef$current.text) || "", textMsgRef.current);
|
|
873
863
|
}
|
|
874
864
|
textMsgRef.current = null;
|
|
865
|
+
ctrl.current = null;
|
|
875
866
|
}
|
|
876
867
|
resolve();
|
|
877
868
|
},
|
|
@@ -880,8 +871,14 @@ function useADKChat(_ref2) {
|
|
|
880
871
|
if (isBackground) {
|
|
881
872
|
var bg = backgroundRef.current.get(targetSessionId);
|
|
882
873
|
if (bg) bg.loading = false;
|
|
874
|
+
// 同上:后台会话已恢复到前台时同步 loading 状态
|
|
875
|
+
if (!backgroundRef.current.has(targetSessionId) && currentSessionIdRef.current === targetSessionId) {
|
|
876
|
+
setLoading(false);
|
|
877
|
+
ctrl.current = null;
|
|
878
|
+
}
|
|
883
879
|
} else {
|
|
884
880
|
setLoading(false);
|
|
881
|
+
ctrl.current = null;
|
|
885
882
|
}
|
|
886
883
|
resolve();
|
|
887
884
|
console.error("EventSource failed:", error);
|
|
@@ -889,7 +886,7 @@ function useADKChat(_ref2) {
|
|
|
889
886
|
}
|
|
890
887
|
});
|
|
891
888
|
});
|
|
892
|
-
}, [
|
|
889
|
+
}, [processActionArtifact, processErrorMessage, processPart, updateLastBotEventMeta]);
|
|
893
890
|
|
|
894
891
|
// 发送会话
|
|
895
892
|
var startChat = /*#__PURE__*/function () {
|
|
@@ -914,6 +911,8 @@ function useADKChat(_ref2) {
|
|
|
914
911
|
sendingRef.current = true;
|
|
915
912
|
// 清空建议问题
|
|
916
913
|
setSuggestedQuestions([]);
|
|
914
|
+
// 正常发送时重置 reChat 删除标记
|
|
915
|
+
reChatRemovedInvocationIdsRef.current = new Set();
|
|
917
916
|
// 发送消息
|
|
918
917
|
setMessages(function (prev) {
|
|
919
918
|
var temp = _toConsumableArray(prev);
|
|
@@ -950,8 +949,8 @@ function useADKChat(_ref2) {
|
|
|
950
949
|
}
|
|
951
950
|
return temp;
|
|
952
951
|
});
|
|
953
|
-
_context2.prev =
|
|
954
|
-
_context2.next =
|
|
952
|
+
_context2.prev = 9;
|
|
953
|
+
_context2.next = 12;
|
|
955
954
|
return sendMessageRequest(_objectSpread({
|
|
956
955
|
stream: true,
|
|
957
956
|
sessionId: currentSessionId,
|
|
@@ -976,18 +975,18 @@ function useADKChat(_ref2) {
|
|
|
976
975
|
}, stateDeltaRef.current !== undefined && {
|
|
977
976
|
stateDelta: stateDeltaRef.current
|
|
978
977
|
}));
|
|
979
|
-
case
|
|
980
|
-
_context2.prev =
|
|
978
|
+
case 12:
|
|
979
|
+
_context2.prev = 12;
|
|
981
980
|
sendingRef.current = false;
|
|
982
|
-
return _context2.finish(
|
|
983
|
-
case
|
|
981
|
+
return _context2.finish(12);
|
|
982
|
+
case 15:
|
|
984
983
|
// 获取聊天记录
|
|
985
984
|
initAppConversations();
|
|
986
|
-
case
|
|
985
|
+
case 16:
|
|
987
986
|
case "end":
|
|
988
987
|
return _context2.stop();
|
|
989
988
|
}
|
|
990
|
-
}, _callee2, null, [[
|
|
989
|
+
}, _callee2, null, [[9,, 12, 15]]);
|
|
991
990
|
}));
|
|
992
991
|
return function startChat(_x) {
|
|
993
992
|
return _ref5.apply(this, arguments);
|
|
@@ -997,7 +996,7 @@ function useADKChat(_ref2) {
|
|
|
997
996
|
// 重新发送会话
|
|
998
997
|
var reChat = /*#__PURE__*/function () {
|
|
999
998
|
var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {
|
|
1000
|
-
var lastUserIndex, newMessages, lastUserMessage, _lastUserMessage$text, text, _lastUserMessage$file, fileData;
|
|
999
|
+
var lastUserIndex, newMessages, removedInvocationIds, i, msg, lastUserMessage, _lastUserMessage$text, text, _lastUserMessage$file, fileData;
|
|
1001
1000
|
return _regeneratorRuntime().wrap(function _callee3$(_context3) {
|
|
1002
1001
|
while (1) switch (_context3.prev = _context3.next) {
|
|
1003
1002
|
case 0:
|
|
@@ -1030,10 +1029,18 @@ function useADKChat(_ref2) {
|
|
|
1030
1029
|
case 10:
|
|
1031
1030
|
newMessages = messages.slice(0, lastUserIndex + 1);
|
|
1032
1031
|
setMessages(newMessages);
|
|
1032
|
+
|
|
1033
|
+
// 收集被截断的 bot 消息的 invocationId,轮询时忽略这些旧回复
|
|
1034
|
+
removedInvocationIds = new Set();
|
|
1035
|
+
for (i = lastUserIndex + 1; i < messages.length; i++) {
|
|
1036
|
+
msg = messages[i];
|
|
1037
|
+
if (msg.invocationId) removedInvocationIds.add(msg.invocationId);
|
|
1038
|
+
}
|
|
1039
|
+
reChatRemovedInvocationIdsRef.current = removedInvocationIds;
|
|
1033
1040
|
lastUserMessage = newMessages[lastUserIndex];
|
|
1034
1041
|
_lastUserMessage$text = lastUserMessage.text, text = _lastUserMessage$text === void 0 ? "" : _lastUserMessage$text, _lastUserMessage$file = lastUserMessage.fileData, fileData = _lastUserMessage$file === void 0 ? [] : _lastUserMessage$file;
|
|
1035
|
-
_context3.prev =
|
|
1036
|
-
_context3.next =
|
|
1042
|
+
_context3.prev = 17;
|
|
1043
|
+
_context3.next = 20;
|
|
1037
1044
|
return sendMessageRequest(_objectSpread({
|
|
1038
1045
|
stream: true,
|
|
1039
1046
|
sessionId: currentSessionId,
|
|
@@ -1053,15 +1060,15 @@ function useADKChat(_ref2) {
|
|
|
1053
1060
|
}, stateDeltaRef.current !== undefined && {
|
|
1054
1061
|
stateDelta: stateDeltaRef.current
|
|
1055
1062
|
}));
|
|
1056
|
-
case 17:
|
|
1057
|
-
_context3.prev = 17;
|
|
1058
|
-
sendingRef.current = false;
|
|
1059
|
-
return _context3.finish(17);
|
|
1060
1063
|
case 20:
|
|
1064
|
+
_context3.prev = 20;
|
|
1065
|
+
sendingRef.current = false;
|
|
1066
|
+
return _context3.finish(20);
|
|
1067
|
+
case 23:
|
|
1061
1068
|
case "end":
|
|
1062
1069
|
return _context3.stop();
|
|
1063
1070
|
}
|
|
1064
|
-
}, _callee3, null, [[
|
|
1071
|
+
}, _callee3, null, [[17,, 20, 23]]);
|
|
1065
1072
|
}));
|
|
1066
1073
|
return function reChat() {
|
|
1067
1074
|
return _ref6.apply(this, arguments);
|
|
@@ -1097,19 +1104,19 @@ function useADKChat(_ref2) {
|
|
|
1097
1104
|
var stopChat = useCallback(function () {
|
|
1098
1105
|
var _ctrl$current;
|
|
1099
1106
|
pendingSessionEventsRef.current = null;
|
|
1100
|
-
cancelSessionEventsFlush();
|
|
1101
|
-
sessionEventsSyncingRef.current = false;
|
|
1102
1107
|
(_ctrl$current = ctrl.current) === null || _ctrl$current === void 0 || _ctrl$current.abort();
|
|
1103
1108
|
ctrl.current = null;
|
|
1104
1109
|
setLoading(false);
|
|
1105
1110
|
textMsgRef.current = null;
|
|
1106
|
-
}, [
|
|
1111
|
+
}, [setLoading]);
|
|
1107
1112
|
|
|
1108
1113
|
// 清除/重置会话
|
|
1109
1114
|
var clearChat = function clearChat() {
|
|
1110
1115
|
var _appInfo$onboardingIn, _appInfo$onboardingIn2;
|
|
1111
1116
|
var newSessionId = v4();
|
|
1112
1117
|
setCurrentSessionId(newSessionId);
|
|
1118
|
+
// 清除 reChat 删除标记
|
|
1119
|
+
reChatRemovedInvocationIdsRef.current = new Set();
|
|
1113
1120
|
// 重置聊天内容
|
|
1114
1121
|
stopChat();
|
|
1115
1122
|
setPrologue((appInfo === null || appInfo === void 0 || (_appInfo$onboardingIn = appInfo.onboardingInfo) === null || _appInfo$onboardingIn === void 0 ? void 0 : _appInfo$onboardingIn.prologue) || "");
|
|
@@ -1129,12 +1136,12 @@ function useADKChat(_ref2) {
|
|
|
1129
1136
|
// 设置当前会话详情
|
|
1130
1137
|
var setCurrentSession = /*#__PURE__*/function () {
|
|
1131
1138
|
var _ref7 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(sessionId) {
|
|
1132
|
-
var prevSessionId, bg, _yield$fetchSessionDe, data, result, _appInfo$onboardingIn3, _appInfo$onboardingIn4;
|
|
1139
|
+
var prevSessionId, bg, isSseStillActive, _yield$fetchSessionDe, data, result, _appInfo$onboardingIn3, _appInfo$onboardingIn4;
|
|
1133
1140
|
return _regeneratorRuntime().wrap(function _callee4$(_context4) {
|
|
1134
1141
|
while (1) switch (_context4.prev = _context4.next) {
|
|
1135
1142
|
case 0:
|
|
1136
1143
|
if (!sessionId) {
|
|
1137
|
-
_context4.next =
|
|
1144
|
+
_context4.next = 35;
|
|
1138
1145
|
break;
|
|
1139
1146
|
}
|
|
1140
1147
|
if (!(sessionId === currentSessionId)) {
|
|
@@ -1144,11 +1151,8 @@ function useADKChat(_ref2) {
|
|
|
1144
1151
|
return _context4.abrupt("return");
|
|
1145
1152
|
case 3:
|
|
1146
1153
|
pendingSessionEventsRef.current = null;
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
sessionEventsSyncingRef.current = false;
|
|
1150
|
-
setLoading(false);
|
|
1151
|
-
}
|
|
1154
|
+
// 切换会话时重置 reChat 删除标记
|
|
1155
|
+
reChatRemovedInvocationIdsRef.current = new Set();
|
|
1152
1156
|
|
|
1153
1157
|
// 1. 将当前会话挂起到后台(不中断 SSE 连接)
|
|
1154
1158
|
prevSessionId = currentSessionId;
|
|
@@ -1176,31 +1180,35 @@ function useADKChat(_ref2) {
|
|
|
1176
1180
|
// 2. 尝试从后台恢复目标会话
|
|
1177
1181
|
bg = backgroundRef.current.get(sessionId);
|
|
1178
1182
|
if (!bg) {
|
|
1179
|
-
_context4.next =
|
|
1183
|
+
_context4.next = 19;
|
|
1180
1184
|
break;
|
|
1181
1185
|
}
|
|
1182
1186
|
setMessages(bg.messages);
|
|
1183
|
-
|
|
1187
|
+
messagesRef.current = bg.messages;
|
|
1184
1188
|
textMsgRef.current = bg.textMsgRef;
|
|
1185
|
-
|
|
1189
|
+
// 仅当 SSE 连接还在运行时才恢复 loading 状态,
|
|
1190
|
+
// 避免 SSE 已关闭但 bg 快照中 loading 仍为 true 导致 sender 永久卡住
|
|
1191
|
+
isSseStillActive = bg.loading && !bg.ctrl.signal.aborted;
|
|
1192
|
+
setLoading(isSseStillActive);
|
|
1193
|
+
ctrl.current = isSseStillActive ? bg.ctrl : null;
|
|
1186
1194
|
setCurrentSessionId(sessionId);
|
|
1187
1195
|
setInitialized(true);
|
|
1188
1196
|
backgroundRef.current.delete(sessionId);
|
|
1189
1197
|
return _context4.abrupt("return");
|
|
1190
|
-
case
|
|
1198
|
+
case 19:
|
|
1191
1199
|
// 3. 后台没有目标 session,走 API 加载(原有逻辑)
|
|
1192
1200
|
setInitialized(false);
|
|
1193
1201
|
setCurrentSessionId(sessionId);
|
|
1194
1202
|
sessionDetailLoadingRef.current = true;
|
|
1195
|
-
_context4.prev =
|
|
1196
|
-
_context4.next =
|
|
1203
|
+
_context4.prev = 22;
|
|
1204
|
+
_context4.next = 25;
|
|
1197
1205
|
return fetchSessionDetail({
|
|
1198
1206
|
url: url,
|
|
1199
1207
|
appNo: appNo,
|
|
1200
1208
|
sessionId: sessionId,
|
|
1201
1209
|
token: tokenRef.current
|
|
1202
1210
|
});
|
|
1203
|
-
case
|
|
1211
|
+
case 25:
|
|
1204
1212
|
_yield$fetchSessionDe = _context4.sent;
|
|
1205
1213
|
data = _yield$fetchSessionDe.data;
|
|
1206
1214
|
result = _yield$fetchSessionDe.result;
|
|
@@ -1212,21 +1220,21 @@ function useADKChat(_ref2) {
|
|
|
1212
1220
|
setSuggestedQuestions((appInfo === null || appInfo === void 0 || (_appInfo$onboardingIn4 = appInfo.onboardingInfo) === null || _appInfo$onboardingIn4 === void 0 ? void 0 : _appInfo$onboardingIn4.suggested_questions) || []);
|
|
1213
1221
|
}
|
|
1214
1222
|
}
|
|
1215
|
-
case
|
|
1216
|
-
_context4.prev =
|
|
1223
|
+
case 29:
|
|
1224
|
+
_context4.prev = 29;
|
|
1217
1225
|
sessionDetailLoadingRef.current = false;
|
|
1218
1226
|
setInitialized(true);
|
|
1219
|
-
return _context4.finish(
|
|
1220
|
-
case
|
|
1221
|
-
_context4.next =
|
|
1227
|
+
return _context4.finish(29);
|
|
1228
|
+
case 33:
|
|
1229
|
+
_context4.next = 36;
|
|
1222
1230
|
break;
|
|
1223
|
-
case 34:
|
|
1224
|
-
setCurrentSessionId(v4());
|
|
1225
1231
|
case 35:
|
|
1232
|
+
setCurrentSessionId(v4());
|
|
1233
|
+
case 36:
|
|
1226
1234
|
case "end":
|
|
1227
1235
|
return _context4.stop();
|
|
1228
1236
|
}
|
|
1229
|
-
}, _callee4, null, [[
|
|
1237
|
+
}, _callee4, null, [[22,, 29, 33]]);
|
|
1230
1238
|
}));
|
|
1231
1239
|
return function setCurrentSession(_x2) {
|
|
1232
1240
|
return _ref7.apply(this, arguments);
|
|
@@ -1561,7 +1569,7 @@ function useADKChat(_ref2) {
|
|
|
1561
1569
|
return _regeneratorRuntime().wrap(function _callee10$(_context10) {
|
|
1562
1570
|
while (1) switch (_context10.prev = _context10.next) {
|
|
1563
1571
|
case 0:
|
|
1564
|
-
if (!(requesting || sessionDetailLoadingRef.current)) {
|
|
1572
|
+
if (!(disposed || requesting || sessionDetailLoadingRef.current)) {
|
|
1565
1573
|
_context10.next = 2;
|
|
1566
1574
|
break;
|
|
1567
1575
|
}
|
|
@@ -1602,7 +1610,8 @@ function useADKChat(_ref2) {
|
|
|
1602
1610
|
return _ref13.apply(this, arguments);
|
|
1603
1611
|
};
|
|
1604
1612
|
}();
|
|
1605
|
-
|
|
1613
|
+
|
|
1614
|
+
// 不立即执行首次 poll,避免与 initAppConversations / setCurrentSession / fetchSessionDetail 竞争。首次数据由初始化流程加载,轮询仅负责后续增量同步。
|
|
1606
1615
|
var timer = window.setInterval(poll, sessionEventsPollingInterval);
|
|
1607
1616
|
return function () {
|
|
1608
1617
|
disposed = true;
|
|
@@ -1614,7 +1623,6 @@ function useADKChat(_ref2) {
|
|
|
1614
1623
|
useEffect(function () {
|
|
1615
1624
|
return function () {
|
|
1616
1625
|
var _ctrl$current2;
|
|
1617
|
-
cancelSessionEventsFlush();
|
|
1618
1626
|
(_ctrl$current2 = ctrl.current) === null || _ctrl$current2 === void 0 || _ctrl$current2.abort();
|
|
1619
1627
|
backgroundRef.current.forEach(function (bg) {
|
|
1620
1628
|
var _bg$ctrl;
|
|
@@ -1622,7 +1630,7 @@ function useADKChat(_ref2) {
|
|
|
1622
1630
|
});
|
|
1623
1631
|
backgroundRef.current.clear();
|
|
1624
1632
|
};
|
|
1625
|
-
}, [
|
|
1633
|
+
}, []);
|
|
1626
1634
|
return {
|
|
1627
1635
|
appInfo: appInfo,
|
|
1628
1636
|
startChat: startChat,
|