@ai-group/chat-sdk 3.4.6 → 3.5.0-alpha1

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 (36) hide show
  1. package/dist/cjs/components/FolderTree/styles.js +2 -1
  2. package/dist/cjs/components/FolderTree/styles.js.map +2 -2
  3. package/dist/cjs/components/XAdkChatbot/index.d.ts +2 -2
  4. package/dist/cjs/components/XAdkChatbot/index.js +433 -389
  5. package/dist/cjs/components/XAdkChatbot/index.js.map +2 -2
  6. package/dist/cjs/components/XAdkThoughtChain/styles.d.ts +0 -1
  7. package/dist/cjs/components/XAdkThoughtChain/styles.js +0 -9
  8. package/dist/cjs/components/XAdkThoughtChain/styles.js.map +2 -2
  9. package/dist/cjs/hooks/useADKChat.js +2 -0
  10. package/dist/cjs/hooks/useADKChat.js.map +2 -2
  11. package/dist/cjs/presets/xGroupAdk.js +0 -1
  12. package/dist/cjs/presets/xGroupAdk.js.map +2 -2
  13. package/dist/cjs/types/XAdkChatbot.d.ts +12 -0
  14. package/dist/cjs/types/XAdkChatbot.js.map +1 -1
  15. package/dist/cjs/utils/umdEntry.d.ts +25 -1
  16. package/dist/cjs/utils/umdEntry.js +126 -41
  17. package/dist/cjs/utils/umdEntry.js.map +3 -3
  18. package/dist/esm/components/FolderTree/styles.js +1 -1
  19. package/dist/esm/components/FolderTree/styles.js.map +1 -1
  20. package/dist/esm/components/XAdkChatbot/index.d.ts +2 -2
  21. package/dist/esm/components/XAdkChatbot/index.js +69 -14
  22. package/dist/esm/components/XAdkChatbot/index.js.map +1 -1
  23. package/dist/esm/components/XAdkThoughtChain/styles.d.ts +0 -1
  24. package/dist/esm/components/XAdkThoughtChain/styles.js +19 -20
  25. package/dist/esm/components/XAdkThoughtChain/styles.js.map +1 -1
  26. package/dist/esm/hooks/useADKChat.js +10 -6
  27. package/dist/esm/hooks/useADKChat.js.map +1 -1
  28. package/dist/esm/presets/xGroupAdk.js +0 -1
  29. package/dist/esm/presets/xGroupAdk.js.map +1 -1
  30. package/dist/esm/types/XAdkChatbot.d.ts +12 -0
  31. package/dist/esm/types/XAdkChatbot.js.map +1 -1
  32. package/dist/esm/utils/umdEntry.d.ts +25 -1
  33. package/dist/esm/utils/umdEntry.js +162 -70
  34. package/dist/esm/utils/umdEntry.js.map +1 -1
  35. package/dist/umd/chat-sdk.min.js +1 -1
  36. package/package.json +1 -1
@@ -47,414 +47,458 @@ var import_xGroupAdk = require("../../presets/xGroupAdk");
47
47
  var import_FunctionCallRender2 = require("../../types/FunctionCallRender");
48
48
  var import_jsx_runtime = require("react/jsx-runtime");
49
49
  var scrollThreshold = 10;
50
- var XAdkChatbot = ({
51
- loading = false,
52
- prologue,
53
- suggestions,
54
- messages,
55
- showFnCallDetail,
56
- onConfirm,
57
- onSuggest,
58
- showRetry,
59
- showCopy,
60
- showLog,
61
- onRetry,
62
- onCopy,
63
- onShowLog,
64
- actions,
65
- actionsExtra,
66
- className,
67
- style,
68
- // welcome = null,
69
- enableGrouping = true,
70
- enableProcessParsing = true,
71
- parseOptions,
72
- initialized = false,
73
- onFileClick,
74
- renderFunctionCall,
75
- toolKindResolver,
76
- strategies,
77
- preset
78
- }) => {
79
- const styles = (0, import_styles.useStyles)();
80
- const listRef = (0, import_react.useRef)(null);
81
- const lastScrollTopRef = (0, import_react.useRef)(0);
82
- const userHasScrolledRef = (0, import_react.useRef)(false);
83
- const messagesEndRef = (0, import_react.useRef)(null);
84
- const prevInitializedRef = (0, import_react.useRef)(false);
85
- const mergedStrategies = (0, import_react.useMemo)(
86
- () => (0, import_xGroupAdk.mergeChatStrategies)(preset, strategies),
87
- [preset, strategies]
88
- );
89
- const resolveToolKind = (0, import_react.useCallback)(
90
- (name, msg) => {
91
- var _a;
92
- return (toolKindResolver == null ? void 0 : toolKindResolver(name)) ?? ((_a = mergedStrategies.resolveToolKind) == null ? void 0 : _a.call(mergedStrategies, { name, msg })) ?? (0, import_FunctionCallRender2.defaultToolKindResolver)(name);
93
- },
94
- [toolKindResolver, mergedStrategies]
95
- );
96
- const parseProcessMessage = mergedStrategies.parseProcessMessage ?? import_utils.parseAgentMessage;
97
- (0, import_react.useEffect)(() => {
98
- if (!initialized)
99
- return;
100
- if (!messages.length)
101
- return;
102
- if (prevInitializedRef.current)
103
- return;
104
- prevInitializedRef.current = true;
105
- const timer = setTimeout(() => {
106
- var _a;
107
- (_a = messagesEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "auto" });
108
- }, 0);
109
- return () => clearTimeout(timer);
110
- }, [initialized, messages]);
111
- (0, import_react.useEffect)(() => {
112
- var _a;
113
- if (!loading)
114
- return;
115
- if (userHasScrolledRef.current)
116
- return;
117
- (_a = messagesEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
118
- }, [loading, messages]);
119
- const handleScroll = (0, import_react.useCallback)(() => {
120
- const el = listRef.current;
121
- if (!el)
122
- return;
123
- const currentTop = el.scrollTop;
124
- if (currentTop < lastScrollTopRef.current) {
125
- userHasScrolledRef.current = true;
126
- }
127
- const isAtBottom = Math.abs(el.scrollHeight - currentTop - el.clientHeight) <= scrollThreshold;
128
- if (isAtBottom) {
50
+ var XAdkChatbot = (0, import_react.forwardRef)(
51
+ ({
52
+ loading = false,
53
+ prologue,
54
+ suggestions,
55
+ messages,
56
+ showFnCallDetail,
57
+ onConfirm,
58
+ onSuggest,
59
+ showRetry,
60
+ showCopy,
61
+ showLog,
62
+ onRetry,
63
+ onCopy,
64
+ onShowLog,
65
+ actions,
66
+ actionsExtra,
67
+ className,
68
+ style,
69
+ // welcome = null,
70
+ enableGrouping = true,
71
+ enableProcessParsing = true,
72
+ parseOptions,
73
+ initialized = false,
74
+ sessionId,
75
+ onFileClick,
76
+ renderFunctionCall,
77
+ toolKindResolver,
78
+ strategies,
79
+ preset
80
+ }, ref) => {
81
+ const styles = (0, import_styles.useStyles)();
82
+ const listRef = (0, import_react.useRef)(null);
83
+ const lastScrollTopRef = (0, import_react.useRef)(0);
84
+ const userHasScrolledRef = (0, import_react.useRef)(false);
85
+ const messagesEndRef = (0, import_react.useRef)(null);
86
+ const prevInitializedRef = (0, import_react.useRef)(false);
87
+ const prevSessionIdRef = (0, import_react.useRef)(sessionId);
88
+ const scrollToBottom = (0, import_react.useCallback)(
89
+ (behavior = "auto") => {
90
+ var _a;
91
+ (_a = messagesEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior });
92
+ },
93
+ []
94
+ );
95
+ (0, import_react.useImperativeHandle)(ref, () => ({ scrollToBottom }), [scrollToBottom]);
96
+ const mergedStrategies = (0, import_react.useMemo)(
97
+ () => (0, import_xGroupAdk.mergeChatStrategies)(preset, strategies),
98
+ [preset, strategies]
99
+ );
100
+ const resolveToolKind = (0, import_react.useCallback)(
101
+ (name, msg) => {
102
+ var _a;
103
+ return (toolKindResolver == null ? void 0 : toolKindResolver(name)) ?? ((_a = mergedStrategies.resolveToolKind) == null ? void 0 : _a.call(mergedStrategies, { name, msg })) ?? (0, import_FunctionCallRender2.defaultToolKindResolver)(name);
104
+ },
105
+ [toolKindResolver, mergedStrategies]
106
+ );
107
+ const parseProcessMessage = mergedStrategies.parseProcessMessage ?? import_utils.parseAgentMessage;
108
+ (0, import_react.useEffect)(() => {
109
+ if (!initialized)
110
+ return;
111
+ if (!messages.length)
112
+ return;
113
+ if (prevInitializedRef.current)
114
+ return;
115
+ prevInitializedRef.current = true;
116
+ const el = listRef.current;
117
+ if (!el)
118
+ return;
119
+ let stableTimer;
120
+ const doScroll = () => {
121
+ var _a;
122
+ (_a = messagesEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "auto" });
123
+ };
124
+ const observer = new MutationObserver(() => {
125
+ clearTimeout(stableTimer);
126
+ stableTimer = setTimeout(doScroll, 80);
127
+ });
128
+ observer.observe(el, { childList: true, subtree: true, characterData: true });
129
+ doScroll();
130
+ const maxTimer = setTimeout(() => {
131
+ observer.disconnect();
132
+ doScroll();
133
+ }, 500);
134
+ return () => {
135
+ clearTimeout(stableTimer);
136
+ clearTimeout(maxTimer);
137
+ observer.disconnect();
138
+ };
139
+ }, [initialized, messages]);
140
+ (0, import_react.useEffect)(() => {
141
+ if (sessionId === void 0)
142
+ return;
143
+ if (prevSessionIdRef.current === sessionId)
144
+ return;
145
+ prevSessionIdRef.current = sessionId;
146
+ prevInitializedRef.current = false;
129
147
  userHasScrolledRef.current = false;
130
- }
131
- lastScrollTopRef.current = currentTop;
132
- }, []);
133
- (0, import_react.useEffect)(() => {
134
- const listElement = listRef.current;
135
- if (!listElement)
136
- return;
137
- listElement.addEventListener("scroll", handleScroll);
138
- return () => {
139
- listElement.removeEventListener("scroll", handleScroll);
140
- };
141
- }, [handleScroll]);
142
- const chatGroups = (0, import_react.useMemo)(() => {
143
- if (!enableGrouping) {
144
- return messages.map((msg) => ({
145
- id: msg.id,
146
- role: msg.role,
147
- msgs: [msg],
148
- invocationId: msg.invocationId,
149
- allFiles: msg.fileData || [],
150
- isLike: msg.isLike ?? 0
151
- }));
152
- }
153
- const groups = [];
154
- messages.forEach((msg) => {
155
- if (msg.role === "followup")
148
+ }, [sessionId]);
149
+ (0, import_react.useEffect)(() => {
150
+ var _a;
151
+ if (!loading)
156
152
  return;
157
- const isRealUserQuery = msg.role === "user" && !msg.functionResponse && !msg.functionCall;
158
- const lastGroup = groups[groups.length - 1];
159
- const isLastGroupAgent = (lastGroup == null ? void 0 : lastGroup.role) === "bot";
160
- if (isLastGroupAgent && !isRealUserQuery) {
161
- lastGroup.msgs.push(msg);
162
- if (msg.invocationId)
163
- lastGroup.invocationId = msg.invocationId;
164
- if (msg.isLike && msg.isLike !== 0) {
165
- lastGroup.isLike = msg.isLike;
166
- }
167
- } else {
168
- groups.push({
169
- id: msg.id || `group-${groups.length}`,
170
- role: isRealUserQuery ? "user" : "bot",
153
+ if (userHasScrolledRef.current)
154
+ return;
155
+ (_a = messagesEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
156
+ }, [loading, messages]);
157
+ const handleScroll = (0, import_react.useCallback)(() => {
158
+ const el = listRef.current;
159
+ if (!el)
160
+ return;
161
+ const currentTop = el.scrollTop;
162
+ if (currentTop < lastScrollTopRef.current) {
163
+ userHasScrolledRef.current = true;
164
+ }
165
+ const isAtBottom = Math.abs(el.scrollHeight - currentTop - el.clientHeight) <= scrollThreshold;
166
+ if (isAtBottom) {
167
+ userHasScrolledRef.current = false;
168
+ }
169
+ lastScrollTopRef.current = currentTop;
170
+ }, []);
171
+ (0, import_react.useEffect)(() => {
172
+ const listElement = listRef.current;
173
+ if (!listElement)
174
+ return;
175
+ listElement.addEventListener("scroll", handleScroll);
176
+ return () => {
177
+ listElement.removeEventListener("scroll", handleScroll);
178
+ };
179
+ }, [handleScroll]);
180
+ const chatGroups = (0, import_react.useMemo)(() => {
181
+ if (!enableGrouping) {
182
+ return messages.map((msg) => ({
183
+ id: msg.id,
184
+ role: msg.role,
171
185
  msgs: [msg],
172
186
  invocationId: msg.invocationId,
173
- allFiles: [],
187
+ allFiles: msg.fileData || [],
174
188
  isLike: msg.isLike ?? 0
175
- });
176
- }
177
- });
178
- groups.forEach((g) => {
179
- g.allFiles = g.msgs.reduce(
180
- (acc, m) => [...acc, ...m.fileData || []],
181
- []
182
- );
183
- });
184
- return groups;
185
- }, [messages, enableGrouping]);
186
- const renderBotGroup = (0, import_react.useCallback)(
187
- (group, isLastGroup, renderFunctionCall2) => {
188
- const { msgs, allFiles } = group;
189
- if (!enableProcessParsing) {
190
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.botMsg, children: msgs.map((msg, i) => {
191
- var _a;
192
- if (msg.text) {
193
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
194
- import_MarkdownRender.default,
195
- {
196
- text: msg.text,
197
- onFileClick
198
- },
199
- `${msg.id}-${i}`
200
- );
201
- }
202
- if (msg.functionCall) {
203
- return (renderFunctionCall2 == null ? void 0 : renderFunctionCall2(msg)) ?? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
204
- import_FunctionCallRender.default,
205
- {
206
- msg,
207
- showDetail: showFnCallDetail,
208
- onConfirm,
209
- kind: resolveToolKind((_a = msg.functionCall) == null ? void 0 : _a.name, msg),
210
- renderApproval: mergedStrategies.renderApproval,
211
- renderHandoff: mergedStrategies.renderHandoff
212
- },
213
- `${msg.id}-${i}`
214
- );
215
- }
216
- return null;
217
- }) }, group.id);
189
+ }));
218
190
  }
219
- const mergedToolMap = /* @__PURE__ */ new Map();
220
- msgs.forEach((msg) => {
221
- if (msg.functionCall) {
222
- const callId = msg.functionCall.id || "";
223
- if (!mergedToolMap.has(callId)) {
224
- mergedToolMap.set(callId, { ...msg });
225
- } else {
226
- mergedToolMap.set(callId, {
227
- ...mergedToolMap.get(callId) ?? {},
228
- ...msg
229
- });
230
- }
231
- } else if (msg.functionResponse) {
232
- const callId = msg.functionResponse.id || "";
233
- if (mergedToolMap.has(callId)) {
234
- const tool = mergedToolMap.get(callId);
235
- if (tool)
236
- tool.functionResponse = msg.functionResponse;
237
- } else {
238
- mergedToolMap.set(callId, {
239
- ...msg,
240
- functionCall: {
241
- id: callId,
242
- name: msg.functionResponse.name || "Unknown",
243
- args: {}
244
- }
245
- });
191
+ const groups = [];
192
+ messages.forEach((msg) => {
193
+ if (msg.role === "followup")
194
+ return;
195
+ const isRealUserQuery = msg.role === "user" && !msg.functionResponse && !msg.functionCall;
196
+ const lastGroup = groups[groups.length - 1];
197
+ const isLastGroupAgent = (lastGroup == null ? void 0 : lastGroup.role) === "bot";
198
+ if (isLastGroupAgent && !isRealUserQuery) {
199
+ lastGroup.msgs.push(msg);
200
+ if (msg.invocationId)
201
+ lastGroup.invocationId = msg.invocationId;
202
+ if (msg.isLike && msg.isLike !== 0) {
203
+ lastGroup.isLike = msg.isLike;
246
204
  }
205
+ } else {
206
+ groups.push({
207
+ id: msg.id || `group-${groups.length}`,
208
+ role: isRealUserQuery ? "user" : "bot",
209
+ msgs: [msg],
210
+ invocationId: msg.invocationId,
211
+ allFiles: [],
212
+ isLike: msg.isLike ?? 0
213
+ });
247
214
  }
248
215
  });
249
- const nodes = [];
250
- let currentProcessItems = [];
251
- const processedToolIds = /* @__PURE__ */ new Set();
252
- const flushProcessItems = () => {
253
- if (currentProcessItems.length > 0) {
254
- nodes.push({
255
- type: "process",
256
- items: [...currentProcessItems],
257
- key: `process-${nodes.length}`
258
- });
259
- currentProcessItems = [];
216
+ groups.forEach((g) => {
217
+ g.allFiles = g.msgs.reduce(
218
+ (acc, m) => [...acc, ...m.fileData || []],
219
+ []
220
+ );
221
+ });
222
+ return groups;
223
+ }, [messages, enableGrouping]);
224
+ const renderBotGroup = (0, import_react.useCallback)(
225
+ (group, isLastGroup, renderFunctionCall2) => {
226
+ const { msgs, allFiles } = group;
227
+ if (!enableProcessParsing) {
228
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.botMsg, children: msgs.map((msg, i) => {
229
+ var _a;
230
+ if (msg.text) {
231
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
232
+ import_MarkdownRender.default,
233
+ {
234
+ text: msg.text,
235
+ onFileClick
236
+ },
237
+ `${msg.id}-${i}`
238
+ );
239
+ }
240
+ if (msg.functionCall) {
241
+ return (renderFunctionCall2 == null ? void 0 : renderFunctionCall2(msg)) ?? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
242
+ import_FunctionCallRender.default,
243
+ {
244
+ msg,
245
+ showDetail: showFnCallDetail,
246
+ onConfirm,
247
+ kind: resolveToolKind((_a = msg.functionCall) == null ? void 0 : _a.name, msg),
248
+ renderApproval: mergedStrategies.renderApproval,
249
+ renderHandoff: mergedStrategies.renderHandoff
250
+ },
251
+ `${msg.id}-${i}`
252
+ );
253
+ }
254
+ return null;
255
+ }) }, group.id);
260
256
  }
261
- };
262
- msgs.forEach((msg) => {
263
- if (msg.functionCall) {
264
- const callId = msg.functionCall.id || "";
265
- if (!processedToolIds.has(callId)) {
266
- const mergedMsg = mergedToolMap.get(callId);
267
- if (mergedMsg) {
268
- currentProcessItems.push({
269
- type: "tool",
270
- key: `tool-${callId}`,
271
- content: "",
272
- msg: mergedMsg
257
+ const mergedToolMap = /* @__PURE__ */ new Map();
258
+ msgs.forEach((msg) => {
259
+ if (msg.functionCall) {
260
+ const callId = msg.functionCall.id || "";
261
+ if (!mergedToolMap.has(callId)) {
262
+ mergedToolMap.set(callId, { ...msg });
263
+ } else {
264
+ mergedToolMap.set(callId, {
265
+ ...mergedToolMap.get(callId) ?? {},
266
+ ...msg
273
267
  });
274
- processedToolIds.add(callId);
275
268
  }
276
- }
277
- } else if (msg.text && !msg.functionResponse) {
278
- const parts = parseProcessMessage(msg.text, parseOptions);
279
- parts.forEach((part, partIdx) => {
280
- if ([
281
- "planning",
282
- "replanning",
283
- "reasoning",
284
- "action_log",
285
- "process_text"
286
- ].includes(part.type)) {
287
- const titleMap = {
288
- planning: "任务规划",
289
- replanning: "重新规划",
290
- reasoning: "推理分析",
291
- action_log: "行动记录",
292
- process_text: "过程分析"
293
- };
294
- currentProcessItems.push({
295
- type: "text",
296
- key: `${msg.id}-${partIdx}`,
297
- content: part.content,
298
- title: titleMap[part.type] || "分析"
299
- });
269
+ } else if (msg.functionResponse) {
270
+ const callId = msg.functionResponse.id || "";
271
+ if (mergedToolMap.has(callId)) {
272
+ const tool = mergedToolMap.get(callId);
273
+ if (tool)
274
+ tool.functionResponse = msg.functionResponse;
300
275
  } else {
301
- flushProcessItems();
302
- if (part.content.trim()) {
303
- const lastNode = nodes[nodes.length - 1];
304
- if ((lastNode == null ? void 0 : lastNode.type) === "text") {
305
- lastNode.content += "\n\n" + part.content;
306
- } else {
307
- nodes.push({
308
- type: "text",
309
- content: part.content,
310
- key: `text-${msg.id}-${partIdx}`
311
- });
276
+ mergedToolMap.set(callId, {
277
+ ...msg,
278
+ functionCall: {
279
+ id: callId,
280
+ name: msg.functionResponse.name || "Unknown",
281
+ args: {}
312
282
  }
313
- }
283
+ });
314
284
  }
315
- });
316
- }
317
- });
318
- flushProcessItems();
319
- const fullTextToCopy = msgs.filter((m) => !m.functionCall && !m.functionResponse).map((m) => m.text || "").join("");
320
- const lastBotMsg = msgs[msgs.length - 1];
321
- const hasProcess = nodes.some((n) => n.type === "process");
322
- const isGroupLoading = loading && isLastGroup;
323
- const actionProps = { message: group, isLastBotMsg: isLastGroup };
324
- const actionExtraNode = actionsExtra == null ? void 0 : actionsExtra(actionProps);
325
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.botMsg, children: [
326
- nodes.map((node, idx) => {
327
- if (node.type === "process") {
328
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
329
- import_XAdkThoughtChain.default,
330
- {
331
- loading: isGroupLoading,
332
- title: "思维链已完成",
333
- items: node.items,
334
- showFnCallDetail,
335
- onConfirm,
336
- defaultOpen: isGroupLoading,
337
- renderFunctionCall: renderFunctionCall2,
338
- toolKindResolver: (name) => resolveToolKind(name),
339
- strategies: mergedStrategies
340
- },
341
- node.key
342
- );
343
285
  }
344
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_MarkdownRender.default, { text: node.content, onFileClick }) }, node.key);
345
- }),
346
- allFiles.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.fileSection, children: [
347
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.fileHeader, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
348
- "生成文件 (",
349
- allFiles.length,
350
- ")"
351
- ] }) }),
352
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: "8px" }, children: allFiles.map((file, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_FileGallery.default, { file, onClick: onFileClick }, index)) })
353
- ] }),
354
- !isGroupLoading && (actions || showRetry || showCopy || showLog || actionExtraNode) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.metaFooter, children: [
355
- actions ? actions(actionProps) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_antd.Flex, { gap: 16, className: styles.actionIcons, children: [
356
- showRetry && isLastGroup && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Tooltip, { title: "重新生成", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.ReloadOutlined, { onClick: onRetry }) }),
357
- showCopy && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Tooltip, { title: "复制内容", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
358
- import_icons.CopyOutlined,
359
- {
360
- onClick: () => {
361
- (0, import_copy_to_clipboard.default)(fullTextToCopy);
362
- import_antd.message.success("复制成功");
363
- onCopy == null ? void 0 : onCopy(fullTextToCopy);
364
- }
286
+ });
287
+ const nodes = [];
288
+ let currentProcessItems = [];
289
+ const processedToolIds = /* @__PURE__ */ new Set();
290
+ const flushProcessItems = () => {
291
+ if (currentProcessItems.length > 0) {
292
+ nodes.push({
293
+ type: "process",
294
+ items: [...currentProcessItems],
295
+ key: `process-${nodes.length}`
296
+ });
297
+ currentProcessItems = [];
298
+ }
299
+ };
300
+ msgs.forEach((msg) => {
301
+ if (msg.functionCall) {
302
+ const callId = msg.functionCall.id || "";
303
+ if (!processedToolIds.has(callId)) {
304
+ const mergedMsg = mergedToolMap.get(callId);
305
+ if (mergedMsg) {
306
+ currentProcessItems.push({
307
+ type: "tool",
308
+ key: `tool-${callId}`,
309
+ content: "",
310
+ msg: mergedMsg
311
+ });
312
+ processedToolIds.add(callId);
365
313
  }
366
- ) }),
367
- showLog && (lastBotMsg == null ? void 0 : lastBotMsg.invocationId) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Tooltip, { title: "查看日志", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
368
- import_icons.InfoCircleOutlined,
369
- {
370
- onClick: () => onShowLog == null ? void 0 : onShowLog(
371
- lastBotMsg.invocationId,
372
- lastBotMsg.timestamp
373
- )
314
+ }
315
+ } else if (msg.text && !msg.functionResponse) {
316
+ const parts = parseProcessMessage(msg.text, parseOptions);
317
+ parts.forEach((part, partIdx) => {
318
+ if ([
319
+ "planning",
320
+ "replanning",
321
+ "reasoning",
322
+ "action_log",
323
+ "process_text"
324
+ ].includes(part.type)) {
325
+ const titleMap = {
326
+ planning: "任务规划",
327
+ replanning: "重新规划",
328
+ reasoning: "推理分析",
329
+ action_log: "行动记录",
330
+ process_text: "过程分析"
331
+ };
332
+ currentProcessItems.push({
333
+ type: "text",
334
+ key: `${msg.id}-${partIdx}`,
335
+ content: part.content,
336
+ title: titleMap[part.type] || "分析"
337
+ });
338
+ } else {
339
+ flushProcessItems();
340
+ if (part.content.trim()) {
341
+ const lastNode = nodes[nodes.length - 1];
342
+ if ((lastNode == null ? void 0 : lastNode.type) === "text") {
343
+ lastNode.content += "\n\n" + part.content;
344
+ } else {
345
+ nodes.push({
346
+ type: "text",
347
+ content: part.content,
348
+ key: `text-${msg.id}-${partIdx}`
349
+ });
350
+ }
351
+ }
374
352
  }
375
- ) })
353
+ });
354
+ }
355
+ });
356
+ flushProcessItems();
357
+ const fullTextToCopy = msgs.filter((m) => !m.functionCall && !m.functionResponse).map((m) => m.text || "").join("");
358
+ const lastBotMsg = msgs[msgs.length - 1];
359
+ const hasProcess = nodes.some((n) => n.type === "process");
360
+ const isGroupLoading = loading && isLastGroup;
361
+ const actionProps = { message: group, isLastBotMsg: isLastGroup };
362
+ const actionExtraNode = actionsExtra == null ? void 0 : actionsExtra(actionProps);
363
+ const lastProcessIdx = nodes.findLastIndex(
364
+ (n) => n.type === "process"
365
+ );
366
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.botMsg, children: [
367
+ nodes.map((node, idx) => {
368
+ if (node.type === "process") {
369
+ const isLastProcess = idx === lastProcessIdx;
370
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
371
+ import_XAdkThoughtChain.default,
372
+ {
373
+ loading: isLastProcess && isGroupLoading,
374
+ title: "思维链已完成",
375
+ items: node.items,
376
+ showFnCallDetail,
377
+ onConfirm,
378
+ defaultOpen: isLastProcess && isGroupLoading,
379
+ renderFunctionCall: renderFunctionCall2,
380
+ toolKindResolver: (name) => resolveToolKind(name),
381
+ strategies: mergedStrategies
382
+ },
383
+ node.key
384
+ );
385
+ }
386
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_MarkdownRender.default, { text: node.content, onFileClick }) }, node.key);
387
+ }),
388
+ allFiles.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.fileSection, children: [
389
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.fileHeader, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
390
+ "生成文件 (",
391
+ allFiles.length,
392
+ ")"
393
+ ] }) }),
394
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: "8px" }, children: allFiles.map((file, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_FileGallery.default, { file, onClick: onFileClick }, index)) })
376
395
  ] }),
377
- actionExtraNode
378
- ] })
379
- ] }, group.id);
380
- },
381
- [
382
- enableProcessParsing,
383
- parseOptions,
384
- parseProcessMessage,
385
- showFnCallDetail,
386
- onConfirm,
387
- loading,
388
- showRetry,
389
- showCopy,
390
- showLog,
391
- onRetry,
392
- onCopy,
393
- onShowLog,
394
- actions,
395
- actionsExtra,
396
- onFileClick,
397
- styles,
398
- resolveToolKind,
399
- mergedStrategies
400
- ]
401
- );
402
- const renderUserGroup = (0, import_react.useCallback)(
403
- (group) => {
404
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.userMsg, children: group.msgs.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.userContainer, children: [
405
- m.fileData && m.fileData.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: m.fileData.map((file, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
406
- import_FileGallery.default,
407
- {
408
- file,
409
- align: "left",
410
- style: { marginBottom: "16px" },
411
- onClick: onFileClick
396
+ !isGroupLoading && (actions || showRetry || showCopy || showLog || actionExtraNode) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.metaFooter, children: [
397
+ actions ? actions(actionProps) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_antd.Flex, { gap: 16, className: styles.actionIcons, children: [
398
+ showRetry && isLastGroup && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Tooltip, { title: "重新生成", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.ReloadOutlined, { onClick: onRetry }) }),
399
+ showCopy && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Tooltip, { title: "复制内容", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
400
+ import_icons.CopyOutlined,
401
+ {
402
+ onClick: () => {
403
+ (0, import_copy_to_clipboard.default)(fullTextToCopy);
404
+ import_antd.message.success("复制成功");
405
+ onCopy == null ? void 0 : onCopy(fullTextToCopy);
406
+ }
407
+ }
408
+ ) }),
409
+ showLog && (lastBotMsg == null ? void 0 : lastBotMsg.invocationId) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Tooltip, { title: "查看日志", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
410
+ import_icons.InfoCircleOutlined,
411
+ {
412
+ onClick: () => onShowLog == null ? void 0 : onShowLog(
413
+ lastBotMsg.invocationId,
414
+ lastBotMsg.timestamp
415
+ )
416
+ }
417
+ ) })
418
+ ] }),
419
+ actionExtraNode
420
+ ] })
421
+ ] }, group.id);
422
+ },
423
+ [
424
+ enableProcessParsing,
425
+ parseOptions,
426
+ parseProcessMessage,
427
+ showFnCallDetail,
428
+ onConfirm,
429
+ loading,
430
+ showRetry,
431
+ showCopy,
432
+ showLog,
433
+ onRetry,
434
+ onCopy,
435
+ onShowLog,
436
+ actions,
437
+ actionsExtra,
438
+ onFileClick,
439
+ styles,
440
+ resolveToolKind,
441
+ mergedStrategies
442
+ ]
443
+ );
444
+ const renderUserGroup = (0, import_react.useCallback)(
445
+ (group) => {
446
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.userMsg, children: group.msgs.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.userContainer, children: [
447
+ m.fileData && m.fileData.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: m.fileData.map((file, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
448
+ import_FileGallery.default,
449
+ {
450
+ file,
451
+ align: "left",
452
+ style: { marginBottom: "16px" },
453
+ onClick: onFileClick
454
+ },
455
+ index
456
+ )) }),
457
+ m.text && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.card, children: m.text })
458
+ ] }, m.id || i)) }, group.id);
459
+ },
460
+ [styles, onFileClick]
461
+ );
462
+ const renderSuggestions = () => {
463
+ if (!suggestions || suggestions.length === 0)
464
+ return null;
465
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.suggestionWrapper, children: suggestions.map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.suggestion, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.suggestContent, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
466
+ import_antd.Button,
467
+ {
468
+ type: "text",
469
+ icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.SwapRightOutlined, {}),
470
+ iconPosition: "end",
471
+ onClick: () => {
472
+ if (!item)
473
+ return;
474
+ onSuggest == null ? void 0 : onSuggest(item);
412
475
  },
413
- index
414
- )) }),
415
- m.text && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.card, children: m.text })
416
- ] }, m.id || i)) }, group.id);
417
- },
418
- [styles, onFileClick]
419
- );
420
- const renderSuggestions = () => {
421
- if (!suggestions || suggestions.length === 0)
422
- return null;
423
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.suggestionWrapper, children: suggestions.map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.suggestion, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.suggestContent, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
424
- import_antd.Button,
425
- {
426
- type: "text",
427
- icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.SwapRightOutlined, {}),
428
- iconPosition: "end",
429
- onClick: () => {
430
- if (!item)
431
- return;
432
- onSuggest == null ? void 0 : onSuggest(item);
433
- },
434
- style: {
435
- whiteSpace: "normal",
436
- height: "auto",
437
- wordWrap: "break-word",
438
- textAlign: "left",
439
- padding: "4px 15px",
440
- lineHeight: "1.5"
441
- },
442
- children: item
443
- }
444
- ) }) }, item)) });
445
- };
446
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_clsx.default)(styles.wrapper, className), style, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.list, ref: listRef, children: [
447
- prologue && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.prologue, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_MarkdownRender.default, { text: prologue, onFileClick }) }),
448
- chatGroups.map(
449
- (group, idx) => group.role === "user" ? renderUserGroup(group) : renderBotGroup(
450
- group,
451
- idx === chatGroups.length - 1,
452
- renderFunctionCall
453
- )
454
- ),
455
- renderSuggestions(),
456
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: messagesEndRef })
457
- ] }) });
458
- };
476
+ style: {
477
+ whiteSpace: "normal",
478
+ height: "auto",
479
+ wordWrap: "break-word",
480
+ textAlign: "left",
481
+ padding: "4px 15px",
482
+ lineHeight: "1.5"
483
+ },
484
+ children: item
485
+ }
486
+ ) }) }, item)) });
487
+ };
488
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_clsx.default)(styles.wrapper, className), style, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.list, ref: listRef, children: [
489
+ prologue && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.prologue, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_MarkdownRender.default, { text: prologue, onFileClick }) }),
490
+ chatGroups.map(
491
+ (group, idx) => group.role === "user" ? renderUserGroup(group) : renderBotGroup(
492
+ group,
493
+ idx === chatGroups.length - 1,
494
+ renderFunctionCall
495
+ )
496
+ ),
497
+ renderSuggestions(),
498
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: messagesEndRef })
499
+ ] }) });
500
+ }
501
+ );
502
+ XAdkChatbot.displayName = "XAdkChatbot";
459
503
  var XAdkChatbot_default = XAdkChatbot;
460
504
  //# sourceMappingURL=index.js.map