@convex-dev/agent 0.0.15-alpha.2 → 0.0.16-alpha.0

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 (84) hide show
  1. package/README.md +93 -29
  2. package/dist/commonjs/client/index.d.ts +768 -71
  3. package/dist/commonjs/client/index.d.ts.map +1 -1
  4. package/dist/commonjs/client/index.js +81 -42
  5. package/dist/commonjs/client/index.js.map +1 -1
  6. package/dist/commonjs/client/playground.d.ts +474 -0
  7. package/dist/commonjs/client/playground.d.ts.map +1 -0
  8. package/dist/commonjs/client/playground.js +178 -0
  9. package/dist/commonjs/client/playground.js.map +1 -0
  10. package/dist/commonjs/component/apiKeys.d.ts +11 -0
  11. package/dist/commonjs/component/apiKeys.d.ts.map +1 -0
  12. package/dist/commonjs/component/apiKeys.js +69 -0
  13. package/dist/commonjs/component/apiKeys.js.map +1 -0
  14. package/dist/commonjs/component/files.d.ts +31 -0
  15. package/dist/commonjs/component/files.d.ts.map +1 -0
  16. package/dist/commonjs/component/files.js +61 -0
  17. package/dist/commonjs/component/files.js.map +1 -0
  18. package/dist/commonjs/component/messages.d.ts +40 -109
  19. package/dist/commonjs/component/messages.d.ts.map +1 -1
  20. package/dist/commonjs/component/messages.js +44 -260
  21. package/dist/commonjs/component/messages.js.map +1 -1
  22. package/dist/commonjs/component/schema.d.ts +54 -10
  23. package/dist/commonjs/component/schema.d.ts.map +1 -1
  24. package/dist/commonjs/component/schema.js +7 -2
  25. package/dist/commonjs/component/schema.js.map +1 -1
  26. package/dist/commonjs/component/threads.d.ts +95 -0
  27. package/dist/commonjs/component/threads.d.ts.map +1 -0
  28. package/dist/commonjs/component/threads.js +151 -0
  29. package/dist/commonjs/component/threads.js.map +1 -0
  30. package/dist/commonjs/component/users.d.ts +37 -0
  31. package/dist/commonjs/component/users.d.ts.map +1 -0
  32. package/dist/commonjs/component/users.js +118 -0
  33. package/dist/commonjs/component/users.js.map +1 -0
  34. package/dist/commonjs/validators.d.ts +2 -6
  35. package/dist/commonjs/validators.d.ts.map +1 -1
  36. package/dist/commonjs/validators.js +0 -1
  37. package/dist/commonjs/validators.js.map +1 -1
  38. package/dist/esm/client/index.d.ts +768 -71
  39. package/dist/esm/client/index.d.ts.map +1 -1
  40. package/dist/esm/client/index.js +81 -42
  41. package/dist/esm/client/index.js.map +1 -1
  42. package/dist/esm/client/playground.d.ts +474 -0
  43. package/dist/esm/client/playground.d.ts.map +1 -0
  44. package/dist/esm/client/playground.js +178 -0
  45. package/dist/esm/client/playground.js.map +1 -0
  46. package/dist/esm/component/apiKeys.d.ts +11 -0
  47. package/dist/esm/component/apiKeys.d.ts.map +1 -0
  48. package/dist/esm/component/apiKeys.js +69 -0
  49. package/dist/esm/component/apiKeys.js.map +1 -0
  50. package/dist/esm/component/files.d.ts +31 -0
  51. package/dist/esm/component/files.d.ts.map +1 -0
  52. package/dist/esm/component/files.js +61 -0
  53. package/dist/esm/component/files.js.map +1 -0
  54. package/dist/esm/component/messages.d.ts +40 -109
  55. package/dist/esm/component/messages.d.ts.map +1 -1
  56. package/dist/esm/component/messages.js +44 -260
  57. package/dist/esm/component/messages.js.map +1 -1
  58. package/dist/esm/component/schema.d.ts +54 -10
  59. package/dist/esm/component/schema.d.ts.map +1 -1
  60. package/dist/esm/component/schema.js +7 -2
  61. package/dist/esm/component/schema.js.map +1 -1
  62. package/dist/esm/component/threads.d.ts +95 -0
  63. package/dist/esm/component/threads.d.ts.map +1 -0
  64. package/dist/esm/component/threads.js +151 -0
  65. package/dist/esm/component/threads.js.map +1 -0
  66. package/dist/esm/component/users.d.ts +37 -0
  67. package/dist/esm/component/users.d.ts.map +1 -0
  68. package/dist/esm/component/users.js +118 -0
  69. package/dist/esm/component/users.js.map +1 -0
  70. package/dist/esm/validators.d.ts +2 -6
  71. package/dist/esm/validators.d.ts.map +1 -1
  72. package/dist/esm/validators.js +0 -1
  73. package/dist/esm/validators.js.map +1 -1
  74. package/package.json +10 -2
  75. package/src/client/index.ts +150 -117
  76. package/src/client/playground.ts +231 -0
  77. package/src/component/_generated/api.d.ts +319 -107
  78. package/src/component/apiKeys.ts +74 -0
  79. package/src/component/files.ts +72 -0
  80. package/src/component/messages.ts +54 -308
  81. package/src/component/schema.ts +7 -2
  82. package/src/component/threads.ts +184 -0
  83. package/src/component/users.ts +145 -0
  84. package/src/validators.ts +0 -1
@@ -1,7 +1,5 @@
1
- import { assert, omit, pick } from "convex-helpers";
2
- import { paginator } from "convex-helpers/server/pagination";
1
+ import { assert } from "convex-helpers";
3
2
  import { mergedStream, stream } from "convex-helpers/server/stream";
4
- import { nullable, partial } from "convex-helpers/validators";
5
3
  import { ObjectType } from "convex/values";
6
4
  import {
7
5
  DEFAULT_MESSAGE_RANGE,
@@ -20,7 +18,6 @@ import { api, internal } from "./_generated/api.js";
20
18
  import { Doc, Id } from "./_generated/dataModel.js";
21
19
  import {
22
20
  action,
23
- internalMutation,
24
21
  internalQuery,
25
22
  mutation,
26
23
  MutationCtx,
@@ -35,196 +32,27 @@ import {
35
32
  VectorTableId,
36
33
  vVectorId,
37
34
  } from "./vector/tables.js";
35
+ import {
36
+ listThreadsByUserId as _listThreadsByUserId,
37
+ getThread as _getThread,
38
+ updateThread as _updateThread,
39
+ } from "./threads.js";
38
40
  import { paginationOptsValidator } from "convex/server";
39
41
 
40
- export const getThread = query({
41
- args: { threadId: v.id("threads") },
42
- handler: async (ctx, args) => {
43
- return ctx.db.get(args.threadId);
44
- },
45
- returns: v.union(v.doc("threads"), v.null()),
46
- });
47
-
48
- export const getThreadsByUserId = query({
49
- args: {
50
- userId: v.string(),
51
- order: v.optional(v.union(v.literal("asc"), v.literal("desc"))),
52
- paginationOpts: v.optional(paginationOptsValidator),
53
- },
54
- handler: async (ctx, args) => {
55
- const threads = await paginator(ctx.db, schema)
56
- .query("threads")
57
- .withIndex("userId", (q) => q.eq("userId", args.userId))
58
- .order(args.order ?? "desc")
59
- .paginate(args.paginationOpts ?? { cursor: null, numItems: 100 });
60
- return threads;
61
- },
62
- returns: paginationResultValidator(v.doc("threads")),
63
- });
64
-
65
- const vThread = schema.tables.threads.validator;
66
-
67
- export const createThread = mutation({
68
- args: omit(vThread.fields, ["order", "status"]),
69
- handler: async (ctx, args) => {
70
- const threadId = await ctx.db.insert("threads", {
71
- ...args,
72
- status: "active",
73
- });
74
- return (await ctx.db.get(threadId))!;
75
- },
76
- returns: v.doc("threads"),
77
- });
78
-
79
- export const updateThread = mutation({
80
- args: {
81
- threadId: v.id("threads"),
82
- patch: v.object(
83
- partial(
84
- pick(vThread.fields, [
85
- "title",
86
- "summary",
87
- "defaultSystemPrompt",
88
- "status",
89
- ])
90
- )
91
- ),
92
- },
93
- handler: async (ctx, args) => {
94
- const thread = await ctx.db.get(args.threadId);
95
- assert(thread, `Thread ${args.threadId} not found`);
96
- await ctx.db.patch(args.threadId, args.patch);
97
- return (await ctx.db.get(args.threadId))!;
98
- },
99
- returns: v.doc("threads"),
100
- });
101
-
102
- // When we expose this, we need to also hide all the messages and steps
103
- // export const archiveThread = mutation({
104
- // args: { threadId: v.id("threads") },
105
- // handler: async (ctx, args) => {
106
- // const thread = await ctx.db.get(args.threadId);
107
- // assert(thread, `Thread ${args.threadId} not found`);
108
- // await ctx.db.patch(args.threadId, { status: "archived" });
109
- // return (await ctx.db.get(args.threadId))!;
110
- // },
111
- // returns: v.doc("threads"),
112
- // });
113
42
 
114
- export const deleteAllForUserId = action({
115
- args: { userId: v.string() },
116
- handler: async (ctx, args) => {
117
- let messagesCursor = null;
118
- let threadsCursor = null;
119
- let isDone = false;
120
- while (!isDone) {
121
- const result: {
122
- messagesCursor: string;
123
- threadsCursor: string | null;
124
- isDone: boolean;
125
- } = await ctx.runMutation(internal.messages._deletePageForUserId, {
126
- userId: args.userId,
127
- messagesCursor,
128
- threadsCursor,
129
- });
130
- messagesCursor = result.messagesCursor;
131
- threadsCursor = result.threadsCursor;
132
- isDone = result.isDone;
133
- }
134
- },
135
- returns: v.null(),
136
- });
43
+ /** @deprecated Use *.threads.listMessagesByThreadId instead. */
44
+ export const listThreadsByUserId= _listThreadsByUserId
137
45
 
138
- export const deleteAllForUserIdAsync = mutation({
139
- args: {
140
- userId: v.string(),
141
- },
142
- handler: async (ctx, args) => {
143
- const isDone = await deleteAllForUserIdAsyncHandler(ctx, {
144
- userId: args.userId,
145
- messagesCursor: null,
146
- threadsCursor: null,
147
- });
148
- return isDone;
149
- },
150
- returns: v.boolean(),
151
- });
152
-
153
- const deleteAllArgs = {
154
- userId: v.string(),
155
- messagesCursor: nullable(v.string()),
156
- threadsCursor: nullable(v.string()),
157
- };
158
- type DeleteAllArgs = ObjectType<typeof deleteAllArgs>;
159
- const deleteAllReturns = {
160
- messagesCursor: v.string(),
161
- threadsCursor: nullable(v.string()),
162
- isDone: v.boolean(),
163
- };
164
- type DeleteAllReturns = ObjectType<typeof deleteAllReturns>;
165
-
166
- export const _deleteAllForUserIdAsync = internalMutation({
167
- args: deleteAllArgs,
168
- handler: deleteAllForUserIdAsyncHandler,
169
- returns: v.boolean(),
170
- });
46
+ /** @deprecated Use *.threads.getThread */
47
+ export const getThread = _getThread;
171
48
 
172
- async function deleteAllForUserIdAsyncHandler(
173
- ctx: MutationCtx,
174
- args: DeleteAllArgs
175
- ): Promise<boolean> {
176
- const result = await deletePageForUserId(ctx, args);
177
- if (!result.isDone) {
178
- await ctx.scheduler.runAfter(
179
- 0,
180
- internal.messages._deleteAllForUserIdAsync,
181
- {
182
- userId: args.userId,
183
- messagesCursor: result.messagesCursor,
184
- threadsCursor: result.threadsCursor,
185
- }
186
- );
187
- }
188
- return result.isDone;
189
- }
49
+ /** @deprecated Use *.threads.updateThread instead */
50
+ export const updateThread= _updateThread;
190
51
 
191
- export const _deletePageForUserId = internalMutation({
192
- args: deleteAllArgs,
193
- handler: deletePageForUserId,
194
- returns: deleteAllReturns,
195
- });
196
- async function deletePageForUserId(
52
+ export async function deleteMessage(
197
53
  ctx: MutationCtx,
198
- args: DeleteAllArgs
199
- ): Promise<DeleteAllReturns> {
200
- const threads = await paginator(ctx.db, schema)
201
- .query("threads")
202
- .withIndex("userId", (q) => q.eq("userId", args.userId))
203
- .order("desc")
204
- .paginate({
205
- numItems: 100,
206
- cursor: args.threadsCursor ?? null,
207
- });
208
- await Promise.all(threads.page.map((c) => ctx.db.delete(c._id)));
209
- const messages = await paginator(ctx.db, schema)
210
- .query("messages")
211
- .withIndex("userId_status_tool_order_stepOrder", (q) =>
212
- q.eq("userId", args.userId)
213
- )
214
- .order("desc")
215
- .paginate({
216
- numItems: 100,
217
- cursor: args.messagesCursor ?? null,
218
- });
219
- await Promise.all(messages.page.map((m) => deleteMessage(ctx, m)));
220
- return {
221
- messagesCursor: messages.continueCursor,
222
- threadsCursor: threads.continueCursor,
223
- isDone: messages.isDone,
224
- };
225
- }
226
-
227
- async function deleteMessage(ctx: MutationCtx, messageDoc: Doc<"messages">) {
54
+ messageDoc: Doc<"messages">
55
+ ) {
228
56
  await ctx.db.delete(messageDoc._id);
229
57
  if (messageDoc.embeddingId) {
230
58
  await ctx.db.delete(messageDoc.embeddingId);
@@ -237,98 +65,6 @@ async function deleteMessage(ctx: MutationCtx, messageDoc: Doc<"messages">) {
237
65
  }
238
66
  }
239
67
 
240
- const deleteThreadArgs = {
241
- threadId: v.id("threads"),
242
- cursor: v.optional(v.string()),
243
- limit: v.optional(v.number()),
244
- };
245
- type DeleteThreadArgs = ObjectType<typeof deleteThreadArgs>;
246
- const deleteThreadReturns = {
247
- cursor: v.string(),
248
- isDone: v.boolean(),
249
- };
250
- type DeleteThreadReturns = ObjectType<typeof deleteThreadReturns>;
251
-
252
- export const deleteAllForThreadIdSync = action({
253
- args: deleteThreadArgs,
254
- handler: async (ctx, args) => {
255
- const result: DeleteThreadReturns = await ctx.runMutation(
256
- internal.messages._deletePageForThreadId,
257
- { threadId: args.threadId, cursor: args.cursor, limit: args.limit }
258
- );
259
- return result;
260
- },
261
- returns: deleteThreadReturns,
262
- });
263
-
264
- export const deleteAllForThreadIdAsync = mutation({
265
- args: deleteThreadArgs,
266
- handler: async (ctx, args) => {
267
- const result = await deletePageForThreadIdHandler(ctx, args);
268
- if (!result.isDone) {
269
- await ctx.scheduler.runAfter(0, api.messages.deleteAllForThreadIdAsync, {
270
- threadId: args.threadId,
271
- cursor: result.cursor,
272
- });
273
- }
274
- return result;
275
- },
276
- returns: deleteThreadReturns,
277
- });
278
-
279
- export const _deletePageForThreadId = internalMutation({
280
- args: deleteThreadArgs,
281
- handler: deletePageForThreadIdHandler,
282
- returns: deleteThreadReturns,
283
- });
284
-
285
- async function deletePageForThreadIdHandler(
286
- ctx: MutationCtx,
287
- args: DeleteThreadArgs
288
- ): Promise<DeleteThreadReturns> {
289
- const messages = await paginator(ctx.db, schema)
290
- .query("messages")
291
- .withIndex("threadId_status_tool_order_stepOrder", (q) =>
292
- q.eq("threadId", args.threadId)
293
- )
294
- .paginate({
295
- numItems: args.limit ?? 100,
296
- cursor: args.cursor ?? null,
297
- });
298
- await Promise.all(messages.page.map((m) => deleteMessage(ctx, m)));
299
- await ctx.db.delete(args.threadId);
300
- return {
301
- cursor: messages.continueCursor,
302
- isDone: messages.isDone,
303
- };
304
- }
305
-
306
- export const getFilesToDelete = query({
307
- args: {
308
- cursor: v.optional(v.string()),
309
- limit: v.optional(v.number()),
310
- },
311
- handler: async (ctx, args) => {
312
- const files = await paginator(ctx.db, schema)
313
- .query("files")
314
- .withIndex("refcount", (q) => q.eq("refcount", 0))
315
- .paginate({
316
- numItems: args.limit ?? 100,
317
- cursor: args.cursor ?? null,
318
- });
319
- return {
320
- files: files.page,
321
- continueCursor: files.continueCursor,
322
- isDone: files.isDone,
323
- };
324
- },
325
- returns: v.object({
326
- files: v.array(v.doc("files")),
327
- continueCursor: v.string(),
328
- isDone: v.boolean(),
329
- }),
330
- });
331
-
332
68
  export const vMessageDoc = schema.tables.messages.validator;
333
69
  export const messageStatuses = vMessageDoc.fields.status.members.map(
334
70
  (m) => m.value
@@ -365,9 +101,7 @@ async function addMessagesHandler(
365
101
  }
366
102
  const { failPendingSteps, pending, messages, parentMessageId, ...rest } =
367
103
  args;
368
- const parent = parentMessageId && (await ctx.db.get(parentMessageId));
369
- // TODO: I think this is a bug - parent will be pending always?
370
- if (failPendingSteps && parent?.status !== "pending") {
104
+ if (failPendingSteps) {
371
105
  assert(args.threadId, "threadId is required to fail pending steps");
372
106
  const pendingMessages = await ctx.db
373
107
  .query("messages")
@@ -473,7 +207,7 @@ async function getMaxMessage(
473
207
  const addStepArgs = {
474
208
  userId: v.optional(v.string()),
475
209
  threadId: v.id("threads"),
476
- messageId: v.id("messages"),
210
+ parentMessageId: v.id("messages"),
477
211
  step: vStepWithMessages,
478
212
  failPendingSteps: v.optional(v.boolean()),
479
213
  };
@@ -487,15 +221,15 @@ async function addStepHandler(
487
221
  ctx: MutationCtx,
488
222
  args: ObjectType<typeof addStepArgs>
489
223
  ) {
490
- const parentMessage = await ctx.db.get(args.messageId);
491
- assert(parentMessage, `Message ${args.messageId} not found`);
224
+ const parentMessage = await ctx.db.get(args.parentMessageId);
225
+ assert(parentMessage, `Message ${args.parentMessageId} not found`);
492
226
  const order = parentMessage.order;
493
- assert(order !== undefined, `${args.messageId} has no order`);
227
+ assert(order !== undefined, `${args.parentMessageId} has no order`);
494
228
  let steps = await ctx.db
495
229
  .query("steps")
496
230
  .withIndex("parentMessageId_order_stepOrder", (q) =>
497
231
  // TODO: fetch pending, and commit later
498
- q.eq("parentMessageId", args.messageId)
232
+ q.eq("parentMessageId", args.parentMessageId)
499
233
  )
500
234
  .collect();
501
235
  if (args.failPendingSteps) {
@@ -509,7 +243,7 @@ async function addStepHandler(
509
243
  const { step, messages } = args.step;
510
244
  const stepId = await ctx.db.insert("steps", {
511
245
  threadId: args.threadId,
512
- parentMessageId: args.messageId,
246
+ parentMessageId: args.parentMessageId,
513
247
  order,
514
248
  stepOrder: (steps.at(-1)?.stepOrder ?? -1) + 1,
515
249
  status: step.finishReason === "stop" ? "success" : "pending",
@@ -519,7 +253,7 @@ async function addStepHandler(
519
253
  userId: args.userId,
520
254
  threadId: args.threadId,
521
255
  stepId,
522
- parentMessageId: args.messageId,
256
+ parentMessageId: args.parentMessageId,
523
257
  agentName: parentMessage.agentName,
524
258
  messages,
525
259
  pending: step.finishReason === "stop" ? false : true,
@@ -527,7 +261,7 @@ async function addStepHandler(
527
261
  });
528
262
  // We don't commit if the parent is still pending.
529
263
  if (step.finishReason === "stop") {
530
- await commitMessageHandler(ctx, { messageId: args.messageId });
264
+ await commitMessageHandler(ctx, { messageId: args.parentMessageId });
531
265
  }
532
266
  steps.push((await ctx.db.get(stepId))!);
533
267
  return steps;
@@ -609,21 +343,23 @@ async function commitMessageHandler(
609
343
  }
610
344
  }
611
345
 
612
- export const getThreadMessages = query({
346
+ export const listMessagesByThreadId = query({
613
347
  args: {
614
348
  threadId: v.id("threads"),
615
- isTool: v.optional(v.boolean()),
349
+ excludeToolMessages: v.optional(v.boolean()),
350
+ /** @deprecated Use excludeToolMessages instead. */
351
+ isTool: v.optional(v.literal("use excludeToolMessages instead of this")),
616
352
  order: v.optional(v.union(v.literal("asc"), v.literal("desc"))),
617
353
  paginationOpts: v.optional(paginationOptsValidator),
618
354
  statuses: v.optional(v.array(vMessageStatus)),
619
- parentMessageId: v.optional(v.id("messages")),
355
+ beforeMessageId: v.optional(v.id("messages")),
620
356
  },
621
357
  handler: async (ctx, args) => {
622
- const statuses = args.statuses ?? ["success"];
623
- const parent =
624
- args.parentMessageId && (await ctx.db.get(args.parentMessageId));
625
- const toolOptions =
626
- args.isTool === undefined ? [true, false] : [args.isTool];
358
+ const statuses =
359
+ args.statuses ?? vMessageStatus.members.map((m) => m.value);
360
+ const before =
361
+ args.beforeMessageId && (await ctx.db.get(args.beforeMessageId));
362
+ const toolOptions = args.excludeToolMessages ? [false] : [true, false];
627
363
  const order = args.order ?? "desc";
628
364
  const streams = toolOptions.flatMap((tool) =>
629
365
  statuses.map((status) =>
@@ -634,8 +370,8 @@ export const getThreadMessages = query({
634
370
  .eq("threadId", args.threadId)
635
371
  .eq("status", status)
636
372
  .eq("tool", tool);
637
- if (parent) {
638
- return qq.lte("order", parent.order);
373
+ if (before) {
374
+ return qq.lte("order", before.order);
639
375
  }
640
376
  return qq;
641
377
  })
@@ -656,11 +392,21 @@ export const getThreadMessages = query({
656
392
  returns: paginationResultValidator(v.doc("messages")),
657
393
  });
658
394
 
395
+ /** @deprecated Use listMessagesByThreadId instead. */
396
+ export const getThreadMessages = query({
397
+ args: { deprecated: v.literal("Use listMessagesByThreadId instead") },
398
+ handler: async () => {
399
+ throw new Error("Use listMessagesByThreadId instead of getThreadMessages");
400
+ },
401
+ returns: paginationResultValidator(v.doc("messages")),
402
+ });
403
+
404
+
659
405
  export const searchMessages = action({
660
406
  args: {
661
407
  userId: v.optional(v.string()),
662
408
  threadId: v.optional(v.id("threads")),
663
- parentMessageId: v.optional(v.id("messages")),
409
+ beforeMessageId: v.optional(v.id("messages")),
664
410
  ...vSearchOptions.fields,
665
411
  },
666
412
  returns: v.array(v.doc("messages")),
@@ -704,7 +450,7 @@ export const searchMessages = action({
704
450
  .sort((a, b) => b.score - a.score);
705
451
  const vectorIds = vectorScores.slice(0, limit).map((v) => v.id);
706
452
  const messages: Doc<"messages">[] = await ctx.runQuery(
707
- internal.messages._fetchVectorMessages,
453
+ internal.messages._fetchSearchMessages,
708
454
  {
709
455
  userId: args.userId,
710
456
  threadId: args.threadId,
@@ -713,7 +459,7 @@ export const searchMessages = action({
713
459
  (m) => !vectorIds.includes(m.embeddingId!)
714
460
  ),
715
461
  messageRange: args.messageRange ?? DEFAULT_MESSAGE_RANGE,
716
- parentMessageId: args.parentMessageId,
462
+ beforeMessageId: args.beforeMessageId,
717
463
  limit,
718
464
  }
719
465
  );
@@ -723,20 +469,20 @@ export const searchMessages = action({
723
469
  },
724
470
  });
725
471
 
726
- export const _fetchVectorMessages = internalQuery({
472
+ export const _fetchSearchMessages = internalQuery({
727
473
  args: {
728
474
  userId: v.optional(v.string()),
729
475
  threadId: v.optional(v.id("threads")),
730
476
  vectorIds: v.array(vVectorId),
731
477
  textSearchMessages: v.optional(v.array(v.doc("messages"))),
732
478
  messageRange: v.object({ before: v.number(), after: v.number() }),
733
- parentMessageId: v.optional(v.id("messages")),
479
+ beforeMessageId: v.optional(v.id("messages")),
734
480
  limit: v.number(),
735
481
  },
736
482
  returns: v.array(v.doc("messages")),
737
483
  handler: async (ctx, args): Promise<Doc<"messages">[]> => {
738
- const parent =
739
- args.parentMessageId && (await ctx.db.get(args.parentMessageId));
484
+ const beforeMessage =
485
+ args.beforeMessageId && (await ctx.db.get(args.beforeMessageId));
740
486
  const { userId, threadId } = args;
741
487
  assert(userId || threadId, "Specify userId or threadId to search");
742
488
  let messages = (
@@ -760,7 +506,7 @@ export const _fetchVectorMessages = internalQuery({
760
506
  m !== undefined &&
761
507
  m !== null &&
762
508
  !m.tool &&
763
- (!parent || m.order <= parent.order)
509
+ (!beforeMessage || m.order <= beforeMessage.order)
764
510
  );
765
511
  messages.push(...(args.textSearchMessages ?? []));
766
512
  // TODO: prioritize more recent messages
@@ -16,12 +16,11 @@ import vectorTables, { vVectorId } from "./vector/tables.js";
16
16
  export const schema = defineSchema({
17
17
  threads: defineTable({
18
18
  userId: v.optional(v.string()), // Unset for anonymous
19
- // TODO: is this bubbling up in continue?
20
- defaultSystemPrompt: v.optional(v.string()),
21
19
  title: v.optional(v.string()),
22
20
  summary: v.optional(v.string()),
23
21
  status: vThreadStatus,
24
22
  // DEPRECATED
23
+ defaultSystemPrompt: v.optional(v.string()),
25
24
  parentThreadIds: v.optional(v.array(v.id("threads"))),
26
25
  order: /*DEPRECATED*/ v.optional(v.number()),
27
26
  }).index("userId", ["userId"]),
@@ -125,6 +124,12 @@ export const schema = defineSchema({
125
124
  .index("hash", ["hash"])
126
125
  .index("refcount", ["refcount"]),
127
126
  ...vectorTables,
127
+ // To authenticate playground usage
128
+ // Delete a key to invalidate it
129
+ // Provide a name to easily identify it / invalidate by name
130
+ apiKeys: defineTable({
131
+ name: v.optional(v.string()),
132
+ }).index("name", ["name"]),
128
133
  });
129
134
 
130
135
  export const vv = typedV(schema);