@convex-dev/agent 0.5.0-alpha.1 → 0.6.0-alpha.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 (235) hide show
  1. package/MIGRATION.md +153 -0
  2. package/README.md +32 -27
  3. package/dist/UIMessages.d.ts +46 -0
  4. package/dist/UIMessages.d.ts.map +1 -0
  5. package/dist/UIMessages.js +546 -0
  6. package/dist/UIMessages.js.map +1 -0
  7. package/dist/client/createTool.d.ts +126 -27
  8. package/dist/client/createTool.d.ts.map +1 -1
  9. package/dist/client/createTool.js +67 -12
  10. package/dist/client/createTool.js.map +1 -1
  11. package/dist/client/defaultComponent.d.ts +11 -0
  12. package/dist/client/defaultComponent.d.ts.map +1 -0
  13. package/dist/client/defaultComponent.js +7 -0
  14. package/dist/client/defaultComponent.js.map +1 -0
  15. package/dist/client/definePlaygroundAPI.d.ts +1335 -204
  16. package/dist/client/definePlaygroundAPI.d.ts.map +1 -1
  17. package/dist/client/definePlaygroundAPI.js +52 -28
  18. package/dist/client/definePlaygroundAPI.js.map +1 -1
  19. package/dist/client/files.d.ts +20 -7
  20. package/dist/client/files.d.ts.map +1 -1
  21. package/dist/client/files.js +68 -11
  22. package/dist/client/files.js.map +1 -1
  23. package/dist/client/index.d.ts +1116 -978
  24. package/dist/client/index.d.ts.map +1 -1
  25. package/dist/client/index.js +332 -747
  26. package/dist/client/index.js.map +1 -1
  27. package/dist/client/messages.d.ts +461 -0
  28. package/dist/client/messages.d.ts.map +1 -0
  29. package/dist/client/messages.js +106 -0
  30. package/dist/client/messages.js.map +1 -0
  31. package/dist/client/mockModel.d.ts +42 -0
  32. package/dist/client/mockModel.d.ts.map +1 -0
  33. package/dist/client/mockModel.js +182 -0
  34. package/dist/client/mockModel.js.map +1 -0
  35. package/dist/client/saveInputMessages.d.ts +20 -0
  36. package/dist/client/saveInputMessages.d.ts.map +1 -0
  37. package/dist/client/saveInputMessages.js +58 -0
  38. package/dist/client/saveInputMessages.js.map +1 -0
  39. package/dist/client/search.d.ts +350 -39
  40. package/dist/client/search.d.ts.map +1 -1
  41. package/dist/client/search.js +350 -39
  42. package/dist/client/search.js.map +1 -1
  43. package/dist/client/start.d.ts +84 -0
  44. package/dist/client/start.d.ts.map +1 -0
  45. package/dist/client/start.js +185 -0
  46. package/dist/client/start.js.map +1 -0
  47. package/dist/client/streamText.d.ts +46 -0
  48. package/dist/client/streamText.d.ts.map +1 -0
  49. package/dist/client/streamText.js +117 -0
  50. package/dist/client/streamText.js.map +1 -0
  51. package/dist/client/streaming.d.ts +3716 -32
  52. package/dist/client/streaming.d.ts.map +1 -1
  53. package/dist/client/streaming.js +161 -59
  54. package/dist/client/streaming.js.map +1 -1
  55. package/dist/client/threads.d.ts +46 -0
  56. package/dist/client/threads.d.ts.map +1 -0
  57. package/dist/client/threads.js +49 -0
  58. package/dist/client/threads.js.map +1 -0
  59. package/dist/client/types.d.ts +266 -128
  60. package/dist/client/types.d.ts.map +1 -1
  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 +24 -2178
  66. package/dist/component/_generated/api.d.ts.map +1 -1
  67. package/dist/component/_generated/api.js +10 -1
  68. package/dist/component/_generated/api.js.map +1 -1
  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 +4 -18
  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 +10 -38
  78. package/dist/component/_generated/server.d.ts.map +1 -1
  79. package/dist/component/_generated/server.js +9 -5
  80. package/dist/component/_generated/server.js.map +1 -1
  81. package/dist/component/files.d.ts +16 -10
  82. package/dist/component/files.d.ts.map +1 -1
  83. package/dist/component/files.js +10 -2
  84. package/dist/component/files.js.map +1 -1
  85. package/dist/component/messages.d.ts +2578 -366
  86. package/dist/component/messages.d.ts.map +1 -1
  87. package/dist/component/messages.js +397 -154
  88. package/dist/component/messages.js.map +1 -1
  89. package/dist/component/schema.d.ts +5697 -3584
  90. package/dist/component/schema.d.ts.map +1 -1
  91. package/dist/component/schema.js +18 -41
  92. package/dist/component/schema.js.map +1 -1
  93. package/dist/component/streams.d.ts +39 -339
  94. package/dist/component/streams.d.ts.map +1 -1
  95. package/dist/component/streams.js +114 -73
  96. package/dist/component/streams.js.map +1 -1
  97. package/dist/component/threads.d.ts +13 -13
  98. package/dist/component/users.d.ts +7 -7
  99. package/dist/component/vector/index.d.ts +1 -1
  100. package/dist/component/vector/index.d.ts.map +1 -1
  101. package/dist/component/vector/index.js +1 -3
  102. package/dist/component/vector/index.js.map +1 -1
  103. package/dist/deltas.d.ts +43 -0
  104. package/dist/deltas.d.ts.map +1 -0
  105. package/dist/deltas.js +446 -0
  106. package/dist/deltas.js.map +1 -0
  107. package/dist/mapping.d.ts +38 -20
  108. package/dist/mapping.d.ts.map +1 -1
  109. package/dist/mapping.js +365 -97
  110. package/dist/mapping.js.map +1 -1
  111. package/dist/react/SmoothText.d.ts +5 -0
  112. package/dist/react/SmoothText.d.ts.map +1 -0
  113. package/dist/react/SmoothText.js +6 -0
  114. package/dist/react/SmoothText.js.map +1 -0
  115. package/dist/react/index.d.ts +5 -77
  116. package/dist/react/index.d.ts.map +1 -1
  117. package/dist/react/index.js +6 -160
  118. package/dist/react/index.js.map +1 -1
  119. package/dist/react/optimisticallySendMessage.d.ts +36 -3
  120. package/dist/react/optimisticallySendMessage.d.ts.map +1 -1
  121. package/dist/react/optimisticallySendMessage.js +35 -9
  122. package/dist/react/optimisticallySendMessage.js.map +1 -1
  123. package/dist/react/types.d.ts +4 -18
  124. package/dist/react/types.d.ts.map +1 -1
  125. package/dist/react/useDeltaStreams.d.ts +10 -0
  126. package/dist/react/useDeltaStreams.d.ts.map +1 -0
  127. package/dist/react/useDeltaStreams.js +106 -0
  128. package/dist/react/useDeltaStreams.js.map +1 -0
  129. package/dist/react/useSmoothText.d.ts +13 -12
  130. package/dist/react/useSmoothText.d.ts.map +1 -1
  131. package/dist/react/useSmoothText.js +32 -15
  132. package/dist/react/useSmoothText.js.map +1 -1
  133. package/dist/react/useStreamingUIMessages.d.ts +22 -0
  134. package/dist/react/useStreamingUIMessages.d.ts.map +1 -0
  135. package/dist/react/useStreamingUIMessages.js +92 -0
  136. package/dist/react/useStreamingUIMessages.js.map +1 -0
  137. package/dist/react/useThreadMessages.d.ts +104 -0
  138. package/dist/react/useThreadMessages.d.ts.map +1 -0
  139. package/dist/react/useThreadMessages.js +148 -0
  140. package/dist/react/useThreadMessages.js.map +1 -0
  141. package/dist/react/useUIMessages.d.ts +96 -0
  142. package/dist/react/useUIMessages.d.ts.map +1 -0
  143. package/dist/react/useUIMessages.js +108 -0
  144. package/dist/react/useUIMessages.js.map +1 -0
  145. package/dist/shared.d.ts +20 -4
  146. package/dist/shared.d.ts.map +1 -1
  147. package/dist/shared.js +45 -8
  148. package/dist/shared.js.map +1 -1
  149. package/dist/validators.d.ts +22981 -5666
  150. package/dist/validators.d.ts.map +1 -1
  151. package/dist/validators.js +245 -137
  152. package/dist/validators.js.map +1 -1
  153. package/package.json +101 -51
  154. package/src/UIMessages.combineUIMessages.test.ts +239 -0
  155. package/src/UIMessages.test.ts +273 -0
  156. package/src/UIMessages.ts +739 -0
  157. package/src/client/approval.test.ts +350 -0
  158. package/src/client/createTool.ts +291 -76
  159. package/src/client/defaultComponent.ts +17 -0
  160. package/src/client/definePlaygroundAPI.ts +67 -31
  161. package/src/client/files.ts +100 -20
  162. package/src/client/index.test.ts +40 -85
  163. package/src/client/index.ts +638 -1289
  164. package/src/client/messages.ts +237 -0
  165. package/src/client/mockModel.ts +252 -0
  166. package/src/client/saveInputMessages.test.ts +583 -0
  167. package/src/client/saveInputMessages.ts +101 -0
  168. package/src/client/search.test.ts +1207 -0
  169. package/src/client/search.ts +581 -70
  170. package/src/client/start.ts +327 -0
  171. package/src/client/streamText.ts +187 -0
  172. package/src/client/streaming.test.ts +186 -0
  173. package/src/client/streaming.ts +241 -97
  174. package/src/client/threads.ts +83 -0
  175. package/src/client/types.ts +370 -219
  176. package/src/client/utils.ts +27 -0
  177. package/src/component/_generated/api.ts +64 -0
  178. package/src/component/_generated/component.ts +4902 -0
  179. package/src/component/_generated/{server.d.ts → server.ts} +33 -21
  180. package/src/component/files.ts +11 -2
  181. package/src/component/messages.test.ts +195 -51
  182. package/src/component/messages.ts +500 -201
  183. package/src/component/schema.ts +20 -46
  184. package/src/component/setup.test.ts +7 -0
  185. package/src/component/streams.ts +184 -83
  186. package/src/component/users.test.ts +0 -1
  187. package/src/component/vector/index.ts +1 -3
  188. package/src/deltas.test.ts +626 -0
  189. package/src/deltas.ts +569 -0
  190. package/src/fromUIMessages.test.ts +497 -0
  191. package/src/mapping.test.ts +180 -6
  192. package/src/mapping.ts +479 -162
  193. package/src/react/SmoothText.tsx +9 -0
  194. package/src/react/index.ts +10 -230
  195. package/src/react/optimisticallySendMessage.ts +55 -12
  196. package/src/react/types.ts +6 -39
  197. package/src/react/useDeltaStreams.ts +160 -0
  198. package/src/react/useSmoothText.ts +56 -36
  199. package/src/react/useStreamingUIMessages.ts +143 -0
  200. package/src/react/useThreadMessages.ts +262 -0
  201. package/src/react/useUIMessages.test.ts +255 -0
  202. package/src/react/useUIMessages.ts +195 -0
  203. package/src/shared.ts +88 -12
  204. package/src/test.ts +18 -0
  205. package/src/toUIMessages.test.ts +1269 -0
  206. package/src/validators.test.ts +18 -19
  207. package/src/validators.ts +325 -185
  208. package/dist/client/_generated/_ignore.d.ts +0 -1
  209. package/dist/client/_generated/_ignore.d.ts.map +0 -1
  210. package/dist/client/_generated/_ignore.js +0 -3
  211. package/dist/client/_generated/_ignore.js.map +0 -1
  212. package/dist/client/listMessages.d.ts +0 -22
  213. package/dist/client/listMessages.d.ts.map +0 -1
  214. package/dist/client/listMessages.js +0 -25
  215. package/dist/client/listMessages.js.map +0 -1
  216. package/dist/package.json +0 -3
  217. package/dist/react/deltas.d.ts +0 -26
  218. package/dist/react/deltas.d.ts.map +0 -1
  219. package/dist/react/deltas.js +0 -384
  220. package/dist/react/deltas.js.map +0 -1
  221. package/dist/react/toUIMessages.d.ts +0 -15
  222. package/dist/react/toUIMessages.d.ts.map +0 -1
  223. package/dist/react/toUIMessages.js +0 -211
  224. package/dist/react/toUIMessages.js.map +0 -1
  225. package/src/client/listMessages.ts +0 -38
  226. package/src/component/_generated/api.d.ts +0 -2202
  227. package/src/component/_generated/api.js +0 -23
  228. package/src/component/_generated/server.js +0 -90
  229. package/src/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  230. package/src/react/deltas.test.ts +0 -315
  231. package/src/react/deltas.ts +0 -478
  232. package/src/react/toUIMessages.test.ts +0 -420
  233. package/src/react/toUIMessages.ts +0 -253
  234. package/src/vitest.config.ts +0 -7
  235. /package/src/component/_generated/{dataModel.d.ts → dataModel.ts} +0 -0
@@ -1,478 +0,0 @@
1
- import type { MessageDoc } from "../client/index.js";
2
- import type {
3
- Message,
4
- MessageStatus,
5
- StreamDelta,
6
- StreamMessage,
7
- TextStreamPart,
8
- vReasoningPart,
9
- vSource,
10
- vTextPart,
11
- vToolCallPart,
12
- vToolResultPart,
13
- } from "../validators.js";
14
- import type { Infer } from "convex/values";
15
-
16
- export function mergeDeltas(
17
- threadId: string,
18
- streamMessages: StreamMessage[],
19
- existingStreams: Array<{
20
- streamId: string;
21
- cursor: number;
22
- messages: MessageDoc[];
23
- }>,
24
- allDeltas: StreamDelta[],
25
- ): [
26
- MessageDoc[],
27
- Array<{ streamId: string; cursor: number; messages: MessageDoc[] }>,
28
- boolean,
29
- ] {
30
- const newStreams: Array<{
31
- streamId: string;
32
- cursor: number;
33
- messages: MessageDoc[];
34
- }> = [];
35
- // Seed the existing chunks
36
- let changed = false;
37
- for (const streamMessage of streamMessages) {
38
- const deltas = allDeltas.filter(
39
- (d) => d.streamId === streamMessage.streamId,
40
- );
41
- const existing = existingStreams.find(
42
- (s) => s.streamId === streamMessage.streamId,
43
- );
44
- const [newStream, messageChanged] = applyDeltasToStreamMessage(
45
- threadId,
46
- streamMessage,
47
- existing,
48
- deltas,
49
- );
50
- newStreams.push(newStream);
51
- if (messageChanged) changed = true;
52
- }
53
- for (const { streamId } of existingStreams) {
54
- if (!newStreams.find((s) => s.streamId === streamId)) {
55
- // There's a stream that's no longer active.
56
- changed = true;
57
- }
58
- }
59
- const messages = newStreams
60
- .map((s) => s.messages)
61
- .flat()
62
- .sort((a, b) => a.order - b.order || a.stepOrder - b.stepOrder);
63
- return [messages, newStreams, changed];
64
- }
65
-
66
- // exported for testing
67
- export function applyDeltasToStreamMessage(
68
- threadId: string,
69
- streamMessage: StreamMessage,
70
- existing:
71
- | { streamId: string; cursor: number; messages: MessageDoc[] }
72
- | undefined,
73
- deltas: StreamDelta[],
74
- ): [{ streamId: string; cursor: number; messages: MessageDoc[] }, boolean] {
75
- let changed = false;
76
- let cursor = existing?.cursor ?? 0;
77
- let parts: TextStreamPart[] = [];
78
- for (const delta of deltas.sort((a, b) => a.start - b.start)) {
79
- if (delta.parts.length === 0) {
80
- console.warn(`Got delta with no parts: ${JSON.stringify(delta)}`);
81
- continue;
82
- }
83
- if (cursor !== delta.start) {
84
- if (cursor >= delta.end) {
85
- console.debug(
86
- `Got duplicate delta for stream ${delta.streamId} at ${delta.start}`,
87
- );
88
- continue;
89
- } else if (cursor < delta.start) {
90
- console.warn(
91
- `Got delta for stream ${delta.streamId} that has a gap ${cursor} -> ${delta.start}`,
92
- );
93
- continue;
94
- } else {
95
- throw new Error(
96
- `Got unexpected delta for stream ${delta.streamId}: delta: ${delta.start} -> ${delta.end} existing cursor: ${cursor}`,
97
- );
98
- }
99
- }
100
- changed = true;
101
- cursor = delta.end;
102
- parts.push(...delta.parts);
103
- }
104
- if (existing && existing.messages.length > 0 && !changed) {
105
- const lastMessage = existing.messages.at(-1)!;
106
- if (statusFromStreamStatus(streamMessage.status) !== lastMessage.status) {
107
- changed = true;
108
- }
109
- }
110
- if (!changed) {
111
- return [
112
- existing ?? { streamId: streamMessage.streamId, cursor, messages: [] },
113
- false,
114
- ];
115
- }
116
-
117
- const existingMessages = existing?.messages ?? [];
118
-
119
- let currentMessage: MessageDoc;
120
- if (existingMessages.length > 0) {
121
- // replace the last message with a new one
122
- const lastMessage = existingMessages.at(-1)!;
123
- currentMessage = {
124
- ...lastMessage,
125
- message: cloneMessageAndContent(lastMessage.message),
126
- status: statusFromStreamStatus(streamMessage.status),
127
- };
128
- } else {
129
- const newMessage = createStreamingMessage(
130
- threadId,
131
- streamMessage,
132
- parts[0]!,
133
- existingMessages.length,
134
- );
135
- parts = parts.slice(1);
136
- currentMessage = newMessage;
137
- }
138
- const newStream = {
139
- streamId: streamMessage.streamId,
140
- cursor,
141
- messages: [...existingMessages.slice(0, -1), currentMessage],
142
- };
143
- let lastContent = getLastContent(currentMessage);
144
- for (const part of parts) {
145
- let contentToAdd:
146
- | Infer<typeof vTextPart>
147
- | Infer<typeof vToolCallPart>
148
- | Infer<typeof vToolResultPart>
149
- | Infer<typeof vReasoningPart>
150
- | undefined;
151
- const isToolRole = part.type === "source" || part.type === "tool-result";
152
- if (isToolRole !== (currentMessage.message!.role === "tool")) {
153
- currentMessage = createStreamingMessage(
154
- threadId,
155
- streamMessage,
156
- part,
157
- newStream.messages.length,
158
- );
159
- lastContent = getLastContent(currentMessage);
160
- newStream.messages.push(currentMessage);
161
- continue;
162
- }
163
- switch (part.type) {
164
- case "text-delta": {
165
- const text = "text" in part ? part.text : part.textDelta;
166
- currentMessage.text = (currentMessage.text ?? "") + text;
167
- if (lastContent?.type === "text") {
168
- lastContent.text = (lastContent.text ?? "") + text;
169
- } else {
170
- contentToAdd = { type: "text", text } satisfies Infer<
171
- typeof vTextPart
172
- >;
173
- }
174
- break;
175
- }
176
- case "tool-input-start":
177
- case "tool-call-streaming-start": {
178
- const toolCallId = "toolCallId" in part ? part.toolCallId : part.id;
179
- currentMessage.tool = true;
180
- contentToAdd = {
181
- type: "tool-call",
182
- toolCallId,
183
- toolName: part.toolName,
184
- args: "",
185
- providerExecuted:
186
- "providerExecuted" in part ? part.providerExecuted : undefined,
187
- providerOptions:
188
- "providerMetadata" in part ? part.providerMetadata : undefined,
189
- } satisfies Infer<typeof vToolCallPart>;
190
- break;
191
- }
192
- case "tool-call-delta":
193
- case "tool-input-delta":
194
- {
195
- currentMessage.tool = true;
196
- if (lastContent?.type !== "tool-call") {
197
- throw new Error("Expected last content to be a tool call");
198
- }
199
- if (typeof lastContent.args !== "string") {
200
- throw new Error("Expected args to be a string");
201
- }
202
- const delta =
203
- "argsTextDelta" in part ? part.argsTextDelta : part.delta;
204
- lastContent.args = (lastContent.args ?? "") + delta;
205
- }
206
- break;
207
- case "tool-call": {
208
- currentMessage.tool = true;
209
- contentToAdd = toolCallContent(part);
210
- break;
211
- }
212
- case "tool-result": {
213
- contentToAdd = toolResultContent(part);
214
- break;
215
- }
216
- case "reasoning":
217
- currentMessage.reasoning =
218
- (currentMessage.reasoning ?? "") + part.textDelta;
219
- if (lastContent?.type === "reasoning") {
220
- lastContent.text = (lastContent.text ?? "") + part.textDelta;
221
- } else {
222
- contentToAdd = {
223
- type: "reasoning",
224
- text: part.textDelta,
225
- };
226
- }
227
- break;
228
- case "reasoning-delta": {
229
- currentMessage.reasoning = (currentMessage.reasoning ?? "") + part.text;
230
- if (lastContent?.type === "reasoning") {
231
- lastContent.text = (lastContent.text ?? "") + part.text;
232
- } else {
233
- contentToAdd = {
234
- type: "reasoning",
235
- text: part.text,
236
- providerOptions:
237
- "providerMetadata" in part ? part.providerMetadata : undefined,
238
- state: "streaming",
239
- } satisfies Infer<typeof vReasoningPart>;
240
- }
241
- break;
242
- }
243
- case "source":
244
- if (!currentMessage.sources) {
245
- currentMessage.sources = [];
246
- }
247
- if ("source" in part) {
248
- currentMessage.sources.push({
249
- type: "source",
250
- ...part.source,
251
- } satisfies Infer<typeof vSource>);
252
- } else {
253
- currentMessage.sources.push(part);
254
- }
255
- break;
256
- case "raw":
257
- contentToAdd = part.rawValue;
258
- break;
259
- default:
260
- console.warn(`Received unexpected part: ${JSON.stringify(part)}`);
261
- break;
262
- }
263
- if (contentToAdd) {
264
- if (!currentMessage.message!.content) {
265
- currentMessage.message!.content = [];
266
- }
267
- if (!Array.isArray(currentMessage.message?.content)) {
268
- throw new Error("Expected message content to be an array");
269
- }
270
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
271
- currentMessage.message.content.push(contentToAdd as any);
272
- lastContent = contentToAdd;
273
- }
274
- }
275
- return [newStream, true];
276
- }
277
-
278
- function toolCallContent(
279
- part: Extract<TextStreamPart, { type: "tool-call" }>,
280
- ): Infer<typeof vToolCallPart> {
281
- const args = "args" in part ? part.args : part.input;
282
- return {
283
- type: "tool-call",
284
- toolCallId: part.toolCallId,
285
- toolName: part.toolName,
286
- args,
287
- providerExecuted: part.providerExecuted,
288
- } satisfies Infer<typeof vToolCallPart>;
289
- }
290
-
291
- function toolResultContent(
292
- part: Extract<TextStreamPart, { type: "tool-result" }>,
293
- ): Infer<typeof vToolResultPart> {
294
- const result =
295
- "output" in part ? part.output : "result" in part ? part.result : undefined;
296
- const args =
297
- "input" in part ? part.input : "args" in part ? part.args : undefined;
298
- return {
299
- type: "tool-result",
300
- toolCallId: part.toolCallId,
301
- toolName: part.toolName,
302
- result,
303
- args,
304
- providerExecuted: part.providerExecuted,
305
- } satisfies Infer<typeof vToolResultPart>;
306
- }
307
- function cloneMessageAndContent(
308
- message: Message | undefined,
309
- ): Message | undefined {
310
- return (
311
- message &&
312
- ({
313
- ...message,
314
- content: Array.isArray(message.content)
315
- ? [...message.content]
316
- : message.content,
317
- } as typeof message)
318
- );
319
- }
320
-
321
- function getLastContent(message: MessageDoc) {
322
- if (Array.isArray(message.message?.content)) {
323
- return message.message.content.at(-1);
324
- }
325
- return undefined;
326
- }
327
-
328
- function statusFromStreamStatus(
329
- status: StreamMessage["status"],
330
- ): MessageStatus {
331
- switch (status) {
332
- case "streaming":
333
- return "pending";
334
- case "finished":
335
- return "success";
336
- case "aborted":
337
- return "failed";
338
- default:
339
- return "pending";
340
- }
341
- }
342
-
343
- // TODO: share more code with applyDeltasToStreamMessage
344
- export function createStreamingMessage(
345
- threadId: string,
346
- message: StreamMessage,
347
- part: TextStreamPart,
348
- index: number,
349
- ): MessageDoc {
350
- const { streamId, ...rest } = message;
351
- const metadata: MessageDoc = {
352
- ...rest,
353
- _id: `${streamId}-${index}`,
354
- _creationTime: Date.now(),
355
- status: statusFromStreamStatus(message.status),
356
- threadId,
357
- tool: false,
358
- };
359
- switch (part.type) {
360
- case "text-delta": {
361
- const text = "text" in part ? part.text : part.textDelta;
362
- return {
363
- ...metadata,
364
- message: {
365
- role: "assistant",
366
- content: [{ type: "text", text }],
367
- },
368
- text,
369
- };
370
- }
371
- case "tool-input-start":
372
- case "tool-call-streaming-start": {
373
- const toolCallId = "toolCallId" in part ? part.toolCallId : part.id;
374
- return {
375
- ...metadata,
376
- tool: true,
377
- message: {
378
- role: "assistant",
379
- content: [
380
- {
381
- type: "tool-call",
382
- toolName: part.toolName,
383
- toolCallId,
384
- args: "", // when it's a string, it's a partial call
385
- providerExecuted:
386
- "providerExecuted" in part ? part.providerExecuted : undefined,
387
- providerOptions:
388
- "providerMetadata" in part ? part.providerMetadata : undefined,
389
- },
390
- ],
391
- },
392
- };
393
- }
394
- case "tool-input-delta":
395
- case "tool-call-delta": {
396
- console.warn("Received tool call delta part first??");
397
- const delta = "argsTextDelta" in part ? part.argsTextDelta : part.delta;
398
- const toolCallId = "toolCallId" in part ? part.toolCallId : part.id;
399
- const toolName =
400
- "toolName" in part ? part.toolName : part.type.slice("tool-".length);
401
- return {
402
- ...metadata,
403
- tool: true,
404
- message: {
405
- role: "assistant",
406
- content: [
407
- {
408
- type: "tool-call",
409
- toolCallId,
410
- toolName,
411
- args: delta,
412
- },
413
- ],
414
- },
415
- };
416
- }
417
- case "tool-call": {
418
- return {
419
- ...metadata,
420
- tool: true,
421
- message: {
422
- role: "assistant",
423
- content: [toolCallContent(part)],
424
- },
425
- };
426
- }
427
- case "tool-result":
428
- return {
429
- ...metadata,
430
- tool: true,
431
- message: {
432
- role: "tool",
433
- content: [toolResultContent(part)],
434
- },
435
- };
436
- case "reasoning":
437
- return {
438
- ...metadata,
439
- message: {
440
- role: "assistant",
441
- content: [{ type: "reasoning", text: part.textDelta }],
442
- },
443
- reasoning: part.textDelta,
444
- };
445
- case "reasoning-delta": {
446
- return {
447
- ...metadata,
448
- message: {
449
- role: "assistant",
450
- content: [{ type: "reasoning", text: part.text }],
451
- },
452
- reasoning: part.text,
453
- };
454
- }
455
- case "source":
456
- console.warn("Received source part first??");
457
- return {
458
- ...metadata,
459
- tool: true,
460
- message: { role: "tool", content: [] },
461
- sources: [
462
- "source" in part
463
- ? {
464
- ...part.source,
465
- type: "source",
466
- }
467
- : part,
468
- ],
469
- };
470
- // case "raw":
471
- // return {
472
- // ...metadata,
473
- // message: { role: "assistant", content: [part.rawValue] },
474
- // };
475
- default:
476
- throw new Error(`Unexpected part type: ${JSON.stringify(part)}`);
477
- }
478
- }