@convex-dev/agent 0.2.7 → 0.2.8-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 (104) hide show
  1. package/dist/UIMessages.d.ts +43 -0
  2. package/dist/UIMessages.d.ts.map +1 -0
  3. package/dist/{react/toUIMessages.js → UIMessages.js} +97 -4
  4. package/dist/UIMessages.js.map +1 -0
  5. package/dist/client/index.d.ts +10 -10
  6. package/dist/client/index.d.ts.map +1 -1
  7. package/dist/client/index.js +23 -20
  8. package/dist/client/index.js.map +1 -1
  9. package/dist/client/messages.d.ts +5 -0
  10. package/dist/client/messages.d.ts.map +1 -1
  11. package/dist/client/messages.js +6 -1
  12. package/dist/client/messages.js.map +1 -1
  13. package/dist/client/search.d.ts.map +1 -1
  14. package/dist/client/search.js +2 -0
  15. package/dist/client/search.js.map +1 -1
  16. package/dist/client/start.d.ts.map +1 -1
  17. package/dist/client/start.js +0 -1
  18. package/dist/client/start.js.map +1 -1
  19. package/dist/client/streaming.d.ts +23 -4
  20. package/dist/client/streaming.d.ts.map +1 -1
  21. package/dist/client/streaming.js +32 -6
  22. package/dist/client/streaming.js.map +1 -1
  23. package/dist/component/_generated/api.d.ts +2 -0
  24. package/dist/component/messages.js +1 -1
  25. package/dist/component/messages.js.map +1 -1
  26. package/dist/component/schema.d.ts +10 -4
  27. package/dist/component/schema.d.ts.map +1 -1
  28. package/dist/component/schema.js +4 -0
  29. package/dist/component/schema.js.map +1 -1
  30. package/dist/component/streams.d.ts +2 -4
  31. package/dist/component/streams.d.ts.map +1 -1
  32. package/dist/component/streams.js +42 -43
  33. package/dist/component/streams.js.map +1 -1
  34. package/dist/deltas.d.ts +48 -0
  35. package/dist/deltas.d.ts.map +1 -0
  36. package/dist/deltas.js +468 -0
  37. package/dist/deltas.js.map +1 -0
  38. package/dist/react/index.d.ts +4 -77
  39. package/dist/react/index.d.ts.map +1 -1
  40. package/dist/react/index.js +4 -178
  41. package/dist/react/index.js.map +1 -1
  42. package/dist/react/optimisticallySendMessage.d.ts +36 -3
  43. package/dist/react/optimisticallySendMessage.d.ts.map +1 -1
  44. package/dist/react/optimisticallySendMessage.js +37 -5
  45. package/dist/react/optimisticallySendMessage.js.map +1 -1
  46. package/dist/react/types.d.ts +4 -18
  47. package/dist/react/types.d.ts.map +1 -1
  48. package/dist/react/useStreamingUIMessages.d.ts +22 -0
  49. package/dist/react/useStreamingUIMessages.d.ts.map +1 -0
  50. package/dist/react/useStreamingUIMessages.js +204 -0
  51. package/dist/react/useStreamingUIMessages.js.map +1 -0
  52. package/dist/react/useThreadMessages.d.ts +104 -0
  53. package/dist/react/useThreadMessages.d.ts.map +1 -0
  54. package/dist/react/useThreadMessages.js +140 -0
  55. package/dist/react/useThreadMessages.js.map +1 -0
  56. package/dist/react/useUIMessages.d.ts +92 -0
  57. package/dist/react/useUIMessages.d.ts.map +1 -0
  58. package/dist/react/useUIMessages.js +116 -0
  59. package/dist/react/useUIMessages.js.map +1 -0
  60. package/dist/validators.d.ts +3 -1
  61. package/dist/validators.d.ts.map +1 -1
  62. package/dist/validators.js +1 -0
  63. package/dist/validators.js.map +1 -1
  64. package/package.json +1 -1
  65. package/src/{react/toUIMessages.ts → UIMessages.ts} +132 -15
  66. package/src/client/index.ts +31 -24
  67. package/src/client/messages.ts +14 -1
  68. package/src/client/search.ts +2 -0
  69. package/src/client/start.ts +0 -1
  70. package/src/client/streaming.test.ts +186 -0
  71. package/src/client/streaming.ts +50 -9
  72. package/src/component/_generated/api.d.ts +2 -0
  73. package/src/component/messages.ts +1 -1
  74. package/src/component/schema.ts +6 -0
  75. package/src/component/streams.ts +49 -66
  76. package/src/{react/deltas.test.ts → deltas.test.ts} +57 -46
  77. package/src/deltas.ts +589 -0
  78. package/src/{react/fromUIMessages.test.ts → fromUIMessages.test.ts} +69 -44
  79. package/src/react/index.ts +8 -250
  80. package/src/react/optimisticallySendMessage.ts +57 -8
  81. package/src/react/types.ts +6 -39
  82. package/src/react/useStreamingUIMessages.ts +294 -0
  83. package/src/react/useThreadMessages.ts +252 -0
  84. package/src/react/useUIMessages.ts +207 -0
  85. package/src/{react/toUIMessages.test.ts → toUIMessages.test.ts} +3 -3
  86. package/src/validators.ts +3 -0
  87. package/dist/client/textStreamParts.d.ts +0 -5
  88. package/dist/client/textStreamParts.d.ts.map +0 -1
  89. package/dist/client/textStreamParts.js +0 -44
  90. package/dist/client/textStreamParts.js.map +0 -1
  91. package/dist/react/deltas.d.ts +0 -27
  92. package/dist/react/deltas.d.ts.map +0 -1
  93. package/dist/react/deltas.js +0 -627
  94. package/dist/react/deltas.js.map +0 -1
  95. package/dist/react/fromUIMessages.d.ts +0 -13
  96. package/dist/react/fromUIMessages.d.ts.map +0 -1
  97. package/dist/react/fromUIMessages.js +0 -75
  98. package/dist/react/fromUIMessages.js.map +0 -1
  99. package/dist/react/toUIMessages.d.ts +0 -19
  100. package/dist/react/toUIMessages.d.ts.map +0 -1
  101. package/dist/react/toUIMessages.js.map +0 -1
  102. package/src/client/textStreamParts.ts +0 -62
  103. package/src/react/deltas.ts +0 -774
  104. package/src/react/fromUIMessages.ts +0 -90
@@ -1,8 +1,11 @@
1
1
  import { describe, it, expect } from "vitest";
2
- import { mergeDeltas, applyDeltasToStreamMessage } from "./deltas.js";
3
- import type { StreamMessage, StreamDelta } from "../validators.js";
2
+ import {
3
+ deriveUIMessagesFromTextStreamParts,
4
+ updateFromTextStreamParts,
5
+ } from "./deltas.js";
6
+ import type { StreamMessage, StreamDelta } from "./validators.js";
4
7
  import { omit } from "convex-helpers";
5
- import type { TextStreamPart, ToolSet } from "ai";
8
+ import type { TextStreamPart, ToolSet, ToolUIPart } from "ai";
6
9
 
7
10
  function makeStreamMessage(
8
11
  streamId: string,
@@ -30,7 +33,7 @@ describe("mergeDeltas", () => {
30
33
  { type: "text-delta", id: "1", text: "Hello" },
31
34
  ]),
32
35
  ];
33
- const [messages, newStreams, changed] = mergeDeltas(
36
+ const [messages, newStreams, changed] = deriveUIMessagesFromTextStreamParts(
34
37
  "thread1",
35
38
  streamMessages,
36
39
  [],
@@ -38,7 +41,7 @@ describe("mergeDeltas", () => {
38
41
  );
39
42
  expect(messages).toHaveLength(1);
40
43
  expect(messages[0].text).toBe("Hello");
41
- expect(messages[0].message?.role).toBe("assistant");
44
+ expect(messages[0].role).toBe("assistant");
42
45
  expect(changed).toBe(true);
43
46
  expect(newStreams[0].cursor).toBe(5);
44
47
  });
@@ -54,7 +57,7 @@ describe("mergeDeltas", () => {
54
57
  { type: "text-delta", id: "2", text: " World!" },
55
58
  ]),
56
59
  ];
57
- const [messages, newStreams, changed] = mergeDeltas(
60
+ const [messages, newStreams, changed] = deriveUIMessagesFromTextStreamParts(
58
61
  "thread1",
59
62
  streamMessages,
60
63
  [],
@@ -75,7 +78,7 @@ describe("mergeDeltas", () => {
75
78
  type: "tool-call",
76
79
  toolCallId: "call1",
77
80
  toolName: "myTool",
78
- input: "",
81
+ input: "What's the meaning of life?",
79
82
  },
80
83
  ]),
81
84
  makeDelta(streamId, 1, 2, [
@@ -88,28 +91,23 @@ describe("mergeDeltas", () => {
88
91
  },
89
92
  ]),
90
93
  ];
91
- const [messages, _, changed] = mergeDeltas(
94
+ const [[message], _, changed] = deriveUIMessagesFromTextStreamParts(
92
95
  "thread1",
93
96
  streamMessages,
94
97
  [],
95
98
  deltas,
96
99
  );
97
- expect(messages).toHaveLength(2);
98
- expect(messages[0].message?.role).toBe("assistant");
99
- expect(messages[0].tool).toBe(true);
100
- const content = messages[0].message?.content;
100
+ expect(message).toBeDefined();
101
+ expect(message.role).toBe("assistant");
102
+ const content = message.parts;
101
103
  expect(content).toEqual([
102
- { type: "tool-call", toolCallId: "call1", toolName: "myTool", args: "" },
103
- ]);
104
- expect(messages[1].message?.role).toBe("tool");
105
- expect(messages[1].tool).toBe(true);
106
- expect(messages[1].message?.content).toEqual([
107
104
  {
108
- type: "tool-result",
105
+ type: "tool-myTool",
109
106
  toolCallId: "call1",
110
- toolName: "myTool",
111
- result: "42",
112
- },
107
+ input: "What's the meaning of life?",
108
+ output: "42",
109
+ state: "output-available",
110
+ } satisfies ToolUIPart,
113
111
  ]);
114
112
  expect(changed).toBe(true);
115
113
  });
@@ -118,13 +116,12 @@ describe("mergeDeltas", () => {
118
116
  const streamId = "s3";
119
117
  const streamMessages = [makeStreamMessage(streamId, 3, 0)];
120
118
  const deltas: StreamDelta[] = [];
121
- const [messages, newStreams, changed] = mergeDeltas(
119
+ const [, newStreams, changed] = deriveUIMessagesFromTextStreamParts(
122
120
  "thread1",
123
121
  streamMessages,
124
122
  [],
125
123
  deltas,
126
124
  );
127
- expect(messages).toHaveLength(0);
128
125
  expect(changed).toBe(false);
129
126
  expect(newStreams[0].cursor).toBe(0);
130
127
  });
@@ -136,7 +133,12 @@ describe("mergeDeltas", () => {
136
133
  makeDelta("s2", 0, 3, [{ type: "text-delta", id: "1", text: "B" }]),
137
134
  makeDelta("s1", 0, 3, [{ type: "text-delta", id: "2", text: "A" }]),
138
135
  ];
139
- const [messages, _, changed] = mergeDeltas("thread1", [s2, s1], [], deltas);
136
+ const [messages, _, changed] = deriveUIMessagesFromTextStreamParts(
137
+ "thread1",
138
+ [s2, s1],
139
+ [],
140
+ deltas,
141
+ );
140
142
  expect(messages).toHaveLength(2);
141
143
  expect(messages[0].text).toBe("A");
142
144
  expect(messages[1].text).toBe("B");
@@ -158,11 +160,16 @@ describe("mergeDeltas", () => {
158
160
  ]),
159
161
  makeDelta(streamId, 11, 12, [{ type: "text-delta", id: "3", text: "!" }]),
160
162
  ];
161
- const [messages] = mergeDeltas("thread1", streamMessages, [], deltas);
163
+ const [messages] = deriveUIMessagesFromTextStreamParts(
164
+ "thread1",
165
+ streamMessages,
166
+ [],
167
+ deltas,
168
+ );
162
169
  expect(messages).toHaveLength(1);
163
170
  expect(messages[0].text).toBe("Hello World!!");
164
171
  // There should only be one text part per message
165
- const content = messages[0].message?.content;
172
+ const content = messages[0].parts;
166
173
  if (Array.isArray(content)) {
167
174
  const textParts = content.filter((p) => p.type === "text");
168
175
  expect(textParts).toHaveLength(1);
@@ -175,20 +182,28 @@ describe("mergeDeltas", () => {
175
182
  const streamMessages = [makeStreamMessage(streamId, 6, 0)];
176
183
  const deltas = [
177
184
  makeDelta(streamId, 0, 1, [
185
+ { type: "reasoning-start", id: "1" },
178
186
  { type: "reasoning-delta", id: "1", text: "I'm thinking..." },
179
187
  ]),
180
188
  makeDelta(streamId, 1, 2, [
181
- { type: "reasoning-delta", id: "2", text: " Still thinking..." },
189
+ { type: "reasoning-delta", id: "1", text: " Still thinking..." },
182
190
  ]),
191
+ makeDelta(streamId, 2, 3, [{ type: "reasoning-end", id: "1" }]),
183
192
  ];
184
- const [messages] = mergeDeltas("thread1", streamMessages, [], deltas);
193
+ const [messages] = deriveUIMessagesFromTextStreamParts(
194
+ "thread1",
195
+ streamMessages,
196
+ [],
197
+ deltas,
198
+ );
185
199
  expect(messages).toHaveLength(1);
186
- if (Array.isArray(messages[0].message?.content)) {
187
- const reasoningParts = messages[0].message.content.filter(
200
+ if (Array.isArray(messages[0].parts)) {
201
+ const reasoningParts = messages[0].parts.filter(
188
202
  (p) => p.type === "reasoning",
189
203
  );
190
204
  expect(reasoningParts).toHaveLength(1);
191
205
  expect(reasoningParts[0].text).toBe("I'm thinking... Still thinking...");
206
+ expect(reasoningParts[0].state).toBe("done");
192
207
  }
193
208
  });
194
209
 
@@ -204,47 +219,43 @@ describe("mergeDeltas", () => {
204
219
  ]),
205
220
  ];
206
221
  // First call: apply both deltas
207
- let [result, changed] = applyDeltasToStreamMessage(
222
+ let [result, changed] = updateFromTextStreamParts(
208
223
  "thread1",
209
224
  streamMessage,
210
225
  undefined,
211
226
  deltas,
212
227
  );
213
- expect(result.messages).toHaveLength(1);
214
- expect(result.messages[0].text).toBe("Hello World!");
228
+ expect(result.message.text).toBe("Hello World!");
215
229
  // Second call: re-apply the same deltas (should not duplicate)
216
- [result, changed] = applyDeltasToStreamMessage(
230
+ [result, changed] = updateFromTextStreamParts(
217
231
  "thread1",
218
232
  streamMessage,
219
233
  result,
220
234
  deltas,
221
235
  );
222
- expect(result.messages).toHaveLength(1);
223
- expect(result.messages[0].text).toBe("Hello World!");
236
+ expect(result.message.text).toBe("Hello World!");
224
237
  // Third call: add a new delta
225
238
  const moreDeltas = [
226
239
  ...deltas,
227
240
  makeDelta(streamId, 11, 12, [{ type: "text-delta", id: "3", text: "!" }]),
228
241
  ];
229
- [result, changed] = applyDeltasToStreamMessage(
242
+ [result, changed] = updateFromTextStreamParts(
230
243
  "thread1",
231
244
  streamMessage,
232
245
  result,
233
246
  moreDeltas,
234
247
  );
235
248
  expect(changed).toBe(true);
236
- expect(result.messages).toHaveLength(1);
237
- expect(result.messages[0].text).toBe("Hello World!!");
249
+ expect(result.message.text).toBe("Hello World!!");
238
250
  // Re-apply all deltas again (should still not duplicate)
239
- [result, changed] = applyDeltasToStreamMessage(
251
+ [result, changed] = updateFromTextStreamParts(
240
252
  "thread1",
241
253
  streamMessage,
242
254
  result,
243
255
  moreDeltas,
244
256
  );
245
257
  expect(changed).toBe(false);
246
- expect(result.messages).toHaveLength(1);
247
- expect(result.messages[0].text).toBe("Hello World!!");
258
+ expect(result.message.text).toBe("Hello World!!");
248
259
  });
249
260
 
250
261
  it("mergeDeltas is pure and does not mutate inputs", () => {
@@ -270,13 +281,13 @@ describe("mergeDeltas", () => {
270
281
  }
271
282
  deepFreeze(streamMessages);
272
283
  deepFreeze(deltas);
273
- const [messages1, streams1, changed1] = mergeDeltas(
284
+ const [messages1, streams1, changed1] = deriveUIMessagesFromTextStreamParts(
274
285
  "thread1",
275
286
  streamMessages,
276
287
  [],
277
288
  deltas,
278
289
  );
279
- const [messages2, streams2, changed2] = mergeDeltas(
290
+ const [messages2, streams2, changed2] = deriveUIMessagesFromTextStreamParts(
280
291
  "thread1",
281
292
  streamMessages,
282
293
  [],
@@ -288,12 +299,12 @@ describe("mergeDeltas", () => {
288
299
  expect(
289
300
  streams1.map((s) => ({
290
301
  ...s,
291
- messages: s.messages.map((m) => omit(m, ["_creationTime"])),
302
+ message: omit(s.message, ["_creationTime"]),
292
303
  })),
293
304
  ).toEqual(
294
305
  streams2.map((s) => ({
295
306
  ...s,
296
- messages: s.messages.map((m) => omit(m, ["_creationTime"])),
307
+ message: omit(s.message, ["_creationTime"]),
297
308
  })),
298
309
  );
299
310
  expect(changed1).toBe(changed2);