@convex-dev/agent 0.1.18-alpha.1 → 0.2.0-alpha.2

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 (96) hide show
  1. package/dist/client/createTool.d.ts +31 -10
  2. package/dist/client/createTool.d.ts.map +1 -1
  3. package/dist/client/createTool.js +25 -10
  4. package/dist/client/createTool.js.map +1 -1
  5. package/dist/client/defaultComponent.d.ts +11 -0
  6. package/dist/client/defaultComponent.d.ts.map +1 -0
  7. package/dist/client/defaultComponent.js +7 -0
  8. package/dist/client/defaultComponent.js.map +1 -0
  9. package/dist/client/definePlaygroundAPI.d.ts +174 -199
  10. package/dist/client/definePlaygroundAPI.d.ts.map +1 -1
  11. package/dist/client/definePlaygroundAPI.js +17 -35
  12. package/dist/client/definePlaygroundAPI.js.map +1 -1
  13. package/dist/client/files.d.ts +6 -3
  14. package/dist/client/files.d.ts.map +1 -1
  15. package/dist/client/files.js +7 -7
  16. package/dist/client/files.js.map +1 -1
  17. package/dist/client/index.d.ts +152 -589
  18. package/dist/client/index.d.ts.map +1 -1
  19. package/dist/client/index.js +138 -222
  20. package/dist/client/index.js.map +1 -1
  21. package/dist/client/messages.d.ts +538 -0
  22. package/dist/client/messages.d.ts.map +1 -0
  23. package/dist/client/messages.js +91 -0
  24. package/dist/client/messages.js.map +1 -0
  25. package/dist/client/search.d.ts +30 -7
  26. package/dist/client/search.d.ts.map +1 -1
  27. package/dist/client/search.js +20 -3
  28. package/dist/client/search.js.map +1 -1
  29. package/dist/client/streaming.d.ts +3 -2
  30. package/dist/client/streaming.d.ts.map +1 -1
  31. package/dist/client/streaming.js.map +1 -1
  32. package/dist/client/threads.d.ts +46 -0
  33. package/dist/client/threads.d.ts.map +1 -0
  34. package/dist/client/threads.js +49 -0
  35. package/dist/client/threads.js.map +1 -0
  36. package/dist/client/types.d.ts +39 -42
  37. package/dist/client/types.d.ts.map +1 -1
  38. package/dist/component/_generated/api.d.ts +437 -75
  39. package/dist/component/messages.d.ts +254 -55
  40. package/dist/component/messages.d.ts.map +1 -1
  41. package/dist/component/messages.js +29 -25
  42. package/dist/component/messages.js.map +1 -1
  43. package/dist/component/schema.d.ts +1459 -158
  44. package/dist/component/schema.d.ts.map +1 -1
  45. package/dist/component/schema.js +8 -14
  46. package/dist/component/schema.js.map +1 -1
  47. package/dist/component/streams.d.ts +180 -6
  48. package/dist/component/streams.d.ts.map +1 -1
  49. package/dist/mapping.d.ts +11 -15
  50. package/dist/mapping.d.ts.map +1 -1
  51. package/dist/mapping.js +191 -61
  52. package/dist/mapping.js.map +1 -1
  53. package/dist/react/deltas.d.ts +0 -3
  54. package/dist/react/deltas.d.ts.map +1 -1
  55. package/dist/react/deltas.js +140 -44
  56. package/dist/react/deltas.js.map +1 -1
  57. package/dist/react/optimisticallySendMessage.d.ts.map +1 -1
  58. package/dist/react/optimisticallySendMessage.js +2 -1
  59. package/dist/react/optimisticallySendMessage.js.map +1 -1
  60. package/dist/react/toUIMessages.d.ts +5 -4
  61. package/dist/react/toUIMessages.d.ts.map +1 -1
  62. package/dist/react/toUIMessages.js +103 -40
  63. package/dist/react/toUIMessages.js.map +1 -1
  64. package/dist/validators.d.ts +1978 -1210
  65. package/dist/validators.d.ts.map +1 -1
  66. package/dist/validators.js +90 -54
  67. package/dist/validators.js.map +1 -1
  68. package/package.json +32 -28
  69. package/src/client/createTool.ts +69 -38
  70. package/src/client/defaultComponent.ts +17 -0
  71. package/src/client/definePlaygroundAPI.ts +29 -43
  72. package/src/client/files.ts +7 -8
  73. package/src/client/index.test.ts +20 -18
  74. package/src/client/index.ts +228 -434
  75. package/src/client/messages.ts +191 -0
  76. package/src/client/search.ts +30 -6
  77. package/src/client/streaming.ts +4 -3
  78. package/src/client/threads.ts +78 -0
  79. package/src/client/types.ts +50 -72
  80. package/src/component/_generated/api.d.ts +437 -75
  81. package/src/component/messages.test.ts +182 -40
  82. package/src/component/messages.ts +30 -32
  83. package/src/component/schema.ts +8 -14
  84. package/src/mapping.ts +230 -94
  85. package/src/react/deltas.ts +165 -52
  86. package/src/react/optimisticallySendMessage.ts +4 -1
  87. package/src/react/toUIMessages.test.ts +154 -36
  88. package/src/react/toUIMessages.ts +136 -57
  89. package/src/validators.test.ts +2 -101
  90. package/src/validators.ts +111 -68
  91. package/dist/client/listMessages.d.ts +0 -22
  92. package/dist/client/listMessages.d.ts.map +0 -1
  93. package/dist/client/listMessages.js +0 -25
  94. package/dist/client/listMessages.js.map +0 -1
  95. package/src/client/listMessages.ts +0 -38
  96. package/src/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
@@ -30,6 +30,29 @@ describe("agent", () => {
30
30
  stepOrder: 1,
31
31
  });
32
32
  });
33
+ test("getMaxMessage works for a specific order", async () => {
34
+ const t = convexTest(schema, modules);
35
+ const thread = await t.mutation(api.threads.createThread, {
36
+ userId: "test",
37
+ });
38
+ const { messages } = await t.mutation(api.messages.addMessages, {
39
+ threadId: thread._id as Id<"threads">,
40
+ messages: [
41
+ { message: { role: "user", content: "hello" } },
42
+ { message: { role: "assistant", content: "step 1" } },
43
+ { message: { role: "user", content: "hello2" } },
44
+ ],
45
+ });
46
+ const maxMessage = await t.run(async (ctx) => {
47
+ return await getMaxMessage(ctx, thread._id as Id<"threads">, 0);
48
+ });
49
+ expect(maxMessage).toMatchObject({
50
+ _id: messages.at(1)!._id,
51
+ order: 0,
52
+ stepOrder: 1,
53
+ });
54
+ });
55
+
33
56
  test("getMaxMessages works when there are tools involved", async () => {
34
57
  const t = convexTest(schema, modules);
35
58
  const thread = await t.mutation(api.threads.createThread, {
@@ -78,7 +101,7 @@ describe("agent", () => {
78
101
  });
79
102
  });
80
103
 
81
- test("ordering is incremented on subsequent calls to addMessages", async () => {
104
+ test("ordering is incremented on subsequent calls to addMessages for user messages", async () => {
82
105
  const t = convexTest(schema, modules);
83
106
  const thread = await t.mutation(api.threads.createThread, {
84
107
  userId: "test",
@@ -109,7 +132,7 @@ describe("agent", () => {
109
132
  });
110
133
  });
111
134
 
112
- test("sub order is incremented on subsequent calls to addMessages for the same promptMessageId", async () => {
135
+ test("ordering is incremented on subsequent calls to addMessages for assistant messages", async () => {
113
136
  const t = convexTest(schema, modules);
114
137
  const thread = await t.mutation(api.threads.createThread, {
115
138
  userId: "test",
@@ -127,8 +150,72 @@ describe("agent", () => {
127
150
  stepOrder: 0,
128
151
  });
129
152
  const { messages: messages2 } = await t.mutation(api.messages.addMessages, {
153
+ threadId: thread._id as Id<"threads">,
154
+ messages: [{ message: { role: "assistant", content: "hello" } }],
155
+ });
156
+ const maxMessage2 = await t.run(async (ctx) => {
157
+ return await getMaxMessage(ctx, thread._id as Id<"threads">);
158
+ });
159
+ expect(maxMessage2).toMatchObject({
160
+ _id: messages2.at(-1)!._id,
161
+ order: 0,
162
+ stepOrder: 1,
163
+ });
164
+ });
165
+
166
+ test("order is incremented for user messages on to addMessages for the same promptMessageId", async () => {
167
+ const t = convexTest(schema, modules);
168
+ const thread = await t.mutation(api.threads.createThread, {
169
+ userId: "test",
170
+ });
171
+ const { messages } = await t.mutation(api.messages.addMessages, {
130
172
  threadId: thread._id as Id<"threads">,
131
173
  messages: [{ message: { role: "user", content: "hello" } }],
174
+ });
175
+ const maxMessage = await t.run(async (ctx) => {
176
+ return await getMaxMessage(ctx, thread._id as Id<"threads">);
177
+ });
178
+ expect(maxMessage).toMatchObject({
179
+ _id: messages.at(-1)!._id,
180
+ order: 0,
181
+ stepOrder: 0,
182
+ });
183
+ const { messages: messages2 } = await t.mutation(api.messages.addMessages, {
184
+ threadId: thread._id as Id<"threads">,
185
+ messages: [{ message: { role: "user", content: "hello" } }],
186
+ agentName: "test",
187
+ promptMessageId: messages.at(-1)!._id as Id<"messages">,
188
+ });
189
+ const maxMessage2 = await t.run(async (ctx) => {
190
+ return await getMaxMessage(ctx, thread._id as Id<"threads">);
191
+ });
192
+ expect(maxMessage2).toMatchObject({
193
+ _id: messages2.at(-1)!._id,
194
+ order: 1,
195
+ stepOrder: 0,
196
+ });
197
+ });
198
+
199
+ test("sub order is incremented on subsequent calls to addMessages for the same promptMessageId", async () => {
200
+ const t = convexTest(schema, modules);
201
+ const thread = await t.mutation(api.threads.createThread, {
202
+ userId: "test",
203
+ });
204
+ const { messages } = await t.mutation(api.messages.addMessages, {
205
+ threadId: thread._id as Id<"threads">,
206
+ messages: [{ message: { role: "user", content: "hello" } }],
207
+ });
208
+ const maxMessage = await t.run(async (ctx) => {
209
+ return await getMaxMessage(ctx, thread._id as Id<"threads">);
210
+ });
211
+ expect(maxMessage).toMatchObject({
212
+ _id: messages.at(-1)!._id,
213
+ order: 0,
214
+ stepOrder: 0,
215
+ });
216
+ const { messages: messages2 } = await t.mutation(api.messages.addMessages, {
217
+ threadId: thread._id as Id<"threads">,
218
+ messages: [{ message: { role: "assistant", content: "hello" } }],
132
219
  agentName: "test",
133
220
  promptMessageId: messages.at(-1)!._id as Id<"messages">,
134
221
  });
@@ -142,6 +229,83 @@ describe("agent", () => {
142
229
  });
143
230
  });
144
231
 
232
+ test("adding multiple messages at a promptMessageId skips later messages", async () => {
233
+ const t = convexTest(schema, modules);
234
+ const thread = await t.mutation(api.threads.createThread, {
235
+ userId: "test",
236
+ });
237
+ const { messages } = await t.mutation(api.messages.addMessages, {
238
+ threadId: thread._id as Id<"threads">,
239
+ messages: [{ message: { role: "user", content: "hello" } }],
240
+ });
241
+
242
+ const { messages: messages2 } = await t.mutation(api.messages.addMessages, {
243
+ threadId: thread._id as Id<"threads">,
244
+ messages: [
245
+ { message: { role: "user", content: "hello2" } },
246
+ { message: { role: "assistant", content: "hello" } },
247
+ ],
248
+ agentName: "test",
249
+ });
250
+ expect(messages2.length).toBe(2);
251
+
252
+ const { messages: messages3 } = await t.mutation(api.messages.addMessages, {
253
+ threadId: thread._id as Id<"threads">,
254
+ messages: [
255
+ {
256
+ message: {
257
+ role: "assistant",
258
+ content: [
259
+ {
260
+ type: "tool-call",
261
+ args: { a: 1 },
262
+ toolCallId: "1",
263
+ toolName: "tool",
264
+ },
265
+ ],
266
+ },
267
+ },
268
+ {
269
+ message: {
270
+ role: "tool",
271
+ content: [
272
+ {
273
+ type: "tool-result",
274
+ toolName: "tool",
275
+ result: "foo",
276
+ toolCallId: "1",
277
+ },
278
+ ],
279
+ },
280
+ },
281
+ { message: { role: "user", content: "bye" } },
282
+ ],
283
+ agentName: "test",
284
+ promptMessageId: messages.at(-1)!._id as Id<"messages">,
285
+ });
286
+
287
+ expect(messages3.length).toBe(3);
288
+
289
+ const allMessages = await t.query(api.messages.listMessagesByThreadId, {
290
+ threadId: thread._id as Id<"threads">,
291
+ order: "asc",
292
+ });
293
+ expect(allMessages.page).toHaveLength(6);
294
+ expect(allMessages.page.map((m) => m.order)).toEqual([0, 0, 0, 1, 1, 2]);
295
+ expect(allMessages.page.map((m) => m.stepOrder)).toEqual([
296
+ 0, 1, 2, 0, 1, 0,
297
+ ]);
298
+ expect(allMessages.page[0]!.message!.role).toBe("user");
299
+ expect(allMessages.page[0]!.message!.content).toBe("hello");
300
+ expect(allMessages.page[1]!.message!.role).toBe("assistant");
301
+ expect(allMessages.page[2]!.message!.role).toBe("tool");
302
+ expect(allMessages.page[3]!.message!.role).toBe("user");
303
+ expect(allMessages.page[3]!.message!.content).toBe("hello2");
304
+ expect(allMessages.page[4]!.message!.role).toBe("assistant");
305
+ expect(allMessages.page[5]!.message!.role).toBe("user");
306
+ expect(allMessages.page[5]!.message!.content).toBe("bye");
307
+ });
308
+
145
309
  test("updateMessage updates message content", async () => {
146
310
  const t = convexTest(schema, modules);
147
311
  const thread = await t.mutation(api.threads.createThread, {
@@ -155,9 +319,7 @@ describe("agent", () => {
155
319
 
156
320
  const updatedMessage = await t.mutation(api.messages.updateMessage, {
157
321
  messageId,
158
- patch: {
159
- message: { role: "user", content: "updated content" },
160
- },
322
+ patch: { message: { role: "user", content: "updated content" } },
161
323
  });
162
324
 
163
325
  expect(updatedMessage.message).toEqual({
@@ -173,8 +335,9 @@ describe("agent", () => {
173
335
  });
174
336
  const { messages } = await t.mutation(api.messages.addMessages, {
175
337
  threadId: thread._id as Id<"threads">,
176
- messages: [{ message: { role: "assistant", content: "hello" } }],
177
- pending: true,
338
+ messages: [
339
+ { message: { role: "assistant", content: "hello" }, status: "pending" },
340
+ ],
178
341
  });
179
342
  const messageId = messages[0]._id as Id<"messages">;
180
343
 
@@ -184,9 +347,7 @@ describe("agent", () => {
184
347
  // Update to success
185
348
  const updatedMessage = await t.mutation(api.messages.updateMessage, {
186
349
  messageId,
187
- patch: {
188
- status: "success",
189
- },
350
+ patch: { status: "success" },
190
351
  });
191
352
 
192
353
  expect(updatedMessage.status).toBe("success");
@@ -199,17 +360,15 @@ describe("agent", () => {
199
360
  });
200
361
  const { messages } = await t.mutation(api.messages.addMessages, {
201
362
  threadId: thread._id as Id<"threads">,
202
- messages: [{ message: { role: "assistant", content: "hello" } }],
203
- pending: true,
363
+ messages: [
364
+ { message: { role: "assistant", content: "hello" }, status: "pending" },
365
+ ],
204
366
  });
205
367
  const messageId = messages[0]._id as Id<"messages">;
206
368
 
207
369
  const updatedMessage = await t.mutation(api.messages.updateMessage, {
208
370
  messageId,
209
- patch: {
210
- status: "failed",
211
- error: "Something went wrong",
212
- },
371
+ patch: { status: "failed", error: "Something went wrong" },
213
372
  });
214
373
 
215
374
  expect(updatedMessage.status).toBe("failed");
@@ -277,9 +436,7 @@ describe("agent", () => {
277
436
  await expect(
278
437
  t.mutation(api.messages.updateMessage, {
279
438
  messageId: "invalidId" as Id<"messages">,
280
- patch: {
281
- message: { role: "user", content: "test" },
282
- },
439
+ patch: { message: { role: "user", content: "test" } },
283
440
  }),
284
441
  ).rejects.toThrow();
285
442
  });
@@ -308,10 +465,7 @@ describe("agent", () => {
308
465
  // Verify messages are actually deleted
309
466
  const remainingMessages = await t.query(
310
467
  api.messages.listMessagesByThreadId,
311
- {
312
- threadId: thread._id as Id<"threads">,
313
- order: "asc",
314
- },
468
+ { threadId: thread._id as Id<"threads">, order: "asc" },
315
469
  );
316
470
  expect(remainingMessages.page).toHaveLength(1);
317
471
  expect(remainingMessages.page[0]._id).toBe(messageIds[1]);
@@ -343,10 +497,7 @@ describe("agent", () => {
343
497
  // Verify the valid message was deleted
344
498
  const remainingMessages = await t.query(
345
499
  api.messages.listMessagesByThreadId,
346
- {
347
- threadId: thread._id as Id<"threads">,
348
- order: "asc",
349
- },
500
+ { threadId: thread._id as Id<"threads">, order: "asc" },
350
501
  );
351
502
  expect(remainingMessages.page).toHaveLength(0);
352
503
  });
@@ -395,10 +546,7 @@ describe("agent", () => {
395
546
  // Verify only messages from order 0 were deleted
396
547
  const remainingMessages = await t.query(
397
548
  api.messages.listMessagesByThreadId,
398
- {
399
- threadId: thread._id as Id<"threads">,
400
- order: "asc",
401
- },
549
+ { threadId: thread._id as Id<"threads">, order: "asc" },
402
550
  );
403
551
 
404
552
  expect(remainingMessages.page).toHaveLength(3); // Should have messages from order 1 and 2
@@ -417,7 +565,7 @@ describe("agent", () => {
417
565
  messages: [
418
566
  { message: { role: "user", content: "step 0" } },
419
567
  { message: { role: "assistant", content: "step 1" } },
420
- { message: { role: "user", content: "step 2" } },
568
+ { message: { role: "assistant", content: "step 2" } },
421
569
  { message: { role: "assistant", content: "step 3" } },
422
570
  ],
423
571
  });
@@ -438,10 +586,7 @@ describe("agent", () => {
438
586
  // Verify only step 1 and 2 were deleted (step 3 is excluded by upperBoundInclusive: false)
439
587
  const remainingMessages = await t.query(
440
588
  api.messages.listMessagesByThreadId,
441
- {
442
- threadId: thread._id as Id<"threads">,
443
- order: "asc",
444
- },
589
+ { threadId: thread._id as Id<"threads">, order: "asc" },
445
590
  );
446
591
 
447
592
  expect(remainingMessages.page).toHaveLength(2);
@@ -501,10 +646,7 @@ describe("agent", () => {
501
646
  // Verify original message is still there
502
647
  const remainingMessages = await t.query(
503
648
  api.messages.listMessagesByThreadId,
504
- {
505
- threadId: thread._id as Id<"threads">,
506
- order: "asc",
507
- },
649
+ { threadId: thread._id as Id<"threads">, order: "asc" },
508
650
  );
509
651
  expect(remainingMessages.page).toHaveLength(1);
510
652
  });
@@ -9,7 +9,7 @@ import {
9
9
  isTool,
10
10
  } from "../shared.js";
11
11
  import {
12
- vMessageEmbeddings,
12
+ vMessageEmbeddingsWithDimension,
13
13
  vMessageStatus,
14
14
  vMessageWithMetadataInternal,
15
15
  vPaginationResult,
@@ -58,9 +58,7 @@ export async function deleteMessage(
58
58
  }
59
59
 
60
60
  export const deleteByIds = mutation({
61
- args: {
62
- messageIds: v.array(v.id("messages")),
63
- },
61
+ args: { messageIds: v.array(v.id("messages")) },
64
62
  returns: v.array(v.id("messages")),
65
63
  handler: async (ctx, args) => {
66
64
  const deletedMessageIds = await Promise.all(
@@ -115,8 +113,8 @@ export const deleteByOrder = mutation({
115
113
  await Promise.all(messages.map((m) => deleteMessage(ctx, m)));
116
114
  return {
117
115
  isDone: messages.length < 64,
118
- lastOrder: messages[messages.length - 1]?.order,
119
- lastStepOrder: messages[messages.length - 1]?.stepOrder,
116
+ lastOrder: messages.at(-1)?.order,
117
+ lastStepOrder: messages.at(-1)?.stepOrder,
120
118
  };
121
119
  },
122
120
  });
@@ -127,16 +125,13 @@ const addMessagesArgs = {
127
125
  promptMessageId: v.optional(v.id("messages")),
128
126
  agentName: v.optional(v.string()),
129
127
  messages: v.array(vMessageWithMetadataInternal),
130
- embeddings: v.optional(vMessageEmbeddings),
131
- pending: v.optional(v.boolean()),
128
+ embeddings: v.optional(vMessageEmbeddingsWithDimension),
132
129
  failPendingSteps: v.optional(v.boolean()),
133
130
  };
134
131
  export const addMessages = mutation({
135
132
  args: addMessagesArgs,
136
133
  handler: addMessagesHandler,
137
- returns: v.object({
138
- messages: v.array(vMessageDoc),
139
- }),
134
+ returns: v.object({ messages: v.array(vMessageDoc) }),
140
135
  });
141
136
  async function addMessagesHandler(
142
137
  ctx: MutationCtx,
@@ -149,14 +144,8 @@ async function addMessagesHandler(
149
144
  assert(thread, `Thread ${args.threadId} not found`);
150
145
  userId = thread.userId;
151
146
  }
152
- const {
153
- embeddings,
154
- failPendingSteps,
155
- pending,
156
- messages,
157
- promptMessageId,
158
- ...rest
159
- } = args;
147
+ const { embeddings, failPendingSteps, messages, promptMessageId, ...rest } =
148
+ args;
160
149
  const parentMessage = promptMessageId && (await ctx.db.get(promptMessageId));
161
150
  if (failPendingSteps) {
162
151
  assert(args.threadId, "threadId is required to fail pending steps");
@@ -187,8 +176,8 @@ async function addMessagesHandler(
187
176
  stepOrder = maxMessage?.stepOrder ?? parentMessage.stepOrder;
188
177
  } else {
189
178
  const maxMessage = await getMaxMessage(ctx, threadId);
190
- order = maxMessage ? maxMessage.order + 1 : 0;
191
- stepOrder = -1;
179
+ order = maxMessage?.order ?? -1;
180
+ stepOrder = maxMessage?.stepOrder ?? -1;
192
181
  }
193
182
  const toReturn: Doc<"messages">[] = [];
194
183
  if (embeddings) {
@@ -209,7 +198,18 @@ async function addMessagesHandler(
209
198
  threadId,
210
199
  });
211
200
  }
212
- stepOrder++;
201
+ if (message.message.role === "user") {
202
+ if (parentMessage && parentMessage.order === order) {
203
+ // see if there's a later message than the parent message order
204
+ const maxMessage = await getMaxMessage(ctx, threadId);
205
+ order = (maxMessage?.order ?? order) + 1;
206
+ } else {
207
+ order++;
208
+ }
209
+ stepOrder = 0;
210
+ } else {
211
+ stepOrder++;
212
+ }
213
213
  const messageId = await ctx.db.insert("messages", {
214
214
  ...rest,
215
215
  ...message,
@@ -219,16 +219,12 @@ async function addMessagesHandler(
219
219
  order,
220
220
  tool: isTool(message.message),
221
221
  text: extractText(message.message),
222
- status: fail ? "failed" : pending ? "pending" : "success",
223
- error: fail ? "Parent message failed" : undefined,
222
+ status: fail ? "failed" : (message.status ?? "success"),
223
+ error: fail
224
+ ? (parentMessage?.error ?? "Parent message failed")
225
+ : undefined,
224
226
  stepOrder,
225
227
  });
226
- // Let's just not set the id field and have it set only in explicit cases.
227
- // if (!message.id) {
228
- // await ctx.db.patch(messageId, {
229
- // id: messageId,
230
- // });
231
- // }
232
228
  if (message.fileIds) {
233
229
  await changeRefcount(ctx, [], message.fileIds);
234
230
  }
@@ -263,7 +259,7 @@ function orderedMessagesStream(
263
259
  .eq("threadId", threadId)
264
260
  .eq("status", status)
265
261
  .eq("tool", tool);
266
- if (order) {
262
+ if (order !== undefined) {
267
263
  return qq.eq("order", order);
268
264
  }
269
265
  return qq;
@@ -435,7 +431,9 @@ export const getMessagesByIds = query({
435
431
  messageIds: v.array(v.id("messages")),
436
432
  },
437
433
  handler: async (ctx, args) => {
438
- return await Promise.all(args.messageIds.map((id) => ctx.db.get(id)));
434
+ return (await Promise.all(args.messageIds.map((id) => ctx.db.get(id)))).map(
435
+ (m) => (m ? publicMessage(m) : null),
436
+ );
439
437
  },
440
438
  returns: v.array(v.union(v.null(), vMessageDoc)),
441
439
  });
@@ -6,7 +6,7 @@ import {
6
6
  vMessageStatus,
7
7
  vUsage,
8
8
  vSource,
9
- vLanguageModelV1CallWarning,
9
+ vLanguageModelCallWarning,
10
10
  vFinishReason,
11
11
  vProviderOptions,
12
12
  vProviderMetadata,
@@ -29,12 +29,8 @@ export const schema = defineSchema({
29
29
  order: /*DEPRECATED*/ v.optional(v.number()),
30
30
  })
31
31
  .index("userId", ["userId"])
32
- .searchIndex("title", {
33
- searchField: "title",
34
- filterFields: ["userId"],
35
- }),
32
+ .searchIndex("title", { searchField: "title", filterFields: ["userId"] }),
36
33
  messages: defineTable({
37
- id: v.optional(v.string()), // external id, e.g. from Vercel AI SDK
38
34
  userId: v.optional(v.string()), // useful for searching across threads
39
35
  threadId: v.id("threads"),
40
36
  order: v.number(),
@@ -62,9 +58,10 @@ export const schema = defineSchema({
62
58
  sources: v.optional(v.array(vSource)),
63
59
  reasoning: v.optional(v.string()),
64
60
  reasoningDetails: v.optional(vReasoningDetails),
65
- warnings: v.optional(v.array(vLanguageModelV1CallWarning)),
61
+ warnings: v.optional(v.array(vLanguageModelCallWarning)),
66
62
  finishReason: v.optional(vFinishReason),
67
63
  // DEPRECATED
64
+ id: v.optional(v.string()), // external id, e.g. from Vercel AI SDK
68
65
  parentMessageId: v.optional(v.id("messages")),
69
66
  stepId: v.optional(v.string()),
70
67
  files: v.optional(v.array(v.any())),
@@ -115,10 +112,7 @@ export const schema = defineSchema({
115
112
  endedAt: v.number(),
116
113
  cleanupFnId: v.optional(v.id("_scheduled_functions")),
117
114
  }),
118
- v.object({
119
- kind: v.literal("aborted"),
120
- reason: v.string(),
121
- }),
115
+ v.object({ kind: v.literal("aborted"), reason: v.string() }),
122
116
  ),
123
117
  })
124
118
  // There should only be one per "order" index
@@ -162,9 +156,9 @@ export const schema = defineSchema({
162
156
  // To authenticate playground usage
163
157
  // Delete a key to invalidate it
164
158
  // Provide a name to easily identify it / invalidate by name
165
- apiKeys: defineTable({
166
- name: v.optional(v.string()),
167
- }).index("name", ["name"]),
159
+ apiKeys: defineTable({ name: v.optional(v.string()) }).index("name", [
160
+ "name",
161
+ ]),
168
162
  });
169
163
 
170
164
  export const vv = typedV(schema);