@ai-group/chat-sdk 3.6.11 → 3.7.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 (149) hide show
  1. package/dist/cjs/components/XAdkChatbot/index.js +27 -15
  2. package/dist/cjs/components/XAdkChatbot/index.js.map +2 -2
  3. package/dist/cjs/components/XAdkProvider/compound/Sender.d.ts +2 -2
  4. package/dist/cjs/components/XAdkProvider/compound/Sender.js +20 -17
  5. package/dist/cjs/components/XAdkProvider/compound/Sender.js.map +2 -2
  6. package/dist/cjs/components/XAdkProvider/compound/Sidebar.js +6 -2
  7. package/dist/cjs/components/XAdkProvider/compound/Sidebar.js.map +2 -2
  8. package/dist/cjs/components/XAdkProvider/context/ChatSenderStateContext.d.ts +6 -2
  9. package/dist/cjs/components/XAdkProvider/context/ChatSenderStateContext.js.map +2 -2
  10. package/dist/cjs/components/XAdkProvider/index.js +8 -5
  11. package/dist/cjs/components/XAdkProvider/index.js.map +2 -2
  12. package/dist/cjs/components/XAdkSender/index.js +502 -496
  13. package/dist/cjs/components/XAdkSender/index.js.map +2 -2
  14. package/dist/cjs/components/XAdkSender/styles.js +0 -13
  15. package/dist/cjs/components/XAdkSender/styles.js.map +2 -2
  16. package/dist/cjs/core/index.d.ts +2 -0
  17. package/dist/cjs/core/index.js +26 -0
  18. package/dist/cjs/core/index.js.map +7 -0
  19. package/dist/cjs/core/protocol/index.d.ts +3 -0
  20. package/dist/cjs/core/protocol/index.js +28 -0
  21. package/dist/cjs/core/protocol/index.js.map +7 -0
  22. package/dist/cjs/core/protocol/messages.d.ts +55 -0
  23. package/dist/cjs/core/protocol/messages.js +307 -0
  24. package/dist/cjs/core/protocol/messages.js.map +7 -0
  25. package/dist/cjs/core/protocol/parts.d.ts +24 -0
  26. package/dist/cjs/core/protocol/parts.js +106 -0
  27. package/dist/cjs/core/protocol/parts.js.map +7 -0
  28. package/dist/cjs/core/protocol/types.d.ts +57 -0
  29. package/dist/cjs/core/protocol/types.js +18 -0
  30. package/dist/cjs/core/protocol/types.js.map +7 -0
  31. package/dist/cjs/core/runtime/createAdkConversationController.d.ts +8 -0
  32. package/dist/cjs/core/runtime/createAdkConversationController.js +424 -0
  33. package/dist/cjs/core/runtime/createAdkConversationController.js.map +7 -0
  34. package/dist/cjs/core/runtime/index.d.ts +2 -0
  35. package/dist/cjs/core/runtime/index.js +26 -0
  36. package/dist/cjs/core/runtime/index.js.map +7 -0
  37. package/dist/cjs/core/runtime/types.d.ts +130 -0
  38. package/dist/cjs/core/runtime/types.js +18 -0
  39. package/dist/cjs/core/runtime/types.js.map +7 -0
  40. package/dist/{esm/utils/umdEntry.d.ts → cjs/entries/umd.d.ts} +7 -0
  41. package/dist/cjs/{utils/umdEntry.js → entries/umd.js} +19 -9
  42. package/dist/cjs/entries/umd.js.map +7 -0
  43. package/dist/cjs/hooks/useADKChat.js +1 -0
  44. package/dist/cjs/hooks/useADKChat.js.map +2 -2
  45. package/dist/cjs/index.d.ts +6 -1
  46. package/dist/cjs/index.js +19 -11
  47. package/dist/cjs/index.js.map +3 -3
  48. package/dist/cjs/presets/xgroup/index.d.ts +4 -0
  49. package/dist/cjs/presets/xgroup/index.js +30 -0
  50. package/dist/cjs/presets/xgroup/index.js.map +7 -0
  51. package/dist/cjs/presets/xgroup/preset.d.ts +15 -0
  52. package/dist/cjs/presets/xgroup/preset.js +69 -0
  53. package/dist/cjs/presets/xgroup/preset.js.map +7 -0
  54. package/dist/cjs/presets/xgroup/strategies.d.ts +8 -0
  55. package/dist/cjs/presets/xgroup/strategies.js +53 -0
  56. package/dist/cjs/presets/xgroup/strategies.js.map +7 -0
  57. package/dist/cjs/presets/xgroup/transport.d.ts +15 -0
  58. package/dist/cjs/presets/xgroup/transport.js +183 -0
  59. package/dist/cjs/presets/xgroup/transport.js.map +7 -0
  60. package/dist/cjs/presets/xgroup/upload.d.ts +8 -0
  61. package/dist/cjs/presets/xgroup/upload.js +65 -0
  62. package/dist/cjs/presets/xgroup/upload.js.map +7 -0
  63. package/dist/cjs/react/index.d.ts +6 -0
  64. package/dist/cjs/react/index.js +53 -0
  65. package/dist/cjs/react/index.js.map +7 -0
  66. package/dist/cjs/react/useAdkConversation.d.ts +27 -0
  67. package/dist/cjs/react/useAdkConversation.js +69 -0
  68. package/dist/cjs/react/useAdkConversation.js.map +7 -0
  69. package/dist/cjs/types/XAdkSender.d.ts +0 -2
  70. package/dist/cjs/types/XAdkSender.js.map +1 -1
  71. package/dist/esm/components/XAdkChatbot/index.js +1 -1
  72. package/dist/esm/components/XAdkChatbot/index.js.map +1 -1
  73. package/dist/esm/components/XAdkProvider/compound/Sender.d.ts +2 -2
  74. package/dist/esm/components/XAdkProvider/compound/Sender.js +7 -4
  75. package/dist/esm/components/XAdkProvider/compound/Sender.js.map +1 -1
  76. package/dist/esm/components/XAdkProvider/compound/Sidebar.js +7 -2
  77. package/dist/esm/components/XAdkProvider/compound/Sidebar.js.map +1 -1
  78. package/dist/esm/components/XAdkProvider/context/ChatSenderStateContext.d.ts +6 -2
  79. package/dist/esm/components/XAdkProvider/context/ChatSenderStateContext.js.map +1 -1
  80. package/dist/esm/components/XAdkProvider/index.js +13 -4
  81. package/dist/esm/components/XAdkProvider/index.js.map +1 -1
  82. package/dist/esm/components/XAdkSender/index.js +2 -5
  83. package/dist/esm/components/XAdkSender/index.js.map +1 -1
  84. package/dist/esm/components/XAdkSender/styles.js +1 -1
  85. package/dist/esm/components/XAdkSender/styles.js.map +1 -1
  86. package/dist/esm/core/index.d.ts +2 -0
  87. package/dist/esm/core/index.js +3 -0
  88. package/dist/esm/core/index.js.map +1 -0
  89. package/dist/esm/core/protocol/index.d.ts +3 -0
  90. package/dist/esm/core/protocol/index.js +4 -0
  91. package/dist/esm/core/protocol/index.js.map +1 -0
  92. package/dist/esm/core/protocol/messages.d.ts +55 -0
  93. package/dist/esm/core/protocol/messages.js +315 -0
  94. package/dist/esm/core/protocol/messages.js.map +1 -0
  95. package/dist/esm/core/protocol/parts.d.ts +24 -0
  96. package/dist/esm/core/protocol/parts.js +100 -0
  97. package/dist/esm/core/protocol/parts.js.map +1 -0
  98. package/dist/esm/core/protocol/types.d.ts +57 -0
  99. package/dist/esm/core/protocol/types.js +2 -0
  100. package/dist/esm/core/protocol/types.js.map +1 -0
  101. package/dist/esm/core/runtime/createAdkConversationController.d.ts +8 -0
  102. package/dist/esm/core/runtime/createAdkConversationController.js +742 -0
  103. package/dist/esm/core/runtime/createAdkConversationController.js.map +1 -0
  104. package/dist/esm/core/runtime/index.d.ts +2 -0
  105. package/dist/esm/core/runtime/index.js +3 -0
  106. package/dist/esm/core/runtime/index.js.map +1 -0
  107. package/dist/esm/core/runtime/types.d.ts +130 -0
  108. package/dist/esm/core/runtime/types.js +2 -0
  109. package/dist/esm/core/runtime/types.js.map +1 -0
  110. package/dist/{cjs/utils/umdEntry.d.ts → esm/entries/umd.d.ts} +7 -0
  111. package/dist/esm/{utils/umdEntry.js → entries/umd.js} +10 -1
  112. package/dist/esm/entries/umd.js.map +1 -0
  113. package/dist/esm/hooks/useADKChat.js +2 -1
  114. package/dist/esm/hooks/useADKChat.js.map +1 -1
  115. package/dist/esm/index.d.ts +6 -1
  116. package/dist/esm/index.js +6 -1
  117. package/dist/esm/index.js.map +1 -1
  118. package/dist/esm/presets/xgroup/index.d.ts +4 -0
  119. package/dist/esm/presets/xgroup/index.js +5 -0
  120. package/dist/esm/presets/xgroup/index.js.map +1 -0
  121. package/dist/esm/presets/xgroup/preset.d.ts +15 -0
  122. package/dist/esm/presets/xgroup/preset.js +44 -0
  123. package/dist/esm/presets/xgroup/preset.js.map +1 -0
  124. package/dist/esm/presets/xgroup/strategies.d.ts +8 -0
  125. package/dist/esm/presets/xgroup/strategies.js +30 -0
  126. package/dist/esm/presets/xgroup/strategies.js.map +1 -0
  127. package/dist/esm/presets/xgroup/transport.d.ts +15 -0
  128. package/dist/esm/presets/xgroup/transport.js +322 -0
  129. package/dist/esm/presets/xgroup/transport.js.map +1 -0
  130. package/dist/esm/presets/xgroup/upload.d.ts +8 -0
  131. package/dist/esm/presets/{xGroupAdk.js → xgroup/upload.js} +9 -63
  132. package/dist/esm/presets/xgroup/upload.js.map +1 -0
  133. package/dist/esm/react/index.d.ts +6 -0
  134. package/dist/esm/react/index.js +5 -0
  135. package/dist/esm/react/index.js.map +1 -0
  136. package/dist/esm/react/useAdkConversation.d.ts +27 -0
  137. package/dist/esm/react/useAdkConversation.js +53 -0
  138. package/dist/esm/react/useAdkConversation.js.map +1 -0
  139. package/dist/esm/types/XAdkSender.d.ts +0 -2
  140. package/dist/esm/types/XAdkSender.js.map +1 -1
  141. package/dist/umd/chat-sdk.min.js +1 -1
  142. package/package.json +36 -2
  143. package/dist/cjs/presets/xGroupAdk.d.ts +0 -20
  144. package/dist/cjs/presets/xGroupAdk.js +0 -130
  145. package/dist/cjs/presets/xGroupAdk.js.map +0 -7
  146. package/dist/cjs/utils/umdEntry.js.map +0 -7
  147. package/dist/esm/presets/xGroupAdk.d.ts +0 -20
  148. package/dist/esm/presets/xGroupAdk.js.map +0 -1
  149. package/dist/esm/utils/umdEntry.js.map +0 -1
@@ -0,0 +1,55 @@
1
+ import type { Event, IMessage } from "../../types";
2
+ import { buildAdkUserParts } from "./parts";
3
+ import type { AdkProtocolOptions, BuildAdkUserPartsInput, MessageEventMeta, NormalizedAdkPart } from "./types";
4
+ /**
5
+ * 获取消息对应的服务端 eventId。
6
+ * session events 补偿和去重会优先用服务端 id,避免前端临时 id 导致重复插入。
7
+ */
8
+ export declare const getAdkMessageEventId: (message: IMessage) => any;
9
+ /**
10
+ * 获取单次模型调用 id。流式分片与 sessionDetails 完整消息通常共享 invocationId,
11
+ * 可用它判断哪些文本属于同一轮回复。
12
+ */
13
+ export declare const getAdkMessageInvocationId: (message: IMessage) => any;
14
+ /**
15
+ * 后端为异步任务补链路时可能插入 user task 事件,这类事件用于关联任务,
16
+ * 默认不作为用户可见消息展示。
17
+ */
18
+ export declare const isAdkAsyncTaskEvent: (event: Event) => boolean;
19
+ export declare const isUserFunctionResponseEvent: (event: Event) => boolean;
20
+ /**
21
+ * 提取 event 级元信息,保证 stream 最后一条里的 modelCode / usageMetadata
22
+ * 能透传到 IMessage,业务侧可据此展示 token 消耗等信息。
23
+ */
24
+ export declare const getAdkEventMeta: (event: Event) => MessageEventMeta;
25
+ export declare const createAdkMessage: (event: Event, part: NormalizedAdkPart, role?: IMessage["role"]) => IMessage;
26
+ /**
27
+ * 将单个 ADK event 转换为 SDK 消息。
28
+ *
29
+ * followup 事件由上层作为 suggestedQuestions 处理;user functionResponse
30
+ * 默认只用于回填对应 functionCall,不单独展示成一条用户消息。
31
+ */
32
+ export declare const mapAdkEventToMessages: (event: Event, options?: AdkProtocolOptions) => IMessage[];
33
+ export declare const mapAdkSessionEventsToMessages: (events?: Event[], options?: AdkProtocolOptions) => IMessage[];
34
+ /**
35
+ * 消息去重分两层:
36
+ * - 先按前端 id 去重。
37
+ * - 再按 invocationId + thought + fileUri 聚合同一轮 bot 文本,保留更完整的长文本。
38
+ *
39
+ * 第二层主要解决 SSE 增量文本和 sessionDetails 完整文本同时存在时重复展示的问题。
40
+ */
41
+ export declare const dedupeAdkMessages: (messages: IMessage[]) => IMessage[];
42
+ export declare const insertMissingAdkSessionEvents: (currentMessages: IMessage[], sessionEvents: Event[], options?: AdkProtocolOptions & {
43
+ removedInvocationIds?: Set<string>;
44
+ }) => IMessage[];
45
+ /**
46
+ * 从 session events 中收集工具响应,用于回填前面已经渲染出来的 functionCall。
47
+ */
48
+ export declare const collectFunctionResponses: (events: Event[]) => Map<string, import("../../types").FunctionResponse>;
49
+ export declare const pairFunctionResponses: (messages: IMessage[], responses?: Map<string, NonNullable<IMessage["functionResponse"]>>) => IMessage[];
50
+ /**
51
+ * 构造本地乐观用户消息。
52
+ * controller 在真正发请求前会先插入这些消息,让 UI 立即响应用户输入。
53
+ */
54
+ export declare const buildAdkUserMessage: ({ text, files, functionResponse, }: BuildAdkUserPartsInput) => IMessage[];
55
+ export { buildAdkUserParts };
@@ -0,0 +1,315 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
2
+ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
3
+ import { v4 } from "uuid";
4
+ import { buildAdkUserParts, normalizeAdkParts } from "./parts";
5
+ var defaultProtocolOptions = {
6
+ hideAsyncTaskEvents: true,
7
+ pairFunctionResponses: true
8
+ };
9
+
10
+ /**
11
+ * 获取消息对应的服务端 eventId。
12
+ * session events 补偿和去重会优先用服务端 id,避免前端临时 id 导致重复插入。
13
+ */
14
+ export var getAdkMessageEventId = function getAdkMessageEventId(message) {
15
+ var _message$raw;
16
+ return message.eventId || ((_message$raw = message.raw) === null || _message$raw === void 0 ? void 0 : _message$raw.id) || message.id;
17
+ };
18
+
19
+ /**
20
+ * 获取单次模型调用 id。流式分片与 sessionDetails 完整消息通常共享 invocationId,
21
+ * 可用它判断哪些文本属于同一轮回复。
22
+ */
23
+ export var getAdkMessageInvocationId = function getAdkMessageInvocationId(message) {
24
+ var _message$raw2;
25
+ return message.invocationId || ((_message$raw2 = message.raw) === null || _message$raw2 === void 0 ? void 0 : _message$raw2.invocationId);
26
+ };
27
+
28
+ /**
29
+ * 后端为异步任务补链路时可能插入 user task 事件,这类事件用于关联任务,
30
+ * 默认不作为用户可见消息展示。
31
+ */
32
+ export var isAdkAsyncTaskEvent = function isAdkAsyncTaskEvent(event) {
33
+ var _event$content;
34
+ return event.author === "user" && ((_event$content = event.content) === null || _event$content === void 0 || (_event$content = _event$content.parts) === null || _event$content === void 0 ? void 0 : _event$content.some(function (part) {
35
+ return Boolean(part === null || part === void 0 ? void 0 : part.task);
36
+ }));
37
+ };
38
+ export var isUserFunctionResponseEvent = function isUserFunctionResponseEvent(event) {
39
+ var _event$content2;
40
+ return ((_event$content2 = event.content) === null || _event$content2 === void 0 ? void 0 : _event$content2.role) === "user" && Array.isArray(event.content.parts) && event.content.parts.length > 0 && event.content.parts.every(function (part) {
41
+ return Boolean(part === null || part === void 0 ? void 0 : part.functionResponse);
42
+ });
43
+ };
44
+
45
+ /**
46
+ * 提取 event 级元信息,保证 stream 最后一条里的 modelCode / usageMetadata
47
+ * 能透传到 IMessage,业务侧可据此展示 token 消耗等信息。
48
+ */
49
+ export var getAdkEventMeta = function getAdkEventMeta(event) {
50
+ return {
51
+ eventId: event.id,
52
+ invocationId: event.invocationId,
53
+ sessionId: event.sessionId,
54
+ timestamp: event.timestamp,
55
+ author: event.author,
56
+ modelCode: event.modelCode,
57
+ usageMetadata: event.usageMetadata,
58
+ finishReason: event.finishReason,
59
+ isLike: event.isLike
60
+ };
61
+ };
62
+ export var createAdkMessage = function createAdkMessage(event, part) {
63
+ var _event$groundingMetad;
64
+ var role = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "bot";
65
+ return _objectSpread(_objectSpread({
66
+ id: v4(),
67
+ role: role
68
+ }, getAdkEventMeta(event)), {}, {
69
+ thought: part.thought,
70
+ functionCall: part.functionCall,
71
+ functionResponse: part.functionResponse,
72
+ fileData: part.fileDataList || (part.fileData ? [part.fileData] : undefined),
73
+ inlineData: part.inlineData,
74
+ executableCode: part.executableCode,
75
+ codeExecutionResult: part.codeExecutionResult,
76
+ text: part.errorMessage || part.text,
77
+ renderedContent: (_event$groundingMetad = event.groundingMetadata) === null || _event$groundingMetad === void 0 || (_event$groundingMetad = _event$groundingMetad.searchEntryPoint) === null || _event$groundingMetad === void 0 ? void 0 : _event$groundingMetad.renderedContent,
78
+ raw: event
79
+ });
80
+ };
81
+
82
+ /**
83
+ * 将单个 ADK event 转换为 SDK 消息。
84
+ *
85
+ * followup 事件由上层作为 suggestedQuestions 处理;user functionResponse
86
+ * 默认只用于回填对应 functionCall,不单独展示成一条用户消息。
87
+ */
88
+ export var mapAdkEventToMessages = function mapAdkEventToMessages(event, options) {
89
+ var _event$content3, _event$content4, _event$actions;
90
+ var mergedOptions = _objectSpread(_objectSpread({}, defaultProtocolOptions), options);
91
+ if (mergedOptions.hideAsyncTaskEvents && isAdkAsyncTaskEvent(event)) return [];
92
+ if (mergedOptions.pairFunctionResponses && isUserFunctionResponseEvent(event)) return [];
93
+ if (((_event$content3 = event.content) === null || _event$content3 === void 0 ? void 0 : _event$content3.role) === "followup") return [];
94
+ if ((_event$content4 = event.content) !== null && _event$content4 !== void 0 && (_event$content4 = _event$content4.parts) !== null && _event$content4 !== void 0 && _event$content4.length) {
95
+ var role = event.content.role === "user" ? "user" : "bot";
96
+ return normalizeAdkParts(event.content.parts).map(function (part) {
97
+ return createAdkMessage(event, part, role);
98
+ });
99
+ }
100
+ if (event.errorMessage) {
101
+ return [_objectSpread(_objectSpread({
102
+ id: v4(),
103
+ role: "bot",
104
+ text: event.errorMessage
105
+ }, getAdkEventMeta(event)), {}, {
106
+ raw: event
107
+ })];
108
+ }
109
+ if ((_event$actions = event.actions) !== null && _event$actions !== void 0 && _event$actions.artifactDelta) {
110
+ return [_objectSpread(_objectSpread({
111
+ id: v4(),
112
+ role: "bot"
113
+ }, getAdkEventMeta(event)), {}, {
114
+ raw: event
115
+ })];
116
+ }
117
+ return [];
118
+ };
119
+ export var mapAdkSessionEventsToMessages = function mapAdkSessionEventsToMessages() {
120
+ var events = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
121
+ var options = arguments.length > 1 ? arguments[1] : undefined;
122
+ return pairFunctionResponses(events.flatMap(function (event) {
123
+ return mapAdkEventToMessages(event, options);
124
+ }));
125
+ };
126
+
127
+ /**
128
+ * 消息去重分两层:
129
+ * - 先按前端 id 去重。
130
+ * - 再按 invocationId + thought + fileUri 聚合同一轮 bot 文本,保留更完整的长文本。
131
+ *
132
+ * 第二层主要解决 SSE 增量文本和 sessionDetails 完整文本同时存在时重复展示的问题。
133
+ */
134
+ export var dedupeAdkMessages = function dedupeAdkMessages(messages) {
135
+ var seenMessageIds = new Set();
136
+ var hasDuplicate = false;
137
+ var uniqueIdMessages = messages.filter(function (message) {
138
+ if (seenMessageIds.has(message.id)) {
139
+ hasDuplicate = true;
140
+ return false;
141
+ }
142
+ seenMessageIds.add(message.id);
143
+ return true;
144
+ });
145
+ var botTextGroups = new Map();
146
+ uniqueIdMessages.forEach(function (message) {
147
+ var invocationId = getAdkMessageInvocationId(message);
148
+ if (message.role !== "bot" || !invocationId || typeof message.text !== "string") return;
149
+ var normalizedText = message.text.replace(/\s+/g, " ").trim();
150
+ if (!normalizedText) return;
151
+ var fileKey = (message.fileData || []).map(function (file) {
152
+ return file.fileUri;
153
+ }).join("|");
154
+ var groupKey = "".concat(invocationId, "\0").concat(Boolean(message.thought), "\0").concat(fileKey);
155
+ var group = botTextGroups.get(groupKey) || [];
156
+ group.push({
157
+ message: message,
158
+ normalizedText: normalizedText
159
+ });
160
+ botTextGroups.set(groupKey, group);
161
+ });
162
+ var redundantIds = new Set();
163
+ botTextGroups.forEach(function (group) {
164
+ var completeTexts = [];
165
+ _toConsumableArray(group).sort(function (a, b) {
166
+ return b.normalizedText.length - a.normalizedText.length;
167
+ }).forEach(function (_ref) {
168
+ var message = _ref.message,
169
+ normalizedText = _ref.normalizedText;
170
+ if (completeTexts.some(function (completeText) {
171
+ return completeText.includes(normalizedText);
172
+ })) {
173
+ redundantIds.add(message.id);
174
+ hasDuplicate = true;
175
+ return;
176
+ }
177
+ completeTexts.push(normalizedText);
178
+ });
179
+ });
180
+ return hasDuplicate ? uniqueIdMessages.filter(function (message) {
181
+ return !redundantIds.has(message.id);
182
+ }) : messages;
183
+ };
184
+ export var insertMissingAdkSessionEvents = function insertMissingAdkSessionEvents(currentMessages, sessionEvents, options) {
185
+ // 先用 sessionEvents 里的 functionResponse 回填已有 functionCall,避免工具状态丢失。
186
+ var nextMessages = pairFunctionResponses(currentMessages);
187
+ var functionResponses = collectFunctionResponses(sessionEvents);
188
+ if (functionResponses.size) {
189
+ nextMessages = pairFunctionResponses(nextMessages, functionResponses);
190
+ }
191
+ var renderedEventIds = new Set(nextMessages.map(getAdkMessageEventId).filter(Boolean));
192
+ var missingMessages = sessionEvents.filter(function (event) {
193
+ var _options$removedInvoc, _event$content5, _event$content6;
194
+ if (options !== null && options !== void 0 && (_options$removedInvoc = options.removedInvocationIds) !== null && _options$removedInvoc !== void 0 && _options$removedInvoc.has(event.invocationId || "")) return false;
195
+ var parts = (_event$content5 = event.content) === null || _event$content5 === void 0 ? void 0 : _event$content5.parts;
196
+ return Boolean(event.id) && ((_event$content6 = event.content) === null || _event$content6 === void 0 ? void 0 : _event$content6.role) === "model" && Array.isArray(parts) && parts.length > 0 && !renderedEventIds.has(event.id);
197
+ }).flatMap(function (event) {
198
+ return mapAdkEventToMessages(event, options);
199
+ });
200
+ if (!missingMessages.length) return nextMessages;
201
+
202
+ // 按服务端事件顺序插入缺失消息,尽量保持历史消息和流式消息的时间线一致。
203
+ var eventOrder = new Map(sessionEvents.map(function (event, index) {
204
+ return [event.id, index];
205
+ }));
206
+ var getMessageOrder = function getMessageOrder(message) {
207
+ var _message$timestamp, _message$raw3;
208
+ var eventId = getAdkMessageEventId(message);
209
+ if (eventId && eventOrder.has(eventId)) return eventOrder.get(eventId);
210
+ var timestamp = (_message$timestamp = message.timestamp) !== null && _message$timestamp !== void 0 ? _message$timestamp : (_message$raw3 = message.raw) === null || _message$raw3 === void 0 ? void 0 : _message$raw3.timestamp;
211
+ if (timestamp !== undefined) {
212
+ var nextEventIndex = sessionEvents.findIndex(function (event) {
213
+ return (event.timestamp || 0) > timestamp;
214
+ });
215
+ return nextEventIndex < 0 ? sessionEvents.length + 0.5 : nextEventIndex - 0.5;
216
+ }
217
+ return Number.POSITIVE_INFINITY;
218
+ };
219
+ missingMessages.forEach(function (message) {
220
+ var targetOrder = getMessageOrder(message);
221
+ var insertIndex = nextMessages.findIndex(function (current) {
222
+ var currentOrder = getMessageOrder(current);
223
+ return Number.isFinite(currentOrder) && currentOrder > targetOrder;
224
+ });
225
+ if (insertIndex < 0) insertIndex = nextMessages.length;
226
+ nextMessages.splice(insertIndex, 0, message);
227
+ });
228
+ return dedupeAdkMessages(pairFunctionResponses(nextMessages));
229
+ };
230
+
231
+ /**
232
+ * 从 session events 中收集工具响应,用于回填前面已经渲染出来的 functionCall。
233
+ */
234
+ export var collectFunctionResponses = function collectFunctionResponses(events) {
235
+ var functionResponses = new Map();
236
+ events.forEach(function (event) {
237
+ var _event$content7;
238
+ (_event$content7 = event.content) === null || _event$content7 === void 0 || (_event$content7 = _event$content7.parts) === null || _event$content7 === void 0 || _event$content7.forEach(function (part) {
239
+ var _part$functionRespons;
240
+ if ((_part$functionRespons = part.functionResponse) !== null && _part$functionRespons !== void 0 && _part$functionRespons.id) {
241
+ functionResponses.set(part.functionResponse.id, part.functionResponse);
242
+ }
243
+ });
244
+ });
245
+ return functionResponses;
246
+ };
247
+ export var pairFunctionResponses = function pairFunctionResponses(messages, responses) {
248
+ var responseMap = responses || new Map(messages.filter(function (message) {
249
+ var _message$functionResp;
250
+ return (_message$functionResp = message.functionResponse) === null || _message$functionResp === void 0 ? void 0 : _message$functionResp.id;
251
+ }).map(function (message) {
252
+ return [message.functionResponse.id, message.functionResponse];
253
+ }));
254
+ if (!responseMap.size) return messages;
255
+ return messages.map(function (message) {
256
+ var _message$functionCall;
257
+ var callId = (_message$functionCall = message.functionCall) === null || _message$functionCall === void 0 ? void 0 : _message$functionCall.id;
258
+ if (!callId || message.functionResponse || !responseMap.has(callId)) {
259
+ return message;
260
+ }
261
+ return _objectSpread(_objectSpread({}, message), {}, {
262
+ functionResponse: responseMap.get(callId)
263
+ });
264
+ });
265
+ };
266
+
267
+ /**
268
+ * 构造本地乐观用户消息。
269
+ * controller 在真正发请求前会先插入这些消息,让 UI 立即响应用户输入。
270
+ */
271
+ export var buildAdkUserMessage = function buildAdkUserMessage(_ref2) {
272
+ var _ref2$text = _ref2.text,
273
+ text = _ref2$text === void 0 ? "" : _ref2$text,
274
+ _ref2$files = _ref2.files,
275
+ files = _ref2$files === void 0 ? [] : _ref2$files,
276
+ functionResponse = _ref2.functionResponse;
277
+ var timestamp = Date.now();
278
+ var messages = [];
279
+ if (files.length) {
280
+ messages.push({
281
+ id: v4(),
282
+ role: "user",
283
+ timestamp: timestamp,
284
+ fileData: files.map(function (file) {
285
+ var _file$response, _file$response2, _file$response3, _file$response4;
286
+ var fileUri = file.tempUrl || file.fileUrl || ((_file$response = file.response) === null || _file$response === void 0 ? void 0 : _file$response.fileUrl) || ((_file$response2 = file.response) === null || _file$response2 === void 0 ? void 0 : _file$response2.tempUrl);
287
+ if (!fileUri) return null;
288
+ return {
289
+ displayName: file.fileName || file.name || ((_file$response3 = file.response) === null || _file$response3 === void 0 ? void 0 : _file$response3.fileName) || "",
290
+ mimeType: file.mimeType || ((_file$response4 = file.response) === null || _file$response4 === void 0 ? void 0 : _file$response4.mimeType) || "",
291
+ fileUri: fileUri
292
+ };
293
+ }).filter(Boolean)
294
+ });
295
+ }
296
+ if (text.trim()) {
297
+ messages.push({
298
+ id: v4(),
299
+ role: "user",
300
+ text: text,
301
+ timestamp: timestamp
302
+ });
303
+ }
304
+ if (functionResponse) {
305
+ messages.push({
306
+ id: v4(),
307
+ role: "user",
308
+ functionResponse: functionResponse,
309
+ timestamp: timestamp
310
+ });
311
+ }
312
+ return messages;
313
+ };
314
+ export { buildAdkUserParts };
315
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["v4","buildAdkUserParts","normalizeAdkParts","defaultProtocolOptions","hideAsyncTaskEvents","pairFunctionResponses","getAdkMessageEventId","message","_message$raw","eventId","raw","id","getAdkMessageInvocationId","_message$raw2","invocationId","isAdkAsyncTaskEvent","event","_event$content","author","content","parts","some","part","Boolean","task","isUserFunctionResponseEvent","_event$content2","role","Array","isArray","length","every","functionResponse","getAdkEventMeta","sessionId","timestamp","modelCode","usageMetadata","finishReason","isLike","createAdkMessage","_event$groundingMetad","arguments","undefined","_objectSpread","thought","functionCall","fileData","fileDataList","inlineData","executableCode","codeExecutionResult","text","errorMessage","renderedContent","groundingMetadata","searchEntryPoint","mapAdkEventToMessages","options","_event$content3","_event$content4","_event$actions","mergedOptions","map","actions","artifactDelta","mapAdkSessionEventsToMessages","events","flatMap","dedupeAdkMessages","messages","seenMessageIds","Set","hasDuplicate","uniqueIdMessages","filter","has","add","botTextGroups","Map","forEach","normalizedText","replace","trim","fileKey","file","fileUri","join","groupKey","concat","group","get","push","set","redundantIds","completeTexts","_toConsumableArray","sort","a","b","_ref","completeText","includes","insertMissingAdkSessionEvents","currentMessages","sessionEvents","nextMessages","functionResponses","collectFunctionResponses","size","renderedEventIds","missingMessages","_options$removedInvoc","_event$content5","_event$content6","removedInvocationIds","eventOrder","index","getMessageOrder","_message$timestamp","_message$raw3","nextEventIndex","findIndex","Number","POSITIVE_INFINITY","targetOrder","insertIndex","current","currentOrder","isFinite","splice","_event$content7","_part$functionRespons","responses","responseMap","_message$functionResp","_message$functionCall","callId","buildAdkUserMessage","_ref2","_ref2$text","_ref2$files","files","Date","now","_file$response","_file$response2","_file$response3","_file$response4","tempUrl","fileUrl","response","displayName","fileName","name","mimeType"],"sources":["../../../../src/core/protocol/messages.ts"],"sourcesContent":["import { v4 } from \"uuid\";\nimport type { Event, IMessage } from \"@/types\";\nimport { buildAdkUserParts, normalizeAdkParts } from \"./parts\";\nimport type {\n AdkProtocolOptions,\n BuildAdkUserPartsInput,\n MessageEventMeta,\n NormalizedAdkPart,\n} from \"./types\";\n\nconst defaultProtocolOptions: Required<AdkProtocolOptions> = {\n hideAsyncTaskEvents: true,\n pairFunctionResponses: true,\n};\n\n/**\n * 获取消息对应的服务端 eventId。\n * session events 补偿和去重会优先用服务端 id,避免前端临时 id 导致重复插入。\n */\nexport const getAdkMessageEventId = (message: IMessage) =>\n message.eventId || message.raw?.id || message.id;\n\n/**\n * 获取单次模型调用 id。流式分片与 sessionDetails 完整消息通常共享 invocationId,\n * 可用它判断哪些文本属于同一轮回复。\n */\nexport const getAdkMessageInvocationId = (message: IMessage) =>\n message.invocationId || message.raw?.invocationId;\n\n/**\n * 后端为异步任务补链路时可能插入 user task 事件,这类事件用于关联任务,\n * 默认不作为用户可见消息展示。\n */\nexport const isAdkAsyncTaskEvent = (event: Event) =>\n event.author === \"user\" &&\n event.content?.parts?.some((part) => Boolean((part as any)?.task));\n\nexport const isUserFunctionResponseEvent = (event: Event) =>\n event.content?.role === \"user\" &&\n Array.isArray(event.content.parts) &&\n event.content.parts.length > 0 &&\n event.content.parts.every((part) => Boolean(part?.functionResponse));\n\n/**\n * 提取 event 级元信息,保证 stream 最后一条里的 modelCode / usageMetadata\n * 能透传到 IMessage,业务侧可据此展示 token 消耗等信息。\n */\nexport const getAdkEventMeta = (event: Event): MessageEventMeta => ({\n eventId: event.id,\n invocationId: event.invocationId,\n sessionId: event.sessionId,\n timestamp: event.timestamp,\n author: event.author,\n modelCode: event.modelCode,\n usageMetadata: event.usageMetadata,\n finishReason: event.finishReason,\n isLike: event.isLike,\n});\n\nexport const createAdkMessage = (\n event: Event,\n part: NormalizedAdkPart,\n role: IMessage[\"role\"] = \"bot\",\n): IMessage => ({\n id: v4(),\n role,\n ...getAdkEventMeta(event),\n thought: part.thought,\n functionCall: part.functionCall,\n functionResponse: part.functionResponse,\n fileData: part.fileDataList || (part.fileData ? [part.fileData] : undefined),\n inlineData: part.inlineData,\n executableCode: part.executableCode,\n codeExecutionResult: part.codeExecutionResult,\n text: part.errorMessage || part.text,\n renderedContent: event.groundingMetadata?.searchEntryPoint?.renderedContent,\n raw: event,\n});\n\n/**\n * 将单个 ADK event 转换为 SDK 消息。\n *\n * followup 事件由上层作为 suggestedQuestions 处理;user functionResponse\n * 默认只用于回填对应 functionCall,不单独展示成一条用户消息。\n */\nexport const mapAdkEventToMessages = (\n event: Event,\n options?: AdkProtocolOptions,\n): IMessage[] => {\n const mergedOptions = { ...defaultProtocolOptions, ...options };\n if (mergedOptions.hideAsyncTaskEvents && isAdkAsyncTaskEvent(event)) return [];\n if (mergedOptions.pairFunctionResponses && isUserFunctionResponseEvent(event))\n return [];\n if (event.content?.role === \"followup\") return [];\n\n if (event.content?.parts?.length) {\n const role = event.content.role === \"user\" ? \"user\" : \"bot\";\n return normalizeAdkParts(event.content.parts).map((part) =>\n createAdkMessage(event, part, role),\n );\n }\n\n if (event.errorMessage) {\n return [\n {\n id: v4(),\n role: \"bot\",\n text: event.errorMessage,\n ...getAdkEventMeta(event),\n raw: event,\n },\n ];\n }\n\n if (event.actions?.artifactDelta) {\n return [\n {\n id: v4(),\n role: \"bot\",\n ...getAdkEventMeta(event),\n raw: event,\n },\n ];\n }\n\n return [];\n};\n\nexport const mapAdkSessionEventsToMessages = (\n events: Event[] = [],\n options?: AdkProtocolOptions,\n): IMessage[] => pairFunctionResponses(events.flatMap((event) =>\n mapAdkEventToMessages(event, options),\n));\n\n/**\n * 消息去重分两层:\n * - 先按前端 id 去重。\n * - 再按 invocationId + thought + fileUri 聚合同一轮 bot 文本,保留更完整的长文本。\n *\n * 第二层主要解决 SSE 增量文本和 sessionDetails 完整文本同时存在时重复展示的问题。\n */\nexport const dedupeAdkMessages = (messages: IMessage[]): IMessage[] => {\n const seenMessageIds = new Set<string>();\n let hasDuplicate = false;\n\n const uniqueIdMessages = messages.filter((message) => {\n if (seenMessageIds.has(message.id)) {\n hasDuplicate = true;\n return false;\n }\n seenMessageIds.add(message.id);\n return true;\n });\n\n const botTextGroups = new Map<\n string,\n Array<{ message: IMessage; normalizedText: string }>\n >();\n\n uniqueIdMessages.forEach((message) => {\n const invocationId = getAdkMessageInvocationId(message);\n if (\n message.role !== \"bot\" ||\n !invocationId ||\n typeof message.text !== \"string\"\n )\n return;\n\n const normalizedText = message.text.replace(/\\s+/g, \" \").trim();\n if (!normalizedText) return;\n\n const fileKey = (message.fileData || [])\n .map((file) => file.fileUri)\n .join(\"|\");\n const groupKey = `${invocationId}\\u0000${Boolean(\n message.thought,\n )}\\u0000${fileKey}`;\n const group = botTextGroups.get(groupKey) || [];\n group.push({ message, normalizedText });\n botTextGroups.set(groupKey, group);\n });\n\n const redundantIds = new Set<string>();\n botTextGroups.forEach((group) => {\n const completeTexts: string[] = [];\n [...group]\n .sort((a, b) => b.normalizedText.length - a.normalizedText.length)\n .forEach(({ message, normalizedText }) => {\n if (\n completeTexts.some((completeText) =>\n completeText.includes(normalizedText),\n )\n ) {\n redundantIds.add(message.id);\n hasDuplicate = true;\n return;\n }\n completeTexts.push(normalizedText);\n });\n });\n\n return hasDuplicate\n ? uniqueIdMessages.filter((message) => !redundantIds.has(message.id))\n : messages;\n};\n\nexport const insertMissingAdkSessionEvents = (\n currentMessages: IMessage[],\n sessionEvents: Event[],\n options?: AdkProtocolOptions & { removedInvocationIds?: Set<string> },\n): IMessage[] => {\n // 先用 sessionEvents 里的 functionResponse 回填已有 functionCall,避免工具状态丢失。\n let nextMessages = pairFunctionResponses(currentMessages);\n const functionResponses = collectFunctionResponses(sessionEvents);\n if (functionResponses.size) {\n nextMessages = pairFunctionResponses(nextMessages, functionResponses);\n }\n\n const renderedEventIds = new Set(\n nextMessages.map(getAdkMessageEventId).filter(Boolean),\n );\n\n const missingMessages = sessionEvents\n .filter((event) => {\n if (options?.removedInvocationIds?.has(event.invocationId || \"\"))\n return false;\n const parts = event.content?.parts;\n return (\n Boolean(event.id) &&\n event.content?.role === \"model\" &&\n Array.isArray(parts) &&\n parts.length > 0 &&\n !renderedEventIds.has(event.id)\n );\n })\n .flatMap((event) => mapAdkEventToMessages(event, options));\n\n if (!missingMessages.length) return nextMessages;\n\n // 按服务端事件顺序插入缺失消息,尽量保持历史消息和流式消息的时间线一致。\n const eventOrder = new Map(\n sessionEvents.map((event, index) => [event.id, index]),\n );\n const getMessageOrder = (message: IMessage) => {\n const eventId = getAdkMessageEventId(message);\n if (eventId && eventOrder.has(eventId)) return eventOrder.get(eventId)!;\n\n const timestamp = message.timestamp ?? message.raw?.timestamp;\n if (timestamp !== undefined) {\n const nextEventIndex = sessionEvents.findIndex(\n (event) => (event.timestamp || 0) > timestamp,\n );\n return nextEventIndex < 0\n ? sessionEvents.length + 0.5\n : nextEventIndex - 0.5;\n }\n return Number.POSITIVE_INFINITY;\n };\n\n missingMessages.forEach((message) => {\n const targetOrder = getMessageOrder(message);\n let insertIndex = nextMessages.findIndex((current) => {\n const currentOrder = getMessageOrder(current);\n return Number.isFinite(currentOrder) && currentOrder > targetOrder;\n });\n if (insertIndex < 0) insertIndex = nextMessages.length;\n nextMessages.splice(insertIndex, 0, message);\n });\n\n return dedupeAdkMessages(pairFunctionResponses(nextMessages));\n};\n\n/**\n * 从 session events 中收集工具响应,用于回填前面已经渲染出来的 functionCall。\n */\nexport const collectFunctionResponses = (events: Event[]) => {\n const functionResponses = new Map<\n string,\n NonNullable<IMessage[\"functionResponse\"]>\n >();\n events.forEach((event) => {\n event.content?.parts?.forEach((part) => {\n if (part.functionResponse?.id) {\n functionResponses.set(part.functionResponse.id, part.functionResponse);\n }\n });\n });\n return functionResponses;\n};\n\nexport const pairFunctionResponses = (\n messages: IMessage[],\n responses?: Map<string, NonNullable<IMessage[\"functionResponse\"]>>,\n): IMessage[] => {\n const responseMap =\n responses ||\n new Map(\n messages\n .filter((message) => message.functionResponse?.id)\n .map((message) => [\n message.functionResponse!.id!,\n message.functionResponse!,\n ]),\n );\n\n if (!responseMap.size) return messages;\n\n return messages.map((message) => {\n const callId = message.functionCall?.id;\n if (!callId || message.functionResponse || !responseMap.has(callId)) {\n return message;\n }\n return {\n ...message,\n functionResponse: responseMap.get(callId),\n };\n });\n};\n\n/**\n * 构造本地乐观用户消息。\n * controller 在真正发请求前会先插入这些消息,让 UI 立即响应用户输入。\n */\nexport const buildAdkUserMessage = ({\n text = \"\",\n files = [],\n functionResponse,\n}: BuildAdkUserPartsInput): IMessage[] => {\n const timestamp = Date.now();\n const messages: IMessage[] = [];\n\n if (files.length) {\n messages.push({\n id: v4(),\n role: \"user\",\n timestamp,\n fileData: files\n .map((file) => {\n const fileUri =\n file.tempUrl ||\n file.fileUrl ||\n file.response?.fileUrl ||\n file.response?.tempUrl;\n if (!fileUri) return null;\n return {\n displayName:\n file.fileName || file.name || file.response?.fileName || \"\",\n mimeType: file.mimeType || file.response?.mimeType || \"\",\n fileUri,\n };\n })\n .filter(Boolean) as IMessage[\"fileData\"],\n });\n }\n\n if (text.trim()) {\n messages.push({ id: v4(), role: \"user\", text, timestamp });\n }\n\n if (functionResponse) {\n messages.push({ id: v4(), role: \"user\", functionResponse, timestamp });\n }\n\n return messages;\n};\n\nexport { buildAdkUserParts };\n"],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { Part } from "../../types";
2
+ import type { BuildAdkUserPartsInput } from "./types";
3
+ import type { NormalizedAdkPart } from "./types";
4
+ /**
5
+ * 将后端 ADK parts 归一化成更适合 UI 渲染的片段。
6
+ *
7
+ * 设计目标:
8
+ * - 连续 text 会被合并,减少流式分片直接渲染带来的碎片化。
9
+ * - fileData 会合并到 fileDataList,支持“文件 + 文本”作为一条消息展示。
10
+ * - functionCall、functionResponse、代码执行等特殊 part 保持独立,避免影响工具渲染。
11
+ * - thought 发生切换时会结算当前缓冲,保证思考内容和普通回答不误合并。
12
+ */
13
+ export declare const normalizeAdkParts: (parts?: Part[]) => NormalizedAdkPart[];
14
+ /**
15
+ * 兼容早期只关注文本合并的调用方,语义上等同于 normalizeAdkParts。
16
+ */
17
+ export declare const combineAdkParts: (parts?: Part[]) => NormalizedAdkPart[];
18
+ /**
19
+ * 将 SDK Sender 的输入内容转换为 ADK 请求体里的 user parts。
20
+ *
21
+ * 这里保持“附件 part 在前、文本 part 在后”的顺序,和业务项目 useDebug
22
+ * 当前对后端协议的使用方式一致;functionResponse 场景只提交工具响应。
23
+ */
24
+ export declare const buildAdkUserParts: ({ text, files, functionResponse, }: BuildAdkUserPartsInput) => Part[];
@@ -0,0 +1,100 @@
1
+ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
+ var hasContent = function hasContent(text, files) {
3
+ return Boolean(text) || Boolean(files === null || files === void 0 ? void 0 : files.length);
4
+ };
5
+ var isSpecialPart = function isSpecialPart(part) {
6
+ return Boolean(part.functionCall || part.functionResponse || part.executableCode || part.codeExecutionResult || part.actions);
7
+ };
8
+
9
+ /**
10
+ * 将后端 ADK parts 归一化成更适合 UI 渲染的片段。
11
+ *
12
+ * 设计目标:
13
+ * - 连续 text 会被合并,减少流式分片直接渲染带来的碎片化。
14
+ * - fileData 会合并到 fileDataList,支持“文件 + 文本”作为一条消息展示。
15
+ * - functionCall、functionResponse、代码执行等特殊 part 保持独立,避免影响工具渲染。
16
+ * - thought 发生切换时会结算当前缓冲,保证思考内容和普通回答不误合并。
17
+ */
18
+ export var normalizeAdkParts = function normalizeAdkParts() {
19
+ var parts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
20
+ var normalized = [];
21
+ var currentFiles = [];
22
+ var currentText = "";
23
+ var currentThought;
24
+ parts.forEach(function (part) {
25
+ var thoughtChanged = part.thought !== currentThought && hasContent(currentText, currentFiles);
26
+ if (isSpecialPart(part) || thoughtChanged) {
27
+ if (hasContent(currentText, currentFiles)) {
28
+ normalized.push({
29
+ text: currentText || undefined,
30
+ fileDataList: currentFiles.length ? currentFiles : undefined,
31
+ thought: currentThought
32
+ });
33
+ currentText = "";
34
+ currentFiles = [];
35
+ }
36
+ if (typeof part.thought !== "undefined") {
37
+ currentThought = part.thought;
38
+ }
39
+ }
40
+ if (isSpecialPart(part)) {
41
+ normalized.push(_objectSpread({}, part));
42
+ return;
43
+ }
44
+ if (part.fileData) currentFiles.push(part.fileData);
45
+ if (part.text) currentText += part.text;
46
+ if (typeof part.thought !== "undefined") currentThought = part.thought;
47
+ });
48
+ if (hasContent(currentText, currentFiles)) {
49
+ normalized.push({
50
+ text: currentText || undefined,
51
+ fileDataList: currentFiles.length ? currentFiles : undefined,
52
+ thought: currentThought
53
+ });
54
+ } else if (!normalized.length && parts.length > 0) {
55
+ return parts.map(function (part) {
56
+ return _objectSpread({}, part);
57
+ });
58
+ }
59
+ return normalized;
60
+ };
61
+
62
+ /**
63
+ * 兼容早期只关注文本合并的调用方,语义上等同于 normalizeAdkParts。
64
+ */
65
+ export var combineAdkParts = normalizeAdkParts;
66
+
67
+ /**
68
+ * 将 SDK Sender 的输入内容转换为 ADK 请求体里的 user parts。
69
+ *
70
+ * 这里保持“附件 part 在前、文本 part 在后”的顺序,和业务项目 useDebug
71
+ * 当前对后端协议的使用方式一致;functionResponse 场景只提交工具响应。
72
+ */
73
+ export var buildAdkUserParts = function buildAdkUserParts(_ref) {
74
+ var _ref$text = _ref.text,
75
+ text = _ref$text === void 0 ? "" : _ref$text,
76
+ _ref$files = _ref.files,
77
+ files = _ref$files === void 0 ? [] : _ref$files,
78
+ functionResponse = _ref.functionResponse;
79
+ if (functionResponse) return [{
80
+ functionResponse: functionResponse
81
+ }];
82
+ var parts = [];
83
+ files.forEach(function (file) {
84
+ var _file$response, _file$response2, _file$response3, _file$response4;
85
+ var fileUri = file.tempUrl || file.fileUrl || ((_file$response = file.response) === null || _file$response === void 0 ? void 0 : _file$response.fileUrl) || ((_file$response2 = file.response) === null || _file$response2 === void 0 ? void 0 : _file$response2.tempUrl);
86
+ if (!fileUri) return;
87
+ parts.push({
88
+ fileData: {
89
+ fileUri: fileUri,
90
+ displayName: file.fileName || file.name || ((_file$response3 = file.response) === null || _file$response3 === void 0 ? void 0 : _file$response3.fileName) || "",
91
+ mimeType: file.mimeType || ((_file$response4 = file.response) === null || _file$response4 === void 0 ? void 0 : _file$response4.mimeType) || ""
92
+ }
93
+ });
94
+ });
95
+ if (text.trim()) parts.push({
96
+ text: text
97
+ });
98
+ return parts;
99
+ };
100
+ //# sourceMappingURL=parts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["hasContent","text","files","Boolean","length","isSpecialPart","part","functionCall","functionResponse","executableCode","codeExecutionResult","actions","normalizeAdkParts","parts","arguments","undefined","normalized","currentFiles","currentText","currentThought","forEach","thoughtChanged","thought","push","fileDataList","_objectSpread","fileData","map","combineAdkParts","buildAdkUserParts","_ref","_ref$text","_ref$files","file","_file$response","_file$response2","_file$response3","_file$response4","fileUri","tempUrl","fileUrl","response","displayName","fileName","name","mimeType","trim"],"sources":["../../../../src/core/protocol/parts.ts"],"sourcesContent":["import type { FileData, Part } from \"@/types\";\nimport type { BuildAdkUserPartsInput } from \"./types\";\nimport type { NormalizedAdkPart } from \"./types\";\n\nconst hasContent = (text?: string, files?: FileData[]) =>\n Boolean(text) || Boolean(files?.length);\n\nconst isSpecialPart = (part: Part) =>\n Boolean(\n part.functionCall ||\n part.functionResponse ||\n part.executableCode ||\n part.codeExecutionResult ||\n (part as any).actions,\n );\n\n/**\n * 将后端 ADK parts 归一化成更适合 UI 渲染的片段。\n *\n * 设计目标:\n * - 连续 text 会被合并,减少流式分片直接渲染带来的碎片化。\n * - fileData 会合并到 fileDataList,支持“文件 + 文本”作为一条消息展示。\n * - functionCall、functionResponse、代码执行等特殊 part 保持独立,避免影响工具渲染。\n * - thought 发生切换时会结算当前缓冲,保证思考内容和普通回答不误合并。\n */\nexport const normalizeAdkParts = (parts: Part[] = []): NormalizedAdkPart[] => {\n const normalized: NormalizedAdkPart[] = [];\n let currentFiles: FileData[] = [];\n let currentText = \"\";\n let currentThought: boolean | undefined;\n\n parts.forEach((part) => {\n const thoughtChanged =\n part.thought !== currentThought && hasContent(currentText, currentFiles);\n\n if (isSpecialPart(part) || thoughtChanged) {\n if (hasContent(currentText, currentFiles)) {\n normalized.push({\n text: currentText || undefined,\n fileDataList: currentFiles.length ? currentFiles : undefined,\n thought: currentThought,\n });\n currentText = \"\";\n currentFiles = [];\n }\n if (typeof part.thought !== \"undefined\") {\n currentThought = part.thought;\n }\n }\n\n if (isSpecialPart(part)) {\n normalized.push({ ...part });\n return;\n }\n\n if (part.fileData) currentFiles.push(part.fileData as FileData);\n if (part.text) currentText += part.text;\n if (typeof part.thought !== \"undefined\") currentThought = part.thought;\n });\n\n if (hasContent(currentText, currentFiles)) {\n normalized.push({\n text: currentText || undefined,\n fileDataList: currentFiles.length ? currentFiles : undefined,\n thought: currentThought,\n });\n } else if (!normalized.length && parts.length > 0) {\n return parts.map((part) => ({ ...part }));\n }\n\n return normalized;\n};\n\n/**\n * 兼容早期只关注文本合并的调用方,语义上等同于 normalizeAdkParts。\n */\nexport const combineAdkParts = normalizeAdkParts;\n\n/**\n * 将 SDK Sender 的输入内容转换为 ADK 请求体里的 user parts。\n *\n * 这里保持“附件 part 在前、文本 part 在后”的顺序,和业务项目 useDebug\n * 当前对后端协议的使用方式一致;functionResponse 场景只提交工具响应。\n */\nexport const buildAdkUserParts = ({\n text = \"\",\n files = [],\n functionResponse,\n}: BuildAdkUserPartsInput): Part[] => {\n if (functionResponse) return [{ functionResponse }];\n\n const parts: Part[] = [];\n files.forEach((file) => {\n const fileUri =\n file.tempUrl ||\n file.fileUrl ||\n file.response?.fileUrl ||\n file.response?.tempUrl;\n if (!fileUri) return;\n\n parts.push({\n fileData: {\n fileUri,\n displayName:\n file.fileName || file.name || file.response?.fileName || \"\",\n mimeType: file.mimeType || file.response?.mimeType || \"\",\n },\n });\n });\n\n if (text.trim()) parts.push({ text });\n return parts;\n};\n"],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import type { AgentRunRequest, Event, FileData, FunctionCall, FunctionResponse, IMessage, Part, SendContent } from "../../types";
2
+ export type AdkEvent = Event;
3
+ export type AdkPart = Part;
4
+ export type AdkFileData = FileData;
5
+ export type AdkFunctionCall = FunctionCall;
6
+ export type AdkFunctionResponse = FunctionResponse;
7
+ export type AdkMessage = IMessage;
8
+ export type AdkSendContent = SendContent;
9
+ export type AdkRunRequest = AgentRunRequest;
10
+ export interface NormalizedAdkPart extends Partial<Part> {
11
+ text?: string;
12
+ fileDataList?: FileData[];
13
+ thought?: boolean;
14
+ }
15
+ export interface MessageEventMeta {
16
+ eventId?: string;
17
+ invocationId?: string;
18
+ sessionId?: string;
19
+ timestamp?: number;
20
+ author?: string;
21
+ modelCode?: string;
22
+ usageMetadata?: AdkEvent["usageMetadata"];
23
+ finishReason?: string;
24
+ isLike?: number;
25
+ }
26
+ export interface AdkProtocolOptions {
27
+ /**
28
+ * Hide user events inserted by backend async tasks.
29
+ * @default true
30
+ */
31
+ hideAsyncTaskEvents?: boolean;
32
+ /**
33
+ * Treat user-only functionResponse events as tool-call status updates instead
34
+ * of standalone messages.
35
+ * @default true
36
+ */
37
+ pairFunctionResponses?: boolean;
38
+ }
39
+ export interface BuildAdkUserPartsInput {
40
+ text?: string;
41
+ files?: Array<{
42
+ fileName?: string;
43
+ name?: string;
44
+ tempUrl?: string;
45
+ fileUrl?: string;
46
+ mimeType?: string;
47
+ type?: string;
48
+ response?: {
49
+ fileName?: string;
50
+ fileUrl?: string;
51
+ tempUrl?: string;
52
+ mimeType?: string;
53
+ fileType?: string;
54
+ };
55
+ }>;
56
+ functionResponse?: FunctionResponse | null;
57
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["../../../../src/core/protocol/types.ts"],"sourcesContent":["import type {\n AgentRunRequest,\n Event,\n FileData,\n FunctionCall,\n FunctionResponse,\n IMessage,\n Part,\n SendContent,\n} from \"@/types\";\n\nexport type AdkEvent = Event;\nexport type AdkPart = Part;\nexport type AdkFileData = FileData;\nexport type AdkFunctionCall = FunctionCall;\nexport type AdkFunctionResponse = FunctionResponse;\nexport type AdkMessage = IMessage;\nexport type AdkSendContent = SendContent;\nexport type AdkRunRequest = AgentRunRequest;\n\nexport interface NormalizedAdkPart extends Partial<Part> {\n text?: string;\n fileDataList?: FileData[];\n thought?: boolean;\n}\n\nexport interface MessageEventMeta {\n eventId?: string;\n invocationId?: string;\n sessionId?: string;\n timestamp?: number;\n author?: string;\n modelCode?: string;\n usageMetadata?: AdkEvent[\"usageMetadata\"];\n finishReason?: string;\n isLike?: number;\n}\n\nexport interface AdkProtocolOptions {\n /**\n * Hide user events inserted by backend async tasks.\n * @default true\n */\n hideAsyncTaskEvents?: boolean;\n /**\n * Treat user-only functionResponse events as tool-call status updates instead\n * of standalone messages.\n * @default true\n */\n pairFunctionResponses?: boolean;\n}\n\nexport interface BuildAdkUserPartsInput {\n text?: string;\n files?: Array<{\n fileName?: string;\n name?: string;\n tempUrl?: string;\n fileUrl?: string;\n mimeType?: string;\n type?: string;\n response?: {\n fileName?: string;\n fileUrl?: string;\n tempUrl?: string;\n mimeType?: string;\n fileType?: string;\n };\n }>;\n functionResponse?: FunctionResponse | null;\n}\n"],"mappings":""}
@@ -0,0 +1,8 @@
1
+ import type { AdkConversationController, AdkConversationOptions } from "./types";
2
+ /**
3
+ * 创建无 React 依赖的 ADK 对话数据流控制器。
4
+ *
5
+ * controller 只管理状态和数据流编排;所有请求细节都交给 transport,
6
+ * 所有 UI 提示都通过 callbacks 抛给调用方。
7
+ */
8
+ export declare const createAdkConversationController: (options: AdkConversationOptions) => AdkConversationController;