@ai-group/chat-sdk 3.4.6 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +415 -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 +40 -9
  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,440 @@ 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 timer = setTimeout(() => {
117
+ var _a;
118
+ (_a = messagesEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "auto" });
119
+ }, 0);
120
+ return () => clearTimeout(timer);
121
+ }, [initialized, messages]);
122
+ (0, import_react.useEffect)(() => {
123
+ if (sessionId === void 0)
124
+ return;
125
+ if (prevSessionIdRef.current === sessionId)
126
+ return;
127
+ prevSessionIdRef.current = sessionId;
128
+ prevInitializedRef.current = false;
129
129
  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")
130
+ }, [sessionId]);
131
+ (0, import_react.useEffect)(() => {
132
+ var _a;
133
+ if (!loading)
156
134
  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",
135
+ if (userHasScrolledRef.current)
136
+ return;
137
+ (_a = messagesEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
138
+ }, [loading, messages]);
139
+ const handleScroll = (0, import_react.useCallback)(() => {
140
+ const el = listRef.current;
141
+ if (!el)
142
+ return;
143
+ const currentTop = el.scrollTop;
144
+ if (currentTop < lastScrollTopRef.current) {
145
+ userHasScrolledRef.current = true;
146
+ }
147
+ const isAtBottom = Math.abs(el.scrollHeight - currentTop - el.clientHeight) <= scrollThreshold;
148
+ if (isAtBottom) {
149
+ userHasScrolledRef.current = false;
150
+ }
151
+ lastScrollTopRef.current = currentTop;
152
+ }, []);
153
+ (0, import_react.useEffect)(() => {
154
+ const listElement = listRef.current;
155
+ if (!listElement)
156
+ return;
157
+ listElement.addEventListener("scroll", handleScroll);
158
+ return () => {
159
+ listElement.removeEventListener("scroll", handleScroll);
160
+ };
161
+ }, [handleScroll]);
162
+ const chatGroups = (0, import_react.useMemo)(() => {
163
+ if (!enableGrouping) {
164
+ return messages.map((msg) => ({
165
+ id: msg.id,
166
+ role: msg.role,
171
167
  msgs: [msg],
172
168
  invocationId: msg.invocationId,
173
- allFiles: [],
169
+ allFiles: msg.fileData || [],
174
170
  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);
171
+ }));
218
172
  }
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
- });
173
+ const groups = [];
174
+ messages.forEach((msg) => {
175
+ if (msg.role === "followup")
176
+ return;
177
+ const isRealUserQuery = msg.role === "user" && !msg.functionResponse && !msg.functionCall;
178
+ const lastGroup = groups[groups.length - 1];
179
+ const isLastGroupAgent = (lastGroup == null ? void 0 : lastGroup.role) === "bot";
180
+ if (isLastGroupAgent && !isRealUserQuery) {
181
+ lastGroup.msgs.push(msg);
182
+ if (msg.invocationId)
183
+ lastGroup.invocationId = msg.invocationId;
184
+ if (msg.isLike && msg.isLike !== 0) {
185
+ lastGroup.isLike = msg.isLike;
246
186
  }
187
+ } else {
188
+ groups.push({
189
+ id: msg.id || `group-${groups.length}`,
190
+ role: isRealUserQuery ? "user" : "bot",
191
+ msgs: [msg],
192
+ invocationId: msg.invocationId,
193
+ allFiles: [],
194
+ isLike: msg.isLike ?? 0
195
+ });
247
196
  }
248
197
  });
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 = [];
198
+ groups.forEach((g) => {
199
+ g.allFiles = g.msgs.reduce(
200
+ (acc, m) => [...acc, ...m.fileData || []],
201
+ []
202
+ );
203
+ });
204
+ return groups;
205
+ }, [messages, enableGrouping]);
206
+ const renderBotGroup = (0, import_react.useCallback)(
207
+ (group, isLastGroup, renderFunctionCall2) => {
208
+ const { msgs, allFiles } = group;
209
+ if (!enableProcessParsing) {
210
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.botMsg, children: msgs.map((msg, i) => {
211
+ var _a;
212
+ if (msg.text) {
213
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
214
+ import_MarkdownRender.default,
215
+ {
216
+ text: msg.text,
217
+ onFileClick
218
+ },
219
+ `${msg.id}-${i}`
220
+ );
221
+ }
222
+ if (msg.functionCall) {
223
+ return (renderFunctionCall2 == null ? void 0 : renderFunctionCall2(msg)) ?? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
224
+ import_FunctionCallRender.default,
225
+ {
226
+ msg,
227
+ showDetail: showFnCallDetail,
228
+ onConfirm,
229
+ kind: resolveToolKind((_a = msg.functionCall) == null ? void 0 : _a.name, msg),
230
+ renderApproval: mergedStrategies.renderApproval,
231
+ renderHandoff: mergedStrategies.renderHandoff
232
+ },
233
+ `${msg.id}-${i}`
234
+ );
235
+ }
236
+ return null;
237
+ }) }, group.id);
260
238
  }
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
239
+ const mergedToolMap = /* @__PURE__ */ new Map();
240
+ msgs.forEach((msg) => {
241
+ if (msg.functionCall) {
242
+ const callId = msg.functionCall.id || "";
243
+ if (!mergedToolMap.has(callId)) {
244
+ mergedToolMap.set(callId, { ...msg });
245
+ } else {
246
+ mergedToolMap.set(callId, {
247
+ ...mergedToolMap.get(callId) ?? {},
248
+ ...msg
273
249
  });
274
- processedToolIds.add(callId);
275
250
  }
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
- });
251
+ } else if (msg.functionResponse) {
252
+ const callId = msg.functionResponse.id || "";
253
+ if (mergedToolMap.has(callId)) {
254
+ const tool = mergedToolMap.get(callId);
255
+ if (tool)
256
+ tool.functionResponse = msg.functionResponse;
300
257
  } 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
- });
258
+ mergedToolMap.set(callId, {
259
+ ...msg,
260
+ functionCall: {
261
+ id: callId,
262
+ name: msg.functionResponse.name || "Unknown",
263
+ args: {}
312
264
  }
313
- }
265
+ });
314
266
  }
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
267
  }
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
- }
268
+ });
269
+ const nodes = [];
270
+ let currentProcessItems = [];
271
+ const processedToolIds = /* @__PURE__ */ new Set();
272
+ const flushProcessItems = () => {
273
+ if (currentProcessItems.length > 0) {
274
+ nodes.push({
275
+ type: "process",
276
+ items: [...currentProcessItems],
277
+ key: `process-${nodes.length}`
278
+ });
279
+ currentProcessItems = [];
280
+ }
281
+ };
282
+ msgs.forEach((msg) => {
283
+ if (msg.functionCall) {
284
+ const callId = msg.functionCall.id || "";
285
+ if (!processedToolIds.has(callId)) {
286
+ const mergedMsg = mergedToolMap.get(callId);
287
+ if (mergedMsg) {
288
+ currentProcessItems.push({
289
+ type: "tool",
290
+ key: `tool-${callId}`,
291
+ content: "",
292
+ msg: mergedMsg
293
+ });
294
+ processedToolIds.add(callId);
365
295
  }
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
- )
296
+ }
297
+ } else if (msg.text && !msg.functionResponse) {
298
+ const parts = parseProcessMessage(msg.text, parseOptions);
299
+ parts.forEach((part, partIdx) => {
300
+ if ([
301
+ "planning",
302
+ "replanning",
303
+ "reasoning",
304
+ "action_log",
305
+ "process_text"
306
+ ].includes(part.type)) {
307
+ const titleMap = {
308
+ planning: "任务规划",
309
+ replanning: "重新规划",
310
+ reasoning: "推理分析",
311
+ action_log: "行动记录",
312
+ process_text: "过程分析"
313
+ };
314
+ currentProcessItems.push({
315
+ type: "text",
316
+ key: `${msg.id}-${partIdx}`,
317
+ content: part.content,
318
+ title: titleMap[part.type] || "分析"
319
+ });
320
+ } else {
321
+ flushProcessItems();
322
+ if (part.content.trim()) {
323
+ const lastNode = nodes[nodes.length - 1];
324
+ if ((lastNode == null ? void 0 : lastNode.type) === "text") {
325
+ lastNode.content += "\n\n" + part.content;
326
+ } else {
327
+ nodes.push({
328
+ type: "text",
329
+ content: part.content,
330
+ key: `text-${msg.id}-${partIdx}`
331
+ });
332
+ }
333
+ }
374
334
  }
375
- ) })
335
+ });
336
+ }
337
+ });
338
+ flushProcessItems();
339
+ const fullTextToCopy = msgs.filter((m) => !m.functionCall && !m.functionResponse).map((m) => m.text || "").join("");
340
+ const lastBotMsg = msgs[msgs.length - 1];
341
+ const hasProcess = nodes.some((n) => n.type === "process");
342
+ const isGroupLoading = loading && isLastGroup;
343
+ const actionProps = { message: group, isLastBotMsg: isLastGroup };
344
+ const actionExtraNode = actionsExtra == null ? void 0 : actionsExtra(actionProps);
345
+ const lastProcessIdx = nodes.findLastIndex(
346
+ (n) => n.type === "process"
347
+ );
348
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.botMsg, children: [
349
+ nodes.map((node, idx) => {
350
+ if (node.type === "process") {
351
+ const isLastProcess = idx === lastProcessIdx;
352
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
353
+ import_XAdkThoughtChain.default,
354
+ {
355
+ loading: isLastProcess && isGroupLoading,
356
+ title: "思维链已完成",
357
+ items: node.items,
358
+ showFnCallDetail,
359
+ onConfirm,
360
+ defaultOpen: isLastProcess && isGroupLoading,
361
+ renderFunctionCall: renderFunctionCall2,
362
+ toolKindResolver: (name) => resolveToolKind(name),
363
+ strategies: mergedStrategies
364
+ },
365
+ node.key
366
+ );
367
+ }
368
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_MarkdownRender.default, { text: node.content, onFileClick }) }, node.key);
369
+ }),
370
+ allFiles.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.fileSection, children: [
371
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.fileHeader, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
372
+ "生成文件 (",
373
+ allFiles.length,
374
+ ")"
375
+ ] }) }),
376
+ /* @__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
377
  ] }),
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
378
+ !isGroupLoading && (actions || showRetry || showCopy || showLog || actionExtraNode) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.metaFooter, children: [
379
+ actions ? actions(actionProps) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_antd.Flex, { gap: 16, className: styles.actionIcons, children: [
380
+ showRetry && isLastGroup && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Tooltip, { title: "重新生成", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.ReloadOutlined, { onClick: onRetry }) }),
381
+ showCopy && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Tooltip, { title: "复制内容", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
382
+ import_icons.CopyOutlined,
383
+ {
384
+ onClick: () => {
385
+ (0, import_copy_to_clipboard.default)(fullTextToCopy);
386
+ import_antd.message.success("复制成功");
387
+ onCopy == null ? void 0 : onCopy(fullTextToCopy);
388
+ }
389
+ }
390
+ ) }),
391
+ showLog && (lastBotMsg == null ? void 0 : lastBotMsg.invocationId) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Tooltip, { title: "查看日志", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
392
+ import_icons.InfoCircleOutlined,
393
+ {
394
+ onClick: () => onShowLog == null ? void 0 : onShowLog(
395
+ lastBotMsg.invocationId,
396
+ lastBotMsg.timestamp
397
+ )
398
+ }
399
+ ) })
400
+ ] }),
401
+ actionExtraNode
402
+ ] })
403
+ ] }, group.id);
404
+ },
405
+ [
406
+ enableProcessParsing,
407
+ parseOptions,
408
+ parseProcessMessage,
409
+ showFnCallDetail,
410
+ onConfirm,
411
+ loading,
412
+ showRetry,
413
+ showCopy,
414
+ showLog,
415
+ onRetry,
416
+ onCopy,
417
+ onShowLog,
418
+ actions,
419
+ actionsExtra,
420
+ onFileClick,
421
+ styles,
422
+ resolveToolKind,
423
+ mergedStrategies
424
+ ]
425
+ );
426
+ const renderUserGroup = (0, import_react.useCallback)(
427
+ (group) => {
428
+ 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: [
429
+ 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)(
430
+ import_FileGallery.default,
431
+ {
432
+ file,
433
+ align: "left",
434
+ style: { marginBottom: "16px" },
435
+ onClick: onFileClick
436
+ },
437
+ index
438
+ )) }),
439
+ m.text && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.card, children: m.text })
440
+ ] }, m.id || i)) }, group.id);
441
+ },
442
+ [styles, onFileClick]
443
+ );
444
+ const renderSuggestions = () => {
445
+ if (!suggestions || suggestions.length === 0)
446
+ return null;
447
+ 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)(
448
+ import_antd.Button,
449
+ {
450
+ type: "text",
451
+ icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.SwapRightOutlined, {}),
452
+ iconPosition: "end",
453
+ onClick: () => {
454
+ if (!item)
455
+ return;
456
+ onSuggest == null ? void 0 : onSuggest(item);
412
457
  },
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
- };
458
+ style: {
459
+ whiteSpace: "normal",
460
+ height: "auto",
461
+ wordWrap: "break-word",
462
+ textAlign: "left",
463
+ padding: "4px 15px",
464
+ lineHeight: "1.5"
465
+ },
466
+ children: item
467
+ }
468
+ ) }) }, item)) });
469
+ };
470
+ 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: [
471
+ prologue && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.prologue, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_MarkdownRender.default, { text: prologue, onFileClick }) }),
472
+ chatGroups.map(
473
+ (group, idx) => group.role === "user" ? renderUserGroup(group) : renderBotGroup(
474
+ group,
475
+ idx === chatGroups.length - 1,
476
+ renderFunctionCall
477
+ )
478
+ ),
479
+ renderSuggestions(),
480
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: messagesEndRef })
481
+ ] }) });
482
+ }
483
+ );
484
+ XAdkChatbot.displayName = "XAdkChatbot";
459
485
  var XAdkChatbot_default = XAdkChatbot;
460
486
  //# sourceMappingURL=index.js.map