@convex-dev/agent 0.2.2 → 0.2.3

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 (62) hide show
  1. package/dist/client/definePlaygroundAPI.d.ts +144 -13
  2. package/dist/client/definePlaygroundAPI.d.ts.map +1 -1
  3. package/dist/client/files.d.ts +1 -1
  4. package/dist/client/files.d.ts.map +1 -1
  5. package/dist/client/files.js.map +1 -1
  6. package/dist/client/index.d.ts +130 -10
  7. package/dist/client/index.d.ts.map +1 -1
  8. package/dist/client/index.js +17 -7
  9. package/dist/client/index.js.map +1 -1
  10. package/dist/client/messages.d.ts +32 -5
  11. package/dist/client/messages.d.ts.map +1 -1
  12. package/dist/client/messages.js +7 -4
  13. package/dist/client/messages.js.map +1 -1
  14. package/dist/client/search.d.ts +31 -4
  15. package/dist/client/search.d.ts.map +1 -1
  16. package/dist/client/search.js +2 -4
  17. package/dist/client/search.js.map +1 -1
  18. package/dist/client/streaming.d.ts +322 -39
  19. package/dist/client/streaming.d.ts.map +1 -1
  20. package/dist/component/_generated/api.d.ts +301 -15
  21. package/dist/component/messages.d.ts +336 -41
  22. package/dist/component/messages.d.ts.map +1 -1
  23. package/dist/component/messages.js +4 -4
  24. package/dist/component/messages.js.map +1 -1
  25. package/dist/component/schema.d.ts +874 -133
  26. package/dist/component/schema.d.ts.map +1 -1
  27. package/dist/mapping.d.ts +4 -4
  28. package/dist/mapping.d.ts.map +1 -1
  29. package/dist/mapping.js +68 -38
  30. package/dist/mapping.js.map +1 -1
  31. package/dist/react/deltas.d.ts +3 -3
  32. package/dist/react/deltas.d.ts.map +1 -1
  33. package/dist/react/deltas.js +321 -28
  34. package/dist/react/deltas.js.map +1 -1
  35. package/dist/react/toUIMessages.d.ts.map +1 -1
  36. package/dist/react/toUIMessages.js +289 -180
  37. package/dist/react/toUIMessages.js.map +1 -1
  38. package/dist/react/useSmoothText.d.ts.map +1 -1
  39. package/dist/react/useSmoothText.js +15 -6
  40. package/dist/react/useSmoothText.js.map +1 -1
  41. package/dist/shared.d.ts +4 -0
  42. package/dist/shared.d.ts.map +1 -1
  43. package/dist/shared.js +8 -0
  44. package/dist/shared.js.map +1 -1
  45. package/dist/validators.d.ts +1887 -249
  46. package/dist/validators.d.ts.map +1 -1
  47. package/dist/validators.js +10 -3
  48. package/dist/validators.js.map +1 -1
  49. package/package.json +1 -1
  50. package/src/client/files.ts +4 -4
  51. package/src/client/index.ts +41 -15
  52. package/src/client/messages.ts +12 -4
  53. package/src/client/search.ts +2 -6
  54. package/src/component/_generated/api.d.ts +301 -15
  55. package/src/component/messages.ts +4 -3
  56. package/src/mapping.ts +105 -56
  57. package/src/react/deltas.ts +391 -46
  58. package/src/react/toUIMessages.test.ts +234 -4
  59. package/src/react/toUIMessages.ts +366 -192
  60. package/src/react/useSmoothText.ts +25 -13
  61. package/src/shared.ts +14 -0
  62. package/src/validators.ts +23 -15
@@ -1,16 +1,26 @@
1
- import type { TextStreamPart, ToolSet } from "ai";
2
- import type { MessageDoc } from "../client/index.js";
3
1
  import type {
4
- Message,
5
- MessageStatus,
6
- StreamDelta,
7
- StreamMessage,
8
- vReasoningPart,
9
- vTextPart,
10
- vToolCallPart,
11
- vToolResultPart,
2
+ ProviderMetadata,
3
+ TextStreamPart,
4
+ ToolSet,
5
+ UIMessageChunk,
6
+ } from "ai";
7
+ import type { MessageDoc } from "../client/index.js";
8
+ import {
9
+ vSource,
10
+ type Message,
11
+ type MessageStatus,
12
+ type StreamDelta,
13
+ type StreamMessage,
14
+ type vFilePart,
15
+ type vReasoningPart,
16
+ type vTextPart,
17
+ type vToolCallPart,
18
+ type vToolResultPart,
12
19
  } from "../validators.js";
13
20
  import type { Infer } from "convex/values";
21
+ import { serializeWarnings } from "../mapping.js";
22
+ import { parse } from "convex-helpers/validators";
23
+ import { sorted } from "../shared.js";
14
24
 
15
25
  export function mergeDeltas(
16
26
  threadId: string,
@@ -55,10 +65,7 @@ export function mergeDeltas(
55
65
  changed = true;
56
66
  }
57
67
  }
58
- const messages = newStreams
59
- .map((s) => s.messages)
60
- .flat()
61
- .sort((a, b) => a.order - b.order || a.stepOrder - b.stepOrder);
68
+ const messages = sorted(newStreams.map((s) => s.messages).flat());
62
69
  return [messages, newStreams, changed];
63
70
  }
64
71
 
@@ -73,7 +80,7 @@ export function applyDeltasToStreamMessage(
73
80
  ): [{ streamId: string; cursor: number; messages: MessageDoc[] }, boolean] {
74
81
  let changed = false;
75
82
  let cursor = existing?.cursor ?? 0;
76
- let parts: TextStreamPart<ToolSet>[] = [];
83
+ let parts: (UIMessageChunk<ToolSet> | TextStreamPart<ToolSet>)[] = [];
77
84
  for (const delta of deltas.sort((a, b) => a.start - b.start)) {
78
85
  if (delta.parts.length === 0) {
79
86
  console.warn(`Got delta with no parts: ${JSON.stringify(delta)}`);
@@ -146,6 +153,7 @@ export function applyDeltasToStreamMessage(
146
153
  | Infer<typeof vToolCallPart>
147
154
  | Infer<typeof vToolResultPart>
148
155
  | Infer<typeof vReasoningPart>
156
+ | Infer<typeof vFilePart>
149
157
  | undefined;
150
158
  const isToolRole = part.type === "source" || part.type === "tool-result";
151
159
  if (isToolRole !== (currentMessage.message!.role === "tool")) {
@@ -161,29 +169,54 @@ export function applyDeltasToStreamMessage(
161
169
  }
162
170
  switch (part.type) {
163
171
  case "text-delta": {
164
- const text = part.text;
172
+ const text = "text" in part ? part.text : part.delta;
173
+ if (!text) {
174
+ console.warn("Got text delta with no text", part);
175
+ }
165
176
  currentMessage.text = (currentMessage.text ?? "") + text;
166
177
  if (lastContent?.type === "text") {
167
178
  lastContent.text = (lastContent.text ?? "") + text;
179
+ lastContent.providerMetadata = mergeProviderMetadata(
180
+ lastContent.providerMetadata,
181
+ part.providerMetadata,
182
+ );
168
183
  } else {
169
- contentToAdd = { type: "text", text } satisfies Infer<
170
- typeof vTextPart
171
- >;
184
+ contentToAdd = {
185
+ type: "text",
186
+ providerMetadata: part.providerMetadata,
187
+ text,
188
+ } satisfies Infer<typeof vTextPart>;
189
+ }
190
+ break;
191
+ }
192
+ case "tool-input-available": {
193
+ if (
194
+ lastContent?.type === "tool-call" &&
195
+ lastContent.toolCallId === part.toolCallId
196
+ ) {
197
+ lastContent.args = part.input;
198
+ lastContent.providerExecuted ??= part.providerExecuted;
199
+ lastContent.providerMetadata = mergeProviderMetadata(
200
+ lastContent.providerMetadata,
201
+ part.providerMetadata,
202
+ );
203
+ } else {
204
+ contentToAdd = toolCallContent(part);
172
205
  }
173
206
  break;
174
207
  }
175
208
  case "tool-input-start": {
176
- const toolCallId = part.id;
209
+ const toolCallId = "id" in part ? part.id : part.toolCallId;
177
210
  currentMessage.tool = true;
178
211
  contentToAdd = {
179
212
  type: "tool-call",
180
213
  toolCallId,
181
214
  toolName: part.toolName,
182
215
  args: "",
216
+ providerMetadata:
217
+ "providerMetadata" in part ? part.providerMetadata : undefined,
183
218
  providerExecuted:
184
219
  "providerExecuted" in part ? part.providerExecuted : undefined,
185
- providerOptions:
186
- "providerMetadata" in part ? part.providerMetadata : undefined,
187
220
  } satisfies Infer<typeof vToolCallPart>;
188
221
  break;
189
222
  }
@@ -194,11 +227,22 @@ export function applyDeltasToStreamMessage(
194
227
  throw new Error("Expected last content to be a tool call");
195
228
  }
196
229
  if (typeof lastContent.args !== "string") {
197
- throw new Error("Expected args to be a string");
230
+ lastContent.args = lastContent.args?.toString() ?? "";
198
231
  }
199
232
  const delta =
200
- "argsTextDelta" in part ? part.argsTextDelta : part.delta;
201
- lastContent.args = (lastContent.args ?? "") + delta;
233
+ "inputTextDelta" in part
234
+ ? part.inputTextDelta
235
+ : "delta" in part
236
+ ? part.delta
237
+ : "";
238
+ lastContent.args = lastContent.args + delta;
239
+ lastContent.providerMetadata =
240
+ "providerMetadata" in part
241
+ ? mergeProviderMetadata(
242
+ lastContent.providerMetadata,
243
+ part.providerMetadata,
244
+ )
245
+ : undefined;
202
246
  }
203
247
  break;
204
248
  case "tool-call": {
@@ -206,21 +250,50 @@ export function applyDeltasToStreamMessage(
206
250
  contentToAdd = toolCallContent(part);
207
251
  break;
208
252
  }
253
+ case "tool-output-available":
254
+ if (
255
+ lastContent?.type === "tool-call" &&
256
+ lastContent.toolCallId === part.toolCallId
257
+ ) {
258
+ contentToAdd = {
259
+ type: "tool-result",
260
+ toolCallId: part.toolCallId,
261
+ toolName: lastContent.toolName,
262
+ args: lastContent.args,
263
+ result: part.output,
264
+ providerExecuted: part.providerExecuted,
265
+ } satisfies Infer<typeof vToolResultPart>;
266
+ } else if (
267
+ lastContent?.type === "tool-result" &&
268
+ lastContent.toolCallId === part.toolCallId
269
+ ) {
270
+ lastContent.result = part.output;
271
+ lastContent.providerExecuted = part.providerExecuted;
272
+ } else {
273
+ console.warn(
274
+ "Got tool output available part for unknown tool call",
275
+ part,
276
+ );
277
+ }
278
+ break;
209
279
  case "tool-result": {
210
280
  contentToAdd = toolResultContent(part);
211
281
  break;
212
282
  }
213
283
  case "reasoning-delta": {
214
- currentMessage.reasoning = (currentMessage.reasoning ?? "") + part.text;
284
+ const text = "text" in part ? part.text : part.delta;
285
+ currentMessage.reasoning = (currentMessage.reasoning ?? "") + text;
215
286
  if (lastContent?.type === "reasoning") {
216
- lastContent.text = (lastContent.text ?? "") + part.text;
287
+ lastContent.text = (lastContent.text ?? "") + text;
288
+ lastContent.providerMetadata = mergeProviderMetadata(
289
+ lastContent.providerMetadata,
290
+ part.providerMetadata,
291
+ );
217
292
  } else {
218
293
  contentToAdd = {
219
294
  type: "reasoning",
220
- text: part.text,
221
- providerOptions:
222
- "providerMetadata" in part ? part.providerMetadata : undefined,
223
- state: "streaming",
295
+ text,
296
+ providerMetadata: part.providerMetadata,
224
297
  } satisfies Infer<typeof vReasoningPart>;
225
298
  }
226
299
  break;
@@ -229,14 +302,158 @@ export function applyDeltasToStreamMessage(
229
302
  if (!currentMessage.sources) {
230
303
  currentMessage.sources = [];
231
304
  }
232
- currentMessage.sources.push(part);
305
+ currentMessage.sources.push(parse(vSource, part));
306
+ console.warn("Got source part with unknown source type", part);
307
+ break;
308
+ case "abort":
309
+ currentMessage.status = "failed";
310
+ currentMessage.error = "abort";
311
+ break;
312
+ case "error":
313
+ currentMessage.status = "failed";
314
+ currentMessage.error =
315
+ "error" in part ? part.error?.toString() : part.errorText;
316
+ break;
317
+ case "message-metadata":
318
+ currentMessage.providerMetadata ??= {};
319
+ currentMessage.providerMetadata["metadata"] = {
320
+ parts: [part.messageMetadata],
321
+ };
322
+ console.warn(
323
+ "Putting message metadata part in providerMetadata. Use useUIMessages or useStreamingUIMessages instead.",
324
+ part,
325
+ );
326
+ break;
327
+ case "source-document":
328
+ contentToAdd = {
329
+ type: "file",
330
+ data: part.sourceId,
331
+ mimeType: part.mediaType,
332
+ filename: part.title ?? part.filename,
333
+ providerMetadata: part.providerMetadata,
334
+ } satisfies Infer<typeof vFilePart>;
233
335
  break;
336
+ case "source-url":
337
+ contentToAdd = {
338
+ type: "file",
339
+ data: part.url,
340
+ filename: part.title,
341
+ mimeType: "text/plain", // What do we do here?
342
+ providerMetadata: part.providerMetadata,
343
+ } satisfies Infer<typeof vFilePart>;
344
+ break;
345
+ case "tool-input-error":
346
+ if (
347
+ lastContent?.type === "tool-call" &&
348
+ lastContent.toolCallId === part.toolCallId
349
+ ) {
350
+ lastContent.args ||= part.input;
351
+ lastContent.providerExecuted ??= part.providerExecuted;
352
+ lastContent.providerMetadata = mergeProviderMetadata(
353
+ lastContent.providerMetadata,
354
+ part.providerMetadata,
355
+ );
356
+ } else {
357
+ if (
358
+ lastContent?.type === "tool-result" &&
359
+ lastContent.toolCallId === part.toolCallId
360
+ ) {
361
+ lastContent.isError = true;
362
+ lastContent.providerExecuted ??= part.providerExecuted;
363
+ lastContent.providerMetadata = mergeProviderMetadata(
364
+ lastContent.providerMetadata,
365
+ part.providerMetadata,
366
+ );
367
+ } else {
368
+ contentToAdd = toolCallContent(part);
369
+ }
370
+ }
371
+ currentMessage.error = part.errorText;
372
+ break;
373
+ case "tool-output-error":
374
+ if (
375
+ lastContent?.type === "tool-result" &&
376
+ lastContent.toolCallId === part.toolCallId
377
+ ) {
378
+ lastContent.isError = true;
379
+ lastContent.result = part.errorText;
380
+ lastContent.providerExecuted = part.providerExecuted;
381
+ } else if (
382
+ lastContent?.type === "tool-call" &&
383
+ lastContent.toolCallId === part.toolCallId
384
+ ) {
385
+ console.warn(
386
+ "Got tool output error part for unknown tool result",
387
+ part,
388
+ );
389
+ contentToAdd = {
390
+ type: "tool-result",
391
+ toolCallId: part.toolCallId,
392
+ toolName: lastContent.toolName,
393
+ args: lastContent.args,
394
+ result: part.errorText,
395
+ providerExecuted: part.providerExecuted,
396
+ isError: true,
397
+ } satisfies Infer<typeof vToolResultPart>;
398
+ } else {
399
+ console.warn(
400
+ "Got tool output error part for unknown tool call",
401
+ part,
402
+ );
403
+ }
404
+ break;
405
+ case "tool-error":
406
+ if (
407
+ lastContent?.type === "tool-result" &&
408
+ lastContent.toolCallId === part.toolCallId
409
+ ) {
410
+ lastContent.isError = true;
411
+ lastContent.result = part.error;
412
+ lastContent.providerExecuted = part.providerExecuted;
413
+ } else {
414
+ if (
415
+ lastContent?.type === "tool-call" &&
416
+ lastContent.toolCallId === part.toolCallId
417
+ ) {
418
+ lastContent.args ||= part.input;
419
+ lastContent.providerExecuted ??= part.providerExecuted;
420
+ }
421
+ currentMessage.error = part.error?.toString();
422
+ contentToAdd = {
423
+ type: "tool-result",
424
+ toolCallId: part.toolCallId,
425
+ toolName: part.toolName,
426
+ result: part.error,
427
+ providerExecuted: part.providerExecuted,
428
+ isError: true,
429
+ args: part.input,
430
+ } satisfies Infer<typeof vToolResultPart>;
431
+ }
432
+ break;
433
+ case "tool-input-end":
434
+ case "text-end":
435
+ case "reasoning-end":
436
+ case "finish-step":
437
+ case "finish":
438
+ case "file":
234
439
  case "raw":
440
+ case "start-step":
441
+ case "text-start":
442
+ case "reasoning-start":
443
+ case "start":
235
444
  // ignore
236
445
  break;
237
- default:
238
- console.warn(`Received unexpected part: ${JSON.stringify(part)}`);
446
+ default: {
447
+ if (!part.type.startsWith("data-")) {
448
+ console.warn(`Received unexpected part: ${JSON.stringify(part)}`);
449
+ } else {
450
+ console.warn(
451
+ "Dropping a data part. Use useUIMessages or useStreamingUIMessages instead for full UIMessage streaming support.",
452
+ part,
453
+ );
454
+ }
239
455
  break;
456
+ }
240
457
  }
241
458
  if (contentToAdd) {
242
459
  if (!currentMessage.message!.content) {
@@ -253,8 +470,34 @@ export function applyDeltasToStreamMessage(
253
470
  return [newStream, true];
254
471
  }
255
472
 
473
+ function mergeProviderMetadata(
474
+ existing: ProviderMetadata | undefined,
475
+ part: ProviderMetadata | undefined,
476
+ ): ProviderMetadata | undefined {
477
+ if (!existing && !part) {
478
+ return undefined;
479
+ }
480
+ if (!existing) {
481
+ return part;
482
+ }
483
+ if (!part) {
484
+ return existing;
485
+ }
486
+ const merged: ProviderMetadata = existing;
487
+ for (const [provider, metadata] of Object.entries(part)) {
488
+ merged[provider] = {
489
+ ...merged[provider],
490
+ ...metadata,
491
+ };
492
+ }
493
+ return merged;
494
+ }
495
+
256
496
  function toolCallContent(
257
- part: Extract<TextStreamPart<ToolSet>, { type: "tool-call" }>,
497
+ part:
498
+ | Extract<TextStreamPart<ToolSet>, { type: "tool-call" }>
499
+ | Extract<UIMessageChunk<ToolSet>, { type: "tool-input-error" }>
500
+ | Extract<UIMessageChunk<ToolSet>, { type: "tool-input-available" }>,
258
501
  ): Infer<typeof vToolCallPart> {
259
502
  const args = "args" in part ? part.args : part.input;
260
503
  return {
@@ -262,6 +505,7 @@ function toolCallContent(
262
505
  toolCallId: part.toolCallId,
263
506
  toolName: part.toolName,
264
507
  args,
508
+ providerMetadata: part.providerMetadata,
265
509
  providerExecuted: part.providerExecuted,
266
510
  } satisfies Infer<typeof vToolCallPart>;
267
511
  }
@@ -318,7 +562,7 @@ function statusFromStreamStatus(
318
562
  export function createStreamingMessage(
319
563
  threadId: string,
320
564
  message: StreamMessage,
321
- part: TextStreamPart<ToolSet>,
565
+ part: UIMessageChunk<ToolSet> | TextStreamPart<ToolSet>,
322
566
  index: number,
323
567
  ): MessageDoc {
324
568
  const { streamId, ...rest } = message;
@@ -330,12 +574,19 @@ export function createStreamingMessage(
330
574
  threadId,
331
575
  tool: false,
332
576
  };
577
+ const providerMetadata =
578
+ "providerMetadata" in part ? part.providerMetadata : undefined;
579
+ metadata.providerMetadata = providerMetadata;
580
+
333
581
  switch (part.type) {
334
582
  case "text-delta": {
335
- const text = part.text || "";
583
+ const text = "text" in part ? part.text : part.delta;
336
584
  return {
337
585
  ...metadata,
338
- message: { role: "assistant", content: [{ type: "text", text }] },
586
+ message: {
587
+ role: "assistant",
588
+ content: [{ type: "text", text, providerMetadata }],
589
+ },
339
590
  text,
340
591
  };
341
592
  }
@@ -349,12 +600,11 @@ export function createStreamingMessage(
349
600
  {
350
601
  type: "tool-call",
351
602
  toolName: part.toolName,
352
- toolCallId: part.id,
603
+ toolCallId: "id" in part ? part.id : part.toolCallId,
353
604
  args: "", // when it's a string, it's a partial call
354
605
  providerExecuted:
355
606
  "providerExecuted" in part ? part.providerExecuted : undefined,
356
- providerOptions:
357
- "providerMetadata" in part ? part.providerMetadata : undefined,
607
+ providerMetadata,
358
608
  },
359
609
  ],
360
610
  },
@@ -362,15 +612,23 @@ export function createStreamingMessage(
362
612
  }
363
613
  case "tool-input-delta": {
364
614
  console.warn("Received tool call delta part first??");
365
- const delta = part.delta;
366
- const toolCallId = part.id;
615
+ const delta = "delta" in part ? part.delta : part.inputTextDelta;
616
+ const toolCallId = "id" in part ? part.id : part.toolCallId;
367
617
  const toolName = part.type.slice("tool-".length);
368
618
  return {
369
619
  ...metadata,
370
620
  tool: true,
371
621
  message: {
372
622
  role: "assistant",
373
- content: [{ type: "tool-call", toolCallId, toolName, args: delta }],
623
+ content: [
624
+ {
625
+ type: "tool-call",
626
+ toolCallId,
627
+ toolName,
628
+ args: delta,
629
+ providerMetadata,
630
+ },
631
+ ],
374
632
  },
375
633
  };
376
634
  }
@@ -388,13 +646,20 @@ export function createStreamingMessage(
388
646
  message: { role: "tool", content: [toolResultContent(part)] },
389
647
  };
390
648
  case "reasoning-delta": {
649
+ const text = "text" in part ? part.text : part.delta;
391
650
  return {
392
651
  ...metadata,
393
652
  message: {
394
653
  role: "assistant",
395
- content: [{ type: "reasoning", text: part.text }],
654
+ content: [
655
+ {
656
+ type: "reasoning",
657
+ text,
658
+ providerMetadata,
659
+ },
660
+ ],
396
661
  },
397
- reasoning: part.text,
662
+ reasoning: text,
398
663
  };
399
664
  }
400
665
  case "source":
@@ -405,6 +670,86 @@ export function createStreamingMessage(
405
670
  message: { role: "tool", content: [] },
406
671
  sources: [part],
407
672
  };
673
+ case "raw":
674
+ case "start":
675
+ return {
676
+ ...metadata,
677
+ tool: false,
678
+ message: { role: "assistant", content: [] },
679
+ };
680
+ case "start-step":
681
+ return {
682
+ ...metadata,
683
+ message: { role: "assistant", content: [] },
684
+ ...("warnings" in part && part.warnings?.length > 0
685
+ ? { warnings: serializeWarnings(part.warnings) }
686
+ : {}),
687
+ };
688
+ case "reasoning-start":
689
+ return {
690
+ ...metadata,
691
+ message: { role: "assistant", content: [] },
692
+ reasoning: "",
693
+ };
694
+ case "abort":
695
+ return {
696
+ ...metadata,
697
+ message: { role: "assistant", content: [] },
698
+ status: "failed",
699
+ error: "abort",
700
+ };
701
+ case "tool-error":
702
+ return {
703
+ ...metadata,
704
+ message: {
705
+ role: "assistant",
706
+ content: [
707
+ {
708
+ type: "tool-call",
709
+ toolCallId: part.toolCallId,
710
+ args: part.input,
711
+ toolName: part.toolName,
712
+ providerExecuted: part.providerExecuted,
713
+ providerMetadata,
714
+ },
715
+ {
716
+ type: "tool-result",
717
+ result: part.error,
718
+ toolCallId: part.toolCallId,
719
+ isError: true,
720
+ args: part.input,
721
+ toolName: part.toolName,
722
+ providerExecuted: part.providerExecuted,
723
+ },
724
+ ],
725
+ },
726
+ error: part.error?.toString(),
727
+ };
728
+ case "text-start":
729
+ return {
730
+ ...metadata,
731
+ message: { role: "assistant", content: [] },
732
+ providerMetadata,
733
+ id: part.id,
734
+ _id: part.id,
735
+ };
736
+ case "error": {
737
+ const errorMessage: MessageDoc = {
738
+ ...metadata,
739
+ message: {
740
+ role: "assistant",
741
+ content: [],
742
+ },
743
+ };
744
+ if ("error" in part) {
745
+ errorMessage.error = part.error?.toString();
746
+ } else if (part.errorText) {
747
+ errorMessage.error = part.errorText;
748
+ } else {
749
+ console.warn("Got an error delta with no error", part);
750
+ }
751
+ return errorMessage;
752
+ }
408
753
  // case "raw":
409
754
  // return {
410
755
  // ...metadata,