@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
@@ -167,14 +167,14 @@ describe("toUIMessages", () => {
167
167
  expect(uiMessages[0].text).toBe("Here's one idea. Here's another idea.");
168
168
  expect(uiMessages[0].parts.filter((p) => p.type === "reasoning")).toEqual([
169
169
  {
170
- providerMetadata: undefined,
171
- state: undefined,
170
+ providerOptions: undefined,
171
+ state: "done",
172
172
  text: "I'm thinking...",
173
173
  type: "reasoning",
174
174
  },
175
175
  {
176
- providerMetadata: undefined,
177
- state: undefined,
176
+ providerOptions: undefined,
177
+ state: "done",
178
178
  text: "I'm thinking...",
179
179
  type: "reasoning",
180
180
  },
@@ -356,6 +356,50 @@ describe("toUIMessages", () => {
356
356
  expect(textParts[0].text).toBe("Hello!");
357
357
  });
358
358
 
359
+ it("sets text field correctly when message has many parts with text part as final part", () => {
360
+ const messages = [
361
+ baseMessageDoc({
362
+ message: {
363
+ role: "assistant",
364
+ content: [
365
+ {
366
+ type: "reasoning",
367
+ text: "Let me think about this...",
368
+ },
369
+ {
370
+ type: "tool-call",
371
+ toolName: "calculator",
372
+ toolCallId: "call1",
373
+ args: { operation: "add", a: 2, b: 3 },
374
+ },
375
+ {
376
+ type: "file",
377
+ mimeType: "application/json",
378
+ data: "some-file-data",
379
+ },
380
+ {
381
+ type: "text",
382
+ text: "Here's my final answer.",
383
+ },
384
+ ],
385
+ },
386
+ text: "Here's my final answer.",
387
+ reasoning: "Let me think about this...",
388
+ }),
389
+ ];
390
+
391
+ const uiMessages = toUIMessages(messages);
392
+
393
+ expect(uiMessages).toHaveLength(1);
394
+ expect(uiMessages[0].role).toBe("assistant");
395
+ expect(uiMessages[0].text).toBe("Here's my final answer.");
396
+
397
+ // Verify that the text part exists in parts
398
+ const textParts = uiMessages[0].parts.filter((p) => p.type === "text");
399
+ expect(textParts).toHaveLength(1);
400
+ expect(textParts[0].text).toBe("Here's my final answer.");
401
+ });
402
+
359
403
  // Add more tests for array content, tool calls, etc. as needed
360
404
 
361
405
  it("should update tool call state from input-available to output-available", () => {
@@ -417,4 +461,190 @@ describe("toUIMessages", () => {
417
461
  );
418
462
  expect(toolCallParts).toHaveLength(0);
419
463
  });
464
+ it("sets text field correctly when message has many parts with text part as final part", () => {
465
+ const messages = [
466
+ baseMessageDoc({
467
+ text: "what time is it in paris?",
468
+ message: {
469
+ role: "user",
470
+ content: "what time is it in paris?",
471
+ },
472
+ }),
473
+ baseMessageDoc({
474
+ tool: true,
475
+ finishReason: "tool-calls",
476
+ text: "",
477
+ stepOrder: 1,
478
+ message: {
479
+ role: "assistant",
480
+ content: [
481
+ {
482
+ type: "reasoning",
483
+ text: "**Finding the Time**\n\nI've pinpointed the core task: obtaining the current time in Paris. It involves using the `dateTime` tool. I've identified \"Europe/Paris\" as the necessary timezone identifier to provide to the tool. My next step is to test the tool.\n\n\n",
484
+ },
485
+ {
486
+ args: {
487
+ timezone: "Europe/Paris",
488
+ },
489
+ type: "tool-call",
490
+ toolName: "dateTime",
491
+ toolCallId: "tool_0_dateTime",
492
+ },
493
+ ],
494
+ },
495
+ reasoning:
496
+ "**Finding the Time**\n\nI've pinpointed the core task: obtaining the current time in Paris. It involves using the `dateTime` tool. I've identified \"Europe/Paris\" as the necessary timezone identifier to provide to the tool. My next step is to test the tool.\n\n\n",
497
+ reasoningDetails: [
498
+ {
499
+ text: "**Finding the Time**\n\nI've pinpointed the core task: obtaining the current time in Paris. It involves using the `dateTime` tool. I've identified \"Europe/Paris\" as the necessary timezone identifier to provide to the tool. My next step is to test the tool.\n\n\n",
500
+ type: "reasoning",
501
+ },
502
+ ],
503
+ warnings: [],
504
+ }),
505
+ baseMessageDoc({
506
+ tool: true,
507
+ stepOrder: 2,
508
+ message: {
509
+ role: "tool",
510
+ content: [
511
+ {
512
+ type: "tool-result",
513
+ toolCallId: "tool_0_dateTime",
514
+ toolName: "dateTime",
515
+ result: {
516
+ type: "json",
517
+ value: {
518
+ day: "20",
519
+ hours: 16,
520
+ minutes: 3,
521
+ month: "August",
522
+ year: "2025",
523
+ },
524
+ },
525
+ },
526
+ ],
527
+ },
528
+ sources: [],
529
+ }),
530
+ baseMessageDoc({
531
+ finishReason: "stop",
532
+ text: "The time in Paris, France is 4:03 PM on August 20, 2025.",
533
+ stepOrder: 3,
534
+ message: {
535
+ role: "assistant",
536
+ content: [
537
+ {
538
+ type: "text",
539
+ text: "The time in Paris, France is 4:03 PM on August 20, 2025.",
540
+ },
541
+ ],
542
+ },
543
+ reasoningDetails: [],
544
+ sources: [],
545
+ warnings: [],
546
+ }),
547
+ ];
548
+
549
+ const uiMessages = toUIMessages(messages);
550
+
551
+ expect(uiMessages).toHaveLength(2);
552
+ expect(uiMessages[0].role).toBe("user");
553
+ expect(uiMessages[0].text).toBe("what time is it in paris?");
554
+ expect(uiMessages[1].role).toBe("assistant");
555
+ expect(uiMessages[1].text).toBe(
556
+ "The time in Paris, France is 4:03 PM on August 20, 2025.",
557
+ );
558
+ });
559
+
560
+ it("handles messages in reverse order (assistant response, then tool response, then tool call)", () => {
561
+ const messages = [
562
+ // Final assistant response comes first (stepOrder 3) - no tool flag since it's the final message
563
+ baseMessageDoc({
564
+ _id: "msg3",
565
+ order: 1,
566
+ stepOrder: 3,
567
+ finishReason: "stop",
568
+ text: "The result is 42.",
569
+ tool: false, // This is the final message without tool calls
570
+ message: {
571
+ role: "assistant",
572
+ content: [
573
+ {
574
+ type: "text",
575
+ text: "The result is 42.",
576
+ },
577
+ ],
578
+ },
579
+ }),
580
+ // Tool result comes second (stepOrder 2)
581
+ baseMessageDoc({
582
+ _id: "msg2",
583
+ order: 1,
584
+ stepOrder: 2,
585
+ tool: true,
586
+ message: {
587
+ role: "tool",
588
+ content: [
589
+ {
590
+ type: "tool-result",
591
+ toolCallId: "call1",
592
+ toolName: "calculator",
593
+ result: "42",
594
+ },
595
+ ],
596
+ },
597
+ }),
598
+ // Tool call comes last (stepOrder 1)
599
+ baseMessageDoc({
600
+ _id: "msg1",
601
+ order: 1,
602
+ stepOrder: 1,
603
+ tool: true,
604
+ text: "",
605
+ message: {
606
+ role: "assistant",
607
+ content: [
608
+ {
609
+ type: "tool-call",
610
+ toolName: "calculator",
611
+ toolCallId: "call1",
612
+ args: { operation: "add", a: 40, b: 2 },
613
+ },
614
+ ],
615
+ },
616
+ }),
617
+ ];
618
+
619
+ const uiMessages = toUIMessages(messages);
620
+
621
+ expect(uiMessages).toHaveLength(1);
622
+ expect(uiMessages[0].role).toBe("assistant");
623
+
624
+ // Should concatenate text from all messages (only the final response has text)
625
+ expect(uiMessages[0].text).toBe("The result is 42.");
626
+
627
+ // Should use first message's fields (msg1 with stepOrder 1)
628
+ expect(uiMessages[0].id).toBe("msg1");
629
+ expect(uiMessages[0].order).toBe(1);
630
+ expect(uiMessages[0].stepOrder).toBe(1);
631
+
632
+ // Should have both tool call and result parts
633
+ const toolParts = uiMessages[0].parts.filter(
634
+ (p) => p.type === "tool-calculator",
635
+ );
636
+ expect(toolParts).toHaveLength(1);
637
+ expect(toolParts[0]).toMatchObject({
638
+ type: "tool-calculator",
639
+ toolCallId: "call1",
640
+ state: "output-available",
641
+ input: { operation: "add", a: 40, b: 2 },
642
+ output: "42",
643
+ });
644
+
645
+ // Should also have text part
646
+ const textParts = uiMessages[0].parts.filter((p) => p.type === "text");
647
+ expect(textParts).toHaveLength(1);
648
+ expect(textParts[0].text).toBe("The result is 42.");
649
+ });
420
650
  });