@convex-dev/agent 0.6.0 → 0.6.1

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 (184) hide show
  1. package/dist/UIMessages.d.ts +46 -0
  2. package/dist/UIMessages.d.ts.map +1 -0
  3. package/dist/UIMessages.js +634 -0
  4. package/dist/UIMessages.js.map +1 -0
  5. package/dist/client/createTool.d.ts +167 -0
  6. package/dist/client/createTool.d.ts.map +1 -0
  7. package/dist/client/createTool.js +116 -0
  8. package/dist/client/createTool.js.map +1 -0
  9. package/dist/client/defaultComponent.d.ts +11 -0
  10. package/dist/client/defaultComponent.d.ts.map +1 -0
  11. package/dist/client/defaultComponent.js +7 -0
  12. package/dist/client/defaultComponent.js.map +1 -0
  13. package/dist/client/definePlaygroundAPI.d.ts +1725 -0
  14. package/dist/client/definePlaygroundAPI.d.ts.map +1 -0
  15. package/dist/client/definePlaygroundAPI.js +271 -0
  16. package/dist/client/definePlaygroundAPI.js.map +1 -0
  17. package/dist/client/files.d.ts +69 -0
  18. package/dist/client/files.d.ts.map +1 -0
  19. package/dist/client/files.js +181 -0
  20. package/dist/client/files.js.map +1 -0
  21. package/dist/client/index.d.ts +2091 -0
  22. package/dist/client/index.d.ts.map +1 -0
  23. package/dist/client/index.js +929 -0
  24. package/dist/client/index.js.map +1 -0
  25. package/dist/client/messages.d.ts +461 -0
  26. package/dist/client/messages.d.ts.map +1 -0
  27. package/dist/client/messages.js +106 -0
  28. package/dist/client/messages.js.map +1 -0
  29. package/dist/client/mockModel.d.ts +42 -0
  30. package/dist/client/mockModel.d.ts.map +1 -0
  31. package/dist/client/mockModel.js +182 -0
  32. package/dist/client/mockModel.js.map +1 -0
  33. package/dist/client/saveInputMessages.d.ts +20 -0
  34. package/dist/client/saveInputMessages.d.ts.map +1 -0
  35. package/dist/client/saveInputMessages.js +58 -0
  36. package/dist/client/saveInputMessages.js.map +1 -0
  37. package/dist/client/search.d.ts +493 -0
  38. package/dist/client/search.d.ts.map +1 -0
  39. package/dist/client/search.js +435 -0
  40. package/dist/client/search.js.map +1 -0
  41. package/dist/client/start.d.ts +84 -0
  42. package/dist/client/start.d.ts.map +1 -0
  43. package/dist/client/start.js +185 -0
  44. package/dist/client/start.js.map +1 -0
  45. package/dist/client/streamText.d.ts +46 -0
  46. package/dist/client/streamText.d.ts.map +1 -0
  47. package/dist/client/streamText.js +127 -0
  48. package/dist/client/streamText.js.map +1 -0
  49. package/dist/client/streaming.d.ts +3778 -0
  50. package/dist/client/streaming.d.ts.map +1 -0
  51. package/dist/client/streaming.js +330 -0
  52. package/dist/client/streaming.js.map +1 -0
  53. package/dist/client/threads.d.ts +46 -0
  54. package/dist/client/threads.d.ts.map +1 -0
  55. package/dist/client/threads.js +49 -0
  56. package/dist/client/threads.js.map +1 -0
  57. package/dist/client/types.d.ts +461 -0
  58. package/dist/client/types.d.ts.map +1 -0
  59. package/dist/client/types.js +2 -0
  60. package/dist/client/types.js.map +1 -0
  61. package/dist/client/utils.d.ts +4 -0
  62. package/dist/client/utils.d.ts.map +1 -0
  63. package/dist/client/utils.js +21 -0
  64. package/dist/client/utils.js.map +1 -0
  65. package/dist/component/_generated/api.d.ts +48 -0
  66. package/dist/component/_generated/api.d.ts.map +1 -0
  67. package/dist/component/_generated/api.js +31 -0
  68. package/dist/component/_generated/api.js.map +1 -0
  69. package/dist/component/_generated/component.d.ts +3120 -0
  70. package/dist/component/_generated/component.d.ts.map +1 -0
  71. package/dist/component/_generated/component.js +11 -0
  72. package/dist/component/_generated/component.js.map +1 -0
  73. package/dist/component/_generated/dataModel.d.ts +46 -0
  74. package/dist/component/_generated/dataModel.d.ts.map +1 -0
  75. package/dist/component/_generated/dataModel.js +11 -0
  76. package/dist/component/_generated/dataModel.js.map +1 -0
  77. package/dist/component/_generated/server.d.ts +121 -0
  78. package/dist/component/_generated/server.d.ts.map +1 -0
  79. package/dist/component/_generated/server.js +78 -0
  80. package/dist/component/_generated/server.js.map +1 -0
  81. package/dist/component/apiKeys.d.ts +11 -0
  82. package/dist/component/apiKeys.d.ts.map +1 -0
  83. package/dist/component/apiKeys.js +69 -0
  84. package/dist/component/apiKeys.js.map +1 -0
  85. package/dist/component/convex.config.d.ts +3 -0
  86. package/dist/component/convex.config.d.ts.map +1 -0
  87. package/dist/component/convex.config.js +3 -0
  88. package/dist/component/convex.config.js.map +1 -0
  89. package/dist/component/files.d.ts +97 -0
  90. package/dist/component/files.d.ts.map +1 -0
  91. package/dist/component/files.js +190 -0
  92. package/dist/component/files.js.map +1 -0
  93. package/dist/component/messages.d.ts +3851 -0
  94. package/dist/component/messages.d.ts.map +1 -0
  95. package/dist/component/messages.js +757 -0
  96. package/dist/component/messages.js.map +1 -0
  97. package/dist/component/schema.d.ts +8029 -0
  98. package/dist/component/schema.d.ts.map +1 -0
  99. package/dist/component/schema.js +147 -0
  100. package/dist/component/schema.js.map +1 -0
  101. package/dist/component/streams.d.ts +128 -0
  102. package/dist/component/streams.d.ts.map +1 -0
  103. package/dist/component/streams.js +413 -0
  104. package/dist/component/streams.js.map +1 -0
  105. package/dist/component/threads.d.ts +115 -0
  106. package/dist/component/threads.d.ts.map +1 -0
  107. package/dist/component/threads.js +208 -0
  108. package/dist/component/threads.js.map +1 -0
  109. package/dist/component/users.d.ts +52 -0
  110. package/dist/component/users.d.ts.map +1 -0
  111. package/dist/component/users.js +229 -0
  112. package/dist/component/users.js.map +1 -0
  113. package/dist/component/vector/index.d.ts +61 -0
  114. package/dist/component/vector/index.d.ts.map +1 -0
  115. package/dist/component/vector/index.js +146 -0
  116. package/dist/component/vector/index.js.map +1 -0
  117. package/dist/component/vector/tables.d.ts +58 -0
  118. package/dist/component/vector/tables.d.ts.map +1 -0
  119. package/dist/component/vector/tables.js +56 -0
  120. package/dist/component/vector/tables.js.map +1 -0
  121. package/dist/deltas.d.ts +43 -0
  122. package/dist/deltas.d.ts.map +1 -0
  123. package/dist/deltas.js +446 -0
  124. package/dist/deltas.js.map +1 -0
  125. package/dist/mapping.d.ts +76 -0
  126. package/dist/mapping.d.ts.map +1 -0
  127. package/dist/mapping.js +720 -0
  128. package/dist/mapping.js.map +1 -0
  129. package/dist/react/SmoothText.d.ts +5 -0
  130. package/dist/react/SmoothText.d.ts.map +1 -0
  131. package/dist/react/SmoothText.js +6 -0
  132. package/dist/react/SmoothText.js.map +1 -0
  133. package/dist/react/index.d.ts +25 -0
  134. package/dist/react/index.d.ts.map +1 -0
  135. package/dist/react/index.js +70 -0
  136. package/dist/react/index.js.map +1 -0
  137. package/dist/react/optimisticallySendMessage.d.ts +42 -0
  138. package/dist/react/optimisticallySendMessage.d.ts.map +1 -0
  139. package/dist/react/optimisticallySendMessage.js +74 -0
  140. package/dist/react/optimisticallySendMessage.js.map +1 -0
  141. package/dist/react/types.d.ts +12 -0
  142. package/dist/react/types.d.ts.map +1 -0
  143. package/dist/react/types.js +2 -0
  144. package/dist/react/types.js.map +1 -0
  145. package/dist/react/useDeltaStreams.d.ts +10 -0
  146. package/dist/react/useDeltaStreams.d.ts.map +1 -0
  147. package/dist/react/useDeltaStreams.js +106 -0
  148. package/dist/react/useDeltaStreams.js.map +1 -0
  149. package/dist/react/useSmoothText.d.ts +27 -0
  150. package/dist/react/useSmoothText.d.ts.map +1 -0
  151. package/dist/react/useSmoothText.js +68 -0
  152. package/dist/react/useSmoothText.js.map +1 -0
  153. package/dist/react/useStreamingUIMessages.d.ts +22 -0
  154. package/dist/react/useStreamingUIMessages.d.ts.map +1 -0
  155. package/dist/react/useStreamingUIMessages.js +92 -0
  156. package/dist/react/useStreamingUIMessages.js.map +1 -0
  157. package/dist/react/useThreadMessages.d.ts +104 -0
  158. package/dist/react/useThreadMessages.d.ts.map +1 -0
  159. package/dist/react/useThreadMessages.js +148 -0
  160. package/dist/react/useThreadMessages.js.map +1 -0
  161. package/dist/react/useUIMessages.d.ts +96 -0
  162. package/dist/react/useUIMessages.d.ts.map +1 -0
  163. package/dist/react/useUIMessages.js +108 -0
  164. package/dist/react/useUIMessages.js.map +1 -0
  165. package/dist/shared.d.ts +26 -0
  166. package/dist/shared.d.ts.map +1 -0
  167. package/dist/shared.js +67 -0
  168. package/dist/shared.js.map +1 -0
  169. package/dist/validators.d.ts +24516 -0
  170. package/dist/validators.d.ts.map +1 -0
  171. package/dist/validators.js +475 -0
  172. package/dist/validators.js.map +1 -0
  173. package/package.json +39 -39
  174. package/src/UIMessages.ts +0 -9
  175. package/src/client/approval.test.ts +144 -0
  176. package/src/client/index.ts +17 -9
  177. package/src/client/search.ts +0 -29
  178. package/src/client/start.ts +2 -2
  179. package/src/client/streamText.ts +9 -0
  180. package/src/client/streaming.ts +30 -23
  181. package/src/component/_generated/dataModel.ts +1 -1
  182. package/src/component/_generated/server.ts +0 -5
  183. package/src/mapping.ts +38 -22
  184. package/src/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
@@ -0,0 +1,46 @@
1
+ import { type UIMessage as AIUIMessage, type UIDataTypes, type UITools } from "ai";
2
+ import type { MessageDoc, MessageStatus, ProviderOptions } from "./validators.js";
3
+ export type UIStatus = "streaming" | MessageStatus;
4
+ export type UIMessage<METADATA = unknown, DATA_PARTS extends UIDataTypes = UIDataTypes, TOOLS extends UITools = UITools> = AIUIMessage<METADATA, DATA_PARTS, TOOLS> & {
5
+ key: string;
6
+ order: number;
7
+ stepOrder: number;
8
+ status: UIStatus;
9
+ agentName?: string;
10
+ userId?: string;
11
+ text: string;
12
+ _creationTime: number;
13
+ };
14
+ /**
15
+ * Converts a list of UIMessages to MessageDocs, along with extra metadata that
16
+ * may be available to associate with the MessageDocs.
17
+ * @param messages - The UIMessages to convert to MessageDocs.
18
+ * @param meta - The metadata to add to the MessageDocs.
19
+ * @returns
20
+ */
21
+ export declare function fromUIMessages<METADATA = unknown>(messages: UIMessage<METADATA>[], meta: {
22
+ threadId: string;
23
+ userId?: string;
24
+ model?: string;
25
+ provider?: string;
26
+ providerOptions?: ProviderOptions;
27
+ metadata?: METADATA;
28
+ }): Promise<(MessageDoc & {
29
+ streaming: boolean;
30
+ metadata?: METADATA;
31
+ })[]>;
32
+ type ExtraFields<METADATA = unknown> = {
33
+ streaming?: boolean;
34
+ metadata?: METADATA;
35
+ };
36
+ /**
37
+ * Converts a list of MessageDocs to UIMessages.
38
+ * This is somewhat lossy, as many fields are not supported by UIMessages, e.g.
39
+ * the model, provider, userId, etc.
40
+ * The UIMessage type is the augmented type that includes more fields such as
41
+ * key, order, stepOrder, status, agentName, text, etc.
42
+ */
43
+ export declare function toUIMessages<METADATA = unknown, DATA_PARTS extends UIDataTypes = UIDataTypes, TOOLS extends UITools = UITools>(messages: (MessageDoc & ExtraFields<METADATA>)[]): UIMessage<METADATA, DATA_PARTS, TOOLS>[];
44
+ export declare function combineUIMessages(messages: UIMessage[]): UIMessage[];
45
+ export {};
46
+ //# sourceMappingURL=UIMessages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UIMessages.d.ts","sourceRoot":"","sources":["../src/UIMessages.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,IAAI,WAAW,EAU7B,KAAK,WAAW,EAChB,KAAK,OAAO,EACb,MAAM,IAAI,CAAC;AAUZ,OAAO,KAAK,EACV,UAAU,EACV,aAAa,EACb,eAAe,EAGhB,MAAM,iBAAiB,CAAC;AAGzB,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,aAAa,CAAC;AAEnD,MAAM,MAAM,SAAS,CACnB,QAAQ,GAAG,OAAO,EAClB,UAAU,SAAS,WAAW,GAAG,WAAW,EAC5C,KAAK,SAAS,OAAO,GAAG,OAAO,IAC7B,WAAW,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,GAAG;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,QAAQ,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,QAAQ,GAAG,OAAO,EACrD,QAAQ,EAAE,SAAS,CAAC,QAAQ,CAAC,EAAE,EAC/B,IAAI,EAAE;IACJ,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,GACA,OAAO,CAAC,CAAC,UAAU,GAAG;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,QAAQ,CAAA;CAAE,CAAC,EAAE,CAAC,CAiEvE;AA8BD,KAAK,WAAW,CAAC,QAAQ,GAAG,OAAO,IAAI;IACrC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,GAAG,OAAO,EAClB,UAAU,SAAS,WAAW,GAAG,WAAW,EAC5C,KAAK,SAAS,OAAO,GAAG,OAAO,EAE/B,QAAQ,EAAE,CAAC,UAAU,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,EAAE,GAC/C,SAAS,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,EAAE,CAiB1C;AA6lBD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CA2CpE"}
@@ -0,0 +1,634 @@
1
+ import { convertToModelMessages, } from "ai";
2
+ import { toModelMessage, fromModelMessage, toUIFilePart } from "./mapping.js";
3
+ import { extractReasoning, extractText, isTool, joinText, sorted, } from "./shared.js";
4
+ import { omit, pick } from "convex-helpers";
5
+ /**
6
+ * Converts a list of UIMessages to MessageDocs, along with extra metadata that
7
+ * may be available to associate with the MessageDocs.
8
+ * @param messages - The UIMessages to convert to MessageDocs.
9
+ * @param meta - The metadata to add to the MessageDocs.
10
+ * @returns
11
+ */
12
+ export async function fromUIMessages(messages, meta) {
13
+ const nested = await Promise.all(messages.map(async (uiMessage) => {
14
+ const stepOrder = uiMessage.stepOrder;
15
+ const commonFields = {
16
+ ...pick(meta, [
17
+ "threadId",
18
+ "userId",
19
+ "model",
20
+ "provider",
21
+ "providerOptions",
22
+ "metadata",
23
+ ]),
24
+ ...omit(uiMessage, ["parts", "role", "key", "text", "userId"]),
25
+ userId: uiMessage.userId ?? meta.userId,
26
+ status: uiMessage.status === "streaming" ? "pending" : "success",
27
+ streaming: uiMessage.status === "streaming",
28
+ // to override
29
+ _id: uiMessage.id,
30
+ tool: false,
31
+ };
32
+ const modelMessages = await convertToModelMessages([uiMessage]);
33
+ return modelMessages
34
+ .map((modelMessage, i) => {
35
+ if (modelMessage.content.length === 0) {
36
+ return undefined;
37
+ }
38
+ const message = fromModelMessage(modelMessage);
39
+ const tool = isTool(message);
40
+ const doc = {
41
+ ...commonFields,
42
+ _id: uiMessage.id + `-${i}`,
43
+ stepOrder: stepOrder + i,
44
+ message,
45
+ tool,
46
+ text: extractText(message),
47
+ reasoning: extractReasoning(message),
48
+ finishReason: tool ? "tool-calls" : "stop",
49
+ sources: fromSourceParts(uiMessage.parts),
50
+ };
51
+ if (Array.isArray(modelMessage.content)) {
52
+ // Find a content part with providerOptions (type assertion needed for SDK compatibility)
53
+ const partWithProviderOptions = modelMessage.content.find((c) => "providerOptions" in c && c.providerOptions !== undefined);
54
+ if (partWithProviderOptions?.providerOptions) {
55
+ // convertToModelMessages changes providerMetadata to providerOptions
56
+ const providerOptions = partWithProviderOptions.providerOptions;
57
+ if (providerOptions) {
58
+ doc.providerMetadata = providerOptions;
59
+ doc.providerOptions ??= providerOptions;
60
+ }
61
+ }
62
+ }
63
+ return doc;
64
+ })
65
+ .filter((d) => d !== undefined);
66
+ }));
67
+ return nested.flat();
68
+ }
69
+ function fromSourceParts(parts) {
70
+ return parts
71
+ .map((part) => {
72
+ if (part.type === "source-url") {
73
+ return {
74
+ type: "source",
75
+ sourceType: "url",
76
+ url: part.url,
77
+ id: part.sourceId,
78
+ providerMetadata: part.providerMetadata,
79
+ title: part.title,
80
+ };
81
+ }
82
+ if (part.type === "source-document") {
83
+ return {
84
+ type: "source",
85
+ sourceType: "document",
86
+ mediaType: part.mediaType,
87
+ id: part.sourceId,
88
+ providerMetadata: part.providerMetadata,
89
+ title: part.title,
90
+ };
91
+ }
92
+ return undefined;
93
+ })
94
+ .filter((p) => p !== undefined);
95
+ }
96
+ /**
97
+ * Converts a list of MessageDocs to UIMessages.
98
+ * This is somewhat lossy, as many fields are not supported by UIMessages, e.g.
99
+ * the model, provider, userId, etc.
100
+ * The UIMessage type is the augmented type that includes more fields such as
101
+ * key, order, stepOrder, status, agentName, text, etc.
102
+ */
103
+ export function toUIMessages(messages) {
104
+ // Group assistant and tool messages together
105
+ const assistantGroups = groupAssistantMessages(sorted(messages));
106
+ const uiMessages = [];
107
+ for (const group of assistantGroups) {
108
+ if (group.role === "system") {
109
+ uiMessages.push(createSystemUIMessage(group.message));
110
+ }
111
+ else if (group.role === "user") {
112
+ uiMessages.push(createUserUIMessage(group.message));
113
+ }
114
+ else {
115
+ // Assistant/tool group
116
+ uiMessages.push(createAssistantUIMessage(group.messages));
117
+ }
118
+ }
119
+ return uiMessages;
120
+ }
121
+ function groupAssistantMessages(messages) {
122
+ const groups = [];
123
+ let currentAssistantGroup = [];
124
+ let currentOrder;
125
+ for (const message of messages) {
126
+ const coreMessage = message.message && toModelMessage(message.message);
127
+ if (!coreMessage)
128
+ continue;
129
+ if (coreMessage.role === "user" || coreMessage.role === "system") {
130
+ // Finish any current assistant group
131
+ if (currentAssistantGroup.length > 0) {
132
+ groups.push({
133
+ role: "assistant",
134
+ messages: currentAssistantGroup,
135
+ });
136
+ currentAssistantGroup = [];
137
+ currentOrder = undefined;
138
+ }
139
+ // Add singleton group
140
+ groups.push({
141
+ role: coreMessage.role,
142
+ message,
143
+ });
144
+ }
145
+ else {
146
+ // Assistant or tool message
147
+ // Start new group if order changes or this is the first assistant/tool message
148
+ if (currentOrder !== undefined && message.order !== currentOrder) {
149
+ if (currentAssistantGroup.length > 0) {
150
+ groups.push({
151
+ role: "assistant",
152
+ messages: currentAssistantGroup,
153
+ });
154
+ currentAssistantGroup = [];
155
+ }
156
+ }
157
+ currentOrder = message.order;
158
+ currentAssistantGroup.push(message);
159
+ // End group if this is an assistant message without tool calls
160
+ if (coreMessage.role === "assistant" && !message.tool) {
161
+ groups.push({
162
+ role: "assistant",
163
+ messages: currentAssistantGroup,
164
+ });
165
+ currentAssistantGroup = [];
166
+ currentOrder = undefined;
167
+ }
168
+ }
169
+ }
170
+ // Add any remaining assistant group
171
+ if (currentAssistantGroup.length > 0) {
172
+ groups.push({
173
+ role: "assistant",
174
+ messages: currentAssistantGroup,
175
+ });
176
+ }
177
+ return groups;
178
+ }
179
+ function createSystemUIMessage(message) {
180
+ const text = extractTextFromMessageDoc(message);
181
+ const partCommon = {
182
+ state: message.streaming ? "streaming" : "done",
183
+ ...(message.providerMetadata
184
+ ? { providerMetadata: message.providerMetadata }
185
+ : {}),
186
+ };
187
+ return {
188
+ id: message._id,
189
+ _creationTime: message._creationTime,
190
+ order: message.order,
191
+ stepOrder: message.stepOrder,
192
+ status: message.streaming ? "streaming" : message.status,
193
+ key: `${message.threadId}-${message.order}-${message.stepOrder}`,
194
+ text,
195
+ role: "system",
196
+ agentName: message.agentName,
197
+ userId: message.userId,
198
+ parts: [{ type: "text", text, ...partCommon }],
199
+ metadata: message.metadata,
200
+ };
201
+ }
202
+ function extractTextFromMessageDoc(message) {
203
+ return ((message.message && extractText(message.message)) || message.text || "");
204
+ }
205
+ function createUserUIMessage(message) {
206
+ const text = extractTextFromMessageDoc(message);
207
+ const coreMessage = toModelMessage(message.message);
208
+ const content = coreMessage.content;
209
+ const nonStringContent = content && typeof content !== "string" ? content : [];
210
+ const partCommon = {
211
+ state: message.streaming ? "streaming" : "done",
212
+ ...(message.providerMetadata
213
+ ? { providerMetadata: message.providerMetadata }
214
+ : {}),
215
+ };
216
+ const parts = [];
217
+ if (text && !nonStringContent.length) {
218
+ parts.push({ type: "text", text });
219
+ }
220
+ for (const contentPart of nonStringContent) {
221
+ switch (contentPart.type) {
222
+ case "text":
223
+ parts.push({ type: "text", text: contentPart.text, ...partCommon });
224
+ break;
225
+ case "file":
226
+ case "image":
227
+ parts.push(toUIFilePart(contentPart));
228
+ break;
229
+ default:
230
+ console.warn("Unknown content part type for user", contentPart);
231
+ break;
232
+ }
233
+ }
234
+ return {
235
+ id: message._id,
236
+ _creationTime: message._creationTime,
237
+ order: message.order,
238
+ stepOrder: message.stepOrder,
239
+ status: message.streaming ? "streaming" : message.status,
240
+ key: `${message.threadId}-${message.order}-${message.stepOrder}`,
241
+ text,
242
+ role: "user",
243
+ userId: message.userId,
244
+ parts,
245
+ metadata: message.metadata,
246
+ };
247
+ }
248
+ function createAssistantUIMessage(groupUnordered) {
249
+ const group = sorted(groupUnordered);
250
+ const firstMessage = group[0];
251
+ // Use first message for special fields
252
+ const common = {
253
+ id: firstMessage._id,
254
+ _creationTime: firstMessage._creationTime,
255
+ order: firstMessage.order,
256
+ stepOrder: firstMessage.stepOrder,
257
+ key: `${firstMessage.threadId}-${firstMessage.order}-${firstMessage.stepOrder}`,
258
+ agentName: firstMessage.agentName,
259
+ userId: firstMessage.userId,
260
+ };
261
+ // Get status from last message
262
+ const lastMessage = group[group.length - 1];
263
+ const status = lastMessage.streaming
264
+ ? "streaming"
265
+ : lastMessage.status;
266
+ const approvalParts = [];
267
+ const executionDeniedResults = [];
268
+ for (const message of group) {
269
+ const rawContent = message.message?.content;
270
+ if (Array.isArray(rawContent)) {
271
+ for (const part of rawContent) {
272
+ if (part.type === "tool-approval-request" ||
273
+ part.type === "tool-approval-response") {
274
+ approvalParts.push(part);
275
+ }
276
+ // Check for execution-denied in tool-result outputs
277
+ if (part.type === "tool-result" &&
278
+ typeof part.output === "object" &&
279
+ part.output !== null &&
280
+ part.output.type === "execution-denied") {
281
+ executionDeniedResults.push({
282
+ toolCallId: part.toolCallId,
283
+ reason: part.output.reason,
284
+ });
285
+ }
286
+ }
287
+ }
288
+ }
289
+ // Collect all parts from all messages
290
+ const allParts = [];
291
+ for (const message of group) {
292
+ const coreMessage = message.message && toModelMessage(message.message);
293
+ if (!coreMessage)
294
+ continue;
295
+ const content = coreMessage.content;
296
+ const nonStringContent = content && typeof content !== "string" ? content : [];
297
+ const text = extractTextFromMessageDoc(message);
298
+ const partCommon = {
299
+ state: message.streaming ? "streaming" : "done",
300
+ ...(message.providerMetadata
301
+ ? { providerMetadata: message.providerMetadata }
302
+ : {}),
303
+ };
304
+ // Add reasoning parts
305
+ if (message.reasoning &&
306
+ !nonStringContent.some((c) => c.type === "reasoning")) {
307
+ allParts.push({
308
+ type: "reasoning",
309
+ text: message.reasoning,
310
+ ...partCommon,
311
+ });
312
+ }
313
+ // Add text parts if no structured content
314
+ if (text && !nonStringContent.length) {
315
+ allParts.push({
316
+ type: "text",
317
+ text: text,
318
+ ...partCommon,
319
+ });
320
+ }
321
+ // Add all structured content parts
322
+ for (const contentPart of nonStringContent) {
323
+ switch (contentPart.type) {
324
+ case "text":
325
+ allParts.push({
326
+ ...partCommon,
327
+ ...contentPart,
328
+ });
329
+ break;
330
+ case "reasoning":
331
+ allParts.push({
332
+ ...partCommon,
333
+ ...contentPart,
334
+ });
335
+ break;
336
+ case "file":
337
+ case "image":
338
+ allParts.push(toUIFilePart(contentPart));
339
+ break;
340
+ case "tool-call": {
341
+ allParts.push({
342
+ type: "step-start",
343
+ });
344
+ const toolPart = {
345
+ type: `tool-${contentPart.toolName}`,
346
+ toolCallId: contentPart.toolCallId,
347
+ input: contentPart.input,
348
+ providerExecuted: contentPart.providerExecuted,
349
+ ...(message.streaming
350
+ ? { state: "input-streaming" }
351
+ : {
352
+ state: "input-available",
353
+ callProviderMetadata: message.providerMetadata,
354
+ }),
355
+ };
356
+ allParts.push(toolPart);
357
+ break;
358
+ }
359
+ case "tool-result": {
360
+ // Note: execution-denied outputs are handled separately via pre-extraction
361
+ // from raw content (converted to text format for providers in start.ts).
362
+ // See executionDeniedResults processing at the end of this function.
363
+ const typedPart = contentPart;
364
+ // Check if this is an execution-denied result
365
+ if (typedPart.output?.type === "execution-denied") {
366
+ const call = allParts.find((part) => part.type === `tool-${contentPart.toolName}` &&
367
+ "toolCallId" in part &&
368
+ part.toolCallId === contentPart.toolCallId);
369
+ if (call) {
370
+ call.state = "output-denied";
371
+ if (!("approval" in call) || !call.approval) {
372
+ call.approval = {
373
+ id: "",
374
+ approved: false,
375
+ reason: typedPart.output.reason,
376
+ };
377
+ }
378
+ else {
379
+ const approval = call.approval;
380
+ approval.approved = false;
381
+ approval.reason = typedPart.output.reason;
382
+ }
383
+ }
384
+ break;
385
+ }
386
+ const output = typeof typedPart.output?.type === "string"
387
+ ? typedPart.output.value
388
+ : typedPart.output;
389
+ // Check for error at both the content part level (isError) and message level
390
+ // isError may exist on stored tool results but isn't in ToolResultPart type
391
+ const hasError = contentPart.isError || message.error;
392
+ const errorText = message.error || (hasError ? String(output) : undefined);
393
+ const call = allParts.find((part) => part.type === `tool-${contentPart.toolName}` &&
394
+ "toolCallId" in part &&
395
+ part.toolCallId === contentPart.toolCallId);
396
+ if (call) {
397
+ if (hasError) {
398
+ call.state = "output-error";
399
+ call.errorText = errorText ?? "Unknown error";
400
+ call.output = output;
401
+ }
402
+ else {
403
+ call.state = "output-available";
404
+ call.output = output;
405
+ }
406
+ }
407
+ else {
408
+ // Tool call is on a previous page - create standalone tool part
409
+ if (hasError) {
410
+ allParts.push({
411
+ type: `tool-${contentPart.toolName}`,
412
+ toolCallId: contentPart.toolCallId,
413
+ state: "output-error",
414
+ input: undefined,
415
+ errorText: errorText ?? "Unknown error",
416
+ callProviderMetadata: message.providerMetadata,
417
+ });
418
+ }
419
+ else {
420
+ allParts.push({
421
+ type: `tool-${contentPart.toolName}`,
422
+ toolCallId: contentPart.toolCallId,
423
+ state: "output-available",
424
+ input: undefined,
425
+ output,
426
+ callProviderMetadata: message.providerMetadata,
427
+ });
428
+ }
429
+ }
430
+ break;
431
+ }
432
+ case "tool-approval-request": {
433
+ // Find the matching tool call
434
+ const typedPart = contentPart;
435
+ const toolCallPart = allParts.find((part) => "toolCallId" in part && part.toolCallId === typedPart.toolCallId);
436
+ if (toolCallPart) {
437
+ toolCallPart.state = "approval-requested";
438
+ toolCallPart.approval = {
439
+ id: typedPart.approvalId,
440
+ };
441
+ }
442
+ else {
443
+ console.warn("Tool approval request without preceding tool call", contentPart);
444
+ }
445
+ break;
446
+ }
447
+ case "tool-approval-response": {
448
+ // Find the tool call that has this approval by matching approval.id
449
+ const typedPart = contentPart;
450
+ const toolCallPart = allParts.find((part) => "approval" in part &&
451
+ part.approval
452
+ ?.id === typedPart.approvalId);
453
+ if (toolCallPart) {
454
+ if (typedPart.approved) {
455
+ toolCallPart.state = "approval-responded";
456
+ toolCallPart.approval = {
457
+ id: typedPart.approvalId,
458
+ approved: true,
459
+ reason: typedPart.reason,
460
+ };
461
+ }
462
+ else {
463
+ toolCallPart.state = "output-denied";
464
+ toolCallPart.approval = {
465
+ id: typedPart.approvalId,
466
+ approved: false,
467
+ reason: typedPart.reason,
468
+ };
469
+ }
470
+ }
471
+ else {
472
+ console.warn("Tool approval response without matching approval request", contentPart);
473
+ }
474
+ break;
475
+ }
476
+ default: {
477
+ const maybeSource = contentPart;
478
+ if (maybeSource.type === "source") {
479
+ allParts.push(toSourcePart(maybeSource));
480
+ }
481
+ else {
482
+ console.warn("Unknown content part type for assistant", contentPart);
483
+ }
484
+ }
485
+ }
486
+ }
487
+ // Add source parts
488
+ for (const source of message.sources ?? []) {
489
+ allParts.push(toSourcePart(source));
490
+ }
491
+ }
492
+ // Final output states that should not be overwritten by approval processing
493
+ const finalStates = new Set([
494
+ "output-available",
495
+ "output-error",
496
+ "output-denied",
497
+ ]);
498
+ // Process approval parts to update tool call states
499
+ for (const approvalPart of approvalParts) {
500
+ if (approvalPart.type === "tool-approval-request") {
501
+ const toolCallPart = allParts.find((part) => "toolCallId" in part && part.toolCallId === approvalPart.toolCallId);
502
+ if (toolCallPart) {
503
+ // Always set approval info (needed for response matching), but only
504
+ // update state if not in a final state
505
+ toolCallPart.approval = {
506
+ id: approvalPart.approvalId,
507
+ };
508
+ if (!finalStates.has(toolCallPart.state)) {
509
+ toolCallPart.state = "approval-requested";
510
+ }
511
+ }
512
+ }
513
+ else if (approvalPart.type === "tool-approval-response") {
514
+ const toolCallPart = allParts.find((part) => "approval" in part &&
515
+ part.approval?.id ===
516
+ approvalPart.approvalId);
517
+ if (toolCallPart) {
518
+ // Always update approval info, but only update state if not in a final state
519
+ toolCallPart.approval = {
520
+ id: approvalPart.approvalId,
521
+ approved: approvalPart.approved,
522
+ reason: approvalPart.reason,
523
+ };
524
+ if (!finalStates.has(toolCallPart.state)) {
525
+ if (approvalPart.approved) {
526
+ toolCallPart.state = "approval-responded";
527
+ }
528
+ else {
529
+ toolCallPart.state = "output-denied";
530
+ }
531
+ }
532
+ }
533
+ }
534
+ }
535
+ // Process execution-denied results to update tool call states
536
+ for (const denied of executionDeniedResults) {
537
+ const toolCallPart = allParts.find((part) => "toolCallId" in part && part.toolCallId === denied.toolCallId);
538
+ if (toolCallPart) {
539
+ toolCallPart.state = "output-denied";
540
+ if (!("approval" in toolCallPart) || !toolCallPart.approval) {
541
+ toolCallPart.approval = {
542
+ id: "",
543
+ approved: false,
544
+ reason: denied.reason,
545
+ };
546
+ }
547
+ else {
548
+ const approval = toolCallPart.approval;
549
+ approval.approved = false;
550
+ approval.reason = denied.reason;
551
+ }
552
+ }
553
+ }
554
+ return {
555
+ ...common,
556
+ role: "assistant",
557
+ text: joinText(allParts),
558
+ status,
559
+ parts: allParts,
560
+ metadata: group.find((m) => m.metadata)?.metadata,
561
+ };
562
+ }
563
+ function toSourcePart(part) {
564
+ if (part.sourceType === "url") {
565
+ return {
566
+ type: "source-url",
567
+ url: part.url,
568
+ sourceId: part.id,
569
+ providerMetadata: part.providerMetadata,
570
+ title: part.title,
571
+ };
572
+ }
573
+ return {
574
+ type: "source-document",
575
+ mediaType: part.mediaType,
576
+ sourceId: part.id,
577
+ title: part.title,
578
+ filename: part.filename,
579
+ providerMetadata: part.providerMetadata,
580
+ };
581
+ }
582
+ export function combineUIMessages(messages) {
583
+ const combined = messages.reduce((acc, message) => {
584
+ if (!acc.length) {
585
+ return [message];
586
+ }
587
+ const previous = acc.at(-1);
588
+ if (message.order !== previous.order ||
589
+ previous.role !== message.role ||
590
+ message.role !== "assistant") {
591
+ acc.push(message);
592
+ return acc;
593
+ }
594
+ // We will replace it with a combined message
595
+ acc.pop();
596
+ const newParts = [...previous.parts];
597
+ for (const part of message.parts) {
598
+ const toolCallId = getToolCallId(part);
599
+ if (!toolCallId) {
600
+ newParts.push(part);
601
+ continue;
602
+ }
603
+ const previousPartIndex = newParts.findIndex((p) => getToolCallId(p) === toolCallId);
604
+ if (previousPartIndex === -1) {
605
+ // Tool call not found in previous parts, add it as new
606
+ newParts.push(part);
607
+ continue;
608
+ }
609
+ const previousPart = newParts.splice(previousPartIndex, 1)[0];
610
+ newParts.push(mergeParts(previousPart, part));
611
+ }
612
+ acc.push({
613
+ ...previous,
614
+ ...pick(message, ["status", "metadata", "agentName"]),
615
+ parts: newParts,
616
+ text: joinText(newParts),
617
+ });
618
+ return acc;
619
+ }, []);
620
+ return combined;
621
+ }
622
+ function getToolCallId(part) {
623
+ return part.toolCallId;
624
+ }
625
+ function mergeParts(previousPart, part) {
626
+ const merged = { ...previousPart };
627
+ for (const [key, value] of Object.entries(part)) {
628
+ if (value !== undefined) {
629
+ merged[key] = value;
630
+ }
631
+ }
632
+ return merged;
633
+ }
634
+ //# sourceMappingURL=UIMessages.js.map