@ai-group/chat-sdk 3.6.3 → 3.6.5

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 (34) hide show
  1. package/dist/cjs/components/FileGallery/index.d.ts +0 -30
  2. package/dist/cjs/components/FileGallery/index.js +287 -209
  3. package/dist/cjs/components/FileGallery/index.js.map +2 -2
  4. package/dist/cjs/components/FileGallery/styles.d.ts +5 -0
  5. package/dist/cjs/components/FileGallery/styles.js +106 -0
  6. package/dist/cjs/components/FileGallery/styles.js.map +2 -2
  7. package/dist/cjs/components/XAdkProvider/compound/Sender.js +3 -2
  8. package/dist/cjs/components/XAdkProvider/compound/Sender.js.map +2 -2
  9. package/dist/cjs/components/XAdkSender/index.js +1 -0
  10. package/dist/cjs/components/XAdkSender/index.js.map +2 -2
  11. package/dist/cjs/hooks/useADKChat.js +392 -157
  12. package/dist/cjs/hooks/useADKChat.js.map +3 -3
  13. package/dist/cjs/types/FileGallery.d.ts +41 -0
  14. package/dist/cjs/types/FileGallery.js.map +1 -1
  15. package/dist/cjs/types/XAdkProvider.d.ts +4 -0
  16. package/dist/cjs/types/XAdkProvider.js.map +1 -1
  17. package/dist/esm/components/FileGallery/index.d.ts +0 -30
  18. package/dist/esm/components/FileGallery/index.js +362 -364
  19. package/dist/esm/components/FileGallery/index.js.map +1 -1
  20. package/dist/esm/components/FileGallery/styles.d.ts +5 -0
  21. package/dist/esm/components/FileGallery/styles.js +10 -2
  22. package/dist/esm/components/FileGallery/styles.js.map +1 -1
  23. package/dist/esm/components/XAdkProvider/compound/Sender.js +5 -3
  24. package/dist/esm/components/XAdkProvider/compound/Sender.js.map +1 -1
  25. package/dist/esm/components/XAdkSender/index.js +1 -0
  26. package/dist/esm/components/XAdkSender/index.js.map +1 -1
  27. package/dist/esm/hooks/useADKChat.js +347 -130
  28. package/dist/esm/hooks/useADKChat.js.map +1 -1
  29. package/dist/esm/types/FileGallery.d.ts +41 -0
  30. package/dist/esm/types/FileGallery.js.map +1 -1
  31. package/dist/esm/types/XAdkProvider.d.ts +4 -0
  32. package/dist/esm/types/XAdkProvider.js.map +1 -1
  33. package/dist/umd/chat-sdk.min.js +1 -1
  34. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  import _regeneratorRuntime from "@babel/runtime/helpers/esm/regeneratorRuntime";
2
2
  import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
3
- import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
4
3
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
4
+ import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
5
5
  import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
6
6
  import _createForOfIteratorHelper from "@babel/runtime/helpers/esm/createForOfIteratorHelper";
7
7
  import { useEffect, useCallback, useMemo, useRef, useState } from "react";
@@ -44,10 +44,196 @@ var combineTextParts = function combineTextParts(parts) {
44
44
  }
45
45
  return result;
46
46
  };
47
+ var DEFAULT_SESSION_EVENTS_POLLING_INTERVAL = 10000;
48
+ var getMessageEventId = function getMessageEventId(messageItem) {
49
+ var _messageItem$raw;
50
+ return messageItem.eventId || ((_messageItem$raw = messageItem.raw) === null || _messageItem$raw === void 0 ? void 0 : _messageItem$raw.id);
51
+ };
52
+ var mapSessionMessages = function mapSessionMessages(sessionEvents) {
53
+ var mapped = [];
54
+ sessionEvents.forEach(function (item) {
55
+ if (!item || !item.content || !Array.isArray(item.content.parts)) return;
56
+ // 后端为异步任务插入的用户事件仅用于关联任务,不在页面展示。
57
+ if (item.author === "user" && item.content.parts.some(function (part) {
58
+ return part.task;
59
+ })) return;
60
+ var role = (item.content.role || "").toLowerCase() === "user" ? "user" : "bot";
61
+ var parts = item.content.parts.filter(function (part) {
62
+ if (!part) return false;
63
+ return Boolean(part.text || part.inlineData || part.functionCall || part.functionResponse || part.fileData || part.executableCode || part.codeExecutionResult || part.errorMessage);
64
+ });
65
+ if (parts.length === 0) return;
66
+ var textParts = parts.filter(function (part) {
67
+ return part.text || part.errorMessage || part.inlineData;
68
+ });
69
+ var fileDataParts = parts.filter(function (part) {
70
+ return part.fileData;
71
+ });
72
+ var otherParts = parts.filter(function (part) {
73
+ return !part.text && !part.errorMessage && !part.inlineData && !part.fileData;
74
+ });
75
+ if (textParts.length > 0 || fileDataParts.length > 0) {
76
+ var messageItem = {
77
+ id: v4(),
78
+ author: item.author,
79
+ invocationId: item.invocationId,
80
+ eventId: item.id,
81
+ timestamp: item.timestamp,
82
+ isLike: item.isLike,
83
+ role: role,
84
+ modelCode: item.modelCode,
85
+ usageMetadata: item.usageMetadata,
86
+ finishReason: item.finishReason,
87
+ raw: item
88
+ };
89
+ textParts.forEach(function (part) {
90
+ if (part.inlineData) {
91
+ messageItem.inlineData = {
92
+ displayName: part.inlineData.displayName,
93
+ data: part.inlineData.data,
94
+ mimeType: part.inlineData.mimeType
95
+ };
96
+ }
97
+ if (part.text) {
98
+ messageItem.text = (messageItem.text ? "".concat(messageItem.text, "\n") : "") + part.text;
99
+ if (typeof part.thought !== "undefined") messageItem.thought = part.thought;
100
+ }
101
+ if (part.errorMessage) {
102
+ messageItem.text = (messageItem.text ? "".concat(messageItem.text, "\n") : "") + part.errorMessage;
103
+ }
104
+ });
105
+ if (fileDataParts.length > 0) {
106
+ messageItem.fileData = fileDataParts.map(function (part) {
107
+ return {
108
+ displayName: part.fileData.displayName || "",
109
+ fileUri: part.fileData.fileUri,
110
+ mimeType: part.fileData.mimeType
111
+ };
112
+ });
113
+ }
114
+ mapped.push(messageItem);
115
+ }
116
+ otherParts.forEach(function (part) {
117
+ var messageItem = {
118
+ id: v4(),
119
+ author: item.author,
120
+ invocationId: item.invocationId,
121
+ eventId: item.id,
122
+ timestamp: item.timestamp,
123
+ isLike: item.isLike,
124
+ role: role,
125
+ modelCode: item.modelCode,
126
+ usageMetadata: item.usageMetadata,
127
+ finishReason: item.finishReason,
128
+ raw: item
129
+ };
130
+ if (part.functionCall) messageItem.functionCall = part.functionCall;
131
+ if (part.executableCode) messageItem.executableCode = part.executableCode;
132
+ if (part.codeExecutionResult) messageItem.codeExecutionResult = part.codeExecutionResult;
133
+ if (part.functionResponse) {
134
+ var functionCallMessage = mapped.find(function (currentMessage) {
135
+ var _currentMessage$funct, _part$functionRespons;
136
+ return ((_currentMessage$funct = currentMessage.functionCall) === null || _currentMessage$funct === void 0 ? void 0 : _currentMessage$funct.id) === ((_part$functionRespons = part.functionResponse) === null || _part$functionRespons === void 0 ? void 0 : _part$functionRespons.id);
137
+ });
138
+ if (functionCallMessage) {
139
+ functionCallMessage.functionResponse = part.functionResponse;
140
+ }
141
+ return;
142
+ }
143
+ mapped.push(messageItem);
144
+ });
145
+ });
146
+ return mapped;
147
+ };
148
+ var getComparableMessageContent = function getComparableMessageContent(messageItem) {
149
+ var _messageItem$text;
150
+ return JSON.stringify({
151
+ role: messageItem.role,
152
+ text: ((_messageItem$text = messageItem.text) === null || _messageItem$text === void 0 ? void 0 : _messageItem$text.replace(/\r\n/g, "\n").trim()) || "",
153
+ thought: Boolean(messageItem.thought),
154
+ inlineData: messageItem.inlineData || null,
155
+ fileData: messageItem.fileData || null,
156
+ functionCall: messageItem.functionCall || null,
157
+ functionResponse: messageItem.functionResponse || null,
158
+ executableCode: messageItem.executableCode || null,
159
+ codeExecutionResult: messageItem.codeExecutionResult || null
160
+ });
161
+ };
162
+ var isStreamMessageWithoutServerEventId = function isStreamMessageWithoutServerEventId(messageItem) {
163
+ var eventId = getMessageEventId(messageItem);
164
+ return Boolean(messageItem.invocationId) && (!eventId || eventId === messageItem.invocationId);
165
+ };
166
+ var insertMissingSessionEvents = function insertMissingSessionEvents(currentMessages, sessionEvents) {
167
+ var renderedEventIds = new Set(currentMessages.map(getMessageEventId).filter(Boolean));
168
+ var unmatchedStreamMessageIndexes = new Set(currentMessages.map(function (messageItem, index) {
169
+ return isStreamMessageWithoutServerEventId(messageItem) ? index : -1;
170
+ }).filter(function (index) {
171
+ return index >= 0;
172
+ }));
173
+ var missingEvents = sessionEvents.filter(function (event) {
174
+ var _event$content, _event$content2;
175
+ var parts = (_event$content = event.content) === null || _event$content === void 0 ? void 0 : _event$content.parts;
176
+ var canRender = Boolean(event.id) && ((_event$content2 = event.content) === null || _event$content2 === void 0 ? void 0 : _event$content2.role) === "model" && Array.isArray(parts) && parts.length > 0;
177
+ if (!canRender || renderedEventIds.has(event.id)) return false;
178
+
179
+ // 新版 SSE 包装数据没有事件 id,只能临时使用 invocationId。
180
+ // 用 invocationId + 完整渲染内容做一次性身份对齐,避免会话轮询重复插入;
181
+ // 同 invocation 下内容不同或后续出现的事件,仍然按独立 event.id 补入。
182
+ var eventMessages = mapSessionMessages([event]);
183
+ var matchedIndexes = [];
184
+ var isRenderedByStream = eventMessages.length > 0 && eventMessages.every(function (eventMessage) {
185
+ var comparableContent = getComparableMessageContent(eventMessage);
186
+ var matchedIndex = currentMessages.findIndex(function (currentMessage, index) {
187
+ return unmatchedStreamMessageIndexes.has(index) && !matchedIndexes.includes(index) && currentMessage.invocationId === eventMessage.invocationId && getComparableMessageContent(currentMessage) === comparableContent;
188
+ });
189
+ if (matchedIndex < 0) return false;
190
+ matchedIndexes.push(matchedIndex);
191
+ return true;
192
+ });
193
+ if (isRenderedByStream) {
194
+ matchedIndexes.forEach(function (index) {
195
+ return unmatchedStreamMessageIndexes.delete(index);
196
+ });
197
+ return false;
198
+ }
199
+ return true;
200
+ });
201
+ if (missingEvents.length === 0) return currentMessages;
202
+ var missingMessages = mapSessionMessages(missingEvents);
203
+ if (missingMessages.length === 0) return currentMessages;
204
+ var eventOrder = new Map(sessionEvents.map(function (event, index) {
205
+ return [event.id, index];
206
+ }));
207
+ var getMessageOrder = function getMessageOrder(messageItem) {
208
+ var _messageItem$timestam, _messageItem$raw2;
209
+ var eventId = getMessageEventId(messageItem);
210
+ if (eventId && eventOrder.has(eventId)) return eventOrder.get(eventId);
211
+ var timestamp = (_messageItem$timestam = messageItem.timestamp) !== null && _messageItem$timestam !== void 0 ? _messageItem$timestam : (_messageItem$raw2 = messageItem.raw) === null || _messageItem$raw2 === void 0 ? void 0 : _messageItem$raw2.timestamp;
212
+ if (timestamp !== undefined) {
213
+ var nextEventIndex = sessionEvents.findIndex(function (event) {
214
+ return (event.timestamp || 0) > timestamp;
215
+ });
216
+ return nextEventIndex < 0 ? sessionEvents.length + 0.5 : nextEventIndex - 0.5;
217
+ }
218
+ return Number.POSITIVE_INFINITY;
219
+ };
220
+ var nextMessages = _toConsumableArray(currentMessages);
221
+ missingMessages.forEach(function (messageItem) {
222
+ var targetOrder = getMessageOrder(messageItem);
223
+ var insertIndex = nextMessages.findIndex(function (currentMessage) {
224
+ var currentOrder = getMessageOrder(currentMessage);
225
+ return Number.isFinite(currentOrder) && currentOrder > targetOrder;
226
+ });
227
+ if (insertIndex < 0) insertIndex = nextMessages.length;
228
+ nextMessages.splice(insertIndex, 0, messageItem);
229
+ });
230
+ return nextMessages;
231
+ };
47
232
 
48
233
  // 后台会话连接状态
49
234
 
50
235
  function useADKChat(_ref) {
236
+ var _config$session$pollS, _config$session, _config$session$sessi, _config$session2;
51
237
  var _ref$url = _ref.url,
52
238
  url = _ref$url === void 0 ? window.location.origin : _ref$url,
53
239
  token = _ref.token,
@@ -65,7 +251,12 @@ function useADKChat(_ref) {
65
251
  var _useState = useState(false),
66
252
  _useState2 = _slicedToArray(_useState, 2),
67
253
  loading = _useState2[0],
68
- setLoading = _useState2[1];
254
+ setLoadingState = _useState2[1];
255
+ var loadingRef = useRef(false);
256
+ var setLoading = useCallback(function (nextLoading) {
257
+ loadingRef.current = nextLoading;
258
+ setLoadingState(nextLoading);
259
+ }, []);
69
260
  var _useState3 = useState(false),
70
261
  _useState4 = _slicedToArray(_useState3, 2),
71
262
  sessionLoading = _useState4[0],
@@ -78,6 +269,8 @@ function useADKChat(_ref) {
78
269
  var _ref2 = config || {},
79
270
  appNo = _ref2.appNo,
80
271
  showFirstSession = _ref2.showFirstSession;
272
+ var pollSessionEvents = (_config$session$pollS = config === null || config === void 0 || (_config$session = config.session) === null || _config$session === void 0 ? void 0 : _config$session.pollSessionEvents) !== null && _config$session$pollS !== void 0 ? _config$session$pollS : true;
273
+ var sessionEventsPollingInterval = Math.max((_config$session$sessi = config === null || config === void 0 || (_config$session2 = config.session) === null || _config$session2 === void 0 ? void 0 : _config$session2.sessionEventsPollingInterval) !== null && _config$session$sessi !== void 0 ? _config$session$sessi : DEFAULT_SESSION_EVENTS_POLLING_INTERVAL, 1000);
81
274
  var _useState5 = useState(null),
82
275
  _useState6 = _slicedToArray(_useState5, 2),
83
276
  appInfo = _useState6[0],
@@ -122,6 +315,10 @@ function useADKChat(_ref) {
122
315
  _useState20 = _slicedToArray(_useState19, 2),
123
316
  messages = _useState20[0],
124
317
  setMessages = _useState20[1];
318
+ var pendingSessionEventsRef = useRef(null);
319
+ var sessionEventsFlushTimerRef = useRef(null);
320
+ var sessionEventsSyncingRef = useRef(false);
321
+ var sessionDetailLoadingRef = useRef(false);
125
322
  // 用户自定义业务参数 (stateDelta),每次发送请求时携带
126
323
  var stateDeltaRef = useRef(undefined);
127
324
 
@@ -151,6 +348,52 @@ function useADKChat(_ref) {
151
348
  }, [messages]);
152
349
  var textMsgRef = useRef(null);
153
350
  var eventDataRef = useRef(new Map());
351
+ var cancelSessionEventsFlush = useCallback(function () {
352
+ if (sessionEventsFlushTimerRef.current === null) return;
353
+ clearTimeout(sessionEventsFlushTimerRef.current);
354
+ sessionEventsFlushTimerRef.current = null;
355
+ }, []);
356
+ var flushPendingSessionEvents = useCallback(function () {
357
+ var pending = pendingSessionEventsRef.current;
358
+ var replyInProgress = loadingRef.current || sendingRef.current || textMsgRef.current !== null;
359
+ if (!pending || replyInProgress || pending.sessionId !== currentSessionIdRef.current) return;
360
+ var previewMessages = insertMissingSessionEvents(messagesRef.current, pending.events);
361
+ pendingSessionEventsRef.current = null;
362
+ if (previewMessages === messagesRef.current) return;
363
+ sessionEventsSyncingRef.current = true;
364
+ setLoading(true);
365
+ sessionEventsFlushTimerRef.current = setTimeout(function () {
366
+ sessionEventsFlushTimerRef.current = null;
367
+ if (pending.sessionId === currentSessionIdRef.current) {
368
+ setMessages(function (prev) {
369
+ var nextMessages = insertMissingSessionEvents(prev, pending.events);
370
+ messagesRef.current = nextMessages;
371
+ return nextMessages;
372
+ });
373
+ }
374
+ sessionEventsSyncingRef.current = false;
375
+ setLoading(false);
376
+ }, 0);
377
+ }, [setLoading]);
378
+ var syncSessionEvents = useCallback(function (events, targetSessionId) {
379
+ if (targetSessionId !== currentSessionIdRef.current) return;
380
+ pendingSessionEventsRef.current = {
381
+ sessionId: targetSessionId,
382
+ events: events
383
+ };
384
+ flushPendingSessionEvents();
385
+ }, [flushPendingSessionEvents]);
386
+ useEffect(function () {
387
+ pendingSessionEventsRef.current = null;
388
+ cancelSessionEventsFlush();
389
+ if (sessionEventsSyncingRef.current) {
390
+ sessionEventsSyncingRef.current = false;
391
+ setLoading(false);
392
+ }
393
+ }, [cancelSessionEventsFlush, currentSessionId, setLoading]);
394
+ useEffect(function () {
395
+ if (!loading) flushPendingSessionEvents();
396
+ }, [flushPendingSessionEvents, loading]);
154
397
 
155
398
  // 插入消息
156
399
  var insertMessage = useCallback(function (msg) {
@@ -345,9 +588,9 @@ function useADKChat(_ref) {
345
588
 
346
589
  // 处理建议类消息
347
590
  var processFollowupPart = useCallback(function (event) {
348
- var _event$content;
591
+ var _event$content3;
349
592
  // 获取建议类消息的文本内容
350
- var part = (event === null || event === void 0 || (_event$content = event.content) === null || _event$content === void 0 || (_event$content = _event$content.parts) === null || _event$content === void 0 ? void 0 : _event$content[0]) || null;
593
+ var part = (event === null || event === void 0 || (_event$content3 = event.content) === null || _event$content3 === void 0 || (_event$content3 = _event$content3.parts) === null || _event$content3 === void 0 ? void 0 : _event$content3[0]) || null;
351
594
  var text = (part === null || part === void 0 ? void 0 : part.text) || "";
352
595
  storeEvents(part, event);
353
596
  if (text) {
@@ -449,7 +692,7 @@ function useADKChat(_ref) {
449
692
  content: rawData.data,
450
693
  invocationId: rawData.result.invocationId,
451
694
  sessionId: rawData.result.sessionId,
452
- id: rawData.result.invocationId
695
+ id: rawData.data.id || rawData.result.id || rawData.result.eventId || rawData.result.invocationId
453
696
  });
454
697
  }
455
698
  if (chunkJson.error) {
@@ -605,7 +848,7 @@ function useADKChat(_ref) {
605
848
  while (1) switch (_context2.prev = _context2.next) {
606
849
  case 0:
607
850
  _ref3$text = _ref3.text, text = _ref3$text === void 0 ? "" : _ref3$text, _ref3$files = _ref3.files, files = _ref3$files === void 0 ? [] : _ref3$files, functionResponse = _ref3.functionResponse;
608
- if (!(loading || sendingRef.current)) {
851
+ if (!(loadingRef.current || sendingRef.current)) {
609
852
  _context2.next = 3;
610
853
  break;
611
854
  }
@@ -707,7 +950,7 @@ function useADKChat(_ref) {
707
950
  return _regeneratorRuntime().wrap(function _callee3$(_context3) {
708
951
  while (1) switch (_context3.prev = _context3.next) {
709
952
  case 0:
710
- if (!(loading || sendingRef.current)) {
953
+ if (!(loadingRef.current || sendingRef.current)) {
711
954
  _context3.next = 2;
712
955
  break;
713
956
  }
@@ -791,7 +1034,7 @@ function useADKChat(_ref) {
791
1034
 
792
1035
  // 使用建议问题
793
1036
  var suggestChat = function suggestChat(text) {
794
- if (loading) return;
1037
+ if (loadingRef.current) return;
795
1038
  if (!text.trim()) return;
796
1039
  setSuggestedQuestions([]);
797
1040
  startChat({
@@ -802,11 +1045,14 @@ function useADKChat(_ref) {
802
1045
  // 停止会话(只中断前台连接)
803
1046
  var stopChat = useCallback(function () {
804
1047
  var _ctrl$current;
1048
+ pendingSessionEventsRef.current = null;
1049
+ cancelSessionEventsFlush();
1050
+ sessionEventsSyncingRef.current = false;
805
1051
  (_ctrl$current = ctrl.current) === null || _ctrl$current === void 0 || _ctrl$current.abort();
806
1052
  ctrl.current = null;
807
1053
  setLoading(false);
808
1054
  textMsgRef.current = null;
809
- }, []);
1055
+ }, [cancelSessionEventsFlush, setLoading]);
810
1056
 
811
1057
  // 清除/重置会话
812
1058
  var clearChat = function clearChat() {
@@ -821,118 +1067,13 @@ function useADKChat(_ref) {
821
1067
  };
822
1068
 
823
1069
  // 格式化会话记录
824
- var formatMessages = function formatMessages(messages) {
1070
+ var formatMessages = useCallback(function (sessionEvents) {
825
1071
  var isReplace = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
826
- var mapped = [];
827
- messages.forEach(function (item) {
828
- if (!item || !item.content || !Array.isArray(item.content.parts)) return;
829
- var role = (item.content.role || "").toLowerCase() === "user" ? "user" : "bot";
830
- var parts = Array.isArray(item.content.parts) ? item.content.parts.filter(function (p) {
831
- if (!p) return false;
832
- return Boolean(p.text || p.inlineData || p.functionCall || p.functionResponse || p.fileData || p.executableCode || p.codeExecutionResult || p.errorMessage);
833
- }) : [];
834
- if (parts.length === 0) return;
835
-
836
- // 将同一条历史消息的 text/fileData parts 合并到一条 IMessage,避免拆分显示
837
- var textParts = parts.filter(function (p) {
838
- return p.text || p.errorMessage || p.inlineData;
839
- });
840
- var fileDataParts = parts.filter(function (p) {
841
- return p.fileData;
842
- });
843
- var otherParts = parts.filter(function (p) {
844
- return !p.text && !p.errorMessage && !p.inlineData && !p.fileData;
845
- });
846
-
847
- // 如果有 text/fileData,合并为一条消息
848
- if (textParts.length > 0 || fileDataParts.length > 0) {
849
- var msg = {
850
- id: v4(),
851
- author: item.author,
852
- invocationId: item.invocationId,
853
- eventId: item.id,
854
- timestamp: item.timestamp,
855
- isLike: item.isLike,
856
- role: role,
857
- modelCode: item.modelCode,
858
- usageMetadata: item.usageMetadata,
859
- finishReason: item.finishReason,
860
- raw: item
861
- };
862
- var _iterator4 = _createForOfIteratorHelper(textParts),
863
- _step4;
864
- try {
865
- for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
866
- var part = _step4.value;
867
- if (part.inlineData) {
868
- msg.inlineData = {
869
- displayName: part.inlineData.displayName,
870
- data: part.inlineData.data,
871
- mimeType: part.inlineData.mimeType
872
- };
873
- }
874
- if (part.text) {
875
- msg.text = (msg.text ? msg.text + "\n" : "") + part.text;
876
- if (typeof part.thought !== "undefined") msg.thought = part.thought;
877
- }
878
- if (part.errorMessage) {
879
- msg.text = (msg.text ? msg.text + "\n" : "") + part.errorMessage;
880
- }
881
- }
882
- } catch (err) {
883
- _iterator4.e(err);
884
- } finally {
885
- _iterator4.f();
886
- }
887
- if (fileDataParts.length > 0) {
888
- msg.fileData = fileDataParts.map(function (part) {
889
- return {
890
- displayName: part.fileData.displayName || "",
891
- fileUri: part.fileData.fileUri,
892
- mimeType: part.fileData.mimeType
893
- };
894
- });
895
- }
896
- mapped.push(msg);
897
- }
898
-
899
- // 处理其他类型的 parts(functionCall、executableCode 等)
900
- otherParts.forEach(function (part) {
901
- var msg = {
902
- id: v4(),
903
- author: item.author,
904
- invocationId: item.invocationId,
905
- eventId: item.id,
906
- timestamp: item.timestamp,
907
- isLike: item.isLike,
908
- role: role,
909
- modelCode: item.modelCode,
910
- usageMetadata: item.usageMetadata,
911
- finishReason: item.finishReason,
912
- raw: item
913
- };
914
- if (part.functionCall) msg.functionCall = part.functionCall;
915
- if (part.executableCode) msg.executableCode = part.executableCode;
916
- if (part.codeExecutionResult) msg.codeExecutionResult = part.codeExecutionResult;
917
- // 补全函数调用结果
918
- if (part.functionResponse) {
919
- // 通过 functionCall.id 寻找对应的函数调用消息,在那条消息上添加functionResponse
920
- var functionCallMsg = mapped.find(function (msg) {
921
- var _msg$functionCall2, _part$functionRespons;
922
- return ((_msg$functionCall2 = msg.functionCall) === null || _msg$functionCall2 === void 0 ? void 0 : _msg$functionCall2.id) === ((_part$functionRespons = part.functionResponse) === null || _part$functionRespons === void 0 ? void 0 : _part$functionRespons.id);
923
- });
924
- if (functionCallMsg) {
925
- functionCallMsg.functionResponse = part.functionResponse;
926
- }
927
- return;
928
- }
929
- mapped.push(msg);
930
- });
931
- });
1072
+ var mapped = mapSessionMessages(sessionEvents);
932
1073
  setMessages(function (prev) {
933
- return isReplace ? mapped : [].concat(_toConsumableArray(prev), mapped);
1074
+ return isReplace ? mapped : [].concat(_toConsumableArray(prev), _toConsumableArray(mapped));
934
1075
  });
935
- };
1076
+ }, []);
936
1077
 
937
1078
  // 设置当前会话详情
938
1079
  var setCurrentSession = /*#__PURE__*/function () {
@@ -942,7 +1083,7 @@ function useADKChat(_ref) {
942
1083
  while (1) switch (_context4.prev = _context4.next) {
943
1084
  case 0:
944
1085
  if (!sessionId) {
945
- _context4.next = 26;
1086
+ _context4.next = 34;
946
1087
  break;
947
1088
  }
948
1089
  if (!(sessionId === currentSessionId)) {
@@ -951,6 +1092,13 @@ function useADKChat(_ref) {
951
1092
  }
952
1093
  return _context4.abrupt("return");
953
1094
  case 3:
1095
+ pendingSessionEventsRef.current = null;
1096
+ cancelSessionEventsFlush();
1097
+ if (sessionEventsSyncingRef.current) {
1098
+ sessionEventsSyncingRef.current = false;
1099
+ setLoading(false);
1100
+ }
1101
+
954
1102
  // 1. 将当前会话挂起到后台(不中断 SSE 连接)
955
1103
  prevSessionId = currentSessionId;
956
1104
  if (ctrl.current) {
@@ -977,7 +1125,7 @@ function useADKChat(_ref) {
977
1125
  // 2. 尝试从后台恢复目标会话
978
1126
  bg = backgroundRef.current.get(sessionId);
979
1127
  if (!bg) {
980
- _context4.next = 15;
1128
+ _context4.next = 18;
981
1129
  break;
982
1130
  }
983
1131
  setMessages(bg.messages);
@@ -988,18 +1136,20 @@ function useADKChat(_ref) {
988
1136
  setInitialized(true);
989
1137
  backgroundRef.current.delete(sessionId);
990
1138
  return _context4.abrupt("return");
991
- case 15:
1139
+ case 18:
992
1140
  // 3. 后台没有目标 session,走 API 加载(原有逻辑)
993
1141
  setInitialized(false);
994
1142
  setCurrentSessionId(sessionId);
995
- _context4.next = 19;
1143
+ sessionDetailLoadingRef.current = true;
1144
+ _context4.prev = 21;
1145
+ _context4.next = 24;
996
1146
  return fetchSessionDetail({
997
1147
  url: url,
998
1148
  appNo: appNo,
999
1149
  sessionId: sessionId,
1000
1150
  token: tokenRef.current
1001
1151
  });
1002
- case 19:
1152
+ case 24:
1003
1153
  _yield$fetchSessionDe = _context4.sent;
1004
1154
  data = _yield$fetchSessionDe.data;
1005
1155
  result = _yield$fetchSessionDe.result;
@@ -1011,16 +1161,21 @@ function useADKChat(_ref) {
1011
1161
  setSuggestedQuestions((appInfo === null || appInfo === void 0 || (_appInfo$onboardingIn4 = appInfo.onboardingInfo) === null || _appInfo$onboardingIn4 === void 0 ? void 0 : _appInfo$onboardingIn4.suggested_questions) || []);
1012
1162
  }
1013
1163
  }
1164
+ case 28:
1165
+ _context4.prev = 28;
1166
+ sessionDetailLoadingRef.current = false;
1014
1167
  setInitialized(true);
1015
- _context4.next = 27;
1168
+ return _context4.finish(28);
1169
+ case 32:
1170
+ _context4.next = 35;
1016
1171
  break;
1017
- case 26:
1172
+ case 34:
1018
1173
  setCurrentSessionId(v4());
1019
- case 27:
1174
+ case 35:
1020
1175
  case "end":
1021
1176
  return _context4.stop();
1022
1177
  }
1023
- }, _callee4);
1178
+ }, _callee4, null, [[21,, 28, 32]]);
1024
1179
  }));
1025
1180
  return function setCurrentSession(_x2) {
1026
1181
  return _ref6.apply(this, arguments);
@@ -1104,7 +1259,7 @@ function useADKChat(_ref) {
1104
1259
  } else {
1105
1260
  // 服务端业务错误,透传原始 code + message 给接入方自行处理
1106
1261
  onError === null || onError === void 0 || onError({
1107
- code: (result === null || result === void 0 ? void 0 : result.code) || 'UNKNOWN_ERROR',
1262
+ code: (result === null || result === void 0 ? void 0 : result.code) || "UNKNOWN_ERROR",
1108
1263
  message: (result === null || result === void 0 ? void 0 : result.message) || "获取会话列表失败",
1109
1264
  raw: result
1110
1265
  });
@@ -1299,7 +1454,7 @@ function useADKChat(_ref) {
1299
1454
  } else {
1300
1455
  // 服务端业务错误,透传原始 code + message
1301
1456
  onError === null || onError === void 0 || onError({
1302
- code: result.code || 'UNKNOWN_ERROR',
1457
+ code: result.code || "UNKNOWN_ERROR",
1303
1458
  message: result.message || "获取应用配置失败",
1304
1459
  raw: result
1305
1460
  });
@@ -1343,10 +1498,72 @@ function useADKChat(_ref) {
1343
1498
  }
1344
1499
  }, [appInfo]);
1345
1500
 
1501
+ // 轮询当前会话详情,空闲时补入后端异步任务产生的模型消息。
1502
+ useEffect(function () {
1503
+ if (!enabled || !initialized || !pollSessionEvents || !appNo || !currentSessionId) return;
1504
+ var disposed = false;
1505
+ var requesting = false;
1506
+ var pollingSessionId = currentSessionId;
1507
+ var poll = /*#__PURE__*/function () {
1508
+ var _ref12 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee10() {
1509
+ var _yield$fetchSessionDe2, data, result;
1510
+ return _regeneratorRuntime().wrap(function _callee10$(_context10) {
1511
+ while (1) switch (_context10.prev = _context10.next) {
1512
+ case 0:
1513
+ if (!(requesting || sessionDetailLoadingRef.current)) {
1514
+ _context10.next = 2;
1515
+ break;
1516
+ }
1517
+ return _context10.abrupt("return");
1518
+ case 2:
1519
+ requesting = true;
1520
+ _context10.prev = 3;
1521
+ _context10.next = 6;
1522
+ return fetchSessionDetail({
1523
+ url: url,
1524
+ appNo: appNo,
1525
+ sessionId: pollingSessionId,
1526
+ token: tokenRef.current
1527
+ });
1528
+ case 6:
1529
+ _yield$fetchSessionDe2 = _context10.sent;
1530
+ data = _yield$fetchSessionDe2.data;
1531
+ result = _yield$fetchSessionDe2.result;
1532
+ if (!disposed && (result === null || result === void 0 ? void 0 : result.code) === API_SUCCESS_CODE && Array.isArray(data)) {
1533
+ syncSessionEvents(data, pollingSessionId);
1534
+ }
1535
+ _context10.next = 14;
1536
+ break;
1537
+ case 12:
1538
+ _context10.prev = 12;
1539
+ _context10.t0 = _context10["catch"](3);
1540
+ case 14:
1541
+ _context10.prev = 14;
1542
+ requesting = false;
1543
+ return _context10.finish(14);
1544
+ case 17:
1545
+ case "end":
1546
+ return _context10.stop();
1547
+ }
1548
+ }, _callee10, null, [[3, 12, 14, 17]]);
1549
+ }));
1550
+ return function poll() {
1551
+ return _ref12.apply(this, arguments);
1552
+ };
1553
+ }();
1554
+ void poll();
1555
+ var timer = window.setInterval(poll, sessionEventsPollingInterval);
1556
+ return function () {
1557
+ disposed = true;
1558
+ window.clearInterval(timer);
1559
+ };
1560
+ }, [appNo, currentSessionId, enabled, initialized, pollSessionEvents, sessionEventsPollingInterval, syncSessionEvents, url]);
1561
+
1346
1562
  // 组件卸载时清理所有连接(前台 + 后台)
1347
1563
  useEffect(function () {
1348
1564
  return function () {
1349
1565
  var _ctrl$current2;
1566
+ cancelSessionEventsFlush();
1350
1567
  (_ctrl$current2 = ctrl.current) === null || _ctrl$current2 === void 0 || _ctrl$current2.abort();
1351
1568
  backgroundRef.current.forEach(function (bg) {
1352
1569
  var _bg$ctrl;
@@ -1354,7 +1571,7 @@ function useADKChat(_ref) {
1354
1571
  });
1355
1572
  backgroundRef.current.clear();
1356
1573
  };
1357
- }, []);
1574
+ }, [cancelSessionEventsFlush]);
1358
1575
  return {
1359
1576
  appInfo: appInfo,
1360
1577
  startChat: startChat,